收藏 分享(赏)

2015广工编译原理课程设计报告.doc

上传人:精品资料 文档编号:8501642 上传时间:2019-06-30 格式:DOC 页数:16 大小:370.37KB
下载 相关 举报
2015广工编译原理课程设计报告.doc_第1页
第1页 / 共16页
2015广工编译原理课程设计报告.doc_第2页
第2页 / 共16页
2015广工编译原理课程设计报告.doc_第3页
第3页 / 共16页
2015广工编译原理课程设计报告.doc_第4页
第4页 / 共16页
2015广工编译原理课程设计报告.doc_第5页
第5页 / 共16页
点击查看更多>>
资源描述

1、课 程 设 计课程名称_编译原理_ _题目名称_PL/0 编译器的扩充 _学生学院_计算机学院_ _专业班级_ 计算机科学与技术 13(9)学 号 学生姓名 指导教师_林志毅_2016 年 1 月 2 日一、 已完成的内容:(1) 扩充赋值运算:*= 和 /=(2) 扩充语句(Pascal 的 FOR 语句)FOR :=STEP UNTILDo(3) 增加类型: 字符类型; 实数类型。(4) 增加注释; 多行注释由 /*和*/包含,单行注释为/ 二、 实验环境与工具(1)计算机及操作系统:PC 机,Windows7(2)程序设计语言:C+(3)使用软件 Borland C+ Builder 6

2、.0(4)教学型编译程序:PL/0三、 具体实现:1. 扩充赋值运算:*= 和 /=(1) 语法树(2) 修改 GetSym()方法(写出修改的代码)else if(CH=*) GetCh();if(CH=) SYM=TIMESBECOMES; GetCh(); else SYM=TIMES; else if(CH=/) GetCh();if(CH=) SYM=SLASHBECOMES; GetCh(); (3) 修改 STATEMENT()方法(写出修改的代码)case IDENT:i=POSITION(ID,TX);if (i=0) Error(11);变量 *=(/=,-=,+=)表达式

3、else if (TABLEi.KIND=VARIABLE | TABLEi.KIND=FLOATTYPE) /*ASSIGNMENT TO NON-VARIABLE*/GetSym();if (SYM=BECOMES| SYM=TIMESBECOMES | SYM=SLASHBECOMES|SYM=PLUSBECOMES|SYM=MINUSBECOMES) RELOP=SYM;if(SYM!=BECOMES) /若为除等于(或其他类似符号)则先把符号左边的变量值放入栈中 GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);GetSym(); else Err

4、or(13);EXPRESSION(FSYS,LEV,TX);if(RELOP=TIMESBECOMES) GEN(OPR,0,4); else if(RELOP=SLASHBECOMES) GEN(OPR,0,5); else if(RELOP=PLUSBECOMES) GEN(OPR,0,2); else if(RELOP=MINUSBECOMES) GEN(OPR,0,3);GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);(4) 运行测试(测试的 PL0 源码扩充单词的测试并贴运行结果截图)PL0 源码:PROGRAM EX01;VAR A,B,C,

5、D;BEGINA:=16;A/=2;WRITE(A); /结果为 8B:=4;B*=2;WRITE(B); /结果为 8C:=6;C+=2;WRITE(C); /结果为 8D:=10;D-=2; WRITE(D); /结果为 8END.(5) 运行结果:(6) 出现的问题及解决开始时在实现/=和*=操作时,*=的实现很顺利,而/=却一直没有得到理想的结果,通过与同学的讨论得知代码中除号指令的解析中,其实为除余操作,于是将%改为/,但是结果还是错误,经过调试发现是两个相除的数在栈中的位置相反了,正确的状态应该是除数位于次栈顶,而被除数位于栈顶。解决:在调用 EXPRESSION 函数解析/=右边

6、表达式前,先将其左边变量的值放入栈中。2. 扩充语句(Pascal 的 FOR 语句)FOR :=STEP UNTILDo(1) 语法图(2) 修改 GetSym()方法(写出修改的代码)此处无修改,FOR、STEP、UNTIL 及 DO 等关键字已放置关键字数组中,通过该数组便可识别。(3) 修改 STATEMENT()方法(写出修改的代码)case FORSYM:GetSym();STATEMENT(SymSetUnion(SymSetNew(STEPSYM),FSYS),LEV,TX); /处理for 后面的赋值语句CX3=CX; GEN(JMP,0,0); /用于第一次执行 for 语

