PLO语言功能扩展_第1页
PLO语言功能扩展_第2页
PLO语言功能扩展_第3页
PLO语言功能扩展_第4页
PLO语言功能扩展_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

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

文档简介

1、编译原理实验报告一实验目的:熟练掌握PLO语言编译程序的结构和功能;二实验要求:扩充PLO语言的功能,增加for语句和case语句;已知for语句和case语句的语法如下:for语句:二for(赋值语句;关系表达式)do语句关系表达式 := 表达式关系运算符表达式case 语句:二case标识符:常量:语句endcase .三.实验环境与工具:计算机及操作系统:WindowsXP程序设计语言:C编译程序:PL/0实现工具(平台):VC+6.0四设计方案:概述:源语言:pl0目标语言:类pcode代码实现工具(平台):VC+6.0结构设计说明:PlO所有子程序如下:过程或函数名简要功能说明mai

2、n初始化编译环境,建立关键字表,调用分程序Block对源文件进行编译, 当编译正确时,自动调用解释执行程序,对目标代码进行解释执行。error出错处理,打印出错位置和错误性质编号。并在信息栏输出错误信息。get ch过滤空格,读取一个字符getsym词法分析,读取一个单词gen生成目标代码(类pcode代码),并送入目标程序区。test测试当前单词是否是合法block分程序分析处理过程。enter登录过程说明对象包括变量、常量和过程名的属性信息到符号表。position查找标识符在符号表中的位置。constdeclaration常量定义处理,收集常量信息并登录到符号表。vardeclarati

3、on变量定义处理,收集变量信息并登录到符号表。listcode列出目标代码清单。statement语法分析,语句部分处理。expression表达式分析处理。term项分析处理过程。factor因子分析处理。condition条件处理。interpret对目标代码进行解析执行。Base通过静态链求数据区首地址。增加for语句:(1)设计思想:For语句的语法分析::二for(赋值语句;关系表达式)do语句设计思路:主要分为两部分模块:一,for和;之间的赋值语句处理;二,条件语句处理和最后的语句处 理。首先获取赋值号左边的标识符,从符号表中找到它的信息,并确认这个标识符确为变量名。 然后通过调

4、用表达式处理过程算得赋值号右部的表达式的值并生成相应的指令保证这个值放在运 行期的数据栈顶。最后通过前面查到的左部变量的位置信息,生成相应的STO指令,把栈顶值存入 指定的变量的空间,实现了赋值操作。返回函数值也是用赋值语句进行返回值的储存。首先调用cond it ion函数处理条件语句,并且把当前condi tion处理生成的判断条件操作代 码的的地址cx保存到cxl。每个循环体中,在循环体结束前,设置跳回判断操作判断当前条件是否 跳出循环。都把本循环体结束的下一个位置保存到cx2生成跳转,并在循环结束时用cx2更新为目 前循环结束跳转地址。难点分析:本模块,主要难点是处理循环体的跳转,解决

5、方法参照上点。不过可以参照if语 句和while语句。(2)扩充代码:在头文件plO.h中的符号symbol中增加所要求增加的符号,用加粗倾斜红色字体标出:源代码:if(sym=forsym) /*准备按照for语句处理*/getsymdo;if(sym=ident) /*按照赋值语句处理*/i=pos tio n(id,*p tx); if(i=0)error(11); /* 变量未找到 */ elseif(t ablei.kind!二variable)error(12); /* for语句格式错误或者赋值语句格式错误*/ i=0; getsymdo;if(sym=becomes)getsy

6、mdo;else error(13); /*检测赋值符号*/ memcpy(nx tl ev,fsys,sizeof(bool)*symnum); expressiondo(nxtlev,ptx,lev); /*处理赋值符号右侧表达式*/ if(i!=0)gendo(sto,lev-tablei.level, tablei.adr); /* expression 将执行一系列指令,但最终 结果将会保存在栈顶,执行sto命令完成赋值*/else error(17);cx1=cx; /*保存判断条件操作的位置*/getsymdo;memcpy(nx tl ev,fsys,sizeof(bool)*

7、symnum);nxtlevdosym二true; /* 后跟符号为 do */conditiondo(nxtlev,ptx,lev); /* 调用条件处理 */cx2=cx; /*保存循环体的结束的下一个位置*/ gendo(jpc,0,0); /*生成条件跳转,但跳出循环的地址未知*/ if(sym=dosym)getsymdo;else error(18); /* 缺少 do */stat emen tdo(fsys,p tx,lev); /* 循环体 */ gendo(jmp,0,cxl); /*回头重新判断条件*/ codecx2.a=cx; /*反填跳出循环的地址,与if类似*/

