广工编译原理课程设计报告_第1页
广工编译原理课程设计报告_第2页
广工编译原理课程设计报告_第3页
广工编译原理课程设计报告_第4页
广工编译原理课程设计报告_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、一、实验目的在分析理解一个教学型编译程序(如PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。达到进一步了解程序编译过程的基本原理和基本实现方法的目的。二、实验成要求1. 课内实验对PL/0作以下修改扩充:(1)增加单词:保留字 ELSE,FOR,TO,DOWNTO,RETURN运算符 +=,-=,+,-(2)修改单词:不等号# 改为 (3)增加条件语句的ELSE子句2. 课程设计基本内容(成绩范围:“中”、“及格”或“不及格”)(1)扩充赋值运算:+= 和 -=(2)扩充语句(Pascal的FOR语句):FOR := TO DO FOR := DOWNTO D

2、O 其中,语句的循环变量的步长为1,语句的循环变量的步长为-1。选做内容(成绩评定范围扩大到:“优”和“良”)(1)增加运算:+ 和 -。;(2)增加类型: 字符类型; 实数类型。(3)扩充函数: 有返回值和返回语句; 有参数函数。(4)增加一维数组类型(可增加指令)。(5)其他典型语言设施。三、实验环境(1)实现平台:WindowsXP, Visual studio 2005(2)教学型编译程序:PL/0 (C语言版)四、设计方案Error()出错处理,打印出错位置和错误编码GetCh()漏掉空格,读取一个字符GetSym() 词法分析,读取一个单词 GEN()目标代码生成过程,本过程用于把

3、生成的目标代码写入目标代码数组,供后面的解释器解释执行TEST() 测试当前单词是否合法过程testENTER()登陆符号表过程enterPOSITION()在符号表中查找指定符号所在位置的函数position,如果找不到就返回0VARDECLARATION()变量声明LISTCODE()列出目标代码清单;FACTOR() 因子处理过程factorTERM() 项处理过程term; EXPRESSION()表达式处理过程CONDITION() 条件处理过程STATEMENT()语句处理过程BLOCK() 语法分析过程 BASE() 通过静态链求出数据区基地址的函数,INTERPRET ()对目

4、标代码解释运行过程启动置初值调用getsym取单词调用block过程是否为源程序结束符源程序是否有错误调用解释过程interpret解释执行目标执行目标程序结束出错打印错误NNYY程序分程序语句条件表达式项因子PL/0语法调用关系图五、主要成分描述1 符号表在编译程序中符号表用来存放语言程序中出现的有关标识符的属性信息,符号表中所登记的信息在编译的不同阶段都要用到。在语义分析中,符号表所登记的内容将用于语义检查(如检查一个名字的使用和原先的说明是否一致)和产生中间代码。在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。对一个多遍扫描的编译程序,不同遍所用的符号表也往往各有不

5、同。因为每遍所关心的信息各有差异。一张符号表的每一项(或称入口才包含两大栏(或称区段、字域),即名字栏(NAME) 信息栏(INFORMATION) 信息栏包含许多子栏和标志位,用来记录相应名字和种种不同属性,由于查填符号表一般是通过匹配名字来寮现的,因此,名字栏也称主栏。主栏的内容称为关键字(key word)。2运行时存储组织和管理由于编译时目标程序运行的数据空间大小已经规定,所以存储组织属于静态存储。源程序的标识符存放在TABLE表中,目标代码存放在CODE中,S是由解释程序定义的一维整型数组,是程序运行时的数据存储空间。解释程序还定义了4个寄存器:1)P:程序地址寄存器:指向下一条要执

6、行的目标程序的地址(相当目标程序CODE数组的下标)。2)I:指令寄存器:存放着当前正在解释的下一条目标指令。3)T:栈顶寄存器:由于每个过程当它被运行时,给它分配的数据空间(下边称数据段)包括静态部分和动态部分,对于动态部分,要注意的是,栈顶寄存器指出了当前栈中最新分配的单元。4)B:基址寄存器:指向每个过程被调用时,在数据区S中给它分配的数据段的起始地址,也称基地址3. 中间代码表示对PL/0编译程序的目标代码的指令格式描述如下: f l a其中f代表功能码,l表示层次差,a的含意对不同的指令有所区别,见下面对每条指令的解释说明:lit 0 a将常数值取到栈顶,a为常数值Lod l a将变

