www.pudn.com > pl0_compiler_c.rar > yufa.cpp


// yufa.cpp: implementation of the yufa class. 
////////////////////////////////////////////////////////////////////// 
#include "yufa.h" 
#include "errors.h" 
#include "cifa.h" 
#include "table.h" 
#include "code.h" 
 
CYufa::CYufa(CPlCompiler *p) 
{ 
	pl=p; 
	//³υΚΌ»― 
	declbegsys+=varsym; 
	declbegsys+=constsym; 
	declbegsys+=procsym; 
	statbegsys+=beginsym; 
	statbegsys+=callsym; 
	statbegsys+=ifsym; 
	statbegsys+=whilesym; 
	statbegsys+=repeatsym; 
	facbegsys+=ident; 
	facbegsys+=number; 
	facbegsys+=lparen; 
} 
void CYufa::Analysis() 
{ 
	getsym(); 
	lev=-1; 
	CSymbolSet s; 
	s=declbegsys; 
	s+=statbegsys; 
	s+=period; 
	block(s); 
} 
void CYufa::test(CSymbolSet s1,CSymbolSet s2,int n) 
{ 
	if (!s1.InSet(sym)) 
	{ 
		pl->errors->Add(n); 
		s1+=s2; 
		while (!s1.InSet(sym)) getsym(); 
	} 
} 
void CYufa::block(CSymbolSet fsys) 
{ 
	lev++; 
	int tx0,cx0; 
	CSymbolSet s; 
	CErrors *err=pl->errors; 
	Ccode *dm=pl->code; 
	Ctable *bg=pl->table; 
	dx[lev]=3; 
	tx0=bg->TableIndex(); 
	bg->table[tx0].adr=dm->cx; 
	dm->Gen(jmp,0,0); 
	if (lev>MAX_LEVEL) err->Add(32); 
	do{ 
		 
		if (sym==varsym) 
		{ 
			getsym(); 
			do{ 
				vardeclaration(); 
				while (sym==comma) 
				{ 
					getsym(); 
					vardeclaration(); 
				} 
				if (sym==semicolon) getsym(); else err->Add(5); 
			}while (sym==ident); 
		} 
		if (sym==constsym) 
		{ 
			getsym(); 
			do{ 
				constdeclaration(); 
				while (sym==comma) 
				{ 
					getsym(); 
					constdeclaration(); 
				} 
				if (sym==semicolon) getsym(); else err->Add(5); 
			}while (sym==ident); 
		} 
		while (sym==procsym) 
		{ 
			getsym(); 
			if (sym==ident) 
			{ 
				bg->Enter(procedure); 
				getsym(); 
			} 
			else err->Add(4); 
			if (sym==semicolon) getsym(); else err->Add(5); 
			s=fsys; 
			s+=semicolon; 
			block(s); 
			if (sym==semicolon) 
			{ 
				getsym(); 
				s=statbegsys; 
				s+=ident; 
				s+=procsym; 
				test(s,fsys,6); 
			} 
			else 
				err->Add(5); 
		} 
		s=statbegsys; 
		s+=ident; 
		test(s,declbegsys,7); 
	}while (declbegsys.InSet(sym)); 
	dm->code[bg->table[tx0].adr].a=dm->cx; 
	bg->table[tx0].adr=dm->cx; 
	bg->table[tx0].size=dx[lev]; 
	cx0=dm->cx; 
	dm->Gen(intint,0,dx[lev]); 
	s=fsys; 
	s+=semicolon; 
	s+=endsym; 
	statement(s); 
	dm->Gen(opr,0,0); 
	test(fsys,CSymbolSet(),8); 
	lev--; 
} 
////////////////////////////////////////////////////////////////////// 
void CYufa::constdeclaration() 
{ 
	CErrors *err=pl->errors; 
	Ctable *bg=pl->table; 
	if (sym==ident) 
	{ 
		getsym(); 
		if (sym==eql || sym==becomes) 
		{ 
			if (sym==becomes) 
				err->Add(1); 
			getsym(); 
			if (sym==number) 
			{ 
				bg->Enter(constant); 
				getsym(); 
			} 
			else 
				err->Add(2); 
		} 
		else 
			err->Add(3); 
	} 
	else 
		err->Add(4); 
} 
void CYufa::vardeclaration() 
{ 
	CErrors *err=pl->errors; 
	Ccode *dm=pl->code; 
	Ctable *bg=pl->table; 
	if (sym==ident) 
	{ 
		bg->Enter(variable); 
		dx[lev]++; 
		getsym(); 
	} 
	else 
		err->Add(4); 
} 
void CYufa::factor(CSymbolSet fsys) 
{ 
	int i; 
	CErrors *err=pl->errors; 
	table_type *table=pl->table->table; 
	Ccode *dm=pl->code; 
	test(facbegsys,fsys,24); 
	while (facbegsys.InSet(sym)) 
	{ 
		switch (sym) 
		{ 
		case ident: 
			i=pl->table->Position(pl->cifa->id); 
			if (i==0) 
				err->Add(11); 
			else 
			{ 
				switch (table[i].kind) 
				{ 
				case constant: 
					dm->Gen(lit,0,table[i].val); 
					break; 
				case variable: 
					dm->Gen(lod,lev-table[i].level,table[i].adr); 
					break; 
				case procedure: 
					err->Add(21); 
					break; 
				} 
			} 
			getsym(); 
			break; 
		case number: 
			if (pl->cifa->num>MAX_NUMBER) 
			{ 
				err->Add(31); 
				pl->cifa->num=0; 
			} 
			dm->Gen(lit,0,pl->cifa->num); 
			getsym(); 
			break; 
		case lparen: 
			getsym(); 
			expression(fsys+=rparen); 
			if (sym==rparen) 
				getsym(); 
			else 
				err->Add(22); 
			break; 
		} 
		test(fsys,facbegsys,23); 
	} 
} 
///////////////////////////////////////////////////////////////////// 
void CYufa::term(CSymbolSet fsys) 
{ 
	symbol mulop; 
	CSymbolSet symset; 
	symset+=fsys; 
	symset+=times; 
	symset+=slash; 
	factor(symset); 
	while (sym==times||sym==slash) 
	{ 
		mulop=sym; 
		getsym(); 
		factor(symset); 
		if (mulop==times) 
			pl->code->Gen(opr,0,4); 
		else 
			pl->code->Gen(opr,0,5); 
	} 
} 
void CYufa::expression(CSymbolSet fsys) 
{ 
	symbol addop; 
	CSymbolSet symset; 
	symset+=fsys; 
	symset+=plus; 
	symset+=minus; 
	if (sym==plus || sym==minus) 
	{ 
		addop=sym; 
		getsym(); 
		term(symset); 
		if (addop==minus) 
			pl->code->Gen(opr,0,1); 
	} 
	else 
		term(symset); 
	while (sym==plus || sym==minus) 
	{ 
		addop=sym; 
		getsym(); 
		term(symset); 
		if (addop==plus) 
			pl->code->Gen(opr,0,2); 
		else 
			pl->code->Gen(opr,0,3); 
	} 
} 
void CYufa::condition(CSymbolSet fsys) 
{ 
	symbol relop; 
	CSymbolSet s1,s2; 
	s1+=eql; 
	s1+=neq; 
	s1+=lss; 
	s1+=leq; 
	s1+=gtr; 
	s1+=geq; 
 
	if (sym==oddsym) 
	{ 
		getsym(); 
		expression(fsys); 
		pl->code->Gen(opr,0,6); 
	} 
	else 
	{ 
		s2+=s1; 
		expression(s2+=fsys); 
		if (!s1.InSet(sym)) 
			pl->errors->Add(20); 
		else 
		{ 
			relop=sym; 
			getsym(); 
			expression(fsys); 
			switch (relop) 
			{ 
			case eql:pl->code->Gen(opr,0,8);break; 
			case neq:pl->code->Gen(opr,0,9);break; 
			case lss:pl->code->Gen(opr,0,10);break; 
			case geq:pl->code->Gen(opr,0,11);break; 
			case gtr:pl->code->Gen(opr,0,12);break; 
			case leq:pl->code->Gen(opr,0,13);break; 
			} 
		} 
	} 
} 
void CYufa::statement(CSymbolSet fsys) 
{ 
	int i,cx1,cx2; 
	table_type *table=pl->table->table; 
	CErrors *err=pl->errors; 
	Ccode *dm=pl->code; 
	CSymbolSet s,s2; 
 
	switch (sym) 
	{ 
	case ident: 
		i=pl->table->Position(pl->cifa->id); 
		if (i==0) 
			err->Add(11); 
		else if (table[i].kind!=variable) 
		{err->Add(12);i=0;} 
		getsym(); 
		if (sym==becomes) 
			getsym(); 
		else 
			err->Add(13); 
		expression(fsys); 
		if (i>0) 
			dm->Gen(sto,lev-table[i].level,table[i].adr); 
		break; 
	case readsym: 
		getsym(); 
		if (sym!=lparen) 
			err->Add(34); 
		else 
			do{ 
				getsym(); 
				i=(sym==ident) ? pl->table->Position(pl->cifa->id):0; 
				if (i==0) 
					err->Add(35); 
				else 
				{ 
					dm->Gen(opr,0,16); 
					dm->Gen(sto,lev-table[i].level,table[i].adr); 
				} 
				getsym(); 
			}while (sym==comma); 
 
		if (sym!=rparen) 
		{ 
			err->Add(33); 
			while (fsys.InSet(sym)) getsym(); 
		} 
		else getsym(); 
		break; 
	case writesym: 
		s=fsys; 
		s+=rparen; 
		s+=comma; 
		getsym(); 
		if (sym==lparen) 
		{ 
			do{ 
				getsym(); 
				expression(s); 
				pl->code->Gen(opr,0,14); 
			}while (sym==comma); 
			if (sym!=rparen) 
				err->Add(33); 
			else 
				getsym(); 
		} 
		dm->Gen(opr,0,15); 
		break; 
	case callsym: 
		getsym(); 
		if (sym!=ident) 
			err->Add(14); 
		else 
		{ 
			i=pl->table->Position(pl->cifa->id); 
			if (i==0) err->Add(11); 
			else if (table[i].kind==procedure) 
				dm->Gen(cal,lev-table[i].level,table[i].adr); 
			else 
				err->Add(15); 
			getsym(); 
		} 
		break; 
	case ifsym: 
		s=fsys; 
		s+=thensym; 
		s+=dosym; 
		getsym(); 
		condition(s); 
		if (sym==thensym) getsym();else err->Add(16); 
		cx1=dm->cx; 
		dm->Gen(jpc,0,0); 
		s=fsys; 
		s+=elsesym; 
		statement(s); 
		if (sym==elsesym) 
		{ 
			getsym(); 
			cx2=dm->cx; 
			dm->Gen(jmp,0,0); 
			statement(fsys); 
			dm->code[cx1].a=cx2+1; 
			dm->code[cx2].a=dm->cx; 
		} 
		else 
			dm->code[cx1].a=dm->cx; 
		break; 
	case beginsym: 
		s=fsys; 
		s+=semicolon; 
		s+=endsym; 
		s2=statbegsys; 
		s2+=semicolon; 
		getsym(); 
		statement(s); 
		while (s2.InSet(sym)) 
		{ 
			if (sym==semicolon) getsym();else err->Add(10); 
			statement(s); 
		} 
		if (sym==endsym) getsym(); else err->Add(17); 
		break; 
	case whilesym: 
		cx1=dm->cx; 
		getsym(); 
		s=fsys; 
		s+=dosym; 
		condition(s); 
		cx2=dm->cx; 
		dm->Gen(jpc,0,0); 
		if (sym==dosym) getsym(); else err->Add(18); 
		statement(fsys); 
		dm->Gen(jmp,0,cx1); 
		dm->code[cx2].a=dm->cx; 
		break; 
	case repeatsym: 
		getsym(); 
		s=fsys; 
		s+=semicolon; 
		s+=untilsym; 
		cx1=dm->cx; 
		statement(s); 
		s2=statbegsys; 
		s2+=semicolon; 
		while (s2.InSet(sym)) 
		{ 
			if (sym==semicolon) getsym();else err->Add(10); 
			statement(s); 
		} 
		if (sym==untilsym) 
		{ 
			getsym(); 
			condition(fsys); 
			dm->Gen(jpc,0,cx1); 
		} 
		else 
			err->Add(25); 
		break; 
	} 
	test(fsys,CSymbolSet(),19); 
}