实验三 自下而上语法分析及语义分析.docx
《实验三 自下而上语法分析及语义分析.docx》由会员分享,可在线阅读,更多相关《实验三 自下而上语法分析及语义分析.docx(13页珍藏版)》请在冰豆网上搜索。
![实验三 自下而上语法分析及语义分析.docx](https://file1.bdocx.com/fileroot1/2023-2/4/a8b9884b-035e-4e19-adff-f22419045324/a8b9884b-035e-4e19-adff-f224190453241.gif)
实验三自下而上语法分析及语义分析
实验三自下而上语法分析及语义分析
一、实验目的:
通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:
4学时。
三、实验内容
根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法
采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:
●LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
●编写总控程序,实现语法分析和语义分析的过程。
注:
对于整数的识别可以借助实验1。
五、文法定义
简单的表达式文法如下:
E->E+T|E-T|T
T->T*F|T/F|F
F->(E)|i
上式中,i为整数。
六、处理程序例
例1:
正确源程序例:
23+(45+4)*40分析结果应为:
正确的表达式。
其值为:
1983
例2:
错误源程序例:
5+(56+)-24
分析结果应为:
错误的表达式:
出错位置为)
附录:
源程序
#include
#include"string.h"
#include
usingnamespacestd;
#defineR30
#defineC20
typedefstructelem
{
chare[4];
}Elem;//ACTION表与GoTo表中的元素类型
ElemLR[R][C];//存放ACTION表与GoTo表中的内容
typedefstructout
{
intorder;//序号
intstate[10];//状态栈
charsign[30];//符号栈
chargrasen[20];//产生式
charinput[30];//输入串
charexplen[50];//解释说明
}OutNode;//输出结果中每一行的类型
OutNodeout[20];//存放输出结果
charSentence[20];//存放文法的一个句子
charGramSent[10][20];//存放文法的一组产生式
introw,colno;//row为状态个数数,colno为ACTION表与GoTo表列总数
intstateTop=0,signTop=0;//状态栈与符号栈的栈顶位置(值与栈中元素的个数相等)
voidinput_GramSent()
{
inti,num;
printf("请输入文法中产生式的个数\n");
scanf("%d",&num);
for(i=0;i{
printf("请输入文法的第%d个产生式\n",i);
scanf("%s",GramSent+i-1);
}
printf("请输入文法的一个句子\n");
scanf("%s",Sentence);
printf("**********************************************************\n");
printf("*文法的产生式如下:
*\n");
printf("**********************************************************\n");
for(i=0;iprintf("%s\n",GramSent+i);
printf("**********************************************************\n");
printf("*文法的句子如下:
*\n");
printf("**********************************************************\n");
printf("%s\n",Sentence);
}
voidinput_LR(introw,intcolno)//row为行总数,colno为列总数
{
inti,j;
charmid[4];
printf("**********************************************************\n");
printf("*提示:
每输入一个元素后就回车*\n");
printf("**********************************************************\n");
printf("请输入LR分析表的终结符(包括#)与非终结符\n");
for(j=0;jscanf("%s",LR[0][j].e);
for(i=0;i{
printf("请输入%d号状态所对应的各列的元素,空白的地方用s代替\n",i);
for(j=0;j{
scanf("%s",mid);
if(strcmp(mid,"s")==0||strcmp(mid,"S")==0)
strcpy(LR[i+1][j].e,"");
else
strcpy(LR[i+1][j].e,mid);
}
}
}
voidoutput_LR(introw,intcolno)
{
inti,j;
printf("**********************************************************\n");
printf("*LR分析表如下:
*\n");
printf("**********************************************************\n");
printf("\n");
printf("");
for(j=0;jprintf("%s",LR[0][j].e);
printf("\n");
for(i=1;i<=row;i++)
{
printf("%d",i-1);
for(j=0;jprintf("%s",LR[i][j].e);
printf("\n");
}
printf("\n");
}
intSignNum(charch)//给定一个终结符或非终结符,返回其在ACTION表与GoTo表中的列位置
{
inti;
charc[2]="0";
c[0]=ch;
for(i=0;iif(strcmp(c,LR[0][i].e)==0)
returni;
return-1;
}
intCharChangeNum(char*ch)//给定一数字字符串,返回其所对应的数字
{
intresult=0;
while(*ch!
='\0')
{
result=result*10+(*ch-'0');
ch++;
}
returnresult;
}
intOutResult(ints,intc,inti)//输出结果的第i+1行处理函数,(s为状态,c为列)
{
charmid[4],gra[20];
ints_num,r_num;
intn,len,j;
strcpy(mid,LR[s+1][c].e);
if(strcmp(mid,"")==0)
{printf("不能规约\n");return-2;}
if(strcmp(mid,"acc")==0||strcmp(mid,"ACC")==0)
{printf("规约成功\n");return-1;}
out[i+1].order=i+2;
if(mid[0]=='s'||mid[0]=='S')
{
s_num=CharChangeNum(mid+1);//s_num为S后的数字
for(j=0;jout[i+1].state[j]=out[i].state[j];
out[i+1].state[stateTop]=s_num;
out[i+1].state[++stateTop]=-1;//完成第i+1行的状态栈赋值
strcpy(out[i+1].sign,out[i].sign);
out[i+1].sign[signTop]=out[i].input[0];
out[i+1].sign[++signTop]='\0';//完成第i+1行的符号栈的赋值
strcpy(out[i+1].grasen,"");//完成第i+1行的产生式的赋值
strcpy(out[i+1].input,out[i].input+1);//完成第i+1行的输入符号串的赋值
}
elseif(mid[0]=='r'||mid[0]=='R')
{
r_num=CharChangeNum(mid+1);//r_num为r后的数字
strcpy(gra,*(GramSent+r_num-1));
len=strlen(gra);
for(j=0;jif(gra[j]=='-'&&gra[j+1]=='>')
break;
n=strlen(gra+j+2);
stateTop-=n;signTop-=n;
for(j=0;jout[i+1].state[j]=out[i].state[j];
j=SignNum(gra[0]);
out[i+1].state[stateTop]=CharChangeNum(LR[out[i+1].state[stateTop-1]+1][j].e);
out[i+1].state[++stateTop]=-1;//完成第i+1行的状态栈赋值
strcpy(out[i+1].sign,out[i].sign);
out[i+1].sign[signTop]=gra[0];
out[i+1].sign[++signTop]='\0';//完成第i+1行的符号栈的赋值
strcpy(out[i+1].grasen,gra);//完成第i+1行的产生式的赋值
strcpy(out[i+1].input,out[i].input);//完成第i+1行的输入符号串的赋值
}
return1;
}
voidOutputResult(intr)
{
inti,j;
printf("**********************************************************\n");
printf("*句子:
%s用LR分析表规约过程如下:
*\n",Sentence);
printf("**********************************************************\n");
for(i=0;i<=r;i++)
{
j=0;
printf("%2d",out[i].order);
while(out[i].state[j]!
=-1)
printf("%d",out[i].state[j++]);
printf("%s%s%s\n",out[i].sign,out[i].grasen,out[i].input);
}
}
intOutControl()//输出结果的总控函数
{
ints_num,i=0;
out[0].order=1;//序号赋值
out[0].state[0]=0;stateTop=1;out[0].state[stateTop]=-1;//状态栈赋值,置栈顶位
strcpy(out[0].sign,"#");signTop=1;//符号栈赋值,置栈顶位
strcpy(out[0].grasen,"");//产生式为空
strcpy(out[0].input,Sentence);//以下两行为输入串赋值
strcat(out[0].input,"#");
strcpy(out[0].explen,"0和#进栈");//解释说明
//初使化输出结果的第一行
while
(1)
{
s_num=SignNum(out[i].input[0]);
//if(s_num!
=-1)
if(OutResult(out[i].state[stateTop-1],s_num,i)!
=1)
break;
i++;
}
returni;
}
main()
{
intr;
printf("**********************************************************\n");
printf("*函数的输入:
文法的产生式,文法句型的一个句子,LR分析表*\n");
printf("*函数的输出:
LR分析器的工作过程与说明*\n");
printf("**********************************************************\n");
printf("请输入LR分析表中终结符与非终结符的总个数\n");
scanf("%d",&colno);
printf("请输入LR分析表中状态的总个数\n");
scanf("%d",&row);
input_LR(row,colno);
output_LR(row,colno);
input_GramSent();
r=OutControl();//r为输出结果的行数
OutputResult(r);
}
七、实验小结
这个程序是从网上下载下来的,根据这个实验要求做了些更改,但是总是出现溢出错误,只能运行到LR分析表的部分(如截图),没有找到解决问题的办法。
(注:
专业文档是经验性极强的领域,无法思考和涵盖全面,素材和资料部分来自网络,供参考。
可复制、编制,期待你的好评与关注)
|