编译原理分析中间代码生成程序Word下载.docx
《编译原理分析中间代码生成程序Word下载.docx》由会员分享,可在线阅读,更多相关《编译原理分析中间代码生成程序Word下载.docx(11页珍藏版)》请在冰豆网上搜索。
在描述这个过程中,要说清楚每个功能有哪个子程序的哪条语句来完成,说清楚语句和参数的含义和功能。
四、实验结果及分析
(一)程序标注
levmax=3;
{maxdepthofblocknesting}{最大允许的块嵌套层数}
{语法分析过程block}
{参数:
lev:
这一次语法分析所在的层次}
{tx:
符号表指针}
{fsys:
用于出错恢复的单词集合}
procedureblock(lev,tx:
integer;
fsys:
symset);
var
dx:
{dataallocationindex}{数据段内存分配指针,指向下一个被分配空间在数据段中的偏移位置}
tx0:
{initialtableindex}{记录本层开始时符号表位置}
cx0:
{initialcodeindex}{记录本层开始时代码段分配位置}
{登陆符号表过程enter}
procedureenter(k:
object1);
begin{enterobjectintotable}{参数:
k:
欲登陆到符号表的符号类型}
tx:
=tx+1;
{符号表指针指向一个新的空位}
withtable[tx]do{开始登录}
begin
name:
=id;
{name是符号的名字,对于标识符,这里就是标识符的名字}
kind:
=k;
{符号类型,可能是常量、变量或过程名}
casekof{根据不同的类型进行不同的操作}
constant:
{如果是常量名}
ifnum>
amaxthen{在常量的数值大于允许的最大值的情况下}
error(31);
{抛出31号错误}
num:
=0;
{实际登陆的数字以0代替}
end;
val:
=num{如是合法的数值,就登陆到符号表}
variable:
{如果是变量名}
level:
=lev;
{记下它所属的层次号}
adr:
=dx;
{记下它在当前层中的偏移量}
dx:
=dx+1;
{偏移量自增一,为下一次做好准备}
procedur:
{如果要登陆的是过程名}
=lev{记录下这个过程所在层次}
End
End
end{enter};
{登录符号过程没有考虑到重复的定义的问题。
如果出现重复定义,则以最后一次的定义为准。
}
{在符号表中查找指定符号所在位置的函数position}
{参数:
id:
要找的符号}
{返回值:
要找的符号在符号表中的位置,如果找不到就返回0}
functionposition(id:
alfa):
var
i:
begin{findidentifierintable}
table[0].name:
{先把id放入符号表0号位置}
i:
=tx;
{从符号表中当前位置也即最后一个符号开始找}
whiletable[i].name<
>
iddo{如果当前的符号与要找的不一致}
=i–1;
{找前面一个}
position:
=i{返回找到的位置号,如果没找到则一定正好为0}
end{position};
(二)过程说明
说明入口参数,返回值和过程的功能
1、入口参数:
过程体入口时的处理
code[table[tx0].adr].a:
=cx;
(cx为过程入口地址,填写在code中)
withtable[tx0]do
begin
adr:
(过程的入口填写在table表的过程名中)
size:
=dx;
(过程需要的空间填写在table中)
end;
cxo:
(保留过程在code中的入口地址在输出目标代码时用)
gen(int,0,dx);
(生成过程入口指令)
2、返回值:
(*通过静态链求出数据区基地址的函数base*)
(*参数说明:
l:
要求的数据区所在层与当前层的层差*)
(*返回值:
要求的数据区基址*)
functionbase(l:
integer):
var
b1:
b1:
=b;
(*findbase1leveldown*)(*首先从当前层开始*)
whilel>
0do(*如果l大于0,循环通过静态链往前找需要的数据区基址*)
=s[b1];
(*用当前层数据区基址中的内容(正好是静态链SL数据,为上一层的基址)的作为新的当前层,即向上找了一层*)
l:
=l-1(*向上了一层,l减一*)
base:
=b1(*把找到的要求的数据区基址返回*)
end(*base*);
(三)程序静态结构图
(四)PL0文法描述
在计算机科学中,文法是编译原理的基础,是描述一门程序设计语言和实现其编译器的方法。
文法的描述多用BNF(巴克斯范式),而另一个重要的概念:
正则表达式,也是文法的另一种形式。
PL/0文法的表示:
<
程序>
:
=<
分程序>
.
=[<
常量说明部分>
][<
变量说明部分>
过程说明部分>
]<
语句>
=const<
常量定义>
{,<
};
标识符>
=<
无符号整数>
数字>
{<
}
字母>
|<
=var<
{,<
过程首部>
{;
=procedure<
;
:
赋值语句>
条件语句>
当循环语句>
过程调用语句>
复合语句>
读语句>
写语句>
空>
表达式>
=[+|-]<
项>
加法运算符>
因子>
乘法运算符>
|‘(’<
‘)’
=+|-
=*|/
条件>
关系运算符>
|odd<
==|<
=|>
|>
=
=if<
then<
=while<
do<
=call<
=begin<
}end
=read‘(’<
}‘)’
=write‘(’<
=a|b|c|d…..x|y|z
=0|1|2|3…...8|9
(五)代码生成程序说明
对分程序体人口的处理(见程序文本block的过程体)
begin(*block*)
dx:
=3;
tx0:
=tx;
(*保留当前table表指针值,实际为过程名在table表中的位置*)
table[tx].adr:
(*保留当前code指针值到过程名的adr域*)
gen(jmp,0,0);
(*生成转向过程体入口的指令,该指令的地址为cx已保留在过程名的adr域,真正的过程体入口地址,等生成过程体入口的指令时,再由table[tx].adr中取出cx将过程体入口返填到cx所指目标代码,即:
(jmp,0,0)的第3区域,同时填到table[tx].adr中*)
②过程体入口时的处理
table表格管理
(六)代码生成程序实例
给出pl0源程序,中间代码和过程说明
编写代码:
programabc(input,output);
begin
=10;
writeln(i);
end.
运行程序如图:
五、实验总结
这次实验加深了我对编译过程的理解,无论是整体还是细节都有了更深入的体会,强化了基础知识的进一步学习,如活动记录、符号表、中间过程生成等。
这次实验让我更深的认识到只是学习课本是远远不够的,我们还需要从实际的操作中体会所学知识。
这次实验让我更好的理解了词法分析语法分析过程的区别。
同时,这次实验我也存在着很多的不足,比如我不能完全靠自己的能力理解PL0程序的全部内容,自身知识的不足督促我们通过书籍、网络等途径完善对于知识的认知,扩展自身知识面,提升自身能力,让我们能更好的利用计算机以及编译原理这门课程的知识。
教师评价
评定项目
A
B
C
D
算法正确
流程图正确
语句语法格式正确
源程序正确
中间代码正确
分析过程正确
报告规范
回答问题正确
实验结果正确
题解正确
其他:
评价教师签名:
年月日