编译原理增加数据类型.docx

上传人:b****1 文档编号:656142 上传时间:2023-04-29 格式:DOCX 页数:79 大小:33.52KB
下载 相关 举报
编译原理增加数据类型.docx_第1页
第1页 / 共79页
编译原理增加数据类型.docx_第2页
第2页 / 共79页
编译原理增加数据类型.docx_第3页
第3页 / 共79页
编译原理增加数据类型.docx_第4页
第4页 / 共79页
编译原理增加数据类型.docx_第5页
第5页 / 共79页
编译原理增加数据类型.docx_第6页
第6页 / 共79页
编译原理增加数据类型.docx_第7页
第7页 / 共79页
编译原理增加数据类型.docx_第8页
第8页 / 共79页
编译原理增加数据类型.docx_第9页
第9页 / 共79页
编译原理增加数据类型.docx_第10页
第10页 / 共79页
编译原理增加数据类型.docx_第11页
第11页 / 共79页
编译原理增加数据类型.docx_第12页
第12页 / 共79页
编译原理增加数据类型.docx_第13页
第13页 / 共79页
编译原理增加数据类型.docx_第14页
第14页 / 共79页
编译原理增加数据类型.docx_第15页
第15页 / 共79页
编译原理增加数据类型.docx_第16页
第16页 / 共79页
编译原理增加数据类型.docx_第17页
第17页 / 共79页
编译原理增加数据类型.docx_第18页
第18页 / 共79页
编译原理增加数据类型.docx_第19页
第19页 / 共79页
编译原理增加数据类型.docx_第20页
第20页 / 共79页
亲,该文档总共79页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

编译原理增加数据类型.docx

《编译原理增加数据类型.docx》由会员分享,可在线阅读,更多相关《编译原理增加数据类型.docx(79页珍藏版)》请在冰点文库上搜索。

编译原理增加数据类型.docx

编译原理增加数据类型

//pl0.h

///这个文件中的代码与课本的一致

//对于使用C++的编译器,这句话可以注释掉,但对于C语言不行

//typedefenum{FALSE,TRUE,}bool;

#definenorw16//关键字的个数

#definetxmax100//名字表的容量

#definenmax14//数字的最大位数

#defineal10//符号的最大长度

#defineamax2047//地址上界

#definelevmax3//最大允许的嵌套声明层数

#definecxmax200//最多的虚拟机代码数

 

enumsymbol{

//枚举类型:

//nul=0,ident=1,number=2,plus=3,minus=4

//times=5,依次类推,procsym=31

nul,ident,number,

//下面的表示的是系统的算数运算符以及逻辑运算符,知道意思就可以

plus,minus,times,//相乘的意思

slash,oddsym,eql,neq,

lss,leq,gtr,geq,lparen,//左括号

rparen,comma,semicolon,period,becomes,//赋值的意思

//下面的表示是系统的保留字

beginsym,endsym,ifsym,thensym,whilesym,

writesym,readsym,dosym,callsym,

constsym,varsym,procsym,

integersym,charactersym,doubsym,

charnum,integercon,doubnum

};

#definesymnum38

enumobject{

constant,

variable,

procedur,

integer,

character,

doub,

};

enumfct{

lit,opr,lod,

sto,cal,inte,

jmp,jpc,

};

#definefctnum11

structinstruction

{

enumfctf;//虚拟机代码指令

intl;//引用层与声明层的层差

doublea;//根据f的不同而不同,参考课本

};

FILE*fas;//输出名字表

FILE*fa;//输出虚拟机代码

FILE*fa1;//输出源文件及其各行对应的首地址

FILE*fa2;//输出结果

boollistswitch;

booltableswitch;

charch;//获取字符的缓冲区

enumsymbolsym;

charid[al+1];

doublenum;

intcc,ll;//cc表示当前字符的位置

intcx;//虚拟机代码指针

charline[81];//读取行缓冲区

chara[al+1];//临时符号,多出的一个字节用于表示字符串的结尾

structinstructioncode[cxmax];//存放虚拟机代码的数组

charword[norw][al];//保留字

enumsymbolwsym[norw];//保留字对应的符号值

enumsymbolssym[256];//单符号的符号值

charmnemonic[fctnum][5];//虚拟机代码指令的名称

booldeclbegsys[symnum];//表示声明开始的符号集合

boolstatbegsys[symnum];//表示语句开始的符号集合

boolfacbegsys[symnum];//表示因子开始的符号集合

//名字表结构

