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
答案 0 :(得分:3)
shift / reduce是一个CONFLICT而不是ERROR - 它告诉你语法不是LALR(1),因此bison生成的解析器可能只识别你的语言的一个子集。这可能是个问题,也可能不是。
在您的情况下,问题来自于C
在COMMA
之前有可选CLOSINGBRACES
这一事实,但语法需要完成(减少)B
在它可以继续解析C
之前。因此,当您有{ INT , INT , }
之类的输入时,当它到达第二个COMMA
时,它不知道它是否应该减少B
(完成列表),或者转移{{ 1}}让另一个COMMA
添加到列表中。在这种情况下,它应该减少(因为constant
应该是COMMA
规则的一部分),但它不知道如果没有两个令牌前瞻,在{{C
之后看到}
1}}。
在这种情况下,shift / reduce冲突的默认解析为shift意味着解析器总是期望逗号之后的另一个值,因此最终将解析语言而不使用可选的逗号(就像规则{{1 }}不存在)
解决此问题的一种简单方法是使,
规则左递归而不是右递归:
C: COMMA CLOSINGBRACES
这样B
是B: A
| B COMMA A
;
的有效前缀,因此解析器可以始终减少B
,然后在结尾处添加额外的B
它稍后(在转移COMMA并查看下一个令牌之后)。