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

📄 pl0.cpp

📁 plo 源碼 在基礎上增加了 switch:case语句 和 while語句 輸入文件為Pascl
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				break;
			case 5:
				t--;
				s[t-1]=s[t-1]/s[t];
				break;
			case 6:
				s[t-1]=s[t-1]%2;
				break;
			case 7:
				break;
			case 8:
				t--;
				s[t-1]=s[t-1]==s[t];
				break;
			case 9:
				t--;
				s[t-1]=s[t-1]!=s[t];
				break;
			case 10:
				t--;
				s[t-1]=s[t-1]<s[t];
				break;
			case 11:
				t--;
				s[t-1]=s[t-1]>=s[t];
				break;
			case 12:
				t--;
				s[t-1]=s[t-1]>s[t];
				break;
			case 13:
				t--;
				s[t-1]=s[t-1]<=s[t];
				break;
			case 14:
				printf("%d",s[t-1]);
				fprintf(fa2,"%d",s[t-1]);
				t--;
				break;
			case 15:
				printf("\n");
				fprintf(fa2,"\n");
				break;
			case 16:
				printf("?");
				fprintf(fa2,"?");
				scanf("%d",&s[t]);
				fprintf(fa2,"%d\n",s[t]);
				t++;
				break;
			}
			break;
		case lod://取相对当前过程的数据基地址为a的内存的值到栈顶
			s[t]=s[base(i.l,s,b)+i.a];
			t++;
			break;
		case sto://栈顶的值存到相对当前过程的数据基地址为a 的内存
			t--;
			s[base(i.l,s,b)+i.a]=s[t];
			break;
		case cal://调用子过程
			s[t]=base(i.l,s,b);//将父过程的基地址入栈
			s[t+1]=b;//将本过程基地址入栈
			s[t+2]=p;//将当前指令指针入栈
			b=t;//改变基地址指针的值为新过程的基地址
			p=i.a;//跳转
			break;
		case inte://分配内存
			t+=i.a;
			break;
		case jmp://直接跳转
			p=i.a;
			break;
		case jpc://条件跳转
			t--;
			if(s[t]==0) p=i.a;
			break;
		}
	}while(p!=0);
}
/*
 * 因子处理
 */
int factor(bool*fsys,int *ptx,int lev)
{
	int i;
	bool nxtlev[symnum];
	testdo(facbegsys,fsys,24);//检测因子的开始符号
	while(inset(sym,facbegsys))//循环直到不是因子的开始符号
	{
		if(sym==ident)//因子为常量或变量
		{
			i=position(id,*ptx);//查找名字
			if(i==0)
			{
				error(11);//标识符没有声明
			}
			else
			{
				switch(table[i].kind)
				{
				case constant://名字是常量
					gendo(lit,0,table[i].val);//直接把常量的值入栈
					break;
				case variable://名字是变量
					gendo(lod,lev-table[i].level,table[i].adr);//找到变量的地址入栈
					break;
				case procedure://名字是过程
					error(21);//不能为过程
					break;
				}
			}
			getsymdo;
		}
		else
		{
			if(sym==number)//因子为数
			{
				if(num>amax)
				{
					error(31);
					num=0;
				}
				gendo(lit,0,num);
				getsymdo;
			}
			else
			{
				if(sym==lparen)//因子是表达式
				{
					getsymdo;
                    memcpy(nxtlev,fsys,sizeof(bool)*symnum);
					nxtlev[rparen]=true;
					expressiondo(nxtlev,ptx,lev);
					if(sym==rparen)
					{
						getsymdo;
					}
					else
					{
						error(22);//缺少右括号
					}
				}
				testdo(fsys,facbegsys,23);//因子后有非法符号
			}
		}
	}
	return 0;
}
/*
 * 项处理
 */
