PL0源代码C语言版

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

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

1、- /*PL/0 编译系统C版本头文件 pl0.h*/* define norw 13 /a number of reserved word /*关键字个数*/ * define t*ma* 100 /length of identifier table /*名字表容量*/* define nma* 14 /ma* number of digits in numbers /*number的最大位数*/* define al 10 /length of identifier /*符号的最大长度*/* define ama* 2047 /ma*imum address /*地址上界*/* defi

2、ne levma* 3 /ma* depth of block nesting /*最大允许过程嵌套声明层数0,le*ma*/* define c*ma* 200 /size of code array /*最多的虚拟机代码数*/*符号*/enum symbol nul, ident, number, plus, minus, times, slash, oddsym, eql, neq, /slash斜线lss, leq, gtr, geq, lparen, /leq :less than or equal to; gtr: great than;lparen:left parenthesi

3、srparen, ma, semicolon,period, bees,/ma逗号 semicolon分号 period句号 bees赋值号beginsym, endsym, ifsym, thensym, whilesym,writesym, readsym, dosym, callsym, constsym,varsym, procsym,;*define symnum 32/*-*/enum object /object为三种标识符的类型 constant, variable, procedur,;/*-*/enum fct /fct类型分别标识类PCODE的各条指令lit, opr,

4、lod, sto, cal, inte, jmp, jpc, /书本P23 ;*define fctnum 8/*-*/struct instruction /指令 enum fct f; /功能码 int l; /层次差 int a; /P23;FILE * fas; /输知名字表FILE * fa; /输出虚拟机代码FILE * fa1; /输出源文件及其各行对应的首地址FILE * fa2; /输出结果bool tableswitch; /显示名字表与否bool listswitch; /显示虚拟机代码与否char ch; /获取字符的缓冲区,getch使用enum symbol sym

5、; /当前符号char idal+1; /当前ident,多出一个字节用于存放0 int num; /当前number int cc,ll; /getch使用的计数器,cc表示当前字符(ch)的位置int c*; /虚拟机代码指针,取值范围0,c*ma*-1char line81; /读取行缓冲区char aal+1; /临时符号,多出的一个字节用于存放0 struct instruction codec*ma*; /存放虚拟机代码的数组char wordnorwal; /保存字enum symbol wsymnorw; /保存字对应的符号值enum symbol ssym256; /单字符的

6、符号值char mnemonicfctnum5; /虚拟机代码指令名称bool declbegsyssymnum; /表示声明开场的符号集合 ,declaring begin symbol setbool statbegsyssymnum; /表示语句开场的符号集 , statementbool facbegsyssymnum; /表示因子开场的符号集合 ,factor/*-*/struct tablestruct char nameal; /*名字*/ enum object kind; /*类型:const,var,array or procedure*/ int val; /*数值,仅c

7、onst使用*/ int level; /*所处层,仅const不使用*/ int adr; /*地址,仅const不使用*/ int size; /*需要分配的数据区空间,仅procedure使用*/;struct tablestruct tablet*ma*; /*名字表*/FILE * fin; /fin文本文件用于指向输入的源程序文件FILE* fout; /fout文本文件用于指向输出的文件char fnameal;int err; /*错误计数器*/*当函数中会发生fatal error时,返回1告知调用它的函数,最终退出程序*/*define getsymdo if(-1=get

8、sym()return -1*define getchdo if(-1=getch()return -1*define testdo(a,b,c) if(-1=test(a,b,c)return -1*define gendo(a,b,c) if(-1=gen(a,b,c)return -1*define e*pressiondo(a,b,c) if(-1=e*pression(a,b,c)return -1*define factordo(a,b,c) if(-1=factor(a,b,c)return -1*define termdo(a,b,c) if(-1=term(a,b,c)ret

9、urn -1*define conditiondo(a,b,c) if(-1=condition(a,b,c)return -1*define statementdo(a,b,c) if(-1=statement(a,b,c)return -1*define constdeclarationdo(a,b,c) if(-1=constdeclaration(a,b,c)return -1*define vardeclarationdo(a,b,c) if(-1=vardeclaration(a,b,c)return -1void error(int n);int getsym();int get

10、ch();void init();int gen(enum fct *,int y,int z);int test(bool*s1,bool*s2,int n);int inset(int e,bool*s);int addset(bool*sr,bool*s1,bool*s2,int n);int subset(bool*sr,bool*s1,bool*s2,int n);int mulset(bool*sr,bool*s1,bool*s2,int n);int block(int lev,int t*,bool* fsys);void interpret();int factor(bool

11、* fsys,int* pt*,int lev);int term(bool*fsys,int*pt*,int lev);int condition(bool*fsys,int*pt*,int lev);int e*pression(bool*fsys,int*pt*,int lev);int statement(bool*fsys,int*pt*,int lev);void listcode(int c*0);int vardeclaration(int* pt*,int lev, int* pd*);int constdeclaration(int* pt*,int lev, int* p

12、d*);int position(char* idt,int t*);void enter(enum object k,int* pt*,int lev,int* pd*);int base(int l,int* s,int b);/A.2 C 版 本/*编译和运行环境:*1Visual C+6.0,VisualC+.NET and Visual C+.NET 2003*WinNT, Win 200, Win*P and Win2003 *2 gcc version 3.3.2 20031022(Red Hat Linu* 3.3.2-1)*Redhat Fedora core 1*Intel

13、 32 platform*使用方法:*运行后输入PL/0 源程序文件名*答复是否输出虚拟机代码*答复是否输知名字表*fa.tmp 输出虚拟机代码*fa1.tmp 输出源文件及其各行对应的首地址*fa2.tmp 输出结果 *fas.tmp 输知名字表*/*include*includepl0.h*includestring.h/*解释执行时使用的栈*/*define stacksize 500int main()bool n*tlevsymnum;printf(Input pl/0 file );scanf(%s,fname); /*输入文件名*/fin=fopen(fname,r); /返回值

