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

📄 compiler.cpp

📁 vc实现的pl0编译器,有读取输出功能-read() -write(),这个源码对初学编译原理者有很好的指导作用,我当初学的时候用了3天看懂了源码,也对编译原理更加理解了,毕竟只学理论不看代码是不可能
💻 CPP
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////
//	PL/0 Compiler Shell 0.14 (2003.12.30) [Source File]
//	Author:Dwing
///////////////////////////////////////////////////////////////
#include"compiler.h"		//For Shell
#include"stdio.h"
///////////////////////////////////////////////////////////////
HINSTANCE hinst;	//Recent Instance
OPENFILENAME ofn;	//For Open File Dialog
FILE *fp;			//For Open File
zCompile *cp;		//编译器对象指针
int asmnum=0;		//目标代码数量
int errnum=0;		//错误数量
char buf[65536];	//I/O Buffer
char bufERR[65536];
char str[512];		//File Name Buffer
char in[16];
char * p=in;
int digit;
//for syntex
zSyntax * s;
char text[65536];		//输入文法缓冲区
char out[65536];		//输出结果缓冲区
char str1[256],b[256];	//临时字串缓冲区
//for syntex end
#ifndef asm_
#define asm_
typedef struct		//汇编指令格式
{
	char			opr;	//指令操作码
	char			lvl;	//级数
	unsigned short	adr;	//地址码/操作数
}ASM;
#endif
enum{OP_LIT,OP_LOD,OP_STO,OP_CAL,OP_INT,OP_JMP,OP_JPC,OP_OPR};
enum{
	OPR_RET,OPR_NEG,OPR_ADD,OPR_SUB,OPR_MUL,OPR_DIV,
	OPR_ODD,OPR_NUL,OPR_EQL,OPR_NE ,OPR_LT ,OPR_LGE,
	OPR_LG ,OPR_LTE,OPR_WRT,OPR_WRN,OPR_RED
};
///////////////////////////////////////////////////////////////
void _main()		//Program Entry
{
//Get Instance Handle
	hinst=GetModuleHandle(0);
//Main DialogBox
	DialogBox(hinst,MAKEINTRESOURCE(IDD_MAINDLG),0,(DLGPROC)dlgproc);
}
///////////////////////////////////////////////////////////////
int getbase(int *s,int base,int lvl)	//取基址
{
	while(lvl--) base=s[base];
	return base;
}
///////////////////////////////////////////////////////////////