8、增加case语句:(1)设计思想:Case语句的语法分析:case语句:二case标识符:常量:语句endcase设计思路:按照上述语法分析图,先写出格式判断,建立语句处理的框架。再细致写出伪代码的生成核 心部分。(以下分析中提及的“循环体”是指上面语法分析图的循环结构)依照语法要求写出语法分析的框架,大致如上分析图。首先,将变量的位置存到blpst,供后面生成变量与常量比较指令用。用casenum记下case 含有的情况个数。每个循环体开始,取得常量之后,生成三条指令lod (将变量压到栈顶)、lit (将 常量押到栈顶)、opr 0 8 (两者作比较)。在生成后面语句的代码之前,生成jpc

9、利用变量和常量 比较所得结果进行跳转,若为假,则跳到本循环体结束的地方。接着,对循环体内语句进行处理。 生成无条件跳转指令跳转到case语句结束,由于地址未知,要等先把各个循环体中的无条件跳转 指令的地址放到cxjmpadr数组中,待case结束后再回填跳转地址。最后,回填本循环体头的条件 跳转地址。难点分析:1处理常量与变量的比较。一开始以为应该跟if语句类似,处理常量与变量的比 较的时候发现这一点跟if语句压根不同,而且要难得多。不过,后来认识到变量的本质,从生成 的汇编代码的角度出发,利用生成三条指令lod (将变量压到栈顶)、lit (将常量押到栈顶)、opr0 8 (两者作比较)解决

10、了这个问题。2循环体的跳转问题,比较复杂。简单来说,三点跳转的关键 点:一,循环体头的判断跳转;二,循环倒数第二个操作,跳出case语句操作;三,最后的回填 条件跳转操作。(2)扩充代码: 在头文件plO.h中的符号symbol中增加所要求增加的符号,用加粗倾斜红色字体标出:源代码:if(sym=casesym) /*case 语句*/getsymdo;if(sym!=ident)error(14);/* case后应为标识符*/elseint blpst=i=postion(id, *ptx);/*将变量的 position 保存在 blpst 中*/ if(i=0)error(ll);/*

11、标识符未找到*/elseif(t ablei.kind!二variable)error(38);/* case后的标识符应该为变量*/getsymdo;if(sym!=colon)error(39);/*应该为冒号*/elseint casenum=0;/*casenum 记录情况个数 */int cxjmpadr50;/*cxjmpadr用于存储各 种情况中转移指令的地址*/int cxb=cx;/*cxb存储case语句开始的指令地址*/int cjpc;/*当前情况处理完常量标号后的跳转指令地址*/ int varpst=i;/*存放 case 后面变量的 position*/ int

12、conpst;/*存放当前处理情况的常量标号的position*/ int jjj;for(jjj=0;jjj50;jjj+)cxjmpadrjjj=0;dogetsymdo;if(sym!二iden t)/*是否为标识符*/error(37);/*case语句体中,冒号前面应该为标识符*/elseconpst=i=postion(id, *ptx);if(i=0)error(ll);/*标识符未找到*/elseif(t ablei.kind!=cons tant)error(40);/*标识符应该为常量*/getsymdo;if(sym!二colon)error(39);/*应该为冒号*/m

13、emcpy(nxtlev, fsys, sizeof(bool)*symnum);nxtlevsemicolon二true;nxtlevcolon二true;nxtlevendcasesym二true;/* 后跟符号为分号或 end */getsymdo;变量放到栈顶*/常量放到栈顶*/否为假放到次栈顶*/gendo(lod,lev-tableblpst. level,tableblpst .adr);/*将 case 后 gendo(lit, lev-tableconpst. level,tableconpst. val);/*将 当 前 变量放到栈顶*/常量放到栈顶*/否为假放到次栈顶*/

