中间代码生成实验报告doc.docx
- 文档编号:25743175
- 上传时间:2023-06-12
- 格式:DOCX
- 页数:12
- 大小:19.59KB
中间代码生成实验报告doc.docx
《中间代码生成实验报告doc.docx》由会员分享,可在线阅读,更多相关《中间代码生成实验报告doc.docx(12页珍藏版)》请在冰豆网上搜索。
中间代码生成实验报告doc
中间代码生成实验报告
篇一:
编译方法实验报告(中间代码生成器)
编译方法实验报告
XX年10月
一、
实验目的
熟悉算术表达式的语法分析与中间代码生成原理。
实验内容二、
(1)设计语法制导翻译生成表达式的四元式的算法;
(2)编写代码并上机调试运行通过。
输入——算术表达式;
输出——语法分析结果;
相应的四元式序列。
(3)设计LL
(1)分析法或LR(0)分析法的属性翻译文法,并根据这些属性翻译文
法,使用扩展的语法分析器实现语法制导翻译。
三、实验原理及基本步骤
●算术表达式文法:
G(E):
E?
Eω0T|T
T?
Tω1F|F
F?
i|(E)
●文法变换:
G’(E)E?
T{ω0T(本文来自:
小草范文网:
中间代码生成实验报告)}
T?
F{ω1F}
F?
i|(E)
●属性翻译文法:
E?
T{ω0“push(SYN,w)”T“QUAT”}
T?
F{ω1“push(SYN,w)”F“QUAT”}
F?
i“push(SEM,entry(w))”|(E)
其中:
push(SYN,w)—当前单词w入算符栈SYN;
push(SEM,entry(w))—当前w在符号表中的入口值压入语义栈SEM;
QUAT—生成四元式函数
i.T=newtemp;
ii.QT[j]=(SYN[k],SEM[s-1],SEM[s],T);j++;
iii.pop(SYN,_);pop(SEM,_);pop(SEM,_);
push(SEM,T);
●递归下降子程序:
数据结构:
SYN—算符栈;
SEM—语义栈;
四、数据结构设计
使用递归的结构进行四元式的设计,同时,运用堆栈结构将四元式的输出序
列打印出来
while(exp[i]=='+'||exp[i]=='-'){
syn[++i_syn]=exp[i];//push(SYN,w)
i++;//read(w)
T();
quat();}
while(exp[i]=='*'||exp[i]=='/'){
syn[++i_syn]=exp[i];//push(SYN,w)
i++;//read(w)
F();
quat();}
voidquat(){
strcpy(qt[j],"(,,,)");
//QT[j]:
=(SYN[k],SEM[s-1],SEM[s],temp);
qt[j][1]=syn[i_syn];
qt[j][3]=sem[i_sem-1];
qt[j][5]=sem[i_sem];
qt[j][7]=temp;
j++;
i_syn--;//pop(SYN);
i_sem--;//pop(SEM);
i_sem--;//pop(SEM);
sem[++i_sem]=temp;//push(SEM,temp);
temp++;}
五、关键代码分析(带注释)及运行结果
#include
#include"string.h"
#include"stdio.h"
usingnamespacestd;
charsyn[10];//文法符号栈
inti_syn;
charsem[10];//运算对象栈
inti_sem;
charexp[50];//算术表达式区
inti;
charqt[30][15];//四元式区
intj=0;
chartemp='q';//临时变量,取值为r--z
intE();
intT();
intF();
voidquat();//生成四元式函数
intmain(intargc,char*argv[]){
printf("pleaseinputyourexpression:
");
scanf("%s",exp);//输入四元式
i=0;//read(w)
E();
if(exp[i]=='\0')
for(i=0;i printf("%s\n",qt[i]);
else
printf("err");
return0;}
intE(){
T();
while(exp[i]=='+'||exp[i]=='-'){
syn[++i_syn]=exp[i];//push(SYN,w)
i++;//read(w)
T();
quat();}
return1;}
intT(){
F();
while(exp[i]=='*'||exp[i]=='/'){
syn[++i_syn]=exp[i];//push(SYN,w)
i++;//read(w)
F();
quat();}
return1;}
intF(){
if(exp[i]=='('){
i++;//read(w)
E();
if(exp[i]!
=')'){
printf("err");
return0;}
}elseif((exp[i]>='a'&&exp[i]='0'&&exp[i] sem[++i_sem]=exp[i];}//push(SEM,w)
else{
printf("err");
return0;}
i++;//read(w)
return1;}
voidquat(){
strcpy(qt[j],"(,,,)");//QT[j]:
=(SYN[k],SEM[s-1],SEM[s],temp);
qt[j][1]=syn[i_syn];
qt[j][3]=sem[i_sem-1];
qt[j][5]=sem[i_sem];
qt[j][7]=temp;
j++;
i_syn--;//pop(SYN);
i_sem--;//pop(SEM);
i_sem--;//pop(SEM);
sem[++i_sem]=temp;//push(SEM,temp);
temp++;}
篇二:
中间代码生成实验报告
一、实验目的
通过在实验二的基础上,增加中间代码生成部分,使程序能够
对实验二中的识别出的赋值语句,if语句和while语句进行语义分析,生成四元式中间代码。
二、实验方法
实验程序由c语言完成,在Turboc2.0环境中调试通过。
语义分析程序的基本做法是对文法中的每个产生式分别编写一个语义分析子程序,当程序语法部分进行推倒或规约时,就分别调用各自的语义分析程序。
当语法分析结束时,语义分析也就结束了。
在本实验程序中,当语法分析部分识别出语法正确的句子时,就进入content函数(当语法分析识别出不正确的句子时,不进入content函数,也就是不进行语义分析),然后根据句子的类型进行分类,进入不同的语义处理部分。
对于赋值语句,关键是产生正确的处理算术表达式E的四元式。
程序中的ec函数的功能就是产生算术表达式的四元式,在ec函数中使用了两个栈idshed,opshed,分别是算术表达式的数据栈和符号栈。
每次提取一个数字和一个算符,然后将算符与与栈顶算符进行优先级比较,优先级高则将单前数字和算符进栈,低或者相等的话则将当前栈顶元素进行合并,产生四元式。
直至整个算术表达式结束。
其中还有一些细节问题,具体的做法可以参看程序。
对于实验给定的if语句的文法格式,条件判断式C只中可能是>或者 通过ec函数可以产生条件判断式C中的E的四元式,然后只要加
上转向四元式就可以了。
本实验程序中只给出真出口的转向四元式,没有给出假出口的转向四元式,这在实际中是不可以的,但在本实验中,实际上是对每条独立的语句进行语法分析,给出假出口转向四元式实际上意义不大,而且假出口转向语句的转移目标必须要到整个语句分析结束以后才可以知道,这样就要建立栈,然后回填,这样会使程序复杂很多,所以没有加上假出口转向四元式。
对于while语句,具体的做法和if语句差不多,所不同的是当while语句结束时,要多出一条无条件转向四元式,重新转到条件判断式C的第一条四元式。
当要产生无条件转向四元式时,它的转向目标C的第一条四元式已经产生了,所以具体的做起来是不太困难的。
只要记下当前while中的C的第一条四元式的位置,填上就可以了。
整个程序的结束是当读入“.”时,程序就中止。
程序中还有很多细节问题,具体的可以后面的附录:
程序的完整代码。
三、测试程序
ff:
=6+6*6-;
ifsl>89+56*67
thenf:
=7*7+4;
ff:
=6+6*6-6%4+8;
ifsl+78*76>89*56+67
thenwhilea-7>98+45*45dof:
=7*7+4;
.
四、运行结果
首先对测试程序进行语法分析,识别出正确的句子,当识别
出正确的句子时,就对当前句子进行语义分析,而语法不正确的句子不进行语义分析。
ff:
=6+6*6-Error(4):
ExceptIDorNUM
;Error
(2):
Syntaxerror
ifsl>89+56*67thenf:
=7*7+4;success!
!
!
(1)[*,56,67,T1]
(2)[+,89,T1,T2]
(3)[j>,sl,T2,(4)]
(4)[*,7,7,T3]
(5)[+,T3,4,T4]
(6)[:
=,T4,-,f]
ff:
=6+6*6-6%4+8;success!
!
!
(7)[*,6,6,T5]
(8)[+,6,T5,T6]
(9)[%,6,4,T7]
(10)[-,T6,T7,T8]
(11)[+,T8,8,T9]
(12)[:
=,T9,-,ff]
ifsl+78*76>89*56+67thenwhilea-7>98+45*45dof:
=7*7+4;success!
!
!
(13)[*,78,76,T10]
(14)[+,sl,T10,T11]
(15)[*,89,56,T12]
(16)[+,T12,67,T13]
(17)[j>,T11,T13,(18)]
(18)[-,a,7,T14]
(19)[*,45,45,T15]
(20)[+,98,T15,T16]
(21)[j>,T14,T16,(22)]
(22)[*,7,7,T17]
(23)[+,T17,4,T18]
(24)[:
=,T18,-,f]
(25)[j,_,_,(18)]
.Error
(2):
Syntaxerror
五、实验小结
终于完成了编译原理的三次实验,这几次实验使我们更彻底地巩固了编译原理。
从詷法分析到语法分析直到这次的中间代码都是看似简单的基础知识,却花了不少时间对课本多次反复研究、请教学习,进行深层次地探讨才找出编程时出现的种种问题。
还有很多程序方面很细节的问题,很容易被突略,却往往又是关键。
总地来说,虽然实验做得很辛苦,但真的可以从实验当中学习到很多,认识到很多。
并对编译理解也透彻了许多,比较清晰地掌握了编译程序的原理和方法。
附录:
#include
#include
#include
#definereser20
char*charstring="abcdefghijklmnopqrstuvwxyz";
char*numstring="09";
char*strstring="abcdefghijklmnopqrstuvwxyz09";
charreserve[reser][10];
charidshed[40][10],opshed[40][10];
chartoken[15],id[15],sym[15];
charline[80],tempp[240];
charch,ch1,temp,tem;
chartx[10];
chartn[4],signt1[20],signt2[20],ju[20];
intcc,ii,k,num,kind,t,e4=0,e3=0,judge=1,row1=0;
intstartc,idsh=0,opsh=0,tt=1,nn=1,signwh,over=0,adds=0,whs=0,pp=0;intli=0;
charfilename[15];
FILE*fp;
voidgetch(){
if(li==0){
if(cc==ii){
cc=1;ii=0;
if(row1==1)fseek(fp,-1,1);/*读行首字符将指针退回一格,若是整个文本的开头,则不需要*/
line[0]=fgetc(fp);
row1=1;
while(((temp=fgetc(fp))!
='\n')&&(temp!
=EOF))
{line[cc]=temp;
cc++;
tempp[pp]=temp;
pp++;
}
line[cc]='';/*将缓冲带后加上一个空字符,以便行和行之间号区分*/cc++;
tempp[pp]='';
pp++;
while(((temp=fgetc(fp))=='\n')&&(temp!
=EOF));/*跳过空行*/line[cc]='\0';
}
tem=line[ii];
ii++;
ch=tem;
}
else{
ch=tempp[pp];
pp++;
}
}
voidgetnbc(){
getch();
while(ch=='')
getch();
if(ch=='{')
{
do
{getch();}
while(ch=='}');
getnbc();
}
}
voidretract(){
ii--;
}
voidret(){
pp--;
}
intjchar(charch){/*判断ch是不是字母*/
篇三:
编译原理实验中间代码生成
实验四中间代码生成
一.实验目的:
掌握中间代码的四种形式(逆波兰式、语法树、三元式、四元式)。
二.实验内容:
1、逆波兰式定义:
将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表
达式也称做后缀式。
2、抽象(语法)树:
运算对象作为叶子结点,运算符作为内部结点。
3、三元式:
形式序号:
(op,arg1,arg2)
4、四元式:
形式(op,arg1,arg2,result)
三、以逆波兰式为例的实验设计思想及算法
(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:
将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。
(5)重复上述操作
(1)-
(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
四、程序代码:
//这是一个由中缀式生成后缀式的程序
#include
#include
#include
#include
#definemaxbuffer64
voidmain()
{
chardisplay_out(charout_ch[maxbuffer],charch[32]);
//intcaculate_array(charout_ch[32]);
staticinti=0;
staticintj=0;
charch[maxbuffer],s[maxbuffer],out[maxbuffer];
cout cin>>ch;
for(i=0;i {out[i]=ch[i];}
cout while(out[j]!
='#')
{
cout j++;
}
cout display_out(s,out);
//caculate_array;
}
chardisplay_out(charout_ch[32],charch[])
{
inttop=-1;
inti=0,data[maxbuffer],n;
intj=0;
charsta[20];
while(ch[i]!
='#')
{
if(isalnum(ch[i]))
{
while(isalnum(ch[i]))
{
out_ch[j]=ch[i];
j++;
i++;
}out_ch[j]='';j++;
}
else{
switch(ch[i])
{
case'+':
case'-':
if(sta[top]=='('||top==-1)
{
top++;
sta[top]=ch[i];
i++;
}
else
{
//j--;
out_ch[j]=sta[top];
j++;
top--;
//i++;
}
break;
//break;
case'*':
case'/':
if(sta[top]=='*'&&sta[top]=='/')
{
out_ch[j]=sta[top];
j++;
//i++;
top--;
}
else
{
top++;
sta[top]=ch[i];
i++;
}
break;
//break;
case'(':
top++;
sta[top]=ch[i];
i++;
break;
case')':
if(sta[top]=='(')
{
top--;
i++;
}
if(top==-1)
{
//cout }
else
{
//while(sta[top]!
=?
(?
){
out_ch[j]=sta[top];
top--;
j++;
//}break;
}
break;
/*case?
#?
:
out_ch[j]=?
#?
;
j++;
break;*/
default:
cout ch[i]='#';
j=0;
break;
}
}
}while(top!
=-1)
{
out_ch[j]=sta[top];j++;
top--;
}
out_ch[j]='#';
n=0;
cout while(out_ch[n]!
='#')
{
cout n++;
}
cout j=0;
returnout_ch[maxbuffer];
}
五、实验结果:
要求:
自己给出3个测试用例,观察结果。
如下例。
图表1
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 中间 代码 生成 实验 报告 doc