7、句时跳过 step 语句CX1=CX; /记录 step 后语句的代码位置if(SYM=STEPSYM) GetSym();STATEMENT(SymSetUnion(SymSetNew(UNTILSYM),FSYS),LEV,TX); /处理step 后面的表达式 else Error(8);if(SYM=UNTILSYM) CODECX3.A=CX; /回填第一次进入 for 循环时的直接跳转地址GetSym(); else Error(8);CONDITION(SymSetAdd(DOSYM, FSYS),LEV,TX); /处理条件语句if(SYM=DOSYM) GetSym(); e

8、lse Error(8);CX2=CX; GEN(JPC,0,0); /条件跳转,栈顶若为非真,则跳转到参数三位置,该位置待回填STATEMENT(FSYS,LEV,TX); /处理 do 后面内容GEN(JMP,0,CX1); /执行完 for 语句内的语句则重新跳回 step 处CODECX2.A=CX; /回填条件跳转break;(4) 运行测试PL0 源码:PROGRAM EX01;VAR A,SUM;BEGINSUM:=0;FOR A:=1 STEP A+=1 UNTIL A=0 /LMAX 为小数点后数字最大度fprintf(FOUT,“%f“, NUM);(2) 修改 Block

9、 中的方法运行测试if (SYM=CHARSYM) GetSym();do CharDeclaration(LEV,TX,DX);while (SYM=COMMA) GetSym(); CharDeclaration(LEV,TX,DX); if (SYM=SEMICOLON) GetSym();else Error(5);while(SYM=IDENT);if (SYM=FLOATSYM) GetSym();do FloatDeclaration(LEV,TX,DX);while (SYM=COMMA) GetSym(); DoubleDeclaration(LEV,TX,DX); if (

10、SYM=SEMICOLON) GetSym();else Error(5);while(SYM=IDENT);(3) 修改 STATEMENT 中的方法case IDENT:GetSym();i=POSITION(ID,TX);if (i=0) Error(11);else if (TABLEi.KIND=CHARTYPE | TABLEi.KIND=VARIABLE | TABLEi.KIND=FLOATTYPE) /*ASSIGNMENT TO NON-VARIABLE*/if (SYM=BECOMES | SYM=TIMESBECOMES | SYM=SLASHBECOMES| SYM=

11、PLUSBECOMES| SYM=MINUSBECOMES) RELOP=SYM;if(SYM!=BECOMES) /若为除等于(或其他类似) 。 。则先把符号左边的变量值放入栈中GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR);GetSym(); else Error(13);EXPRESSION(FSYS,LEV,TX);if(RELOP=TIMESBECOMES) GEN(OPR,0,4); else if(RELOP=SLASHBECOMES) GEN(OPR,0,5); else if(RELOP=PLUSBECOMES) GEN(OPR,0,2)

12、; else if(RELOP=MINUSBECOMES) GEN(OPR,0,3);GEN(STO,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); else Error(12); i=0;break;case WRITESYM: /根据不同类型进行相应输出GetSym();if (SYM=LPAREN) do GetSym();EXPRESSION(SymSetUnion(SymSetNew(RPAREN,COMMA),FSYS),LEV,TX);i=POSITION(ID,TX);switch (TABLEi.KIND) case CHARTYPE:GEN(OPR,

13、0,17); break;case FLOATTYPE:GEN(OPR,0,18); break;default:GEN(OPR,0,14);while(SYM=COMMA);if (SYM!=RPAREN) Error(SBNUM);else GetSym();GEN(OPR,0,15);break; /*WRITESYM*/(4) 修改 FACTOR 中的方法(包含字符的识别处理)while (SymIn(SYM,FACBEGSYS) if (SYM=IDENT) i=POSITION(ID,TX);if (i=0) Error(11);elseswitch (TABLEi.KIND) c

14、ase CONSTANT: GEN(LIT,0,TABLEi.VAL); break;case VARIABLE: GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); break;case PROCEDUR: Error(21); break;case FLOATTYPE: GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); break;case CHARTYPE: GEN(LOD,LEV-TABLEi.vp.LEVEL,TABLEi.vp.ADR); break;GetSym(); else if (SYM=NUMBER

15、) if (NUMAMAX) Error(31); NUM=0; GEN(LIT,0,NUM); GetSym(); /将表达式中的数字置于栈顶 else if (SYM=LPAREN) /左 括 号GetSym(); EXPRESSION(SymSetAdd(RPAREN,FSYS),LEV,TX);if (SYM=RPAREN) GetSym();else Error(22); else if (SYM=CHARACTER) GEN(LIT,0,NUM); /将字符放入栈顶GetSym();(5) 修改 ENTER 中的方法case CHARTYPE:TABLETX.vp.LEVEL=LE

