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

📄 pl0.cpp

📁 c++语言编写的PL0语言的语法分析程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "Pl0.h"

//////////////////////////////////////////////////////////
Pl0::Pl0(char *fileName, bool debugOn, bool outputOn){
	//	must declaration before DEBUG is called.
	if (outputOn == true)
		#define OUTPUT OUTPUT			//output信息
	if (debugOn == true)
		#define DEBUG DEBUG			//调试信息

#ifdef	OUTPUT
	out.open("output.txt");
#endif
#ifdef	DEBUG
	debugOut.open("debug.txt");	//, ios_base::out
#endif

	counter = 0;
	
	DEBUG(1, "->Pl0();");
	fin.open(fileName);

	lineNum = 0;
	lineLen = 0;
	charCount =0;
	number =0;
	sourceEnd = false;

	ch = ' ';
	token[0] = '\0';
	lastIdentLen = identMaxLen;
	codeIndex = 0;
	errorCount=0;

/////////////////////////
	strcpy(word[1],"begin");//13个关键字
	strcpy(word[2],"call");
	strcpy(word[3],"const"); 
	strcpy(word[4],"do");
	strcpy(word[5],"end");
	strcpy(word[6],"if");
	strcpy(word[7],"odd");
	strcpy(word[8],"procedure");
	strcpy(word[9],"read");
	strcpy(word[10],"then");
	strcpy(word[11],"var");
	strcpy(word[12],"while");
	strcpy(word[13],"write");

	wsym[1]= BEGINSYM;//13个关键字所对应的类型
	wsym[2]=CALLSYM;
	wsym[3]= CONSTSYM;
	wsym[4]=DOSYM;
	wsym[5]=ENDSYM;
	wsym[6]=IFSYM;
	wsym[7]=ODDSYM;
	wsym[8]=PROCSYM;
	wsym[9]=READSYM;
	wsym[10]=THENSYM;
	wsym[11]=VARSYM;
    wsym[12]=WHILESYM;
	wsym[13]=WRITESYM;

	ssym['+'] = PLUS;
	ssym['-'] = MINUS;
	ssym['*'] = TIMES;
	ssym['/'] = SLASH;
	ssym['('] = LPAREN;
	ssym[')'] = RPAREN;
	ssym['='] = EQL;
	ssym[','] = COMMA;
	ssym['.'] = PERIOD;
	ssym['<'] = LSS;
	ssym['>'] = GTR;
	ssym[';'] = SEMICOLON;
	ssym['#']=NEQ;

	declbegsys.insert(CONSTSYM);//分程序的first集
	declbegsys.insert(VARSYM);
	declbegsys.insert(PROCSYM);

	statbegsys.insert(BEGINSYM);//语句的first集
	statbegsys.insert(CALLSYM);
	statbegsys.insert(IFSYM);
	statbegsys.insert(WHILESYM);
	statbegsys.insert(READSYM);
	statbegsys.insert(WRITESYM);
	statbegsys.insert(IDENT);

	facbegsys.insert(IDENT);//因子的first集
	facbegsys.insert(NUMBER);
	facbegsys.insert(LPAREN);

	//目标代码的8种类型
	strcpy(mnemonic[LIT], "LIT");		//LIT 0,a  取常量a放到数据栈顶
	strcpy(mnemonic[OPR], "OPR");		//OPR 0,a  执行运算,a表示执行何种运算
	strcpy(mnemonic[LOD], "LOD");		//LOD	l,a	取变量(相对地址为a,层次差为l)放到数据栈栈顶
	strcpy(mnemonic[STO], "STO");		//STO  l,a	将数据栈顶内容存入变量()
	strcpy(mnemonic[CAL], "CAL");		//CAL	l,a	调用过程(入口指令地下为a,层次差为l)
	strcpy(mnemonic[INT], "INT");		//INT	0,a	数据栈栈顶指针加a
	strcpy(mnemonic[JMP], "JMP");		//JMP	0,a	无条件转移到a
	strcpy(mnemonic[JPC], "JPC");		//JPC	0,a	条件转移

	getsym();
	DEBUG(-1, "->Pl0();");
}
	
Pl0::~Pl0() {		//close file
	DEBUG(1, "->~Pl0();");
	fin.close();
	debugOut.close();
	out.close();
	DEBUG(-1, "->~Pl0();");
}			

void Pl0::getch()
{
//	DEBUG(1, "->Getch();");
	if (charCount >= lineLen) {
		if (fin.eof()) {
			sourceEnd = true;
			return;
		}
		charCount = 0;
		fin.getline(lineBuffer,lineMaxLen);

		cout << lineNum+1 << " " << lineBuffer << endl;
		OUTPUT(lineBuffer, lineNum+1);
		DEBUG(0, lineBuffer);

		lineLen = strlen(lineBuffer);
		lineNum++;
	}
	ch = lineBuffer[charCount];	
	if (ch >= 'A' && ch <= 'Z')	//转化为小写字母
		ch = tolower(ch);
	charCount++;
//	DEBUG(-1, "->Getch();");
}

