广工编译原理课程设计及实验报告Word文档下载推荐.docx
《广工编译原理课程设计及实验报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《广工编译原理课程设计及实验报告Word文档下载推荐.docx(40页珍藏版)》请在冰豆网上搜索。
if条件then语句[else语句]
1.课程设计
基本内容(成绩范围:
“中”、“及格”或“不及格”)
(1)扩充赋值运算:
*=和/=
语句->
ident*=表达式
ident/=表达式
扩充语句(Pascal的FOR语句):
①FOR<
变量>
:
=<
表达式>
TO<
DO<
语句>
②FOR<
DOWNTO<
其中,语句①的循环变量的步长为2,
语句②的循环变量的步长为-2。
(3)增加运算:
++和--。
选做内容(成绩评定范围扩大到:
“优”和“良”)
(1)增加类型:
①字符类型;
②实数类型。
(2)扩充函数:
①有返回值和返回语句;
②有参数函数。
(3)增加一维数组类型(可增加指令)。
(4)其他典型语言设施。
二、实验环境及工具
源语言:
PL0
目标语言:
假想栈式计算机的汇编语言(C语言实现)
实现工具:
codeblock
运行平台:
Windows10
三、结构设计说明
(1)PL/0语言编译程序结构
PL/0语言可看成是PASCAL语言的子集,它的编译程序是一个编译解释执行系统。
PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关。
PL/0源程序
词法分析程序
语法语义分析程序
代码生成程序
表格管理程序
出错处理程序
目标程序
PL/0编译程序的结构图
(2)PL/0语言编译程序总体流程
以下是编译程序的总体流程图,其中,PL/0编译程序的语法分析过程BLOCK是整个编译过程的核心,我们通过该流程图来弄清BLOCK过程在整个编译程序中的作用。
PL/0的编译程序采用一趟扫描方式,以语法分析程序为核心,词法分析程序和代码生成程序都作为一个独立的过程,当语法分析需要读单词时就用词法分析程序,而当语法分析正确需生成相应的目标代码时,则调用代码生成程序。
此外,用表格管理程序建立变量,常量和过程标识符的说明与引用之间的信息联系。
用出错处理程序对词法和语法分析遇到的错误给出在源程序中出错的位置和错误性质。
(3)各功能模块描述
过程或函数名
简要功能说明
pl0
主程序
error
出错处理,打印出错位置和错误编码
getsym
词法分析,读取一个单词
getch
漏掉空格,读取一个字符
gen
生成目标代码,并送入目标程序区
test
测试当前单词符号是否合法
block
分程序分析处理过程
enter
登录名字表
position(函数)
查找标识符在名字表中的位置
constdeclaration
常量定义处理
vardeclaration
变量说明处理
listode
列出目标代码清单
statement
语句处理
expression
表达式处理
term
项处理
factor
因子处理
condition
条件处理
interpret
对目标代码的解释执行程序
base(函数)
通过静态链求出数据区的基地址
四、主要成分描述
①符号表
在PL0中,使用以下数据结构存储符号表:
structtablestruct
{
charname[al];
/*名字*/
enumobjectkind;
/*类型:
const,var,arrayorprocedure*/
intval;
/*数值,仅const使用*/
intlevel;
/*所处层,仅const不使用*/
intadr;
/*地址,仅const不使用*/
intsize;
/*需要分配的数据区空间,仅procedure使用*/
};
structtablestructtable[txmax];
/*名字表*/
他是一个全程量一维数组TABLE。
表中每个元素为记录型数据。
如果标识符被说明为常数,其属性值为常数值;
如果标识符被说明成变量,其属性就是由层次和修正量(偏移量)组成的地址;
如果标识符被说明为过程,其属性就是过程的入口地址及层次。
常数的值由程序正文提供,编译的任务就是确定存放该值的地址。
我们选择顺序分配变量和代码的方法;
每遇到一个变量说明,就将数据单元的下标加一(PL/0机中,每个变量占一个存贮单元)。
开始编译一个过程时,要对数据单元的下标dx赋初值,表示新开辟一个数据区。
dx的初值为3,因为每个数据区包含三个内部变量RA,DL和SL。
②运行时存储组织和管理
当源程序经过语法分析,如果没有发现错误,由编译程序调用解释程序,对存放在CODE中的目标代码从CODE[0]开始解释执行。
存放目标代码的数据结构:
structinstruction
enumfctf;
/*虚拟机代码指令*/
intl;
/*引用层与声明层层次差*/
inta;
/*根据f的不同而不同*/
structinstructioncode[cxmax];
/*存放虚拟机代码的数组*/
当编译结束之后,记录源程序中标识符的TABLE表已经没用了,因此存储区只需要以数组CODE存放的只读目标程序和运行时的数据区S。
S是由解释程序定义的一维整型数组。
代码如下:
intp,b,t;
/*指令指针,指令基址,栈顶指针*/
structinstructioni;
/*存放当前指令*/
ints[stacksize];
/*栈*/
其中,有四个寄存器。
分别为I指令寄存器,P程序地址寄存器,T栈顶寄存器,B基址寄存器。
对于源程序的每一个过程(包括主程序),在被调用时,首先在数据段中开辟三个空间,存放静态链SL、动态链DL和返回地址RA。
1.静态链记录了定义该过程的直接外过程(或主程序)运行时最新数据段的基地址。
2.动态链记录调用该过程前正在运行的过程的数据段基址。
3.返回地址记录了调用该过程时程序运行的断点位置。
对于主程序来说,SL、DL和RA的值均置为0。
静态链的功能是在一个子过程要引用它的直接或间接父过程(这里的父过程是按定义过程时的嵌套情况来定的,而不是按执行时的调用顺序定的)的变量时,可以通过静态链,跳过个数为层差的数据段,找到包含要引用的变量所在的数据段基址,然后通过偏移地址访问它。
③语法分析方法
PL/0编译程序的语法分析采用了自顶向下的递归子程序法。
语法分析从读入第一个单词开始由开始符『程序』出发,沿语法描述图箭头所指方向进行分析。
当遇到非终结符时,则调用相对应的处理过程,从语法描述图也就进入了一个语法单元,再沿当前所进入的语法描述图的箭头方向进行分析,当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,则执行对应的语义程序(翻译程序)。
再读入下一个单词继续分析。
遇到分支点时将当前的单词与分支点上的多个终结符逐个比较,若都不匹配时可能是进入下一非终结符语法单位或是出错。
如果一个PL0语言程序的单词序列在整个语法分析中,都能逐个得到匹配,直到程序结束符『·
』,这时说明所输入的程序是正确的。
对于正确的语法分析进行对应的语义翻译,生成目标代码。
语法分析主要由分程序分析过程(BLOCK)常量定义分析过程(ConstDeclaration)、变量定义分析过程(Vardeclaration)、字符变量定义分析过程(Chardeclaration)、语句分析过程(Statement)、表达式处理过程(Expression)、项处理过程(Term)、因子处理过程(Factor)和条件处理过程(Condition)构成。
这些过程在结构上构成一个嵌套的层次结构。
④中间代码表示
中间代码是是源程序的一种内部表示,复杂性介于源语言和目标机语言之间。
中间代码的表示方法有逆波兰式、三元式、树形、四元式等。
(1) 逆波兰记号是最简单的一种中间代码表示形式,早在编译程序出现之前,它就用于表示算术表达式。
后缀表示法表示表达式,其最大的优点是易于栈式计算机处理表达式。
(2)每个三元式由三个部分组成:
算符op
第一运算对象ARG1
第二运算对象ARG2
运算对象可能是源程序中的变量,也可能是某个三元式的结果,用三元式的编号表示。
(3)树形表示是三元式表示的翻版。
(4)四元式是一种比较普遍采用的中间代码形式:
运算对象ARG1
运算对象ARG2
运算结果RESULT
五、开发过程和完成情况
1.1修改symbol枚举
enumsymbo
l{
nul,ident,number,plus,minus,
times,slash,oddsym,eql,neq,
lss,leq,gtr,geq,lparen,
rparen,comma,semicolon,period,becomes,
beginsym,endsym,ifsym,thensym,whilesym,
writesym,readsym,dosym,callsym,constsym,
varsym,procsym,elsesym,forsym,tosym,downtosym,returnsym,
muleqsym,deviesym,pplus,mminus,andsym,logical_or,logical_not,charsym,charvalue,
writecharsym,readcharsym
1.2修改getSym(),增加以下语句
intgetsym()
//乘等识别
elseif(ch=='
*'
)
{
getchdo;
if(ch=='
='
{
sym=muleqsym;
getchdo;
}
else
sym=nul;
}
.....