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

📄 pl0.cpp

📁 编译原理课设
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "pl0.h"
/**************************************************************************
*	PL/0 语言编译程序,由江汉石油学院计算机系周云才根据清华大学出版社出版,
*	吕映芝,张素琴,蒋维杜编写的教材《编译原理》中第二章(PL/0编译程序的实现)
*	以及附录A中的代码改编而成。
*	代码版权由周云才拥有,使用者必须遵循以下约定:
*	可以免费使用此文件,但必须包含此声明。
*	可以修改、传播、打印、出版这里的源代码。
*	可以在任何软件工程中使用这里的源代码。
*	周云才对于由此源代码的使用而引起的任何问题没有任何责任。
*	周云才地址:湖北省荆州市江汉石油学院计算机系
*		  邮编:434023
*	      信箱:zyc262@163.net
*		  电话: 0716-8431262
********************************************************************************************* */

// 错误字符串数组
string PL0::errStr[]={" ","error 0001:  常数说明中“=”写成“:=”",
	"error 0002:  常数说明中的“=”后应为数字",
	"error 0003:  常数说明中的标识符后应是“=”",
	"error 0004:  const,var,procedure后应为标识符",
	"error 0005:  漏掉了‘,’或‘;’",
	"error 0006:  过程说明后的符号不正确(应是语句开始符或过程开始符)",
	"error 0007:  应是语句开始符",
	"error 0008:  过程体内语句部分的后跟符不正确",
	"error 0009:  程序皆为丢了句号‘.’",
	"error 0010:  语句之间漏了‘;’",
	"error 0011:  标识符没说明",
	"error 0012:  赋值语句中,赋值号左部标识符属性应是变量",
	"error 0013:  赋值语句左部标识符应是赋值号:=",
	"error 0014:  call后应为标识符",
	"error 0015:  call后标识符属性应为过程",
	"error 0016:  条件语句中丢了then",
	"error 0017:  丢了end或;",
	"error 0018:  while型循环语句中丢了do",
	"error 0019:  语句后的标识符不正确",
	"error 0020:  应为关系运算符",
	"error 0021:  表达式内标识符属性不能是过程",
	"error 0022:  表达式中漏掉了右括号‘)’",
	"error 0023:  因子后的非法符号",
	"error 0024:  表达式开始符不能是此符号",
	"error 0025:  文件在不该结束的地方结束了",
	"error 0026:  结束符出现在不该结束的地方",
	"error 0027:  ","error 0028:  ","error 0029:  ","error 0030:  ",
	"error 0031:  数越界",
	"error 0032:  read语句括号中标识符不是变量",
	"error 0033:  else附近错误" ,
	"error 0034:  repeat附近错误"};
  


// PL0构造函数
PL0::PL0(char* source,char*destination)
{
	listswitch=true,sourceEnd=false;

	strcpy(word[1],"begin");                     // 初始化存储保留字
	strcpy(word[2],"call");
	strcpy(word[3],"const"); 
	strcpy(word[4],"do");
	strcpy(word[5],"else");
	strcpy(word[6],"end");
	strcpy(word[7],"if");
	strcpy(word[8],"odd");
	strcpy(word[9],"procedure");
	strcpy(word[10],"read");	
	strcpy(word[11],"repeat");
	strcpy(word[12],"then");
	strcpy(word[13],"until");
	strcpy(word[14],"var");	
	strcpy(word[15],"while");
	strcpy(word[16],"write");


	wsym[1]= BEGINSYM;   wsym[2]= CALLSYM;       // 初始化保留字表中每一个保留字对应的symbol类型 
	wsym[3]= CONSTSYM;   wsym[4]= DOSYM;
	wsym[5]= ELSESYM;    wsym[6]= ENDSYM;
	wsym[7]= IFSYM;      wsym[8]= ODDSYM;
	wsym[9]= PROCSYM;    wsym[10]= READSYM;
    wsym[11]= REPEATSYM; wsym[12]= THENSYM;
	wsym[13]= UNTILSYM;  wsym[14]= VARSYM; 
	wsym[15]= WHILESYM;  wsym[16]= WRITESYM;  		

	memset(code,0,sizeof(code));
	memset(ssym,0,100*sizeof(symbol));
	memset(table,0,sizeof(table));
	memset(line,0,sizeof(line));

	ssym['+']= PLUS;                            // 初始化一些符号对应的symbol类型表
	ssym['-']= MINUS;
	ssym['*']= TIMES;
	ssym['/']= SLASH;
	ssym['(']= LPAREN;
	ssym[')']= RPAREN;
	ssym['=']= EQL;
	ssym[',']= COMMA;
	ssym['.']= PERIOD;
	ssym['#']= NEQ;
	ssym['<']= LSS;
	ssym['>']= GTR;
	ssym[';']= SEMICOLON;	

	strcpy(mnemonic[LIT]," lit ");             // 初始化类PCODE指令助记符表  
	strcpy(mnemonic[OPR]," opr ");
	strcpy(mnemonic[LOD]," lod ");
	strcpy(mnemonic[STO]," sto ");
	strcpy(mnemonic[CAL]," cal ");
	strcpy(mnemonic[INT]," int ");
	strcpy(mnemonic[JMP]," jmp ");
	strcpy(mnemonic[JPC]," jpc ");

	declbegsys.insert(CONSTSYM),declbegsys.insert(VARSYM),declbegsys.insert(PROCSYM); // 初始化声明开始符号集合  
	statbegsys.insert(BEGINSYM),statbegsys.insert(CALLSYM),statbegsys.insert(IFSYM),statbegsys.insert(WHILESYM); // 初始化表达式开始符号集合
	facbegsys.insert(IDENT),facbegsys.insert(NUMBER),facbegsys.insert(LPAREN); // 初始化项开始符号集合

	err= 0;
	cc= 0;                          // 行缓冲区指针
	cx= 0;                          // 代码分配指针,代码生成模块总在cx所指位置生成新的代码                       
	ll= 0;                          // 行缓冲区长度
	ch= ' ';                        // last character read   
	kk= al;                         // 引入此变量是出于程序性能考虑
	codeNo=0;                       // code line no.
	fin=fopen(source,"r");
	fout=fopen(destination,"w");
}



