我正在尝试解决几个yacc问题。在我遇到冲突后,我的尝试很少都是徒劳:减少/减少错误。举一个例子,我试图解决“比1更多的字符串”,我写下面的代码,显示减少/减少冲突(我只给出规则部分):
s : s1 ';' {printf("valid");exit(0);}
;
s1 : '0' '1' '0' s
| '0' '0' '1' s
| '1' '0' '0' s
| '0' s
|
;
任何人都可以告诉我这里我犯了什么错误如果你将来建议我如何从这个错误中恢复过来,我将不胜感激。
感谢你,
答案 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
的输入符合要求更多的零,但不会被此语法识别。