广工编译原理课程设计Word文件下载.doc

上传人:wj 文档编号:6955832 上传时间:2023-05-07 格式:DOC 页数:12 大小:735.30KB
下载 相关 举报
广工编译原理课程设计Word文件下载.doc_第1页
第1页 / 共12页
广工编译原理课程设计Word文件下载.doc_第2页
第2页 / 共12页
广工编译原理课程设计Word文件下载.doc_第3页
第3页 / 共12页
广工编译原理课程设计Word文件下载.doc_第4页
第4页 / 共12页
广工编译原理课程设计Word文件下载.doc_第5页
第5页 / 共12页
广工编译原理课程设计Word文件下载.doc_第6页
第6页 / 共12页
广工编译原理课程设计Word文件下载.doc_第7页
第7页 / 共12页
广工编译原理课程设计Word文件下载.doc_第8页
第8页 / 共12页
广工编译原理课程设计Word文件下载.doc_第9页
第9页 / 共12页
广工编译原理课程设计Word文件下载.doc_第10页
第10页 / 共12页
广工编译原理课程设计Word文件下载.doc_第11页
第11页 / 共12页
广工编译原理课程设计Word文件下载.doc_第12页
第12页 / 共12页
亲,该文档总共12页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

广工编译原理课程设计Word文件下载.doc

《广工编译原理课程设计Word文件下载.doc》由会员分享,可在线阅读,更多相关《广工编译原理课程设计Word文件下载.doc(12页珍藏版)》请在冰点文库上搜索。

广工编译原理课程设计Word文件下载.doc

FOR<

变量>

:

=<

表达式>

STEP<

UNTIL<

Do<

语句>

选做内容(成绩评定范围扩大到:

“优”和“良”)

(1)增加类型:

①字符类型;

②实数类型。

(2)增加注释;

注释由/*和*/包含;

(3)扩充函数:

①有返回值和返回语句;

②有参数函数。

(4)增加一维数组类型(可增加指令)。

(5)其他典型语言设施。

三、课程设计环境与工具

(1)运行平台:

WIN7旗舰SP1

(2)实现工具:

C++Builder6.0

(3)教学型编译程序:

PL/0

四、结构设计说明和各功能模块描述

(1)PL/0语言编译器

PL/0语言可看成是PASCAL语言的子集,它的编译程序是一个编译解释执行系统。

PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关。

PL/0源程序

目标代码生成程序程序

(2)PL/0编译程序的过程或函数的功能表

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&

常量说明处理

