自上而下语法实验报告剖析.docx
《自上而下语法实验报告剖析.docx》由会员分享,可在线阅读,更多相关《自上而下语法实验报告剖析.docx(11页珍藏版)》请在冰豆网上搜索。
![自上而下语法实验报告剖析.docx](https://file1.bdocx.com/fileroot1/2023-1/14/3b357bd4-e30a-4f51-a87a-2275532d9b74/3b357bd4-e30a-4f51-a87a-2275532d9b741.gif)
自上而下语法实验报告剖析
自上而下语法分析
1、实验目的:
1.根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
(选做)
2.根据某一文法编制调试LL
(1)分析程序,以便对任意输入的符号串进行分析。
(必做)
2、本次实验的目的主要是加深对自上而下分析法的理解。
实验内容:
(1)程序的功能描述
LL
(1)分析法的功能是利用LL
(1)控制程序根据显示栈栈顶内容、向前看符号以及LL
(1)分析表,对输入符号串自上而下的分析过程。
具体描述如下:
对下列文法,对任意输入的符号串进行分析:
(1)E->TG
(2)G->+TG
(3)G->ε
(4)T->FS
(5)S->*FS
(6)S->ε
(7)F->(E)
(8)F->i
输入一以#结束的符号串(包括+—*/()i#):
输出结果:
包括分析栈、数组中的剩余字符串以及所用的产生式,形如:
分析栈
剩余输入串
所用产生式
E
i+i*i#
E->TG
其中有如下两点要求:
1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符I,结束符#;
2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);
(二)LL
(1)分析法实验设计思想及算法
三、程序设计的过程以及关键函数的功能
(一)模块结构:
1、定义部分:
定义常量、变量、数据结构。
2、初始化:
设立LL
(1)分析表、初始化变量空间(包括堆栈、结构体等);
3、运行程序:
让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则;
4、利用LL
(1)分析算法进行表达式处理:
根据LL
(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简单的错误提示。
(二)程序的整体流程及关键函数解析:
1、定义一个栈,用于存放非终结符
2、将终结符和非终结符各存放在一个数组中,用于判断栈顶元素是否是终结符或非终结符,然后根据情况判断接下来是查表,还是进行匹配移进。
3、定义一个全局变量f,用于指示从文件中读出的匹配后的剩余字符串中的首个字符在数组中的位置。
当输出栈时,同时输出剩余字符串。
4、对于chaxun()函数,X在v2[5]中的位置相当于表的行位置,sym在v1[6]中的位置,相当于表的列位置。
根据查表操作可以判断(X,sym)对于的表中是否有产生式。
boolchaxun(charX,charsym){
intm=feizhongjie(X);
intn=iszhongjie(sym);
charstr[10];
strcpy(str,table[m][n]);
if(strlen(str)==0)
{returnfalse;}
else
{if(str[0]!
='^')
{
for(inti=strlen(str)-1;i>=0;i--)
push(str[i]);
}
print();
cout<<'\t'<"<returntrue;}
}
5、读文件,并将文件里的内容读入数组b[]中。
6、根据表中的产生式,对栈顶元素根据情况进行移进匹配操作,知道剩余表达式中无非终结符为止,即匹配成功。
否则,则匹配失败,给出的字符表达式无法由给定的文法推出。
while(flag&&!
cuo)
{
X=pop();//把符号栈的式子付给x
if(X=='#')
{
if(sym==X)
{
cout<<"输入的是合法符号串"<flag=false;
}
else
cout<<"非法的符号串"<}
elseif(iszhongjie(X)!
=-1){//如果是终结符跳到if
if(X==sym)
{
f++;
sym=fgetc(fp);
}
else
printf("错误");}
else
if(!
chaxun(X,sym))cuo=true;
}
四、运行结果:
输入文件内容:
i+i*i
若输入i++i*i,显示如下:
若输入i*(i+i),显示如下:
五、实验总结
通过本次实验,我初步掌握了ll
(1)文法,在写代码的过程中也加深了我对栈的理解,,老师课上已经讲解了许多,而且实验时也指导了我们一些该注意的地方,中间还是有一些小问题但是,在判断输入串是否匹配的时候,还是有些问题,不过总体目标还是完成了,当然问题最多的还是栈顶元素与剩余字符串的移进匹配过程,这一点我老是搞不太清楚。
不过在同学的帮助和指导下这些问题都慢慢的解决了。
不过总体来说,使我的编程能力得到了很大的提高。
附录:
#include
#include
#include
#include
#include
#include
#defineerror0
structStack{
chars[30];
inttop;//栈顶指针
}S1;
intf=0;
charb[20];
charv1[6]={'i','+','*','(',')','#'};//终结符
charv2[5]={'E','G','T','S','F'};//非终结符
/*用二维数组保存预测分析表,可用符号^来代替ε,注意字符串结束位自动加'\0'*/
chartable[5][6][4]={{"TG","","","TG","",""},
{"","+TG","","","^","^"},
{"FS","","","FS","",""},
{"","^","*FS","","^","^"},
{"i","","","(E)","",""}};
voidprintbiao()
{
cout<<"TG@@TG@@"<cout<<"@+TG@@^^"<cout<<"FS@@FS@@"<cout<<"@^*FS@^^"<cout<<"i@@(E)@@"<}
voidprint()/*输出分析栈*/
{
inta;/*指针*/
for(a=0;acout<cout<<'\t';
intlen=strlen(b);
for(intn=f;n{
cout<
}
}/*print*/
voidintialstack()
{
S1.top=0;
}
voidpush(charch)
{
S1.s[S1.top]=ch;S1.top++;
}
charpop()
{
S1.top--;
returnS1.s[S1.top];
}
intiszhongjie(charX){
for(intk=0;k<6;k++){
if(X==v1[k])
returnk;}
return-1;
}//判断X是否为终结符,是返回数组下标
intfeizhongjie(charf){
for(intk=0;k<5;k++){
if(f==v2[k])
returnk;}
return-1;
}//判断X是否为非终结符,是返回数组下标
boolchabiao(charX,charsym){
intm=feizhongjie(X);
intn=iszhongjie(sym);
charstr[10];
strcpy(str,table[m][n]);
if(strlen(str)==0)
{
//cout<<"匹配失败!
"<returnfalse;
}
else
{
if(str[0]!
='^')
{
for(inti=strlen(str)-1;i>=0;i--)
push(str[i]);
}
print();
cout<<'\t'<"<returntrue;
}
}
/*判断X是否为非终结符,sym是否为终结符,若是查找预测表对应表格是否为空白,是则出错,否则进栈*/
voidmain()
{
printbiao();
ifstreamfile("d:
\\111.txt");
file.getline(b,sizeoffile);
FILE*fp;
charsym,X;
boolflag,cuo;
if((fp=fopen("D:
\\111.txt","r"))==NULL)
{//读取文件内容,并返回文件指针,该指针指向文件的第一个字符
fprintf(stderr,"读取文件失败!
\n");
exit
(1);
}
intialstack();
push('#');
push('E');
sym=fgetc(fp);//把第一个输入符号读进sym
flag=true;
cuo=false;
print();
cout<while(flag&&!
cuo)
{
X=pop();
if(X=='#')
{
if(sym==X)
{
cout<<"匹配成功"<flag=false;
}
else
printf("错误");
}
elseif(iszhongjie(X)!
=-1){
if(X==sym)
{
f++;
sym=fgetc(fp);
}
else
printf("错误");}
else
if(!
chabiao(X,sym))cuo=true;
}
}