structtablestruct

{

charname[al];//名字

//enumdatatypetype;//数据类型:

integer,character,doub,

enumobjectkind;//类型:

const,var,array,procedure

doubleval;//数值,仅const使用,使用双精度浮点型

intlevel;//所处层

intadr;//地址

intsize;//需分配的数据空间

};

structtablestructtable[txmax];//名字表

FILE*fin;

FILE*fout;

charfname[al];

interr;//错误计数器,每出一次错误,其加一

#definegetsymdoif(-1==getsym())return-1

#definegetchdoif(-1==getch())return-1

#definetestdo(a,b,c)if(-1==test(a,b,c))return-1

#definegendo(a,b,c)if(-1==gen(a,b,c))return-1

#defineexpressiondo(a,b,c)if(-1==expression_r(a,b,c))return-1

#definefactordo(a,b,c)if(-1==factor(a,b,c))return-1

#definetermdo(a,b,c)if(-1==term(a,b,c))return-1

#defineconditiondo(a,b,c)if(-1==condition(a,b,c))return-1

#definestatementdo(a,b,c)if(-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-1

#defineintegerdeclarationdo(a,b,c)if(-1==integerdeclaration(a,b,c))return-1

#definecharacterdeclarationdo(a,b,c)if(-1==characterdeclaration(a,b,c))return-1

#definedoubdeclarationdo(a,b,c)if(-1==doubdeclaration(a,b,c))return-1

voiderror(intn);

intgetsym();

intgetch();

voidinit();

intgen(enumfctx,inty,doublez);

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(bool*fsys,int*ptx,intlev);

intcondition(bool*fsys,int*ptx,intlev);

intexpression_r(bool*fsys,int*ptx,intlev);

intstatement(bool*fsys,int*ptx,intlev);

voidlistcode(intcx0);

intvardeclaration(int*ptx,intlev,int*pdx);

intintegerdeclaration(int*ptx,intlev,int*pdx);

intcharacterdeclaration(int*ptx,intlev,int*pdx);

intdoubdeclaration(int*ptx,intlev,int*pdx);

intconstdeclaration(int*ptx,intlev,int*pdx);

intposition(char*idt,inttx);

voidenter(enumobjectk,int*ptx,intlev,int*pdx);

intbase(intl,int*s,intb);

//pl0.cpp

 

#include

#include"pl0.h"

#include"string.h"

//这个宏定义的意思表示是运行时的数据栈大小,这个会在interpret函数中出现,可以先不用管它

#definestacksize500

 

/*********************************************************************************

**在看源程序之前,请始终记住**

**sym表示的是当前字符串的类型,**

**num表示的数字,**

**id中存放的是字符串,**

**记住这点在看源程序的时候非常重要。

**

**另外,还要记住的是nxtlev数组中存放的是后继符号集**

**********************************************************************************/

intmain()

