广东工业大学10级编译原理课程设计报告.docx
- 文档编号:24847136
- 上传时间:2023-06-02
- 格式:DOCX
- 页数:27
- 大小:341.23KB
广东工业大学10级编译原理课程设计报告.docx
《广东工业大学10级编译原理课程设计报告.docx》由会员分享,可在线阅读,更多相关《广东工业大学10级编译原理课程设计报告.docx(27页珍藏版)》请在冰豆网上搜索。
广东工业大学10级编译原理课程设计报告
广东工业大学10级编译原理课程设计报告
《编译原理》
课程设计
实验时间:
实验班级:
姓名:
焦王
学号:
实验教师:
计算机学院
广东工业大学
一、基本内容
(1)扩充赋值运算:
*=和/=
(2)扩充语句(Pascal的FOR语句):
①FOR<变量>:
=<表达式>TO<表达式>DO<语句>
②FOR<变量>:
=<表达式>DOWNTO<表达式>DO<语句>
其中,语句①的循环变量的步长为2,
语句②的循环变量的步长为-2。
(3)增加运算:
++和--。
(4)选做内容(成绩评定范围扩大到:
“优”和“良”)
(1)增加类型:
①字符类型;②实数类型。
(2)扩充函数:
①有返回值和返回语句;②有参数函数。
(3)增加一维数组类型(可增加指令)。
(4)其他典型语言设施。
二、实验环境与工具
(1)计算机及操作系统:
PC机,Windows7,WindowsXP
(2)程序设计语言:
C++Builder5,VC6.0
(3)教学型编译程序:
PL/0
三、设计方案
(1)概述:
源、目标语言,实现工具(平台),运行平台
源语言:
PL/0语言
目标语言:
类PCODE
实现工具:
C++Builder
运行平台:
windows7
(2)结构设计说明--各功能模块描述
1、intPOSITION(ALFAID,intTX):
查找标识符在名字表中的位置
2、intBASE(intL,intB,intS[]):
通过静态链求出数据区的基地址
3、voidError(intn):
错误处理,打印出错位置和错误编码
4、voidGetCh():
漏掉空格,读取一个字符
5、voidGetSym():
词法分析,读取一个单词
6、voidGEN(FCTX,intY,intZ):
生成目标代码,并送入目标程序区
7、voidTEST(SYMSETS1,SYMSETS2,intN):
测试当前单词符号是否合法
8、voidENTER(OBJECTSK,intLEV,int&TX,int&DX):
登录名字表
9、voidConstDeclaration(intLEV,int&TX,int&DX):
常量说明处理
10、voidVarDeclaration(intLEV,int&TX,int&DX):
变量说明处理
11、voidCharDeclaration(intLEV,int&TX,int&DX):
字符说明处理
12、voidRealDeclaration(intLEV,int&TX,int&DX):
实数说明处理
13、voidListCode(intCX0):
列出目标代码清单
14、voidFACTOR(SYMSETFSYS,intLEV,int&TX):
因子处理
15、voidTERM(SYMSETFSYS,intLEV,int&TX):
项处理
16、voidEXPRESSION(SYMSETFSYS,intLEV,int&TX):
表达式处理
17、voidCONDITION(SYMSETFSYS,intLEV,int&TX):
条件处理
18、voidSTATEMENT(SYMSETFSYS,intLEV,int&TX):
语句部分处理
19、voidBlock(intLEV,intTX,SYMSETFSYS):
分程序分析处理过程
20、voidInterpret():
对目标代码的解释执行程序
21、void__fastcallTForm1:
:
ButtonRunClick(TObject*Sender):
进行编译,RUN
(3)主要成分描述
①符号表
符号表的主要功能如下:
1、收集符号属性
2、上下文语义合法性检查的依据
3、作为目标代码生成阶段地址分配的依据
②运行时存储组织和管理
解释程序定义了4个寄存器:
1、指令寄存器.存放当前正在解释的一条目标指令2、程序地址寄存器.指向下一条要执行的目标程序的地址3、栈顶寄存器.4、基址寄存器.指向每个过程被调用时,在数据区S中给它分配原则的数据段起始地址,也称基地址.
当源程序经过语法分析,如果未发现错误时,由编译程序调用解释程序,对存放在CODE中的代码CODE[0]开始进行解释执行.当废弃结束后,记录源程序中标识符的TABLE表已没有作用.因此存储区只需以数组CODE存储的只读目标程序和运行机制时的数据区S,S是由解释程序定义的一维整数型数组.解释执行时的数据空间S为栈式计算机的在座空间,遵循后进先出规则,对每个过程(包括主程序)当调用时,才分配数据空间,退出过程进,则所分配原则的数据空间被释放.
③语法分析方法
语法分析研究从读入第一个单词开始由非终结符程序即开始符出发,沿语法描述图箭头所指出的方向进行分析.当遇到非终结符时,则调用相应的处理过程,从语法描述图看也就进入了一个语法单元,再沿当前所进入的语法描述图的箭头方向进行分析,当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,则执行相应的语义程序(就是翻译程序).再读取下一个单词继续分析.遇到分支点时将当前的单词与分支点上的多个终结符逐个相比较,若都不匹配时可能是进入下一非终结符语法单位或是出错.
如果一个PL/0语言程序的单词序列在整修语法分析中,都能逐个得到匹配,直到程序结束’.’,这时就说所输入的程序是正确的.对于正确的语法分析做相应的语义翻译,最终得出目标程序.
④中间代码表示
中间代码表示格式如下:
fLa
其中f代表功能码,l表示层次差,也就是变量或过程被引用的分程序与说明该变量或过程的分程序之间的层次差.a的含意对不同的指令有所区别,见下面对每条指令解释说明.
LIT0A将常数值取到栈顶,A为常数值
LODLA将变量值取到栈顶,A为偏移量,L为层差
STOLA将栈顶内容送入某一变量单元中,A为偏移量,L为层差
CALLA调用过程,A为过程地址,L为层差
INT0A在运行栈中为被调用的过程开辟A个单元的数据区
JMP0A无条件跳转到A地址
JPC0A条件跳转,当栈顶布尔值非真则跳转到A地址,否则顺序执行
OPR00过程调用结束后,返回调用点并退栈
OPR01栈顶元素取反
OPR02次栈顶与栈顶相加,退两个栈元素,结果值进栈
OPR03次栈顶减去栈顶,退两个栈元素,结果值进栈
OPR04次栈顶乘以栈顶,退两个栈元素,结果值进栈
OPR05次栈顶除以栈顶,退两个栈元素,结果值进栈
OPR06栈顶元素的奇偶判断,结果值在栈顶
OPR07
OPR08次栈顶与栈顶是否相等,退两上栈元素,结果值进栈
OPR09次栈顶与栈顶是否不等,退两个栈元素,结果值进栈
OPR010次栈顶是否小于栈顶,退两个栈元素,结果值进栈
OPR011次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈
OPR012次栈顶是否大于栈顶,退两个栈元素,结果值进栈
OPR013次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈
OPR014栈顶值输出到屏幕
OPR015屏幕输出换行
OPR016从命令行读入一个输入置于栈顶
(4)测试用例
①测试文件名:
E01.plo
测试对象:
*=、/=、++、--、FOR、TO、DOWNTO
E01的具体测试代码:
PROGRAMEX01;
VARA,B,C,Y;
BEGIN
A:
=9;B:
=10;
A++;WRITE(A);
B--;WRITE(B);
A/=3;WRITE(A);
B*=2;WRITE(B);
C:
=A+B*(A-3);WRITE(C);
FORY:
=1TO5DOWRITE(Y);
FORY:
=5DOWNTO1DOWRITE(Y);
END.
测试结果:
②测试文件名:
E0101.plo
测试对象:
CHAR和REAL
②测试文件名:
E010101.plo
测试对象:
数组
四、开发过程和完成情况
1)开发过程:
先往typedefenumchar*SYMOUT[]加入:
TEQL,SEQL,DPLUS,DMINUS,ELSESYM,FORSYM,TOSYM,DOWNTOSYM,RETURNSYM,CHARSYM,REALSYM,
LEFTS,RIGHTS,MIDD
①++(DPLUS)——(DMINUS)*=(TEQL)/=(SEQL)
先往voidGetSym()添加识别
else
if(CH=='+')
{GetCh();
if(CH=='+'){SYM=DPLUS;GetCh();}
elseSYM=PLUS;}
else
if(CH=='-')
{GetCh();
if(CH=='-'){SYM=DMINUS;GetCh();}
elseSYM=MINUS;}
else
if(CH=='*')
{GetCh();
if(CH=='='){SYM=TEQL;GetCh();}
elseSYM=TIMES;}
else
if(CH=='/')
{GetCh();
if(CH=='='){SYM=SEQL;GetCh();}
elseSYM=SLASH;}
再往voidFACTOR(SYMSETFSYS,intLEV,int&TX)
添加因子处理
if(SYM==DPLUS)
{GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,1);
GEN(OPR,0,2);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GetSym();
}
if(SYM==DMINUS)
{GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,1);
GEN(OPR,0,3);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GetSym();
}
else
if(SYM==DPLUS)
{GetSym();
i=POSITION(ID,TX);
if(i==0)Error(11);
else
if(TABLE[i].KIND!
=VARIABLE)
{Error(12);i=0;}
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,1);
GEN(OPR,0,2);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GetSym();
}
else
if(SYM==DMINUS)
{GetSym();
i=POSITION(ID,TX);
if(i==0)Error(11);
else
if(TABLE[i].KIND!
=VARIABLE)
{Error(12);i=0;}
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,1);
GEN(OPR,0,3);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GetSym();
}
最后往voidSTATEMENT(SYMSETFSYS,intLEV,int&TX)
添加
elseif(SYM==TEQL)
{GetSym();
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
EXPRESSION(FSYS,LEV,TX);
GEN(OPR,0,4);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
}
elseif(SYM==SEQL)
{GetSym();
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
EXPRESSION(FSYS,LEV,TX);
GEN(OPR,0,5);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
}
elseif(SYM==DPLUS)
{GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,1);
GEN(OPR,0,2);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
//TABLE[i].VAL=NUM;
GetSym();
}
elseif(SYM==DMINUS)
{GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,1);
GEN(OPR,0,3);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
//TABLE[i].VAL=NUM;
GetSym();
}
caseDPLUS:
//++
GetSym();
i=POSITION(ID,TX);
if(i==0)Error(11);
else
if(TABLE[i].KIND!
=VARIABLE)
{
Error(12);i=0;
}
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,1);
GEN(OPR,0,2);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
//TABLE[i].VAL=NUM;
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GetSym();
break;
caseDMINUS:
//--
GetSym();
i=POSITION(ID,TX);
if(i==0)Error(11);
else
if(TABLE[i].KIND!
=VARIABLE)
{
Error(12);i=0;
}
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,1);
GEN(OPR,0,3);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
//TABLE[i].VAL=NUM;
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GetSym();
break;
②扩充语句(Pascal的FOR语句):
①FOR<变量>:
=<表达式>TO<表达式>DO<语句>
②FOR<变量>:
=<表达式>DOWNTO<表达式>DO<语句>
其中,语句①的循环变量的步长为2,
语句②的循环变量的步长为-2。
直接在voidSTATEMENT(SYMSETFSYS,intLEV,int&TX)
添加
caseFORSYM:
GetSym();
if(SYM!
=IDENT)//For后跟一变量
Error(31);
i=POSITION(ID,TX);
if(i==0)
Error(11);
else
if(TABLE[i].KIND!
=VARIABLE)
{
Error(12);i=0;
}
GetSym();
if(SYM!
=BECOMES)//For后变量赋值
Error(13);
GetSym();
EXPRESSION(SymSetUnion(SymSetNew(TOSYM,DOWNTOSYM,DOSYM),FSYS),LEV,TX);//For后变量赋值为表达式
if(SYM==TOSYM){//变量赋值后跟TO关键字
CX1=CX;//记录跳转位置,对应于P192101
GetSym();
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//将TO后跟随的值放到栈顶
EXPRESSION(SymSetAdd(DOSYM,FSYS),LEV,TX);//参考WHILESYM
GEN(OPR,0,13);//判断是否小于等于,OPR查P452CASE13
CX2=CX;//记录跳转位置,对应于P192104
GEN(JPC,0,0);//当大于的时候跳出循环
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//以下三句为循环变量加1
GEN(LIT,0,2);
GEN(OPR,0,2);
if(SYM==DOSYM){//遇到DO时
GetSym();
STATEMENT(FSYS,LEV,TX);
}
GEN(JMP,0,CX1);//跳转至CX1处,对应于P192107
CODE[CX2].A=CX;//回填,大于时跳至这里
}
else
if(SYM==DOWNTOSYM)//DOWNTO的处理同TO的处理类似
{
CX1=CX;
GetSym();
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
EXPRESSION(SymSetAdd(DOSYM,FSYS),LEV,TX);
GEN(OPR,0,11);//查课本P452,判断是否大于等于
CX2=CX;
GEN(JPC,0,0);//小于时退出循环
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);//以下三句为循环变量减1
GEN(LIT,0,2);
GEN(OPR,0,3);
if(SYM==DOSYM){//DO
GetSym();
STATEMENT(FSYS,LEV,TX);
}
GEN(JMP,0,CX1);//跳转到CX1处
CODE[CX2].A=CX;//回填,小于时跳到这里
}
elseError(35);//FOR后面必须有TO或者DOWNTO
break;
③增加类型:
字符类型和实数类型:
首先在voidGetSym()修改:
elseif(CH>='0'&&CH<='9'){/*NUMBER*/
K=0;NUM=0;SYM=NUMBER;floatcount=0.1;
do{
if(CH=='.')
{GetCh();
SYM=REALSYM;
while(CH>='0'&&CH<='9')
{NUM=NUM+(CH-'0')*count;
K++;
count*=0.1;
GetCh();}break;}
else
{NUM=10*NUM+(CH-'0');
K++;
GetCh();
}
}while((CH>='0'&&CH<='9')||CH=='.');
if(K>NMAX)Error(30);
}
然后在voidENTER(OBJECTSK,intLEV,int&TX,int&DX)添加
caseCHARCON:
/*字符*/
TABLE[TX].vp.LEVEL=LEV;TABLE[TX].vp.ADR=DX;DX++;
break;
caseREALCON:
/*实数*/
TABLE[TX].vp.LEVEL=LEV;TABLE[TX].vp.ADR=DX;DX++;
break;
接着声明函数:
voidCharDeclaration(intLEV,int&TX,int&DX){//声明
if(SYM==IDENT){ENTER(CHARCON,LEV,TX,DX);GetSym();}
elseError(4);
}/*CharDeclaration()*/
//---------------------------------------------------------------------------
voidRealDeclaration(intLEV,int&TX,int&DX){//声明
if(SYM==IDENT){ENTER(REALCON,LEV,TX,DX);GetSym();}
elseError(4);
}/*RealDeclaration()*/
在voidFACTOR添加:
switch(TABLE[i].KIND){
caseCHARCON:
GetSym();GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);break;caseREALCON:
GetSym();GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);break;
}
在voidSTATEMENT(SYMSETFSYS,intLEV,int&TX)添加:
caseIDENT:
i=POSITION(ID,TX);
if(i==0)Error(11);
if(TABLE[i].KIND==CHARCON)
{GetSym();
if(SYM!
=BECOMES)Error(13);
else{
GetSym();
if(SYM!
=CHARS)Error(32);
else{
GEN(LIT,0,NUM);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABL
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 广东工业大学 10 编译 原理 课程设计 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)