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

📄 yacc.cpp

📁 一个编译器原码
💻 CPP
字号:
#include "compile.h"

//******************************************************************/
//函数原型:void enterTable(int k)
//参数说明:k: 标识符类型
//函数功能:把标识符放入符号表
//返回值  :无
//******************************************************************/
void enterTable(int k)
{
	tableCount++;//注:table[0]不存放内容。当position()函数返回0时,表示未找到。
	table[tableCount].kind=k;
	table[tableCount].offSet=stackCount;
	strcpy( table[tableCount].name, ident);//ident是词法分析中填入的当前标识符

	dataStack[stackCount++]=0;//初始化变量的植为0

	return;
}

//******************************************************************/
//函数原型:int position(char *id)
//参数说明:id: 被查找的标识符
//函数功能:查找标识符id在table中的位置
//返回值  :如果找到,返回该标识符在table中的下标;否则返回0
//******************************************************************/
int position(char *id)
{
	int i=tableCount;
	while(i>0)
	{
		if( strcmp(table[i].name,id) == 0 )//发现匹配
			break;
		else
			i--;
	}
	return i;
}

//******************************************************************/
//函数原型:void gen(int i, int j)
//参数说明:i: 目标代码类型
//			j: 目标代码参数,一般代表位移
//函数功能:产生一条目标代码
//返回值  :无
//******************************************************************/
void gen(int i, int j)
{
	code[codeCount].funCode=i;
	code[codeCount++].offset=j;
}

//******************************************************************/
//函数原型:void yacc_prog()
//参数说明:无
//函数功能:语法分析分程序之prog
//返回值  :无
//******************************************************************/
void yacc_prog()
{
	if(sym != PROGRAM)
		errorOccur(1);//缺少关键字program
	else
		getSym();
	yacc_ds();
	if(sym != BEGIN)
		errorOccur(2);//缺少关键字begin
	else
		getSym();
	yacc_ss();
	if(sym != END)
		errorOccur(3);//缺少关键字end
	else
		printf("yacc completed\n");

	return;
}

//******************************************************************/
//函数原型:void yacc_ds()
//参数说明:无
//函数功能:语法分析分程序之ds
//返回值  :无
//******************************************************************/
void yacc_ds()
{
	yacc_d();
	while(sym == SEMICOLON)
	{
		getSym();
		yacc_d();
	}
	gen(INT,stackCount);//stackCount表示当前数据栈的大小,也就是变量的个数,需要为这些变量预留空间
	return;
}

//******************************************************************/
//函数原型:void yacc_ss()
//参数说明:无
//函数功能:语法分析分程序之ss
//返回值  :无
//******************************************************************/
void yacc_ss()
{
	yacc_s();
	while(sym == SEMICOLON)
	{
		getSym();
		yacc_s();
	}
	return;
}

//******************************************************************/
//函数原型:void yacc_d()
//参数说明:无
//函数功能:语法分析分程序之d
//返回值  :无
//******************************************************************/
void yacc_d()
{
	switch(sym)
	{
	case INTEGER:
		getSym();
		if(sym != IDENT)
			errorOccur(4);//缺少一个标识符,语法分析中止
		else
		{
			enterTable(INTEGER);
			getSym();
			while(sym == COMMA)
			{
				getSym();
				if(sym != IDENT)
					errorOccur(4);//缺少一个标识符,语法分析中止
				else
				{
					enterTable(INTEGER);
					getSym();
				}
			}
		}
		break;

	case LOGICAL:
		getSym();
		if(sym != IDENT)
			errorOccur(4);//缺少一个标识符,语法分析中止
		else
		{
			enterTable(LOGICAL);
			getSym();
			while(sym == COMMA)
			{
				getSym();
				if(sym != IDENT)
					errorOccur(4);//缺少一个标识符,语法分析中止
				else
				{
					enterTable(LOGICAL);
					getSym();
				}
			}
		}
		break;
	}

	return;
}

