广工编译原理课程设计报告Word格式.docx

上传人:b****6 文档编号:22215741 上传时间:2023-02-03 格式:DOCX 页数:15 大小:43.37KB
下载 相关 举报
广工编译原理课程设计报告Word格式.docx_第1页
第1页 / 共15页
广工编译原理课程设计报告Word格式.docx_第2页
第2页 / 共15页
广工编译原理课程设计报告Word格式.docx_第3页
第3页 / 共15页
广工编译原理课程设计报告Word格式.docx_第4页
第4页 / 共15页
广工编译原理课程设计报告Word格式.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

广工编译原理课程设计报告Word格式.docx

《广工编译原理课程设计报告Word格式.docx》由会员分享,可在线阅读,更多相关《广工编译原理课程设计报告Word格式.docx(15页珍藏版)》请在冰豆网上搜索。

广工编译原理课程设计报告Word格式.docx

(4)教学型编译程序:

PL/0

三、具体实现:

1.扩充赋值运算:

(1)语法树

(2)修改GetSym()方法(写出修改的代码)

elseif(CH=='

*'

){

GetCh();

if(CH=='

='

){SYM=TIMESBECOMES;

}

elseSYM=TIMES;

}elseif(CH=='

/'

){SYM=SLASHBECOMES;

(3)修改STATEMENT()方法(写出修改的代码)

caseIDENT:

i=POSITION(ID,TX);

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

elseif(TABLE[i].KIND==VARIABLE||TABLE[i].KIND==FLOATTYPE){/*ASSIGNMENTTONON-VARIABLE*/

GetSym();

if(SYM==BECOMES||SYM==TIMESBECOMES||SYM==SLASHBECOMES||SYM==PLUSBECOMES||SYM==MINUSBECOMES){

RELOP=SYM;

if(SYM!

=BECOMES){//若为除等于(或其他类似符号)则先把符号左边的变量值放入栈中GEN(LOD,LEV-TABLE[i].vp.LEVEL,TABLE[i].vp.ADR);

}elseError(13);

EXPRESSION(FSYS,LEV,TX);

if(RELOP==TIMESBECOMES){

GEN(OPR,0,4);

}elseif(RELOP==SLASHBECOMES){

GEN(OPR,0,5);

}elseif(RELOP==PLUSBECOMES){

GEN(OPR,0,2);

}elseif(RELOP==MINUSBECOMES){

GEN(OPR,0,3);

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

(4)运行测试(测试的PL0源码扩充单词的测试并贴运行结果截图)

PL0源码:

PROGRAMEX01;

VARA,B,C,D;

BEGIN

A:

=16;

A/=2;

WRITE(A);

//结果为8

B:

=4;

B*=2;

WRITE(B);

C:

=6;

C+=2;

WRITE(C);

D:

=10;

D-=2;

WRITE(D);

END.

(5)运行结果:

(6)出现的问题及解决

开始时在实现/=和*=操作时,*=的实现很顺利,而/=却一直没有得到理想的结果,通过与同学的讨论得知代码中除号指令的解析中,其实为除余操作,于是将%改为/,但是结果还是错误,经过调试发现是两个相除的数在栈中的位置相反了,正确的状态应该是除数位于次栈顶,而被除数位于栈顶。

解决:

在调用EXPRESSION函数解析/=右边表达式前,先将其左边变量的值放入栈中。

2.扩充语句(Pascal的FOR语句)

(1)

语法图

此处无修改,FOR、STEP、UNTIL及DO等关键字已放置关键字数组中,通过该数组便可识别。

caseFORSYM:

STATEMENT(SymSetUnion(SymSetNew(STEPSYM),FSYS),LEV,TX);

//处理for后面的赋值语句

CX3=CX;

GEN(JMP,0,0);

//用于第一次执行for语句时跳过step语句

CX1=CX;

//记录step后语句的代码位置

if(SYM==STEPSYM){

STATEMENT(SymSetUnion(SymSetNew(UNTILSYM),FSYS),LEV,TX);

//处理step后面的表达式

}elseError(8);

if(SYM==UNTILSYM){

CODE[CX3].A=CX;

//回填第一次进入for循环时的直接跳转地址

CONDITION(SymSetAdd(DOSYM,FSYS),LEV,TX);

//处理条件语句

if(SYM==DOSYM){

CX2=CX;

GEN(JPC,0,0);

//条件跳转,栈顶若为非真,则跳转到参数三位置,该位置待回填

STATEMENT(FSYS,LEV,TX);

//处理do后面内容

GEN(JMP,0,CX1);

//执行完for语句内的语句则重新跳回step处

CODE[CX2].A=CX;

//回填条件跳转

break;

(4)运行测试

VARA,SUM;

SUM:

=0;

FORA:

=1STEPA+=1UNTILA<

=100DO//求1~100的和

SUM+=A;

WRITE(SUM);

//结果为5050

实现FOR循环的前提是理解表达式处理函数及语句处理函数,关键是处理好跳转关系,例如第一次进入FOR循环时,生成FOR后面的表达式后应该有一个直接跳转跳过STEP语句进入UNTIL的条件判断;

而调用CONDITION处理UNTIL后的条件语句后,便有一个条件跳转跳到STEP后的表达式代码位置。

由于有了之前IF...ELSE...的参考及大致理解相关函数,因此实现时没出现太大问题。

3.增加类型:

(1)在GetSym中增加字符型及实数型数据的识别

elseif(CH=='

\'

'

NUM=CH;

){SYM=CHARACTER;

elseError(8);

elseif(CH>

0'

&

&

CH<

9'

){/*NUMBER*/

K=0;

NUM=0;

SYM=NUMBER;

do{

NUM=10*NUM+(CH-'

);

K++;

}while(CH>

.'

){//实现小数点后的识别

i=0;

M=0;

while(CH>

){//以下获取小数点后的值

J=0;

M=(CH-'

)*0.1;

while(J<

i){

M*=0.1;

J++;

NUM=NUM+M;

i++;

if(i>

LMAX)Error(30);

//LMAX为小数点后数字最大度

fprintf(FOUT,"

%f"

NUM);

(2)修改Block中的方法运行测试

if(SYM==CHARSYM){

CharDeclaration(LEV,TX,DX);

while(SYM==COMMA){GetSym();

if(SYM==SEMICOLON)GetSym();

elseError(5);

}while(SYM==IDENT);

}

if(SYM==FLOATSYM){

FloatDeclaration(LEV,TX,DX);

DoubleDeclaration(LEV,TX,DX);

(3)修改STATEMENT中的方法

elseif(TABLE[i].KIND==CHARTYPE||TABLE[i].KIND==VARIABLE||TABLE[i].KIND==FLOATTYPE){/*ASSIGNMENTTONON-VARIABLE*/

if(SYM==BECOMES||SYM==TIMESBECOMES||SYM==SLASHBECOMES

||SYM==PLUSBECOMES||SYM==MINUSBECOMES){

=BECOMES){//若为除等于(或其他类似)。

则先把符号左边的变量值放入栈中

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

EXPRESSION(FSYS,LEV,TX);

}else{

Error(12);

break;

caseWRITESYM:

//根据不同类型进行相应输出

GetSym();

if(SYM==LPAREN){

do{

GetSym();

EXPRESSION(SymSetUnion(SymSetNew(RPAREN,COMMA),FSYS),LEV,TX);

switch(TABLE[i].KIND){

caseCHARTYPE:

GEN(OPR,0,17);

caseFLOATTYPE:

GEN(OPR,0,18);

default:

{GEN(OPR,0,14);

}

}while(SYM==COMMA);

if(SYM!

=RPAREN)Error(SBNUM);

elseGetSym();

GEN(OPR,0,15);

/*WRITESYM*/

(4)修改FACTOR中的方法(包含字符的识别处理)

while(SymIn(SYM,FACBEGSYS)){

if(SYM==IDENT){

i=POSITION(ID,TX);

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

else

switch(TABLE[i].KIND){

caseCONSTANT:

GEN(LIT,0,TABLE[i].VAL);

caseVARIABLE:

casePROCEDUR:

Error(21);

}elseif(SYM==NUMBER){

if(NUM>

AMAX){Error(31);

GEN(LIT,0,NUM);

//将表达式中的数字置于栈顶

}elseif(SYM==LPAREN){//左括号

EXPRESSION(SymSetAdd(RPAREN,FSYS),LEV,TX);

if(SYM==RPAREN)GetSym();

elseError(22);

}elseif(SYM==CHARACTER){

GEN(LIT,0,NUM);

//将字符放入栈顶

(5)修改ENTER中的方法

caseCHARTYPE:

TABLE[TX].vp.LEVEL=LEV;

TABLE[TX].vp.ADR=DX;

DX++;

(6)在Interpret指令OPR中增加字符输出和实数输出

case17:

Form1->

printcs(S[T]);

fprintf(FOUT,"

%c\n"

S[T]);

T--;

//增加字符输出

case18:

Form1->

printrs("

"

%d\n"

//增加实数型输出

(7)其它修改

1)增加相应的关键字char和float;

2)由于增加实型,因此将模拟栈的数组类型改为double型;

另目标指令结构体INSTRUCTION中的A,及全局变量NUM也改为double型

(8)运行测试:

CHARA,B;

FLOATC,D,SUM;

A'

;

B'

+2;

WRITE(B+2);

=123.321;

=321.123;

=C+D+0.0004;

(9)运行结果:

(10)出现的问题及解决

字符型的实现主要问题是在赋值、字符表达式的处理及输出三个方面。

赋值刚开始没有思路,之后借鉴VAR型的赋值,才清楚需要使用到栈这个媒介进入赋值:

先把字符值放入栈中,在将栈顶值传给字符型变量。

而字符表达式的处理在Factor里进行识别处理。

关于输出则需要在WRITESYM的识别处理中进行类型判断采取不同输出方式,并需新建一条指令专门用于字符输出

实数型的实现主要问题为:

1、数据获取:

小数点后的值的获取需要用到循环帮助实现;

2、变量更改:

在没有引入实数型前,用来模拟栈的数组类型为int型,而引入后,则需要将其更改为实数型,在程序中与栈值有关的那些变量类型也同样改为实数型。

4.增加注释;

(1)修改GetSym()方法(写出修改的代码)

elseif(CH=='

i=CH;

while(i!

||CH!

//Form1->

printcs(CH);

if(i!

CH!

)Error(19);

else{

//不能忽略,为下一次调用GetSym提供第一个字符,用于switch语句

){//单行注释功能

i=CX;

//记录当前行

while(CC!

=LL)GetCh();

//CC为当前字符在行中位置,LL为当前行的字数

//滤去注释后继续获取后面的字符串

}elseSYM=SLASH;

(2)运行测试

/*下面代码求解1到100的之间

每个整数的相加之和*/

(3)运行结果

(4)出现问题及解决

刚开始就认为注释功能的实现比较容易,但是在实现过程还是出现不少问题。

我的思路是在getSym方法中使用循环滤去注释的内容,过程不断调用getCh读取下一个字符。

在循环处理注释结束后需要调用自身GetSym,因为上次调用的GetSym方法都用于处理注释了。

然而/**/这种情况却一直有报19号错误,经过查找发现该情况的循环执行完后,当前CH为符号’/’,而不是’/’后的字符,因此需要在调用GetSym前先调用getCh以便获取下一个新字符用于GetSym中的switch判断。

//不存在此情况,其循环结束CH为注释结束的下一字符。

四、心得

经过了一周多的奋战,此次课程设计的实现过程让我收获颇多,同时也让我意识到自己在编码过程中的不足。

在没做课程设计之前,我对代码编译的实现过程和对PL0代码的体系结构都很陌生,而当一步一步从实现/=等、for循环、注释及增加类型等功能后,我对代码编译过程有了一个整体而深入的认识。

在实现的过程中,虽然出现很多问题,但是通过自己的思考和请教同学都能得到解决。

在实现的过程中,我发现自己在考虑功能的实现方面不够全面仔细,例如字符型的增加,我只考虑到了字母这一种字符型,而没有考虑其他符号也为字符型,因此先前字符的识别我是通过判别当前SYM是否为ident型且其字符串长度是否为1这两个条件进行识别出来的。

当完成过后才发现该方法存在缺陷,才在GetSym里面另起分支进行识别处理。

这也提醒我以后考虑问题应当尽量周全。

源码下载地址:

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

当前位置:首页 > 幼儿教育 > 育儿理论经验

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1