用C语言写PL0编译器

#include
/*#include"pl0.h"*/
#include"string.h"
#include 

/*PL/0编译系统C版本头文件pl0.h*/
/*typedef enum{false,true}bool;*/
#define norw 13
#define txmax 100
#define nmax 14
#define al 10
#define amax 2047
#define levmax 3
#define cxmax 200

enum symbol{
	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,
};
#define symnum 32

enum object{
	constant,
	variable,
	procedur,
};

enum fct{
	lit,opr,lod,sto,cal,inte,jmp,jpc,
};
#define fctnum 8

struct instruction
{
	enum fct f;
	int l;
	int a;
};
FILE* fas;
FILE* fa;
FILE* fa1;
FILE* fa2;
bool listswitch;
bool tableswitch;
char ch;
enum symbol sym;
char id[al+1];
int num;
int cc,ll;
int cx;
char line[81];
char a[al+1];
struct instruction code[cxmax];
char word[norw][al];
enum symbol wsym[norw];
enum symbol ssym[256];
char mnemonic[fctnum][5];
bool declbegsys[symnum];
bool statbegsys[symnum];
bool facbegsys[symnum];

struct tablestruct
{
	char name[al];
	enum object kind;
	int val;
	int level;
	int adr;
	int size;
};
struct tablestruct table[txmax];
FILE* fin;
FILE* fout;
char fname[al];
int err;

#define getsymdo if(-1==getsym())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 expressiondo(a,b,c) if(-1==expression(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))return -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 -1
void error(int n);
int getsym();
int getch();
void init();
int gen(enum fct x,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 tx,bool* fsys);
void interpret();
int factor(bool* fsys,int* ptx,int lev);
int term(bool* fsys,int* ptx,int lev);
int condition(bool* fsys,int* ptx,int lev);
int expression(bool* fsys,int* ptx,int lev);
int statement(bool* fsys,int* ptx,int lev);
void listcode(int cx0);
int vardeclaration(int* ptx,int lev,int* pdx);
int constdeclaration(int* ptx,int lev,int*pdx);
int position(char* idt,int tx);
void enter(enum object k,int* ptx,int lev,int* pdx);
int base(int l,int* s,int b);








#define stacksize 500
int main()
{
	bool nxtlev[symnum];
	printf("Input pl/0 file?");
	scanf("%s",fname);
	fin=fopen(fname,"r");
	if(fin)
	{
		printf("List object code? (Y/N)");
		scanf("%s",fname);
		listswitch=(fname[0]=='y'||fname[0]=='Y');
		printf("List symbol table?(Y/N)");
		scanf("%s",fname);
		tableswitch=(fname[0]=='y'||fname[0]=='Y');
		fa1=fopen("fa1.tmp","w");
		fprintf(fa1,"Input pl/0 file?");
		fprintf(fa1,"%s\n",fname);
		init();
		err=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");
				return 0;
			}
			fclose(fa);
			fclose(fa1);
			fclose(fas);
			if(sym!=period)
			{
				error(9);
			}
			if(err==0)
			{
				fa2=fopen("fa2.tmp","w");
				interpret();
				fclose(fa2);
			}
			else
			{
				printf("Errors in pl/0 program");
			}
		}
		fclose(fin);
	}
	else
	{
		printf("Can't open file!\n");
	}
	printf("\n");
	return 0;
}
void init()
{
	int i;
	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='a'&&ch<='z')
	{
		k=0;
		do{
			if(k='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=='<')
				{
					getchdo;
					if(ch=='=')
					{
						sym=leq;
						getchdo;
					}
					else
					{
						sym=lss;
					}
				}
				else
				{
					if(ch=='>')
					{
						getchdo;
						if(ch=='=')
						{
							sym=geq;
							getchdo;
						}
						else
						{
							sym=gtr;
						}
					}
					else
					{
						sym=ssym[ch];
						if(sym!=period)
						{
							getchdo;
						}
					}
				}
			}
		}
	}
	return 0;
}




int gen(enum fct x,int y,int z)
{
	if(cx>=cxmax)
	{
		printf("Program too long");
		return -1;
	}
	code[cx].f=x;
	code[cx].l=y;
	code[cx].a=z;
	cx++;
	return 0;
}



int test(bool *s1,bool *s2,int n)
{
	if(!inset(sym,s1))
	{
		error(n);
		while((!inset(sym,s1))&&(!inset(sym,s2)))
		{
			getsymdo;
		}
	}
	return 0;
}



