PL0源代码C语言版.docx

上传人:b****8 文档编号:28207639 上传时间:2023-07-09 格式:DOCX 页数:62 大小:26.96KB
下载 相关 举报
PL0源代码C语言版.docx_第1页
第1页 / 共62页
PL0源代码C语言版.docx_第2页
第2页 / 共62页
PL0源代码C语言版.docx_第3页
第3页 / 共62页
PL0源代码C语言版.docx_第4页
第4页 / 共62页
PL0源代码C语言版.docx_第5页
第5页 / 共62页
点击查看更多>>
下载资源
资源描述

PL0源代码C语言版.docx

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

PL0源代码C语言版.docx

PL0源代码C语言版

.

 

/*PL/0编译系统C版本头文件pl0.h*/

#definenorw13

//anumberofreservedword

/*关键字个数*/

#definetxmax100

//lengthofidentifiertable

/*名字表容量*/

#definenmax14

//maxnumberofdigitsinnumbers

/*number的最大位数*/

#defineal10

//lengthofidentifier

/*符号的最大长度*/

#defineamax2047

//maximumaddress

/*地址上界*/

#definelevmax3

//maxdepthofblocknesting

/*最大允许过程嵌套声明层数

[0,lexmax]*/

#definecxmax200

//sizeofcodearray

/*最多的虚拟机代码数

*/

/*符号*/

enumsymbol{

nul,

ident,

number,

plus,

minus,

times,

slash,oddsym,

eql,

neq,//slash斜线

lss,

leq,

gtr,

geq,

lparen,//leq

:

lessthanorequalto;gtr:

great

than;lparen:

leftparenthesis

rparen,

comma,

semicolon,period,

becomes,//comma

逗号semicolon

分号period句号

becomes赋值号

beginsym,endsym,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;

//P23

};

FILE*fas;

//输出名字表

 

.

.

 

FILE*fa;

//输出虚拟机代码

FILE*fa1;

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

FILE*fa2;

//输出结果

booltableswitch;

//显示名字表与否

boollistswitch;

//显示虚拟机代码与否

charch;

//获取字符的缓冲区,getch使用

enumsymbolsym;

//当前符号

charid[al+1];

//当前ident,多出一个字节用于存放0

intnum;

//当前number

intcc,ll;

//getch使用的计数器,cc表示当前字符(ch)的位置

intcx;

//虚拟机代码指针,取值范围[0,cxmax-1]

charline[81];

//读取行缓冲区

chara[al+1];

//临时符号,多出的一个字节用于存放

0

structinstructioncode[cxmax];

//存放虚拟机代码的数组

charword[norw][al];

//保留字

enumsymbolwsym[norw];

//保留字对应的符号值

enumsymbolssym[256];

//单字符的符号值

charmnemonic[fctnum][5];

//虚拟机代码指令名称

booldeclbegsys[symnum];

//表示声明开始的符号集合

declaringbeginsymbolset

boolstatbegsys[symnum];

//表示语句开始的符号集

statement

boolfacbegsys[symnum];

//表示因子开始的符号集合

factor

/*------------------------------*/

 

structtablestruct

{

charname[al];/*名字*/

enumobjectkind;/*类型:

const,var,arrayorprocedure*/

intval;/*数值,仅const使用*/

intlevel;/*所处层,仅const不使用*/

intadr;/*地址,仅const不使用*/

intsize;/*需要分配的数据区空间,仅procedure使

用*/

};

structtablestructtable[txmax];/*名字表*/

FILE*fin;//fin文本文件用于指向输入的源程序文件

FILE*fout;//fout文本文件用于指向输出的文件

charfname[al];

interr;/*错误计数器*/

/*当函数中会发生fatalerror时,返回-1告知调用它的函数,最终退出程序*/

#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(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

voiderror(intn);

intgetsym();

intgetch();

voidinit();

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

intbase(intl,int*s,intb);

 

.

.

 

//A.2C版本

 

/*编译和运行环境:

*1VisualC++6.0,VisualC++.NETandVisualC++.NET2003

*WinNT,Win200,WinXPand

Win2003

*2gccversion3.3.220031022(RedHatLinux3.3.2-1)

*RedhatFedoracore1

*Intel32platform

*使用方法:

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

*回答是否输出虚拟机代码

*回答是否输出名字表

*fa.tmp输出虚拟机代码

*fa1.tmp输出源文件及其各行对应的首地址

*fa2.tmp输出结果

*fas.tmp输出名字表

*/

#include

#include"pl0.h"

#include"string.h"

/*解释执行时使用的栈*/

#definestacksize500

intmain()

{

boolnxtlev[symnum];

printf("Inputpl/0file?

");

scanf("%s",fname);/*输入文件名*/

fin=fopen(fname,"r");//返回值:

文件顺利打开后,指向该流的文件指针就会被返回。

如果文件打开失败则返回NULL,并把错误代码存在errno中

if(fin)

{

printf("Listobjectcode?

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

scanf("%s",fname);

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

printf("Listsymboltable?

(Y/N)");/*是否输出名字表*/

scanf("%s",fname);

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

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

fprintf(fa1,"Iputpl/0file?

");

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

init();/*初始化*/

err=0;//错误计数器置0

cc=cx=ll=0;

ch='';

 

.

.

 

if(-1!

=getsym())

{

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

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

addset(nxtlev,declbegsys,statbegsys,symnum);

nxtlev[period]=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);

}

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;//ssym:

单字符的符号值

}

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;

}

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);printf("-------%c\n",ch);

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

printf("****%s!

%d\n",space,n);

err++;

}

/*

*漏掉空格,读取一个字符

*

*每次读一行,存入line缓冲区,line被getsym取空后再读一行

*

*被函数getsym调用

 

.

.

 

*/

intgetch()

{

if(cc==ll)

{

if(feof(fin))//如果文件结束,则返回非0值,否则返回0,文件结束符只能被

clearerr()清除。

{

printf("programincomplete");

return-1;

}

ll=0;

cc=0;

printf("%d",cx);

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

ch='';

while(ch!

=10)

{

//fscanf(fin,"%c",&ch)

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

{

line[ll]=0;

break;

}

printf("%c",ch);

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

line[ll]=ch;

ll++;

}

printf("\n");

fprintf(fa1,"\n");

}

ch=line[cc];

cc++;

return0;

}

/*词法分析,获取一个符号流程图P19

*/

 

intgetsym()

{

inti,j,k;

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

{

 

.

.

 

getchdo;//getchdo:

if(-1==getch())return-1

}

if(ch>='a'&&ch<='z')

{

k=0;

do{

if(k

{

a[k]=ch;

k++;

}

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

}

else

{

sym=ident;

}

}

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)

{

error(30);

}

}

else

{

if(ch==':

')/*检测赋值符号*/

{

getchdo;

if(ch=='=')

{

sym=becomes;

getchdo;

}

else

{

sym=nul;/*不能识别的符号*/

}

}

else

{

if(ch=='<')/*检测小于或小于等于符

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

当前位置:首页 > 自然科学 > 物理

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

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