int term(bool*fsys,int *ptx,int lev)
{
	enum symbol mulop;//用于保存乘法或除法符号
	bool nxtlev[symnum];
	memcpy(nxtlev,fsys,sizeof(bool)*symnum);
	nxtlev[times]=true;
	nxtlev[slash]=true;
	factordo(nxtlev,ptx,lev);//处理因子
	while(sym==times||sym==slash)
	{
		mulop=(symbol)sym;
		getsymdo;
		factordo(nxtlev,ptx,lev);
		if(mulop==times)
		{
			gendo(opr,0,4);//生成乘法指令
		}
		else
		{
			gendo(opr,0,5);//生成除法指令
		}
	}
	return 0;
}
/* 
 * 条件处理
 */
int condition(bool*fsys,int *ptx,int lev)
{
	enum symbol relop;
	bool nxtlev[symnum];
	if(sym==oddsym)//按照odd运算处理
	{
		getsymdo;
		expressiondo(fsys,ptx,lev);
		gendo(opr,0,6);//生成odd指令
	}
	else
	{   //逻辑表达式处理
		memcpy(nxtlev,fsys,sizeof(bool)*symnum);
		nxtlev[eql]=true;
		nxtlev[neq]=true;
		nxtlev[lss]=true;
		nxtlev[leq]=true;
		nxtlev[gtr]=true;
		nxtlev[geq]=true;
		expressiondo(nxtlev,ptx,lev);
		if(sym!=eql&&sym!=neq&&sym!=lss&&sym!=leq&&sym!=gtr&&sym!=geq)
		{
			error(20);
		}
		else
		{
			relop = sym;
			getsymdo;
			expressiondo(fsys,ptx,lev);
			switch(relop)
			{
			case eql:
				gendo(opr,0,8);
				break;
			case neq:
				gendo(opr,0,9);
				break;
			case lss:
				gendo(opr,0,10);
				break;
			case leq:
				gendo(opr,0,13);
				break;
			case gtr:
				gendo(opr,0,12);
				break;
			case geq:
				gendo(opr,0,11);
				break;
			}
		}
	}
	return 0;
}
/* 
 * 表达式处理
 */
int expression(bool*fsys,int *ptx,int lev)
{
	enum symbol addop;//用于保存正负号
	bool nxtlev[symnum];
	if(sym==plus||sym==minus)//开头是正负号,此时当前表达式被看作一个正的或负的项
	{
		addop=sym;//保存开头的正负号
		getsymdo;
		memcpy(nxtlev,fsys,sizeof(bool)*symnum);
		nxtlev[plus]=true;
		nxtlev[minus]=true;
		termdo(nxtlev,ptx,lev);//处理项
		if(addop==minus)//如果开头为负号生成取负指令
		{
			gendo(opr,0,1);
		}
	}
	else//此时表达式被看作项的加减
	{
		memcpy(nxtlev,fsys,sizeof(bool)*symnum);
		nxtlev[plus]=true;
		nxtlev[minus]=true;
		termdo(nxtlev,ptx,lev);//处理项
	}
	while(sym==plus||sym==minus)
	{
		addop=sym;
		getsymdo;
		memcpy(nxtlev,fsys,sizeof(bool)*symnum);
		nxtlev[plus]=true;
		nxtlev[minus]=true;
		termdo(nxtlev,ptx,lev);//处理项
		if(addop==plus)
		{
			gendo(opr,0,2);//生成加法指令
		}
		else
		{
			gendo(opr,0,3);//生成减法指令
		}
	}
	return 0;
}
/*
 * 语句处理
 */
