为什么这些冲突出现在XML的以下yacc语法中

我有以下XML语法,工作正常:

program : '' root ; root : '' node_list '' ; node_list : node_s | node_list node_s ; node_s : node | u_node | ID ; node : '' ; u_node :'' node_list '' |'' '' ; attribute_list : attributes | ; attributes : attribute | attributes attribute ; attribute : ID ASSIGNOP '"' ID '"' | ID ASSIGNOP '"' NUM '"' | ID ASSIGNOP '"' NUM ID'"' | ID ASSIGNOP '"' WEB '"' ; 

我不喜欢空node_list的附加语句,所以我在node_s |中添加了一个空规则

但通过这样做,我得到以下冲突

 conflicts: 8 shift/reduce prog1.y:40.10: warning: rule useless in parser due to conflicts: node_s: /* empty */ 

我不知道为什么,任何帮助将不胜感激。

运行bison --verbose ay信息打印到文件a.output 。 该文件包含以下信息:

 State 27 conflicts: 2 shift/reduce Grammar 3 node_list: node_s 4 | node_list node_s 5 node_s: node 6 | u_node 7 | ID 8 | /* empty */ ... state 27 2 root: '<' ID attribute_list '>' . node_list '<' '/' ID '>' ID shift, and go to state 28 '<' shift, and go to state 29 ID [reduce using rule 8 (node_s)] '<' [reduce using rule 8 (node_s)] node_list go to state 30 node_s go to state 31 node go to state 32 u_node go to state 33 state 28 7 node_s: ID . 

在这里我们可以看到在状态27中存在2个移位/减少冲突。 我将描述第一次转换/减少冲突:当状态机处于状态27并且输入是ID ,机器可以执行两个操作:

 shift, and go to state 28 [reduce using rule 8 (node_s)] 

第一个操作由规则7 node_s:ID生成,第二个操作由规则8 node_s:/*empty*/ 。 选择哪种行动是模棱两可的。

node_listnode_s列表。 在状态27中,输入ID可以被解析为

  ID node_list = node_s:/*empty*/, node_s:ID 

或者作为

 ID node_list = node_s:ID 

换句话说,不可能确定节点列表是否应该以空节点开始。

要解决此问题,应该像这样修改语法:

 node_list : /*empty*/ | node_list node_s ; node_s : node | u_node | ID ; u_node :'<' ID attribute_list '>' node_list '<''/'ID'>' ; 

现在,在解析node_list '<''/'ID'>'输入将明确地确定节点列表是空还是非空:

 INPUT ACTION < / empty node list < ID non-empty node list ID non-empty node list