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

📄 pl0dlg.cpp

📁 C++扩展pl0编译
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// PL0Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "PL0.h"
#include "PL0Dlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define stacksize 500            /*解释执行时使用的栈*/
# define maxerr 49               /*错误类型数量*/
char in[16];                     /*暂存用对话框输入的数值*/
char *pi=in;                     /*定义一个指针*/
int digit;                       /*输入的数字*/
const char* const errtxt[maxerr]=		//错误提示信息
{
	"标识符太长",                           //0
		"常数说明中的\'=\'写成了\':=\'",	//1
		"常数说明中的\'=\'后应是数字",	    //2
		"常数说明中的标识符后应是\'=\'",	//3
		"const声明后缺少标识符",            //4
		"漏掉了\',\'或\';\'",               //5
		"过程说明后的符号不正确。",         //6
		"应是语句开始符",                   //7
		"标识符的后跟符不正确",             //8
		"程序结尾丢了\'.\'或结尾不正常",    //9
		"语句之间漏了\';\'或\'end\'",       //10
		"标识符未说明",	                    //11
		"需赋值的标识符属性应是变量",       //12
		"赋值语句左部标识符后应是\':=\'",   //13
		"call后应为标识符",				    //14
		"call后标识符属性应是过程",		    //15
		"if条件语句中缺少\'then\'",         //16
		"repeat语句中缺少until",            //17
		"while语句中缺少\'do\'",            //18
		"语句后的符号不正确",               //19
		"应为关系运算符",				    //20
		"表达式内标识符属性不能是过程",	    //21
		"for语句中缺少\'to\'或\'downto\'",  //22
		"因子后的非法符号",                 //23
		"表达式开始符不能是此符号",	        //24
		"read语句中的标识符不是变量",	    //25
		"表达式中缺少标识符",			    //26
		"数组越界",						    //27
		"数组表达中缺少\'[\'",				//28
		"for语句中缺少\'step\'或\'do\'",    //29
		"过程嵌套层次太多",	                //30
		"数越界",                           //31
		"标识符表格溢出",				    //32
		"目标代码过长",			            //33
		"read语句缺少左括号\'(\'",	        //34
		"read语句缺少右括号\')\'",	        //35
		"数组中的下标表示不正确",			//36
		"case语句中缺少了\'of\'",           //37
		"数组表达中缺少\']\'",              //38
		"var声明后缺少标识符",              //39
		"procedure声明后缺少标识符",        //40
		"漏掉了\';\'",                      //41
		"赋值语句中的'':=\'写成了\'=\'",    //42
		"write语句缺少左括号\'(\'",	        //43
		"write语句缺少右括号\')\'",	        //44
		"call后漏掉了标识符",               //45
		"for语句中缺少\'do\'",              //46
		"表达式缺少右括号\')\'",            //47
		"++或--的后跟符号不正确",           //48
};

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPL0Dlg dialog

CPL0Dlg::CPL0Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPL0Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPL0Dlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
}

void CPL0Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPL0Dlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPL0Dlg, CDialog)
	//{{AFX_MSG_MAP(CPL0Dlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_OPEN, OnOpen)
	ON_BN_CLICKED(IDC_SAVE, OnSave)
	ON_BN_CLICKED(IDC_COMPILE, OnCompile)
	ON_BN_CLICKED(IDC_RUN, OnRun)
	ON_BN_CLICKED(IDC_NEW, OnNew)
	ON_BN_CLICKED(IDC_ABOUT, OnAbout)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPL0Dlg message handlers

BOOL CPL0Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	buf[65535]=0;	//结尾清0防止溢出
	bufOut[2047]=0;
	str[0]=0;		//Clear str[]
	//填充OPENFILENAME结构体
	memset(&ofn,0,sizeof(OPENFILENAME));	//Clear it First
	ofn.lStructSize=sizeof(OPENFILENAME);
	ofn.lpstrFilter="Test File(*.txt)\0*.txt\0All File(*.*)\0*.*\0\0";
	ofn.nMaxFile=511;		//最大文件名缓冲区长度
	ofn.lpstrFile=str;		//使用临时字符串
	ofn.Flags=OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
	ofn.lpstrTitle="PL/0文件";
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CPL0Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CPL0Dlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPL0Dlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CPL0Dlg::OnOpen() 
{
	// TODO: Add your control notification handler code here
	int i;
	if(GetOpenFileName(&ofn))
	{
		if(!(fp=fopen(ofn.lpstrFile,"rb")))
			MessageBox(str,"无法打开文件!",MB_ICONERROR);
		else
		{
			fseek(fp,0,SEEK_END);
			if((i=ftell(fp))>65535)
				MessageBox("文件过长(>=64K)!","错误",MB_ICONERROR);
			else
			{
				fseek(fp,0,SEEK_SET);
				fread(buf,1,i,fp);
				buf[i]=0;			//防止溢出
				SetDlgItemText(IDC_INPUT,buf);
			}
			fclose(fp);
		}
	}
	buf[0]=0;
	cx=0;
	err=0;

}