int block(int lev,int tx,bool *fsys)
{
	int i;
	int dx;
	int tx0;
	int cx0;
	bool nxtlev[symnum];
	dx=3;
	tx0=tx;
	table[tx].adr=cx;
	gendo(jmp,0,0);
	if(lev>levmax)
	{
		error(32);
	}
	do{
		if(sym==constsym)
		{
			getsymdo;
			do{
				constdeclarationdo(&tx,lev,&dx);
				while(sym==comma)
				{
					getsymdo;
					constdeclarationdo(&tx,lev,&dx);
				}
				if(sym==semicolon)
				{
					getsymdo;
				}
				else
				{
					error(5);
				}
			}while(sym==ident);
		}
		if(sym==varsym)
		{
			getsymdo;
			do{
				vardeclarationdo(&tx,lev,&dx);
				while(sym==comma)
				{
					getsymdo;
					vardeclarationdo(&tx,lev,&dx);
				}
				if(sym==semicolon)
				{
					getsymdo;
				}
				else
				{
					error(5);
				}
			}while(sym==ident);
		}
		while(sym==procsym)
		{
			getsymdo;
			if(sym==ident)
			{
				enter(procedur,&tx,lev,&dx);
				getsymdo;
			}
			else
			{
				error(4);
			}
			if(sym==semicolon)
			{
				getsymdo;
			}
			else
			{
				error(5);
			}
			memcpy(nxtlev,fsys,sizeof(bool)* symnum);
			nxtlev[semicolon]=true;
			if(-1==block(lev+1,tx,nxtlev))
			{
				return -1;
			}
			if(sym==semicolon)
			{
				getsymdo;
				memcpy(nxtlev,statbegsys,sizeof(bool)* symnum);
				nxtlev[ident]=true;
				nxtlev[procsym]=true;
				testdo(nxtlev,fsys,6);
			}
			else
			{
				error(5);
			}
		}
		memcpy(nxtlev,statbegsys,sizeof(bool)* symnum);
		nxtlev[ident]=true;
		nxtlev[period]=true;
		testdo(nxtlev,declbegsys,7);
	}while(inset(sym,declbegsys));
	code[table[tx0].adr].a=cx;
	table[tx0].adr=cx;
	table[tx0].size=dx;

	cx0=cx;
	gendo(inte,0,dx);
	if(tableswitch)
	{
		printf("TABLE:\n");
		if(tx0+1>tx)
		{
			printf("NULL\n");
		}
		for(i=tx0+1;i<=tx;i++)
		{
			switch(table[i].kind)
			{
			case constant:
				printf(" %d const %s ",i,table[i].name);
				printf(" val=%d\n",table[i].val);
				fprintf(fas," %d const %s ",i,table[i].name);
				fprintf(fas," val=%d\n",table[i].val);
				break;
			case variable:
				printf(" %d var %s ",i,table[i].name);
				printf(" lev=%d addr=%d\n",table[i].level,table[i].adr);
				fprintf(fas," %d var %s ",i,table[i].name);
				fprintf(fas," lev=%d addr=%d\n",table[i].level,table[i].adr);
				break;
			case procedur:
				printf(" %d proc %s ",i,table[i].name);
				printf(" lev=%d addr=%d size=%d\n",table[i].level,table[i].adr,table[i].size);
				fprintf(fas," %d proc %s ",i,table[i].name);
				fprintf(fas," lev=%d addr=%d size=%d\n",table[i].level,table[i].adr,table[i].size);
				break;
			}
		}
		printf("\n");
	}
	memcpy(nxtlev,fsys,sizeof(bool)* symnum);
	nxtlev[semicolon]=true;
	nxtlev[endsym]=true;
	statementdo(nxtlev,&tx,lev);
	gendo(opr,0,0);
	memset(nxtlev,0,sizeof(bool)* symnum);
	testdo(fsys,nxtlev,8);
	listcode(cx0);
	return 0;
}




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[(*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(table[0].name,idt);
	i=tx;
	while(strcmp(table[i].name,idt)!=0)
	{
		i--;
	}
	return i;
}



int constdeclaration(int* ptx,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;
			}
			else
			{
				error(2);
			}
		}
		else
		{
			error(3);
		}
	}
	else
	{
		error(4);
	}
	return 0;
}




int vardeclaration(int* ptx,int lev,int* pdx)
{
	if(sym==ident)
	{
		enter(variable,ptx,lev,pdx);
		getsymdo;
	}
	else
	{
		error(4);
	}
	return 0;
}




