⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zcompile.cpp

📁 扩充PL0语言的编译器
💻 CPP
📖 第 1 页 / 共 2 页
字号:

///////////////////////////////////////////////////////////////
#include"zCompile.h"
///////////////////////////////////////////////////////////////
enum{
	TYPE_ERROR,		//错误类型号
	TYPE_KEYWORD,	//关键字类型号
	TYPE_SYMBOL,	//符号类型号
	TYPE_NUMBER,	//常量类型号
	TYPE_OPWORD,	//运算符类型号
	TYPE_ENDWORD,	//界符类型号
};
enum{FORM_NULL,FORM_PROC,FORM_CONST,FORM_VAR};
const char* const keytxt[MAX_KEYWORD]=		//关键字
{
	"procedure","call","begin","end","var","const",
	"if","then","else","do","read","write",
	"function","integer",
	"real","char","repeat","for","until","to","downto","while"
};
enum
{
	KW_PROCEDURE,KW_CALL,KW_BEGIN,KW_END,KW_VAR,KW_CONST,
	KW_IF,KW_THEN,KW_ELSE,KW_DO,KW_READ,KW_WRITE,
	KW_FUNCTION,KW_INTEGER,
	KW_REAL,KW_CHAR,KW_REPEAT,KW_FOR,
	KW_UNTIL,KW_TO,KW_DOWNTO,KW_WHILE
};
const char opatxt[MAX_OPWORDA]=				//单字运算符
{
	'+','-','*','/','<','>','=','#'
};
const char* const opbtxt[MAX_OPWORDB]=		//双字运算符
{
	"<=",">=",":=","<>"
};
enum
{
	OW_PLUS,OW_MINUS,OW_TIMES,OW_SLASH,
	OW_LT,OW_LG,OW_EQL,OW_NE,OW_LTE,OW_LGE,OW_DEF,OW_SB
};
const char eoptxt[MAX_ENDWORD]=				//单字界符
{
	',',';','(',')','.',':'
};
enum{EW_COMMA,EW_SEM,EW_LP,EW_RP,EW_END,EW_MAO};
const char* oprtxt[MAX_ASMWORD]=			//单字界符
{
	"LIT","LOD","STO","CAL","INT","JMP","JPC","OPR"
};
enum{OP_LIT,OP_LOD,OP_STO,OP_CAL,OP_INT,OP_JMP,OP_JPC,OP_OPR};
enum{
	OPR_RET,OPR_NEG,OPR_ADD,OPR_SUB,OPR_MUL,OPR_DIV,
	OPR_ODD,OPR_NUL,OPR_EQL,OPR_NE ,OPR_LT ,OPR_LGE,
	OPR_LG ,OPR_LTE,OPR_WRT,OPR_WRN,OPR_RED,OPR_SB
};
const char* const errtxt[MAX_ERROR]=		//错误提示信息
{
	"程序结尾有多余字符",				//0  ERR_ERREND
	"",									//1  (Reserved)
	"常数说明中的\'=\'后应是正整数",	//2  ERR_NEEDNUM
	"常数说明中的标识符后应是\'=\'",	//3  ERR_NEEDEQL
	"const,var,procedure后缺少标识符",	//4  ERR_NEEDSYM
	"漏掉了\',\'或\';\'",				//5  ERR_NEEDEND
	"",									//6  (Reserved)
	"",									//7  (Reserved)
	"",									//8  (Reserved)
	"程序结尾丢了\'.\'或结尾不正常",	//9  ERR_NOEND
	"语句之间漏了\';\'或\'end\'",		//10 ERR_NOTSEM
	"标识符未说明",						//11 ERR_NODEFSYM
	"需赋值标识符属性应是变量",			//12 ERR_NOTVAR
	"赋值语句左部标识符后应是\':=\'",	//13 ERR_NOTDEFOP
	"call后应为标识符",					//14 ERR_NOTSYM
	"call后标识符属性应是过程",			//15 ERR_NOTPROC
	"条件语句中缺少\'then\'",			//16 ERR_NOTTHEN
	"read语句中缺少变量",				//17 ERR_NEEDVAR
	"while型循环语句中缺少\'do\'",		//18 ERR_NOTDO
	"",									//19 (Reserved)
	"应为关系运算符",					//20 ERR_NOTRLOP
	"表达式内标识符属性不能是过程",		//21 ERR_NOPROC
	"表达式中缺少\')\'",				//22 ERR_NOTRP
	"表达式中缺少标识符",				//23 ERR_NOSYM
	"表达式开始符不能是此符号",			//24 ERR_WRONGOP
	"标识符太长",						//25 ERR_OVERSYMLEN
	"常数越界",							//26 ERR_OVERNUMLEN
	"常数中含有字母",					//27 ERR_NUMBER
	"未定义的符号",						//28 ERR_NOTDEF
	"过程嵌套层次太多",					//29 ERR_OVERLVL
	"标识符表格溢出",					//30 ERR_OVERFORM
	"read/write中变量缺少括号",			//31 ERR_NOTPAREN
	"目标代码过长",						//32 ERR_OVERASM
	"还有更多的错误没有显示..."			//33 ERR_OVERERR
};
///////////////////////////////////////////////////////////////
zCompile::zCompile()
{
	memset(this,0,sizeof(zCompile));
}
///////////////////////////////////////////////////////////////
int zCompile::getsym()
{
	int i,n=0,e=0;				//序号/字符数/出错标记
	int d=0;
	i=sym.line;
	memset(&sym,0,sizeof(SYM1));
	sym.line=i;
	while(!ISCHAR(*text))			//滤出前面的非字符
	{
		if(*text=='\n') sym.line++;	//换行时,ln++
		if(!*text) return 0;		//如果无字符则退出
		text++;
	}
	if(ISLETTER(*text))				//字母开头情况
	{
		while(ISLETTER(*text)||ISNUMBER(*text))
		{
			if(n<=MAX_SYMLEN) sym.name[n]=*text;
			n++; text++;
		}
		sym.name[MAX_SYMLEN]=0;		//符号结尾置0
		if(n>MAX_SYMLEN)			//超出符号最大长度
		{
			sym.type=TYPE_ERROR;
			sym.id=ERR_OVERSYMLEN;
			adderr(sym.name,ERR_OVERSYMLEN);
		}
		else
		{
			for(i=0;i<MAX_KEYWORD;i++)
				if(strcmp(sym.name,keytxt[i])==0) break;
			if(i<MAX_KEYWORD)		//属于关键字
			{
				sym.type=TYPE_KEYWORD;
				sym.id=i;
			}
			else					//不属于关键字
			{
				sym.type=TYPE_SYMBOL;	//符号类型
				sym.id=0;
			}
		}
		return n;
	}
	if(*text=='^'||*text=='&')//^=====+;&=====-
	{
		if(*text=='^')
		{
			if(n<=MAX_SYMLEN) sym.name[n]='+';
					n++; text++;
			if(ISNUMBER(*text))				//数字开头情况
			{
				e=0;
				while(ISNUMBER(*text)||ISLETTER(*text)||*text=='.')
				{
					if(ISLETTER(*text)) e=1;//含字母则置出错标记
					if(n<=MAX_SYMLEN) sym.name[n]=*text;
					n++; text++;
				}
				sym.name[MAX_SYMLEN]=0;		//数字尾置0
				sym.type=TYPE_NUMBER;
				sym.id=atoi(sym.name);
				if(e)						//含字母情况
					adderr(sym.name,ERR_NUMBER);
				else
				if(n>MAX_NUMLEN||sym.id>MAX_NUMBER)	//超出数字最大长度情况
					adderr(sym.name,ERR_OVERNUMLEN);
				return n;
			}
		}
		else 
		{
			if(n<=MAX_SYMLEN) sym.name[n]='-';
					n++; text++;
			if(ISNUMBER(*text))				//数字开头情况
			{
				e=0;
				while(ISNUMBER(*text)||ISLETTER(*text)||*text=='.')
				{
					if(ISLETTER(*text)) e=1;//含字母则置出错标记
					if(n<=MAX_SYMLEN) sym.name[n]=*text;
					n++; text++;
				}
				sym.name[MAX_SYMLEN]=0;		//数字尾置0
				sym.type=TYPE_NUMBER;
				sym.id=atoi(sym.name);
				if(e)						//含字母情况
					adderr(sym.name,ERR_NUMBER);
				else
				if(n>MAX_NUMLEN||sym.id>MAX_NUMBER)	//超出数字最大长度情况
					adderr(sym.name,ERR_OVERNUMLEN);
				return n;
			}
		}
	}
	if(ISNUMBER(*text))				//数字开头情况
	{
		e=0;
		while(ISNUMBER(*text)||ISLETTER(*text)||*text=='.')
		{
			if(ISLETTER(*text)) e=1;//含字母则置出错标记
			if(n<=MAX_SYMLEN) sym.name[n]=*text;
			n++; text++;
		}
		sym.name[MAX_SYMLEN]=0;		//数字尾置0
		sym.type=TYPE_NUMBER;
		sym.id=atoi(sym.name);
		if(e)						//含字母情况
			adderr(sym.name,ERR_NUMBER);
		else
			if(n>MAX_NUMLEN||sym.id>MAX_NUMBER)	//超出数字最大长度情况
				adderr(sym.name,ERR_OVERNUMLEN);
		return n;
	}
	for(i=0;i<MAX_OPWORDB;i++)		//双字运算符情况
		if(*(short*)text==*(short*)(opbtxt[i])) break;
	if(i<MAX_OPWORDB)
	{
		sym.type=TYPE_OPWORD;
		sym.id=MAX_OPWORDA+i;
		*(short*)sym.name=*(short*)opbtxt[i];
		sym.name[2]=0;
		text+=2;
		return 2;
	}
	sym.name[0]=*text;
	sym.name[1]=0;
	for(i=0;i<MAX_OPWORDA;i++)		//单字运算符情况
		if(*text==opatxt[i]) break;
	if(i<MAX_OPWORDA)
	{
		sym.type=TYPE_OPWORD;
		sym.id=i;
		text++;
		return 1;
	}
	for(i=0;i<MAX_ENDWORD;i++)		//单字界符情况
		if(*text==eoptxt[i]) break;
	if(i<MAX_ENDWORD)
	{
		sym.type=TYPE_ENDWORD;
		sym.id=i;
		text++;
		return 1;
	}
	sym.type=TYPE_ERROR;
	sym.id=ERR_NOTDEF;				//其他符号则出错
	adderr(sym.name,ERR_NOTDEF);
	text++;
	return 1;
}
///////////////////////////////////////////////////////////////
int zCompile::addasm(char opr,char lvl,short adr)
{
	if(asmnum==MAX_ASM)
	{
		adderr("",ERR_OVERASM);
		return 1;
	}
	asms[asmnum].opr=opr;
	asms[asmnum].lvl=lvl;
	asms[asmnum].adr=adr;
	asmnum++;
	return 0;
}
///////////////////////////////////////////////////////////////
int zCompile::adderr(char *name,int id)
{
	if(errnum==MAX_ERR) return 1;
	*err[errnum].name=0;
	strcpy(err[errnum].name,name);
	err[errnum].id=id;
	err[errnum].line=sym.line;
	errnum++;
	if(errnum==MAX_ERR-1)
		adderr("",ERR_OVERERR);
	return 0;
}
///////////////////////////////////////////////////////////////
int zCompile::getasm(char *buf)
{
	int n=0;
	char b[20];
	for(int i=0;i<asmnum;i++)
	{
		sprintf(b,"%04u:%s %u %u\r\n",i,oprtxt[asms[i].opr],asms[i].lvl,asms[i].adr);
		strcpy(buf+n,b);
		n+=strlen(b);
		if(!i||asms[i].opr==OP_OPR&&!asms[i].adr)
		{
			strcpy(buf+n,"\r\n");
			n+=2;
		}
	}
	buf[n]=0;
	return i;
}
///////////////////////////////////////////////////////////////
int zCompile::geterr(char *buf)
{
	int n=0;
	char b[128];
	for(int i=0;i<errnum;i++)
	{
		sprintf(b,"Line(%u):error[%u]:%s",err[i].line,err[i].id,errtxt[err[i].id],err[i].name);
		strcpy(buf+n,b);
		n+=strlen(b);
		if(*err[i].name)
		{
			sprintf(b,":\"%s\"",err[i].name);
			strcpy(buf+n,b);
			n+=strlen(b);
		}
		strcpy(buf+n,"\r\n");
		n+=2;
	}
	sprintf(b,"\r\n%u error(s)",errnum);
	strcpy(buf+n,b);
	buf[n+strlen(b)]=0;
	return i;
}
///////////////////////////////////////////////////////////////
int zCompile::formpush(char *name,int type,int id)
{
	if(formnum==MAX_FORM)
	{
		adderr("",ERR_OVERFORM);
		return 1;
	}
	if(formlvl>=MAX_LEVEL)
	{
		adderr("",ERR_OVERLVL);
		return 2;
	}
	form[formnum].type=type;
	strcpy(form[formnum].name,name);
	form[formnum].lvl=formlvl;
	if(type==FORM_PROC)
	{
		formlvl++;
		formadr[formlvl]=3;
	}
	if(type==FORM_VAR)
		form[formnum].adr=formadr[formlvl]++;
	else
		form[formnum].adr=id;
	formnum++;
	return 0;
}
///////////////////////////////////////////////////////////////
int zCompile::formpop()
{
	if(!formnum||!formlvl) return 1;
	for(;form[--formnum].lvl==formlvl;);
	formnum++;
	formlvl--;
	return 0;
}
///////////////////////////////////////////////////////////////
int zCompile::formget(char *name,FORM1 *fm)
{
	for(int i=formnum-1;i>=0;i--)
		if(!strcmp(form[i].name,name))
		{
			memcpy(fm,&form[i],sizeof(FORM1));
			return i;
		}
	return -1;
}
///////////////////////////////////////////////////////////////
void zCompile::compile(char *txt)
{
	memset(this,0,sizeof(zCompile));
	text=txt;
	sym.line=1;
	formadr[0]=3;
	addasm(OP_JMP,0,1);
	if(getsym())
		asms[0].adr=syn_block();
	addasm(OP_OPR,0,OPR_RET);
	do{
		if(sym.type==TYPE_ENDWORD&&sym.id==EW_END)
		{
			if(getsym()) adderr("",ERR_ERREND);
			return;
		}
		else
			break;
	}while(getsym());
	adderr("",ERR_NOEND);
}
///////////////////////////////////////////////////////////////
int zCompile::syn_block()
{
	char t[MAX_SYMLEN+1];
	int s;
	if(sym.type==TYPE_KEYWORD&&sym.id==KW_CONST)
	{
_nextconst:
		getsym();
		if(sym.type==TYPE_SYMBOL)
		{
			strcpy(t,sym.name);
			getsym();
			if(sym.type==TYPE_OPWORD&&sym.id==OW_EQL)
			{
				getsym();
				if(sym.type==TYPE_NUMBER)
				{
					formpush(t,FORM_CONST,sym.id);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -