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?

Était-ce utile?

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 analyseur p. Si p é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).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top