質問

私は単純なifステートメントの構造を再現しようとしています:

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

if(paren)ブロックの場合、ifblock astノードを作成します。それ以外の場合は、ifelseblockノードを再帰的に埋めます。

私はかなりの数の代替構造を試しました

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

提案?

役に立ちましたか?

解決

私のGLSLパーサー(Cのような言語です)を見ましたか?http://laurent.le-brun.eu/fsharp/glsl_parse.fs

コードの例から、ここに関連する部分があります if 声明:

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
  //...
  ]

あなたの問題はあなたが使用しているということだと思います attempt それ以外の opt. opt 意味を意味します else パーツはオプションです(そこにない場合、あなたは取得します None). attempt まったく異なります:

パーサー attempt p パーサーを適用します p. 。もしも p パーサー状態を変更した後、または致命的なエラーで失敗すると、 attempt p 元のパーサー状態にバックトラックし、非致命的なエラーを報告します。

パーサーが attempt 失敗しますが、まだエラーがありますが、入力は消費されません(と組み合わせると便利です <|> また choice オペレーター)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top