14、:文件顺利翻开后,指向该流的文件指针就会被返回。如果文件翻开失败则返回NULL,并把错误代码存在errno 中if(fin)printf(List object code (Y/N); /*是否输出虚拟机代码*/scanf(%s,fname);listswitch=(fname0=y|fname0=Y); printf(List symbol table (Y/N); /*是否输知名字表*/scanf(%s,fname);tableswitch=(fname0=y|fname0=Y);fa1=fopen(fa1.tmp,w);fprintf(fa1,Iput pl/0 file );fprin

15、tf(fa1,%sn, fname);init(); /*初始化*/err=0; /错误计数器置0 cc=c*=ll=0;ch= ;if(-1!=getsym()fa=fopen(fa.tmp,w);fas=fopen(fas.tmp,w);addset(n*tlev,declbegsys,statbegsys,symnum);n*tlevperiod=true; if(-1=block(0,0,n*tlev)/*调用编译程序*/fclose(fa);fclose(fa1);fclose(fas);fclose(fin);printf(n);return 0;fclose(fa);fclose

16、(fa1);fclose(fas);if(sym!=period)error(9);if(err=0)fa2=fopen(fa2.tmp, w);interpret();fclose(fa2);elseprintf(Errors in pl/0 program);fclose(fin);elseprintf(Cant open file! n);printf(n);return 0;/*初始化*/void init()int i;for(i=0;i=255;i+) ssymi=nul; /ssym:单字符的符号值 ssym+=plus;ssym-=minus;ssym*=times;ssym/

17、=slash;ssym(=lparen;ssym)=rparen;ssym=eql;ssym,=ma;ssym.=period;ssym*=neq;ssym;=semicolon;/*设置保存字名字,按照字母顺序,便于折半查找*/strcpy(&(word00),begin);strcpy(&(word10),call);strcpy(&(word20),const);strcpy(&(word30),do);strcpy(&(word40),end);strcpy(&(word50),if);strcpy(&(word60),odd);strcpy(&(word70),procedure);

18、strcpy(&(word80),read);strcpy(&(word90),then);strcpy(&(word100),var);strcpy(&(word110),while);strcpy(&(word120),write);/*设置保存字符号*/wsym0=beginsym;wsym1=callsym;wsym2=constsym;wsym3=dosym;wsym4=endsym;wsym5=ifsym;wsym6=oddsym;wsym7=procsym;wsym8=readsym;wsym9=thensym;wsym10=varsym;wsym11=whilesym;wsym

19、12=writesym;/*设置指令名称*/strcpy(&(mnemoniclit0),lit);strcpy(&(mnemonicopr0),opr);strcpy(&(mnemoniclod0),lod);strcpy(&(mnemonicsto0),sto);strcpy(&(mnemoniccal0),cal);strcpy(&(mnemonicinte0),int);strcpy(&(mnemonicjmp0),jmp);strcpy(&(mnemonicjpc0),jpc);/*设置符号集*/for(i=0;isymnum;i+)declbegsysi=false;statbeg

20、sysi=false;facbegsysi=false;/*设置声明开场符号集*/declbegsysconstsym=true;declbegsysvarsym=true;declbegsysprocsym=true;/*设置语句开场符号集*/statbegsysbeginsym=true;statbegsyscallsym=true;statbegsysifsym=true;statbegsyswhilesym=true;/*设置因子开场符号集*/facbegsysident=true;facbegsysnumber=true;facbegsyslparen=true; /* *用数组实现

21、集合的集合运算 */int inset(int e,bool* s) return se;int addset(bool* sr,bool* s1,bool* s2,int n) int i; for(i=0;in;i+) sri=s1i|s2i; return 0;int subset(bool* sr,bool* s1,bool* s2,int n) int i; for(i=0;in;i+) sri=s1i&(!s2i); return 0; int mulset(bool* sr,bool* s1,bool* s2,int n) int i; for(i=0;i=a&ch=z) k=0

22、;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&chnma*)error(30);elseif(ch=:) /*检测赋值符号*/getchdo;if(ch=)sym=bees;getchdo;elsesym=nul; /*不能识别的符号*/elseif(ch=) /*检测大于或大于等于符号*/getchdo;if(ch=)sym=geq;getchdo;else

23、 sym=gtr;elsesym=ssymch;/* 当符号不满足上述条件时,全部按照单字符号处理*/getchdo;/richardif(sym!=period)getchdo;/end richardreturn 0;/*生成虚拟机代码*:instruction.f;*y:instruction.l;*z:instruction.a;*/int gen(enum fct *,int y,int z)if(c*=c*ma*)printf(Program too long); /*程序过长*/return -1;codec*.f=*;codec*.l=y;codec*.a=z;c*+;retu

24、rn 0;/*测试当前符号是否合法*在*一局部如一条语句,一个表达式将要完毕时时我们希望下一个符号属于*集合*该局部的后跟符号 test 负责这项检测,并且负责当检测不通过时的补救措施*程序在需要检测时指定当前需要的符号集合和补救用的集合如之前未完成局部的后跟*符号,以及不通过时的错误号*S1:我们需要的符号*s2:如果不是我们需要的,则需要一个补救用的集合*n:错误号*/int test(bool* s1,bool* s2,int n) if(! inset(sym,s1) error(n);/*当检测不通过时,不停获取符号,直到它属于需要的集合或补救的集合*/while(! inset(s

25、ym,s1)&(! inset(sym,s2)getsymdo; return 0;/* *编译程序主体 * *lev:当前分程序所在层 *t*:名字表当前尾指针 *fsys:当前模块后跟符号集合 */int block(int lev,int t*,bool* fsys) int i; int d*; /*名字分配到的相对地址*/ int t*0; /*保存初始t*/ int c*0; /*保存初始c*/ bool n*tlevsymnum; /*在下级函数的参数中,符号集合均为值参,但由于使用数组 实现,传递进来的是指针,为防止下级函数改变上级函数的 集合,开辟新的空间传递给下级函数*/

26、d*=3; t*0=t*; /*记录本层名字的初始位置*/ tablet*.adr=c*; gendo(jmp,0,0); if(lev levma*) error(32); do if(sym=constsym) /*收到常量声明符号,开场处理常量声明*/ getsymdo;do constdeclarationdo(&t*,lev,&d*); /*d*的值会被constdeclaration改变,使用 指针*/ while(sym=ma) getsymdo; constdeclarationdo(&t*,lev,&d*); if(sym=semicolon) getsymdo;elseer

27、ror(5); /*漏掉了逗号或者分号*/while(sym=ident);if(sym=varsym)/*收到变量声名符号,开场处理变量声名*/getsymdo;dovardeclarationdo(&t*,lev,&d*);while(sym=ma)getsymdo;vardeclarationdo(&t*,lev,&d*);if(sym=semicolon)getsymdo;elseerror(5);while(sym=ident);while(sym=procsym)/*收到过程声名符号,开场处理过程声名*/getsymdo;if(sym=ident)enter(procedur,&t

28、*,lev,&d*);/*记录过程名字*/getsymdo;elseerror(4);/*procedure后应为标识符*/if(sym=semicolon)getsymdo;elseerror(5);/*漏掉了分号*/memcpy(n*tlev,fsys,sizeof(bool)*symnum);n*tlevsemicolon=true;if(-1=block(lev+1,t*,n*tlev)return -1;/*递归调用*/ if(sym=semicolon) getsymdo; memcpy(n*tlev,statbegsys,sizeof(bool)*symnum); n*tlevi

29、dent=true; n*tlevprocsym=true; testdo(n*tlev,fsys,6); else error(5); /*漏掉了分号*/ memcpy(n*tlev,statbegsys,sizeof(bool)*symnum); n*tlevident=true; n*tlevperiod=true; testdo(n*tlev,declbegsys,7); while(inset(sym,declbegsys); /*直到没有声明符号*/ codetablet*0.adr.a=c*; /*开场生成当前过程代码*/ tablet*0.adr=c*; /*当前过程代码地址*

30、/ tablet*0.size=d*; /*声明局部中每增加一条声明都会给d*增加1,声明局部已经完毕,d*就是当前过程数据的size*/c*0=c*; gendo(inte,0,d*); /*生成分配内存代码*/ if(tableswitch) /*输知名字表*/ printf(TABLE:n); if(t*0+1t*) printf(NULLn); for(i=t*0+1;iama*)error(31);num=0;table(*pt*).val=num;break;case variable: /*变量名字*/table(*pt*).level=lev;table(*pt*).adr=(

31、*pd*);(*pd*)+;break; /*过程名字*/case procedur:table(*pt*).level=lev;break;/* *查找名字的位置 *找到则返回在名字表中的位置,否则返回0 * *idt: 要查找的名字 *t*::当前名字表尾指针 */int position(char * idt,int t*)int i;strcpy(table0.name,idt);i=t*;while(strcmp(tablei.name,idt)!=0)i-;return i;/* *常量声明处理 */int constdeclaration(int * pt*,int lev,in

32、t * pd*)if(sym=ident)getsymdo;if(sym=eql |sym=bees)if(sym=bees)error(1); /*把=写出成了:=*/getsymdo;if(sym=number)enter(constant,pt*,lev,pd*);getsymdo;elseerror(2); /*常量说明=后应是数字*/ elseerror(3); /*常量说明标识后应是=*/elseerror(4); /*const后应是标识*/return 0;/* * */int vardeclaration(int * pt*,int lev,int * pd*)if(sym=

33、ident) enter(variable,pt*,lev,pd*);/填写名字表 getsymdo; else error(4); return 0; /* *输入目标代码清单 */void listcode(int c*0)int i; if (listswitch) for(i=c*0;ic*;i+) printf(%d %s %d %dn,i,mnemoniccodei.f,codei.l,codei.a); fprintf(fa,%d %s %d %dn,i,mnemoniccodei.f,codei.l,codei.a); /*语句处理*/int statement(bool* f

34、sys,int * pt*,int lev)int i,c*1,c*2; bool n*tlevsymnum; if(sym=ident) i=position(id,*pt*); if(i=0) error(11); else if(tablei.kind!=variable) error(12); i=0; else getsymdo; if(sym=bees) getsymdo; else error(13); memcpy(n*tlev,fsys,sizeof(bool)* symnum); e*pressiondo(n*tlev,pt*,lev); if(i!=0) gendo(st

35、o,lev-tablei.level,tablei.adr); else if(sym=readsym) getsymdo; if(sym!=lparen) error(34); else do getsymdo; if(sym=ident) i=position(id, *pt*); else i=0; if(i=0) error(35); else gendo(opr,0,16);gendo(sto,lev-tablei.level,tablei.adr);/* 储存到变量*/getsymdo;while (sym=ma);/*一条read语句可读多个变量 */if(sym!=rparen)error(33

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