为了个人娱乐,我一直在研究类C语法。但是,我一直在遇到转换/减少冲突,我很确定它们可以解决。
现在我的expressions
看起来像这样,以简化的形式被剥夺了行动:
%left '+' '-'
%%
expr
: NUMBER
| IDENTIFIER
| expr '+' expr
| expr '-' expr
/* other operators like '*', '/', etc. */
| expr '(' expr ')' /* function call */
%%
但是,这会导致转换/减少冲突:解析器不确定如何处理括号。根据{{1}}告诉我的情况,不清楚-v
这样的表达式是否应将expr '+' expr '('
缩减为expr '+' expr
或移位括号。
显然,我希望改变括号。 expr
不应该最终成为foo % bar(4)
。但是,我没有成功使用(foo % bar)(4)
指令。在规则之后添加%prec
和%left FUNCALL
不会产生任何变化。
我知道当遇到shift / reduce时,默认路径Bison的LALR解析器将会移动,并且我可以使用%prec FUNCALL
来 fix 解决问题。但是,为每个表达式生成一个冲突,并且我需要更改该列表,我还需要更改%expect
声明,这看起来对我来说是一个相当丑陋的解决方案。此外,我相信你们其中一个聪明的孩子能解决这个问题。
我的目标是制定一个类似于上述规则的规则,Bison将知道每当它遇到函数调用规则中的%expect
时,它就会移动括号,而不会发生可能的移位/减少冲突。为了记录,我使用'('
指令如下,所以如果我做错了你可以纠正我。它确实有转移/减少冲突。
%prec
答案 0 :(得分:4)
您需要将%left '('
添加到您的优先规则中(或%nonassoc '('
可能更好)。
优先级在yacc / bison中解决转移/减少冲突的方式是它将规则的优先级与令牌的优先级进行比较转移。在您的示例中,冲突在减少expr: expr '+' expr
和转移'('
之间,因此要解决它,您需要'('
的优先级(并且您希望它高于规则,来自'+'
)
%prec
指令仅设置规则的优先级,覆盖其默认优先级,该优先级来自其rhs上的第一个标记。它不会以任何方式影响规则中出现的令牌的优先级。