void Pl0::getsym () {//保证ch中始终有一个字符
	if (sourceEnd == true)
		return;
	DEBUG(1, "<-getsym ();");

	while ( ch == ' ' || ch == 9 || ch == 0)		//'\0' 是空格
		getch();		//skip space and tab
//////////////////////////////////////////
	if ( isalpha(ch) ) {
		int k;
		for (k=0; isalpha(ch) || isdigit(ch); k++) {
			token[k] = ch;
			getch();
		}
		token[k] = '\0';
/*		if (k > lastIdentLen)
			lastIdentLen = k;
		else {
			for (; k< lastIdentLen; k++)
				token[k]= '*';
			token[k] = '\0';
		}
*/

		strcpy(id, token);
		DEBUG(0, token,lineNum);

		sym = IDENT;						//未用二分法查找
		for (k =1; k < numReservedWord+1; k++) {
			if (strcmp (word[k],token) == 0) {
				sym = wsym[k];
			}
		}
	}
////////////////////////////////////////
	else if ( isdigit(ch) ) {
		int k = 0;
		number = 0;
		sym = NUMBER;
		while ( isdigit(ch) ) {
			number = number*10 + (int)ch - (int)('0');
			getch();
			k++;
		}
		if (k > numMaxLen)
			error(29);					//数的位数多于14位
		DEBUG(0, "number = ",number);
	}
//////////////////////////////////////////
	else if ( ch == ':') {
		getch();
		if (ch == '=') {
			sym = BECOMES;
			getch();
		}
		else
			error(28);
	}
	else if ( ch == '<' ) {
		getch();
		if (ch == '=') {
			sym = LEQ;
			getch();
		}
		else sym = LSS;
	}
	else if ( ch == '>' ) {
		getch();
		if (ch == '=') {
			sym = GEQ;
			getch();
		}
		else sym = GTR;
	}
	else {
		switch(ch){
		case '#':
			sym=NEQ;
			break;
		case '+':
			sym = PLUS;
			break;
		case '-':
			sym = MINUS;
			break;
		case '*':
			sym = TIMES;
			break;
		case '/':
			sym = SLASH;
			break;
		case '(':
			sym = LPAREN;
			break;
		case ')':
			sym = RPAREN;
			break;
		case '=':
			sym = EQL;
			break;
		case ',':
			sym = COMMA;
			break;
		case '.':
			sym = PERIOD;
			break;
		case ';':
			sym = SEMICOLON;
			break;
		default:
			error(27);
		}
		getch();
	}
	//cout<<"<----"<<lineNum<<"------"<<sym<<endl;
	DEBUG(0, "sym=",(int)sym);
	DEBUG(-1, ">-getsym ();");
}
///////////////////////////////////////////////
void Pl0::gen(fct x, int y, int z)//生成目标代码
{
	DEBUG(1, "<-gen();");
	if (codeIndex > cxMax) {
		cout << "Program too long." << endl;
		DEBUG(-1, "Program too long.");
		return;
	}
	code[codeIndex].func = x;
	code[codeIndex].lev = y;
	code[codeIndex].addr = z;
	codeIndex++;

	DEBUG(0, mnemonic[x], y, z);
 
	DEBUG(-1, ">-gen();");
}
//////////////////////////////////////////////
void Pl0::error(int i)
{
	DEBUG(1, "<-error();");
	cout << "****Line <" << lineNum -1//<<"----"<<charCount<<"---"<<ch
		<< "> "
		 << errorInfo[i]
		 << endl;
	DEBUG(0, "******************************Line: ", lineNum);
//	DEBUG(0, errorInfo[i]);		//不是数组,是字符串
	#ifdef DEBUG
		debugOut << errorInfo[i] <<endl;
	#endif
	errorCount++;
	DEBUG(-1, ">-error();");
}
void Pl0::printTable()
{
	int i;
	for(i=1;i<=tablenum;i++){
		cout<<"table表的第"<<i<<"行为: NAME: "<<table[i].name<<"   KIND:  ";
	switch((int)table[i].kind){
	case 0:
		cout<<"CONSTANT";
		break;
	case 1:
		cout<<"VARIABLE";
		break;
	case 2:
		cout<<"PROCEDURE";
		break;
	default:
		break;
	}
	cout<<"  VAL:  "<<table[i].val<<" LEV:  "<<table[i].level<<" ADR:  "<<table[i].addr<<endl;
	cout<<endl;
	}
}
void Pl0::enter(object kind, int &tableIndex,int &dataIndex, int &lev)//登记标识符
{
	DEBUG(1, "<-enter();");
	tableIndex++;
	strcpy(table[tableIndex].name, id);
	table[tableIndex].kind = kind;		//所有类型都有名字和属性
	switch(kind) {
	case CONSTANT:
		if (number > numMax) {
			error(31);//超过所允许的最大数
			number = 0;
		}
		table[tableIndex].val = number;		//常量必须是数字,具有数值
		table[tableIndex].addr=-1;   //-1代表没有
		table[tableIndex].level = -1;
		break;
	case VARIABLE:
		table[tableIndex].level = lev;		//变量有值和地址
		table[tableIndex].addr = dataIndex;
		table[tableIndex].val =-1;
		dataIndex++;						//需要增加分配的空间
		break;
	case PROCEDURE:
		table[tableIndex].level = lev;		//过程有层,地址后面再补上
		table[tableIndex].val = -1;
		break;
	default:
		break;
	}
	DEBUG(-1, ">-enter();");
}
int Pl0::getError()
{
	return errorCount;
}
int Pl0::position(char *id, int tableIndex)		//查找变量
{
	DEBUG(1, "<-position();");
	int i;
	strcpy(table[0].name, id);		//第一个为空,用于终止循环查找
	i = tableIndex;
	while (strcmp(table[i].name, id) != 0)		//strcmp(),相等返回0
		i--;
	DEBUG(-1, ">-position();");
	return i;
}
void Pl0::test(symset s1, symset s2, int n)
{
	if (sourceEnd == true)
		return;
	DEBUG(1, "<-test();");
	
	if (s1.find(sym) == s1.end())	{	// sym 不在 s1
		error(n);

		symset::iterator it_s2;
		for (it_s2 = s2.begin(); it_s2 != s2.end(); it_s2++)
			s1.insert(*it_s2);		//		s1 += s2;

		while (s1.find(sym) == s1.end()) {  //sym 不在 s1
			getsym();
			if (sourceEnd == true)		//
				return;
		}
	}
	DEBUG(-1, ">-test();");
}

