ImageVerifierCode 换一换
格式:DOCX , 页数:30 ,大小:440.57KB ,
资源ID:24825992      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/24825992.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(编译原理课程设计报告PL0编译程序改进及完善.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

编译原理课程设计报告PL0编译程序改进及完善.docx

1、编译原理课程设计报告PL0编译程序改进及完善 燕山大学编译原理课程设计题目:PL/0编译程序改进及完善姓名:简越班级:06级计算机应用3班学号:060104010084日期:2009年7月15日设计题目:PL/0编译程序改进及完善。设计目的:阅读研究,改进设计和调试一个简单的编译程序。加深对编译理论和过程的了解。设计要求:1.有选择的对PL/0编译源程序补充,完善.2.设计编译典型的运行实例,以便反应出自己作出改进后的编 具有的功能。设计思想:PL/0语言可以看成PASCAL语言的子集,它的编译程序是一个编译解释执行系统。PL/0的目标程序为假想栈式计算机的汇编语言,与具体计算机无关。 PL/

2、0的编译程序和目标程序的解释执行程序都是用PASCAL语言书写的,因此PL/0语言可在配备PASCAL语言的任何机器上实现 。其编译过程采用一趟扫描方式,以语法分析程序为核心,词法分析和代码生成程序都作为一个独立的过程,当语法分析需要读单词时就调用词法分析程序,而当语法分析正确需要生成相应的目标代码时,则调用代码生成程序。 用表格管理程序建立变量、常量和过程表示符的说明与引用之间的信息联系。 当源程序编译正确时,PL/0编译程序自动调用解释执行程序,对目标代码进行解释执行,并按用户程序的要求输入数据和输出运行结果。 主要变量说明:/*变量说明*/FILE* fas; /*输出名字表*/FILE

3、* fa; /*输出虚拟机代码*/FILE* fa1; /*输出源文件及其各行对应的首地址*/FILE* fa2; /*输出结果*/bool listswitch; /*显示虚拟机代码与否*/bool tableswitch; /*显示名字表与否*/char ch; /*获取字符的缓冲区,getch使用*/enum symbol sym; /*当前的符号*/char idal+1; /*当前ident,多出的一个字节用于存放0*/int num; /*当前number*/int cc,ll; /*getch使用的计数器,cc表示当前字符(ch)的位置*/int cx; /*虚拟机代码指针,取值

4、范围0,cxmax-1*/char line81; /*读取行缓冲区*/char aal+1; /*临时符号,多出的一个字节用于存放0*/struct instruction codecxmax; /*存放虚拟机代码的数组*/char wordnorwal; /*保留字*/enum symbol wsymnorw; /*保留字对应的符号值*/enum symbol ssym256; /*单字符的符号值*/char mnemonicfctnum5; /*虚拟机代码指令名称*/bool declbegsyssymnum; /*表示声明开始的符号集合*/bool statbegsyssymnum;

5、/*表示语句开始的符号集合*/bool facbegsyssymnum; /*表示因子开始的符号集合*/* 目标指令*/1、LIT:将常量值取到运行栈顶.2、LOD:将变量放到运行栈顶.3、STO:将栈顶的内容送入某变量单元中.4、CAL:调用过程的指令.5、INT:为被调用的过程(或主程序)在运行栈中开辟数据区.6、JMP:无条件转移指令.7、JPC:条件转移指令,当栈顶的布尔值为真时, 顺序执行,否则转向域的地址.8、OPR:系运算符和算术运算指令.将栈顶和次栈顶的内容进行运算,结果存放栈顶./*函数说明*/void error(int n,int line)说明:出错处理函数,打印出错信

6、息,错误总数加1。int getch()说明:读取字符函数,返回字符。int getsym()说明:读取下一单词符号int position(char* idt,int tx);说明:字符在符号表中位置查询函数返回值:返回标识符在符号表中的索引int gen(enum fct x,int y,int z);说明:生成P代码指令int test(bool* s1,bool* s2,int n);说明:测试当前符号是否合法,若不合法,打印出错信息并进行跳读void enter(enum object k, int* ptx,int lev,int* pdx);说明:在符号表中登录分程序说明部分出现

7、的名字int constdeclaration(int* ptx,int lev,int* pdx); 说明:处理常量说明,并将常量名及相应信息填入符号表int vardeclaration(int* ptx,int lev,int* pdx); 说明:处理变量说明,并将变量名及相应信息填入符号表int statement(bool* fsys,int* ptx,int lev); 说明:分析处理各种语句int condition(bool* fsys,int* ptx,int lev); 说明:分析处理条件式 返回值:由参数x返回求值结果的类型void listcode(int cx0);

8、说明:打印P代码int block(int lev,int tx,bool* fsys); 说明:PL0编译器对外的接口,由main()调用void interpret(); 说明:解释执行P代码int base(int l,int* s,int b); 说明:基地址处理函数 返回值:返回变量的基地址值int expression(bool* fsys,int* ptx,int lev) 说明:表达式处理,由参数返回结果类型int term(bool* fsys,int* ptx,int lev); 说明:项处理,由参数返回结果类型int factor(bool* fsys,int* ptx,

9、int lev); 说明:因子处理,由参数返回结果类型int inset(int e,bool* s);int addset(bool* sr,bool* s1,bool*s2,int n);int subset(bool* sr,bool* s1,bool*s2,int n);int mulset(bool* sr,bool* s1,bool*s2,int n);说明:使用数组实现集合的集合运算算法描述:在原算法基础上我进行了一下修改1.增加单词:保留字 ELSE2.运算符 +=,=,+,3.增加条件语句的ELSE子句为此添加了ELSESYM,为了实现如上要求的扩充,必须再正确地添加JIAJ

10、IA,JIANJIAN,JIADENG,JIANDENG等几个个SYMBOL,具体必须包括以下三个方面的修改或添加: 在枚举变量SYMBOL的定义内添加JIAJIA,JIANJIAN,JIADENG,JIANDENG和ELSESYM;然后在在源程序文件中加上保留字ELSE,为了识别例如A:=+A之类的功能,还需在因子开始符号中加入JIAJIA,JIANJIAN。这样,我们就正确地加入了五个将用来作为扩充语言功能的SYM。为了实现功能首先需要在词法分析中加入识别单词功能增加JIAJIA()、JIADENG()、JIANJIAN()、JIANDENG()的词法分析,代码修改如下: if(ch=+)

11、 getchdo; if(ch=) sym=jiadeng; getchdo; else if(ch=+) sym=jiajia; getchdo; else sym=plus; else if(ch=-) getchdo; if(ch=) sym=jiandeng; getchdo; else if(ch=-) sym=jianjian; getchdo; else sym=minus; 这样,我们就完成了对词法分析器的修改。然后JIAJIA.,JIANJIAN操作的语法图有如下两个: 语 句 因 子 根据以上语法图,我们只要对语句处理程序和因子处理程序进行修改添加,即可实现增加INC和DE

12、C操作,首先对语句处理程序进行如下修改: 语句中形如+A,A修改:if(sym=jiajia|sym=jianjian)/+a,-a if(sym=jiajia) getsymdo; if(sym=ident) i=position(id,*ptx); if(i=0) error(11); else if(tablei.kind!=variable) error(12); i=0; else gendo(lod,lev-tablei.level,tablei.adr);/生成指令,将变量放到栈顶 gendo(lit,0,1);/生成指令,把常量取到运行栈顶 gendo(opr,0,2);/生成

13、指令,栈顶加次栈顶 gendo(sto,lev-tablei.level,tablei.adr);/生成指令,结果写回变量地址单元 getsymdo; else /-a getsymdo; if(sym=ident) i=position(id,*ptx); if(i=0) error(11); else if(tablei.kind!=variable) error(12); i=0; else gendo(lod,lev-tablei.level,tablei.adr);/生成指令,取变量放大栈顶 gendo(lit,0,1);/生成指令,取常数到栈顶 gendo(opr,0,3);/生成

14、指令,栈顶减次栈顶 gendo(sto,lev-tablei.level,tablei.adr);/生成指令,结果写回变量地址单元 getsymdo; 随后修改如A+,A if(sym=jiajia|sym=jianjian)/a+,a- addop=sym; gendo(lod,lev-tablei.level,tablei.adr); /把变量的值压入栈 gendo(lit,0,1); if(addop=jiajia) gendo(opr,0,2); gendo(sto,lev-tablei.level,tablei.adr); else gendo(opr,0,3); gendo(sto

15、,lev-tablei.level,tablei.adr); getsymdo; 这样,对JIAJIA和JIANJIAN操作就扩充完成。 扩充和操作 这两个操作都是一种对变量进行赋值的形式,其合法的语句形式的语法图如下所示: 根据图3,在已经处理部分的基础上,添加对运算和运算的扩充,相关代码添加如下: if(sym=jiadeng|sym=jiandeng) addop=sym; getsymdo; gendo(lod,lev-tablei.level,tablei.adr); /*把变量的值压入栈*/ factordo(nxtlev,ptx,lev); if(addop=jiadeng) g

16、endo(opr,0,2); /*生成加法指令*/ else gendo(opr,0,3); /*生成减法指令*/ 这样就完成了对运算和运算的添加。 增加条件语句else该语句的语法图如只要在STATEMENT修改如下代码: if(sym=elsesym) cx2=cx; gendo(jmp,0,0); codecx1.a=cx; getsymdo; statementdo(nxtlev,ptx,lev);/*处理else后的语句*/ codecx2.a=cx; else codecx1.a=cx; 这样ELSE语句扩充完毕为了显示错误更清晰我增加了显示错误原因的语句具体代码在ERROR中实现

17、 switch(n) case 1: printf(常数说明中的“=”写成了“:=”。n); break; case 2: printf(常数说明中的“=”后应是数字。n); break; case 3: printf(常数说明中的标识符后应是“=”。n); break; case 4: printf(const,var,procedure后应为标识符。n); break; case 5: printf(漏掉了“,”或“;”。n); break; case 6: printf(过程说明后的符号不正确(应是语句开始符,或过程定义符)。n); break; case 7: printf(应是语句开

18、始符。n); break; case 8: printf(程序体内语句部分的后跟符号不正确。n); break; case 9: printf(程序结尾丢了句号“.”。n); break; case 10: printf(语句之间漏了“;”。n); break; case 11: printf(标志符未说明。n); break; case 12: printf(在“:=”或“+=”或“-=”左部标志符属性应是变量。n); break; case 13: printf(缺少“:=”或“+=”或“-=”。n); break; case 14: printf(call后应为标志符。n); break

19、; case 15: printf(call后标志符属性应为过程。n); break; case 16: printf(条件语句中丢了“then”。n); break; case 17: printf(丢了“end”或“;”。n); break; case 18: printf(while型循环语句中丢了“do”。n); break; case 19: printf(语句后的符号不正确。n); break; case 20: printf(应为关系运算符。n); break; case 21: printf(表达式内标志符属性不能是过程。n); break; case 22: printf(表

20、达式内中漏掉右括号“)”。n); break; case 23: printf(因子后的非法符号。n); break; case 24: printf(表达式的开始符不能是此符号。n); break; case 30: printf(number的最大位数为。n); break; case 31: printf(数越界。n); break; case 32: printf(最大的嵌套层数不能大于层。n); break; case 33: printf(格式错误,应是右括号。n); break; case 34: printf(格式错误,应是左括号。n); break; case 35: pri

