0

我的野牛代码中有一个 Shit/reduce 冲突:

expression : LBRACKET expression RBRACKET  {$$ = $2;}
       | fct_call                          {}
       | operand                           {}    
       | expression operator_arith expression   {$$ = new NBinaryOperation(*$1, $2, *$3);}
       ;

我可以解决它写作:

expression : LBRACKET expression RBRACKET compexp  // {$$ = $2;}
       | fct_call_in_exp compexp               {}
       | operand compexp                       {}
       ;
compexp : /* empty */     {/* Do smthg */}
    | operator_arith expression   {/* Do smthg */}

但它需要对我的节点结构进行大量修改。因此,我正在寻找一种新的方法来解决它。你能帮助我吗 ?

祝你有美好的一天 !

4

1 回答 1

1

这是模棱两可的:

expression : expression operator_arith expression

问题是,如果您有多个中缀运算符(例如A + B * C),则可以先使用左运算符(远离解析树的根)或先使用右运算符对其进行解析。

您需要决定如何解决这种歧义,并将其添加到您的解析器中。通常的方法是定义优先级,表示某些运算符的优先级高于其他运算符(因此它们应该总是首先被解析),对于相同级别的运算符,左边的或右边的应该是第一个(经常提到到左递归和右递归)。

有两种方法可以进行这种消歧。您可以引入更多非终结符(每个优先级一个)并用它们编写语法(有许多示例语法使用这些额外级别的termfactor其他相关内容)。或者,您可以使用 bison 的内置%left%right声明来设置各种运算符标记的优先级,并为每个产生式提供匹配的优先级(直接使用标记或使用%prec)。您需要为每个优先级(至少)单独制作,以便为它们提供不同的优先级。

Bison 的手册包含后一种风格的示例。

于 2013-04-07T19:05:30.177 回答