void Pl0::block1(symset fsys, int tableIndex, int lev)//代码生成、语法分析、语义分析模块     分程序
{
	if (sourceEnd == true)
		return;
	DEBUG(1, "<-block();");
	int dataIndex=3;		//地址分配下标, 从 3开始
	int tableIndex0 = tableIndex;	//初始化table表下标
	int codeIndex0 = 0;		//initial code index	//初始化为0
	table[tableIndex].addr = codeIndex;
	gen(JMP,0,0);		//跳转到操作部分
	if (lev > levMax)
		error(30);
	symset follow;
	follow.insert(SEMICOLON);
	follow.insert(PERIOD);
	test(fsys,follow,37);
	do {
		//常量处理部分
		if (sym == CONSTSYM) {
			getsym();
			do {
				constDeclaration(tableIndex, dataIndex, lev);
				while(sym == COMMA) {
					getsym();
					constDeclaration(tableIndex, dataIndex, lev);
				}
				if (sym == SEMICOLON) {		//常量声明部分结束
					getsym();
				}
				else {
					error(5);
				}
			} while(sym == IDENT);
		}

		//变量处理部分
		if (sym == VARSYM) {
			getsym();
			do {
				varDeclaration(tableIndex, dataIndex, lev);		//与常量声明类似
				while(sym == COMMA) {
					getsym();
					varDeclaration(tableIndex, dataIndex, lev);
				}
				if (sym == SEMICOLON) {
					getsym();
				}
				else {
					error(5);
				}
			} while(sym == IDENT);
		}

		//过程处理部分
		while(sym == PROCSYM) {
			getsym(); 
			if (sym == IDENT) {
				enter(PROCEDURE, tableIndex, dataIndex, lev);	//过程的层没变
				getsym();
			}
			else error(4);
			if (sym == SEMICOLON)
				getsym();
			else error(5);	
			block1(fsys, tableIndex,lev+1);
		}
	} while(declbegsys.find(sym) != declbegsys.end());//检测是否还有常量、变量、过程声明	

	code[table[tableIndex0].addr].addr = codeIndex;		//跳转到语句代码操作区
	table[tableIndex0].addr = codeIndex;			//代码操作开始地址
	codeIndex0 = codeIndex;
	gen(INT, 0, dataIndex);		//申请的数据区
	
	statement(statbegsys, tableIndex, lev); 
	if(lev>0)
	{
	if(sym!=SEMICOLON&&sym!=PERIOD)
		error(38);
	else{
		getsym(); 
	}
	}

	gen(OPR, 0, 0);
	//test(follow,fsys,38);
	tablenum=tableIndex;
		
	//listCode(codeIndex0);
	DEBUG(-1, ">-block();");
}
void Pl0::block(symset fsys,int tableIndex, int lev)
{
	fsys.insert(IDENT);//语句的首符集
	fsys.insert(IFSYM);
	fsys.insert(CALLSYM);
	fsys.insert(WHILESYM);
	fsys.insert(READSYM);
	fsys.insert(WRITESYM);
	fsys.insert(CONSTSYM);
	fsys.insert(VARSYM);
	fsys.insert(PROCSYM);
	fsys.insert(BEGINSYM);
	block1(fsys,tableIndex, lev);
	if(sym!=PERIOD)//检测主程序结束字符
		error(38);
}

