2013-04-07 83 views
0

我有个妈/减少我的野牛代码冲突:这个Bison代码中的转换/减少冲突在哪里?

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 */} 

但它需要的修饰在我的节点结构。因此我正在寻找一种解决问题的新方法。 你能帮我吗?

祝您有美好的一天!

回答

1

这是不明确的:

expression : expression operator_arith expression 

的问题是,如果你有一个以上的管道符(如A + B * C)可以与任一左操作者第一(远离解析的根解析树)还是正确的操作员。

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

做这种消歧有两种方法。您可以引入更多非终端(每个优先级别为一个终端),并与它们一起编写语法(有很多使用termfactor以及其他相关事项的示例语法)。或者,您可以使用内部版本%left%right声明中的野牛来设置各种运算符标记的优先级,并为每个生产提供匹配的优先级(通过直接使用标记或使用%prec)。您需要针对每个优先级(至少)单独生产,以便为它们提供不同的优先级。

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