//For MAIN DialogBox
BOOL CALLBACK dlgproc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam)
{
	int i;int j;
	int num;//for run
	char b[4];//for run
	ASM a[16384];//for run
	switch(msg)
	{
	case WM_INITDIALOG:
		buf[65535]=0;	//结尾清0防止溢出
        bufERR[65535]=0;
		str[0]=0;		//Clear str[]
	//Set Window Text Font
		SendDlgItemMessage(hdlg,IDC_INPUT,WM_SETFONT,(DWORD)GetStockObject(ANSI_FIXED_FONT),0);
		SendDlgItemMessage(hdlg,IDC_ASM,WM_SETFONT,(DWORD)GetStockObject(SYSTEM_FIXED_FONT),0);
		SendDlgItemMessage(hdlg,IDC_ERR,WM_SETFONT,(DWORD)GetStockObject(SYSTEM_FIXED_FONT),0);
	//填充OPENFILENAME结构体
		memset(&ofn,0,sizeof(OPENFILENAME));	//Clear it First
		ofn.lStructSize=sizeof(OPENFILENAME);
		ofn.hwndOwner=hdlg; 
		ofn.hInstance=hinst; 
		ofn.lpstrFilter="所有文件(*.*)\0*.*\0";
		ofn.nMaxFile=511;		//最大文件名缓冲区长度
		ofn.lpstrFile=str;		//使用临时字符串
		ofn.Flags=OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST;
		ofn.lpstrTitle="打开PL/0程序文件";
		return 1;
	case WM_COMMAND:
		switch(LOWORD(wparam))
		{
		case ID_SYN:
			DialogBox(hinst,MAKEINTRESOURCE(IDD_SYN),0,(DLGPROC)synproc);break;
		case ID_COMPILE:
			SetCursor(LoadCursor(0,IDC_WAIT));			//Please wait...
			GetDlgItemText(hdlg,IDC_INPUT,buf,65535);	//Get PL/0 Text
			cp=new zCompile;							//Let's begin to compile...
			cp->compile(buf);							//Do the most complex part
			errnum=cp->geterr(bufERR);						//Get Error Text
			SetDlgItemText(hdlg,IDC_ERR,bufERR);         //Display it
			strcpy(bufERR,"运行结果为:\r\n");
			asmnum=cp->getasm(buf);						//Get ASM Text
			SetDlgItemText(hdlg,IDC_ASM,buf);			//Display it
			delete cp;									//The end of Compiling
			SetCursor(LoadCursor(0,IDC_ARROW));			//Completed
			break;
		case ID_RUN://以下为模拟堆栈机执行代码
			if(!asmnum)
				MessageBox(hdlg,"请先编译后再运行!","错误",MB_ICONERROR);
			else
				if(errnum)
					MessageBox(hdlg,"请先改正错误后再运行!","错误",MB_ICONERROR);
				else
				{
					fp=fopen("temp.pl0","wb");	//Write to temp file
					fprintf(fp,"%u\r\n",asmnum);
					fwrite(buf,1,strlen(buf),fp);
					fclose(fp);
					//PL/0 Interpreter
						fp=fopen("temp.pl0","rb");
	if(!fp)
	{
		printf("PL/0 ASM Interpreter 0.1\n");
		printf("Can't open \"temp.pl0\"!\n");
		return 0;
	}
	fscanf(fp,"%u",&num);
	for(i=0;i<num;i++)
	{
		fscanf(fp,"%*4u:%s%u%u",b,&a[i].lvl,&a[i].adr);
		if(!strcmp(b,"LIT")) a[i].opr=OP_LIT;
		if(!strcmp(b,"LOD")) a[i].opr=OP_LOD;
		if(!strcmp(b,"STO")) a[i].opr=OP_STO;
		if(!strcmp(b,"CAL")) a[i].opr=OP_CAL;
		if(!strcmp(b,"INT")) a[i].opr=OP_INT;
		if(!strcmp(b,"JMP")) a[i].opr=OP_JMP;
		if(!strcmp(b,"JPC")) a[i].opr=OP_JPC;
		if(!strcmp(b,"OPR")) a[i].opr=OP_OPR;
	}
	fclose(fp);

	int s[16384]={0},bp=0,sp=3,ip=0;
	do{
		switch(a[ip].opr)
		{
		case OP_INT:sp+=a[ip].adr;								break;
		case OP_LIT:s[++sp]=a[ip].adr;							break;
		case OP_LOD:s[++sp]=s[getbase(s,bp,a[ip].lvl)+a[ip].adr];break;
		case OP_STO:s[getbase(s,bp,a[ip].lvl)+a[ip].adr]=s[sp--];break;
		case OP_JMP:ip=a[ip].adr-1;								break;
		case OP_JPC:if(!s[sp--]) ip=a[ip].adr-1;				break;
		case OP_CAL:
			s[sp++]=getbase(s,bp,a[ip].lvl);//静态链
			s[sp++]=bp;						//动态链
			s[sp++]=ip+1;						//返回地址
			bp=sp-3;
			ip=a[ip].adr-1;
			break;
		case OP_OPR:
			switch(a[ip].adr)
			{
	//过程返回
			case OPR_RET:sp=bp; ip=s[bp+2]-1; bp=s[bp+1]; break;
	//栈顶元素取负数
			case OPR_NEG:s[sp]=-s[sp];break;
	//次栈顶和栈顶相加,结果为栈顶
			case OPR_ADD:sp--;s[sp]=s[sp]+s[sp+1];break;
	//次栈顶和栈顶相减,结果为栈顶
			case OPR_SUB:sp--;s[sp]=s[sp]-s[sp+1];break;
	//次栈顶和栈顶相乘,结果为栈顶
			case OPR_MUL:sp--;s[sp]=s[sp]*s[sp+1];break;
	//次栈顶和栈顶相除,结果为栈顶
			case OPR_DIV:sp--;s[sp]=s[sp]/s[sp+1];break;
	//栈顶是否为奇数,结果入栈(0或1)
			case OPR_ODD:s[sp]=s[sp]&1;break;
	//次栈顶和栈顶是否相等,结果入栈(0或1)
			case OPR_EQL:sp--;s[sp]=(s[sp]==s[sp+1]);break;
	//次栈顶和栈顶是否不等,结果入栈(0或1)
			case OPR_NE: sp--;s[sp]=(s[sp]!=s[sp+1]);break;
	//次栈顶是否比栈顶小,结果入栈(0或1)
			case OPR_LT: sp--;s[sp]=(s[sp]<s[sp+1]);break;
	//是否次栈顶大于等于栈顶,结果入栈(0或1)
			case OPR_LGE:sp--;s[sp]=(s[sp]>=s[sp+1]);break;
	//是否次栈顶大于栈顶,结果入栈(0或1)
			case OPR_LG: sp--;s[sp]=(s[sp]>s[sp+1]);break;
	//是否次栈顶小于等于栈顶,结果入栈(0或1)
			case OPR_LTE:sp--;s[sp]=(s[sp]<=s[sp+1]);break;
	//打印栈顶元素
			case OPR_WRT:j=strlen(bufERR);sprintf(bufERR+j,"%d  ",s[sp--]);
				            SetDlgItemText(hdlg,IDC_ERR,bufERR);break;
	//打印回车
			case OPR_WRN: strcat(bufERR,"\r\n");
				           j=strlen(bufERR);sprintf(bufERR+j,"%d  ",s[sp--]);
				            SetDlgItemText(hdlg,IDC_ERR,bufERR);break;
	//从键盘读取数
			case OPR_RED:DialogBox(hinst,MAKEINTRESOURCE(IDD_INPUT),0,(DLGPROC)inputproc);
			int len=strlen(in);
			if(len>6)
			{
				MessageBox(hdlg,"输入大于六位整数,请重新输入","错误!",MB_ICONERROR);
                DialogBox(hinst,MAKEINTRESOURCE(IDD_INPUT),0,(DLGPROC)inputproc);
			}
			digit=0;
			p=in;
			if(*p=='-')//p是指向in的指针,处理输入为负数
			{
				p++;
				while(*p)
				{
					if(ISNUMBER(*p))
					{
						digit=10*digit+(*p-'0');
						p++;
					}
					else
					{
						MessageBox(hdlg,"输入有非数字,请重新输入","错误!",MB_ICONERROR);
                        DialogBox(hinst,MAKEINTRESOURCE(IDD_INPUT),0,(DLGPROC)inputproc);
					}
				}
				digit=-digit;
			}
			else//处理输入为正整数
			{
				while(*p)
				{
					if(ISNUMBER(*p))
					{
						digit=10*digit+(*p-'0');
						p++;
					}
					else
					{
						MessageBox(hdlg,"输入有非数字或未输入,请重新输入","错误!",MB_ICONERROR);
                        DialogBox(hinst,MAKEINTRESOURCE(IDD_INPUT),0,(DLGPROC)inputproc);
					}
				}

			}
			
			s[++sp]=digit;
			break;	 
			}
		}
		ip++; //得到下条指令 
	}while(ip);
	printf("\nProgram terminated!\nPress ENTER to return...");
	getchar();
	return 0;
				}
			break;
		case ID_OPEN:
			if(!GetOpenFileName(&ofn)) break;
			str[512]=0;				//防止溢出
			if(!(fp=fopen(ofn.lpstrFile,"rb")))
				MessageBox(hdlg,str,"无法打开文件!",MB_ICONERROR);

⌨️ 快捷键说明

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