广东工业大学pl0课程设计.docx
- 文档编号:29251878
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:32
- 大小:477.66KB
广东工业大学pl0课程设计.docx
《广东工业大学pl0课程设计.docx》由会员分享,可在线阅读,更多相关《广东工业大学pl0课程设计.docx(32页珍藏版)》请在冰豆网上搜索。
广东工业大学pl0课程设计
课程设计
课程名称___编译原理________
题目名称__编译原理课程设计___
学生学院__计算机学院_________
专业班级_08级计科3班_
学号___3208006558__________
学生姓名____刘恰恰___________
指导教师_______张巍____________
2011年1月6日
一、设计要求
基本内容
(1)扩充赋值运算:
+=和-=
(2)扩充语句(Pascal的FOR语句):
①FOR<变量>:
=<表达式>TO<表达式>DO<语句>
②FOR<变量>:
=<表达式>DOWNTO<表达式>DO<语句>
其中,语句①的循环变量的步长为2,
语句②的循环变量的步长为-2。
选做内容
(1)增加运算:
++和--。
(2)增加类型:
①字符类型;②实数类型。
(3)扩充函数:
①有返回值和返回语句;②有参数函数。
(4)增加一维数组类型(可增加指令)。
(5)其他典型语言设施。
二、概述:
源、目标语言,实现工具(平台),运行平台
1.源语言:
PL/0语言
2.目标语言:
类PCODE
3.实现工具:
C++Builder
4.运行平台:
windowsxp
三、结构设计说明:
各功能模块描述
1、voidError(intn):
错误处理,打印出错位置和错误编码
2、voidGetCh():
漏掉空格,读取一个字符
3、voidGetSym():
词法分析,读取一个单词
4、voidGEN(FCTX,intY,intZ):
生成目标代码,并送入目标程序区
5、voidTEST(SYMSETS1,SYMSETS2,intN):
测试当前单词符号是否合法
6、voidENTER(OBJECTSK,intLEV,int&TX,int&DX):
登录名字表
7、intPOSITION(ALFAID,intTX):
查找标识符在名字表中的位置
8、voidConstDeclaration(intLEV,int&TX,int&DX):
常量说明处理
9、voidVarDeclaration(intLEV,int&TX,int&DX):
变量说明处理
10、voidCharDeclaration(intLEV,int&TX,int&DX):
字符说明处理
11、voidRealDeclaration(intLEV,int&TX,int&DX):
实数说明处理
12、voidListCode(intCX0):
列出目标代码清单
13、voidFACTOR(SYMSETFSYS,intLEV,int&TX):
因子处理
14、voidTERM(SYMSETFSYS,intLEV,int&TX):
项处理
15、voidEXPRESSION(SYMSETFSYS,intLEV,int&TX):
表达式处理
16、voidCONDITION(SYMSETFSYS,intLEV,int&TX):
条件处理
17、voidSTATEMENT(SYMSETFSYS,intLEV,int&TX):
语句部分处理
18、voidBlock(intLEV,intTX,SYMSETFSYS):
分程序分析处理过程
19、intBASE(intL,intB,intS[]):
通过静态链求出数据区的基地址
20、voidInterpret():
对目标代码的解释执行程序
21、void__fastcallTForm1:
:
ButtonRunClick(TObject*Sender):
进行编译,RUN
四、主要成分描述
1、符号表
struct{
ALFANAME;
OBJECTSKIND;
union{
intVAL;/*CONSTANT*/
struct{intLEVEL,ADR,SIZE;}vp;/*VARIABLE,PROCEDUR:
*/
};
}TABLE[TXMAX];
在编译程序中符号表用来存放语言程序中出现的有关标识符的属性信息,这些信息集中反映了标识符的语义特征属性.符号表的主要功能如下:
1、收集符号属性
2、上下文语义合法性检查的依据
3、作为目标代码生成阶段地址分配的依据.
2、运行时存储组织和管理
当源程序经过语法分析,如果未发现错误时,由编译程序调用解释程序,对存放在CODE中的代码CODE[0]开始进行解释执行.当废弃结束后,记录源程序中标识符的TABLE表已没有作用.因此存储区只需以数组CODE存储的只读目标程序和运行机制时的数据区S,S是由解释程序定义的一维整数型数组.解释执行时的数据空间S为栈式计算机的在座空间,遵循后进先出规则,对每个过程(包括主程序)当调用时,才分配数据空间,退出过程进,则所分配原则的数据空间被释放.
解释程序还定义了4个寄存器:
1、指令寄存器.存放当前正在解释的一条目标指令2、程序地址寄存器.指向下一条要执行的目标程序的地址3、栈顶寄存器.4、基址寄存器.指向每个过程被调用时,在数据区S中给它分配原则的数据段起始地址,也称基地址.
3、语法分析方法
语法分析的任务是识别由词法分析给出的单词符号序列在结构上是否符合给定的文法规则.PL/0编译程序的语法分析采用了自顶向下的递归子程序法.粗略地说:
就是对应每个非终结符语法单元,编一个独立的处理过程(或子程序).语法分析研究从读入第一个单词开始由非终结符程序即开始符出发,沿语法描述图箭头所指出的方向进行分析.当遇到非终结符时,则调用相应的处理过程,从语法描述图看也就进入了一个语法单元,再沿当前所进入的语法描述图的箭头方向进行分析,当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,则执行相应的语义程序(就是翻译程序).再读取下一个单词继续分析.遇到分支点时将当前的单词与分支点上的多个终结符逐个相比较,若都不匹配时可能是进入下一非终结符语法单位或是出错.
如果一个PL/0语言程序的单词序列在整修语法分析中,都能逐个得到匹配,直到程序结束’.’,这时就说所输入的程序是正确的.对于正确的语法分析做相应的语义翻译,最终得出目标程序.
4、中间代码表示
中间代码表示格式如下:
f
L
a
其中f代表功能码,l表示层次差,也就是变量或过程被引用的分程序与说明该变量或过程的分程序之间的层次差.a的含意对不同的指令有所区别,见下面对每条指令解释说明.
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从命令行读入一个输入置于栈顶
五、测试用例
1、测试文件名:
E0101.plo
测试对象:
+=、-=、++、--
测试结果:
2、测试文件名:
E0102.plo
测试对象:
for,char和real
测试结果:
3、测试文件名:
E0103.plo
测试对象:
一维数组
测试结果:
六、开发过程和完成情况
1)开发过程
(在课内实验基础上继续操作:
)
(1)扩充赋值运算:
+=和-=,增加运算:
++和--。
首先增加保留字PLUSBK(+=)、MINUSBK(-=)、INC(++)、DEC(--)到相应的位置、并增加相应的代码,用于词法分析的识别。
具体扩充到typedefenum和char*SYMOUT[]和GetSym函数中。
具体添加的代码如下:
voidGetSym(){//词法分析,获取一个符号
······
//以下是增加+=,-=,++,--部分
else
if(CH=='+')
{GetCh();
if(CH=='='){SYM=PLUSBK;GetCh();}
elseif(CH=='+'){SYM=INC;GetCh();}
elseSYM=PLUS;
}
else
if(CH=='-')
{GetCh();
if(CH=='='){SYM=MINUSBK;GetCh();}
elseif(CH=='-'){SYM=DEC;GetCh();}
elseSYM=MINUS;
}
······
}/*GetSym()*/
voidFACTOR(SYMSETFSYS,intLEV,int&TX){//因子处理
inti,j;
TEST(FACBEGSYS,FSYS,24);
while(SymIn(SYM,FACBEGSYS)){
if(SYM==IDENT)
{
······
if(SYM==INC)
{
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==DEC)
{
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==INC)
{
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==DEC)
{
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();
}
TEST(FSYS,FACBEGSYS,23);
}
}/*FACTOR*/
voidSTATEMENT(SYMSETFSYS,intLEV,int&TX){//语句处理
inti,j,j1,j2,CX1,CX2,STE,STE1,tag=0;
switch(SYM){
caseIDENT:
······
if(TABLE[i].KIND==VARIABLE)
{GetSym();
if(SYM==BECOMES)
······
elseif(SYM==PLUSBK)
{GetSym();
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
EXPRESSION(FSYS,LEV,TX);
GEN(OPR,0,2);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
}
elseif(SYM==MINUSBK)
{GetSym();
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
EXPRESSION(FSYS,LEV,TX);
GEN(OPR,0,3);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
}
elseif(SYM==INC)
{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==DEC)
{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();
}
······
}
elseError(13);
break;
······
caseINC:
//++
GetSym();
i=POSITION(ID,TX);
if(i==0)Error(11);
else
if(TABLE[i].KIND!
=VARIABLE)
{/*ASSIGNMENTTONON-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;
//--
caseDEC:
GetSym();
i=POSITION(ID,TX);
if(i==0)Error(11);
else
if(TABLE[i].KIND!
=VARIABLE)
{/*ASSIGNMENTTONON-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;
······
}/*STATEMENT*/
++和--可以增加到运算表达式中对单个数值进行运算或直接跟在数值变量标识符,而+=和-=只能跟在变量标识符的后面。
(2)扩充语句(Pascal的FOR语句):
①FOR<变量>:
=<表达式>TO<表达式>DO<语句>
②FOR<变量>:
=<表达式>DOWNTO<表达式>DO<语句>
其中,语句①的循环变量的步长为2,
语句②的循环变量的步长为-2。
voidSTATEMENT(SYMSETFSYS,intLEV,int&TX){//语句处理
······
switch(SYM){
······
caseFORSYM:
//for语句处理
GetSym();
if(SYM!
=IDENT)Error(8);
i=POSITION(ID,TX);
if(i==0)Error(11);
else
if(TABLE[i].KIND!
=VARIABLE){
Error(12);i=0;
}
GetSym();
if(SYM==BECOMES)
{
GetSym();
EXPRESSION(SymSetUnion(SymSetNew(TOSYM,DOSYM,DOWNTOSYM),FSYS),LEV,TX);
if(i!
=0)GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
TABLE[i].VAL=NUM;
}
elseError(13);
if(SYM==TOSYM)
{GetSym();
EXPRESSION(SymSetUnion(SymSetNew(TOSYM,DOSYM),
FSYS),LEV,TX);
if(SYM==DOSYM)GetSym();
elseError(18);
CX1=CX;
GEN(OPR,0,17);
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(OPR,0,11);
CX2=CX;
GEN(JPC,0,0);
STATEMENT(FSYS,LEV,TX);
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,2);
GEN(OPR,0,2);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
TABLE[i].VAL=TABLE[i].VAL+1;
GEN(JMP,0,CX1);
CODE[CX2].A=CX;
}
if(SYM==DOWNTOSYM)
{GetSym();
EXPRESSION(SymSetUnion(SymSetNew(DOWNTOSYM,DOSYM),
FSYS),LEV,TX);
if(SYM==DOSYM)GetSym();
elseError(18);
CX1=CX;
GEN(OPR,0,17);
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(OPR,0,13);
CX2=CX;
GEN(JPC,0,0);
STATEMENT(FSYS,LEV,TX);
GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
GEN(LIT,0,2);
GEN(OPR,0,3);
GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);
TABLE[i].VAL=NUM;
GEN(JMP,0,CX1);
CODE[CX2].A=CX;
}
break;
}
TEST(FSYS,SymSetNULL(),19);
}/*STATEMENT*/
(2)增加类型:
①字符类型;②实数类型
首先词法分析中加入小数和字符的识别;然后在符号表中加入类型属性项;第三步在定义常量、变量、参变量、数组、函数的过程中,加入类型的声明过程。
REALCON表示实型,CHARCON表示字符型;第四步,在运算过程中对每个运算操作进行类型匹配的检查。
字符型不允许加入到运算表达式中,整型类型的赋值运算和数组上下界的运算中不可以出现‘/’法运算;最后在解释执行过程中将虚拟的数据堆栈类型调整为实型,这样就无须在其他代码部分扩充。
voidGetSym(){//词法分析,获取一个符号
······
else
if(CH>='0'&&CH<='9'){/*NUMBER*///小数部分的识别
K=0;NUM=0;SYM=NUMBER;floatcount=0.1;
do{
if(CH=='.')
{GetCh();
SYM=REALS;
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);
}
else
if((int)CH==39)//加入字符类型
{GetCh();
if((CH>='A'&&CH<='Z')||(CH>='a'&&CH<='z'))
{NUM=(int)CH;
GetCh();
if((int)CH==39)SYM=CHARS;
else{NUM=0;SYM=NUL;Error(39);}//类型错误
}
elseError(39);//类型不匹配
GetCh();
}
······
}/*GetSym()*/
voidENT
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 广东工业大学 pl0 课程设计