Frage

Ich versuche, die Struktur einer einfachen If -Anweisung zu replizieren:

if (paren) { block } [else ({ block } | rec if (paren)) ]

Für IF (Paren) Block erstelle ich einen IFBLOCK -AST -Knoten. Andernfalls füllt es rekursiv einen IFelsblock -Knoten.

Ich habe einige alternative Konstruktionen ausprobiert

let parse_if = 
    suffixparen .>>. suffixblock |>> IfBlock 
    //>>? attempt (str "else" >>. ifParser) |>> IfElseBlock 
    //<|> preturn IfBlock
    // .>>? attempt (str "else" >>. ifParser) |>> IfElseBlock
    // suffixparen .>>. suffixblock |>> IfBlock 
    // <|> ifParser |>> IfElseBlock

let inlineIf = str_ws "if" >>. parse_if
do ifParserR := inlineIf

Anregungen?

War es hilfreich?

Lösung

Haben Sie sich meinen GLSL-Parser angesehen (es ist eine C-ähnliche Sprache)?http://laurent.le-brun.eu/fsharp/glsl_parse.fs

Aus dem Code -Beispiel finden Sie hier der relevante Teil für die if Aussage:

let statement, stmtRef = createParserForwardedToRef()

let ifStatement =
    pipe3 (keyword "if" >>. parenExp) statement (opt (keyword "else" >>. statement))
      (fun cond stmt1 stmt2 -> Ast.If(cond, stmt1, stmt2))

stmtRef := choice [
  simpleStatement
  block
  ifStatement
  forLoop
  //...
  ]

Ich denke, Ihr Problem ist, dass Sie verwenden attempt Anstatt von opt. opt Bedeutet die else Teil ist optional (wenn es nicht da ist, bekommen Sie None). attempt ist ganz anders:

Der Parser attempt p Wendet den Parser an p. Wenn p fällt nach dem Ändern des Parser -Zustands oder mit einem tödlichen Fehler, fehl. attempt p wird in den ursprünglichen Parser -Status zurückverfolgen und einen nicht tödlichen Fehler melden.

Wenn der Parser in attempt fällt aus, es gibt immer noch einen Fehler, aber der Eingang wird nicht verbraucht (es ist nützlich, wenn sie mit dem kombiniert werden <|> oder choice Betreiber).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top