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

📄 pl0.c

📁 本程序实现编译原理中
💻 C
📖 第 1 页 / 共 3 页
字号:
						{
							if(sym == whilesym)
							{
								cx1 = cx;
								getsymdo;
								memcpy(nxtlev,fsys,sizeof(bool)*symnum);
								nxtlev[dosym] = true;

								conditiondo(nxtlev,ptx,lev);

								cx2 = cx;
								gendo(jpc,0,0);
								if(sym == dosym)
								{
									getsymdo;
								}
								else
								{
									error(18);
								}

								statementdo(fsys,ptx,lev);
								
								gendo(jmp,0,cx1);
								code[cx2].a = cx;
							}
							else
							{
								memset(nxtlev,0,sizeof(bool)*symnum);
								testdo(fsys,nxtlev,19);/*<><><><><><><><>语句处理末尾*/
							}
						}
					}
				}
			}
		}
	}
	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 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;
	nxtlev[cossym] = true;
	nxtlev[sinsym] = true;
	nxtlev[tansym] = true;
	nxtlev[expsym] = true;

 	factordo(nxtlev,ptx,lev);

	while(sym == times || sym == slash)
	{
		mulop = sym;
		getsymdo;

		factordo(nxtlev,ptx,lev);

		if(mulop == times)
		{
			gendo(opr,0,4);
		}
		else
		{
			gendo(opr,0,5);
		}
	}
	return 0;
}

/*
<因子> ::= <标识符>|<无符号整数>|'('<表达式>')'
左右括号表示pl0程序正文中的括号,而不是EBNF元语言的括号
*/
int factor(bool* fsys,int* ptx,int lev)
{ 
	int i;
	bool nxtlev[symnum];

	
	testdo(facbegsys,fsys,24);/*<><><><><><><><>因子处理的开始*/

	while(inset(sym,facbegsys))//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 procedur://不可能是过程名
						error(21);
						break;
				}
			}
			getsymdo;
		}
		else
		{
			if(sym == number)
			{
				if(numlen > MAX_NUM_LENGTH)
				{
					error(31);
					num = 0;
				}
				gendo(lit,0,num);

				getsymdo;
			}			
			else
			{
				if(sym == cossym || sym == sinsym || sym == tansym || sym == expsym)// 
				{
					enum symbol tmpsym;
					tmpsym = sym;
					getsymdo;
					memcpy(nxtlev,fsys,sizeof(bool)*symnum);

					funcdo(nxtlev,ptx,lev);

					if(sym == rparen)
					{
						if(tmpsym == cossym)
						{
							gen(fun,0,0);//cos
							getsymdo;						
						}
						else if(tmpsym == sinsym)
						{
							gen(fun,0,1);
							getsymdo;
						}
						else if(tmpsym == tansym)
						{
							gen(fun,0,2);
							getsymdo;
						}
						else
						{
							gen(fun,0,3);
							getsymdo;
						}

					}
					else
					{
						error(22);
					}
				}
				else if(sym == lparen)//else 为什么不行呢?????
				{
					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 func(bool* fsys,int* ptx,int lev)
{
	bool nxtlev[symnum];
	
	if(sym == lparen)
	{				
		getsymdo;
		memcpy(nxtlev,fsys,sizeof(bool)*symnum);
		nxtlev[rparen] = true;
		expressiondo(nxtlev,ptx,lev);
	}
	else
	{
		printf("Standard function must be followed (\n");
	}


	return 0;
}
/*
<条件>::=<表达式><关系运算符><表达式>|ODD<表达式>
*/
int condition(bool* fsys,int* ptx,int lev)
{
	enum symbol relop;
	bool nxtlev[symnum];

	if(sym == oddsym)
	{
		getsymdo;
		expressiondo(fsys,ptx,lev);
		gendo(opr,0,6);
	}
	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 geq:
					gendo(opr,0,11);
					break;
				case gtr:
					gendo(opr,0,12);
					break;
				case leq:
					gendo(opr,0,13);
					break;
			}
		}
	}
	return 0;
}

