PLO语言功能扩展.docx

上传人:小飞机 文档编号:4888083 上传时间:2023-05-21 格式:DOCX 页数:14 大小:171.94KB
返回 下载 相关 举报
PLO语言功能扩展.docx_第1页
第1页 / 共14页
PLO语言功能扩展.docx_第2页
第2页 / 共14页
PLO语言功能扩展.docx_第3页
第3页 / 共14页
PLO语言功能扩展.docx_第4页
第4页 / 共14页
PLO语言功能扩展.docx_第5页
第5页 / 共14页
亲,该文档总共14页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《PLO语言功能扩展.docx》由会员分享,可在线阅读,更多相关《PLO语言功能扩展.docx(14页珍藏版)》请在三一办公上搜索。

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

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

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

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

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

6、error(13); /*检测赋值符号*/memcpy(nxtlev,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(nxtlev,fsys,sizeof(bool)*symnum);nxtlev

7、dosym=true; /* 后跟符号为 do */conditiondo(nxtlev,ptx,lev); /* 调用条件处理 */cx2=cx; /*保存循环体的结束的下一个位置*/gendo(jpc,0,0); /*生成条件跳转,但跳出循环的地址未知*/ if(sym=dosym) getsymdo;else error(18); /* 缺少 do */statementdo(fsys,ptx,lev); /* 循环体 */gendo(jmp,0,cx1); /*回头重新判断条件*/codecx2.a=cx; /*反填跳出循环的地址,与if类似*/4. 增加case语句:(1)设计思想:

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

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

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

11、f(tablei.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 conpst;/*存放当前处理情

12、况的常量标号的position*/ int jjj;for(jjj=0;jjj50;jjj+)cxjmpadrjjj=0;do getsymdo;if(sym!=ident)/*是否为标识符*/error(37);/*case语句体中,冒号前面应该为标识符*/elseconpst=i=postion(id, *ptx);if(i=0)error(11);/*标识符未找到*/elseif(tablei.kind!=constant)error(40);/*标识符应该为常量*/getsymdo;if(sym!=colon)error(39);/*应该为冒号*/memcpy(nxtlev, fsys

13、, 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);/*将 当 前 常量放到栈顶*/gendo(opr,0,8);/*将当前栈顶和次栈顶比较,看是否相等,是为真, 否为假放到次栈顶*/cjpc=cx;/

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

15、or(jjj=0;jjjcasenum;jjj+)codecxjmpadrjjj.a=cx;getsymdo;5.相关代码的修改说明:修改部分为红色加粗字体1) .h中文件的修改:/*关键字个数*/#define norw 17/*符号*/enum symbolnul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss,leq,gtr,geq,lparen,rparen,comma,semicolon,colon,period,becomes,beginsym,endsym,ifsym,thensym,whilesym,writesym

16、,readsym,dosym,callsym,constsym,varsym,procsym, forsym,casesym,endcasesym;#define symnum 362) 初始化函数init ()中的修改:/*设置保留字名字*/strcpy(&(word00),begin);strcpy(&(word10),call);strcpy(&(word20),case);strcpy(&(word30),const);strcpy(&(word40),do);strcpy(&(word50),end);strcpy(&(word60),endcase);strcpy(&(word70

17、),for);strcpy(&(word80),if);strcpy(&(word90),odd);strcpy(&(word100),procedure);strcpy(&(word110),read);strcpy(&(word120),then);strcpy(&(word130),var);strcpy(&(word140),while);strcpy(&(word150),write);/*设置保留字符号*/wsym0=beginsym;wsym1=callsym;wsym2=casesym;wsym3=constsym;wsym4=dosym;wsym5=endsym;wsym6=

18、endcasesym;wsym7=forsym;wsym8=ifsym;wsym9=oddsym;wsym10=procsym;wsym11=readsym;wsym12=thensym;wsym13=varsym;wsym14=whilesym;wsym15=writesym;3) 新增错误编号及含义:33 read语句缺少右括号34 read语句缺少左括号35 read ()中的标识符应为声明过的变量36 case 中丢了 endcase37 case语句体开头应为标识符38 case后的标识符应为变量39 case变量后应为冒号40 case语句体开头因为常量五. 测试数据及结果:测试用

19、例一1. 测试代码:文件名:success.txt代码:const a=1,c=2,d=3;var b,i,k;beginread(k);b:=0;for i:=0;i=k dobeginb:=b+i;i:=i+1;end;write(b);read(i);case i:a:b:=11;c:b:=22;d:b:=33endcase;write(b)end.2. 测试说明:首先输入源文件文件全名success.txt。在输入一个整数x,函数将输出x从0到x的所有整数和。接着,输入1或者2或者3,将相应输出11、22、33。本测试用例中既含有for语句,有含有case语句,同时测试了两种语句的功能

20、。3. 运行截图:21write;24read;26case i:S6a:S6b:=11 ;3333c :33b:=22;4040d:40b:=3345endcase ;4747write49end.1 int 0 62 opr 0 163 sto 0 546 Jup 0 4747 lod 0 348 opr 0 1449 opr 0 1550 opr 0 0start pl0?1005050?333Press mny key to cont inue测试用例二1. 测试代码:文件名: error.txt代码:const a=10,c=1,d=2;var b,i,k;beginread(k);

21、b:=0;for i:=0;ikbeginb:=b+i;i:=i+1end;write(b ;b:=1;case a:a:b:=a;c:b:=c+a;b:b:=aendcase;write(b)end.2. 测试说明:下输入文件全名error.txt。程序语法有错,运行后会有报错信息,但是还是会生 成汇编代码。报错编号与课本一样,不过新增36到40几个编号。3. 运行截图:Input file? error.txt List object code?y List symbol table?y Oconst a=10,c=l,d=2;luar b,i,k;1beginTABLE:1 const

22、a ual=102 const c ual=l3 const d ual=24 uar b leu=0 addr=35 uar i leu=0 addr=46 uar k leu=0 addr=52 read;4 b:=0;6 for i:=0;ik10 begin*1812b:=b+i;16i:=i+l18 end;21 writeb ;*33Q4 b:=l26 casea:*38a:Q6b: =a; 3 3c : 3b : =c +a ;广J12 lod0313 lod0414 opr0215 sto0316 lod0417 lit0118 opr0219 sto0420 Jmp08El

23、lod0322 opr01423 opr015E4 lit0125 sto03加lod00E7 lit01028 opr08b? jpc033he lit010hi sto03 2 JmpU-L J-LF10J-X49J-X 3 lod00 4 lit01 5 opr08t o p d r i t m o p 1 s j 1 o 6 7 8 9 0 4 4 4 4s0 9 413 4 3 1El opr 0 15E2 opr 0 0Errors in pl/0 program Press anij key to continue其他测试用例说明:说明:以下说明的程序文件在工程文件夹里。程序ab.txt:简单的输入输出测试;程序adder.txt、adder2.txt:累加的for语句测试程序;程序casess.txt: case测试语句。六.实验感想:

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号