void CPL0Dlg::OnSave() 
{
	// TODO: Add your control notification handler code here
	if(GetSaveFileName(&ofn))
	{
		str[512]=0;	
		if(!(fp=fopen(ofn.lpstrFile,"wb")))
			MessageBox(str,"无法创建文件!",MB_ICONERROR);
		else
		{
			GetDlgItemText(IDC_INPUT,buf,65535);
			fprintf(fp,"%s",buf);
		}
		fclose(fp);
	}
	
}

void CPL0Dlg::OnCompile() 
{
	// TODO: Add your control notification handler code here
	int len;
	memset(buf,0,65535);
	GetDlgItemText(IDC_INPUT,buf,55535);
	if(buf[0]==0)
	{
		MessageBox("请先输入源程序!");
	}
	else
	{
		sprintf(bufOut,"");       /*清空结果*/
		compile();                /*执行编译程序*/
		fa=fopen("fa","rb");
		fseek(fa,0,SEEK_END);
		len=ftell(fa);
		fseek(fa,0,SEEK_SET);
		fread(buf,1,len,fa);
		buf[len]=0;		    	//防止溢出
		SetDlgItemText(IDC_RESULT,buf);   /*输出目标代码*/
		fclose(fa);

		fas=fopen("fas","rb");
		fseek(fas,0,SEEK_END);
		len=ftell(fa);
		fseek(fas,0,SEEK_SET);
		fread(buf,1,len,fas);
		buf[len]=0;			   //防止溢出
		SetDlgItemText(IDC_NAMETABLE,buf);   /*输出名字表*/
		fclose(fas);

		SetDlgItemText(IDC_OUTPUT,bufOut);   /*输出编译结果*/
	}
	
}

void CPL0Dlg::OnRun() 
{
	// TODO: Add your control notification handler code here
	if(cx<1)
	{
		MessageBox("请先编译再运行!");
		return;
	}
	if(err)
	{
		MessageBox("请先改正错误后再运行!");
		return;
	}
	interpret();        /*执行解释程序*/
}

