这种语法有歧义,还是图书馆的错?

Is this grammar ambiguous, or is it the library's fault?

我正在使用 rust-peg parsing expression grammar library, but the principles should be generally understandable. I'm using the library to create a parser for go based on the spec。我在获取要解析的 if 语句时遇到问题,我已将问题提炼为一个简单的示例。

sep
    = ( " " / "\n" )*

expression
    = "x" sep block
    / "x"

if_stmt
    = "if" sep expression sep block

block
    = "{" ( sep stmt )* "}"

stmt
    = if_stmt
    / expression

pub file
    = ( sep stmt )*

这个语法应该(在我看来)解析一种非常简单的语言,它包含两种类型的语句:If 语句和表达式语句。表达式可以是 x,或 x 后跟一个块。 if 语句是 if 后跟一个表达式,再后跟一个块。这是我的语法无法解析的示例输入:

x {}
if x {

}

这无法解析,因为 if 语句行中 x 之后的大括号被解释为作为 "x" sep block 规则一部分的块,而不是作为 "x" sep block 规则一部分的块if_stmt 规则。不幸的是,这个解析库不会回溯并尝试在失败时将这部分行重新解析为 if 语句块。我已经意识到,如果我切换 expression 规则的顺序,使其首先尝试解析 "x",那么 if 语句就可以正常解析。这确实为行 x {} 带来了问题,因为行开头的 x 只是作为普通的 "x" 进行解析,并且它在尝试解析之前退出表达式规则解析 {}

这些限制是否使库无法解析这样的语法?我应该找另一个,还是只写我自己的解析器? (我真的不想那样做)

编辑

我试验了 go 语法,发现将结构文字("x" sep block 示例)放在 if 语句条件中是不合法的。因此,我能够按照 attdona 的建议消除语法歧义。

尝试消除语法歧义:

simple_expr
    = "x"

block_expr
    = "x" sep block

expression
    = simple_expr
    / block_expr

if_stmt
    = "if" sep simple_expr sep block

我不知道rust-peg,希望这对解决你的语法解析有帮助。