编译原理pl语言实验.docx
- 文档编号:23079398
- 上传时间:2023-04-30
- 格式:DOCX
- 页数:14
- 大小:696.52KB
编译原理pl语言实验.docx
《编译原理pl语言实验.docx》由会员分享,可在线阅读,更多相关《编译原理pl语言实验.docx(14页珍藏版)》请在冰豆网上搜索。
编译原理pl语言实验
编译原理
课程实践报告书
学员姓名:
张冠宇
学号:
201306042020
专业:
软件工程
年级:
2013
2015年12月25日
1、课程实践目的
通过读懂源程序,全面掌握编译原理的基本实现过程。
对PL编译程序进行扩充,通过扩充加深对编译程序的理解。
2、任务概述
首先对PL编译程序进行学习,了解其中各功能模块之间的调用关系。
在阅读和理解PL编译程序之后,根据教学要求和条件对PL语言及编译程序进行扩充。
在这个实验里,我扩充了3条语句:
for语句、repeat语句、case语句,增加了复制运算+=,-=,
3、实现方法
上面的两张流程图分别是pl编译程序的总体流程图和模块功能之间的调用关系,是完成三个statement的必须知识。
在程序中出现了非常多的过程、函数定义,在这里列出PL编译程序的过程或函数的功能表:
过程或函数名
简要功能说明
pl0
主程序
error
出错处理,打印出错位置和错误编码
getsym
词法分析,读取一个单词
getch
漏掉空格,读取一个字符
gen
生成目标代码,并送入目标程序区
test
测试当前单词符号是否合法
block
分程序分析处理过程
enter
登录名字表
position(函数)
查找标识符在名字表中的位置
constdeclaration
常量定义处理
vardeclaration
变量说明处理
listode
列出目标代码清单
statement
语句处理
expression
表达式处理
term
项处理
factor
因子处理
condition
条件处理
interpret
对目标代码的解释执行程序
base(函数)
通过静态链求出数据区的基地址
一、Repeat
Repeat语句:
S->REPEATS1UNTILE
Repeat的程序结构为:
Repeat的结构和while的结构比较相似,我是从这一个开始添加的。
如果遇到了repeat语句就转入repeatstatement,在这里:
1通过getsym()读入一个词语,在这里功能是从源程序中读出一个单词符号(token),把它的信息放入全局变量sym、id和num中。
2记下当前代码分配位置,记做cx1,这是repeat循环的开始位置,跳转需要用到。
3使用statement函数分析repeat后的语句块,分析的同时生成相应的指令。
4分析语句块遇到until符号,此时应当获取逻辑表达式,然后使用expression函数进行分析计算,expression函数第一个参数是follow集,当分析计算读取到follow集中的元素时结束,将表达式的类型存入x中,并生成该表达式的相关代码。
5当栈顶值为零时进行跳转,跳转位置为cx1,即repeat开始的位置。
二、For
FOR语句:
FOR->FORID:
=E1TOE2DOS1
基本思路:
语句的基本实现思想是依次读取,首先计算E1的值然后赋给ID,计算S2的值作为终结值。
循环时用变量的值和终结值进行比对,决定是不是回到循环之中。
每次循环都执行S1.
实现方法:
1通过getsym(),获取赋值号左边的标识符id,使用assignment函数对其进行分析。
从符号表nametab中找到它的地址信息adrr,并确认这个标识符就是变量名。
2当getsym读取到to时进行判断,如果有tosym时,就继续getsym()进行继续分析,如果不是tosym的话,说明出现语法错误。
3通过simpleexpression函数对do语句进行分析,simpleexpression的第一个参数是follow集,当读取到follow集中的元素时结束,并将表达式的类型存入x中,并生成该表达式的相关代码使用。
cx1记录下当前位置cx。
执行到这里时,do之前的部分大致完成。
4由于id是有范围的,需要对范围进行限定,首先通过lod,level,adrr指令将adrr赋给level,也就是更新了层次,level大于addr时重复操作,这里要用cx2记录当前的cx位置,这是把本循环体结束的下一个位置保存到cx2生成跳转,并在循环结束时用cx2更新为目前循环结束跳转地址。
5当getsym读取到do时进行判断,如果有dosym时,就继续getsym()进行继续分析,并用statement分析do后面的表达式,如果不是tosym的话,说明出现语法错误。
6最后要进行回填过程,为下一次循环的地址赋值。
三、Case
CASE语句:
:
=
{<常量>:
<语句>}otherwise
例如:
Casea:
1:
s1
2:
s2
Otherwise:
sotend
1第一阶段,case和ident,在这一阶段要用casenum记下case含有的情况个数,要保存ident在nametab表中的level与adr值,供后面生成变量与常量比较指令用。
并进行判断,判断case后是否为ident,判断ident地址是否为零也就是是否找到了标识符,判断ident的类型是否为变量。
2第二阶段,读冒号,不是冒号就报错。
3第三阶段,在这里是一个常量,不是常量就报错,要判断常量和变量的值进行匹配。
4第四阶段,对于冒号与冒号后语句这个小循环的处理,在这里生成后面语句的代码之前,生成jpc利用变量和常量比较所得结果进行跳转,若为假,则跳到本循环体结束的地方。
这里要记录一下cx的值,cx就是跳转到下一个case的位置,便于回填。
这种情况下就是case语句判断失败跳转到其他case的情况。
5第五阶段对于语句的处理,也就是变量与常量的匹配为真时处理的情况,也就是case命中,处理后生成无条件跳转指令跳转到case语句结束,由于地址未知,要等先把各个循环体中的无条件跳转指令的地址放到gotolist数组中,待case结束后再回填跳转地址。
6第六阶段是对otherwise的处理,之前写的是一个初始化过程,这里要进行循环来将所有的case进行那个处理。
7最后,回填本循环体头的条件跳转地址。
回填case结束后跳出的指令。
四、+=和-=运算
语句:
赋值语句:
:
=<标识符>[+=|-=]<表达式>
例如:
s+=a;
S-=a;
思路(以+=为例):
五、a++和a—和++a和--a运算
语句:
赋值语句:
:
=<标识符>[+=|-=]<表达式>
例如:
a++;
++a;
思路(以++为例):
4、实验的例程
Repeat语句:
测试语句:
Interrupt结果:
Case语句:
测试语句:
Interrupt结果:
For语句:
测试语句:
Interrupt结果:
+=、-=样例:
Interrupt结果:
++、--样例:
Interrupt结果:
Error样例:
代码:
Pl分析:
Interrepet分析:
0programmain;
0consta=10,c=1,d=2;
****^23
Errorinfo:
应是“;”
****^13
Errorinfo:
本符号在此出现是非法的
****^23
Errorinfo:
应是“;”
****^13
Errorinfo:
本符号在此出现是非法的
1varb,i,k;
****^24
Errorinfo:
应是“:
”
****^10
Errorinfo:
标识符无定义
1begin
2callread(k;
****^43
Errorinfo:
操作数类型错
****^25
Errorinfo:
未知错误
3b:
=0;
****^40
Errorinfo:
类型不一致
5fori:
=0tokdo
9begin
11b:
=b+i;
****^0
Errorinfo:
非法字符
****^43
Errorinfo:
操作数类型错
13i:
=i+1
****^0
Errorinfo:
非法字符
15end;
****^40
Errorinfo:
类型不一致
27callwrite(b);
****^43
Errorinfo:
操作数类型错
27end.
****^13
Errorinfo:
本符号在此出现是非法的
5、总结
实验充分说明自己在之前的学习中基础很不扎实,在刚开始进行实验时一筹莫展,经过在微信群中的讨论以及其他同学的帮助,还是将第一个问题,也就是添加三条语句实现了出来。
这个实验有一定难度,但在写完repeat语句后掌握了方法就快得多了。
在实验中,给我留下最深刻印象,也是花费时间最多的部分有各种条件下的跳转(尤其是循环体跳转)、缺少跳转地址时进行回填操作、进行变量和常量的比较等部分。
事实证明做实验确实是掌握记住知识的有效途径,如果在当时上课时就能够边学边做,相信就会对课程内容有更深的了解了。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 pl 语言 实验
![提示](https://static.bdocx.com/images/bang_tan.gif)