部分答案是仔细查看来自bison -v 的输出文件。对于你的第一个语法,我得到了这些摘录:
State 8 conflicts: 1 shift/reduce
State 9 conflicts: 1 shift/reduce
State 10 conflicts: 1 shift/reduce
State 11 conflicts: 1 shift/reduce
State 12 conflicts: 1 shift/reduce
Grammar
0 $accept: expr $end
1 expr: NUMBER
2 | expr '+' expr
3 | expr '-' expr
4 | expr '*' expr
5 | expr '/' expr
6 | expr expr
所以语法中有 5 个移位/归约冲突。这些是不太严重的冲突类型;如果您确信语法所做的事情是正确的,您可以在语法中使用%expect 5 声明您期望它们。
state 0
0 $accept: . expr $end
NUMBER shift, and go to state 1
expr go to state 2
state 1
1 expr: NUMBER .
$default reduce using rule 1 (expr)
state 2
0 $accept: expr . $end
2 expr: expr . '+' expr
3 | expr . '-' expr
4 | expr . '*' expr
5 | expr . '/' expr
6 | expr . expr
$end shift, and go to state 3
'+' shift, and go to state 4
'-' shift, and go to state 5
'*' shift, and go to state 6
'/' shift, and go to state 7
NUMBER shift, and go to state 1
expr go to state 8
state 3
0 $accept: expr $end .
$default accept
state 4
2 expr: expr '+' . expr
NUMBER shift, and go to state 1
expr go to state 9
状态 5、6、7 模拟状态 4,但适用于其他运算符。状态 8 是第一个发生转移/减少冲突的状态。请记住,规则中的.(点)表示解析器到达此状态时所处的位置。
state 8
2 expr: expr . '+' expr
3 | expr . '-' expr
4 | expr . '*' expr
5 | expr . '/' expr
6 | expr . expr
6 | expr expr .
NUMBER shift, and go to state 1
NUMBER [reduce using rule 6 (expr)]
$default reduce using rule 6 (expr)
expr go to state 8
state 9
2 expr: expr . '+' expr
2 | expr '+' expr .
3 | expr . '-' expr
4 | expr . '*' expr
5 | expr . '/' expr
6 | expr . expr
'*' shift, and go to state 6
'/' shift, and go to state 7
NUMBER shift, and go to state 1
NUMBER [reduce using rule 2 (expr)]
$default reduce using rule 2 (expr)
expr go to state 8
这两个状态有区别也有相似之处,但是状态10、11、12匹配状态9除了歧义点不同。
麻烦的是,当语法看到:
NUMBER OP NUMBER NUMBER
它无法判断是否将其解析为:
(号码操作号码)号码
expr 表达式
或作为:
NUMBER OP ( NUMBER NUMBER )
expr OP expr
鉴于在每种情况下都是移位/减少冲突,它选择移位。如果这就是您想要的,那么添加%expect 5 并继续生活。如果那不是你想要的,那么你需要重新考虑你的语法。一对相邻的数字表示什么,您确定不需要一些运算符字符(可能是逗号或冒号)来分隔它们吗?
我尝试使用以下方法提高缺失运算符的优先级:
%left MISSING
在其他优先级声明之后,然后使用:
expr expr %prec MISSING
这并没有改变任何东西。通过将 MISSING 列在其他运算符之前也不会降低 MISSING 的优先级。
如果您考虑应该如何解析这样的表达式,您就会对问题有所了解:
NUMBER OP NUMBER NUMBER NUMBER OP NUMBER NUMBER OP NUMBER
每次出现的 OP 都相同。我的脑袋好痛! bison's 也是如此!