




已阅读5页,还剩12页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
课内实验报告 项目名称 PL/0编译器 学 院_ 计算机学院_专 业_ _年级班别_学 号 _学生姓名_ _辅导教师_成 绩_ _目录一、课内实验的内容-4二、实验修改部分-4三、概述-11四、结构设计说明-11五、各功能模块描述-14六、主要成份描述-14七、测试用例-16八、开发过程和完成情况-21一、课内实验的内容对PL/0作以下修改扩充:(1)增加单词:保留字 ELSE,FOR, STEP,RETURN运算符 +=,-=,+,-,&,|,(2)修改单词:不等号# 改为 (3)增加条件语句的ELSE子句二、实验修改部分:1、增加四个保留字和七个运算符,共十一个单词。修改部分:#define symnum 43 /保留字从32增加到43个2、增加五个保留字:ELSE,FOR,STEP,RETURN头文件pl0.henum symbol 新增加单词: elsesym, forsym, stepsym,returnsym, pluseq/* += */,plusone/* + */,plus/* + */,minuseq/* -= */,minusone/* - */,minus/* - */,and,or,not头文件pl0.h#define norw 24 /关键字从13增加到24个PL0.cppinit();新增加:(增加后数组的内容要再次根据字母顺序重新排列) strcpy(&(word00),begin);strcpy(&(word10),call);strcpy(&(word20),const);strcpy(&(word30),do);strcpy(&(word40),else); /*增加单词:保留字else*/ strcpy(&(word50),end); strcpy(&(word60),for); /*增加单词:保留字 for*/strcpy(&(word70),if); strcpy(&(word80),odd);strcpy(&(word90),procedure);strcpy(&(word100),read); strcpy(&(word110),return);/*增加单词:保留字 return*/strcpy(&(word120),step); /*增加单词:保留字step*/strcpy(&(word130),then);strcpy(&(word140),while); strcpy(&(word150),write); wsym0=beginsym; wsym1=callsym; wsym2=constsym; wsym3=dosym; wsym4=elsesym; /*else*/ wsym5=endsym; wsym6=forsym; /*for*/ wsym7=ifsym; wsym8=oddsym; wsym9=procsym; wsym10=readsym; wsym11=returnsym; /*return*/ wsym12=stepsym; /*step*/ wsym13=thensym; wsym14=whilesym; wsym15=writesym;3、增加四个运算符 :+=,-=,+,- , l PL0.cppgetsym();增加对+,-,+,-,+=,-=的识别; Statement(); 增加对+,-,+,-,-=的语句的处理;Init()中改动:ssym&=and;ssym|=or;ssym=not;facbegsysplusone=true; / 添加前自加运算facbegsysminusone=true;/ 添加前自减运算Getsym()增加的内容:17int getsym()int i,j,k;while( ch= |ch=10|ch=9)getchdo;if(ch=a&ch=z) k=0;doif(k=a&ch=0&ch=9);ak=0;strcpy(id,a);i=0;j=norw-1;dok=(i+j)/2;if(strcmp(id,wordk)=0)i=k+1;while(ij)sym=wsymk;elsesym=ident;elseif(ch=0&ch=0&chnmax)error(30);elseif(ch=:) /*检测赋值符号*/getchdo;if(ch=)sym=becomes;getchdo;elsesym=nul; /*不能识别的符号*/elseif(ch=) /*检测大于或大于等于符号*/ getchdo;if(ch=)sym=geq;getchdo;elsesym=gtr;/*这里之间为添加的内容*/else if(ch=+)/*检测+,+=,+符号*/getchdo;if(ch=) sym=pluseq;getchdo;else if(ch=+) sym=plusone; getchdo;else sym=plus;else if(ch=-)/*检测-,-=,-符号*/getchdo;if(ch=)sym=minuseq;getchdo;else if(ch=-)sym=minusone;getchdo;else sym=minus;/*这里之间为添加的内容*/elsesym=ssymch;/* 当符号不满足上述条件时,全部按照单字符号处理*/getchdo;/richardif(sym!=period)getchdo;/end richardreturn 0;Statement()增加的内容:(将本来“if(sym=becomes)”部分的内容修改为处理+,+=,-,-=),并在Statement()中定义变量int sym2; if(sym=becomes|sym=pluseq|sym=minuseq|sym=plusone|sym=minusone) sym2=sym; getsymdo;gendo(lod,lev-tablei.level,tablei.adr); else error(13); if(sym2=plusone|sym2=minusone)/* 准备按照a+、a-语句处理,与read类似*/ if(i!=0) if(sym2=plusone) gendo(lit,0,1); gendo(opr,0,2); gendo(sto,lev-tablei.level,tablei.adr); if(sym2=minusone) gendo(lit,0,1); gendo(opr,0,3); gendo(sto,lev-tablei.level,tablei.adr); else memcpy(nxtlev,fsys,sizeof(bool)* symnum); expressiondo(nxtlev,ptx,lev); if(i!=0) if(sym2=becomes) gendo(sto,lev-tablei.level,tablei.adr);if(sym2=pluseq) gendo(opr,0,2);gendo(sto,lev-tablei.level,tablei.adr);if(sym2=minuseq) gendo(opr,0,3);gendo(sto,lev-tablei.level,tablei.adr); /else 4、修改单词:不等号# 改为 l PL0.cppinit(); 移除: ssym#=neq;在getsym()里增加对的识别(在或=基础上修改)。下面为在基础上修改,注意在if(ch=)那部分:if(ch=) /add neq sym=neq;getchdo;/*在之间添加*/else sym=lss;5、增加条件语句的ELSE子句l PL0.cpp在statement()里的“if.then”语句处理的基础上添加对else子句的处理,使之能处理ifthenelse的语句。elseif(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; /*保存当前指令地址*/gendo(jpc,0,0); /*生成条件跳转指令,跳转地址暂写0*/*这里之间开始添加*/memcpy(nxtlev,fsys,sizeof(bool)*symnum); /添加后跟符号nxtlevelsesym=true;statementdo(nxtlev,ptx,lev); /*处理then后的语句*/codecx1.a=cx; /*经statement处理后,cx为then后语句执行完的位置,它正是前面未定的跳转地址*/if(sym=elsesym) cx2=cx; getsymdo; gendo(jmp,0,0); codecx1.a=cx; statementdo(fsys,ptx,lev); codecx2.a=cx;/*这里之间开始添加*/ elseif(sym=beginsym) /*准备按照复合语句处理*/ getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevsemicolon=true;nxtlevendsym=true;/*后跟符号为分号或end*/*循环调用语句处理函数,直到下一个符号不是语句开始符号或收到end*/statementdo(nxtlev,ptx,lev);while(inset(sym,statbegsys)|sym=semicolon)if(sym=semicolon)getsymdo;elseerror(10);/*缺少分号*/statementdo(nxtlev,ptx,lev);if(sym=endsym)getsymdo;elseerror(17); /*缺少end或分号*/写出相关文法:G(S): Sif S else S | if S | aElse语法图:三、概述源语言:PL/0语言目标语言:假想栈式计算机的汇编语言实现工具: VC+6.0 运行平台: Windows 7四、结构设计说明1、PL/0编译程序的结构图如下:由于PL/0编译程序采用一趟扫描方法,所以语法语义分析过程block是整个编译程序的核心。下面给出编译程序的总体流程图,以弄清block过程在整个编译程序中的作用。在流程图中可以看出,主程序置初值后先调整用读单词过程getsym取一个单词,然后再调用语法分析过程block,直到遇源程序的结束符“.”为止。五、 各功能模块描述GetSym() : 词法分析, 从源文件中读出若干有效字符,组成token串,识别它的类型为保留字/标识符/数字或其它符号。GEN() : 目标代码生成过程,本过程用于把生成的目标代码写入目标代码数组,供后面的解释器解释执行.TEST() : 测试当前单词是否合法ENTER() : 在名字表中加入一项POSITION () : 查找名字的位置,找到则返回名字表中的位置,否则返回0ConstDeclaration() : 常量声明处理VarDeclaration() : 变量声明处理ListCode() : 输出目标代码清单FACTOR() : 因子处理过程TERM() : 项处理过程EXPRESSION() : 表达式处理过程CONDITION() : 条件处理过程STATEMENT() : 语句处理过程Block() : 编译程序主体, 参数:lev:这一次语法分析所在的层次,tx:符号表指针, fsys:用于出错恢复的 单词集合BASE() : 通过过程基址求上一层过程的基址Interpret() : 解释程序, PL/0编译器产生的类PCODE目标代码解释运行过程六、主要成份描述 1.符号表在编译程序中符号表用来存放语言程序中出现的有关标识符的属性信息,这些信息集中反映了标识符的语义特征属性.符号表的主要功能如下:、收集符号属性、上下文语义合法性检查的依据、作为目标代码生成阶段地址分配的依据.、符号表的数据结构:struct tablestruct char nameal; /*名字*/ enum object kind; /*类型:const,var,array orprocedure*/ int val; /*数值,仅const使用*/ int level; /*所处层,仅const不使用*/ int adr; /*地址,仅const不使用*/ int size; /*需要分配的数据区空间,仅procedure使用*/;struct tablestruct tabletxmax; /*名字表*/2.运行时的存储组织和管理当源程序经过语法分析,如果未发现错误时,由编译程序调用解释程序,对存放在CODE中的代码CODE0开始进行解释执行.当废弃结束后,记录源程序中标识符的TABLE表已没有作用.因此存储区只需以数组CODE存主的只读目标程序和运行机制时的数据区S,S是由解释程序定义的一维整数型数组. 解释执行时的数据空间S为栈式计算机的在座空间,遵循后进先出规则,对每个过程(包括主程序)当调用 时,才分配数据空间,退出过程进, 则所分配原则的数据空间被释放.解释程序还定义了4个寄存器:1、指令寄存器.存放当前正在解释的一条目标指令2、程序地址寄存器.指向下一条要执行的目标程序的地址3、栈顶寄存器.4、基址寄存器.指向每个过程被调用时,在数据区S中给它分配原则的数据段起始地址,也称基地址.为了实现过程被调用时给它分配数据段,过程运行结束后释放数据段以及嵌套过程之间结标志符引用的问题,当过程被调用时,在栈顶分配三个联系单元,这三个联系单元存放的内容分别为:SL静态链,动态链DL,RA返回地址。3.语法分析方法语法分析的任务是识别由词法分析给出的单词符号序列在结构上是否符合给定的文法规则.PL/0编译程序的语法分析采用了自顶向下的递归子程序法.粗略地说:就是对应每个非终结符语法单元,编一个独立的处理过程(或子程序).语法分析研究从读入第一个单词开始由非终结符程序即开始符出发,沿语法描述图箭头所指出的方向进行分析.当遇到非终结符时,则调用相应的处理过程,从语法描述图看也就进入了一个语法单元,再沿当前所进入的语法描述图的箭头方向进行分析,当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,则执行相应的语义程序(就是翻译程序).再读取下一个单词继续分析.遇到分支点时将当前的单词与分支点上的多个终结符逐个相比较,若都不匹配时可能是进入下一非终结符语法单位或是出错.如果一个PL/0语言程序的单词序列在整修语法分析中,都能逐个得到匹配,直到程序结束.,这时就说所输入的程序是正确的.对于正确的语法分析做相应的语义翻译,最终得出目标程序. 4.中间代码表示PL/0编译程序所产生的目标代码是一个假想栈式计算机的汇编语言,可称为类pcode指令代码,它不依赖任何实际计算机,其指令集极为简单,指令格式如下:fLalit 0 a将常数值取到栈顶,a为常数值Lod l a将变量值取到栈顶,a为偏移量,l为层差Sto l a将栈顶内容送入某变量单元中,a为偏移量,l为层差Cal 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 6栈顶元素的奇偶判断,结果值在栈顶opr 0 7opr 0 8次栈顶与栈顶是否相等,退两个栈元素,结果值进栈opr 0 9次栈顶与栈顶是否不等,退两个栈元素,结果值进栈opr 0 10次栈顶是否小于栈顶,退两个栈元素,结果值进栈opr 0 11次栈顶是否大于等于栈顶,退两个栈元素,结果值
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论