我的野牛代码中有一个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结构需要进行大量修改。因此,我正在寻找一种解决它的新方法。 你能救我吗?
祝你有个美好的一天!
答案 0 :(得分:1)
这是不明确的:
expression : expression operator_arith expression
问题在于,如果你有一个中缀运算符(例如A + B * C
),可以先用左运算符(远离解析树的根)或右运算符进行解析。
您需要决定如何解决这种歧义,并将其添加到解析器中。通常的方法是定义优先级,说某些运算符的优先级高于其他运算符(因此应始终首先解析它们),对于同一级别的运算符,左侧或右侧运算符应该是第一个(通常是左转和右递归)。
有两种方法可以做到这种消歧。您可以引入更多非终端(每个优先级一个)并使用它们编写语法(有许多示例语法使用term
和factor
以及这些额外级别的其他相关内容)。或者,您可以使用bison的内置%left
和%right
声明来设置各种运算符标记的优先级,并为每个生产提供匹配的优先级(通过直接使用标记,或使用{{1 }})。您需要为每个优先级(至少)单独生成,以便为它们提供不同的优先级。
Bison的手册包含后一种风格的例子。