为什么这些冲突出现在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_list
是node_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