为了我的个人娱乐,我一直在研究一种类似 C 的语法。但是,我一直在遇到 shift/reduce 冲突,我很确定它们可以得到解决。
现在我expressions
看起来像这样,以简化的形式,剥离了动作:
%left '+' '-'
%%
expr
: NUMBER
| IDENTIFIER
| expr '+' expr
| expr '-' expr
/* other operators like '*', '/', etc. */
| expr '(' expr ')' /* function call */
%%
但是,这会导致移位/减少冲突:解析器不确定如何处理括号。据我-v
所知,尚不清楚 like 表达式是否expr '+' expr '('
应该减少或expr '+' expr
移动expr
括号。
显然,我希望括号移动。foo % bar(4)
不应该最终成为(foo % bar)(4)
. 但是,我没有成功使用该%prec
指令来表示这个意思。在规则之后添加%left FUNCALL
and%prec FUNCALL
不会产生任何变化。
我知道 Bison 的 LALR 解析器在遇到 shift/reduce 时的默认路径是 shift,我可以用它%expect
来解决问题。但是,每个表达式都会产生一个冲突,我是否需要更改该列表,我还需要更改%expect
声明,这对我来说似乎是一个相当丑陋的解决方案。此外,我相信你们中的一个聪明的孩子有解决这个问题的办法。
我的目标是有一个类似于上面的规则,Bison 会知道,每当它遇到'('
from 函数调用规则时,它都会移动括号,而不会发生移位/减少冲突。作为记录,我对%prec
指令的使用如下,所以如果我做错了,你可以纠正我。它确实存在移位/减少冲突。
%left '+' '-'
%left FUNCALL
%%
expr
: NUMBER
| IDENTIFIER
| expr '+' expr
| expr '-' expr
/* other operators like '*', '/', etc. */
| expr '(' expr ')' %prec FUNCALL /* function call */
%%