下面是Bison非常简化的XML语法:
head : NODE_START NAME atts
| NODE_START NAME
;
element : head NODE_CLOSE NODE_END
| head NODE_END anys NODE_START NODE_CLOSE NAME NODE_END
| head NODE_END NODE_START NODE_CLOSE NAME NODE_END
;
text : TEXT
;
comment : NODE_START COMMENT_START COMMENT_END NODE_END
;
cdata : NODE_START CDATA_START CDATA_END NODE_END
;
attr : NAME EQUALS value
;
value : QUOTED
| APOSED
;
atts : attr atts
| attr
elt : element
| comment
| cdata
any : elt
| text
;
elts : elt elts
| elt
;
anys : text elts anys
| elts
| text
;
s : any
| PROLOG any
;
所谓的冲突是anys -> text
规则。
当我查看相应的输出时:
State 35
21 anys: text elts . anys
NODE_START shift, and go to state 1
TEXT shift, and go to state 2
head go to state 4
element go to state 5
text go to state 25
comment go to state 7
cdata go to state 8
elt go to state 26
elts go to state 27
anys go to state 42
我如何理解这里发生的冲突?
答案 0 :(得分:1)
如果查看.output文件的开头,您将看到以下内容:
Rules useless in parser due to conflicts
23 anys: text
State 26 conflicts: 1 shift/reduce
State 27 conflicts: 1 shift/reduce
第一个警告告诉您生产anys: text
完全被消除,因为解析冲突的解决方案(语法中的其他地方)使得规则无法被使用。 (因此,它是“无用的”。)接下来的两行告诉你在哪里可以找到冲突:在状态26和27中。
所以你引用的规则是不“涉嫌冲突”,你所引用的状态与冲突无关(事实上,我不知道你为什么专注于它。)
在有冲突的州,你会看到,例如:
State 26
21 anys: text . elts anys
23 | text .
NODE_START shift, and go to state 1
NODE_START [reduce using rule 23 (anys)]
head go to state 4
element go to state 5
comment go to state 7
cdata go to state 8
elt go to state 27
elts go to state 35
冲突由前瞻(在这种情况下为NODE_START
)指示,具有两个或更多不同的操作。括号括起来的行动(在这种情况下为[reduce using rule 23 (anys)]
)被野牛的冲突解决机制(在没有优先权声明的情况下,如果有的话选择转移行动,以及其他减少行动)消除最小的生产数量。)
状态转储应该清楚说明为什么规则anys: text
变得无用。在可以减少的两种情况下,都存在减少转移的冲突,并且转移行动是首选。
问题是anys: text elts anys
。考虑一个由三个elt
组成的输入。这可以解析为elts
,其中包含两个elt
s,后跟一个由elts
组成的elt
,反之亦然。模棱两可导致转移减少冲突。
该制作的另一个问题是它不允许elts
以text
结尾(除非它只包含一个text
。
更好的定义是简单的
anys: any | anys any
注意:您使用的是自下而上的解析器,右递归(字面上)是反模式。如上所述以递归方式编写列表将限制解析器堆栈的使用并导致senantic操作以预期的顺序(即从左到右)运行。除非你有非常具体的需求,否则你应该避免正确的递归。