14、gendo(jpc,0,0);/*设置条件跳转,地址暂时未知*/statementdo(nxtlev, ptx, lev);cxjmpadrcasenum+二ex;/*记住当前情况的jmp语句代码地址*/gendo(jmp,0,0);/*设置跳出case语句,跳转地址暂时未知*/codecjpc.a=cx;/*回填 jpc 跳转地址*/pri ntf (%dn,codecjpc.a);while(sym=semicolon);if(sym!二endcasesym)error(36);/*结束符号因该为endcase*/*回填各个情况处理中的jmp语句的跳转地址*/ for(jjj=0;jjjc

15、asenum;jjj+)codecxjmpadrjjj.a=cx;getsymdo;5.相关代码的修改说明:修改部分为红色加粗字体.h中文件的修改:/*关键字个数*/#define norw 17/*符号*/enum symbolnul,ide nt,n umber,plus,minus ,ti mes,slash,oddsym,eql,neq,lss,leq, gt r,geq,lparen,rparen,comma,semicolon,colon,period,becomes,beginsym, endsym,ifsym ,t hensym,whilesym,wri tesym,reads

16、ym,dosym,callsym,cons tsym,varsym,procsym, forsym,casesym,endcasesym;#define symnum 36初始化函数init()中的修改:/*设置保留字名字*/st rcpy (&(word00),begin);st rcpy( &(wordl0),call);st rcpy( &(word20),case);st rcpy (&(word30),cons t);st rcpy( &(word40),do);st rcpy (&(word50),end);st rcpy( &(word60),endcase);st rcpy(

17、&(word70),for);st rcpy (&(word80),if);st rcpy( &(word90),odd);st rcpy (&(word100),procedure);st rcpy (&(wordll0),read);st rcpy( &(word120), then);st rcpy (&(word130),var);st rcpy (&(word140),while);st rcpy (&(word150),wr it e); /*设置保留字符号*/ wsym0=beginsym; wsym1=callsym;wsym2=casesym;wsym3=constsym;

18、wsym4=dosym; wsym5=endsym; wsym6=endcasesym; wsym7=forsym; wsym8=ifsym; wsym9=oddsym; wsym10=procsym; wsym11=readsym; wsym12二thensym; wsym13=varsym; wsym14=whilesym; wsym15=writesym;新增错误编号及含义:read语句缺少右括号read语句缺少左括号read ()中的标识符应为声明过的变量case 中丢了 endcasecase语句体开头应为标识符case后的标识符应为变量case变量后应为冒号case语句体开头因为常

19、量五测试数据及结果:测试用例一1.测试代码:文件名:success .txt代码:cons t a=l,c=2,d=3;var b,i,k;beginread(k);b:=0;for i:=0;i=k dobeginb:=b+i;i:=i+l;end;writ e(b);read(i);case i:a:b:=11;c:b:=22;d:b:=33endcase;writ e(b)end.2测试说明:首先输入源文件文件全名success. txt。在输入一个整数x,函数将输出x从0到x的所有整数和。接着,输入1或者2或者3,将相应输出11、22、33。本测试用例中既含有for语句,有含有case

20、语句,同时测试了两种语句的功能。3.运行截图:21既含有for语句,有含有case语句,同时测试了两种语句的功能。3.运行截图:21write;24read;26case i:S6a:S6b:=11 ;3333c :33b:=22;4040d:40b:=3345endcase ;4747 0 6opr 0 16sto 0 534lit0235opr0836JPC04037lit02238sto0339jmp04740lod0441lit0342opr0843JPC04744lit03345sto03Jup 0 47lod 0 3opr 0 14opr 0 15opr 0 0start pl0?1005050?333Press ani/ key to cont inue测试用例二1.测试代码:文件名: error .txt代码:cons t a=10,c=l,d=2;var b,i,k;beginread(k);b:=0;for i:=0;ikbeginb:=b+i;i:=i+1end;writ e(b ;b:=1;case a:a:b:=a;c:b:=c+a;b:b:=aendcase;writ e(b)e

温馨提示

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

评论

0/150

提交评论