📄 pl0dlg.cpp
字号:
// 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 + -