COMMA 移位/减少误差 bison

1 bison

A: constant
 | OPENINGBRACES B C 
;

constant: INTEGER | REAL | CHARACTER ;

C: CLOSINGBRACES
 | COMMA CLOSINGBRACES
;

B: A
 | A COMMA B 
;
Run Code Online (Sandbox Code Playgroud)

该语法正在产生移位/减少错误。使用 -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)
**
Run Code Online (Sandbox Code Playgroud)

规则 8 是
8 B: A

Chr*_*odd 5

移位/归约是冲突而不是错误——它告诉您语法不是 LALR(1),因此 bison 生成的解析器可能只能识别您语言的子集。这可能是个问题,也可能不是。

在您的情况下,问题来自于在 之前C有一个可选的事实,但语法需要完成(减少) 之前它可以继续解析。因此,当您有像 之类的输入时,当它到达第二个时,它不知道是否应该减少(完成列表),或移动以获取另一个以添加到列表中。在这种情况下,它应该减少(因为应该是规则的一部分),但它不知道如果没有两个标记前瞻来查看后的内容。COMMACLOSINGBRACESBC{ INT , INT , }COMMABCOMMAconstantCOMMAC},

在这种情况下,移位/归约冲突的默认解决方案为移位意味着解析器将始终期望逗号后有另一个值,因此最终将解析不带可选逗号的语言(就好像规则不C: COMMA CLOSINGBRACES存在一样)

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

B: A
 | B COMMA A
;
Run Code Online (Sandbox Code Playgroud)

这样, aB是 a 的有效前缀B,因此解析器始终可以减少 a B,然后A在稍后在其末尾添加额外的 s (在移动逗号并查看下一个标记是什么之后)。