在编译原理的语法分析中,不少文法都是递归形式给出的。函数
假设有以下文法:spa
G[F]:code
F→fGblog
G→gF递归
判断字符串 a 是否知足的程序以下:ci
int F(int pos) { if(a[pos] == 'f') return G(pos+1); return -1; } int G(int pos) { if(a[pos] == 'g') return F(pos+1); return -1; } int main(){ //freopen("1.in","r",stdin); while(cin>>a){ printf("%d\n", F(0)); } return 0; }
易知,这个程序输出总为 -1,由于不存在有限长的 F,F = fgF.字符串
反过来,要想结果输出的不是 -1,F的结果是G(pos+1),G的结果又是F,不可能从这个圈推出。编译
若是咱们给 F/G 增长一个可行出口,就能找到知足条件的有限长的字符串。class
例如文法改为:编译原理
G[F]:
F→fG | a
G→gF
int F(int pos) { if(a[pos] == 'a') return pos+1; if(a[pos] == 'f') return G(pos+1); return -1; } int G(int pos) { if(a[pos] == 'g') return F(pos+1); return -1; }
此时,像 fgfga 这样的就知足条件了。
可见,相互递归调用有可行输出的条件是,一个函数的可行输出不是惟一的。