我有以下XML语法可以正常工作:
program
: '<' '?'ID attribute_list '?''>'
root
;
root
: '<' ID attribute_list '>' node_list '<''/'ID'>'
;
node_list
: node_s
| node_list node_s
;
node_s
: node
| u_node
| ID
;
node
: '<' ID attribute_list '/''>'
;
u_node
:'<' ID attribute_list '>' node_list '<''/'ID'>'
|'<' ID attribute_list '>' '<''/'ID'>'
;
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 */
我不知道为什么,任何帮助都会受到赞赏。
答案 0 :(得分:2)
运行bison --verbose a.y
将信息打印到文件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
可以解析为
<nothing> 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