解析 if / else / if 语句

发布于 2024-11-15 02:35:27 字数 687 浏览 2 评论 0原文

我试图复制一个简单的 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

建议?

I'm trying to replicate the structure of a simple if statement:

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

for if (paren) block, I create a IfBlock AST node. Otherwise, it recursively fills a IfElseBlock node.

I've tried quite a few alternate constructions

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沧笙踏歌 2024-11-22 02:35:27

你看过我的 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 是完全不同的:

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

attempt 中的解析器失败时,仍然会出现错误,但输入不会被消耗(与 <|>choice 运算符)。

Have you had a look at my GLSL parser (it's a C-like language)?
http://laurent.le-brun.eu/fsharp/glsl_parse.fs

From the code example, here is the relevant part for the if statement:

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

I think your problem is that you're using attempt instead of opt. opt means the else part is optional (if it's not there, you get None). attempt is quite different:

The parser attempt p applies the
parser p. If p fails after changing
the parser state or with a fatal
error, attempt p will backtrack to the
original parser state and report a
non‐fatal error.

When the parser in attempt fails, there's still an error but the input is not consumed (it's useful when combined with the <|> or choice operators).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文