PL0源代码(C语言版)

上传人:z**** 文档编号:69497988 上传时间:2022-04-05 格式:DOC 页数:28 大小:214.50KB
收藏 版权申诉 举报 下载
PL0源代码(C语言版)_第1页
第1页 / 共28页
PL0源代码(C语言版)_第2页
第2页 / 共28页
PL0源代码(C语言版)_第3页
第3页 / 共28页
资源描述:

《PL0源代码(C语言版)》由会员分享,可在线阅读,更多相关《PL0源代码(C语言版)(28页珍藏版)》请在装配图网上搜索。

1、#definenorw13/anumberofreservedword/*关键字个数*/#definetxmax100/lengthofidentifiertable/*名字表容量*/#definenmax14/maxnumberofdigitsinnumbers/*number的最大位数#defineal10/lengthofidentifier/*符号的最大长度*/#defineamax2047/maximumaddress/*地址上界*/#definelevmax3/maxdepthofblocknesting/*最大允许过程嵌套声明层数0,lexmax*/#definecxmax200

2、/sizeofcodearray/*最多的虚拟机代码数*/*符号*/enumsymbolnul,ident,number,plus,minus,/*PL/0编译系统C版本头文件pl0.h*/*/oddsym,eql,gtr,times,slash,lss,leq,than;lparen:leftparenthesisrparen,comma,semicolon,period,becomes赋值号geq,neq,/slash斜线lparen,/leq:lessthanorequalto;gtr:greatbecomes,/comma逗号semicolon分号period句号beginsym,en

3、dsym,ifsym,thensym,whilesym,writesym,readsym,dosym,callsym,constsym,varsym,procsym,;#definesymnum32/*/enumobject/object为三种标识符的类型constant,variable,procedur,;/*/enumfct/fct类型分别标识类PCODE的各条指令lit,opr,lod,sto,cal,inte,jmp,jpc,/书本P23;#definefctnum8/*/structinstruction/指令enumfctf;/功能码intl;/层次差inta;l/P23;FIL

4、E*fas;/输出名字表FILE*fa;/输出虚拟机代码FILE*fa1;/输出源文件及其各行对应的首地址FILE*fa2;/输出结果booltableswitch;boollistswitch;charch;enumsymbolsym;charidal+1;intnum;/显示名字表与否/显示虚拟机代码与否/获取字符的缓冲区,getch使用/当前符号/当前ident,多出一个子节用于存放0/当前numberintcc,ll;intcx;charline81;/getch使用的计数器,cc表示当前子符(ch)的位置/虚拟机代码指针,取值范围0,cxmax-1/读取行缓冲区charaal+1;/

5、临时符号,多出的一个字节用于存放0structinstructioncodecxmax;charwordnorwal;enumsymbolwsymnorw;enumsymbolssym256;charmnemonicfctnum5;booldeclbegsyssymnum;boolstatbegsyssymnum;boolfacbegsyssymnum;/*/structinstructioncodecxmax;charwordnorwal;enumsymbolwsymnorw;enumsymbolssym256;charmnemonicfctnum5;booldeclbegsyssymnum

6、;boolstatbegsyssymnum;boolfacbegsyssymnum;/*/structtablestructcharnameal;enumobjectkind;intval;intlevel;intadr;intsize;用*/存放虚拟机代码的数组/保留字/保留字对应的符号值/单字符的符号值/虚拟机代码指令名称/表示声明开始的符号集合,declaringbeginsymbolset/表示语句开始的符号集,statement/表示因子开始的符号集合,factor/*名字*/*类型:const,var,arrayorprocedure*/*数值,仅const使用*/*所处层,仅co

7、nst不使用*/*地址,仅const不使用*/*需要分配的数据区空间,仅procedure使;structtablestructtabletxmax;/*名字表*/FILE*fin;/fin文本文件用于指向输入的源程序文件FILE*fout;/fout文本文件用于指向输出的文件charfnameal;interr;/*错误计数器*/*当函数中会发生fatalerror时,返回一1告知调用它的函数,最终退出程序*/#definegetsymdo#definegetchdo#definetestdo(a,b,c)#definegendo(a,b,c)#defineexpressiondo(a,b,

8、c)#definegetsymdo#definegetchdo#definetestdo(a,b,c)#definegendo(a,b,c)#defineexpressiondo(a,b,c)#definefactordo(a,b,c)#definetermdo(a,b,c)#defineconditiondo(a,b,c)#definestatementdo(a,b,c)if(-1=getsym()return-1if(-1=getch()return-1if(-1=test(a,b,c)return-1if(-1=gen(a,b,c)return-1if(-1=expression(a,b