// 出错处理,打印出错位置和出错代码
void PL0::error(int n)
{
	char s[10];
	sprintf(s,"第 %d 行:",codeNo);
	errorString.push_back(s+errStr[n]);
	err= err+1;//error count
}//error end

// 词法分析,读取一个单词 
void PL0::getsym()
{
	if(sourceEnd)
		return;
	int i,j,k;
	while (ch ==' '||ch==9)
		getch();    // cls space and tab
	if(isalpha(ch)) // id or reserved word
	{
		k=0;
		memset(a,0,al+1);
		// 检测一个单词长度
		do{
			if (k < al)
			{
				a[k]= ch;
				k= k+1;
			}
			getch();
			if(sourceEnd)
				return;
		}while(isalpha(ch)||isdigit(ch));
		if(k >= kk)
			kk = k;
		else
		{
			do{
				a[kk]= ' ';
				kk= kk-1;
			}while(kk > k);
		}
		strcpy(id,a);
		i= 1;
		j= norw;
		// 判断是否是关键字(二分搜索)
		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(isdigit(ch))  // number
	{
		k= 0;
		num= 0;
		sym= NUMBER;
		do{
			num= 10 * num + ch - '0';
			k= k+1;
			getch();
		}while(isdigit(ch));
		if(k > nmax)
			error(30);
	}
	else if (ch == ':')
	{
		getch();
		if( ch == '=')
		{
			sym= BECOMES;
			getch();
		}
		else
			sym= NUL;
	}
	else if(ch == '<')   // extra stuff added to support <=
	{
		getch();
		if (ch== '=')
		{
			sym= LEQ;
			getch();
		}
		else
			sym= LSS;
	}
	else if (ch == '>')
	{
		getch();
		if( ch == '=')
		{
			sym= GEQ;
			getch();
		}
		else
			sym= GTR;
	}
	else                // end of extra stuff
	{
		sym= ssym[ch];  // 其它符号的赋值
		getch();
	}
}

// 漏掉空格,读取一个字符	
void PL0::getch()
{
	if(cc == ll)
	{
		if(feof(fin))
		{
			if(sym!=PERIOD)
				error(25);
			sourceEnd=true;
			return;
		}
		cc= 0;
		fgets(line,lineLength,fin);
		codeNo++;
		ll=strlen(line);
		if(line[ll-1]==10) ll--;
	}
	ch= line[cc];
	cc= cc+1;
}


// 生成目标代码,并送入目标程序区
void PL0::gen(fct x,int y,int z)
{
	if (cx > cxmax)
	{
		cout<<"Program too long\n";
		return;
	}
	code[cx].f= x;
	code[cx].l= y;
	code[cx].a= z;
    cx= cx+1;
}//gen end

// 测试当前单词符号是否合法 
void PL0::test(symset s1,symset s2,int n)
{
	if(sourceEnd)        return;
	if (s1.find(sym)==s1.end())
	{
		error(n);
		symset::iterator it;
		for(it=s2.begin();it!=s2.end();it++)
			s1.insert(*it);//s1=s1+s2
		while (s1.find(sym)==s1.end())
			getsym();
	}
}//test end


// 分程序分析处理过程 
void PL0::block(int lev,int tx,symset fsys)
{
	if(sourceEnd)
		return;
	int dx;  // data allocation index
	int tx0; // initial table index
	int cx0; // initial code index
	dx= 3;   // 变量的个数
	tx0= tx; // 表指针
	table[tx].other.inOther.adr= cx;
	gen(JMP,0,0);
	if( lev>levmax)
		error(32);
	do{  
		if( sym == CONSTSYM)        // 处理常量声明
		{
			getsym();
			do{
				constdeclaration(tx,dx,lev);
				while (sym == COMMA)
				{
					getsym();
					constdeclaration(tx,dx,lev);
				}
				if (sym ==SEMICOLON)
					getsym();
				else
					error(5);
			}while(sym==IDENT);
		}
		if( sym == VARSYM)            // 处理变量声明
		{
			getsym();
			do{
				vardeclaration(tx,dx,lev);
				while( sym == COMMA){
					getsym();
					vardeclaration(tx,dx,lev);
				}
				if( sym ==SEMICOLON)
					getsym();
				else
					error(5);
			}while(sym==IDENT);
		}
		while( sym ==PROCSYM)         // 处理过程的声明
		{
			getsym();
			if (sym ==IDENT)
			{
				enter(PROCEDURE,tx,dx,lev);
				getsym();
			}
			else
				error(4);
			if( sym ==SEMICOLON)
				getsym();
			else
				error(5);
			symset tmp = fsys;
			tmp.insert(SEMICOLON);
			block(lev+1,tx,tmp);
			if (sym == SEMICOLON){
				getsym();
				symset tmp = statbegsys;
				for(int i= IDENT;i<=PROCSYM;i++)
					tmp.insert((symbol)i);
				test(tmp,fsys,6);
			}
			else
				error(5);
		}
		symset tmp=statbegsys;
		tmp.insert(IDENT);
		test(tmp,declbegsys,7);
	}while(declbegsys.find(sym)!=declbegsys.end());

	code[table[tx0].other.inOther.adr].a= cx;
	table[tx0].other.inOther.adr= cx; // start adr of code
	table[tx0].other.inOther.size=dx;

	cx0= cx;
	gen(INT,0,dx);
	symset tmp=statbegsys;
	for(int i=SEMICOLON;i <= ENDSYM;i++)
		tmp.insert((symbol)i);
	statement(tmp,tx,lev);
	gen(OPR,0,0); // return
	symset s2;
	test(fsys,s2,8);
	listcode(cx0);
}// block end

// 登入名字表
void PL0::enter(obj0 k,int &tx,int &dx,int lev)
{
	tx= tx+1;
	strcpy(table[tx].name,id);
	table[tx].kind=k;
	switch(k)
	{
	case CONSTANT:
		if(num>amax)
		{
			error(31);
			num=0;
		}
		table[tx].other.val=num;
		break;
	case VARIABLE:
		table[tx].other.inOther.level=lev;
		table[tx].other.inOther.adr=dx;
		dx++;
		break;
	case PROCEDURE:
		table[tx].other.inOther.level=lev;
		break;
	case ARRAY:		
		table[tx].other.inOther.size = lev;
		break;
	}
}//enter end


// 查找标示符在名字表中的位置 
int PL0::position(alfa id,int tx)//find identifier id in table
{
	int i;
	strcpy(table[0].name, id);
	i= tx;
	while (strcmp(table[i].name,id)!=0)i--;
	return i;
}//position end

// 常量定义处理
void PL0::constdeclaration(int&tx,int&dx,int lev)
{
	if(sym == IDENT)
	{
	  getsym();
	  if(sym>=EQL&&sym<=BECOMES)
	  {
		if( sym ==BECOMES)
			  error(1);
		getsym();
		if( sym == NUMBER)
		{
			enter(CONSTANT,tx,dx,lev);
			getsym();
		}
		else
		  error(2);
	  }
	  else
		error(3);
	}
	else
	  error(4);
}// constdeclaration end

// 变量说明处理
void PL0::vardeclaration(int&tx,int&dx,int lev)
{
	if( sym == IDENT)
	{				
		enter(VARIABLE,tx,dx,lev);
		getsym();
	}
	else
		error(4);
}//vardeclaration end

// 数组说明处理
void PL0::arraydeclaration(int&tx,int&dx,int lev)
{
    int upscript=0,downscript=0;
	getsym();
	if(sym == NUMBER || sym == CONSTSYM)
	{
		if(num == 0)
		{
			upscript = num;
			getsym();
		}
		else 
			error(32);
	}
	if(sym == COMMA)
		getsym();
	else
		error(32);
	if(sym == NUMBER || sym == CONSTSYM)
	{
		downscript = num;
		getsym();
	}
	if(sym != RPAREN)
		error(32);
	else
	{
		enter(ARRAY,tx,dx,downscript+1);
		getsym();
	}
}

// 列出目标代码清单
void PL0::listcode(int cx0)//list code generated for this block
{
	int i;
	if(listswitch)
		for (i= cx0;i<cx;i++)
		   cout<<" "<<i<<"  "<<mnemonic[code[i].f]
			<<"  "<<code[i].l<<"  "<<code[i].a<<endl;
}// listcode end

// 语句部分处理 
void PL0::statement(symset fsys,int tx,int lev)
{

⌨️ 快捷键说明

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