PL0功能扩充课程设计.doc_第1页
PL0功能扩充课程设计.doc_第2页
PL0功能扩充课程设计.doc_第3页
PL0功能扩充课程设计.doc_第4页
PL0功能扩充课程设计.doc_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

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

文档简介

课 程 设 计 课程名称_编译原理_ 题目名称 pl/0功能扩充 学生学院 计算机学院 专业班级 计科一班 2012年 1 月 1 日1 课程设计目的在分析理解一个教学型编译程序(如pl/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。达到进一步了解程序编译过程的基本原理和基本实现方法的目的。2 课程设计要求基本内容(1)扩充赋值运算:+= 和 -= (2)扩充语句(pascal的for语句):for := to do for := downto do 其中,语句的循环变量的步长为1,语句的循环变量的步长为-1。(3)增加运算:+ 和 -。3 课程设计环境与工具(1)计算机及操作系统:pc机,windows7(2)实现工具:c+builder6(3)教学型编译程序:pl/0 4 说明1、pl/0编译程序的结构图pl0 源 程 序词法分析程序语法分析程序代码生产程序目 标 程 序表 格 管 理 程 序出 错 处 理 程 序2、pl/0编译程序的总体流程图:启动置初值调用getsym取单词调用block过程是否为源程序结束符源程序是否有错误调用解释过程interpret解释执行目标执行目标程序结束出错打印错误nnyy 3、pl/0编译程序的过程或函数的功能表过程或函数名简要功能说明pl0主程序error出错处理,打印出错位置和错误编码getsym词法分析,读取一个单词getch漏掉空格,读取一个字符gen生成目标代码,并送入目标程序区test测试当前单词符号是否合法block分程序分析处理过程enter登录名字表position(函数)查找标识符在名字表中的位置constdeclaration常量定义处理vardeclaration变量说明处理listode列出目标代码清单statement语句处理expression表达式处理term项处理factor因子处理condition条件处理interpret对目标代码的解释执行程序base(函数)通过静态链求出数据区的基地址4、词法分析词法分析是编译的第一个阶段,它的主要任务是从左向右逐个字符地对源程序进行扫描,产生一个个单词序列用于语法分析。pl/0词法分析程序getsym的功能是为语法分析提供单词用的,是语法分析的基础,把输入的字符串形式的源程序分割成一个个单词符号。经过词法分析程序分析出来的单词,对语言固有的单词只给出类别存放在全程变量sym中,而对用户定义的单词(标识符或常数)既给出类别又给值,其类别放在sym中,值放在全程变量id或全程变量num中,全部单词种类由编译程序定义的纯量类型symbol给出,称为语法词汇表。程序分程序语句条件表达式项因子pl/0 语法调用关系图5、语法分析pl/0编译程序的语法分析采用了自顶向下的递归的子程序法。语法分析同时也根据程序的语义生成相应三元代码,并提供了出错处理的机制。语法分析主要由分程序分析过程(block)、常量定义分析过程(constdeclaration)、变量定义分析过程(vardeclaration)、语句分析过程(statement)、表达式处理过程(expression)、项处理过程(term)、因子处理过程(factor)和条件处理过程(condition)构成。这些过程在结构上构成一个嵌套的层次结构。详细见作图6、语义分析pl/0 的语义分析主要进行以下检查:(1) 是否存在标识符先引用未声明的情况;(2) 是否存在己声明的标识符的错误引用;(3) 是否存在一般标识符的多重声明。7、中间代码生成目标代码类pcode是一种假想栈式计算机的汇编语言。添加覆盖:opr l 14栈顶值输出至屏幕(l=1:字符型;l=0:整型)opr 0 15输出回车opr l 16从命令行读入一个字符输入置于栈顶(l=1:字符型;l=0:整型)stp l a将栈顶置入暂存数组tmpa里,l=1退一栈,否则不退gtp 0 a 将暂存数组tmpa的值放到栈顶以下3个为数组新增:acp l al=1则将当前离栈顶偏移a的值复制到新栈顶;l=0不操作ast l a 将栈顶的值写入与a偏移量等于次栈顶的地址,栈退2ald l a 从与a偏移量等于栈顶得地址的值放在该栈顶上8、语法错误处理pl/0编译程序对语法错误的处理采用两种办法:(1)对于一些易于校正的错误,如丢了逗号、分号等,指出出错的位置,加以校正,继续进行分析。 (2)对于难于校正的错误,给出错误的位置与性质,跳过后面一些单词,直到下一个可以进行正常语法分析的语法单位。错误类型如下0 过程开始部分说明不正确1 常数说明中=写成:=2 常数说明中=后应为整数或实数或字符3 常数说明中的标识符后应是=4 const, var, procedure后应为标识符5 漏掉了,或;6 过程说明后的符号不正确(应该是语句开始符,或过程定义符)7 应是语句开始符8 程序体内语句部分的后跟符不正确9 程序结尾丢了句号.10 语句间漏了;11 标识符未说明12 赋值语句中,赋值号左部标识符属性应是变量13 变量后不能是此符号14 call后应为标识符15 call后标识符属性应为过程16 条件语句中丢了then17 丢了end或;18 while型循环语句丢了do19 语句后的符号不正确20 应为关系运算符21 表达式内标识符属性不能是过程22 表达式中漏掉右括号(23 因子后的非法符号24 表达式的开始符不能是此符号31 数越界32 read语句中的标识符不是变量33 后接符号应该是“”34 未知的类型35 缺少“”36 运行栈空间不足,无法申请该数组37数组的下标不合法38 后接符号应该是“do”39 应为to或者downto五、设计过程:a、增加运算+=,-=,+,-1、代码:词法分析:case +: getch(); if(ch=+)sym=inc;getch(); else if(ch=)sym=append;getch(); else sym= plus; break; case -: getch(); if(ch=-)sym=dec;getch(); else if(ch=)sym=reduce;getch(); else sym= minus;语法分析:1、在因子处理程序里:case constant: if(sym=inc|sym=dec)error(23);break; gen(lit,0,tablei.val); break; case variable: if(sym=lmparen) getsym(); set=ast;lod=ald; expression(symsetadd(rmparen,fsys),lev,tx); if(rmparen=sym) getsym(); else error(35); if(sym=inc|sym=dec) gen(acp,ast=set,0); gen(lod,lev-tablei.vp.level,tablei.vp.adr); if(sym=inc) gen(lit,0,1); else gen(lit,0,-1); gen(opr,0,2); gen(set,lev-tablei.vp.level,tablei.vp.adr); gen(acp,ast=set,-1); gen(lod,lev-tablei.vp.level,tablei.vp.adr); if(sym=inc) gen(lit,0,-1); else gen(lit,0,1); gen(opr,0,2); getsym(); else gen(lod,lev-tablei.vp.level,tablei.vp.adr); break; case inc: case dec: getsym(); if(sym=ident) i=position(id,tx); if(i!=0) vstyle=tablei.style; getsym(); if(sym=lmparen) getsym(); set=ast;lod=ald; expression(symsetadd(rmparen,fsys),lev,tx); if(rmparen=sym) getsym(); else error(35); if(cursym=inc) gen(lit,0,1); else gen(lit,0,-1); gen(acp,set=ast,1); gen(lod,lev-tablei.vp.level,tablei.vp.adr); gen(opr,0,2); gen(set,lev-tablei.vp.level,tablei.vp.adr); gen(acp,set=ast,-1); gen(lod,lev-tablei.vp.level,tablei.vp.adr); else error(11); /if(sym=ident) else error(23);2、在语句处理分程序:case ident:i=position(id,tx); getsym();if (i=0) error(11);else if (tablei.kind!=variable) /*assignment to non-variable*/error(12); i=0; else vstyle=tablei.style; if(sym=lmparen) getsym(); set=ast;lod=ald; expression(symsetadd(rmparen,fsys),lev,tx); if(rmparen=sym) getsym(); else error(35); switch(sym) case becomes: getsym(); expression(fsys,lev,tx); if (i=0) error(11);/gen(set,lev-tablei.vp.level,tablei.vp.adr); break; case append: getsym(); expression(fsys,lev,tx); if (i!=0) gen(acp,set=ast,1); gen(lod,lev-tablei.vp.level,tablei.vp.adr); gen(opr,0,2); /gen(set,lev-tablei.vp.level,tablei.vp.adr); break; case reduce: getsym(); expression(fsys,lev,tx); if (i!=0) gen(acp,set=ast,1); gen(lod,lev-tablei.vp.level,tablei.vp.adr); gen(opr,0,3); gen(opr,0,1); /gen(set,lev-tablei.vp.level,tablei.vp.adr); break; case inc: getsym(); if (i!=0) gen(lit,0,1); gen(acp,set=ast,1); gen(lod,lev-tablei.vp.level,tablei.vp.adr); gen(opr,0,2); /gen(set,lev-tablei.vp.level,tablei.vp.adr); break; case dec: getsym(); if (i!=0) gen(lit,0,-1); gen(acp,set=ast,1); gen(lod,lev-tablei.vp.level,tablei.vp.adr); gen(opr,0,2); /gen(set,lev-tablei.vp.level,tablei.vp.adr); break; default: error(13);break; gen(set,lev-tablei.vp.level,tablei.vp.adr);break;测试程序:incdec程序:program testelse;var a,b,c,d,e,f,g;begina:=5;f:=0;g:=0;b:=a+;c:=+a;d:=a-;e:=-a;f+=a;g-=a;println(a,b,c,d,e,f,g);end.测试结果:= compile pl0 = 0 program testelse; 0 var a,b,c,d,e,f,g; 1 begin 2 a:=5; 4 f:=0; 6 g:=0; 8 b:=a+; 18 c:=+a; 26 d:=a-; 36 e:=-a; 44 f+=a; 49 g-=a; 55 println(a,b,c,d,e,f,g); 70 end. 0 jmp 0 1 1 ini 0 10 2 lit 0 5 3 sto 0 3 4 lit 0 0 5 sto 0 8 6 lit 0 0 7 sto 0 9 8 acp 0 0 9 lod 0 3 10 lit 0 1 11 opr 0 2 12 sto 0 3 13 acp 0 -1 14 lod 0 3 15 lit 0 -1 16 opr 0 2 17 sto 0 4 18 lit 0 1 19 acp 0 1 20 lod 0 3 21 opr 0 2 22 sto 0 3 23 acp 0 -1 24 lod 0 3 25 sto 0 5 26 acp 0 0 27 lod 0 3 28 lit 0 -1 29 opr 0 2 30 sto 0 3 31 acp 0 -1 32 lod 0 3 33 lit 0 1 34 opr 0 2 35 sto 0 6 36 lit 0 -1 37 acp 0 1 38 lod 0 3 39 opr 0 2 40 sto 0 3 41 acp 0 -1 42 lod 0 3 43 sto 0 7 44 lod 0 3 45 acp 0 1 46 lod 0 8 47 opr 0 2 48 sto 0 8 49 lod 0 3 50 acp 0 1 51 lod 0 9 52 opr 0 3 53 opr 0 1 54 sto 0 9 55 lod 0 3 56 opr 0 14 57 lod 0 4 58 opr 0 14 59 lod 0 5 60 opr 0 14 61 lod 0 6 62 opr 0 14 63 lod 0 7 64 opr 0 14 65 lod 0 8 66 opr 0 14 67 lod 0 9 68 opr 0 14 69 opr 0 15 70 opr 0 0 run pl0 5 5 7 7 5 5 -5 end pl0 b、for语句:修改statement就能实现for语句的扩充,代码如下:case forsym: / for := to do / for := downto do getsym(); fsys=symsetunion(symsetnew(dosym,tosym,downtosym),fsys); if(sym=ident) i=position(id,tx); if( i!=0) getsym(); if(becomes=sym) getsym(); expression(fsys,lev,tx); gen(sto,lev-tablei.vp.level,tablei.vp.adr); if(tosym=sym|downtosym=sym) tmpsym=sym; getsym(); expression(fsys,lev,tx); if(dosym=sym) getsym(); tmpaddr=1; gen(stp,1,tmpaddr); /循环体无条件回跳到这里重新判断循环条件 cx1=cx; /循环体条件判断码的生成 switch(tmpsym) case tosym: gen(lod,lev-tablei.vp.level,tablei.vp.adr); gen(gtp,0,tmpaddr); step=1; break; case downtosym: gen(gtp,0,tmpaddr); gen(lod,lev-tablei.vp.level,tablei.vp.adr); step=-1; break; default: error(8); gen(opr,0,10); / 栈顶:原(次栈顶 statement(fsys,lev,tx); / gen(lod,lev-tablei.vp.level,tablei.vp.adr); gen(lit,0,step); gen(opr,0,2); gen(sto,lev-tablei.vp.level,tablei.vp.adr); /imax) error(31); num=0; tabletx.val=num; else error(34); break; case variable: getsym(); if(lmparen=sym) getsym(); if(sym=number&num+dxamax) tabletx.vp.size=num; tabletx.vp.adr=dx; dx+=num; / newarray(num,dx); getsym(); if(rmparen!=sym)error(35); else getsym(); /数组的处理 else error(36); else tabletx.vp.level=lev; tabletx.vp.adr=dx; tabletx.vp.size=0; /0在这里只是用来标识变量a和数组a1的差别 dx+; break;case procedur: tabletx.vp.level=lev; break; /*enter*/其它代码大部分也有涉及,为了能够使数组和一般变量一样参加运算,需要对其偏移地址进行计算,一般偏移地址计算后都会放在栈顶,处理这个偏移量成了一个问题,主要有:如何让赋值左边的数组的偏移量不被先计算的赋值式右边的数组偏移量所替代,因此在存储上我的思路是:将偏移量放在栈顶先不处理,等到要赋值到数组元素的地址时,有两种操作:ald和ast,ald根据栈顶这个便宜量+数组基址取得值放在这个顶上,此时偏移量被冲走;ast是栈顶为表达式算出的值,次栈顶为偏移量,将栈顶的值根据次栈顶的偏移量赋到正确的位置(有一个操作用于协助这两个操作:acp)。下面是这三个操作的具体代码:case acp: if(i.l!=0) st+1=st-i.a; t+; break; case ald: st=sbase(i.l,b,s)+i.a+st; break; case ast: sbase(i.l,b,s)+i.a+st-1=st; t-=2; break;对这三个操作的应用在因子,语句中的输入,变量中;因为时间不足,没有实现数组的总体赋值a2=1,2这种形式,只能单个赋值。没有边界判断。测试程序:program ex01;var a,b2,c;var d10;begin b0:=1;

温馨提示

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

最新文档

评论

0/150

提交评论