为什么这个简单的语法会出现移位/减少冲突?

Mus*_*faM 5 grammar yacc bison shift-reduce-conflict

%token <token> PLUS MINUS INT
%left PLUS MINUS
Run Code Online (Sandbox Code Playgroud)

这有效:

exp : exp PLUS exp;
exp : exp MINUS exp;
exp : INT;
Run Code Online (Sandbox Code Playgroud)

这有 2 个转移/减少冲突:

exp : exp binaryop exp;
exp : INT;
binaryop: PLUS | MINUS ;
Run Code Online (Sandbox Code Playgroud)

为什么?

Kaz*_*Kaz 5

这是因为第二个实际上是模棱两可的。第一个语法也是如此,但是您通过添加%left.

%left在第二个语法中不起作用,因为关联性和优先级不是从规则到规则继承的。即binaryop非终结符不会继承任何这样的东西,即使它产生PLUSMINUS。关联性和优先级被本地化为规则,并围绕终端符号。

我们不能做%left binaryop,但我们可以稍微重构一下语法:

exp : exp binaryop term
exp : term;
term : INT;
binaryop: PLUS | MINUS ;
Run Code Online (Sandbox Code Playgroud)

现在没有冲突,因为它是隐式左关联的。即越来越长的表达式的产生只能发生在 的左侧binaryop,因为右侧是term只产生 INT 的 a。