//******************************************************************/
//函数原型:void yacc_s()
//参数说明:无
//函数功能:语法分析分程序之s
//返回值  :无
//******************************************************************/
void yacc_s()
{
	int i;
	int temp,temp2;

	switch(sym)
	{
	/********************* IDENT *********************/
	case IDENT:
		i=position(ident);//ident是词法分析中填入的当前标识符
		if(i == 0)
			errorOccur(5);//标识符未定义,定义后才可以使用

		/************ INTEGER *************/
		if(table[i].kind == INTEGER)
		{
			temp=table[i].offSet;
			getSym();
			if(sym != BECOMES)
				errorOccur(6);//此处需要有:=
			else
				getSym();
			yacc_ae();
			gen(STO,temp);
		}
		/************ LOGICAL *************/
		else
		{
			temp=table[i].offSet;
			getSym();
			if(sym != BECOMES)
				errorOccur(6);//此处需要有:=
			else
				getSym();
			yacc_be();
			gen(STO,temp);
		}
		break;

	/********************** IF ***********************/
	case IF:
		getSym();
		yacc_be();
		temp=codeCount;//记下目标代码的序号,也即下面gen()产生的跳转指令的序号,用于以后回填
		gen(JPC,0);
		if(sym != THEN)
			errorOccur(7);//缺少关键字then
		else
			getSym();
		yacc_ss();
		if(sym == ELSE)
		{
			//ELSE
			code[temp].offset=codeCount;//回填if语句的假出口
			getSym();
			yacc_ss();
		}
		//END
		if(sym != END)
			errorOccur(3);//缺少关键字end
		else
		{
			if(code[temp].offset == 0)
			{
				//假如条件成立,表示该if语句没有else分句,
				//所以上面的回填没有执行,需要在此处回填
				code[temp].offset=codeCount;
			}
			getSym();
		}
		break;

	/********************* WHILE *********************/
	case WHILE:
		getSym();
		temp2=codeCount;//记下目标代码的序号,也即条件判断语句的起始序号,用于一次循环后跳转回来
		yacc_be();
		temp=codeCount;//记下目标代码的序号,也即下面gen()产生的跳转指令的序号,用于以后回填
		gen(JPC,0);
		if(sym != DO)
			errorOccur(8);//缺少关键字do
		else
			getSym();
		yacc_ss();
		if(sym != END)
			errorOccur(3);//缺少关键字end
		else
		{
			gen(JMP,temp2);//跳转到条件判断语句的起始序号
			code[temp].offset=codeCount;//回填while语句的出口
			getSym();
		}
		break;

	/********************* REPEAT ********************/
	case REPEAT:
		getSym();
		temp=codeCount;//记下目标代码的序号,也即循环体的起始序号,用于一次循环后跳转回来
		yacc_ss();
		if(sym != UNTIL)
			errorOccur(9);//缺少关键字until
		else
			getSym();
		yacc_be();
		gen(JPC,temp);//假如判断失败,则跳回至上面的循环体;否则顺序执行下去
		break;

	/********************* WRITE *********************/
	case WRITE:
		getSym();
		yacc_ae();
		gen(WRT,0);
		break;
	default:
		errorOccur(10);//此处需要aident,bident,if,while,repeat,write中的一个
		break;
	}
	return;
}

//******************************************************************/
//函数原型:void yacc_ae()
//参数说明:无
//函数功能:语法分析分程序之ae
//返回值  :无
//******************************************************************/
void yacc_ae()
{
	if(sym == MINUS)
	{
		getSym();
		yacc_at();
		while(sym == MINUS || sym == PLUS)
		{
			if(sym == MINUS)
			{
				getSym();
				yacc_at();
				gen(OPR,OPR_MINUS);
			}
			else
			{
				getSym();
				yacc_at();
				gen(OPR,OPR_PLUS);
			}
		}
		gen(OPR,OPR_OPPO);
	}
	else
	{
		yacc_at();
		while(sym == MINUS || sym == PLUS)
		{
			if(sym == MINUS)
			{
				getSym();
				yacc_at();
				gen(OPR,OPR_MINUS);
			}
			else
			{
				getSym();
				yacc_at();
				gen(OPR,OPR_PLUS);
			}
		}
	}

	return;
}

//******************************************************************/
//函数原型:void yacc_at()
//参数说明:无
//函数功能:语法分析分程序之at
//返回值  :无
//******************************************************************/
void yacc_at()
{
	yacc_af();
	while(sym == TIMES || sym == SLASH)
	{
		if(sym == TIMES)
		{
			getSym();
			yacc_af();
			gen(OPR,OPR_TIMES);
		}
		else
		{
			getSym();
			yacc_af();
			gen(OPR,OPR_SLASH);
		}
	}
	return;
}