void interpret()
{	
	
	int p,b,t;						/*指令指针、指令基址、栈顶指针 所谓基址就是每个过程的基址
									栈顶是将要存放数据的位置,也就是说t所在位置永远都是空位置*/
	struct instruction i;
	double s[stacksize];				//运行栈是个局部变量

	int loop = 0;//add by daka
	int delay = 0;//add by daka
	int nl = 0;	//add by daka
	double tmp;//add by daka
	
	t = 0;
	p = 0;
	b = 0;
	s[0] = s[1] = s[2] = 0;	

	for(delay=0;delay<80;delay++)
	{
		loop = 0;
		while(loop<5000000)
			loop++;
		printf(">");	
	}
	

	do
	{
		i = code[p];
		p++;
		switch(i.f)
		{
			case lit:
				s[t] = (double)i.a;
				t++;
				break;
			case opr:
				switch(i.a)
				{
					case 0://过程调用结束后,返回调用点并退栈
						t = b;//b指向静态链,于是t+1指向动态链,t+2指向返回地址。
						p = (int)s[t+2];
						b = (int)s[t+1];
						break;
					case 1://栈顶元素取反
						s[t-1] = -s[t-1];
						break;
					case 2://次栈顶与栈顶相加,退两个栈元素,结果值进栈
						t--;
						s[t-1] = s[t-1] + s[t];
						break;
					case 3://相减
						t--;
						s[t-1] = s[t-1] - s[t];
						break;
					case 4://相乘
						t--;
						s[t-1] = s[t-1] * s[t];
						break;
					case 5://相除
						t--;
						s[t-1] = s[t-1] / s[t];
						break;
					case 6://栈顶元素奇偶判断,奇为真,偶为假,结果值在栈顶
						s[t-1] = (int)s[t-1] % 2;
						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("[PL0 START]# %lf\n",s[t-1]);
						fprintf(fa2,"[PL0 START]# %lf\n",s[t-1]);
						t--;
						break;
					case 15://屏幕输出换行
						printf("\n");
						fprintf(fa2,"\n");
						break;
					case 16://从命令行读入 输入置于栈顶
						printf("[PL0 START]# ");
						fprintf(fa2,"[PL0 START]# ");
						scanf("%lf",&(s[t]));

						fprintf(fa2,"%lf\n",s[t]);
						t++;
						break;

				}
				break;
			case fun:
				switch(i.a)
				{
					case 0:
						s[t-1] = cos((int)s[t-1]);
						break;
					case 1:
						s[t-1] = sin((int)s[t-1]);
						break;
					case 2:
						s[t-1] = tan((int)s[t-1]);
						break;
					case 3:
						s[t-1] = exp(s[t-1]);
						break;
					default:
						break;
				}
				break;
			case lod://将变量取到栈顶,a为偏移量,l为层差。
				s[t] = s[base(i.l,s,b)+i.a];
				t++;
				break;
			case sto://将栈顶内容送入某变量单元中,a为偏移量,l为层差
				t--;
				s[base(i.l,s,b)+i.a] = s[t];//s是运行时栈,b是当前过程的基址,i.l是当前过程与被调用过程的层差。
				break;
			/*
				PL0调用规则:
				1、任意一个过程只能调用它的直接内层过程
				2、只要确保不超出范围,任意一个过程可以调用它的任何外过程
				3、同层过程
				总结:向内调用只能逐层调用,而向外调用则可以跳跃调用。
				*/
			case cal://过程调用,a为过程地址,l为层差
				s[t] = base(i.l,s,b);
				s[t+1] = (double)b;
				s[t+2] = (double)p;
				b = t;
				p = i.a;
				printf("s[%d]=%d,s[%d]=%d,s[%d]=%d start=%d\n",t,s[t],t+1,s[t+1],t+2,s[t+2],i.a);
				fprintf(fa2,"s[%d]=%d,s[%d]=%d,s[%d]=%d start=%d\n",t,s[t],t+1,s[t+1],t+2,s[t+2],i.a);

				break;
			case inte://在运行栈中为被调用的过程开辟a个单元的数据区。
				t += i.a;
				break;
			case jmp://无条件跳转至a地址
				p = i.a;
				break;
			case jpc://条件跳转,当栈顶布尔值非真时,则跳转至a地址执行,否则顺序执行。
				t--;
				if(s[t] == 0)
				{
					p = i.a;
				}
				break;
		}
	
	}while(p != 0);
}

/*
通过过程基址求上L层过程的基址
*/
int base(int l,double *s,int b)
{
	int bl;
	bl = b;

	//当l<=0时,

	while(l > 0)
	{
		bl = (int)s[bl];
		l--;
	}
	return bl;
}

⌨️ 快捷键说明

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