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


// code.cpp: implementation of the code class. 
////////////////////////////////////////////////////////////////////// 
#include "code.h" 
 
void Ccode::Gen(enum fct x,int y,int z) 
{ 
	if (cx>CODE_SIZE) { 
		printf("error:program too long"); 
		} 
	if (cx0) 
	{ 
		b1=s[b1]; 
		l--; 
	} 
	return b1; 
} 
//解析code中的p-code代码并执行 
void Ccode::Interpret() 
{ 
	int p,t; 
	fct f; 
	int l,a; 
	t=0;                             //p-code机的数据堆栈区 
	b=1;                             //p-code机的栈顶寄存器 
	p=0;                             //p-code机的基址寄存器 
	s[1]=0;s[2]=0;s[3]=0;            //数据内存中为SL,DL,RA三个单元均为0,标识为主程序 
	do{ 
		f=code[p].f;l=code[p].l;a=code[p].a;//开始获取一行目标代码 
		p++;                                //指令指针加一,指向下一条代码 
		switch (f) 
		{ 
		case lit:                           //如果是lit指令 
			s[++t]=a;                       //把常量值放到运行栈栈顶 
			break; 
		case opr:                           //如果是opr指令 
			switch (a) 
			{ 
			case 0:                         //0号操作为从子过程返回操作 
				t=b-1;                      //释放这段子过程占用的数据内存空间 
				p=s[t+3];                   //把指令指针取到RA的值,指向的是返回地址 
				b=s[t+2];                   //把数据段基址取到DL的值,指向调用前子过程的数据段基址 
				break; 
			case 1:                         //1号操作为栈顶数据取反 
				s[t]=-s[t]; 
				break; 
			case 2:	t--;                    //2号操作为栈顶两个数据加法 
				s[t]=s[t]+s[t+1]; 
				break; 
			case 3:	t--;                    //3号操作为栈顶两个数据减法 
				s[t]=s[t]-s[t+1]; 
				break; 
			case 4:	t--;                    //4号操作为栈顶两个数据乘法 
				s[t]=s[t]*s[t+1]; 
				break; 
			case 5:	t--;                    //5号操作为栈顶两个数据除法 
				s[t]=s[t]/s[t+1]; 
				break; 
			case 6:                         //6号操作为判奇偶 
				s[t]=s[t]%2; 
				break; 
			case 8:	t--;                    //8号操作为栈顶两个数据判等 
				s[t]=(s[t]==s[t+1]); 
				break; 
			case 9:	t--;                    //9号操作为栈顶两个数据判不等 
				s[t]=(s[t]!=s[t+1]); 
				break; 
			case 10: t--;                   //10号操作为栈顶两个数据判小于 
				s[t]=(s[t]=s[t+1]); 
				break; 
			case 12: t--;                   //12号操作为栈顶两个数据判大于 
				s[t]=(s[t]>s[t+1]); 
				break; 
			case 13: t--;                   //13号操作为栈顶两个数据判小于等于 
				s[t]=(s[t]<=s[t+1]); 
				break; 
			case 14:                        //14号操作为输出栈顶值 
				printf("%d\t",s[t]); 
				break; 
			case 15:                        //15号操作为输出换行 
				printf("\n"); 
				break; 
			case 16:                        //16号操作为接受键盘值输入到栈顶 
				t++; 
				printf("?"); 
				scanf("%d",&s[t]); 
				break; 
			} 
			break; 
		case lod:                           //如果是lod指令:将变量放到栈顶 
			t++;                            //栈顶上移,开辟空间 
			s[t]=s[base(l)+a];              //通过数据区层差l和偏移地址a找到变量的数据,存入栈顶 
			break; 
		case sto:                           //如果是sto指令 
			s[base(l)+a]=s[t];              //把栈顶的值存入位置在数据区层差l偏移地址a的变量内存 
			t--;                            //栈项下移,释放空间 
			break; 
		case cal:                           //如果是cal指令 
			s[t+1]=base(l);                 //在栈顶压入静态链SL 
			s[t+2]=b;                       //然后压入当前数据区基址,作为动态链DL 
			s[t+3]=p;                       //最后压入当前的断点,作为返回地址RA 
			b=t+1;                          //把当前数据区基址指向SL所在位置 
			p=a;                            //从a所指位置开始继续执行指令,即实现了程序执行的跳转 
			break; 
		case intint:                        //如果是int指令 
			t+=a;                           //栈顶上移a个空间,即开辟a个新的内存单元 
			break; 
		case jmp:                           //如果是jmp指令 
			p=a;                            //把jmp指令操作数a的值作为下一次要执行的指令地址,实现无条件跳转 
			break; 
		case jpc:                           //如果是jpc指令 
			if (s[t]==0)                    //判断栈顶值 
				p=a;                        //如果是0就跳转,否则不跳转 
			t--;                            //释放栈顶空间 
			break; 
		} 
	}while (p!=0); 
} 
void Ccode::ListCode() 
{ 
	for (int i=0;i