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

📄 pl0.cpp

📁 pl0的编译程序源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			error(20);
		else
		{
			relop= sym;
			getsym();
			expression(fsys,tx,lev);
			switch(relop)
			{
			case EQL: gen(OPR,0,8);//次栈顶与栈顶是否相等,退两个栈元素,结果值进栈
				break;
			case NEQ: gen(OPR,0,9);//次栈顶与栈顶是否不等,退两个栈元素,结果值进栈
				break;
			case LSS: gen(OPR,0,10);//次栈顶是否小于栈顶,退两个栈元素,结果值进栈
				break;
			case GEQ: gen(OPR,0,11);//次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈
				break;
			case GTR: gen(OPR,0,12);//次栈顶是否大于栈顶,退两个栈元素,结果值进栈
				break;
			case LEQ: gen(OPR,0,13);//次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈
				break;
			}
		}
	}
}//condition结束
void PL0::statement(symset fsys,int tx,int lev)//语句分析
{
	if(sourceEnd)
		return;
	int i,cx1,cx2;
	if(sym ==IDENT)
	{
		i= position(id,tx);//查找表
		if (i == 0)//未查到
			error(11);
		else if (table[i].kind!=VARIABLE)
		{
			error(12);//如果赋值号左边不是变量的报错
			i= 0;
		}
		getsym();
		if(sym ==BECOMES)
			getsym();
		else
			error(13);
		expression(fsys,tx,lev);
		if(sym!=SEMICOLON)
			error(10);
		if( i!= 0)
			gen(STO,lev-table[i].other.inOther.level,table[i].other.inOther.adr);//实现存数即赋值过程完成。
	}
	else if( sym==READSYM)//READ符号相当与C++中的CIN。
	{
		getsym();
		if( sym!=LPAREN)//左括号
			error(34);
		else
			do{
				getsym();
				if (sym==IDENT)
					i=position(id,tx);
				else
					i=0;
				if( i==0 )
					error(35);
				else
				{
					gen(OPR,0,16);//从命令行读入一个输入置于栈顶
					gen(STO,lev-table[i].other.inOther.level,table[i].other.inOther.adr);//存数,即将刚刚用户输入的数存入变量。
				}
				getsym();
			}while(sym==COMMA);
			if (sym!=RPAREN)
			{
				error(33);
				while (fsys.find(sym)!=fsys.end())  getsym();
			}
			else
				getsym();
	}
	else if( sym==WRITESYM)//相当于cout
	{
		getsym();
		if (sym==LPAREN)
		{
			do{
				getsym();
				symset tmp=fsys;
				for(int t=RPAREN;t<=COMMA;t++)
					tmp.insert((symbol)t);
				expression(tmp,tx,lev);
				gen(OPR,0,14);//栈顶值输出至屏幕
			}while(sym==COMMA);
			if (sym!=RPAREN)
				error(33);
			else
				getsym();
		}
		gen(OPR,0,15);
	}
	else if( sym ==CALLSYM)//过程调用语句。
	{
		getsym();
		if( sym!=IDENT)
			error(14);
		else
		{
			i= position(id,tx);
			if (i == 0)
				error(11);
			else if (table[i].kind = PROCEDURE)
				gen(CAL,lev-table[i].other.inOther.level,table[i].other.inOther.adr);//调用过程,adr为过程地址,level为层差
			else
				error(15);//CALL后接的变量不是过程名的报错
			getsym();
		}
	}
	else if( sym ==IFSYM)//IF语句的分析
	{
		getsym();
		symset tmp=fsys;
		for(int i=THENSYM;i<=DOSYM;i++)
			tmp.insert((symbol)i);
		condition(tmp,tx,lev);
		if( sym == THENSYM)
			getsym();
		else
			error(16);
		cx1= cx;//返填技术开始
		gen(JPC,0,0);
		statement(fsys,tx,lev);
		code[cx1].a= cx;
	}
	else if( sym ==BEGINSYM)//过程开始分析
	{
		getsym();
		symset tmp=fsys;
		for(int i=SEMICOLON;i<=ENDSYM;i++)
			tmp.insert((symbol)i);
		statement(tmp,tx,lev);
		tmp=statbegsys;
		tmp.insert(SEMICOLON);
		while( tmp.find(sym)!=tmp.end())
		{
			if(sourceEnd)return;
			if (sym ==SEMICOLON||sym ==ENDSYM)
				getsym();
			else if(sym=PERIOD)
			{
				error(26);
				getsym();
			}
			else
				error(10);
			tmp=fsys;
			for(i=SEMICOLON;i<=ENDSYM;i++)
				tmp.insert((symbol)i);
			if(sourceEnd)return;
			if(sym==ENDSYM)
				break;
			statement(tmp,tx,lev);
		}
		if( sym ==ENDSYM)
			getsym();
		else if(!sourceEnd)
			error(17);
	}
	else if(sym ==WHILESYM)//WHILE循环分析,典型的返填技术应用
	{
		cx1= cx;
		getsym();
		symset tmp=fsys;
		tmp.insert(DOSYM);
		condition(tmp,tx,lev);
		cx2= cx;
		gen(JPC,0,0);
		if(sym ==DOSYM)
			getsym();
		else
			error(18);//缺少DO
		statement(fsys,tx,lev);
		gen(JMP,0,cx1);//无条件跳转到cx1即WHILE条件判断处,返填的第一次应用。
		code[cx2].a= cx;//返填的第二次应用。
	}
}//statement结束
void PL0::block(int lev,int tx,symset fsys)//语法分析过程开始
{
	if(sourceEnd)
		return;
	int dx;//数据区的索引
	int tx0;//初始化分析表的索引,保留初始tx
	int cx0;//初始化code数组的索引,保留初始cx
	dx= 3;//数据区的索引要初始化为3,因为前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);//procedure后应为标识符
			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);
		}
	}while(declbegsys.find(sym)!=declbegsys.end());//直到没有声明符号
	code[table[tx0].other.inOther.adr].a= cx;//开始生成当前过程代码
	table[tx0].other.inOther.adr= cx;// 当前过程代码地址
	table[tx0].other.inOther.size=dx;//声明部分中每增加一条声明都会给dx增加1,声明部分已经结束,dx就是当前过程数据的size
	cx0= cx;
	gen(INT,0,dx);//生成分配内存代码--在运行栈中为被调用的过程开辟dx个单元的数据区
	symset tmp=statbegsys;
	for(int i=SEMICOLON;i<=ENDSYM;i++)
		tmp.insert((symbol)i);
	statement(tmp,tx,lev);
	gen(OPR,0,0);//过程调用结束后,返回调用点并退栈
	symset s2;
	test(fsys,s2,8);//检测后跟符号正确性
	listcode(cx0);//输出代码
}// block结束
int PL0::base(int l,int b,int s[])//通过过程基址求上l层过程的基址
{
	int b1;
	b1= b;
	while(l>0){//自下而上查找基址
		b1= s[b1];
		l= l-1;
	}
	return  b1;
}
void PL0::errout()//错误输出方法
{
	ofstream outfile("scanerr.txt");
	int err1=errorString.size();
	if(err1>0)
	{
		copy(errorString.begin(),errorString.end(),ostream_iterator<string>(outfile));
			return;
	}
}
	void PL0::interpret()//解释执行方法
	{
	const stacksize = 500;//运行栈大小
	int  p=0,b=1,t=0;//指令指针,指令基址,栈顶指针
	instruction  i;// 存放当前指令
	int  s[stacksize+1]={0};//运行栈
	cout<<" Start PL/0--Sundic\n";
	do{
		i= code[p];//读当前指令
		p= p+1;
		switch(i.f)
		{
		case LIT://将a的值取到栈顶
			t= t+1;
			s[t]= i.a;
			break;
		case OPR://数学、逻辑运算
			switch(i.a) //判断为哪一种操作
			{
			case 0:
				t= b-1;
				p= s[t+3];
				b= s[t+2];
				break;
			case 1:
				s[t]= -s[t];
				break;
			case 2:
				t= t-1;
				s[t]= s[t]+s[t+1];
				break;
			case 3:
				t= t-1;
				s[t]= s[t]-s[t+1];
				break;
			case 4:
				t= t-1;
				s[t]= s[t]*s[t+1];
				break;
			case 5:
				t= t-1;
				s[t]= s[t] / s[t+1];
				break;
			case 6:
				if(s[t]%2)
					s[t]=1;
				else
					s[t]=0;
				break;
			case 8:
				t= t-1;
				if(s[t]==s[t+1])
					s[t]=1;
				else
					s[t]=0;
				break;
			case 9:
				t= t-1;
				if(s[t]==s[t+1])
					s[t]=0;
				else
					s[t]=1;
				break;
			case 10:
				t= t-1;
				if(s[t]<s[t+1])
					s[t]=1;
				else
					s[t]=0;
				break;
			case 11:
				t= t-1;
				if(s[t]>=s[t+1])
					s[t]= 1;
				else
					s[t]=0;
				break;
			case 12:
				t= t-1;
				if(s[t]>s[t+1])
					s[t]= 1;
				else
					s[t]=0;
				break;
			case 13:
				t= t-1;
				if(s[t]<=s[t+1])
					s[t]= 1;
				else
					s[t]=0;
				break;
			case 14:
				cout<<"    "<<s[t];
				t=t-1;
				break;
			case 15:
				cout<<endl;
				break;
			case 16:
				t=t+1;
				cout<<"?";
				s[t]=0;
				cin>>s[t];
				break;
			};
			break;
			case LOD://取相对当前过程的数据基地址为a的内存的值到栈顶
				t= t+1;
				s[t]= s[base(i.l,b,s)+i.a];
				break;
			case STO://栈顶的值存到相对当前过程的数据基地址为a的内存
				s[base(i.l,b,s)+i.a]= s[t];
				t= t-1;
				break;
			case CAL://调用子过程
				s[t+1]= base(i.l,b,s);//将父过程基地址入栈
				s[t+2]= b;//将本过程基地址入栈,此两项用于base函数
				s[t+3]= p;//将当前指令指针入栈
				b= t+1;//改变基地址指针值为新过程的基地址
				p=i.a;//跳转
				break;
			case INT://分配内存
				t= t+i.a;
				break;
			case JMP://直接跳转
				p= i.a;
				break;
			case JPC://条件跳转
				if (s[t] == 0)
					p= i.a;
				t= t-1;
				break;
		}//switch结束
	  }while(p!=0);
	  cout<<" End PL/0--Sundic\n";
}//interpret结束
void PL0::SaveCode()
{
	if(fout)
		for (int i=0;i<cx;i++)
			fprintf(fout,"%d  %s %d %d\n ",i,mnemonic[code[i].f],code[i].l,code[i].a);
		fclose(fout);
}

⌨️ 快捷键说明

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