这个Bison代码中的转移/减少冲突在哪里?

时间:2013-04-07 11:38:34

标签: bison shift-reduce-conflict

我的野牛代码中有一个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 */}

但是我的Node结构需要进行大量修改。因此,我正在寻找一种解决它的新方法。 你能救我吗?

祝你有个美好的一天!

1 个答案:

答案 0 :(得分:1)

这是不明确的:

expression : expression operator_arith expression

问题在于,如果你有一个中缀运算符(例如A + B * C),可以先用左运算符(远离解析树的根)或右运算符进行解析。

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

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

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