//******************************************************************/
//函数原型:void yacc_af()
//参数说明:无
//函数功能:语法分析分程序之af
//返回值  :无
//******************************************************************/
void yacc_af()
{
	int i;

	switch(sym)
	{
	/********************* IDENT *********************/
	case IDENT:
		i=position(ident);//ident是词法分析中填入的当前标识符
		if(i == 0)
			errorOccur(5);//标识符未定义,定义后才可以使用
		if(table[i].kind == INTEGER)
		{
			gen(LOD,table[i].offSet);
			getSym();
		}
		else
		{
			errorOccur(11);//此处需要aident,不能是bident
		}
		break;

	/********************* NUMBER ********************/
	case NUMBER:
		gen(LIT,num);//num,全局变量,存放当前被取到的常数
		getSym();
		break;

	/********************* LPAREN ********************/
	case LPAREN:
		getSym();
		yacc_ae();
		if(sym != RPAREN)
			errorOccur(12);//此处需要有)
		else
			getSym();
		break;

	default:
		errorOccur(13);//此处需要aident,NUMBER,LPAREN中的一个
		break;
	}
	return;
}

//******************************************************************/
//函数原型:void yacc_be()
//参数说明:无
//函数功能:语法分析分程序之be
//返回值  :无
//******************************************************************/
void yacc_be()
{
	yacc_bt();
	while(sym == OR)
	{
		getSym();
		yacc_bt();
		gen(OPR,OPR_OR);
	}
	return;
}

//******************************************************************/
//函数原型:void yacc_bt()
//参数说明:无
//函数功能:语法分析分程序之bt
//返回值  :无
//******************************************************************/
void yacc_bt()
{
	yacc_bf();
	while(sym == AND)
	{
		getSym();
		yacc_bf();
		gen(OPR,OPR_AND);
	}
	return;
}

//******************************************************************/
//函数原型:void yacc_bf()
//参数说明:无
//函数功能:语法分析分程序之bf
//返回值  :无
//******************************************************************/
void yacc_bf()
{
	int i;

	switch(sym)
	{
	/********************* IDENT *********************/
	case IDENT:
		i=position(ident);//ident是词法分析中填入的当前标识符
		if(i == 0)
			errorOccur(5);//标识符未定义,定义后才可以使用
		if(table[i].kind == LOGICAL)
		{
			gen(LOD,table[i].offSet);
			getSym();
		}
		else
		{
			yacc_re();//如果不是bident,可能是aident,可以进入到re过程继续进行分析
		}
		break;

	/********************* TRUE **********************/
	case TRUE:
		gen(LIT,TRUE);
		getSym();
		break;

	/********************* FALSE *********************/
	case FALSE:
		gen(LIT,FALSE);
		getSym();
		break;

	/********************** NOT **********************/
	case NOT:
		getSym();
		yacc_bf();
		gen(OPR,OPR_OPPO);
		break;

	/********************* LPAREN ********************/
	case LPAREN:
		getSym();
		yacc_be();
		if(sym != RPAREN)
			errorOccur(12);//此处需要有)
		else
			getSym();
		break;

	/******************** yacc_re() ******************/
	default:
		yacc_re();
		break;
	}
	return;
}

//******************************************************************/
//函数原型:void yacc_re()
//参数说明:无
//函数功能:语法分析分程序之re
//返回值  :无
//******************************************************************/
void yacc_re()
{
	int i;

	switch(sym)
	{
	/********************* IDENT *********************/
	case IDENT:
		i=position(ident);//ident是词法分析中填入的当前标识符
		if(i == 0)
			errorOccur(5);//标识符未定义,定义后才可以使用
		if(table[i].kind == INTEGER)
		{
			gen(LOD,table[i].offSet);
			getSym();
		}
		else
		{
			errorOccur(11);//此处需要aident,不能是bident
		}
		break;

	/********************* NUMBER ********************/
	case NUMBER:
		gen(LIT,num);//num,全局变量,存放当前被取到的常数
		getSym();
		break;

	default:
		errorOccur(14);//此处需要aident,NUMBER中的一个
		break;
	}

	switch(sym)
	{
	case EQL:
		getSym();
		yacc_ae();
		gen(OPR,OPR_EQL);
		break;
	case GTR:	
		getSym();
		yacc_ae();
		gen(OPR,OPR_GTR);
		break;
	case GEQ:
		getSym();
		yacc_ae();
		gen(OPR,OPR_GEQ);
		break;
	case LSS:
		getSym();
		yacc_ae();
		gen(OPR,OPR_LSS);
		break;
	case LEQ:
		getSym();
		yacc_ae();
		gen(OPR,OPR_LEQ);
		break;
	default:
		errorOccur(15);//此处需要=,>,>=,<,<=中的一个
	}

	return;
}

⌨️ 快捷键说明

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