void listcode(int cx0)
{
	int i;
	if(listswitch)
	{
		for(i=cx0;iamax)
				{
					error(31);
					num=0;
				}
				gendo(lit,0,num);
				getsymdo;
			}
			else
			{
				if(sym==lparen)
				{
					getsymdo;
					memcpy(nxtlev,fsys,sizeof(bool)* symnum);
					nxtlev[rparen]=true;
					expressiondo(nxtlev,ptx,lev);
					if(sym==rparen)
					{
						getsymdo;
					}
					else
					{
						error(22);
					}
				}
				testdo(fsys,facbegsys,23);
			}
		}
	}
	return 0;
}




int condition(bool* fsys,int* ptx,int lev)
{
	enum symbol relop;
	bool nxtlev[symnum];
	if(sym==oddsym)
	{
		getsymdo;
		expressiondo(fsys,ptx,lev);
		gendo(opr,0,6);
	}
	else
	{
		memcpy(nxtlev,fsys,sizeof(bool)* symnum);
		nxtlev[eql]=true;
		nxtlev[neq]=true;
		nxtlev[lss]=true;
		nxtlev[leq]=true;
		nxtlev[gtr]=true;
		nxtlev[geq]=true;
		expressiondo(nxtlev,ptx,lev);
		if(sym!=eql&&sym!=neq&&sym!=lss&&sym!=leq&&sym!=gtr&&sym!=geq)
		{
			error(20);
		}
		else
		{
			relop=sym;
			getsymdo;
			expressiondo(fsys,ptx,lev);
			switch(relop)
			{
			case eql:
				gendo(opr,0,8);
				break;
			case neq:
				gendo(opr,0,9);
				break;
			case lss:
				gendo(opr,0,10);
				break;
			case geq:
				gendo(opr,0,11);
				break;
			case gtr:
				gendo(opr,0,12);
				break;
			case leq:
				gendo(opr,0,13);
				break;
			}
		}
	}
	return 0;
}




void interpret()
{
	int p,b,t;
	struct instruction i;
	int s[stacksize];
	printf("start pl0\n");
	t=0;
	b=0;
	p=0;
	s[0]=s[1]=s[2]=0;
	do{
		i=code[p];
		p++;
		switch(i.f)
		{
		case lit:
			s[t]=i.a;
			t++;
			break;
		case opr:
			switch(i.a)
			{
			case 0:
				t=b;
				p=s[t+2];
				b=s[t+1];
				break;
			case 1:
				s[t-1]=-s[t-1];
				break;
			case 2:
				t--;
				s[t-1]=s[t-1]+s[t];
				break;
			case 3:
				t--;
				s[t-1]=s[t-1]-s[t];
				break;
			case 4:
				t--;
				s[t-1]=s[t-1]*s[t];
				break;
			case 5:
				t--;
				s[t-1]=s[t-1]/s[t];
				break;
			case 6:
				s[t-1]=s[t-1]%2;
				break;
			case 8:
				t--;
				s[t-1]=(s[t-1]==s[t]);
				break;
			case 9:
				t--;
				s[t-1]=(s[t-1]!=s[t]);
				break;
			case 10:
				t--;
				s[t-1]=(s[t-1]=s[t]);
				break;
			case 12:
				t--;
				s[t-1]=(s[t-1]>s[t]);
				break;
			case 13:
				t--;
				s[t-1]=(s[t-1]<=s[t]);
				break;
			case 14:
				printf("%d",s[t-1]);
				fprintf(fa2,"%d",s[t-1]);
				t--;
				break;
			case 15:
				printf("\n");
				fprintf(fa2,"\n");
				break;
			case 16:
				printf("?");
				fprintf(fa2,"?");
				scanf("%d",&(s[t]));
				fprintf(fa2,"%d\n",s[t]);
				t++;
				break;
			}
			break;
			case lod:
				s[t]=s[base(i.l,s,b)+i.a];
				t++;
				break;
			case sto:
				t--;
				s[base(i.l,s,b)+i.a]=s[t];
				break;
			case cal:
				s[t]=base(i.l,s,b);
				s[t+1]=b;
				s[t+2]=p;
				b=t;
				p=i.a;
				break;
			case inte:
				t+=i.a;
				break;
			case jmp:
				p=i.a;
				break;
			case jpc:
				t--;
				if(s[t]==0)
				{
					p=i.a;
				}
				break;
		}
	}while(p!=0);
}




int base(int l,int* s,int b)
{
	int b1;
	b1=b;
	while(l>0)
	{
		b1=s[b1];
		l--;
	}
	return b1;
}



 

你可能感兴趣的:(用C语言写PL0编译器)