删除可选else块上的shift / reduce冲突

时间:2012-11-25 12:18:57

标签: bison yacc

我正在用Bison定义一个语法,我偶然发现了一个我想要消除的转变/减少冲突。冲突是由旨在匹配if/else语句的规则引起的:

state 17

   13 Stmt: IfBlock . OptionalElseBlock

    ELSE  shift, and go to state 42

    ELSE      [reduce using rule 16 (OptionalElseBlock)]
    $default  reduce using rule 16 (OptionalElseBlock)

    OptionalElseBlock  go to state 43

OptionalElseBlock的定义如下:

   16 OptionalElseBlock: /* empty */
   17                  | ELSE Stmt

状态42和43看起来像这样,省略了shift和reduce信息:

state 42
   17 OptionalElseBlock: ELSE . Stmt

state 43
   13 Stmt: IfBlock OptionalElseBlock .

之前我使用过可选令牌,但我猜测因为解析器的前瞻缓冲区只包含1个终端OptionalElseBlock会导致冲突。有没有简单的方法可以解决这个冲突?

2 个答案:

答案 0 :(得分:0)

这是经典的转移/减少冲突。问题如下:

if (c1) if (c2) stmt1; else stmt2;

问题是if所属的else。如果它不是可选的,那么就没有问题,或者if语句必须被终止(比如fiend,以选择两个流行的替代方案),但是{ {1}}语法似乎已经赢了,因此我们可以改变/减少冲突。

写一个没有出现这个问题的语法是可能的,但并不重要。您可以通过使用优先规则玩游戏或仅仅“预期”转移/减少冲突来隐藏冲突。 (我更喜欢后者,但有很多人会说优先黑客更好,虽然它与imho相同。)

重写的语法是龙书中的一个练习,可能是其他解析文本,所以它可能值得为学习目的而做,但它在语法维护方面是一个真正的痛苦,它使得语法更难阅读,如果这完全是一个问题。


关于如何使用优先级和移位偏好来简化解析的经典论文是由Aho,Johnson和Ullman于1975年出版的“确定性解析模糊语法”。如果您无法访问好的图书馆,谷歌可能会找到一份您可以在线阅读的副本。

答案 1 :(得分:0)

您可能想查看我对同一问题的回答。这是一个FAQ。

Reforming the grammar to remove shift reduce conflict in if-then-else

我建议不要将%expect n用于除0之外的任何内容。