编译原理PL0编译程序源代码.docx

上传人:b****4 文档编号:3829193 上传时间:2022-11-25 格式:DOCX 页数:35 大小:24.15KB
下载 相关 举报
编译原理PL0编译程序源代码.docx_第1页
第1页 / 共35页
编译原理PL0编译程序源代码.docx_第2页
第2页 / 共35页
编译原理PL0编译程序源代码.docx_第3页
第3页 / 共35页
编译原理PL0编译程序源代码.docx_第4页
第4页 / 共35页
编译原理PL0编译程序源代码.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

编译原理PL0编译程序源代码.docx

《编译原理PL0编译程序源代码.docx》由会员分享,可在线阅读,更多相关《编译原理PL0编译程序源代码.docx(35页珍藏版)》请在冰豆网上搜索。

编译原理PL0编译程序源代码.docx

编译原理PL0编译程序源代码

/*PL/0编译程序(C语言版)

*编译和运行环境:

*VisualC++6.0

*WinXP/7

*使用方法:

*运行后输入PL/0源程序文件名

*回答是否将虚拟机代码写入文件

*回答是否将符号表写入文件

*执行成功会产生四个文件(词法分析结果.txt符号表.txt虚拟代码.txt源程序和地址.txt)

*/

#include

#include"pl0.h"

#include"string"

#definestacksize500//解释执行时使用的栈

