Parsing 减少/减少语法冲突
让我们想象一下,我希望能够像这样解析值(每一行都是一个单独的示例): 我写了以下YACC语法:Parsing 减少/减少语法冲突,parsing,grammar,bison,yacc,Parsing,Grammar,Bison,Yacc,让我们想象一下,我希望能够像这样解析值(每一行都是一个单独的示例): 我写了以下YACC语法: %% Line: Binding | Expr Binding: Pattern '=' Expr Expr: Id | '(' Expr ')' Pattern: Id | '(' Pattern ')' Id: 'x' 但是我得到了一个reduce/reduce冲突: $ bison example.y example.y: warning: 1 reduce/reduce conflict [
%%
Line: Binding | Expr
Binding: Pattern '=' Expr
Expr: Id | '(' Expr ')'
Pattern: Id | '(' Pattern ')'
Id: 'x'
但是我得到了一个reduce/reduce冲突:
$ bison example.y
example.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
有没有关于如何解决这个问题的提示?我正在使用GNU bison 3.0.2Reduce/Reduce冲突通常意味着语法中存在一个基本问题 解析的第一步是获取输出文件(
bison-v example.y
productsexample.output
)。野牛2.3(部分)说:
冲突是显而易见的;语法读取x
(并将其减少为Id
)和)
后,它不知道是将表达式减少为Expr
还是减少为模式。这带来了一个问题
我认为你应该重写语法,不要使用Expr
和Pattern
:
%%
Line: Binding | Expr
Binding: Expr '=' Expr
Expr: Id | '(' Expr ')'
Id: 'x'
对于任何k
,您的语法都不是LR(k)
。所以你要么修改语法,要么使用
假设输入以以下内容开始:
(((((((((((((x
到目前为止,没有问题,因为每个字符都已转移到解析器堆栈上
但是现在呢?在下一步中,x
必须减少,并且向前看是)
。如果将来某个地方有一个=
,x
是一个模式
。否则,它是一个Expr
您可以通过以下方式修复语法:
- 摆脱
模式
并将绑定
更改为Expr | Expr'='Expr代码>
- 去掉
Expr
的所有定义,并将其替换为Expr:Pattern
从长远来看,第二种选择可能更好,因为在您想象(或开发)的完整语法中,模式
可能是Expr
的子集,而不是与Expr
相同。将Expr
分解为Pattern
和非模式替代品的单元产品,将允许您使用LALR(1)
解析器解析语法(如果语法的其余部分符合)
或者您可以使用GLR语法,如上所述 谢谢!这确实解决了冲突,但我应该在问题中注意到,实际语法中的模式和表达式是相似的,但不完全相同。谢谢,现在已经很清楚了。在实际语法中,模式和表达式相似但不完全相同(它们在AST中生成不同的节点)。在bison中启用GLR解析器确实解决了这个问题(我想性能不会那么好,但我并不在乎这是否简化了语法)。
%%
Line: Binding | Expr
Binding: Expr '=' Expr
Expr: Id | '(' Expr ')'
Id: 'x'
(((((((((((((x