void CPL0Dlg::OnNew() 
{
	// TODO: Add your control notification handler code here
	memset(buf,0,sizeof(buf));     /*清空文本框*/
	SetDlgItemText(IDC_INPUT,buf);
	cx=0;
	err=0;
}
/*编译开始*/
int CPL0Dlg::compile()
{
	bool nxtlev[symnum];
	int j;
	init();                                          /*初始化*/
	err=0;
	cc=cx=0;
	line=1;
	ifi=elsei=0;
	ch=' ';
	if(-1!=getsym())
	{
		fa=fopen("fa","w");
		fprintf(fa,"目标代码:\n");
		fas=fopen("fas","w");
		fprintf(fas,"名字表:\n");
		fa1=fopen("fa1","w");

		addset(nxtlev,declbegsys,statbegsys,symnum);
		nxtlev[period]=true;    
		if(-1==block(0,0,nxtlev))			/*调用编译程序*/
		{
			return 0;
		}
		if(sym!=period)
		{
			error(9,line);
		}
		j=strlen(bufOut);
		sprintf(bufOut+j,"\r\n PL0.exe - %d Error(s)\r\n",err);
		listcode(0);                        /*输出代码*/
	}
	fclose(fa);
	fclose(fas);
	fclose(fa1);
	return 0;
}
/*初始化*/
void CPL0Dlg::init()
{
	int i;
	for(i=0;i<=255;i++)
	{
		ssym[i]=nul;
	}
	ssym['[']=lepa;
	ssym[']']=ripa;
	ssym['(']=lparen;
	ssym[')']=rparen;
	ssym['=']=eql;
	ssym[':']=colon;
	ssym[',']=comma;
	ssym['.']=period;
	ssym[';']=semicolon;
	/*设置保留字名字,按照字母顺序,便于折半查找*/
	strcpy(&(word[0][0]),"begin");
	strcpy(&(word[1][0]),"call");
	strcpy(&(word[2][0]),"case");
	strcpy(&(word[3][0]),"const");
	strcpy(&(word[4][0]),"do");
	strcpy(&(word[5][0]),"downto");
	strcpy(&(word[6][0]),"else");
	strcpy(&(word[7][0]),"end");
	strcpy(&(word[8][0]),"for");
	strcpy(&(word[9][0]),"if");
	strcpy(&(word[10][0]),"odd");
	strcpy(&(word[11][0]),"of");
	strcpy(&(word[12][0]),"procedure");
	strcpy(&(word[13][0]),"read");
	strcpy(&(word[14][0]),"repeat");
	strcpy(&(word[15][0]),"return");
	strcpy(&(word[16][0]),"step");
	strcpy(&(word[17][0]),"then");
	strcpy(&(word[18][0]),"to");
	strcpy(&(word[19][0]),"until");
	strcpy(&(word[20][0]),"var");
	strcpy(&(word[21][0]),"while");
	strcpy(&(word[22][0]),"write");
	/*设置保留字符号*/
	wsym[0]=beginsym;
	wsym[1]=callsym;
	wsym[2]=casesym;
	wsym[3]=constsym;
	wsym[4]=dosym;
	wsym[5]=downtosym;
	wsym[6]=elsesym;
	wsym[7]=endsym;
	wsym[8]=forsym;
	wsym[9]=ifsym;
	wsym[10]=oddsym;
	wsym[11]=ofsym;
	wsym[12]=procsym;
	wsym[13]=readsym;
	wsym[14]=repeatsym;
	wsym[15]=returnsym;
	wsym[16]=stepsym;
	wsym[17]=thensym;
	wsym[18]=tosym;
	wsym[19]=untilsym;
	wsym[20]=varsym;
	wsym[21]=whilesym;
	wsym[22]=writesym;

	/*设置指令名称*/
	strcpy(&(mnemonic[lit][0]),"lit");
	strcpy(&(mnemonic[opr][0]),"opr");
	strcpy(&(mnemonic[lod][0]),"lod");
	strcpy(&(mnemonic[sto][0]),"sto");
	strcpy(&(mnemonic[cal][0]),"cal");
	strcpy(&(mnemonic[inte][0]),"int");
	strcpy(&(mnemonic[jmp][0]),"jmp");
	strcpy(&(mnemonic[jpc][0]),"jpc");
	strcpy(&(mnemonic[get][0]),"get");
	strcpy(&(mnemonic[kep][0]),"kep");

	/*设置符号集*/
	for(i=0;i<symnum;i++)
	{
		declbegsys[i]=false;
		statbegsys[i]=false;
		facbegsys[i]=false;
	}

	/*设置声明开始符号集*/
	declbegsys[constsym]=true;
	declbegsys[varsym]=true;
	declbegsys[procsym]=true;
	/*设置语句开始符号集*/
	statbegsys[beginsym]=true;
	statbegsys[callsym]=true;
	statbegsys[ifsym]=true;
	statbegsys[repeatsym]=true;
	statbegsys[forsym]=true;
	statbegsys[whilesym]=true;
	statbegsys[casesym]=true;
	/*设置因子开始符号集*/
	facbegsys[incsym]=true;
	facbegsys[decsym]=true;
	facbegsys[ident]=true;
	facbegsys[number]=true;
	facbegsys[lparen]=true;
}
/*用数组实现集合的集合运算*/
int CPL0Dlg::inset(int e,bool* s)
{
	return s[e];
}
int CPL0Dlg::addset(bool* sr,bool* s1,bool* s2,int n)
{
    int i;
    for(i=0;i<n;i++)
    {
       sr[i]=s1[i]||s2[i];  
    }
    return 0;
}
int CPL0Dlg::subset(bool* sr,bool* s1,bool* s2,int n)
{
    int i;
    for(i=0;i<n;i++)
    {
       sr[i]=s1[i]&&(!s2[i]);
    }
    return 0; 
}
int CPL0Dlg::mulset(bool* sr,bool* s1,bool* s2,int n)
{
    int i;
    for(i=0;i<n;i++)
    {
       sr[i]=s1[i]&&s2[i];  
    } 
    return 0;
}
/*出错处理,打印出错位置和错误编码*/
void CPL0Dlg::error(int n,int errline)
{
	int j;
	err++;
    j=strlen(bufOut);
	sprintf(bufOut+j,"\r\n Line(%d):%s",errline,errtxt[n]);
}
/*
 *  漏掉空格,读取一个字符
 *
 *  每次读一行,存入line缓冲区,line被getsym取空后再读一行
 *
 *  被函数getsym调用
 */
int CPL0Dlg::getch()
{
	ch=buf[cc];
	cc++;
	
	while(ch==13)
	{
		line++;       /*行数加1*/
		ch=buf[cc];   /*如果是回车,则跳过*/
	    cc++;
	}
	return 0;
}
/*词法分析,获取一个符号*/
int CPL0Dlg::getsym()
{
	int i,j,k;
	while(ch==' '||ch==10 || ch==9)
	{
		getchdo;
	}
	if(ch>='a' && ch<='z')
	{ 
		k=0;

⌨️ 快捷键说明

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