为什么这个 Yacc/bison 规则没用?

Why is this Yacc/bison rule useless?

%nonassoc ELSE
%nonassoc THEN

我明白了

$ bison -dv tiger.yy
tiger.yy:74.5-28: warning: rule useless in parser due to conflicts [-Wother]
: IF exp THEN exp ELSE exp
^^^^^^^^^^^^^^^^^^^^^^^^

%nonassoc THEN
%nonassoc ELSE

规则有效。

这是怎么回事?为什么会这样?

如警告所述,该规则无用,因为如果 THEN 优先于 ELSE,则 shift/reduce 冲突的解决使得该规则无法应用.

我认为语法实际上包含如下内容:

exp: IF exp THEN exp ELSE exp
   | IF exp THEN exp

因为如果 ELSE 子句是强制性的,就不会有冲突。上面的规则有一个 shift/reduce 冲突,因为当 ELSEIF exp THEN IF exp THEN exp ELSE... 解析中的先行标记时,可以 shift ELSE 减少 内部 IF exp THEN expexp.

为了正确解析表达式,有必要支持shift动作,这样ELSE就会与最里面可用的[=22]相关联=].如果没有优先级声明,那将是默认的解决方案,因为 yacc/bison 更喜欢 shift 而不是 reduce。但是,如果 bison 使用默认分辨率,它还会生成有关该分辨率的警告。为了避免警告,通常通过给予 ELSE 优先于 THEN 来显式强制默认分辨率。就是这样

%nonassoc THEN
%nonassoc ELSE

确实如此。如果您以其他顺序编写优先级声明,

%nonassoc ELSE
%nonassoc THEN

那么你给 THEN 优先于 ELSE,这意味着你指示解析器生成器更喜欢减少最后一个非终结符是 THEN 的产生式而不是移位 [=14] =]. Bison/yacc 将服从该请求,但如果它这样做,它永远不会改变 ELSE,从而使包含 ELSE 的规则变得无用。