解析if / else / if语句

时间:2011-06-14 09:00:32

标签: f# fparsec

我正在尝试复制简单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

建议?

1 个答案:

答案 0 :(得分:4)

您是否看过我的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而不是optopt表示else部分是可选的(如果不存在,则获得None)。 attempt完全不同:

  

解析器attempt p适用   解析器p。如果更改后p失败   解析器状态或致命的   错误,attempt p将回溯到   原始解析器状态并报告a   非致命错误。

attempt中的解析器失败时,仍然存在错误,但输入未被消耗(当与<|>choice运算符结合使用时,它很有用。)