Pregunta

Estoy tratando de replicar la estructura de una instrucción SIMPLE IF:

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

Para el bloque if (paren), creo un nodo ASTBLOCK AST. De lo contrario, llena recursivamente un nodo ifelseblock.

He probado bastantes construcciones alternativas

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

¿Sugerencias?

¿Fue útil?

Solución

¿Has echado un vistazo a mi analizador GLSL (es un lenguaje similar a C)?http://laurent.le-brun.eu/fsharp/glsl_parse.fs

Del ejemplo del código, aquí está la parte relevante para el if declaración:

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

Creo que tu problema es que estás usando attempt en vez de opt. opt significa el else parte es opcional (si no está allí, obtienes None). attempt es bastante diferente:

El analizador attempt p aplica el analizador p. Si p falla después de cambiar el estado del analizador o con un error fatal, attempt p retrocederá en el estado de analizador original e informará un error no fatal.

Cuando el analizador attempt falla, todavía hay un error, pero la entrada no se consume (es útil cuando se combina con el <|> o choice operadores).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top