问题
I have the following XML grammar which works fine:
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 '"'
;
I don't like the additional statement for empty node_list so I added an empty rule to node_s |
but by doing so i get the following conflicts
conflicts: 8 shift/reduce
prog1.y:40.10: warning: rule useless in parser due to conflicts: node_s: /* empty */
I have no idea why, any help would be appreciated.
回答1:
Running bison --verbose a.y
prints information into file a.output
. The file contains information such as:
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 .
Here we can see that in state 27 there are 2 shift/reduce conflicts. I will describe the 1st shift/reduce conflict: when the state machine is in state 27, and the input is ID
, the machine can do two actions:
shift, and go to state 28
[reduce using rule 8 (node_s)]
The 1st action was generated by rule 7 node_s:ID
, the 2nd action was generated by rule 8 node_s:/*empty*/
. It is ambiguous which action to choose.
node_list
is list of node_s
. In state 27, the input ID
can be parsed as
<nothing> ID node_list = node_s:/*empty*/, node_s:ID
or as
ID node_list = node_s:ID
In other words, it is impossible to decide whether the node list should begin with an empty node.
To fix this problem, the grammar should be modified like this:
node_list
: /*empty*/
| node_list node_s
;
node_s
: node
| u_node
| ID
;
u_node
:'<' ID attribute_list '>' node_list '<''/'ID'>'
;
Now, when parsing node_list '<''/'ID'>'
, the input will unambiguously determine whether the node list is empty or non-empty:
INPUT ACTION
< / empty node list
< ID non-empty node list
ID non-empty node list
来源:https://stackoverflow.com/questions/9651733/why-are-these-conflicts-appearing-in-the-following-yacc-grammar-for-xml