我正在使用bison在C语言中编写一个解析器,虽然它似乎在我迄今为止尝试过的所有情况下都能正常工作,但我在二元运算符上得到了一堆shift / reduce警告(还有一个在我的一元运算符上)也不是运营商。)
binary_op :
PLUS { }
| MINUS { }
| TIMES { }
| SLASH { }
| POWER { }
| AND { }
| OR { }
| LE { }
| LT { }
| GE { }
| GT { }
| EQ { }
| NE { }
| MOD { }
;
unary_op :
NOT { }
;
expr :
...
| unary_op expr { }
| expr binary_op expr { }
当我通过野牛--verbose运行我的.y文件时,我看到:
state 51
11 set_existence: expr . IN set
12 | expr . NOT IN set
34 expr: expr . binary_op expr
34 | expr binary_op expr .
...
NOT shift, and go to state 26
AND shift, and go to state 27
OR shift, and go to state 28
....
NOT [reduce using rule 34 (expr)]
AND [reduce using rule 34 (expr)]
OR [reduce using rule 34 (expr)]
我没有看到实际解析二元运算符的任何问题,但似乎我应该解决转移/减少问题。我无法弄清楚冲突的位置 - set_existence制作似乎完全不相关。我最好的猜测(在黑暗中拍摄)是因为它可能与EQ用作二元运算符(相等比较)以及赋值(例如,“foo = bar = baz;”将设置)有关根据bar和baz是否相等,foo为true / false。如果我将我的等式比较更改为==(“foo = bar == baz;”),我的解析器按预期运行,但仍然具有相同的转换/减少冲突。
编辑:我确实有指定的关联性:
%left OR
%left AND
%left NOT
%left LT LE GT GE NE EQ
%left PLUS MINUS
%left TIMES MOD SLASH
%left POWER
答案 0 :(得分:2)
有几种方法可以避免这种情况。第一种是使用%left
,%right
和%nonassoc
命令来指定优先级(请参阅the manual)。
我个人更喜欢的另一个选项是将优先级直接编码到语法中。例如,这里是简单算术表达式的BNF:
expr ::= term | expr + term
term ::= factor | term * factor
factor ::= number | ( expr )
这消除了语法级别的模糊解析。