我试图复制一个简单的 if 语句的结构:
if (paren) { block } [else ({ block } | rec if (paren)) ]
Run Code Online (Sandbox Code Playgroud)
对于 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
Run Code Online (Sandbox Code Playgroud)
建议?
你有没有看过我的 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
//...
]
Run Code Online (Sandbox Code Playgroud)
我认为您的问题是您正在使用attempt而不是opt. opt意味着该else部分是可选的(如果它不存在,你会得到None)。attempt完全不同:
解析器
attempt p应用解析器p。如果p更改解析器状态后失败或出现致命错误,attempt p将回溯到原始解析器状态并报告非致命错误。
当解析器attempt失败时,仍然会出现错误,但不会消耗输入(与<|>orchoice运算符结合使用时很有用)。
| 归档时间: |
|
| 查看次数: |
612 次 |
| 最近记录: |