语义分析.docx
- 文档编号:15464541
- 上传时间:2023-07-04
- 格式:DOCX
- 页数:14
- 大小:334.75KB
语义分析.docx
《语义分析.docx》由会员分享,可在线阅读,更多相关《语义分析.docx(14页珍藏版)》请在冰点文库上搜索。
语义分析
三、词法、语法、语义分析结合
一、实验目的与要求
在实现词法、语法分析程序的基础上,编写相应的语义子程序,进行语义处理,加深对语法制导翻译原理的理解,进一步掌握将语法分析所识别的语法范畴变换为某种中间代码(四元式)的语义分析方法,并完成相关语义分析器的代码开发。
二、实验内容
语法制导翻译模式是在语法分析的基础上,增加语义操作来实现的。
对于给定文法中的每一产生式,编写相应的语义子程序。
在语法分析过程中,每当用一个产生式进行推导或归约时,语法分析程序除执行相应的语法分析动作之外,还要调用相应的语义子程序,以便完成生成中间代码、查填有关表格、检查并报告源程序中的语义错误等工作。
每个语义子程序需指明相应产生式中各个符号的具体含义,并规定使用该产生式进行分析时所应采取的语义动作。
这样,语法制导翻译程序在对源程序从左到右进行的一遍扫描中,既完成语法分析任务,又完成语义分析和中间代码生成方面的工作。
输入:
包含测试用例,如由无符号数和+、−、*、/、(、)构成的算术表达式的源程序文件。
输出:
将源程序转换为中间代码形式表示,并将中间代码序列输出到文件中。
若源程序中有错误,应指出错误信息。
三、实验设计
语法制导翻译模式实际上是对前后文无关文法的一种扩展。
一般而言,首先需要根据进行的语义工作,完成对文法的必要拆分和语义动作的编写,从而为每个产生式都配备相应的语义子程序,以便在进行语法分析的同时进行语义解释。
要求从编译器的整体设计出发,重点通过对实验二中语法分析程序的扩展,完成一个编译器前端程序的编写、调试和测试工作,形成一个将源程序翻译为中间代码序列的编译系统。
对文法G3[<算术表达式>]中的产生式添加语义处理子程序,完成无符号数的四则运算的计值处理,将输入的四则运算转换为四元式形式的中间代码。
本实验只进行了算术表达式四元式的翻译。
四、源代码
1、在.h文件中添加了
//语义分析部分
#definePMAX5//define后面不加括号,定义产生式符号属性字符串的长度
intNXQ=0;/*全局变量NXQ用于指示所要产生的下一个四元式的编号*/
intNXTemp=1;//整型变量NXTemp指示临时变量的编号
intSentenceCount=1;//存放文件中句子的个数
structQUATERNION/*四元式表的结构*/
{
charop[PMAX];/*操作符*/
chararg1[PMAX];/*第一个操作数*/
chararg2[PMAX];/*第二个操作数*/
charresult[PMAX];/*运算结果*/
}pQuad[256];/*存放四元式的数组*/
charEBracket_Place[PMAX];//(E)的语义属性
chari_Place[PMAX];
charE_Place[PMAX];
charT_Place[PMAX];
charF_Place[PMAX];
//charJudgeStr[100];
intEXCUTE(intstate,intsymbol,FILE*fp,charJudgeStr[],introw,intindex);
intGetChar(charch);
intHandleError(charStrJudge[],introw);
intPush(intState);
intPop(intcount);
intSLRControl(FILE*fp);
voidGEN(char*Op,char*Arg1,char*Arg2,char*Result);
char*NewTemp(void);
voidNextSentence(FILE*fp);//当语法或者词法产生错误的时候,跳过当前错误的句子,将文件指针指向下一个句子的开始
#defineMAXLENGTH10;
voidGEN(char*Op,char*Arg1,char*Arg2,char*Result)
{
strcpy(pQuad[NXQ].op,Op);/*pQuad为全局变量,是用于存放四元式的数组*/
strcpy(pQuad[NXQ].arg1,Arg1);
strcpy(pQuad[NXQ].arg2,Arg2);
strcpy(pQuad[NXQ].result,Result);
NXQ++;/*全局变量NXQ用于指示所要产生的下一个四元式的编号*/
}
char*NewTemp(void)/*产生一个临时变量*/
{
char*TempID=(char*)malloc(PMAX);
sprintf(TempID,"T%d",NXTemp++);
returnTempID;
}
2、在.cpp文件中修改的部分
intSLRControl(FILE*fp)
{
while(Action[TopState][InputWordType][0]!
='A')
{
if(UNKNOWN==InputWordType)
{
printf("**********************分析语句%i时词法分析出错******************\n",SentenceCount);
return0;
}
printf("栈顶状态:
%i\n",TopState);
printf("扫描的单词类型:
%i\n",InputWordType);
/*if('A'==Action[State][WordType][0])
{
TopState=0;//正确后把栈顶状态置为初始化
StackPoint=0;//同理上面
memset(StateStack,-1,sizeof(StateStack));
printf("Right!
");
return1;
}*/
if(-1==TopState)
{
printf("分析语句%i时状态栈栈顶指针错误!
分析结束\n",SentenceCount);
return0;
}
if(''==Action[TopState][InputWordType][0])
{
printf("分析语句%i时语法分析出错!
分析结束\n",SentenceCount);
return0;
}
elseif('s'==Action[TopState][InputWordType][0])
{
//TopState=atoi(&Action[TopState][InputWordType][1]);
Push(atoi(&Action[TopState][InputWordType][1]));
printf("执行压栈操作\n");
if(EOF!
=fgetc(fp))
{
scanner(fp);
}
else
{
printf("语句%i不完整!
分析结束\n",SentenceCount);
return0;
}
}
elseif('r'==Action[TopState][InputWordType][0])
{
//do//用一个while循环为了可能遇到连续规约的情况,即从文件中扫描一个单词之后,可能连续规约多次
//{
intProductionNum=atoi(&Action[TopState][InputWordType][1]);
intProdutionLeft=0;
if(1==ProductionNum)
{
ProdutionLeft=E;//为下面差goto表提供列坐标
Pop(3);
printf("用产生式1归约\n");
char*Temp=NewTemp();
GEN("+",E_Place,T_Place,Temp);
strcpy(E_Place,Temp);
printf("生成四元式:
(“+”,E_Place,T_Place,E_Place)\n");
}
elseif(2==ProductionNum)
{
ProdutionLeft=E;
Pop(3);
printf("用产生式2归约\n");
char*Temp=NewTemp();
GEN("-",E_Place,T_Place,Temp);
strcpy(E_Place,Temp);
printf("生成四元式:
(“-”,E_Place,T_Place,E_Place)\n");
}
elseif(3==ProductionNum)
{
ProdutionLeft=E;
Pop
(1);
printf("用产生式3归约\n");
char*Temp=NewTemp();
GEN("",T_Place,"",Temp);
strcpy(E_Place,Temp);
printf("生成四元式:
(-,-,T_Place,E_Place)\n");
}
elseif(4==ProductionNum)
{
ProdutionLeft=T;
Pop(3);
printf("用产生式4归约\n");
char*Temp=NewTemp();
GEN("*",T_Place,F_Place,Temp);
strcpy(T_Place,Temp);
printf("生成四元式:
(“*”,T_Place,F_Place,T_Place)\n");
}
elseif(5==ProductionNum)
{
ProdutionLeft=T;
Pop(3);
printf("用产生式5归约\n");
char*Temp=NewTemp();
GEN("/",T_Place,F_Place,Temp);
strcpy(T_Place,Temp);
printf("生成四元式:
(“/”,T_Place,F_Place,T_Place)\n");
}
elseif(6==ProductionNum)
{
ProdutionLeft=T;
Pop
(1);
printf("用产生式6归约\n");
char*Temp=NewTemp();
GEN("+",F_Place,"",Temp);
strcpy(T_Place,Temp);
printf("生成四元式:
(-,-,F_Place,T_Place)\n");
}
elseif(7==ProductionNum)
{
ProdutionLeft=F;
Pop(3);
printf("用产生式7归约\n");
char*Temp=NewTemp();
GEN("+",EBracket_Place,"",Temp);
strcpy(F_Place,Temp);
printf("生成四元式:
(-,-,(E)_Place,F_Place)\n");
}
elseif(8==ProductionNum)
{
ProdutionLeft=F;
Pop
(1);
printf("用产生式8归约\n");
char*Temp=NewTemp();
GEN("+",i_Place,"",Temp);
strcpy(F_Place,Temp);
printf("生成四元式:
(-,-,i_Place,F_Place)\n");
}
else
{
printf("分析语句%i时产生式编号超出范围!
分析结束\n",SentenceCount);
return0;
}
Push(Goto[TopState][ProdutionLeft]);
//}while('r'==Action[TopState][InputWordType][0])
}
}
printf("栈顶状态:
%i\n",TopState);
printf("扫描的单词类型:
%i\n",InputWordType);
printf("*********************************语句%i正确*********************************\n",SentenceCount);
return1;
}
voidNextSentence(FILE*fp)
{
while('#'!
=ch)
{
ch=fgetc(fp);
}
if('\n'==fgetc(fp)){
return;}
SentenceCount++;
return;
}
/////////////////////////////////主程序
intmain(intargc,char*argv[])
{
externcharch;
FILE*fp;
if((fp=fopen("date.txt","r"))==NULL)
{
printf("\nfileopenerror!
\n");
exit(0);
}
if(ch=fgetc(fp)=='EOF')//不管小括号内的判断是否成功,p指针都会向后移一个位置,判断不成功,ch中存的字符不变
{
printf("Thefileisnull.\n");
return0;
}
while('\n'!
=fgetc(fp))
{
TopState=0;
StackPoint=0;
memset(StateStack,-1,sizeof(StateStack));
printf("***********************语句%i分析开始**************************\n",SentenceCount);
scanner(fp);
SLRControl(fp);
NextSentence(fp);
}
//printf("第一个字母是:
%c\n",ch);
//fseek(p,-1,1);
/*do
{
scanner(p);
}while(ch=fgetc(p)!
=EOF);*/
fclose(fp);
return0;
}
五、测试用例和结果分析
运行结果:
结果分析:
虽然能分开语句,但仍用“#”做结束标识符。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语义 分析