如何在野牛中定义二元运算符?

时间:2010-10-05 00:17:20

标签: binary bison operator-keyword shift-reduce

我正在使用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

1 个答案:

答案 0 :(得分:2)

有几种方法可以避免这种情况。第一种是使用%left%right%nonassoc命令来指定优先级(请参阅the manual)。

我个人更喜欢的另一个选项是将优先级直接编码到语法中。例如,这里是简单算术表达式的BNF:

expr ::= term | expr + term
term ::= factor | term * factor
factor ::= number | ( expr )

这消除了语法级别的模糊解析。