2017-09-22 2 views
4

Wie kann ich mehr Codezeilen analysieren?Wie Parsen mehrzeiliger String in Julia?

Dies funktioniert:

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 

BTW, wenn ich Linie versuchen, durch die Linie I andere Probleme haben:

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

Diese nicht funktioniert. Zum Beispiel:

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

obwohl:

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

Antwort

2

parse soll einen einheitlichen Ausdruck zu analysieren (zumindest das ist, was die docs sagen: Da das ich eigentlich ein bisschen Ihr erstes Beispiel arbeitet überrascht, ohne einen Fehler zu werfen ...).

Wenn Sie mutliple Ausdrücke analysieren wollen, dann können Sie die Vorteile aus der Tatsache ziehen, dass:

  1. parse ein zweites Argument nehmen start, die es von , wo man beginnt das Parsen erzählt.
  2. Wenn Sie dieses Startargument angeben, gibt es ein Tupel mit dem Ausdruck zurück, und der Ausdruck ist beendet.

um eine parseall Funktion zu definieren. Früher gab es einen in der Basis, aber ich bin mir nicht sicher, ob es mehr gibt. Edit: gibt es noch in den Tests siehe unten

# 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

Dank! Es ist inspirierend! :) Es scheint, dass es ein Problem mit mehreren Ausdrücken in einer Zeile gibt. Ich bearbeite deine Antwort, um sie im Code anzuzeigen. Aber ich habe nicht erwartet, dass es eine Peer-Review benötigt ... Sie könnten 'eval (parseall (" print (1); print (2) \ n \ nfür i in 3: 4 \ n print (i) \ nend \ n "))' und 'eval (parseall (" drucken (1) \ nprint (2) \ n \ nfür i in 3: 4 \ n drucken (i) \ nend \ n "))' – Liso

+1

@Liso Ihre Beispiele in der Tat Fehler, und es hat etwas mit Parser zu tun, der einen ': toplevel' Ausdruck erzeugt, wenn er ein Semikolon findet. Ersetzen Sie 'push! (Exs, ex)' durch 'ex.head ==: toplevel? append! (exs, ex.args): push! (exs, ex) 'reparierte das Problem für mich. –

+0

Alexander_Morley und @Dan_Getz Ich akzeptiere eine feste Version. Wie können wir das machen? – Liso