l'analyse syntaxique if / else / if
Question
Je suis en train de reproduire la structure de simple instruction if:
if (paren) { block } [else ({ block } | rec if (paren)) ]
for if (paren) bloc, je crée un noeud IfBlock AST. Dans le cas contraire, il remplit récursive un nœud IfElseBlock.
J'ai essayé pas mal de constructions alternatives
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
Suggestions?
La solution
Avez-vous eu un coup d'œil à mon analyseur GLSL (c'est un C-comme la langue)? http://laurent.le-brun.eu/fsharp/glsl_parse.fs
Dans l'exemple de code, voici la partie pertinente de la déclaration de 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
//...
]
Je pense que votre problème est que vous utilisez attempt
au lieu de opt
. opt
signifie la partie else
est facultative (si ce n'est pas là, vous obtenez None
). attempt
est tout à fait différent:
Le
attempt p
analyseur applique la analyseurp
. Sip
échoue après le changement l'état de l'analyseur ou avec un fatal erreur,attempt p
va revenir en arrière à la état de l'analyseur original et un rapport erreur non fatale.
Lorsque l'analyseur en attempt
échoue, il y a toujours une erreur, mais l'entrée ne se consume pas (il est utile lorsqu'il est combiné avec les opérateurs de <|>
ou choice
).