#include<stdio.h>
#include<string.h>
char lookahead;
char token[80];\\存储字符串
char ch,t;
int p=0;
int flat=1;\\标志位
void G();
void T();
void S();
void F();//函数声明
void match(char t)//匹配函数
{
if(lookahead==t)
{
lookahead=token[++p];
}
else printf("匹配不正确") ;
}
void E()
{
printf("E=>TG ");
T();
G();
}
void G()
{
if(lookahead=='+')
{
printf(" G=>+TG");
match('+');
T();
G();
}
else if (lookahead=='-')
{
printf(" G=>-TG ");
match('-');
T();
G();
}
else printf(" G=>ε");
}
void T()
{
printf(" T=>FS");
F();
S();
}
void S()
{
if(lookahead=='*')
{
printf(" S=>*FS");
match('*');
F();
S();
}
else if(lookahead=='/')
{
printf(" S=>/FS");
match('/');
F();
S();
}
else printf(" S=>ε");
}
void F()
{
if(lookahead=='i')
{ printf(" F=>i ");
match('i');
}
else if(lookahead=='(')
{
printf(" F=>(E)");
match('(');
E();
if(lookahead==')')
{ match(')');
}
else
{ flat=0; }
}
else
{ flat=0; }
}
int main()
{
int pd=1;
int r=0;
char ch;
printf("请输入以#结束的符号串(包括+ - * / ( ) i #):");
do{
ch=getchar();
token[r++]=ch;
}while(ch!='#');
lookahead=token[0];
E();
printf("\n");
if(pd==flat&&lookahead=='#')
{
printf("输出结果:");
printf("%s",token);
printf("为合法符号串\n");
}
else {
printf("输出结果:");
printf("非法的符号串\n");
}
实验总结:
1.对于嵌套调用函数必须在函数前进行函数声明
2.递归下降分析法和LL(1)文法都必须消除文法二义性,消除左递归,提公共公左因子
3.最重要的是lookahead=token[0];E();调用且只调用一次文法开始符,切勿循环调用
4.错误可以用一个标志位解决,首先可以将flat定义为1,然后如果错了将flat置为0,最后通过if(pd==flat&&lookahead=='#')判断分析是否正确。(解释为什么要判断lookahead是否等于‘#’?如果最后分析错误,那么lookahead就不会指道‘#’。例如字符串‘i)#’,lookahead首先指向i,
E->TG,T->FS,F->i(匹配成功,lookahead指向下一个,既‘)’),S->ε,G->ε(G要么匹配加要么匹配减,而lookahead指向右括号,所以执行else,返回ε,最后函数调用完lookahead值为右括号,并非#,所以以lookahead最后等于#作为判断是否成功的其中一个条件))
5.特别注意有左右括号的写法有俩个错误输出,第一如果匹配不上右有括号;一个是既匹配不上i,又匹配不上左括号
if(lookahead=='(')
{
match('(');
E();
if(lookahead==')')
{ match(')');
}
else
{ flat=0; }
}
else
{ flat=0; }
}