{

boolnxtlev[symnum];//这个数组表示的是当前语句的后继符号集合,一共有个

printf("Inputpl/0file?

");//输入文件的路径

scanf("%s",fname);

fin=fopen(fname,"r");//以只读打开文件,fin文件指针

if(fin)

{

printf("Listobjectcode?

(Y/N)");

scanf("%s",fname);

listswitch=(fname[0]=='y'||fname[0]=='Y');//listswitch用于列举代码

printf("Listsymboltable?

(Y/N)");

scanf("%s",fname);

tableswitch=(fname[0]=='y'||fname[0]=='Y');//tableswitch表示是否输出table表

//该表类似于页的表

fa1=fopen("fa1.tmp","w");//以只读格式打开文件,对于本程序其实是新建一个文件

//fa1文件中存储的是源程序,运行一次,看看这个文件就明白啦

fprintf(fa1,"Inputpl/0file?

");//将"Inputpl/0file?

"输入文件中

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

init();//初始化

err=0;

cc=cx=ll=0;

ch='';

if(-1!

=getsym())

{

//如果程序开始是对的,则往下执行

//fa存放的是模拟程序的代码

//fas存放的是table表中的数据

//运行一次代码看一下文件即明白

fa=fopen("fa.tmp","w");//以只读形式打开

fas=fopen("fas.tmp","w");//同上

//函数原型:

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

//boolnxtlev[32];

/*

declbegsys[constsym]=true;

declbegsys[varsym]=true;

declbegsys[procsym]=true;

statbegsys[beginsym]=true;

statbegsys[callsym]=true;

statbegsys[ifsym]=true;

statbegsys[whilesym]=true;

执行该函数的结果为对应的下标在nxtlev中上述值均为true;

*/

//在分程序开始的时候,其后继符号可以是

//const,var,procedure,begin,call,if,while

//所以在nxtlev中将上述这些置为true

//当然在整个程序可以只有一个'.',即程序是空的也可以,所以会有nxtlev[period]=true;

addset(nxtlev,declbegsys,statbegsys,symnum);//symnum=32;

nxtlev[period]=true;

//block是编译程序的主程序,是分程序的分析处理过程,其里面调用了大部分程序

//耐心看

//请记住在block程序开始的时候,只读取了源程序的一个语句单位

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);

}

//err=0表示源程序没有错误

if(err==0)

{

//在源程序没有错误的前提下,打开fa2文件,依次执行里面的语句,输出源程序结果

fa2=fopen("fa2.tmp","w");

//模拟计算机执行源程序

interpret();

fclose(fa2);

}

else

{

//如果远程有错的话,会这样

printf("Errorsinpl/0program");

}

}

fclose(fin);

}

else

{

printf("Can'topenfile!

\n");

}

printf("\n");

return0;

}

voidinit()

{

inti;

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

{

ssym[i]=nul;//nul为,将ssym初始化为

}

//ssym大小为,可以表示所有的ASCLL码

ssym['+']=plus;

ssym['-']=minus;

ssym['*']=times;

ssym['/']=slash;

ssym['(']=lparen;

ssym[')']=rparen;

ssym['=']=eql;

ssym[',']=comma;

ssym['.']=period;

ssym['#']=neq;

ssym[';']=semicolon;

//将保留字输入word数组中,为了使用二分查找,这个设置顺序是按照字母序

/*strcpy(&(word[0][0]),"begin");

strcpy(&(word[14][0]),"character");

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

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

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

strcpy(&(word[15][0]),"doub");

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

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

strcpy(&(word[13][0]),"integer");

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");*/

strcpy(&(word[0][0]),"begin");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

//wsym内放有保留字所对应的枚举变量的值

wsym[0]=beginsym;

wsym[1]=callsym;

wsym[2]=charactersym;

wsym[3]=constsym;

wsym[4]=dosym;

wsym[5]=doubsym;

wsym[6]=endsym;

wsym[7]=ifsym;

wsym[8]=integersym;

wsym[9]=oddsym;

wsym[10]=procsym;

wsym[11]=readsym;

wsym[12]=thensym;

wsym[13]=varsym;

wsym[14]=whilesym;

wsym[15]=writesym;

//mnemonic中存放的是模拟程序的命令符

//大小是个,因为只有中命令符

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");

//初始化这些数组,全部为false

for(i=0;i

{

declbegsys[i]=false;

statbegsys[i]=false;

facbegsys[i]=false;

}

//下面的这三块内容的功能在后续的介绍中会有,

//分别是声明开始符号集,语句开始符号集,因子开始符号集

declbegsys[constsym]=true;

declbegsys[varsym]=true;

declbegsys[procsym]=true;

declbegsys[integersym]=true;

declbegsys[charactersym]=true;

declbegsys[doubsym]=true;

statbegsys[beginsym]=true;

statbegsys[callsym]=true;

statbegsys[ifsym]=true;

statbegsys[whilesym]=true;

facbegsys[ident]=true;

facbegsys[number]=true;

facbegsys[lparen]=true;

facbegsys[charnum]=true;

facbegsys[doubnum]=true;

}

//该函数的功能是返回符号e是否在符号集s中

//是则返回true,否则返回false

intinset(inte,bool*s)

{

returns[e];

}

//对于下标i,如果s1或s2是true,则sr也是true

//这个函数其实是初始化后继符号集,即nxtlev数组

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

{

inti;

for(i=0;i

{

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

}

return0;

}

//下面的函数不知干什么用,我没找到这两个函数的使用地方,不知道是不是作者弄错啦

intsubset(bool*sr,bool*s1,bool*s2,intn)

{

inti;

for(i=0;i

{

sr[i]=s1[i]&&(!

s2[i]);

}

return0;

}

intmulset(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全部置为空格

space[cc-1]=0;//出错时当前符号已经读完,所以是CC-1

printf("****%s!

%d\n",space,n);

fprintf(fa1,"****%s!

%d\n",space,n);

err++;

}

intgetch()

{

if(cc==ll)

{

if(feof(fin))//fin未知

{

printf("programincomplete"

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

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2