void Pl0::constDeclaration(int &tableIndex, int &dataIndex, int &lev)//常量定义
{
	DEBUG(1, "<-constDeclaration();");
	if (sym == IDENT) {
		getsym();
		if (sym >= EQL && sym <= BECOMES) {
			if (sym == BECOMES)
				error(1);
			getsym();
			if (sym == NUMBER) {
				enter(CONSTANT, tableIndex, dataIndex, lev);
				getsym();
			}
			else error(2);
		}
		else error(3);
	}
	else error(4);
	DEBUG(-1, ">-constDeclaration();");
}

void Pl0::varDeclaration(int &tableIndex, int &dataIndex, int &lev)//变量定义
{
	DEBUG(1, "<-varDeclaration();");
	if (sym == IDENT) {				//检测是否是标识符
		enter(VARIABLE, tableIndex, dataIndex, lev);
		getsym();
	}
	else error(4);
	DEBUG(-1, ">-varDeclaration();");
}

void Pl0::listCode(int codeIndex0)
{
	DEBUG(1, "<-listCode();");
	for (int i = codeIndex0; i <= codeIndex - 1; i++) {
		cout << "-->" << i 
			<< " " << mnemonic[code[i].func]
			<< " " << code[i].lev 
			<< " " << code[i].addr
			<< endl;

		OUTPUT("-->", mnemonic[code[i].func], i, code[i].lev, code[i].addr);
		DEBUG(0, mnemonic[code[i].func], code[i].lev, code[i].addr);
	}

	DEBUG(-1, ">-listCode();");
}

void Pl0::statement(symset fsys, int tableIndex, int lev)	//语句处理部分
{
	if (sourceEnd == true)
		return;
	DEBUG(1, "<-statement()");
	
	int i;
	int codeIndex1;
	int codeIndex2;
	
	symset follow;
	follow.insert(PERIOD);
	follow.insert(SEMICOLON);
	follow.insert(ENDSYM);  
	test(fsys,follow,7);
	if (sym == IDENT) {
		i = position(id, tableIndex);
		if (i == 0)		//could not find
			error(11);
		else if (table[i].kind != VARIABLE) {
			error(12);
			i = 0;
		}
		getsym();
		if (sym == BECOMES)
			getsym();
		else error(13);

		symset tempsys;
		tempsys.insert(PLUS);
		tempsys.insert(MINUS);
		tempsys.insert(LPAREN);
		tempsys.insert(IDENT);
		tempsys.insert(NUMBER);

		expression(tempsys, tableIndex, lev);
		if (i != 0)
			gen(STO, lev - table[i].level, table[i].addr);
	}


	else if (sym == CALLSYM) {//调用模块
		getsym();
		if (sym != IDENT)
			error(14);
		else {
			i = position(id, tableIndex);
			if (i == 0)
				error(11);
			else if (table[tableIndex].kind == PROCEDURE){
				gen(CAL, lev - table[i].level, table[i].addr);
				getsym();
			}
			else 
				error(15);
		}
	}
	else if (sym == IFSYM) {
		getsym();

		symset tempsys;
		tempsys.insert(ODDSYM);
		tempsys.insert(PLUS);
		tempsys.insert(MINUS);
		tempsys.insert(LPAREN);
		tempsys.insert(IDENT);
		tempsys.insert(NUMBER);


		condition(tempsys, tableIndex, lev);
		if (sym == THENSYM)
			getsym();
		else
			error(16);
		codeIndex1 = codeIndex;
		gen(JPC, 0, 0);
		statement(fsys, tableIndex, lev);
		code[codeIndex1].addr = codeIndex;
	}


		else if (sym == BEGINSYM) {
		getsym(); 
		statement(fsys, tableIndex, lev);
	
		symset tempsys;
		tempsys.insert(PERIOD);
		tempsys.insert(SEMICOLON);
		tempsys.insert(ENDSYM);
		if(sym!=ENDSYM){
		if(sym== SEMICOLON) {
			getsym();
			statement(fsys, tableIndex, lev);
			while(sym!=ENDSYM)
			{
			if(sym== SEMICOLON)

⌨️ 快捷键说明

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