




已阅读5页,还剩113页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第2章PL/0编译程序的实现,本章目的:以PL/0编译程序为实例,学习编译程序实现的基本步骤和相关技术1PL/0编译程序的结构2PL/0编译程序的分析工作(词法,语法和语义)实现3PL/0编译程序的错误处理方法4目标代码生成和类pcode代码解释器,1.PL/0编译程序的结构,PL/0编译程序,PL/0语言程序,类pcode代码,源语言(PL/0)目标语言(类pcode)实现语言(pascal/C),PL/0,类pcode,pascal/C,PL/0编译程序,类pcode解释程序,类pcode代码,PL/0源程序,输入数据,输出数据,PL/0编译系统的结构框架,PL/0语言,PL/0语言:PASCAL语言的子集PL/0程序示例PL/0的语法描述图PL/0语言的EBNF表示,PL/0程序示例,CONSTA=10;(*常量说明部分*)VARB,C;(*变量说明部分*)PROCEDUREP;(*过程说明部分*)VARD;(*P的局部变量说明部分*)PROCEDUREQ;(*P的局部过程说明部分*)VARX;BEGINREAD(X);D:=X;WHILEX#0DOCALLP;END;BEGINWRITE(D);CALLQ;END;BEGINCALLP;END.,Q过程体,p过程体,主程序体,输入圆柱的半径和高,计算一些面积、体积等,varr,h,len,a1,a2,volumn;beginread(r);read(h);len:=2*3*r;a1:=3*r*r;a2:=a1+a1+len*h;volumn:=a1*h;write(len);write(a1);write(a2);write(volumn);end.,计算最大公约数,varm,n,r,q;计算m和n的最大公约数proceduregcd;beginwhiler#0dobeginq:=m/n;r:=m-q*n;m:=n;n:=r;endend;,beginread(m);read(n);为了方便,规定m=nifm0thenbeginfact:=fact*m;m:=m-1;callfactorial;end;end;,begin读入nread(n);sum:=0;whilen0dobeginm:=n;fact:=1;callfactorial;sum:=sum+fact;n:=n-1;end;输出n!write(sum);end.,程序,分程序,.,内的文字表示语法成分(短语),或,内的文字表示单词符号,程序,.,内的文字表示语法成分(短语),语法图,const,ident,number,var,ident,procedure,ident,分程序,语句,分程序,PL/0语言的EBNF表示,构成EBNF的元素(非终结符,终结符,开始符,规则)EBNF的元符号:用左右尖括号括起来的内容为非终结符=读做定义为=的左部由右部定义读做定义为的左部由右部定义|读做或表示右部候选内容表示花括号内的内容可重复任意次或限定次数表示方括号内的内容为任选项()表示圆括号内的内容优先,例:用EBNF描述的定义:=+|-=0|1|2|3|4|5|6|7|8|9或=+|-|0=1|2|3|4|5|6|7|8|9=0|,PL/0语言是PASCAL语言的子集,同PASCAL作用域规则(内层可引用包围它的外层定义的标识符),上下文约束,过程可嵌套定义,可递归调用子集数据类型,只有整型数据结构,只有简变和常数数字最多为14位标识符的有效长度是10语句种类过程无参,最多可嵌套三层,目标代码类p-code,目标代码类p-code是一种栈式机的汇编语言。栈式机系统结构:没有累加器和寄存器,只有存储栈指针所有运算都在栈顶(零地址机)指令格式:,fla,f功能码l层次差(标识符引用层减去定义层)a根据不同的指令有所区别,指令功能表,consta=10;varb,c;procedurep;beginc:=b+a;end;beginread(b);whileb#0dobegincallp;write(2*c);read(b);endend.,(0)jmp08转向主程序入口(1)jmp02转向过程p入口(2)int03过程p入口,为过程p开辟空间(3)lod13取变量b的值到栈顶(4)lit010取常数10到栈顶(5)opr02次栈顶与栈顶相加(6)sto14栈顶值送变量c中(7)opr00退栈并返回调用点(16)(8)int05主程序入口开辟5个栈空间(9)opr016从命令行读入值置于栈顶(10)sto03将栈顶值存入变量b中(11)lod03将变量b的值取至栈顶(12)lit00将常数值0进栈(13)opr09次栈顶与栈顶是否不等(14)jpc024等时转(24)(条件不满足转)(15)cal02调用过程p(16)lit02常数值2进栈(17)lod04将变量c的值取至栈顶(18)opr04次栈顶与栈顶相乘(2*c)(19)opr014栈顶值输出至屏幕(20)opr015换行(21)opr016从命令行读取值到栈顶(22)sto03栈顶值送变量b中(23)jmp011无条件转到循环入口(11)(24)opr00结束退栈,PL/0编译程序的结构,词法分析程序,语法语义分析程序,代码生成程序,表格管理程序,出错处理程序,PL/0源程序,目标程序,PL/0编译程序的总体设计,以语法、语义分析程序为核心词法分析程序和代码生成程序都作为一个过程,当语法分析需要读单词时就调用词法分析程序,而当语法、语义分析正确,需要生成相应的目标代码时,则调用代码生成程序。表格管理程序实现变量,常量和过程标识符的信息的登录与查找。出错处理程序,对词法和语法、语义分析遇到的错误给出在源程序中出错的位置和与错误性质有关的编号,并进行错误恢复。,第2章PL/0编译程序,本章目的:以PL/0编译程序为实例,学习编译程序实现的基本步骤和相关技术1PL/0编译程序的结构2PL/0编译程序的分析工作(词法,语法和语义)实现3PL/0编译程序的错误处理方法4目标代码生成和类pcode代码解释器,2PL/0编译程序的分析工作(词法,语法和语义)2.1PL/0编译程序词法分析的实现,识别的单词:保留字或关键字:如:BEGIN、END、IF、THEN等运算符:如:+、-、*、/、:=、#、=、amax)error(31);/*数越界*/num=0;table(*ptx).val=num;break;,过程ENTER的实现(C),casevariable:/*变量名字*/table(*ptx).level=lev;table(*ptx).adr=(*pdx);(*pdx)+;break;caseprocedur:/*过程名字*/table(*ptx).level=lev;break;,过程ENTER的实现,tx:table表的指针procedureenter(k:object);begin(*enterobjectintotable*)tx:=tx+1;withtabletxdo(*开域语句*)beginname:=id;(*表示:=id;*)kind:=k;(*表示tabletx.kind:=k;*),过程ENTER的实现,casekofconstant:beginifnumamaxthenbeginerror(31);num:=0;end;val:=num;(*tabletx.val:=num;*)end;,过程ENTER的实现,variable:beginlevel:=lev;(*表示tabletx.level:=lev*)adr:=dx;(*表示tabletx.adr:=dx*)dx:=dx+1;end;procedur:level:=lev(*表示tabletx.level:=lev;*)end(*case*);endend(*enter*);,过程体的处理,/*编译程序主体*lev:当前分程序所在层*tx:名字表当前尾指针*fsys:当前模块后跟符号集合*/intblock(intlev,inttx,bool*fsys),过程体的处理,./main()函数if(-1=block(0,0,nxtlev).if(sym!=period)error(9);.interpret();/*调用解释执行程序*/.,过程体的处理,while(sym=procsym)/block()函数getsymdo;if(sym=ident)enter(procedur,.if(-1=block(lev+1,tx,nxtlev),过程体的处理变量引用的处理,对语句进行语法分析语义分析当遇到标识符的引用时就调用POSITION函数查TABLE表,看是否有过正确定义,若已有,则从表中取相应的有关信息,供代码的生成使用。若无定义则错。语义分析TABLE表若已有过正确定义,检查引用与说明的属性是否一致,若不一致则错。当语法语义正确时,就生成相应语句功能的目标代码,赋值语句的处理(C),if(sym=ident)/*准备按照赋值语句处理*/i=position(id,*ptx);if(i=0)error(11);/*变量未找到*/elseif(tablei.kind!=variable)error(12);/*赋值语句格式错误*/i=0;else.gendo(sto,lev-tablei.level,tablei.adr);.,赋值语句的处理,ifsym=identthenbegini:=position(id);ifi=0thenerror(11)elseiftablei.kindvariablethenbeginerror(12);i:=0end;getsym;ifsym=becomesthengetsymelseerror(13);expression(fsys);ifi0thenwithtableidogen(sto,lev-level,adr)end,第2章PL/0编译程序,本章目的:以PL/0编译程序为实例,学习编译程序实现的基本步骤和相关技术1PL/0编译程序的结构2PL/0编译程序的分析工作(词法,语法和语义)实现3PL/0编译程序的错误处理方法4目标代码生成和类pcode代码解释器,编译程序的错误处理,错误处理的原则:尽可能准确指出出错位置,错误性质,尽可能进行校正。PL/0编译程序对语法错误的处理:(1)对于易于校正的错误,如丢了逗号,分号等,指出出错位置,加以校正,继续进行分析。(2)对于难于校正的错误,给出错误的位置与性质,跳过后面的一些单词,直到下一个可以进行正常语法分析的语法单位。,在进入某个语法单位时,调用TEST,检查当前符号是否属于该语法单位的开始符号集合。若不属于,则滤去开始符号和后跟符号集合外的所有符号。在语法单位分析结束时,调用TEST,检查当前符号是否属于调用该语法单位时应有的后跟符号集合。若不属于,则滤去后跟符号和开始符号集合外的所有符号。,TESTTEST,开始符号集合与后跟符号集合,开始符号集合symset=setofsymbol;declbegsys,statbegsys,facbegsys:symset;开始符号集合(*主程序*)declbegsys:=constsym,varsym,procsym;statbegsys:=beginsym,callsym,ifsym,whilesym,readsym,writesym;facbegsys:=ident,number,lparen;,后跟符号集合fsys作为参数:proceduretest(s1,s2:symset;n:integer);procedureblock(lev,tx:integer;fsys:symset);procedurestatement(fsys:symset);procedureexpression(fsys:symset);procedureterm(fsys:symset);procedurefactor(fsys:symset);,READ语句的分析处理(C),if(sym=readsym)/处理read语句getsymdo;if(sym!=lparen)error(34);/格式错误,应是左括号elsedogetsymdo;,READ语句的语法语义分析处理,ifsym=readsymthenbegingetsym;ifsymlparenthenerror(34)elserepeatgetsym;,READ语句的语法语义分析处理,ifsym=identtheni:=position(id)elsei:=0;ifi=0thenerror(35)elsewithtableidobegingen(opr,0,16);gen(sto,lev-level,adr)end;,READ语句的语法语义分析处理,getsymuntilsymcomma;ifsymrparenthenbeginerror(33);whilenot(syminfsys)dogetsymendelsegetsymend,出错处理跳过不应出现的符号,正确出口,TEST,SYM在S1中?,打印出错编号n,S1:=S1+S2,SYM在S1中?,GETSYM,返回,Y,Y,N,N,TEST测试过程流程图,因子的处理过程,例:因子的处理过程procedurefactor(fsys:symset);vari:integer;begin入口:test(facbegsys,fsys,24);whilesyminfacbegsysdobeginif.出口:test(fsys,facbegsys,23);endend;,因子的处理过程,Facbegsys,y,处理identnumber,lparen,test,n,test,增加后跟符与调用位置有关例:调用expression(fsys);write语句的语法write(,);write语句(后调用expression时后跟符expression(rparen,comma+fsys);factor的语法:factor=.|(exp)在factor(后调用expression时后跟符expression(rparen+fsys);,第2章PL/0编译程序,本章目的:以PL/0编译程序为实例,学习编译程序实现的基本步骤和相关技术1PL/0编译程序的结构2PL/0编译程序的分析工作(词法,语法和语义)实现3PL/0编译程序的错误处理方法4目标代码生成和类pcode代码解释器,代码生成,代码生成是由过程GEN完成。GEN有3个参数,分别代表目标代码的功能码,层差和位移量。例如gen(opr,0,16);gen(sto,lev-level,adr)lev:当前处理的过程层次level:被引用变量或过程所在层次CX:为目标代码code数组的下标指针,代码结构变换,地址返填,Ifcthensgetsym;condition;ifsym=thensymthengetsymelseerror(16);cx1:=cx;gen(jpc,0,0)statement();codecx1.a:=cx,类pcode代码解释器的实现,类pcode目标机结构目标代码解释执行时数据栈的布局(运行栈的存储分配),目标代码类p-code,目标代码类p-code是一种栈式机的汇编语言。栈式机系统结构:没有累加器和寄存器,只有存储栈指针所有运算都在栈顶(零地址机)指令格式:,fla,f功能码l层次差(标识符引用层减去定义层)a根据不同的指令有所区别,类pcode解释器的结构,目标代码(指令)存放在数组CODE中(程序地址寄存器p)。解释程序定义一个一维整型数组S作为运行栈栈顶寄存器(指针)t,基址寄存器(指针)b,指令寄存器i(当前正在解释的目标指令),consta=10;varb,c;procedurep;beginc:=b+a;end;beginread(b);whileb#0dobegincallp;write(2*c);read(b);endend.,(0)jmp08转向主程序入口(1)jmp02转向过程p入口(2)int03过程p入口,为过程p开辟空间(3)lod13取变量b的值到栈顶(4)lit010取常数10到栈顶(5)opr02次栈顶与栈顶相加(6)sto14栈顶值送变量c中(7)opr00退栈并返回调用点(16)(8)int05主程序入口开辟5个栈空间(9)opr016从命令行读入值置于栈顶(10)sto03将栈顶值存入变量b中(11)lod03将变量b的值取至栈顶(12)lit00将常数值0进栈(13)opr09次栈顶与栈顶是否不等(14)jpc024等时转(24)(条件不满足转)(15)cal02调用过程p(16)lit02常数值2进栈(17)lod04将变量c的值取至栈顶(18)opr04次栈顶与栈顶相乘(2*c)(19)opr014栈顶值输出至屏幕(20)opr015换行(21)opr016从命令行读取值到栈顶(22)sto03栈顶值送变量b中(23)jmp011无条件转到循环入口(11)(24)opr00结束退栈,目标代码解释执行时数据栈的布局(运行栈的存储分配),在每个过程调用时在栈顶分配3个联系单元:SL:静态链,指向定义该过程的直接外过程(或主程序)运行时最新数据段的基地址。DL:动态链,指向调用该过程前正在运行过程的数据段基地址。RA:返回地址,记录调用该过程时目标程序的断点,即调用过程指令的下一条指令的地址。,Varx,y;ProcedureP;vara;procedureQ;varb;begin(*Q*)b:=10;end(*Q*);procedureS;varc,d;procedureR;vare,f;begin(*R*)callQ;end(*R*);,begin(*S*)callR;end(*S*);begin(*P*)callS;end;(*P*)begin(*MAIN*)callP;end(*MAIN*).,目标代码的解释执行运行栈S,M调用过程PM调用过程PP调用过程S,RADLSL,b,t,t,b,P,M,P,M,S,目标代码的解释执行,几条特殊指令在code中的位置和功能INT0A在过程目标程序的入口处,开辟A个单元的数据段。A为局部变量的个数+3。OPR00在过程目标程序的出口处,释放数据段(退栈),恢复调用该过程前正在运行的过程的数据段基址寄存器B和栈顶寄存器T的值,并将返回地址送到指令地址寄存器P中,以使调用前的程序从断点开始继续执行。,目标代码的解释执行,几条特殊指令在code中的位置和功能CALLA调用过程,还完成填写静态链、动态链、返回地址,给出被调用过程的基地址值,送入基址寄存器B中,目标程序的入口地址A的值送指令地址寄存器P中,使指令从A开始执行。,CX:为目标代码code数组的下标指针。code为一维数组,数组元素为记录型数据。每一个记录就是一条目标指令。CX为整数变量,由0开始顺序增加。实际上目标代码的顺序是内层过程的在前边,主程序的目标代码在最后。tx:table表的下标指针,是以值参数形式使用的。dx:计算每个变量在运行栈中相对本过程基地址的偏移量,放在table表中的adr域,生成目标代码时再放在code中的a域。,下标指针cx,tx和变量dx的作用,codecxtabletxst(运行栈)cxtxt(运行时栈指针),(0)jmp00(1)int07.(cx).,(0)nameadr.(1)b(dx).(tx),q,p,m,b,Table表的下标指针tx补充说明:,主程序,BLOCK,第1次调用blockBLOCK(0,0,),0,0,.,BLOCK,BLOCK(LEV+1,TX,)(递归进入分程序),LEV,tx,LEV,tx,(6),6(9),1,tx是BLOCK的实际值参,PL/0编译程序的实现,proceduregen(x:fct;y,z:integer);beginifcxcxmaxthen(*指针越界*)beginwrite(programtoolong);close(fin);(*关闭文件*)writeln;exitend;,PL/0编译程序的实现,withcodecxdobeginf:=x;(*表示codecx.f:=x;*)l:=y;(*表示codecx.l:=y;*)a:=z;(*表示codecx.a:=z;*)end;cx:=cx+1end(*gen*);,PL/0编译程序的实现,对分程序的定义(见教材417,437页)procedureblock(lev,tx:integer;fsys:symset);vardx:integer;(*dataallocationindex*)tx0:integer;(*initialtableindex*)cx0:integer;(*initialcodeindex*)(tx0,cx0是tx,cx的初值),PL/0编译程序的实现,对分程序体人口的处理(见程序文本block的过程体)begin(*block*)dx:=3;tx0:=tx;(保留当前table表指针值)tabletx.adr:=cx;(保留当前code指针值到过程名的adr域)gen(jmp,0,0);(生成转向过程体入口的指令,该指令的地址为cx已保留在过程名的adr域,等生成过程体入口的指令时,再由tabletx.adr中取出cx将过程体入口返填到cx中,即(jmp,0,0)的第3区域。(注意dx,tx,cx的作用),CONSTA=35,B=49;VARC,D,E;PROCEDUREP;VARG,table表格管理,名字类型层次/值地址存储空间,(0)jmp00CX(1)jmp00.,记录过程在code的入口到table中的adr域,PL/0编译程序的实现,过程体入口时的处理codetabletx0.adr.a:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论