我正在编写一个简单的递归下降解析器,该解析器采用标准输入并计算'a'和'b'字符的数量。语法如下:
S-> A B'\ n'
A-> a A |空
B-> b B |空
int lookahead;
int nontermA();
int nontermB();
void match (int terminal){
if (lookahead == terminal){
lookahead = getchar();
} else {
printf("Syntax error at %c\n", lookahead);
exit(0);
}
}
void nontermS(){
int a,b;
switch(lookahead){
default:
a = nontermA();
b = nontermB();
printf("Match! Number of A's is %d and number of B's is %d", a,b);
match('\n');
}
}
int nontermA(){
int countA = 0;
switch(lookahead){
case 'a': match('a'); countA++; nontermA(); break;
case 'A': match('A'); countA++; nontermA(); break;
default: break;
}
return countA;
}
int nontermB(){
int countB = 0;
switch(lookahead){
case 'b': match('b'); countB++; nontermB(); break;
case 'B': match('B'); countB++; nontermB(); break;
default: break;
}
return countB;
}
基本上,如果我输入“ aA”,“ bB”或“ abAB”之类的东西,它应该只输出a和b的数目,但是我的程序的实际输出仅为a和b的1。当我输入“ ba”以及输入“ B”时,也会出现语法错误。
答案 0 :(得分:2)
nontermA
和nontermB
函数都表现出相同的逻辑缺陷。以下仅描述nontermA
的错误,但在nontermB
中也会发生相同的错误。
int countA = 0;
这声明了int
本地的新nontermA
变量。
case 'a': match('a'); countA++; nontermA(); break;
这使countA
递增,并递归地调用自身。
但是,nontermA
的每个递归调用的工作方式都与对nontermA
的任何其他函数调用完全相同:它创建了一个名为countA
的新局部变量并将其初始化为0。
此处的明显意图是使计数器在所有递归调用中均保持不变。但是递归不能以这种方式工作。
每个递归调用仅为该递归函数调用创建一个新的countA
局部int
变量 ,这是唯一递增的东西。这就是C ++的工作方式。
解决方案非常简单:只需返回计数器值,让nontermA
和nontermB
直接返回计数器值即可。
case 'a': match('a'); return nontermA()+1;
否则,
return 0;
没有匹配时。