版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、精选优质文档-倾情为你奉上/*PL/0编译程序(C语言版)*编译和运行环境:*Visual C+6.0*WinXP/7*使用方法:*运行后输入PL/0源程序文件名*回答是否将虚拟机代码写入文件*回答是否将符号表写入文件*执行成功会产生四个文件 (词法分析结果.txt符号表.txt虚拟代码.txt源程序和地址.txt)*/ #include <stdio.h>#include"pl0.h"#include"string"#define stacksize 500/解释执行时使用的栈int main()bool nxtlevsymnum;prin
2、tf("请输入源程序文件名:");scanf("%s",fname);fin=fopen(fname,"r");/以只读方式打开pl0源程序文件cifa=fopen("词法分析结果.txt","w");fa1=fopen("源程序和地址.txt","w");/输出源文件 及各行对应的首地址fprintf(fa1,"输入pl0源程序文件名:");fprintf(fa1,"%sn",fname);if(fin)print
3、f("是否将虚拟机代码写入文件?(Y/N)");/是否输出虚拟机代码scanf("%s",fname);listswitch=(fname0='y'|fname0='Y'); printf("是否将符号表写入文件?(Y/N)");/是否输出符号表scanf("%s",fname);tableswitch=(fname0='y'|fname0='Y');init();/初始化err=0;cc=cx=ll=0;ch=' 'if(-1!=ge
4、tsym()fa=fopen("虚拟代码.txt","w");fas=fopen("符号表.txt","w");addset(nxtlev,declbegsys,statbegsys,symnum);nxtlevperiod=true;if(-1=block(0,0,nxtlev)/调用编译程序fclose(fa);fclose(fa1);fclose(fas);fclose(fin);return 0;if(sym!=period)error(9);/结尾丢失了句号if(err!=0)printf("p
5、l0源程序出现错误,退出编译!请从第一个错误处开始修改.nn");fprintf(cifa,"源程序出现错误,请检查!");fprintf(fa1,"源程序出现错误,请检查!");fprintf(fa,"源程序出现错误,请检查!");fprintf(fas,"源程序出现错误,请检查!");fclose(fa);fclose(fa1); fclose(fas);fclose(fin);elseprintf("Can't open file!n"); fclose(cifa);/p
6、rintf("n");return 0;void init()/初始化int i;for(i=0;i<=255;i+)ssymi=nul;/设置单字符符号ssym'+'=plus;ssym'-'=minus;ssym'*'=times;ssym'/'=slash;ssym'('=lparen;ssym')'=rparen; ssym'='=eql;ssym','=comma;ssym'.'=period;ssym'#&
7、#39;=neq;ssym''=semicolon;strcpy(&(word00),"begin");/保留字设置,以字母顺序排列 便于折半查找strcpy(&(word10),"call");strcpy(&(word20),"const");strcpy(&(word30),"do");strcpy(&(word40),"end");strcpy(&(word50),"if");strcpy(&(w
8、ord60),"odd");strcpy(&(word70),"procedure");strcpy(&(word80),"read");strcpy(&(word90),"then");strcpy(&(word100),"var");strcpy(&(word110),"while");strcpy(&(word120),"write");wsym0=beginsym;/设置保留字类别 一字即一类wsym
9、1=callsym;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"
10、);strcpy(&(mnemonicsto0),"sto");strcpy(&(mnemoniccal0),"cal");strcpy(&(mnemonicinte0),"int");strcpy(&(mnemonicjmp0),"jmp");strcpy(&(mnemonicjpc0),"jpc"); for(i=0;i<symnum;i+)/设置符号集declbegsysi=false;statbegsysi=false;facbegsysi=
11、false;declbegsysconstsym=true;/设置声明开始符号集declbegsysvarsym=true;declbegsysprocsym=true;statbegsysbeginsym=true;/设置语句开始符号集statbegsyscallsym=true;statbegsysifsym=true;statbegsyswhilesym=true;facbegsysident=true;/设置因子开始符号集facbegsysnumber=true;facbegsyslparen=true;/用数组实现集合的集合运算int inset(int e,bool* s)retu
12、rn se;int addset(bool*sr,bool* s1,bool* s2,int n)int i;for(i=0;i<n;i+)sri=s1i|s2i;return 0;void error(int n)/出错处理,打印出错位置和错误编码char space81;memset(space, 32,81);spacecc-1=0;printf("error(%d)",n);fprintf(fa1,"error(%d)",n);switch(n)case 1:printf("tt常量说明中的“=”写成“:=”n"); f
13、printf(fa1,"tt常量说明中的“=”写成“:=”n");break;case 2:printf("tt常量说明中的=后应该是数字n"); fprintf(fa1,"tt常量说明中的=后应该是数字n");break;case 3:printf("tt常量说明符中的表示符应该是=n" ); fprintf(fa1,"tt常量说明符中的表示符应该是=n");break;case 4:printf("ttconst,var,procedure后应为标识符n" ); fpri
14、ntf(fa1,"ttconst,var,procedure后应为标识符n");break;case 5:printf("tt漏掉了“,”或“;”n" ); fprintf(fa1,"tt漏掉了“,”或“;”n" );break;case 6:printf("tt过程说明后的符号不正确n" ); fprintf(fa1,"tt过程说明后的符号不正确n");break;case 7:printf("tt应是语句开始符n" ); fprintf(fa1,"tt应是语句开
15、始符n" );break;case 8:printf("tt程序体内语句部分的后跟符不正确n" ); fprintf(fa1,"tt程序体内语句部分的后跟符不正确n" );break;case 9:printf("tt程序结尾丢了句号“.”nn" ); fprintf(fa1,"tt程序结尾丢了句号“.”n");break;case 10:printf("tt语句之间漏了“;”n" ); fprintf(fa1,"tt语句之间漏了“;”n");break;case
16、11:printf("tt标识符拼写错误或未说明n" ); fprintf(fa1,"tt标识符拼写错误或未说明n");break;case 12:printf("tt赋值语句中,赋值号左部标识符属性应是变量n" ); fprintf(fa1,"tt赋值语句中,赋值号左部标识符属性应是变量n");break;case 13:printf("tt赋值语句左部标识符后应是复制号“:=”n" ); fprintf(fa1,"tt赋值语句左部标识符后应是复制号“:=”n");brea
17、k;case 14:printf("ttcall后应为标识符n" ); fprintf(fa1,"ttcall后应为标识符n");break;case 15:printf("ttcall后标识符属性应为过程n" ); fprintf(fa1,"ttcall后标识符属性应为过程n");break;case 16:printf("tt条件语句中丢了thenn" ); fprintf(fa1,"tt条件语句中丢了thenn");break;case 17:printf("
18、tt丢了“end”或“;”n" ); fprintf(fa1,"tt丢了“end”或“;”n");break;case 18:printf("ttwhile型循环语句中丢了“do”n" ); fprintf(fa1,"ttwhile型循环语句中丢了“do”n");break;case 19:printf("tt语句后的符号不正确n" ); fprintf(fa1,"tt语句后的符号不正确n" );break;case 20:printf("tt应为关系运算符n" )
19、; fprintf(fa1,"tt应为关系运算符n");break;case 21:printf("tt表达式内标示符属性不能是过程n" ); fprintf(fa1,"tt表达式内标示符属性不能是过程n");break;case 22:printf("tt表达式漏掉了右括号n" ); fprintf(fa1,"tt表达式漏掉了右括号n");break;case 23:printf("tt因子后的非法符号n" ); fprintf(fa1,"tt因子后的非法符号n&
20、quot;);break;case 24:printf("tt表达式的开始符不能是此符号n" ); fprintf(fa1,"tt表达式的开始符不能是此符号n");break;case 25:printf("tt标识符越界n" ); fprintf(fa1,"tt标识符越界n");break;case 26:printf("tt非法字符n" ); fprintf(fa1,"tt非法字符n");break;case 31:printf("tt数越界n");
21、fprintf(fa1,"tt数越界n");break;case 32:printf("ttread语句括号中的标识符不是变量n" ); fprintf(fa1,"ttread语句括号中的标识符不是变量n");break;case 33:printf("ttwrite()或read()中应为完整表达式n" ); fprintf(fa1,"ttwrite()或read()中应为完整表达式n");break;default: printf("tt出现未知错误n" ); fprin
22、tf(fa1,"tt出现未知错误n");err+;/漏掉空格,读取一个字符,每次读一行,存入line缓冲区,line被getsym取空后再读一/行,被函数getsym调用int getch()if(cc=ll)if(feof(fin)printf("program incomplete");return-1;ll=0;cc=0;printf("n%d ",cx);fprintf(fa1,"n%d ",cx);ch=' 'while(ch!=10)if(EOF=fscanf(fin,"%c&
23、quot;,&ch)linell=0;break;printf("%c",ch);fprintf(fa1,"%c",ch);linell=ch;ll+;fprintf(cifa,"n");ch=linecc;cc+;return 0;int getsym()/词法分析int i,j,k,l;while(ch=' '|ch=10|ch=9)/忽略空格 换行 TABgetchdo;if(ch>='a'&&ch<='z')/以字母开头的为保留字或者标识符k=
24、0,l=1;doif(k<al)/al为标识符或保留字最大长度ak=ch;k+;if(k=al&&l=1)error(25);l=0;getchdo;while(ch>='a'&&ch<='z'|ch>='0'&&ch<='9');ak=0;/末尾存零strcpy(id,a);i=0;j=norw-1;do/开始折半查找k=(i+j)/2;if(strcmp(id,wordk)<=0)j=k-1;if(strcmp(id,wordk)>=0)
25、i=k+1;while(i<=j);if(i-1>j)/找到 即为保留字 sym=wsymk; fprintf(cifa,"%stt%ssymn",id,id);/printf("%stt%ssymn",id,id);else/否则为标识符或数字sym=ident;fprintf(cifa,"%sttidentn",id);/printf("%sttidentn",id);else if(ch>='0'&&ch<='9')k=0;num=0;s
26、ym=number;donum=10*num+ch-'0'/数字的数位处理k+;getchdo;while(ch>='0'&&ch<='9');k-;if(k>nmax)/数字的长度限制fprintf(cifa,"0ttnumbern");num=0;error(31);elsefprintf(cifa,"%dttnumbern",num);/printf("%dttnumbern",num);elseif(ch=':')/检测赋值符号,
27、:只能和=匹配,否则不能识别getchdo;if(ch='=')sym=becomes;fprintf(cifa,":=ttbecomesn");getchdo;elsesym=nul;elseif(ch='<')getchdo;if(ch='=')sym=leq;/小于等于fprintf(cifa,"<=ttleqn");getchdo;elsesym=lss;/小于fprintf(cifa,"<ttlssn");elseif(ch='>')ge
28、tchdo;if(ch='=')sym=geq;/大于等于fprintf(cifa,">=ttgeqn");getchdo;elsesym=gtr;/大于fprintf(cifa,">ttgtrn");elsesym=ssymch;/不满足上述条件时 按单字/符处理switch(ch)case'+':fprintf(cifa,"%cttplusn",ch);break;case '-':fprintf(cifa,"%cttminusn",ch);break
29、;case '*':fprintf(cifa,"%ctttimesn",ch);break;case '/':fprintf(cifa,"%cttslashn",ch);break;case '(':fprintf(cifa,"%cttlparenn",ch);break;case ')':fprintf(cifa,"%cttrparenn",ch);break;case '=':fprintf(cifa,"%ctteqln&
30、quot;,ch);break;case ',':fprintf(cifa,"%cttcomman",ch);break;case '#':fprintf(cifa,"%cttneqn",ch);break;case '':fprintf(cifa,"%cttsemicolonn",ch);break;case '.':break;default :error(26);if(sym!=period)/判断是否结束getchdo;elseprintf("n&quo
31、t;); fprintf(cifa,".ttperiodn");return 0;/生成目标代码/目标代码的功能码,层差和位移量int gen(enum fct x,int y,int z)if(cx>=cxmax)/如果目标代码索引过大,报错 printf("Program too long");return -1;codecx.f=x;codecx.l=y;codecx.a=z;cx+;return 0;/测试字符串int test(bool* s1,bool* s2,int n)if(!inset(sym,s1)/测试sym是否属于s1,不属
32、于则报错nerror(n);while(!inset(sym,s1)&&(!inset(sym,s2)/检测不通过时,不停获得符号,直到它属于需要或补救的集合getsymdo;return 0;/编译程序主体/lev:当前分程序所在层,tx:名字表当前尾指针fsys:当前模块 后跟符号集合int block(int lev,int tx,bool* fsys)int i;int dx;/名字分配到的相对地址int tx0;/保留初始txint cx0;/保留初始cxbool nxtlevsymnum;dx=3;/相对地址从3开始,前3个单元即0、1、2单元分别为 SL:静态链;
33、/DL:动态链;RA:返回地址tx0=tx;/记录本层的初始位置tabletx.adr=cx;gendo(jmp,0,0);if(lev>levmax)/层数超过3error(32);doif(sym=constsym)/收到常量声明printf("该语句为常量定义语句n");getsymdo;doconstdeclarationdo(&tx,lev,&dx);/常量声明处理,dx会改/变 所以使用指针while(sym=comma)/处理一次多常量定义getsymdo;constdeclarationdo(&tx,lev,&dx);i
34、f(sym=semicolon)/常量声明处理结束getsymdo;elseerror(5);/漏掉了逗号或者分号(一般是分号)while(sym=ident);if(sym=varsym)/收到变量声明printf("该语句为变量声明语句n");getsymdo;dovardeclarationdo(&tx,lev,&dx);/变量声明处理while(sym=comma)/处理一次多变量定义getsymdo;vardeclarationdo(&tx,lev,&dx);if(sym=semicolon)/变量声明处理结束getsymdo;el
35、seerror(5);/漏掉逗号或者分号while(sym=ident);while(sym=procsym)/收到过程声明printf("该语句为过程声明语句n");getsymdo;if(sym=ident)enter(procedur,&tx,lev,&dx);/记录过程名getsymdo;elseerror(4);/过程声明后应为标识符if(sym=semicolon)getsymdo;elseerror(5);/漏掉了分号memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevsemicolon=true;if(
36、-1=block(lev+1,tx,nxtlev)return -1;if(sym=semicolon)getsymdo;memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);nxtlevident=true;nxtlevprocsym=true;testdo(nxtlev,fsys,6);elseerror(5);memcpy(nxtlev,statbegsys,sizeof(bool)*symnum);nxtlevident=true;nxtlevperiod=true;testdo(nxtlev,declbegsys,7);while(inset(s
37、ym,declbegsys);/直到没有声明符号codetabletx0.adr.a=cx;/开始生成当前过程代码tabletx0.adr=cx;/当前过程代码地址tabletx0.size=dx;cx0=cx;gendo(inte,0,dx);/生成分配内存代码if(tableswitch)/输出符号表if(tx0+1<tx)fprintf(fas,"TABLE:n");/printf("NULLn");for(i=tx0+1;i<=tx;i+)switch(tablei.kind)case constant:fprintf(fas,&qu
38、ot;%d const %s ",i,);fprintf(fas,"val=%dn",tablei.val);break;case variable:fprintf(fas,"%d var %s ",i,);fprintf(fas,"lev=%daddr=%dn",tablei.level,tablei.adr);break;case procedur:fprintf(fas,"%d proc %s ",i,); fprintf(fas,&
39、quot;lev=%daddr=%dsize=%dn",tablei.level,tablei.adr,tablei.size);break;memcpy(nxtlev,fsys,sizeof(bool)*symnum);/每个后跟符号集和都包含上层后跟符/号集和,以便补救nxtlevsemicolon=true;nxtlevendsym=true;statementdo(nxtlev,&tx,lev);gendo(opr,0,0);/每个过程出口都要使用的释放数据指令memset(nxtlev,0,sizeof(bool)*symnum);/分程序没有补救集合testdo(
40、fsys,nxtlev,8);/检测后跟符号集的正确性listcode(cx0);/输出代码return 0;/k:const var procedure /ptx:符号表尾的指针/pdx:dx为当前应分配变量的相对地址/lev:符号名字所在的层次/往符号表中添加void enter(enum object k,int* ptx,int lev,int* pdx)(* ptx)+;strcpy(table(*ptx).name,id);table(* ptx).kind=k;switch(k)case constant:if(num>amax)error(31);num=0; table
41、(*ptx).val=num; break;case variable:table(*ptx).level=lev;table(*ptx).adr=(*pdx);(*pdx)+;break;case procedur:table(*ptx).level=lev;break;/寻找符号在符号表中的地址int position(char*idt,int tx)int i;strcpy(,idt);i=tx;/符号表尾while(strcmp(,idt)!=0)i-;return i;/常量声明处理int constdeclaration(int* ptx
42、,int lev,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);return 0;/变量声明处理int vardeclaration (int* ptx,int lev,int* pdx)if(sym=ident)enter(variable,ptx,lev,pdx);getsymdo;el
43、seerror(4);return 0;/输出目标代码清单void listcode(int cx0)int i;if(listswitch)for(i=cx0;i<cx;i+) fprintf(fa,"%d %s %d %dn",i,mnemoniccodei.f,codei.l,codei,a);/语句处理int statement(bool* fsys,int* ptx,int lev)int i,cx1,cx2;bool nxtlevsymnum;if(sym=ident)i=position(id,*ptx);if(i=0)error(11);elseif(
44、tablei.kind!=variable)error(12);i=0;elsegetsymdo;if(sym=becomes)getsymdo;printf("该语句为赋值语句。n");elseerror(13);memcpy(nxtlev,fsys,sizeof(bool)* symnum);expressiondo(nxtlev,ptx,lev);if(i!=0)gendo(sto,lev-tablei.level,tablei.adr);/if(i=0)else/保留字匹配if(sym=readsym)printf("该语句为读语句n");get
45、symdo;if(sym!=lparen)error(34);elsedogetsymdo;if(sym=ident)i=position(id,*ptx);elsei=0;if(i=0)error(35);elsegendo(opr,0,16);gendo(sto,lev-tablei.level,tablei.adr);getsymdo;while(sym=comma);if(sym!=rparen)error(33);while(!inset(sym,fsys)getsymdo;elsegetsymdo;elseif(sym=writesym)printf("该语句为写语句n&
46、quot;);getsymdo;if(sym=lparen)dogetsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevrparen=true;nxtlevcomma=true;expressiondo(nxtlev,ptx,lev);gendo(opr,0,14);while(sym=comma);if(sym!=rparen)error(33);elsegetsymdo;gendo(opr,0,15);elseif(sym=callsym)printf("该语句为调用语句n");getsymdo;if(sym!=id
47、ent)error(14);elsei=position(id,*ptx);if(i=0)error(11);elseif(tablei.kind=procedur)gendo(cal,lev-tablei.level,tablei.adr);elseerror(15);getsymdo;elseif(sym=ifsym)printf("该语句为if条件语句n");getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevrparen=true;nxtlevcomma=true;conditiondo(nxtlev,ptx
48、,lev);if(sym=thensym)getsymdo;elseerror(16);cx1=cx;gendo(jpc,0,0);statementdo(fsys,ptx,lev);codecx1.a=cx;elseif(sym=beginsym)getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevrparen=true; nxtlevcomma=true;statementdo(nxtlev,ptx,lev);while(inset(sym,statbegsys)|sym=semicolon)if(sym=semicolon)getsymdo;elseerror(10);statementdo(nxtlev,ptx,lev);if(sym=endsym)getsymdo;elseerror(17);elseif(sym=whilesym)printf("该语句为while循环语句n");cx1=cx;getsymdo;memcpy(nxtlev,fsys,sizeof(bool)*symnum);nxtlevdosym=true;conditiondo(nxtlev,ptx,lev);cx2=cx;gendo(jpc,0,0);if(sym=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 湘西土家族苗族自治州泸溪县2025-2026学年第二学期四年级语文期末考试卷(部编版含答案)
- 焦作市沁阳市2025-2026学年第二学期四年级语文第七单元测试卷(部编版含答案)
- 临沧地区云县2025-2026学年第二学期五年级语文第八单元测试卷(部编版含答案)
- 定西地区漳县2025-2026学年第二学期三年级语文第八单元测试卷(部编版含答案)
- 机绣工QC管理测试考核试卷含答案
- 把钩信号工变革管理模拟考核试卷含答案
- 拖拉机机械加工生产线操作调整工岗前技能掌握考核试卷含答案
- 辽阳市白塔区2025-2026学年第二学期三年级语文期末考试卷(部编版含答案)
- 九江市浔阳区2025-2026学年第二学期五年级语文第八单元测试卷(部编版含答案)
- 昭通地区镇雄县2025-2026学年第二学期三年级语文期末考试卷(部编版含答案)
- 涉及民族因素矛盾纠纷突发事件应急预案
- 农业现代化农业机械智能化管理方案设计
- 倾斜摄影测量技术方案设计
- 烧结厂岗前安全培训
- 中国共产主义青年团团章
- DB41T+2740-2024内河闸控航道通航技术要求
- 工程造价基础知识课件
- DL-T825-2021电能计量装置安装接线规则
- 公路建设项目经济评价表模板(自动计算)
- 航天禁(限)用工艺目录(2021版)-发文稿(公开)
- 人类辅助生殖技术规范1;2
评论
0/150
提交评论