编译原理课程设计.docx
- 文档编号:14432847
- 上传时间:2023-06-23
- 格式:DOCX
- 页数:19
- 大小:461.05KB
编译原理课程设计.docx
《编译原理课程设计.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计.docx(19页珍藏版)》请在冰点文库上搜索。
编译原理课程设计
一、概述:
源语言:
源程序是PL0语言编写的程序,PL0语言可以看成是Pascal语言的子集。
目标语言:
目标语言是一个假想栈式计算机的汇编语言,与具体的计算机无关。
实现工具(平台):
BorlandC++Builder6.0
运行平台:
Windows7旗舰版
二、结构设计说明
编译程序概述
PL/0的编译过程采用一趟扫描方式,以语法语义分析程序为核心,词法分析程序和代码生成程序都作为一个独立的过程,当语法分析需要读入单词时就调用词法分析程序,而当语法分析正确需生成相应的目标代码时,则调用代码生成程序。
此外,用表格管理程序建立变量、常量和过程标识符的说明与引用之间的信息联系。
用出错处理程序对词法和语法分析遇到的错误给出在源程序中出错的位置和错误性质。
当源程序编译正确时,PL/0编译程序自动调用解释执行程序,对目标代码进行解释执行,并按用户程序的要求输入数据和输出运行结果。
其编译和解释执行的结构图如下所示:
各功能模块描述
1.词法分析
PL0词法分析程序GETSYM是一个独立个过程,为语法语义分析提供单词。
1.1可以从三个方面理解词法分析程序:
读入,中间处理,输出。
1.1.1读入:
调用GetCh()函数,由全局变量CH返回一个字符给GETSYM程序。
具体实现是GetCh()函数从源程序读取一行字符存放在LINE数组,每次将LINE数组的一个元素赋值给CH,由CH返回,直到LINE数组读取完毕,重复读取一行字符。
1.1.2中间处理:
识别保留字,识别标识符,识别数字并拼数,拼复合词。
保留字、标识符以字母开头,中间可以有数字,但不可以有下划线,用户定义的标识符出现下划线会使程序出现死循环。
1.1.3输出:
实际上就是将中间处理过程识别的单词类别存放在全局的SYM中,用户定义的标识符,常数,类别存放在SYM中,值存放在ID或NUM中。
词法分析结束后,由调用程序对存放在全局变量中的信息进行操作。
2.语法语义分析
PL/0编译程序的语法分析采用了自顶向下的递归的子程序法。
对应于每个非终结符语法单元,编写一个独立的处理过程。
2.1非终结符具体是:
CONST,VAR,PROGRAM。
2.2编译程序主程序在满足SYM==PROGSYM时调用BLOCK开始经行语法语义分析
2.3当前非终结符是CONST或VAR时,只要是通过调用常量或变量声明处理函数,对声明语句经行处理。
2.4当前非终结符是PROGRAM时,需要在TABLE表中登记过程名,递归调用BLOCK,此时参数LEV=LEV+1;
3.语法错误处理
PL/0编译程序对语法错误的处理采用两种办法:
3.1对于一些易于校正的错误,如丢了逗号、分号等,指出出错的位置,加以校正,继续进行分析。
3.2对于难于校正的错误,给出错误的位置与性质,跳过后面一些单词,直到读入一个能使编译程序进行正常语法分析的单词。
4.目标代码解释执行
4.1源程序中没有出现错误时,才调用解释程序,解释执行存放在CODE中的目标代码。
4.2解释执行时的数据空间实际上就是一个遵循后进先出规则的一维数组,即所说的栈式计算机存储空间。
4.3在实现上,指令寄存器(I)实际上是一个INSTRUCTION类型变量,程序地址寄存器(P)、栈顶寄存器(T)、基址寄存器(B)实际上就是几个整形变量。
P标识目标程序CODE的当前下标,T标识运行时数据空间S数组的下标。
4.4除了OPR0,0外,其他OPR指令都是栈顶元素自身的一些算术操作或栈顶元素和次栈顶元素的算术或关系运算,运算后改变栈顶指针,保存结果在栈顶。
4.5LOD指令在实现上实际是将S数组指定下标的元素存放在T下标指定的位置(也就是栈顶)
4.6STO指令在实现上实际是将S数组T下标指定的元素(栈顶元素)存放在S数组指定的另一个位置上
三、主要成分描述
1.符号表
符号表是全程一维数组TABLE.TABLE是一个结构体数组,每个数组元素(即一个结构体变量)记录着变量或者过程名的相关信息。
记录的信息包括变量或过程的名字、类别、常量的值、变量或过程的地址和所在层次、过程需要分配的空间。
在语法分析程序中,调用相应的子程序,将变量,常量,过程名存放在全局变量SYM,ID,LEV,TX,DX登记到符号表。
语义分析过程,调用POSITION函数返回要查找标识符在表中的下标,若返回的下标为0说明标识符未定义,若不为0,则可以经行类型检查等意义分析操作。
2.运行时存储组织和管理
对于PL0编译程序,运行时存储区中只需以数组CODE存放只读目标程序和运行时的数据区S。
CODE数组是一个结构体数组,数组元素是INSTRUCTION类型变量。
格式如下:
解释程序定义一个一维整型数组S作为运行栈,栈顶寄存器T,基址寄存器B,程序地址寄存器P,指令寄存器I。
在每个过程调用时在栈顶分配3个联系单元。
存放的内容分别是:
1.SL静态链:
指向定义该过程的直接外过程(或主程序)运行时最新数据段的基地址。
2.DL动态链:
指向调用该过程前正在运行过程的数据段基地址。
3.RA返回地址:
记录调用该过程时目标程序的断点,即调用过程指令的下一条指令的地址。
动态链和返回地址的作用是当一个过程运行结束后,为了恢复调用该过程前的执行状态而设置的。
4.语法分析方法
PL/0编译程序的语法分析采用了自顶向下的递归的子程序法。
对应于每个非终结符语法单元,编写一个独立的处理过程。
5.中间代码表示
1、LIT0A将常数值取到栈顶,A为常数值
2、LODLA将变量值取到栈顶,A为偏移量,L为层差
3、STOLA将栈顶内容送入某一变量单元中,A为偏移量,L为层差
4、CALLA调用过程,A为过程地址,L为层差
5、INT0A在运行栈中为被调用的过程开辟A个单元的数据区
6、JMP0A无条件跳转到A地址
7、JPC0A条件跳转,当栈顶布尔值非真则跳转到A地址,否则顺序执行
8、OPR00过程调用结束后,返回调用点并退栈
9、OPR01栈顶元素取反
10、OPR02次栈顶与栈顶相加,退两个栈元素,结果值进栈
11、OPR03次栈顶减去栈顶,退两个栈元素,结果值进栈
12、OPR04次栈顶乘以栈顶,退两个栈元素,结果值进栈
13、OPR05次栈顶除以栈顶,退两个栈元素,结果值进栈
14、OPR06栈顶元素的奇偶判断,结果值在栈顶
15、OPR07
16、OPR08次栈顶与栈顶是否相等,退两上栈元素,结果值进栈
17、OPR09次栈顶与栈顶是否不等,退两个栈元素,结果值进栈
18、OPR010次栈顶是否小于栈顶,退两个栈元素,结果值进栈
19、OPR011次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈
20、OPR012次栈顶是否大于栈顶,退两个栈元素,结果值进栈
21、OPR013次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈
22、OPR014栈顶值输出到屏幕
23、OPR015屏幕输出换行
24、OPR016从命令行读入一个输入置于栈顶
四、测试用例
测试文件名:
E01.PL0
测试对象:
扩充赋值运算:
+=和-=
测试程序:
运行结果如下:
测试文件名:
E02.PL0
测试对象:
扩充语句(Pascal的FOR语句)
测试程序:
运行结果如下:
测试文件名:
E03.PL0
测试对象:
增加类型:
①字符类型;②实数类型。
测试程序:
运行结果如下:
测试文件名:
E04.PL0
测试对象:
增加一维数组类型
测试程序:
运行结果如下:
测试文件名:
E05.PL0
测试对象:
增加运算:
++和--
测试程序:
运行结果:
、
五、开发过程和完成情况
开发过程:
(1)扩充赋值运算:
+=,-=,++,--的实现
增加单词ADDEQUAL,SUBEQUAL,INC,DEC;为二维保留字数组KWORD,一维数组WSYM添加数组元素,并更改顺序.
修改词法分析程序,实现对增加单词的识别:
修改语句处理函数,实现对-=,+=语句的语法语义分析:
修改语句处理函数,实现对形如A==;A--;语句的语法语义分析:
修改语句处理函数,增加caseINC分支选项,实现对++A;类型句型的识别
修改语句处理函数,增加caseDEC分支选项,实现对--A;类型句型的识别
修改因子处理函数,处理形如:
A=A++;A=A--;句型
修改因子处理函数,处理形如:
A=++A;A=--A;句型
为处理A=++A类型句型,还需要修改因子开始的符号集合
(2)扩充语句FOR<变量>:
=<表达式>STEP<表达式>UNTIL<表达式>DO<语句>
的实现
增加单词FORSYM,STEPSYM,UNTILSYM,为二维保留字数组KWORD,一维数组WSYM添加数组元素,并更改顺序.增加了句型,扩展表示语句开始的符号集合。
由于增加了相应的保留字,词法分析程序可以识别出,关键是在语句处理函数中,添加for语句的处理部分。
()
(3)增加类型:
①字符类型;②实数类型的实现
增加表示数据类型的枚举类型TYPE,在字母表中添加TYPE类型变量,用于记录变量的数据类型。
在词法分析中加入小数和字符的识别。
修改了变量声明处理语句,修改了enter函数,实现不同类型变量在符号表中的信息记录。
为了能表示浮点数,目标指令的A域的类型要由int类型改为float类型,在程序中所有对A域的操作到要强制类型转换为int类型才能正确执行。
为了存储浮点数,运行时栈的类型也要由int类型转化为float类型,为了保证运算正常,也要做相应的类型转化。
为了输出不同类型的数据,修改了write函数,查符号表根据要输出变量的类型,选择不同的输出指令.增加了两条指令用于输出不同类型的数据。
PL0编译程序本身设计时只考虑了基本整形类型,里面所有的数据结构的设计都只是考虑了基本整形,在此基础添加浮点型数据,可能会出现很大误差。
增加TYPE类型枚举量:
修改字母表结构:
修改指令的A域:
修改词法分析程序,识别字符数据:
修改词法分析程序,识别浮点数据:
修改变量声明处理语句。
记录下当前标识符名字,再获取类型,根据不同的类型,通过不同的参数进行登录符号表。
修改enter函数,登录符号表的标识符名字不再由全局变量ID传递,而是调用函数传递过来的ALFA类型参数id,标识符类型也由参数传递进来。
修改输出函数,根据输出数据的类型,选择合适的输出指令:
修改运行时栈的类型:
类型转换:
等等
(4)增加一维数组类型的实现
按照pascal的语法规则,实现了数组的声明处理。
对于数组的操作还没实现。
增加了ARRAYSYM,OFSYM关键字。
增加了用于数组声明的函数处理,同时修改了enter函数(贴图如上)。
在变量声明函数处理中,当前SYM==ARRAYSYM时,调用数组声明处理函数。
数组声明处理函数:
完成情况:
基本内容
(1)扩充赋值运算:
+=和-=
(2)扩充语句(Pascal的FOR语句):
FOR<变量>:
=<表达式>STEP<表达式>UNTIL<表达式>DO<语句>
(3)增加运算:
++和--。
选做内容
(1)增加类型:
①字符类型;②实数类型。
(2)增加一维数组类型。
(只实现了声明处理)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 课程设计