21、ntf(read()中的变量名没有声明过。n); break; case 36: printf(“;”写成了“,”。n); break; 这样代码修改完毕我还改进了一个形如var a;b;或者const a;b;语句错误添加错误编号36(“;”写成了“,”)。 if(sym=semicolon) getsymdo if(sym=ident) error(36); 改变了声明符号时无法重复或无法改变声明顺序。具体方法是讲源代码中 memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);nxtlevident=true;nxtlevperiod=true;tes

22、tdo(nxtlev,declbegsys,7);增加VARSYM与CONSTSYM后跟符号集修改后变为memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);nxtlevident=true;nxtlevperiod=true;nxtlevconstsym=true;nxtlevvarsym=true;testdo(nxtlev,declbegsys,7);最后为了实行人性化操作我增加了编译程序循环执行的方法具体方法是在主函数中加入 while(1) /保证用户连续运行程序. getchar(); /退出程序的字符标号 printf(n退出程序请按q键,继

23、续运行请按其它键!t); scanf(%c,&ch); if(ch=q) break;/退出程序 else system(cls);/清屏*/ 调试情况:形如var a;b;或者const a;b;语句错误文件名为test1.txtvar a;const d=2;var b;const c=1;begina:=d;b:=c;write(a);write(b)end.改动前程序执行情况改动后程序执行情况我还改进了一个形如var a;b;或者const a;b;语句错误添加错误编号36(“;”写成了“,”)。文件名为test2.txtvar a;b;const c=1;b:=2;begina:=c

24、;write(a)end.程序执行情况:调试if then else文件名为else.txtvar a,b;begin read(a); if a0 then b:=-1 else b:=1; write(a); write(b)end.运行结果:调试+,文件名为+.txtvar a,b,c,d;begin a:=1; b:=2; c:=9; c+; c-; -c; +c; a+=-c; a-=c-; d:=(+b)+c; write(b); write(c); write(d); write(a)end.运行结果:设计技巧:万事无捷径,只有一步一步脚踏实地。只有相对的技巧,就是对原程序的错误编号,标记。对改动的错误利用编译程序的断点功能检查错误。书写程序的时候,首先画语法图列出框架,在根据框架书写程序。心得体会:这次改进还有不完善的地方,例如检查形为CONST A=1;B=2;时的错误的时候,如果把语句放入BEGIN语句体内会出现新的错误。所以完善此编译程序还得考虑的更加仔细

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

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