7、量值取到栈顶,a为偏移量,l为层差Sto l a将栈顶内容送入某变量单元中,a为偏移量,l为层差Cal l a调用过程,a为过程地址,l为层差Int 0 a在运行栈中为被调用的过程开辟a个单元的数据区jmp 0 a无条件跳转至a地址Jpc 0 a条件跳转,当栈顶布尔值非真则跳转至a地址,否则顺序执行opr 0 0过程调用结束后,返回调用点并退栈opr 0 1栈顶元素取反opr 0 2次栈顶与栈顶相加,退两个栈元素,结果值进栈opr 0 3次栈顶减去栈顶,退两个栈元素,结果值进栈opr 0 4次栈顶乘以栈顶,退两个栈元素,结果值进栈opr 0 5次栈顶除以栈顶,退两个栈元素,结果值进栈opr 0

8、 6栈顶元素的奇偶判断,结果值在栈顶opr 0 7opr 0 8次栈顶与栈顶是否相等,退两个栈元素,结果值进栈opr 0 9次栈顶与栈顶是否不等,退两个栈元素,结果值进栈opr 0 10次栈顶是否小于栈顶,退两个栈元素,结果值进栈opr 0 11次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈opr 0 12次栈顶是否大于栈顶,退两个栈元素,结果值进栈opr 0 13次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈opr 0 14栈顶值输出至屏幕opr 0 15屏幕输出换行opr 0 16从命令行读入一个输入置于栈顶4. 语法分析方法自顶向下的语法分析: . VAR ; A BEGIN END

9、 READ ( ) A六、测试用例var a,b,c,d; 结果:输入3beginread(a); b:=a;c:=b-;d:=(b+2)/+c;if a=3 then begin /a=3 write(a); /b=2 write(b); /c=4 write(c); /d=1 write(d); end else结果:输入1/test begin/百慕大 c:=4; c+=-4; for a:=1 to 100 do c+; write(c); a-=1; write(a); endend. /test七、开发过程和完成情况1)增加保留字 ELSE,FOR,TO, DOWN, RETURN

10、.增加运算符 +=,-=,+,-首先, 在pl0.h中添加保留字(黑体字部分)enum symbol /此处需要修改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,elsesym,forsym,tosym,downto

11、sym,returnsym,plusplus,minusminus,plusequal,minusequal,;#define symnum 41 /改为相应的个数然后: 由于是二分查找,在如下位置按顺序排关键字/*设置保留字名字,按照字母顺序,便于折半查找*/strcpy(&(word00),begin);strcpy(&(word10),call);strcpy(&(word20),const);strcpy(&(word30),do);strcpy(&(word40),downto);strcpy(&(word50),else);strcpy(&(word60),end);strcpy(

12、&(word70),for);strcpy(&(word80),if);strcpy(&(word90),odd);strcpy(&(word100),procedure);strcpy(&(word110),read);strcpy(&(word120),return);strcpy(&(word130),then);strcpy(&(word140),to);strcpy(&(word150),var);strcpy(&(word160),while);strcpy(&(word170),write);/*设置保留字符号*/wsym0=beginsym;wsym1=callsym; wsy

13、m2=constsym;wsym3=dosym;wsym4=downtosym;wsym5=elsesym; wsym6=endsym; wsym7=forsym;wsym8=ifsym; wsym9=oddsym; wsym10=procsym;wsym11=readsym;wsym12=returnsym;wsym13=thensym;wsym14=tosym; wsym15=varsym;wsym16=whilesym;wsym17=writesym;2) 修改单词:不等号# 改为 首先, 将这句 ssym#=neq; 删除然后,在getsym()函数中,把分析到的定义为不等号if(ch

