Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 解析if/else/if语句_F#_Fparsec - Fatal编程技术网

F# 解析if/else/if语句

F# 解析if/else/if语句,f#,fparsec,F#,Fparsec,我试图复制一个简单if语句的结构: if (paren) { block } [else ({ block } | rec if (paren)) ] let statement, stmtRef = createParserForwardedToRef() let ifStatement = pipe3 (keyword "if" >>. parenExp) statement (opt (keyword "else" >>. statement))

我试图复制一个简单if语句的结构:

if (paren) { block } [else ({ block } | rec if (paren)) ]
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
  //...
  ]
对于if(paren)块,我创建了一个ifast块节点。否则,它将递归地填充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
如果=
足印。suffixblock |>>IfBlock
//>>? 尝试(str“else”>>.ifParser)|>>IfElseBlock
//预烧IfBlock
// .>>? 尝试(str“else”>>.ifParser)|>>IfElseBlock
//足印。suffixblock |>>IfBlock
//ifParser |>>IfElseBlock
让inlineIf=str_ws“if”>>。解析_如果
do ifParserR:=inlineIf

建议?

您看过我的GLSL解析器吗(它是一种类似C的语言)?

在代码示例中,以下是
if
语句的相关部分:

if (paren) { block } [else ({ block } | rec if (paren)) ]
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
  //...
  ]
我认为您的问题在于您使用的是
尝试
,而不是
选择
opt
表示
else
部分是可选的(如果不存在,则得到
None
)<代码>尝试与此完全不同:

解析器
尝试p
应用 解析器
p
。如果
p
在更改后失败 解析器状态或具有致命错误 错误,
尝试p
将返回到 原始解析器状态并报告 非致命错误


尝试中的解析器失败时,仍然会出现错误,但不会使用输入(与
选择
运算符组合使用时非常有用)。

谢谢Laurent。对于记录,我还尝试将尝试和%None结合使用,但没有效果。