9、,c)return-1if(-1=factor(a,b,c)return-1if(-1=term(a,b,c)return-1if(-1=condition(a,b,c)return-1if(-1=statement(a,b,c)return-1#defineconstdeclarationdo(a,b,c)if(-1=constdeclaration(a,b,c)return-1#definevardeclarationdo(a,b,c)if(-1=vardeclaration(a,b,c)return-1voiderror(intn);intgetsym();intgetch();void

10、init();intgen(enumfctx,inty,intz);inttest(bool*s1,bool*s2,intn);intinset(inte,bool*s);intaddset(bool*sr,bool*s1,bool*s2,intn);intsubset(bool*sr,bool*s1,bool*s2,intn);intmulset(bool*sr,bool*s1,bool*s2,intn);intblock(intlev,inttx,bool*fsys);voidinterpret();intfactor(bool*fsys,int*ptx,intlev);intterm(b

11、ool*fsys,int*ptx,intlev);intcondition(bool*fsys,int*ptx,intlev);intexpression(bool*fsys,int*ptx,intlev);intstatement(bool*fsys,int*ptx,intlev);voidlistcode(intcx0);intvardeclaration(int*ptx,intlev,int*pdx);intconstdeclaration(int*ptx,intlev,int*pdx);intposition(char*idt,inttx);voidenter(enumobjectk,

12、int*ptx,intlev,int*pdx);intbase(intl,int*s,intb);/A.2C版本/*编译和运行环境:*1VisualC+6.0,VisualC+.NETandVisualC+.NET2003*WinNT,Win200,WinXPandWin2003*2gccversion(RedHatLinux*RedhatFedoracore1*Intel32platform*使用方法:*运行后输入PL/0源程序文件名*回答是否输出虚拟机代码*回答是否输出名字表*fa.tmp输出虚拟机代码*fa1.tmp输出源文件及其各行对应的首地址*fa2.tmp输出结果*fas.tmp输

13、出名字表*/#include#includepl0.h#includestring.h/*解释执行时使用的栈*/#definestacksize500intmain()boolnxtlevsymnum;printf(Inputpl/0file?);scanf(%s,fname);/*输入文件名*/fin=fopen(fname,r);/返回值:文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno中if(fin)printf(Listobjectcode?(Y/N);scanf(%s,fname);listswitch=(fname0=y|fn

14、ame0=Y);printf(Listsymboltable?(Y/N);scanf(%s,fname);tableswitch=(fname0=y|fname0=Y);fa1=fopen(fa1.tmp,w);fprintf(fa1,Iputpl/0file?);fprintf(fa1,%sn,fname);init();err=0;/*是否输出虚拟机代码*/*是否输出名字表*/*初始化*/错误计数器置0cc=cx=ll=0;ch=;if(-1!=getsym()fa=fopen(fa.tmp,w);fas=fopen(fas.tmp,w);addset(nxtlev,declbegsys,

15、statbegsys,symnum);nxtlevperiod=true;if(-1=block(0,0,nxtlev)fclose(fa);fclose(fa1);fclose(fas);fclose(fin);printf(n);return0;fclose(fa);fclose(fa1);fclose(fas);if(sym!=period)/*调用编译程序*/error(9);if(err=0)fa2=fopen(fa2.tmp,w);interpret();fclose(fa2);elseprintf(Errorsinpl/0program);fclose(fin);elseprin

16、tf(Cantopenfile!n);printf(n);return0;/*初始化*/voidinit()inti;for(i=0;i=255;i+)ssymi=nul;/ssym:单字符的符号值ssym+=plus;ssym-=minus;ssym*=times;ssym/=slash;ssym(=lparen;ssym)=rparen;ssym=eql;ssym,=comma;ssym.=period;ssym#=neq;ssym;=semicolon;/*设置保留字名字,按照字母顺序,便于折半查找*/strcpy(&(word00),begin);strcpy(&(word10),ca

17、ll);strcpy(&(word20),const);strcpy(&(word30),do);strcpy(&(word40),end);strcpy(&(word50),if);strcpy(&(word60),odd);strcpy(&(word70),procedure);strcpy(&(word80),read);strcpy(&(word90),then);strcpy(&(word100),var);strcpy(&(word110),while);strcpy(&(word120),write);/*设置保留字符号*/wsym0=beginsym;wsym1=callsym

18、;wsym2=constsym;wsym3=dosym;wsym4=endsym;wsym5=ifsym;wsym6=oddsym;wsym7=procsym;wsym8=readsym;wsym9=thensym;wsym10=varsym;wsym11=whilesym;wsym12=writesym;/*设置指令名称*/strcpy(&(mnemoniclit0),lit);strcpy(&(mnemonicopr0),opr);strcpy(&(mnemoniclod0),lod);strcpy(&(mnemonicsto0),sto);strcpy(&(mnemoniccal0),c

19、al);strcpy(&(mnemonicinte0),int);strcpy(&(mnemonicjmp0),jmp);strcpy(&(mnemonicjpc0),jpc);/*设置符号集*/for(i=0;isymnum;i+)declbegsysi=false;statbegsysi=false;facbegsysi=false;/*设置声明开始符号集*/declbegsysconstsym=true;declbegsysvarsym=true;declbegsysprocsym=true;/*设置语句开始符号集*/statbegsysbeginsym=true;statbegsysc

20、allsym=true;statbegsysifsym=true;statbegsyswhilesym=true;/*设置因子开始符号集*/facbegsysident=true;facbegsysnumber=true;facbegsyslparen=true;/*用数组实现集合的集合运算*/intinset(inte,bool*s)returnse;intaddset(bool*sr,bool*s1,bool*s2,intn)inti;for(i=0;in;i+)sri=s1i|s2i;return0;intsubset(bool*sr,bool*s1,bool*s2,intn)inti;

21、for(i=0;in;i+)sri=s1i&(!s2i);return0;intmulset(bool*sr,bool*s1,bool*s2,intn)inti;for(i=0;i=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

22、=becomes;getchdo;elsesym=nul;/*不能识别的符号*/elseif(ch=)/*检测大于或大于等于符号*/getchdo;if(ch=)sym=geq;getchdo;elsesym=gtr;else处理*/处理*/sym=ssymch;/*当符号不满足上述条件时,全部按照单字符号/getchdo;/richardif(sym!=period)getchdo;/endrichardreturn0;/*生成虚拟机代码*x:instruction.f;*y:instruction.l;*z:instruction.a;*/intgen(enumfctx,inty,intz

23、)if(cx=cxmax)printf(Programtoolong);/*程序过长*/return-1;codecx.f=x;codecx.l=y;codecx.a=z;cx+;return0;/*测试当前符号是否合法*在某一部分(如一条语句,一个表达式)将要结束时时我们希望下一个符号属于某集合*(该部分的后跟符号)test负责这项检测,并且负责当检测不通过时的补救措施*程序在需要检测时指定当前需要的符号集合和补救用的集合(如之前未完成部分的后跟*符号),以及不通过时的错误号*S1:我们需要的符号*s2:如果不是我们需要的,则需要一个补救用的集合*n:错误号*/inttest(bool*s1

24、,bool*s2,intn)if(!inset(sym,s1)error(n);/*当检测不通过时,不停获取符号,直到它属于需要的集合或补救的集合*/while(!inset(sym,s1)&(!inset(sym,s2)getsymdo;return0;/*编译程序主体*lev:当前分程序所在层*tx:名字表当前尾指针*fsys:当前模块后跟符号集合*/intblock(intlev,inttx,bool*fsys)inti;intdx;inttx0;intcx0;boolnxtlevsymnum;使用数组上级函数的/*名字分配到的相对地址*/*保留初始tx*/*保留初始cx*/*在下级函数

25、的参数中,符号集合均为值参,但由于实现,传递进来的是指针,为防止下级函数改变集合,开辟新的空间传递给下级函数*/dx=3;tx0=tx;/*记录本层名字的初始位置*/tabletx.adr=cx;gendo(jmp,0,0);if(levlevmax)error(32);doif(sym=constsym)/*收到常量声明符号,开始处理常量声明*/getsymdo;do的值会被constdeclaration改变,constdeclarationdo(&tx,lev,&dx);/*dx使用指针*/while(sym=comma)getsymdo;constdeclarationdo(&tx,l

26、ev,&dx);if(sym=semicolon)getsymdo;elseerror(5);/*漏掉了逗号或者分号*/while(sym=ident);if(sym=varsym)/*收到变量声名符号,开始处理变量声名*/getsymdo;dovardeclarationdo(&tx,lev,&dx);while(sym=comma)getsymdo;vardeclarationdo(&tx,lev,&dx);if(sym=semicolon)getsymdo;elseerror(5);while(sym=ident);while(sym=procsym)/*收到过程声名符号,开始处理过程声

27、名*/getsymdo;if(sym=ident)enter(procedur,&tx,lev,&dx);/*记录过程名字*/getsymdo;elseerror(4);/*procedure后应为标识符*/if(sym=semicolon)getsymdo;elseerror(5);/*漏掉了分号*/memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevsemicolon=true;if(-1=block(lev+1,tx,nxtlev)return-1;/*递归调用*/if(sym=semicolon)getsymdo;memcpy(nxtlev,st

28、atbegsys,sizeof(bool)*symnum);nxtlevident=true;nxtlevprocsym=true;testdo(nxtlev,fsys,6);else/*漏掉了分号*/*漏掉了分号*/error(5);memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);nxtlevident=true;nxtlevperiod=true;testdo(nxtlev,declbegsys,7);/*直到没有声明符号*/*开始生成当前过程代码*/*当前过程代码地址*/*声明部分中每增加一条声明都会给size*/while(inset(sym

29、,declbegsys);codetabletx0.adr.a=cx;tabletx0.adr=cx;tabletx0.size=dx;dx增加1,声明部分已经结束,dx就是当前过程数据的cx0=cx;gendo(inte,0,dx);if(tableswitch)printf(TABLE:n);if(tx0+1tx)printf(NULLn);/*生成分配内存代码*/*输出名字表*/for(i=tx0+1;iamax)error(31);num=0;table(*ptx).val=num;break;casevariable:table(*ptx).level=lev;table(*ptx)

30、.adr=(*pdx);(*pdx)+;break;caseprocedur:table(*ptx).level=lev;break;/*查找名字的位置*找到则返回在名字表中的位置,否则返回*idt:要查找的名字*tx::当前名字表尾指针*/intposition(char*idt,inttx)inti;strcpy(table0.name,idt);i=tx;while(strcmp(tablei.name,idt)!=0)/*全局变量id中已存有当前名字的名字*/*常量名字*/*变量名字*/*过程名字*/i-;returni;/*常量声明处理*/intconstdeclaration(in

31、t*ptx,intlev,int*pdx)if(sym=ident)getsymdo;if(sym=eql|sym=becomes)if(sym=becomes)error(1);/*把=写出成了:=*/getsymdo;if(sym=number)enter(constant,ptx,lev,pdx);getsymdo;elseerror(2);/*常量说明=后应是数字*/elseerror(3);/*常量说明标识后应是=*/elseerror(4);/*const后应是标识*/return0;/*/intvardeclaration(int*ptx,intlev,int*pdx)if(sy

32、m=ident)enter(variable,ptx,lev,pdx);/填写名字表getsymdo;elseerror(4);return0;/*输入目标代码清单*/voidlistcode(intcx0)inti;if(listswitch)for(i=cx0;iamax)error(31);num=0;gendo(lit,0,num);getsymdo;else/*因子为if(sym=lparen)/*因子为表达式*/getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevrparen=true;expressiondo(nxtlev

33、,ptx,lev);if(sym=rparen)getsymdo;elseerror(22);括号*/testdo(fsys,facbegsys,23);*/return0;/*条件处理*/intcondition(bool*fsys,int*ptx,intlev)enumsymbolrelop;boolnxtlevsymnum;if(sym=oddsym)getsymdo;expressiondo(fsys,ptx,lev);gendo(opr,0,6);elseif(sym=rparen)getsymdo;elseerror(22);括号*/testdo(fsys,facbegsys,23

34、);*/return0;/*条件处理*/intcondition(bool*fsys,int*ptx,intlev)enumsymbolrelop;boolnxtlevsymnum;if(sym=oddsym)getsymdo;expressiondo(fsys,ptx,lev);gendo(opr,0,6);else/*缺少右/*银子后有非法符号/*准备按照odd运算处理*/*生成odd指令*/memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtleveql=true;nxtlevneq=true;nxtlevlss=true;nxtlevleq=true;

35、nxtlevgtr=true;nxtlevgeq=true;expressiondo(nxtlev,ptx,lev);if(sym!=eql&sym!=neq&sym!=lss&sym!=leq&sym!=gtr&sym!=geq)error(20);elserelop=sym;getsymdo;expressiondo(fsys,ptx,lev);switch(relop)caseeql:gendo(opr,0,8);break;caseneq:gendo(opr,0,9);break;caselss:gendo(opr,0,10);break;casegeq:gendo(opr,0,11);break;casegtr:gendo(opr,0,12);break;caseleq:gendo(opr,0,13);break;return0;voidinterpret()intp,b,t;structinstructioni;intsstacksize;printf(startpl0n);t=0;b=0;p=0;return0;voidinte

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!