9、 voidVarDeclaration(intLEV,int&

变量说明处理

10、voidCharDeclaration(intLEV,int&

字符说明处理

11、voidRealDeclaration(intLEV,int&

实数说明处理

12、voidListCode(intCX0):

列出目标代码清单

13、voidFACTOR(SYMSETFSYS,intLEV,int&

TX):

因子处理

14、voidTERM(SYMSETFSYS,intLEV,int&

项处理

15、voidEXPRESSION(SYMSETFSYS,intLEV,int&

TX):

表达式处理

16、voidCONDITION(SYMSETFSYS,intLEV,int&

条件处理

17、voidSTATEMENT(SYMSETFSYS,intLEV,int&

语句部分处理

18、voidBlock(intLEV,intTX,SYMSETFSYS):

分程序分析处理过程

19、intBASE(intL,intB,intS[]):

通过静态链求出数据区的基地址

20、voidInterpret():

对目标代码的解释执行程序

21、void__fastcallTForm1:

ButtonRunClick(TObject*Sender):

进行编译,RUN

(3)PL/0编译程序的总流程图

1、符号表

在编译程序中符号表用来存放语言程序中出现的有关标识符的属性信息,符号表中所登记的信息在编译的不同阶段都要用到。

在语义分析中,符号表所登记的内容将用于语义检查(如检查一个名字的使用和原先的说明是否一致)和产生中间代码。

在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。

对一个多遍扫描的编译程序,不同遍所用的符号表也往往各有不同。

因为每遍所关心的信息各有差异。

一张符号表的每一项(或称入口才包含两大栏(或称区段、字域),即名字栏(NAME)信息栏(INFORMATION)

 

信息栏包含许多子栏和标志位,用来记录相应名字和种种不同属性,由于查填符号表一般是通过匹配名字来寮现的,因此,名字栏也称主栏。

主栏的内容称为关键字(keyword)。

2、运行时存储组织和管理

由于编译时目标程序运行的数据空间大小已经规定,所以存储组织属于静态存储。

源程序的标识符存放在TABLE表中,目标代码存放在CODE中,S是由解释程序定义的一维整型数组,是程序运行时的数据存储空间。

解释程序还定义了4个寄存器:

1)P:

程序地址寄存器:

指向下一条要执行的目标程序的地址(相当目标程序CODE数组的下标)。

2)I:

指令寄存器:

存放着当前正在解释的下一条目标指令。

3)T:

栈顶寄存器:

由于每个过程当它被运行时,给它分配的数据空间(下边称数据段)包括静态部分和动态部分,对于动态部分,要注意的是,栈顶寄存器指出了当前栈中最新分配的单元。

4)B:

基址寄存器:

指向每个过程被调用时,在数据区S中给它分配的数据段的起始地址,也称基地址

2.1中间代码表示

对PL/0编译程序的目标代码的指令格式描述如下:

fla

其中f代表功能码,l表示层次差,a的含意对不同的指令有所区别,见下面对每条指令的解释说明:

lit0a

将常数值取到栈顶,a为常数值

Lodla

将变量值取到栈顶,a为偏移量,l为层差

SSTEPla

将栈顶内容送入某变量单元中,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

从命令行读入一个输入置于栈顶

2.2语法分析方法

自顶向下的语法分析:

<

程序>

<

分程序>

.

<

变量说明部分>

<

VAR<

标识符>

<

复合语句>

ABEGIN<

END

<

读语句>

READ(<

A

六、测试用例

1.测试*=和/=的运算功能,测试文件为P9101.PLO

2.测试FOR语句功能,测试文件为P9104.PLO

STEP<

DO<

七、开发过程和完成情况

1、扩充赋值运算:

思路:

乘等和除等运算的实现方法近似,故把两者看成一个看待。

采用临时变量存储这两个运算符,再分别对这两种情况处理。

具体代码实现:

if(SYM==ADDEQ||SYM==DIVEQ)//遇到*=和/=

{

ADDOP=SYM;

//临时存放运算符

if(i!

=0){//开始处理

GetSym();

GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);

//取值到栈顶

EXPRESSION(FSYS,LEV,TX);

if(ADDOP==ADDEQ)//遇到*=时

{GEN(OPR,0,4);

}//次栈顶乘以栈顶,退两个栈元素,结果值进栈.

else//遇到/=时

{GEN(OPR,0,5);

}//次栈顶乘以栈顶,退两个栈元素,结果值进栈

GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);

//出栈取值到内存

}

2、扩充FOR语句(Pascal)

①FOR<

②FOR<

其中,语句①的循环变量的步长为2,

语句②的循环变量的步长为-2。

以下为新增代码段:

//开始插入新增代码

caseFORSYM:

GetSym();

if(SYM!

=IDENT)Error(32);

elsei=POSITION(ID,TX);

if(i==0)Error(11);

elseif(TABLE[i].KIND!

=VARIABLE){/*ASSIGNMENTSTEPNON-VARIABLE*/

Error(12);

i=0;

//赋值语句中,赋值号左部标识符属性应是变量

//否则报错

}

if(SYM==BECOMES)GetSym();

elseError(13);

//赋值语句左部标识符后应是赋值号:

=否则报错

EXPRESSION(SymSetUnion(SymSetNew(TOSYM,DOWNTOSYM),FSYS),LEV,TX);

//EXPRESSION(FSYS,LEV,TX);

if(i!

=0)

GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);

//保存初值

if(SYM==TOSYM){//FOR..TO组合,即递增

CX1=CX;

//保存循环开始点

GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);

//将循环判断变量取出放到栈顶

GetSym();

EXPRESSION(SymSetUnion(SymSetNew(DOSYM),FSYS),LEV,TX);

/*判断循环变量条件,看是否跳出循环*/

GEN(OPR,0,13);

//生成比较指令,看循环变量是否依旧满足条件

CX2=CX;

//保存循环结束点

GEN(JPC,0,0);

//生成条件跳转指令,跳出循环,跳出的地址未知

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);

//将栈顶的值存入循环变量

if(SYM==DOSYM){//处理循环体

GetSym();

STATEMENT(FSYS,LEV,TX);

}

elseError(48);

GEN(JMP,0,CX1);

//无条件跳转到循环开始点

CODE[CX2].A=CX;

/*回填循环结束点的地址,CX为ELSE后语句执

行完的位置,它正是前面未定的跳转地址*/

}

elseif(SYM==DOWNTOSYM){//FOR..DOWNTO..组合,即递减

//保存循环开始点

/*判断循环变量条件,看是否跳出循环*/

GEN(OPR,0,11);

//生成比较指令,看循环变量是否依旧满足条件

CX2=CX;

//保存循环结束点

GEN(JPC,0,0);

//将循环变量取出放在栈顶

GEN(LIT,0,2);

//将步长取到栈顶

GEN(OPR,0,3);

//循环变量加步长,实现逐级递减

GEN(STO,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);

//将栈顶的值存入循环变量

if(SYM==DOSYM){//处理循环体

//循环体处理

/*回填循环结束点的地址,CX为ELSE后语句执

elseError(47);

break;

//结束插入新增代码

3、添加单行注释

在程序中,形如//C:

=1;

的代码段将会被忽略

if(ch=='

/'

){//开始处理

if(EOF!

=fscanf(fin,"

%c"

&

ch)){

if(ch=='

){

while(EOF!

ch)&

&

ch!

='

\n'

);

if(EOF==fscanf(fin,"

line[ll]=0;

break;

}else{

printf("

'

fprintf(fa1,"

line[ll]='

;

ll++;

}

}else{

printf("

注释出错!

!

"

return-1;

}

}

八、心得体会

课程设计的基本内容并不算难,但FOR语句功能实现比较繁琐,需要花时间调试和验证结果。

增加单词比较简单易行,而实现扩充功能则相对困难,需要理解编译程序的核心和基本思想,包括基本的语法分析和句法分析以及中间代码的生成,还有十分重要的堆栈应用。

把这些基础知识串联起来,理解好编译程序结构和原理及基本实现方法,才能更顺利的完成后面的设计内容。

当然,理论联系实际并不是那么简单,遇到困难并非那么轻易就能解决,通过和同学的交流,交流自己的调试错误所在和交换设计思路,同样把问题清晰化,最终达成一个解决方案。

很高兴本次课程设计达到了预期目标,巩固了编译程序理论知识,学以致用,当然也不能局限于课程设计,往后的自觉动手实践才能继续保持进步。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 幼儿读物

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2