编译原理课程设计报告.docx
- 文档编号:3328125
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:16
- 大小:121.40KB
编译原理课程设计报告.docx
《编译原理课程设计报告.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计报告.docx(16页珍藏版)》请在冰豆网上搜索。
编译原理课程设计报告
燕山大学
编译原理课程设计报告
PL0的扩充
学院信息学院
年级专业
学生姓名
学号
指导教师
设计日期2014年12月29日—
2015年1月2日
一、课设目的及要求
目的:
扩充PL/0编译程序功能,
要求:
(1)阅读、研究PL/0编译程序源文件。
(2)在上述工作基础上,可有选择地补充、完善其中词法分析、语法分析、语义分析、目标代码生成、目标代码解释执行等部分的功能。
如以语法分析部分为例,则可以增加处理更多语法成分的功能,如可处理一维数组、++、--、+=、-=、*=、/=、%(取余)、!
(取反)、repeat、for、else、开方、处理注释、错误提示、标示符或变量中可以有下划线等。
(3)设计编制典型的运行实例,以便能反应出自己所作的改进。
二、完成的实验内容
基本内容
(1)扩充赋值运算:
+=、—=、*=、/=、++、——-
(2)扩充语句if-then-else语句
三、实验环境与工具
(1)计算机及操作系统:
PC机,WindowsXP
(2)程序设计语言:
C++Builder5,VC6.0
(3)教学型编译程序:
PL/0
(4)编译和运行环境:
1VisualC++6.0,VisualC++.NETandVisualC++.NET2003
WinNT,Win2000,WinXPandWin2003
2gccversion3.3.220031022(RedHatLinux3.3.2-1)
RedhatFedoracore1
Intel32platform
使用方法:
运行后输入PL/0源程序文件名
回答是否输出虚拟机代码
回答是否输出名字表
fa.tmp输出虚拟机代码
fa1.tmp输出源文件及其各行对应的首地址
fa2.tmp输出结果
fas.tmp输出名字表
四、设计方案
(1)结构设计说明:
各功能模块描述
Error()
出错处理,打印出错位置和错误号
GetCh()
漏掉空格,读取一个字符
GetSym()
词法分析,读取一个单词
GEN()
目标代码生成过程,本过程用于把生成的目标代码写入目标代码数组,供后面的解释器解释执行
TEST()
测试当前单词是否合法过程test
ENTER()
登陆符号表过程enter
POSITION()
在符号表中查找指定符号所在位置的函数position,如果找不到就返回0
VARDECLARATION()
变量声明
LISTCODE()
列出目标代码清单
FACTOR()
因子处理过程factor
TERM()
项处理过程term;
EXPRESSION()
表达式处理过程
CONDITION()
条件处理过程
STATEMENT()
语句处理过程
BLOCK()
语法分析过程
BASE()
通过静态链求出数据区基地址的函数,
INTERPRET()
对目标代码解释运行过程
(2)主要成分描述
符号表:
在编译程序中符号表用来存放语言程序中出现的有关标识符的属性信息,符号表中所登记的信息在编译的不同阶段都要用到。
在语义分析中,符号表所登记的内容将用于语义检查(如检查一个名字的使用和原先的说明是否一致)和产生中间代码。
在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。
对一个多遍扫描的编译程序,不同遍所用的符号表也往往各有不同。
因为每遍所关心的信息各有差异。
一张符号表的每一项(或称入口才包含两大栏(或称区段、字域),即名字栏(NAME),信息栏(INFORMATION)
信息栏包含许多子栏和标志位,用来记录相应名字和种种不同属性,由于查填符号表一般是通过匹配名字来寮现的,因此,名字栏也称主栏。
主栏的内容称为关键字(keyword)。
运行时存储组织和管理:
由于编译时目标程序运行的数据空间大小已经规定,所以存储组织属于静态存储。
源程序的标识符存放在TABLE表中,目标代码存放在CODE中,S是由解释程序定义的一维整型数组,是程序运行时的数据存储空间。
语法分析方法:
自顶向下的语法分析:
中间代码表示:
对PL/0编译程序的目标代码的指令格式描述如下:
f
l
a
其中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
从命令行读入一个输入置于栈顶
(3)修改部分代码
1、增加保留字:
在增加保留字的过程中,仔细阅读了初始化的程序,相应的增加addbecomes,
minbecomes,mulbecomes,divbecomes,inc,dec,即运算符+=,-=,*=,/=,++,--。
保留字增加else,按照字母顺序增加,符号记为elsesym,同时在头文件中相应的增加保留字和运算符,修改关键字NORW的个数为14个。
具体如下:
头文件中:
#definenorw14/*关键字个数*/
enumsymbol{
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,addbecomes,
minbecomes,mulbecomes,divbecomes,inc,dec,elsesym,colon
};
#definesymnum40
enumsymbolsym,sym1;/*当前的符号?
*/
代码修改部分:
/*设置单字符号,*/
ssym['+']=plus;
ssym['-']=minus;
ssym['*']=times;
ssym['/']=slash;
ssym['(']=lparen;
ssym[')']=rparen;
ssym['=']=eql;
ssym[',']=comma;
ssym['.']=period;
ssym['#']=neq;
ssym[';']=semicolon;
ssym[':
']=colon;
/*设置保留字名字,按照字母顺序,便于折半查找*/
strcpy(&(word[0][0]),"begin");
strcpy(&(word[1][0]),"call");
strcpy(&(word[2][0]),"const");
strcpy(&(word[3][0]),"do");
strcpy(&(word[4][0]),"else");
strcpy(&(word[5][0]),"end");
strcpy(&(word[6][0]),"if");
strcpy(&(word[7][0]),"odd");
strcpy(&(word[8][0]),"procedure");
strcpy(&(word[9][0]),"read");
strcpy(&(word[10][0]),"then");
strcpy(&(word[11][0]),"var");
strcpy(&(word[12][0]),"while");
strcpy(&(word[13][0]),"write");
/*设置保留字符号*/
wsym[0]=beginsym;
wsym[1]=callsym;
wsym[2]=constsym;
wsym[3]=dosym;
wsym[4]=elsesym;
wsym[5]=endsym;
wsym[6]=ifsym;
wsym[7]=oddsym;
wsym[8]=procsym;
wsym[9]=readsym;
wsym[10]=thensym;
wsym[11]=varsym;
wsym[12]=whilesym;
wsym[13]=writesym;
在intgetch()中增加
if(ch=='{')
{//分析注释
do
{
cc++;//跳过注Á释
ch=line[cc];
}while(ch!
='}');
if(ch!
='}')
error(35);//确实少”}”
ch=line[cc+1];
cc++;
}
else
cc++;//当前字符指针加1
2、在intgetsym中增加+=、-=、*=、/=、++、--
{
switch(ch){//不是字母也不是数字
case':
':
getchdo;
if(ch=='=')//:
=
{
sym=becomes;
getchdo;
}
else
{
sym=colon;//:
}
break;
case'+':
getchdo;
if(ch=='=')//+=
{
sym=addbecomes;
getchdo;
}
elseif(ch=='+')//++
{
sym=inc;
getchdo;
}
else
{
sym=plus;//+
}
break;
case'-':
getchdo;
if(ch=='=')//-=
{
sym=minbecomes;
getchdo;
}
elseif(ch=='-')//--
{
sym=dec;
getchdo;
}
else
{
sym=minus;//-
}
break;
case'*':
getchdo;
if(ch=='=')
{
sym=mulbecomes;//*=
getchdo;
}
else
{
sym=times;//*
}
break;
case'/':
getchdo;
if(ch=='=')
{
sym=divbecomes;///=
getchdo;
}
else
{
sym=slash;///
}
break;
case'<':
getchdo;
if(ch=='=')//<=
{
sym=leq;
getchdo;
}
else
{
sym=lss;//<
}
break;
case'>':
/*检测大于或大于等Ì于符号*/
getchdo;
if(ch=='=')//>=
{
sym=geq;
getchdo;
}
else
{
sym=gtr;//>
}
break;
default:
sym=ssym[ch];/*当符号不满足上述条件时,全部按照单字符号处理*/
if(sym!
=period)
{
getchdo;
}
}
}
3、增加if-then-else语句的处理:
caseifsym:
/*准备按照语句处理*/
{
getsymdo;
memcpy(nxtlev,fsys,sizeof(bool)*symnum);
nxtlev[thensym]=true;
nxtlev[dosym]=true;/*后跟符号为then或do*/
conditiondo(nxtlev,ptx,lev);/*调用条件处理(逻辑运算)函数*/
if(sym==thensym)
{
getsymdo;
}
else
{
error(16);/*缺少then*/
}
cx1=cx;/*保存当前指令地址*/
gendo(jpc,0,0);/*生成条件跳转指令,跳转地址暂写0*/
statementdo(fsys,ptx,lev);/*处理then后的语句*/
code[cx1].a=cx;/*经statement处理后,cx为then后语句执行完的位置,它正是前面未定的跳转地址*/
if(sym==elsesym){
getsymdo;
intcx2;
cx2=cx;
gendo(jmp,0,0);
statementdo(fsys,ptx,lev);
code[cx1].a++;
code[cx2].a=cx;
}
}
break;
五、测试用例:
+=、-=、*=、/=、++、--测试程序及结果
vara,b;
begin
read(a);
read(b);
b+=a;
write(b);
b-=a;
write(b);
b*=a;
write(b);
b/=a;
write(b);
++b;
write(b);
--b;
write(b);
end.
If-then-else测试程序及结果:
vara,b,c;
begin
read(a,b,c);
ifa>0thenwrite(b)elsewrite(c);
end.
六、心得体会
在开始本次编译课程设计时,要想实现对pl0的扩充,必须要先详细了解代码,加深对编译原理的了解,编译过程在整个设计过程中都是按照词法分析――语法分析――语义分析――代码生成――目标程序这个过程执行的,语法语义分析程序还包括表格管理和出错处理程序,所以设计的要点和流程相当清晰,本实验是对pl0功能的扩充,只要在必要的地方修改或者添加程序就能实现所需+=、-=、*=、/=、++、--、if-then-else功能。
通过这次的实验,我学会了很多东西。
首先,加深了对编译原理的理解。
通过课程设计对所学知识有了系统的认识,加深了印象,原理更加明朗。
通过自己动手修改程序,关键是看懂程序的意思,每一个模块的功能,然后结合实验要求,进一步对程序做修改,以达到编译功能的扩展。
在理解的基础上,我懂得了如何实现编译程序,以及实现的步骤等。
其次,通过这次实验,对C++的编译环境有了一定的了解,获得了一些新的知识。
这次实验我收获颇丰。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 课程设计 报告