bison 中应该如何定义二元运算符?
我正在用 bison 用 C 语言编写一个解析器,虽然它在我迄今为止尝试过的所有情况下似乎都能正常工作,但我在我的二元运算符上收到了一堆移位/归约警告(以及在我的一元 NOT 运算符上的一个警告)出色地)。
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 { }
当我通过 bison --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
I'm writing a parser in C with bison, and while it appears to work correctly in all circumstances I've tried so far, I get a bunch of shift/reduce warnings on my binary operators (and one on my unary NOT operator as well).
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 { }
When I run my .y file through bison --verbose, I see:
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)]
I don't see any issues actually parsing binary operators, but it seems I should probably resolve the shift/reduce issues anyway. I can't figure out where the conflict is -- the set_existence productions seem completely unrelated. My best guess (a shot in the dark) is that it could have something to do with the fact that EQ is used as a binary operator (equality comparison) as well as assignment (eg, "foo = bar = baz;" would set foo to true/false based on whether bar and baz are equal). If I change my equality comparison to be == ("foo = bar==baz;"), my parser acts as expected but still has the same shift/reduce conflicts.
EDIT: I do have associativity specified:
%left OR
%left AND
%left NOT
%left LT LE GT GE NE EQ
%left PLUS MINUS
%left TIMES MOD SLASH
%left POWER
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
有几种方法可以避免这种情况。第一种是使用
%left
、%right
和%nonassoc
命令指定优先级(请参阅 手册)。我个人更喜欢的另一个选项是将优先级直接编码到语法中。例如,下面是简单算术表达式的 BNF:
这消除了语法级别的二义性解析。
There are a couple of ways to avoid this. The first is to use the
%left
,%right
and%nonassoc
commands to specify the precedence level (see the manual).The other option, which I personally prefer, is to encode the precedence directly into the grammar. For example, here is a BNF for simple arithmetic expressions:
This eliminates the ambiguous parse at the grammar level.