如何在Julia中解析多行字符串?

时间:2017-09-22 12:32:25

标签: julia

如何解析更多行代码?

这是有效的:

julia> eval(parse("""print("O");print("K")"""))
OK

这不起作用:

julia> eval(parse("""print("N");
print("O")"""))
ERROR: ParseError("extra token after end of expression")
Stacktrace:
 [1] #parse#235(::Bool, ::Function, ::String) at ./parse.jl:237
 [2] parse(::String) at ./parse.jl:232
顺便说一句,如果我逐行尝试,我还有其他问题。例如:

julia> parse("""for i in 1:3""")
:($(Expr(:incomplete, "incomplete: premature end of input")))

虽然:

julia> eval(parse("""for i in 1:2
println(i)
end"""))
1
2

2 个答案:

答案 0 :(得分:3)

parse旨在解析单个表达式(至少这是文档所说的内容:鉴于此,我实际上对您的第一个示例有点惊讶,而不会抛出错误......)。

如果你想解析多个表达式,那么你可以利用以下这个事实:

  1. parse可以使用第二个参数start来告诉它在哪里 开始解析。
  2. 如果你提供这个start参数,那么它会返回一个包含表达式的元组,以及表达式完成的位置。
  3. 自己定义parseall函数。曾经有一个在基地,但我不确定已经有了。 修改:测试中仍有以下内容

    # modified from the julia source ./test/parse.jl
    function parseall(str)
        pos = start(str)
        exs = []
        while !done(str, pos)
            ex, pos = parse(str, pos) # returns next starting point as well as expr
            ex.head == :toplevel ? append!(exs, ex.args) : push!(exs, ex) #see comments for info
        end
        if length(exs) == 0
            throw(ParseError("end of input"))
        elseif length(exs) == 1
            return exs[1]
        else
            return Expr(:block, exs...) # convert the array of expressions
                                        # back to a single expression
        end
    end
    

答案 1 :(得分:1)

有点笨拙,但这可以解决问题!:

function parseall(str)
    return Meta.parse("begin $str end")
end

说明:

正如@Alexander Morley指出的aboveparse旨在仅解析单个表达式。因此,如果仅使单个表达式能够包含原始字符串中的所有表达式,则它将对其进行解析! :)

最简单的方法是将字符串包装在一个块中,这使其成为有效的julia表达式。您可以看到这样的表达式可以很好地解析:

julia> Meta.parse("""
       begin
       function f3(x)
         x + 2
       end
       print("N")
       print(f3(5))
       end
       """)
>> quote
    #= none:2 =#
    function f3(x)
        #= none:3 =#
        x + 2
    end
    #= none:5 =#
    print("N")
    #= none:6 =#
    print(f3(5))
end

这实际上是@Alexander Morley中的代码正在构建的结构。 (这就是让我想到这种方式的原因!谢谢亚历山大!)