int statement(bool*fsys,int *ptx,int lev)
{
	int i,cx1,cx2;
	bool nxtlev[symnum];
	if(sym==ident)//按照赋值语句处理
	{
		i=position(id,*ptx);
		if(i==0)//变量没有找到
		{
			error(11);
		}
		else
		{
			if(table[i].kind!=variable)
			{
				error(12);//赋值语句格式错误
				i=0;
			}
			else
			{
				getsymdo;
				if(sym==becomes)
				{
					getsymdo;
				}
				else
				{
					error(13);//没有检测到赋值符号
				}
				memcpy(nxtlev,fsys,sizeof(bool)*symnum);
				expressiondo(nxtlev,ptx,lev);//处理赋值符号右边的表达式
				/* expression将执行一系列指令,但最终结果将会保存在栈顶
				 * 执行sto命令完成赋值
				 */
				if(i!=0)
				{
					gendo(sto,lev-table[i].level,table[i].adr);
				}
			}
		}
	}
	else
	{
		if(sym==readsym)//按照read语句处理
		{
			getsymdo;
			if(sym!=lparen)
			{
				error(34);//格式错误,应是左括号
			}
			else
			{
				do
				{
					getsymdo;
					if(sym==ident)
					{
						i=position(id,*ptx);//查找要读的变量
					}
					else
					{
						i=0;
					}
					if(i==0)
					{
						error(35);//read()中应是声明过的变量名
					}
					else
					{
						gendo(opr,0,16);//生成输入指令,读取值到栈顶
						gendo(sto,lev-table[i].level,table[i].adr);//存储到变量
					}
					getsymdo;
				}while(sym==comma);//一条read语句可以读取多个变量
			}
			if(sym!=rparen)
			{
				error(33);//格式错误,应是右括号
				while(!inset(sym,fsys))//出错补救,直到收到上层函数的后继符号
				{
					getsymdo;
				}
			}
			else
			{
				getsymdo;
			}
		}
		else
		{
			if(sym==writesym)//按照write语句处理
			{
				getsymdo;
				if(sym==lparen)
				{
					do
					{
						getsymdo;
						memcpy(nxtlev,fsys,sizeof(bool)*symnum);
						nxtlev[rparen]=true;//write的后继符号是右括号或逗号
						nxtlev[comma]=true;
						expressiondo(nxtlev,ptx,lev);//调用表达式处理
						gendo(opr,0,14);//生成输出指令,输出栈顶的值
					}while(sym==comma);
					if(sym!=rparen)
					{
						error(33);//write中应为完整表达式
					}
					else
					{
						getsymdo;
					}
				}
				gendo(opr,0,15);//输出换行
			}
			else
			{
				if(sym==callsym)//按照call语句处理
				{
					getsymdo;
					if(sym!=ident)
					{
						error(14);//call应是标识符
					}
					else
					{
						i=position(id,*ptx);
						if(i==0)
						{
							error(11);//过程没有找到
						}
						else
						{
							if(table[i].kind==procedure)
							{
								gendo(cal,lev-table[i].level,table[i].adr);//生成call指令
							}
							else
							{
								error(15);//call后标识符应是过程
							}
						}
						getsymdo;
					}
				}
				else
				{
					if(sym==ifsym)//按照if 语句处理
					{
						getsymdo;
				    	memcpy(nxtlev,fsys,sizeof(bool)*symnum);
				    	nxtlev[thensym]=true;//后继符号是then或do
				    	nxtlev[dosym]=true;
				    	condition(nxtlev,ptx,lev);//调用条件处理函数
				    	if(sym==thensym)
						{
							getsymdo;
						}
				    	else
						{
							error(16);//缺少then
						}
				    	cx1 = cx;//保存当前指令地址
				    	gendo(jpc,0,0);//生成条件跳转指令,跳转地址暂时写0
				    	statementdo(fsys,ptx,lev);//处理then后的语句
					    code[cx1].a=cx;/* 经过statement处理后cx为then后语句执行
									    * 完的位置,它正是前面未指定的跳转地址
										*/
					}
			    	else
					{
						if(sym==beginsym)//按照复合语句处理
						{
							getsymdo;
						    memcpy(nxtlev,fsys,sizeof(bool)*symnum);
					     	nxtlev[semicolon]=true;//后继符号是分号或end
					    	nxtlev[endsym]=true;
							/* 循环调用语句处理函数,直到下一个符号不是
							 * 语句开始符号或收到end
							 */
					    	statementdo(nxtlev,ptx,lev);
					    	while(inset(sym,statbegsys)||sym==semicolon)
							{
								if(sym==semicolon)
								{
									getsymdo;
								}
						    	else
								{
									error(10);//少分号
								}
						    	statementdo(nxtlev,ptx,lev);
							}
						    if(sym==endsym)
							{
								getsymdo;
							}
					    	else
							{
								error(17);//少end 或分号
							}
						}
				    	else
						{
							if(sym==whilesym)//按照while语句处理
							{
								cx1 = cx;//保存判断条件操作的位置
						    	getsymdo;
						     	memcpy(nxtlev,fsys,sizeof(bool)*symnum);
						    	nxtlev[dosym]=true;//后继符号是do
						    	conditiondo(nxtlev,ptx,lev);
						    	cx2 = cx;//保存循环体内的结束的下一个位置
						    	gendo(jpc,0,0);//生成条件跳转,但跳出的地址不知道
						    	if(sym==dosym)
								{
									getsymdo;
								}
						    	else
								{
									error(18);//少do
								}
						    	statementdo(fsys,ptx,lev);//循环体
							    gendo(jmp,0,cx1);//回头重新判断条件
						    	code[cx2].a=cx;//反填跳出循环的地址,与if类似
							}
					    	else
							{
								memset(nxtlev,0,sizeof(bool)*symnum);//语句结束无补救集合
						    	testdo(fsys,nxtlev,19);//检查语句结束的正确性
							}
						}
					}
				}
			}
		}
	}
	return 0;
}
/* 
 * 输出目标代码清单
 */
