Bison下类C语法的移位/归约冲突

Bison下类C语法的移位/归约冲突,bison,Bison,我一直在写一个类似C的语法,以供个人消遣。然而,我遇到了轮班/减少冲突,我非常确信它们可以得到解决 现在我的表达式看起来像这样,以简化的形式,没有动作: %left '+' '-' %% expr : NUMBER | IDENTIFIER | expr '+' expr | expr '-' expr /* other operators like '*', '/', etc. */ | expr '(' expr ')' /* function call */ %% 但是,这

我一直在写一个类似C的语法,以供个人消遣。然而,我遇到了轮班/减少冲突,我非常确信它们可以得到解决

现在我的
表达式
看起来像这样,以简化的形式,没有动作:

%left '+' '-'

%%
expr
 : NUMBER
 | IDENTIFIER
 | expr '+' expr
 | expr '-' expr
 /* other operators like '*', '/', etc. */
 | expr '(' expr ')' /* function call */
%%
但是,这会导致移位/减少冲突:解析器不确定如何处理括号。根据
-v
告诉我的,不清楚像
expr'+'expr'(“
这样的表达式是否应该将
expr'+'expr
减少为
expr
或将括号移动

显然,我希望括号被移动。
foo%bar(4)
不应该成为
(foo%bar)(4)
。但是,我没有成功地使用
%prec
指令来表示这一点。在规则之后添加
%left FUNCALL
%prec FUNCALL
不会产生任何更改

我知道Bison的LALR解析器在遇到shift/reduce时的默认路径是to shift,我可以使用
%expect
来解决这个问题。但是,每个表达式都会产生一个冲突,如果我需要更改该列表,我还需要更改
%expect
声明对我来说,这似乎是一个相当丑陋的解决方案。此外,我相信你们中的一个聪明的孩子有解决这个问题的办法

我的目标是制定一条类似于上述规则的规则,让野牛在遇到
时知道这一点(“
根据函数调用规则,它在括号中移位,没有可能的移位/减少冲突。作为记录,我对
%prec
指令的使用如下,因此如果我只是做错了,您可以纠正我。它确实存在移位/减少冲突

%left '+' '-'
%left FUNCALL

%%

expr
    : NUMBER
    | IDENTIFIER
    | expr '+' expr
    | expr '-' expr
    /* other operators like '*', '/', etc. */
    | expr '(' expr ')' %prec FUNCALL /* function call */

%%

您需要将
%left'('
添加到优先规则中(或者
%nonassoc'('
可能更好)

在yacc/bison中,优先级解决移位/减少冲突的方式是将要减少的规则的优先级与要移位的令牌的优先级进行比较。在您的示例中,冲突发生在减少
expr:expr'+'expr
和移动
'(“
,所以要解决它,您需要在
”上有一个优先级(“
”(您希望它高于规则,规则来自
”+“


%prec
指令只设置规则的优先级,覆盖其rhs上第一个标记的默认优先级。它不会以任何方式影响规则中出现的标记的优先级。

哦,我明白了。我真的负担不起
%nonassoc'(“
因为它会完全打断嵌套的括号,除非我遗漏了其他内容,但我明白你的意思。谢谢。嵌套的括号不应该涉及任何冲突,所以
%nonassoc
不应该是个问题——优先级规则只对解决冲突有影响