14、=)sym=neq;getchdo;else sym=lss;3)增加条件语句的ELSE子句在statement函数中改为if(sym=ifsym) /*准备按照if语句处理*/getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevthensym=true;nxtlevdosym=true; /*后跟符号为then或do*/conditiondo(nxtlev,ptx,lev); /*调用条件处理(逻辑运算)函数*/if(sym=thensym)getsymdo;elseerror(16); /*缺少then*/cx1=cx; /*保存当

15、前指令地址*/gendo(jpc,0,0); /*生成条件跳转指令,跳转地址暂写*/statementdo(fsys,ptx,lev); /*处理then后的语句*/add keyword elseif(sym=elsesym)getsymdo;int cx2=cx;gendo(jmp,0,0);codecx1.a=cx;statementdo(fsys,ptx,lev);codecx2.a=cx;elsecodecx1.a=cx; /*经statement处理后,cx为then后语句执行 完的位置,它正是前面未定的跳转地址*/4)添加+, -,+=, -=首先,在getsym函数中添加if(

16、ch=+)/plusplus pluseqalgetchdo;if(ch=+)sym=plusplus;getchdo;else if(ch=)sym=plusequal;getchdo;elsesym=plus;else if(ch=-)/minusminus minusequalgetchdo;if(ch=-)sym=minusminus;getchdo;else if(ch=)sym=minusequal;getchdo;然后,在statement函数中,修改switch(sym) case becomes:getsymdo;expressiondo(nxtlev,ptx,lev);br

17、eak;/+case plusplus:getsymdo;gendo(lit,0,1);gendo(opr,0,2);break;/+=case plusequal:getsymdo;expressiondo(nxtlev,ptx,lev);gendo(opr,0,2);break;/-case minusminus:getsymdo;gendo(lit,0,1);gendo(opr,0,3);break;/-=case minusequal:getsymdo;expressiondo(nxtlev,ptx,lev);gendo(opr,0,3);break;default: error(13

18、);再次,由于+,-运算要用到在表达式处理中,而且又有前加,前减,后加后减之类的,所以因子函数factor中也要有相应的处理。switch(tablei.kind)case constant: /*名字为常量*/gendo(lit,0,tablei.val); /*直接把常量的值入栈*/break;case variable: /*名字为变量*/gendo(lod,lev-tablei.level,tablei.adr); /*找到变量地址并将其值入栈*/加加减减if(forhead)gen(lit,0,1);if(temp=plusplus)gen(opr,0,2);else gen(opr

19、,0,3);gen(sto,lev-tablei.level,tablei.adr);gen(lod,lev-tablei.level,tablei.adr);forhead=false;end=true;elseforhead=true;break;case procedur: /*名字为过程*/error(21); /*不能为过程*/break;/增加加加与减减运算(后加后减)if(sym=plusplus|sym=minusminus)if(end) error(2000);if(forhead)gen(lit,0,1);if(sym=plusplus)gen(opr,0,2);else

20、 gen(opr,0,3);gen(sto,lev-tablei.level,tablei.adr);gen(lod,lev-tablei.level,tablei.adr);gen(lit,0,1);if(sym=plusplus) gen(opr,0,3);else gen(opr,0,2);end=false;getsym();elsetemp=sym;forhead=true;getsym();5) 添加for语句在statement函数中修改if(sym=forsym)getsymdo;if(sym=ident)i=position(id, *ptx);if(i=0) error(1

21、1);/变量没有说明elseif(tablei.kind!=variable) error(1000);getsym();if(sym!=becomes) error(1000);elsegetsym();expression(nxtlev,ptx,lev);if(sym=tosym|sym=downtosym)symbol tmp=sym;cx1=cx;gen(sto,lev-tablei.level,tablei.adr);gen(lod,lev-tablei.level,tablei.adr);getsym();expression(nxtlev,ptx,lev);if(tmp=tosy

22、m)gen(opr,0,13);else gen(opr,0,11);cx2=cx;gen(jpc,0,0);if(sym=dosym)getsym();statement(fsys,ptx,lev);gen(lod,lev-tablei.level,tablei.adr);gen(lit,0,1);if(tmp=tosym)gen(opr,0,2);else gen(opr,0,3);gen(jmp,0,cx1);codecx2.a=cx;else error(1000);else error(1000);else error(1000);6)添加单行注释对于单行注释,在getch函数中,将以/开头的文字去掉即可以实现单行

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论