Why are these conflicts appearing in the following yacc grammar for XML

隐身守侯 提交于 2019-12-22 13:07:51

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!