intmain(){

boolnxtlev[symnum];

printf("请输入源程序文件名:

");

scanf("%s",fname);

fin=fopen(fname,"r");//以只读方式打开pl0源程序文件

cifa=fopen("词法分析结果.txt","w");

fa1=fopen("源程序和地址.txt","w");//输出源文件及各行对应的首地址

fprintf(fa1,"输入pl0源程序文件名:

");

fprintf(fa1,"%s\n",fname);

if(fin){

printf("是否将虚拟机代码写入文件?

(Y/N)");//是否输出虚拟机代码

scanf("%s",fname);

listswitch=(fname[0]=='y'||fname[0]=='Y');

printf("是否将符号表写入文件?

(Y/N)");//是否输出符号表

scanf("%s",fname);

tableswitch=(fname[0]=='y'||fname[0]=='Y');

init();//初始化

err=0;

cc=cx=ll=0;

ch='';

if(-1!

=getsym()){

fa=fopen("虚拟代码.txt","w");

fas=fopen("符号表.txt","w");

addset(nxtlev,declbegsys,statbegsys,symnum);

nxtlev[period]=true;

if(-1==block(0,0,nxtlev)){//调用编译程序

fclose(fa);

fclose(fa1);

fclose(fas);

fclose(fin);

return0;

}

if(sym!

=period){

error(9);//结尾丢失了句号

}

if(err!

=0){

printf("pl0源程序出现错误,退出编译请从第一个错误处开始修改.\n\n");

fprintf(cifa,"源程序出现错误,请检查");

fprintf(fa1,"源程序出现错误,请检查");

fprintf(fa,"源程序出现错误,请检查");

fprintf(fas,"源程序出现错误,请检查");

}fclose(fa);

fclose(fa1);

fclose(fas);

}fclose(fin);

}else{

printf("Can'topenfile!

\n");

}

fclose(cifa);//printf("\n");

return0;

}

voidinit(){//初始化

inti;

for(i=0;i<=255;i++)

ssym[i]=nul;//设置单字符符号

ssym['+']=plus;

ssym['-']=minus;

ssym['*']=times;

ssym['/']=slash;

ssym['(']=lparen;

ssym[')']=rparen;

ssym['=']=eql;

ssym[',']=comma;

ssym['.']=period;

ssym['#']=neq;

ssym[';']=semicolon;

strcpy(&(word[0][0]),"begin");//保留字设置,以字母顺序排列便于折半查找

strcpy(&(word[1][0]),"call");

strcpy(&(word[2][0]),"const");

strcpy(&(word[3][0]),"do");

strcpy(&(word[4][0]),"end");

strcpy(&(word[5][0]),"if");

strcpy(&(word[6][0]),"odd");

strcpy(&(word[7][0]),"procedure");

strcpy(&(word[8][0]),"read");

strcpy(&(word[9][0]),"then");

strcpy(&(word[10][0]),"var");

strcpy(&(word[11][0]),"while");

strcpy(&(word[12][0]),"write");

wsym[0]=beginsym;//设置保留字类别一字即一类

wsym[1]=callsym;

wsym[2]=constsym;

wsym[3]=dosym;

wsym[4]=endsym;

wsym[5]=ifsym;

wsym[6]=oddsym;

wsym[7]=procsym;

wsym[8]=readsym;

wsym[9]=thensym;

wsym[10]=varsym;

wsym[11]=whilesym;

wsym[12]=writesym;

strcpy(&(mnemonic[lit][0]),"lit");//设置指令名称

strcpy(&(mnemonic[opr][0]),"opr");

strcpy(&(mnemonic[lod][0]),"lod");

strcpy(&(mnemonic[sto][0]),"sto");

strcpy(&(mnemonic[cal][0]),"cal");

strcpy(&(mnemonic[inte][0]),"int");

strcpy(&(mnemonic[jmp][0]),"jmp");

strcpy(&(mnemonic[jpc][0]),"jpc");

for(i=0;i

declbegsys[i]=false;

statbegsys[i]=false;

facbegsys[i]=false;

}

declbegsys[constsym]=true;//设置声明开始符号集

declbegsys[varsym]=true;

declbegsys[procsym]=true;

statbegsys[beginsym]=true;//设置语句开始符号集

statbegsys[callsym]=true;

statbegsys[ifsym]=true;

statbegsys[whilesym]=true;

facbegsys[ident]=true;//设置因子开始符号集

facbegsys[number]=true;

facbegsys[lparen]=true;

}//用数组实现集合的集合运算

intinset(inte,bool*s){

returns[e];

}

intaddset(bool*sr,bool*s1,bool*s2,intn){

inti;

for(i=0;i

sr[i]=s1[i]||s2[i];

return0;

}

voiderror(intn){//出错处理,打印出错位置和错误编码

charspace[81];

memset(space,32,81);

space[cc-1]=0;

printf("error(%d)",n);

fprintf(fa1,"error(%d)",n);

switch(n){

case1:

printf("\t\t常量说明中的“=”写成“:

=”\n");

fprintf(fa1,"\t\t常量说明中的“=”写成“:

=”\n");

break;

case2:

printf("\t\t常量说明中的=后应该是数字\n");

fprintf(fa1,"\t\t常量说明中的=后应该是数字\n");

break;

case3:

printf("\t\t常量说明符中的表示符应该是=\n");

fprintf(fa1,"\t\t常量说明符中的表示符应该是=\n");

break;

case4:

printf("\t\tconst,var,procedure后应为标识符\n");

fprintf(fa1,"\t\tconst,var,procedure后应为标识符\n");

break;

case5:

printf("\t\t漏掉了“,”或“;”\n");

fprintf(fa1,"\t\t漏掉了“,”或“;”\n");

break;

case6:

printf("\t\t过程说明后的符号不正确\n");

fprintf(fa1,"\t\t过程说明后的符号不正确\n");

break;

case7:

printf("\t\t应是语句开始符\n");

fprintf(fa1,"\t\t应是语句开始符\n");

break;

case8:

printf("\t\t程序体内语句部分的后跟符不正确\n");

fprintf(fa1,"\t\t程序体内语句部分的后跟符不正确\n");

break;

case9:

printf("\t\t程序结尾丢了句号“.”\n\n");

fprintf(fa1,"\t\t程序结尾丢了句号“.”\n");

break;

case10:

printf("\t\t语句之间漏了“;”\n");

fprintf(fa1,"\t\t语句之间漏了“;”\n");

break;

case11:

printf("\t\t标识符拼写错误或未说明\n");

fprintf(fa1,"\t\t标识符拼写错误或未说明\n");

break;

case12:

printf("\t\t赋值语句中,赋值号左部标识符属性应是变量\n");

fprintf(fa1,"\t\t赋值语句中,赋值号左部标识符属性应是变量\n");

break;

case13:

printf("\t\t赋值语句左部标识符后应是复制号“:

=”\n");

fprintf(fa1,"\t\t赋值语句左部标识符后应是复制号“:

=”\n");

break;

case14:

printf("\t\tcall后应为标识符\n");

fprintf(fa1,"\t\tcall后应为标识符\n");

break;

case15:

printf("\t\tcall后标识符属性应为过程\n");

fprintf(fa1,"\t\tcall后标识符属性应为过程\n");

break;

case16:

printf("\t\t条件语句中丢了then\n");

fprintf(fa1,"\t\t条件语句中丢了then\n");

break;

case17:

printf("\t\t丢了“end”或“;”\n");

fprintf(fa1,"\t\t丢了“end”或“;”\n");

break;

case18:

printf("\t\twhile型循环语句中丢了“do”\n");

fprintf(fa1,"\t\twhile型循环语句中丢了“do”\n");

break;

case19:

printf("\t\t语句后的符号不正确\n");

fprintf(fa1,"\t\t语句后的符号不正确\n");

break;

case20:

printf("\t\t应为关系运算符\n");

fprintf(fa1,"\t\t应为关系运算符\n");

break;

case21:

printf("\t\t表达式内标示符属性不能是过程\n");

fprintf(fa1,"\t\t表达式内标示符属性不能是过程\n");

break;

case22:

printf("\t\t表达式漏掉了右括号\n");

fprintf(fa1,"\t\t表达式漏掉了右括号\n");

break;

case23:

printf("\t\t因子后的非法符号\n");

fprintf(fa1,"\t\t因子后的非法符号\n");

break;

case24:

printf("\t\t表达式的开始符不能是此符号\n");

fprintf(fa1,"\t\t表达式的开始符不能是此符号\n");

break;

case25:

printf("\t\t标识符越界\n");

fprintf(fa1,"\t\t标识符越界\n");

break;

case26:

printf("\t\t非法字符\n");

fprintf(fa1,"\t\t非法字符\n");

break;

case31:

printf("\t\t数越界\n");

fprintf(fa1,"\t\t数越界\n");

break;

case32:

printf("\t\tread语句括号中的标识符不是变量\n");

fprintf(fa1,"\t\tread语句括号中的标识符不是变量\n");

break;

case33:

printf("\t\twrite()或read()中应为完整表达式\n");

fprintf(fa1,"\t\twrite()或read()中应为完整表达式\n");

break;

default:

printf("\t\t出现未知错误\n");

fprintf(fa1,"\t\t出现未知错误\n");

}err++;

}

//漏掉空格,读取一个字符,每次读一行,存入line缓冲区,line被getsym取空后再读一//行,被函数getsym调用

intgetch(){

if(cc==ll){

if(feof(fin)){

printf("programincomplete");

return-1;

}

ll=0;

cc=0;

printf("\n%d",cx);

fprintf(fa1,"\n%d",cx);

ch='';

while(ch!

=10){

if(EOF==fscanf(fin,"%c",&ch)){

line[ll]=0;

break;

}printf("%c",ch);

fprintf(fa1,"%c",ch);

line[ll]=ch;

ll++;

}fprintf(cifa,"\n");

}

ch=line[cc];

cc++;

return0;

}

intgetsym(){//词法分析

inti,j,k,l;

while(ch==''||ch==10||ch==9)//忽略空格换行TAB

getchdo;

if(ch>='a'&&ch<='z'){//以字母开头的为保留字或者标识符

k=0,l=1;

do{

if(k

a[k]=ch;

k++;

}

if(k==al&&l==1){

error(25);

l=0;

}getchdo;

}

while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9');

a[k]=0;//末尾存零

strcpy(id,a);

i=0;

j=norw-1;

do{//开始折半查找

k=(i+j)/2;

if(strcmp(id,word[k])<=0){

j=k-1;

}

if(strcmp(id,word[k])>=0){

i=k+1;

}

}while(i<=j);

if(i-1>j){//找到即为保留字

sym=wsym[k];

fprintf(cifa,"%s\t\t%ssym\n",id,id);//printf("%s\t\t%ssym\n",id,id);

}

else{//否则为标识符或数字

sym=ident;

fprintf(cifa,"%s\t\tident\n",id);//printf("%s\t\tident\n",id);

}

}else{

if(ch>='0'&&ch<='9'){

k=0;

num=0;

sym=number;

do{

num=10*num+ch-'0';//数字的数位处理

k++;

getchdo;

}while(ch>='0'&&ch<='9');

k--;

if(k>nmax){//数字的长度限制

fprintf(cifa,"0\t\tnumber\n");

num=0;

error(31);

}else

fprintf(cifa,"%d\t\tnumber\n",num);//printf("%d\t\tnumber\n",num);

}else{

if(ch==':

'){//检测赋值符号,:

只能和=匹配,否则不能识别

getchdo;

if(ch=='='){

sym=becomes;fprintf(cifa,":

=\t\tbecomes\n");

getchdo;

}

else{

sym=nul;

}

}else{

if(ch=='<'){

getchdo;

if(ch=='='){

sym=leq;//小于等于

fprintf(cifa,"<=\t\tleq\n");

getchdo;

}else{

sym=lss;//小于

fprintf(cifa,"<\t\tlss\n");

}

}else{

if(ch=='>'){

getchdo;

if(ch=='='){

sym=geq;//大于等于

fprintf(cifa,">=\t\tgeq\n");

getchdo;

}else{

sym=gtr;//大于

fprintf(cifa,">\t\tgtr\n");

}

}else{

sym=ssym[ch];//不满足上述条件时按单字//符处理

switch(ch){

case'+':

fprintf(cifa,"%c\t\tplus\n",ch);

break;

case'-':

fprintf(cifa,"%c\t\tminus\n",ch);

break;

case'*':

fprintf(cifa,"%c\t\ttimes\n",ch);

break;

case'/':

fprintf(cifa,"%c\t\tslash\n",ch);

break;

case'(':

fprintf(cifa,"%c\t\tlparen\n",ch);

break;

case')':

fprintf(cifa,"%c\t\trparen\n",ch);

break;

case'=':

fprintf(cifa,"%c\t\teql\n",ch);

break;

case',':

fprintf(cifa,"%c\t\tcomma\n",ch);

break;

case'#':

fprintf(cifa,"%c\t\tneq\n",ch);

break;

case';':

fprintf(cifa,"%c\t\tsemicolon\n",ch);

break;

case'.':

break;

default:

error(26);

}

if(sym!

=period){//判断是否结束

getchdo;

}else{

printf("\n");

fprintf(cifa,".\t\tperiod\n");

}

}

}

}

}

}return0;

}

//生成目标代码//目标代码的功能码,层差和位移量

intgen(enumfctx,inty,intz){

if(cx>=cxmax){//如果目标代码索引过大,报错

printf("Programtoolong");

return-1;

}

code[cx].f=x;

code[cx].l=y;

code[cx].a=z;

cx++;

return0;

}

//测试字符串

inttest(bool*s1,bool*s2,intn){

if(!

inset(sym,s1)){//测试sym是否属于s1,不属于则报错n

error(n);

while((!

inset(sym,s1))&&(!

inset(sym,s2))){//检测不通过时,不停获得符号,直到它属于需要或补救的集合

getsymdo;

}

}return0;

}

//编译程序主体

//lev:

当前分程序

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1