编译原理语法分析.docx
- 文档编号:9027009
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:17
- 大小:20.10KB
编译原理语法分析.docx
《编译原理语法分析.docx》由会员分享,可在线阅读,更多相关《编译原理语法分析.docx(17页珍藏版)》请在冰豆网上搜索。
编译原理语法分析
实验三 中间代码生成
一.实验目的与要求:
1.掌握语法制导进行语义分析的基本方法。
2.中间代码的几种形式(后缀式,三元式,四元式,抽象语法树和DAG图)。
3.掌握简单表达式,多维下标变量、原子语句、结构语句、声明的中间代码结构。
4.用LR分析法处理表达式(简单的表达式)。
二.实验内容:
给出一表达式的后缀式,借助于语义信息找semstack(数组实现)输出其四元式,假设此表达式只含常量或变量,不含函数的调用。
三、主要算法如下:
1、此方法处理的要点:
A.当读出常量C时,产生常量的内部表示将类型和值Arg(c)压入语义信息栈中。
B.当读出变量id时,产生变量的内部表示,将其类型和内部地址压入语义信息栈。
C.当碰到运算符w时,从栈顶出两个元素即sem[top]和sem[top-1],产生中间代码Gencode,并从栈顶删除这两个元素,将此中间代码的结果的临时变量的类型和临时变量的地址入栈。
D.重复上述工作,直到扫描完整个表达式。
2、产生中间代码的Gencode过程,工作如下:
1.若sem[top-1].Type≠sem[top].Type,且sem[top-1].Type=integer则结果为实型real,并且为左分量即sem[top-1]产生类型转换代码。
则结果为实型real,并且为左分量产生类型转换代码。
2.若sem[top-1].Type≠sem[top].Type,且sem[top].Type=integer则结果为实型real并且为右分量即sem[top]产生类型转换代码。
3.若sem([op-1].Type=sem[top].Type,则结果类型为sem[top].Type不产生类型转换。
4.产生(w,sem[top-1],sem[top],temp)中间代码。
5.删除左右分量的栈单元,把结果的类型和临时变量地址入栈。
四、实验代码:
#include
#include
#include
typedefstruct{
charname[10];
chartype;
}sem,*ptsem;
typedefstruct{
ptsem*base;
intutop;
}stack;
inti=1;
intj=0;
intn=0;
stacklist;
charst[10],str1[10],*p;
ptsemyylist=newsem[10];
voidpop(ptsem&pt)
{
pt=list.base[list.utop--];
return;
}
voidgencode(ptsemtop,ptsemsubtop,charw)
{
ptsempt=newsem;
if(top->type==subtop->type){}
elseif(top->type!
='r')
{
printf("(FLOAT,%s,t%d);\n",top->name,i);
charc=i+48;
top->name[0]='t';
top->name[1]=c;
top->name[2]='\0';
top->type='r';
i++;
}
else
{
printf("(FLOAT,%s,t%d);\n",subtop->name,i);
charc=i+48;
subtop->name[0]='t';
subtop->name[1]=c;
subtop->name[2]='\0';
subtop->type='r';
i++;
}
printf("(%c,%s,%s,t%d);\n",w,subtop->name,top->name,i);
charc=i+48;
pt->type=top->type;
pt->name[0]='t';
pt->name[1]=c;
pt->name[2]='\0';
i++;
push(pt);
return;
}
voididentify()
{
while(*p>='a'&&*p<='z')
st[j++]=*p++;
st[j]='\0';
j=0;
intflag=0;
if(!
strcmp(st,"float")||!
strcmp(st,"int"))flag=1;
if(flag==1){strcpy(str1,st);return;}
sempp;
if(!
strcmp(str1,"float"))
{
strcpy(pp.name,st);
pp.type='r';
}
if(!
strcmp(str1,"int"))
{
strcpy(pp.name,st);
pp.type='i';
}
yylist[n++]=pp;
}
voidconid()
{
ptsempt=newsem;
intflag=0,k=0;
do
{
pt->name[k++]=*p;
if(*p++=='.')flag=1;
}while(*p>='0'&&*p<='9'||*p=='.');
pt->type=flag?
'r':
'i';
if(*p>'9'&&*p<'0')
{printf("theconstdatayouinputediswrong");
exit(0);
}
pt->name[k]='\0';
push(pt);
}
voidmain()
{
initlist();
printf("\n");
charstr[100];
gets(str);
p=str;
while(*p!
='\0')
{
if(!
(*p>='a'&&*p<='z'||*p>='A'&&*p<='Z'||*p==';'||*p==''||*p==','))
{printf("thisdefineiswrong!
");exit(0);}
switch(*p){
case',':
p++;break;
case'':
p++;break;
case';':
p++;break;
default:
identify();
}
}
charstrpds[100];
gets(strpds);
p=strpds;
charch=*p,a;
ptsemtop,subtop;
while(*p!
='\0'){
if(ch>='0'&&ch<='9')a='0';
elseif(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')a='1';
elseif(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='^')a='2';
elseif(ch==';')break;
elseif(ch=='')a='4';
elsea='3';
switch(a){
case'0':
conid();ch=*p;break;
case'1':
varid();ch=*p;break;
case'2':
pop(top);pop(subtop);gencode(top,subtop,ch);ch=*++p;break;
case'3':
printf("%cisaillegalletter!
\n",ch);exit(0);
case'4':
ch=*++p;
}
}
if(*++p!
='\0')
printf("thissetenseisillegal!
");
}
实验四中间代码优化
一.实验的目的和要求:
1.掌握中间代码优化的目标和要求及优化的必要性。
2.掌握几种优化方法及优化能到什么程度。
3.实现一种简单的中间代码优化常量表达式的局部优化。
二、基本块上常量表达式的局部优化的主要算法如下:
1.设置一张常量表consdef(空),其元素是二元组(Var,Val),Var是变量名或常量名,Val是它们的值。
2.读当前文件中的四元式tuple。
3.对tuple中的分量去查常量表,若有则用其值去代换,得到新的newtuple。
4.若新的四元式newtuple是(w,A,B,T)情形,若A,B都是常量,则计算AwB的值V,并在consdef表中填入(T,V),同时删除本四元式,即不把此四元式写入输出文件中,否则将新的四元式输入输出文件中。
5.若newtuple是(Assign,A,B)情形,若A是常量,则把(B,A)填入consdef表,(若有B项,则只需改值),若A是变量,但consdef中有B则删除此项。
6.重复上述步骤,直到输入文件结束。
三、实验代码:
structconsdef
{charvar;
intval;}
voidmain()
{FILE*cfptr;
FILE*cfpt;
charstring[100][100];
char*w;
charr[10];
charstring1='\n';
structconsdefvaltable[100];
for(i=0;i<10;i++)
{valtable[i].val=0;
valtable[i].var='';
} //初始化consdef
if((cfptr=fopen("wsq.txt","r+"))==NULL)
printf("Filecouldnotbeopened\n");
else
while(!
feof(cfptr))
{fscanf(cfptr,"%s",string[i]);
}//读取文件中的内容并将其存入到数组中
fclose(cfptr);
for(i=0;i {while(string[i][m]! =',') {w[m-1]=string[i][m]; }//取tuple的逗号前的3字符串并将其存入到w中 for(into=m-1;o<10;o++) if(! strcmp(w,"assig ")&&isdigit(string[i][m]-'\0')&&! (isdigit(string[i][m+2]))) {valtable[e].val=string[i][m]; valtable[e].var=string[i][m+2]; } //若该tuple是赋值语句且第一个是数字第二个是变量 if(! (isdigit(string[i][m]-'\0')))//若第一个是变量则查consdef表 { for(intp=0;p if(valtable[p].var==string[i][m])//若consdef中有该变量,则改变tuple为newtuple并设置标志v {string[i][m]=valtable[p].val; } if(v) {if(isdigit(string[i][m]-'\0')&&isdigit(string[i][m+2]-'\0')) { if(! strcmp(w,"addi "))//若该语句是加运算 {valtable[e].var=string[i][m+4]; string[i][m+4]=string[i][m]+string[i][m+2]-48; valtable[e].val=string[i][m+4]; e++; string[i][0]='#'; } if(! strcmp(w,"subi ")) //若该语句是减运算 {valtable[e].var=string[i][m+4]; string[i][m+4]=string[i][m]-string[i][m+2]+48; valtable[e].val=string[i][m+4]; string[i][0]='#'; } if(! strcmp(w,"divi ")) //若该语句是除运算 {valtable[e].var=string[i][m+4]; string[i][m+4]=(string[i][m]-48)/(string[i][m+2]-48)+48; valtable[e].val=string[i][m+4]; string[i][0]='#'; } } if(! strcmp(w,"assig ")&&isdigit(string[i][m]-'\0')) {valtable[e].val=string[i][m]; valtable[e].var=string[i][m+2]; } } } if((cfptr=fopen("wsq1.txt","w"))==NULL)//将优化后的tuple存入文件wsq1.txt中 printf("Filecouldnotbeopened\n"); else for(i=0;i { if(string[i][0]! ='#') { fprintf(cfptr,"%s",string[i]); fprintf(cfptr,"%c",string1); } } } 华东理工大学信息学院计算机系 2010年12月16日 一. 实验序号 实验3 二. 实验题目 中间代码生成 三. 实验日期 2010.12.16-2010.12.23 四. 实验环境(操作系统,开发语言) 操作系统是Windows 开发语言是VisualC++2003语言 五. 实验内容(实验要求) (a) 在VisualC++2003中创建项目: “VisualC++项目”/“Win32”(Win32控制台项目) (b) 输入下面“六.C语言源程序”一节中的C语言语句。 (c) 点击菜单“调试”/“逐语句”(F11)。 (d) 点击菜单“调试”/“窗口”/“反汇编”,观察C语言语句相应的汇编代码并仔细阅读分析和理解所有的汇编代码。 (e) 填写下面“七.汇编代码” 一节中的空白,并在右边的注释处写出你填空的依据(注意: “七.汇编代码”中的地址也许与你的计算机中观察到的地址有些偏差,请根据“七.汇编代码”中显示的代码的地址进行填写和说明)。 六. C语言源程序 int_tmain(intargc,_TCHAR*argv[]) { int nWeigh,nMiles,nLong,nDiscount,Price[10],i,nFee; nWeigh=10; nMiles=5; nLong=0; if(nMiles>10) nLong=1; if(nLong==1&&nWeigh>50) nDiscount=4; else if(nLong==1&&nWeigh>40) nDiscount=3; else if(nLong==1&&nWeigh>30) nDiscount=2; else nDiscount=1; for(i=0;i<10;i++) Price[i]=i*20; i=0; nFee=0; while(i { nFee=nFee+Price[i]; i++; } switch(nDiscount) { case1: nFee=nFee+100; break; case2: nFee=nFee+80; break; case3: nFee=nFee+40; case4: nFee=nFee+10; break; default: nFee=200; } return0; } 七. 汇编代码 00411A10 push ebp 00411A11 mov ebp,esp 00411A13 sub esp,13Ch 00411A19 push ebx 00411A1A push esi 00411A1B push edi 00411A1C lea edi,[ebp-13Ch] 00411A22 mov ecx,4Fh 00411A27 mov eax,0CCCCCCCCh 00411A2C repstos dwordptr[edi] 00411A2E mov dwordptr[nWeigh],0Ah 00411A35 mov dwordptr[nMiles],5 00411A3C mov dwordptr[nLong],0 00411A43 cmp dwordptr[nMiles],0Ah 00411A47 jle main+40h(411A50)// 如果小于等于的话就跳到下一个if语句 00411A49 mov dwordptr[nLong],1 00411A50 cmp dwordptr[nLong],1 00411A54 jne main+55h(411A65h)//如果nLong不等于1就直接跳到下一个if语句 00411A56 cmp dwordptr[nWeigh],32h 00411A5A jle main+55h(411A65h) 00411A5C mov dwordptr[nDiscount],4 00411A63 jmp main+86h(411A96h)// 直接跳到for循环 00411A65 cmp dwordptr[nLong],1 00411A69 jne main+6Ah(411A7Ah) 00411A6B cmp dwordptr[nWeigh],28h 00411A6F jle main+6Ah(411A7Ah) 00411A71 mov dwordptr[nDiscount],3 00411A78 jmp main+86h(411A96h) // 直接跳到for循环 00411A7A cmp dwordptr[nLong],1 00411A7E jne main+7Fh(411A8Fh) // 如果nLong不等于1,就给nDiscount赋值1 00411A80 cmp dwordptr[nWeigh],1Eh 00411A84 jle main+7Fh(411A8Fh) // 如果nWeigh小于等于30,就给nDiscount赋值为1 00411A86 mov dwordptr[nDiscount],2 00411A8D jmp main+86h(411A96h) 00411A8F mov dwordptr[nDiscount],1 00411A96 mov dwordptr[i],0 00411A9D jmp main+98h(411AA8h)//直接跳到i与10比较的语句 00411A9F mov eax,dwordptr[i] 00411AA2 add eax,1 00411AA5 mov dwordptr[i],eax
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译原理 语法分析 编译 原理