質問
私は単純な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
オペレーター)。
所属していません StackOverflow