如何删除减少/减少冲突

时间:2013-09-15 14:14:19

标签: bison yacc

我正在尝试解决几个yacc问题。在我遇到冲突后,我的尝试很少都是徒劳:减少/减少错误。举一个例子,我试图解决“比1更多的字符串”,我写下面的代码,显示减少/减少冲突(我只给出规则部分):

    s   :   s1 ';'   {printf("valid");exit(0);}
        ;
    s1  :   '0' '1' '0' s   
        |   '0' '0' '1' s
        |   '1' '0' '0' s
        |   '0' s
        | 
        ;

任何人都可以告诉我这里我犯了什么错误如果你将来建议我如何从这个错误中恢复过来,我将不胜感激。

感谢你,

1 个答案:

答案 0 :(得分:1)

你正在使用右递归而不是左递归。通常,在Bison和Yacc语法中,左递归是首选。您在s规则中s1而不是s1也有点奇怪。

详细输出文件(bison -v rrconf.y产生rrconf.output)表示:

State 20 conflicts: 1 reduce/reduce
State 21 conflicts: 1 reduce/reduce

Grammar

    0 $accept: s $end

    1 s: s1 ';'

    2 s1: '0' '1' '0' s
    3   | '0' '0' '1' s
    4   | '1' '0' '0' s
    5   | '0' s
    6   | /* empty */

...

state 20

    2 s1: '0' '1' '0' s .
    5   | '0' s .

    ';'       reduce using rule 2 (s1)
    ';'       [reduce using rule 5 (s1)]
    $default  reduce using rule 2 (s1)


state 21

    4 s1: '1' '0' '0' s .
    5   | '0' s .

    ';'       reduce using rule 4 (s1)
    ';'       [reduce using rule 5 (s1)]
    $default  reduce using rule 4 (s1)

将语法更改为使用左递归很容易:

%%
s   :   s1 ';'   {printf("valid");exit(0);}
    ;
s1  : s1 '0' '1' '0'
    | s1 '0' '0' '1'
    | s1 '1' '0' '0'
    | s1 '0'
    | 
    ;
%%

它会给你留下两个转移/减少冲突(比减少/减少冲突要严重得多):

State 5 conflicts: 2 shift/reduce

Grammar

    0 $accept: s $end

    1 s: s1 ';'

    2 s1: s1 '0' '1' '0'
    3   | s1 '0' '0' '1'
    4   | s1 '1' '0' '0'
    5   | s1 '0'
    6   | /* empty */

...


state 5

    2 s1: s1 '0' . '1' '0'
    3   | s1 '0' . '0' '1'
    5   | s1 '0' .

    '0'  shift, and go to state 7
    '1'  shift, and go to state 8

    '0'       [reduce using rule 5 (s1)]
    '1'       [reduce using rule 5 (s1)]
    $default  reduce using rule 5 (s1)

这对你来说是否足够,我不确定。

但是仍然存在另一个问题 - 高级算法设计问题。输入10 1后跟11 0的输入符合要求更多的零,但不会被此语法识别。