16、V; TABLETX.vp.ADR=DX; DX+;break;case FLOATTYPE:TABLETX.vp.LEVEL=LEV; TABLETX.vp.ADR=DX; DX+;break;(6) 在 Interpret 指令 OPR 中增加字符输出和实数输出case 17: Form1-printcs(ST); fprintf(FOUT,“%cn“,ST); T-; /增加字符输出break;case 18: Form1-printrs(“,ST); fprintf(FOUT,“%dn“,ST); T-; /增加实数型输出break;(7) 其它修改1) 增加相应的关键字 char 和

17、 float;2) 由于增加实型,因此将模拟栈的数组类型改为 double 型;另目标指令结构体 INSTRUCTION 中的 A,及全局变量 NUM 也改为 double 型(8) 运行测试:PL0 源码:PROGRAM EX01;CHAR A,B;FLOAT C,D,SUM;BEGINA:=A;B:=B+2;WRITE(A); WRITE(B); WRITE(B+2);C:=123.321;D:=321.123;SUM:=C+D+0.0004;WRITE(SUM); END.(9) 运行结果:(10) 出现的问题及解决字符型的实现主要问题是在赋值、字符表达式的处理及输出三个方面。赋值刚开始

18、没有思路,之后借鉴 VAR 型的赋值,才清楚需要使用到栈这个媒介进入赋值:先把字符值放入栈中,在将栈顶值传给字符型变量。而字符表达式的处理在 Factor 里进行识别处理。关于输出则需要在 WRITESYM 的识别处理中进行类型判断采取不同输出方式,并需新建一条指令专门用于字符输出实数型的实现主要问题为:1、数据获取:小数点后的值的获取需要用到循环帮助实现;2、变量更改:在没有引入实数型前,用来模拟栈的数组类型为int 型,而引入后,则需要将其更改为实数型,在程序中与栈值有关的那些变量类型也同样改为实数型。4. 增加注释; 多行注释由/*和*/包含,单行注释为/ (1) 修改 GetSym()

19、方法(写出修改的代码)else if(CH=/) GetCh();if(CH=) SYM=SLASHBECOMES; GetCh(); else if(CH=*) GetCh();i=CH;while(i!=* | CH!=/) i=CH;GetCh();/ Form1-printcs(CH);if(i!=*else GetCh();/不能忽略,为下一次调用 GetSym 提供第一个字符,用于 switch 语句GetSym(); else if(CH=/) /单行注释功能i=CX;/记录当前行while(CC!=LL) GetCh(); /CC 为当前字符在行中位置,LL 为当前行的字数Ge

20、tSym(); /滤去注释后继续获取后面的字符串 else SYM=SLASH;(2) 运行测试PL0 源码:PROGRAM EX01;VAR A,SUM;BEGIN/*下面代码求解 1 到 100 的之间每个整数的相加之和*/SUM:=0;FOR A:=1 STEP A+=1 UNTIL A=100 DO /求 1100 的和SUM+=A;WRITE(SUM); END.(3) 运行结果(4) 出现问题及解决刚开始就认为注释功能的实现比较容易,但是在实现过程还是出现不少问题。我的思路是在 getSym 方法中使用循环滤去注释的内容,过程不断调用getCh 读取下一个字符。在循环处理注释结束后

21、需要调用自身 GetSym,因为上次调用的 GetSym 方法都用于处理注释了。然而/*/这种情况却一直有报 19 号错误,经过查找发现该情况的循环执行完后,当前 CH 为符号/ ,而不是/后的字符,因此需要在调用 GetSym 前先调用 getCh 以便获取下一个新字符用于 GetSym 中的 switch 判断。/不存在此情况,其循环结束 CH 为注释结束的下一字符。四、 心得经过了一周多的奋战,此次课程设计的实现过程让我收获颇多,同时也让我意识到自己在编码过程中的不足。在没做课程设计之前,我对代码编译的实现过程和对 PL0 代码的体系结构都很陌生,而当一步一步从实现/=等、for 循环、注释及增加类型等功能后,我对代码编译过程有了一个整体而深入的认识。在实现的过程中,虽然出现很多问题,但是通过自己的思考和请教同学都能得到解决。在实现的过程中,我发现自己在考虑功能的实现方面不够全面仔细,例如字符型的增加,我只考虑到了字母这一种字符型,而没有考虑其他符号也为字符型,因此先前字符的识别我是通过判别当前SYM 是否为 ident 型且其字符串长度是否为 1 这两个条件进行识别出来的。当完成过后才发现该方法存在缺陷,才在 GetSym 里面另起分支进行识别处理。这也提醒我以后考虑问题应当尽量周全。源码下载地址:http:/

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

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报