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

时间:2012-03-11 01:44:30

标签: c xml grammar bison yacc

我有以下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 */

我不知道为什么,任何帮助都会受到赞赏。

1 个答案:

答案 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_listnode_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