PL/0编译器

源代码在线查看: code.cpp

软件大小: 635 K
上传用户: 5201314
关键词: PL 编译器
下载地址: 免注册下载 普通下载 VIP

相关代码

				#include "StdAfx.h"
				#include ".\code.h"
				#include 
				#include 
				#include 
				
				using namespace std;
				
				CCode::CCode(CPl0*p)
				{
					cx = 0;
					pl=p;
				}
				
				/*目标代码生成过程gen 
				  参数:x:要生成的一行代码的助记符 
				  y, z:代码的两个操作数 
				  本过程用于把生成的目标代码写入目标代码数组,供后面的解释器解释执行 */
				void CCode::Gen(enum fct x,int y,int z)
				{
					if (cxcxmax表示当前生成的代码行号大于允许的最大代码行数
					{
						code[cx].f=x;
						code[cx].l=y;
						code[cx].a=z;
						cx++;						//移动cx指针指向下一个空位
					}
				}
				
				/* 通过静态链求出数据区基地址的函数base
				   参数说明:l:要求的数据区所在层与当前层的层差
				   返回值:要求的数据区基址 */
				int CCode::base(int l)
				{
					int b1;
					b1=b;							//首先从当前层开始
					while (l>0)
					{
						b1=s[b1];					//用当前层数据区基址中的内容(正好是静态链SL数据,为上一层的基址)
													//的作为新的当前层,即向上找了一层
						l--;						//向上了一层,l减一
					}
					return b1;						//把找到的要求的数据区基址返回
				}
				
				void CCode::Interpret()
				{
					int p,t;
					fct f;
					int l,a;
				
					t=0;b=1;p=0;					//程序开始运行时栈顶寄存器置0,数据段基址为1,从0号代码开始执行程序
					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)					//如果i的f,即指令助记符是下面的某种情况,执行不同的功能
						{
						case lit:
							s[++t]=a;				//栈顶指针上移,在栈中分配了一个单元
							break;					//该单元的内容存放i指令的a操作数,即实现了把常量值放到运行栈栈顶 
						case opr:
							switch (a)
							{
							case 0:
								t=b-1;				//释放这段子过程占用的数据内存空间
								p=s[t+3];			//把指令指针取到RA的值,指向的是返回地址
								b=s[t+2];			//把数据段基址取到DL的值,指向调用前子过程的数据段基址
								break;
							case 1:
								s[t]=-s[t];			//对栈顶数据进行取反
								break;
							case 2:	
								t--;
								s[t]=s[t]+s[t+1];	//把两单元数据相加存入栈顶
								break;
							case 3:	
								t--;
								s[t]=s[t]-s[t+1];	//把两单元数据相减存入栈顶
								break;
							case 4:	t--;
								s[t]=s[t]*s[t+1];	//把两单元数据相乘存入栈顶
								break;
							case 5:	
								t--;
								s[t]=s[t]/s[t+1];	//把两单元数据相整除存入栈顶
								break;
							case 6:
								s[t]=s[t]%2;		//数据栈顶的值是奇数则把栈顶值置1,否则置0
								break;
							case 8:	
								t--;
								s[t]=(s[t]==s[t+1]);//判等,相等栈顶置1,不等置0 
								break;
							case 9:	
								t--;
								s[t]=(s[t]!=s[t+1]);//判不等,不等栈顶置1,相等置0
								break;
							case 10: 
								t--;
								s[t]=(s[t]								break;
							case 11: 
								t--;
								s[t]=(s[t]>=s[t+1]);//判大于等于,如果下面的值大于等于上面的值,栈顶置1,否则置0
								break;
							case 12: 
								t--;
								s[t]=(s[t]>s[t+1]); //判大于,如果下面的值大于上面的值,栈顶置1,否则置0
								break;
							case 13: 
								t--;
								s[t]=(s[t]								break;
							case 14:
								cout								break;
							case 15:
								cout								break;
							case 16:
								t++;
								cout								cin>>s[t];			//16号操作是接受键盘值输入到栈顶
								break;
							}
							break;
						case lod:					//如果是lod指令:将变量放到栈顶
							t++;					//栈顶上移,开辟空间
							s[t]=s[base(l)+a];		//通过数据区层差l和偏移地址a找到变量的数据,存入上面开辟的新空间(即栈顶)
							break;
						case sto:
							s[base(l)+a]=s[t];		//把栈顶的值存入位置在数据区层差l偏移地址a的变量内存
							t--;					//栈项下移,释放空间
							break;
						case 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 tint:
							t+=a;					//栈顶上移a个空间,即开辟a个新的内存单元
							break;
						case jmp:
							p=a;					//把jmp指令操作数a的值作为下一次要执行的指令地址,实现无条件跳转
							break;
						case jpc:
							if (s[t]==0)			//判断栈顶值
								p=a;				//如果是0就跳转,否则不跳转
							t--;					//释放栈顶空间
							break;
						}
					}while (p!=0);
				}
				
				//逐行输出代码
				void CCode::ListCode()
				{
					FILE *fp;
					//int i;
					char c[1];
					char *filename = pl->flnm;
				
					strcat(filename,".txt");
				
					if((fp=fopen(filename,"wb"))==NULL)
					{
						printf("cant open the file");
						exit(0);
					}
				
					for (int i=0;i					{
						cout						switch (code[i].f)
						{
						case lit:
							cout							fwrite("lit  ",sizeof(char),strlen("lit  "),fp);
							break;
						case lod:
							cout							fwrite("lod  ",sizeof(char),strlen("lod  "),fp);
							break;
						case sto:
							cout							fwrite("sto  ",sizeof(char),strlen("sto  "),fp);
							break;
						case cal:
							cout							fwrite("cal  ",sizeof(char),strlen("cal  "),fp);
							break;
						case tint:
							cout							fwrite("int  ",sizeof(char),strlen("int  "),fp);
							break;
						case jmp:
							cout							fwrite("jmp  ",sizeof(char),strlen("jmp  "),fp);
							break;
						case jpc:
							cout							fwrite("jpc  ",sizeof(char),strlen("jpc  "),fp);
							break;
						case opr:
							cout							fwrite("opr  ",sizeof(char),strlen("opr  "),fp);
							break;
						}
						cout						c[0] = static_cast('0'+ code[i].l);
						fwrite(c,sizeof(char),1,fp);
						fwrite("  ",sizeof(char),strlen("  "),fp);
						if(code[i].a >= 10)
						{
							c[0] = static_cast('0'+ code[i].a / 10);
							fwrite(c,sizeof(char),1,fp);
						}
						c[0] = static_cast('0'+ code[i].a%10);
						fwrite(c,sizeof(char),1,fp);
						fwrite("\t\t",sizeof(char),strlen("\t\t"),fp);
					}
				}
				
				CCode::~CCode(void)
				{
				}
							

相关资源