您使用的是右递归而不是左递归。通常,在 Bison 和 Yacc 语法中,左递归是首选。s
你有而不是s1
在s1
规则中也有点奇怪。
详细的输出文件(bison -v rrconf.y
yield 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'
|
;
%%
它给你留下了两个 shift/reduce 冲突(这比 reduce/reduce 冲突严重得多):
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)
这对你来说是否足够,我不确定。
不过,您还有另一个问题——高级算法设计问题。输入 101
后跟 110
满足零多于一的要求,但不会被此语法识别。