1
A: constant
 | OPENINGBRACES B C 
;

constant: INTEGER | REAL | CHARACTER ;

C: CLOSINGBRACES
 | COMMA CLOSINGBRACES
;

B: A
 | A COMMA B 
;

这个语法正在产生移位/减少错误。使用 -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

4

1 回答 1

5

移位/减少是冲突而不是错误——它告诉你语法不是 LALR(1),所以野牛生成的解析器可能只识别你语言的一个子集。这可能是个问题,也可能不是。

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

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

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

B: A
 | B COMMA A
;

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

于 2013-10-20T18:43:21.263 回答