void listcode(int cx0)
{
	int i;
	if(listswitch)
	{
		for(i=cx0;i<cx;i++)
		{
			printf("%d %s %d %d\n",i,mnemonic[code[i].f],code[i].l,code[i].a);
			fprintf(fa,"%d %s %d %d\n",i,mnemonic[code[i].f],code[i].l,code[i].a);
		}
	}

}
/*
 * 变量声明处理
 */
int vardeclaration(int *ptx,int lev,int*pdx)
{
	if(sym==ident)
	{
		enter(variable,ptx,lev,pdx);//填写名字表
		getsymdo;
	}
	else
	{
		error(4);//var后应是标识符
	}
	return 0;
}
/*
 * 常量声明处理
 */
int constdeclaration(int*ptx,int lev,int *pdx)
{
	if(sym==ident)
	{
		getsymdo;
		if(sym==eql||sym==becomes)
		{
			if(sym==becomes)
			{
				error(1);//把=写成了:=
			}
			getsymdo;
			if(sym==number)
			{
				enter(constant,ptx,lev,pdx);
				getsymdo;
			}
			else
			{
				error(2);//常量说明后应是数字
			}
		}
		else
		{
			error(3);//常量说明标识后应是=
		}
	}
	else
	{
		error(4);//const后应是标识符
	}
	return 0;
}
/*
 * 查找名字的位置
 * idt:要查找的名字
 * tx:当前名字表尾指针
 */
int position(char*idt,int tx)
{
	int i;
	strcpy(table[0].name,idt);
	i=tx;
	while(strcmp(table[i].name,idt)!=0)
	{
		i--;
	}
	return i;
}
/*
 * 在名字表中加入一项
 * k:名字的种类
 * ptx:名字表尾指针的指针
 * lev:名字所在的层次
 * pdx:当前应分配的变量的相对地址
 */
void enter(enum object k,int *ptx,int lev,int *pdx)
{
	(*ptx)++;
	strcpy(table[*ptx].name,id);//全局变量id已经存有当前名字的名字
	table[*ptx].kind=k;
	switch(k)
	{
	case constant://常量名字
		if(num>amax)
		{
			error(31);//数越界
			num=0;
		}
		table[(*ptx)].val =num;
		break;
	case variable://变量名字
		table[(*ptx)].level=lev;
		table[(*ptx)].adr=(*pdx);
		(*pdx)++;
		break;
	case procedure://过程名字
		table[(*ptx)].level=lev;
		break;
	}
}
/*
 *通过过程基址求上1层过程的基址
 */
int base(int l,int*s,int b)
{
	int bl;
	bl = b;
	while(l>0)
	{
		bl=s[bl];
		l--;
	}
	return bl;
}

⌨️ 快捷键说明

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