如何解析Julia表达式

时间:2017-08-02 03:59:43

标签: parsing metaprogramming julia

我一直试图从元编程的角度理解Julia,而且我经常发现自己处于我希望从Expr生成面向Julia语法的用户的位置。

在GitHub上搜索源代码时,我遇到了#34; deparse" femtolisp中定义的函数。但它似乎根本没有曝光。

我只使用内部表示法生成合适的Julia表达式有哪些方法?

P上。 S.生成的Julia代码应该有某种美化工具,你知道一些这样的(un / registered)pkg吗?

〜#〜#〜

更新

我已将julia源文件的所有Meta.show_sexpr存储到另一个文件中。

# This function is identical to create_adder implementation above.
function create_adder(x)
    y -> x + y
end

# You can also name the internal function, if you want
function create_adder(x)
    function adder(y)
        x + y
    end
    adder
end

add_10 = create_adder(10)
add_10(3) # => 13

转换为

  (:line, 473, :none),
    (:function, (:call, :create_adder, :x), (:block,
        (:line, 474, :none),
        (:function, (:call, :adder, :y), (:block,
            (:line, 475, :none),
            (:call, :+, :x, :y)
          )),
        (:line, 477, :none),
        :adder
      )),
    (:line, 480, :none),
    (:(=), :add_10, (:call, :create_adder, 10)),
    (:line, 481, :none),
    (:call, :add_10, 3))

现在,希望在朱莉娅评估这些。

1 个答案:

答案 0 :(得分:1)

这是一个带有" s_expression"的函数示例。以元组形式,并生成相应的Expr对象:

"""rxpe_esrap: parse expr in reverse :p """
function rpxe_esrap(S_expr::Tuple)
  return Expr( Tuple( isa(i, Tuple) ? rpxe_esrap(i) : i for i in S_expr )... );
end

演示

让我们生成一个很好的s_expression元组来测试我们的函数 (不幸的是Meta.show_sexpr没有生成字符串,它只是打印到IOStream,所以要将其输出作为我们可以解析/ eval的字符串,我们需要从文件中获取它,或直接打印成IOBuffer

之类的东西
B     = IOBuffer();              # will use to 'capture' the s_expr in
Expr1 = :(1 + 2 * 3);            # the expr we want to generate an s_expr for
Meta.show_sexpr(B, Expr1);       # push s_expr into buffer B
seek(B, 0);                      # 'rewind' buffer
SExprStr = read(B, String);      # get buffer contents as string
close(B);                        # please to be closink after finished, da?
SExpr = parse(SExprStr) |> eval; # final s_expr in tuple form

导致以下s_expression:

julia> SExpr
(:call, :+, 1, (:call, :*, 2, 3))

现在让我们测试一下我们的功能:

julia> rpxe_esrap(SExpr)
:(1 + 2 * 3)                     # Success!

<子>注意:
<子> 1。这只是一个简单的函数来演示这个概念,显然如果要用于严肃的项目,这将需要适当的健全性检查。
<子> 2。这个实现只需要一个&#34; s_expr元组&#34;参数;您的示例显示了一个与元组的序列对应的字符串,但可能您可以先将这样的字符串标记为获取单个元组参数,然后分别对每个元组运行该函数。
<子> 3。有关解析/评估和范围的常见警告适用。此外,如果您想将s_expr字符串本身作为函数参数传递,而不是传递&#34; s_expr元组&#34;,那么您可以修改此函数以在函数内部移动解析/评估步骤。这可能是一个更好的选择,因为您可以在评估潜在危险代码等之前检查字符串包含的内容。
<子> 我并不是说没有正式的功能可以做到这一点。虽然如果有的话,我也不知道。尽管写这很有趣。