COMMA转移/减少错误野牛

时间:2013-10-20 16:58:25

标签: bison

A: constant
 | OPENINGBRACES B C 
;

constant: INTEGER | REAL | CHARACTER ;

C: CLOSINGBRACES
 | COMMA CLOSINGBRACES
;

B: A
 | A COMMA B 
;

这个语法正在产生shift / reduce错误。在使用-v选项运行它后,它会在状态7中显示冲突。

**
state 7

8 B: A .
9  | A . COMMA B

COMMA  shift, and go to state 10

COMMA     [reduce using rule 8 (B)]
$default  reduce using rule 8 (B)
**

规则8是
8 B:A

1 个答案:

答案 0 :(得分:3)

shift / reduce是一个CONFLICT而不是ERROR - 它告诉你语法不是LALR(1),因此bison生成的解析器可能只识别你的语言的一个子集。这可能是个问题,也可能不是。

在您的情况下,问题来自于CCOMMA之前有可选CLOSINGBRACES这一事实,但语法需要完成(减少)B在它可以继续解析C之前。因此,当您有{ INT , INT , }之类的输入时,当它到达第二个COMMA时,它不知道它是否应该减少B(完成列表),或者转移{{ 1}}让另一个COMMA添加到列表中。在这种情况下,它应该减少(因为constant应该是COMMA规则的一部分),但它不知道如果没有两个令牌前瞻,在{{C之后看到} 1}}。

在这种情况下,shift / reduce冲突的默认解析为shift意味着解析器总是期望逗号之后的另一个值,因此最终将解析语言而不使用可选的逗号(就像规则{{1 }}不存在)

解决此问题的一种简单方法是使,规则左递归而不是右递归:

C: COMMA CLOSINGBRACES

这样BB: A | B COMMA A ; 的有效前缀,因此解析器可以始终减少B,然后在结尾处添加额外的B它稍后(在转移COMMA并查看下一个令牌之后)。