📄 compiler.cpp
字号:
// Compiler.cpp: implementation of the CCompiler class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Compiler.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define LEN_KEYWORDTAB 15//关键字表长
#define LEN_OPRSYMTAB 11//运算符表长
#define LEN_BNDSYMTAB 4 //界符表长
//关键字表
const char tabKeyWord[LEN_KEYWORDTAB][10]=
{
"program",
"const",
"var",
"procedure",
"begin",
"end",
"if",
"then",
"else",
"while",
"do",
"call",
"read",
"write",
"odd",
};
//运算符表
const char tabOprSym[LEN_OPRSYMTAB][3]=
{
"+",
"-",
"*",
"/",
"=",
"<",
">",
"<>",
"<=",
">=",
":=",
};
//界符表
const char tabBndSym[LEN_BNDSYMTAB][2]=
{
";",
",",
"(",
")",
};
CCompiler::CCompiler()
{
}
CCompiler::~CCompiler()
{
//下面这段释放内存的代码不知道为什么出错
// for(int i=0;i<m_iVecotrSymbolSize;i++)
// delete m_vectorSymbol[i].szStr;
}
bool CCompiler::LexAnalysis(char *szStr)
{
SYNTAXERR seTemp;
if(!strcmp(szStr,""))
{
seTemp.iSyntaxErrCode=SE_FE_NOCODE;
m_vectorSyntaxErr.push_back(seTemp);
return 0;
}
int nLen;
char *szTemp;
LEXPROPERTYVS lpvTemp;
char *szStrBU=szStr;
strlwr(szStr);//小写字符串
while(*szStr!='\0')
{
szStr=JumpNoMatterChar(szStr);
if(*szStr=='\0')
break;
nLen=0;
if(isalpha(*szStr))
{
lpvTemp.nStrPos=szStr-szStrBU;
while(isalpha(*szStr) || isdigit(*szStr))
{
nLen++;
szStr++;
}
szTemp=new char[nLen];
memcpy(szTemp,szStr-nLen,nLen);
szTemp[nLen]='\0';
lpvTemp.nStrLen=nLen;
if(IsKeyWord(szTemp))
lpvTemp.lpProperty=KeyWord;//该字符串为关键字
else
lpvTemp.lpProperty=Id; //该字符串可能为变量,过程名,常量
lpvTemp.szStr=szTemp;
m_vectorSymbol.push_back(lpvTemp);
}
else
{
if(isdigit(*szStr))
{
lpvTemp.nStrPos=szStr-szStrBU;
while(isdigit(*szStr))
{
nLen++;
szStr++;
}
szTemp=new char[nLen];
memcpy(szTemp,szStr-nLen,nLen);
szTemp[nLen]='\0';
lpvTemp.nStrLen=nLen;
lpvTemp.lpProperty=Const;
lpvTemp.szStr=szTemp;
m_vectorSymbol.push_back(lpvTemp);
}
else
{
lpvTemp.nStrPos=szStr-szStrBU;
szTemp=new char[2];
if(!isalpha(*szStr) && !isdigit(*szStr) && *szStr!='\r' && *szStr!='\n' && *szStr!='\0' && *szStr!=' ' && *szStr!=9)
{
szTemp[0]=*szStr;
szStr++;
}
switch(szTemp[0])
{
case '<':
if(*szStr=='=' || *szStr=='>')
{
szTemp[1]='=';
szTemp[2]='\0';
lpvTemp.lpProperty=OprSym;
lpvTemp.nStrLen=2;
szStr++;
}
else
{
szTemp[1]='\0';
lpvTemp.lpProperty=OprSym;
lpvTemp.nStrLen=1;
}
break;
case '>':
if(*szStr=='=')
{
szTemp[1]='=';
szTemp[2]='\0';
lpvTemp.lpProperty=OprSym;
lpvTemp.nStrLen=2;
szStr++;
}
else
{
szTemp[1]='\0';
lpvTemp.lpProperty=OprSym;
lpvTemp.nStrLen=1;
}
break;
case ':':
if(*szStr=='=')
{
szTemp[1]='=';
szTemp[2]='\0';
lpvTemp.lpProperty=OprSym;
lpvTemp.nStrLen=2;
szStr++;
}
else
{
szTemp[1]='\0';
lpvTemp.lpProperty=IllegalChar;
lpvTemp.nStrLen=1;
seTemp.iSyntaxErrCode=SE_ILLEGALCHAR;
m_vectorSyntaxErr.push_back(seTemp);
}
break;
default:
szTemp[1]='\0';
if(IsOprSym(szTemp))
{
lpvTemp.nStrLen=1;
lpvTemp.lpProperty=OprSym;
}
else
{
if(IsBndSym(szTemp))
{
lpvTemp.nStrLen=1;
lpvTemp.lpProperty=BndSym;
}
else//有错误产生
{
lpvTemp.nStrLen=1;
lpvTemp.lpProperty=IllegalChar;
seTemp.iSyntaxErrCode=SE_ILLEGALCHAR;
m_vectorSyntaxErr.push_back(seTemp);
}
}
break;
}
lpvTemp.szStr=szTemp;
m_vectorSymbol.push_back(lpvTemp);
}
}
}
return 1;
}
bool CCompiler::IsKeyWord(char *szStr)
{
for(int i=0;i<LEN_KEYWORDTAB;i++)
{
if(!strcmp(szStr,tabKeyWord[i]))
return 1;
}
return 0;
}
bool CCompiler::IsBndSym(char *szStr)
{
for(int i=0;i<LEN_BNDSYMTAB;i++)
{
if(!strcmp(szStr,tabBndSym[i]))
return 1;
}
return 0;
}
bool CCompiler::IsOprSym(char *szStr)
{
for(int i=0;i<LEN_OPRSYMTAB;i++)
{
if(!strcmp(szStr,tabOprSym[i]))
return 1;
}
return 0;
}
bool CCompiler::IsInSymbolTab(char *szStr)
{
for(int i=0;i<m_iVecotrSymbolSize;i++)
{
if(!strcmp(m_vectorSymbol[i].szStr,szStr))
return 1;
}
return 0;
}
void CCompiler::SyntaxAnalysis()
{
SyntaxAnalysis_Prog();
}
void CCompiler::Compile(char *szFile)
{
char *szStr;
int nLength;
CFile file(szFile,0);
CString str;
CString strLeft,strRight;
int nPos;
m_iCurPointer=0; //复位符号表指针
m_vectorSyntaxErr.clear();//清空语法错误向量
m_vectorSymbol.clear(); //清空符号表向量
nLength=file.GetLength();
szStr=new char[nLength];
file.Read(szStr,nLength);
szStr[nLength]='\0';
if(!LexAnalysis(szStr))//词法分析
return;
//-----------输出符号表-----------
str.Format("%s",szFile);
nPos=str.ReverseFind('\\');
strLeft=str.Left(nPos+1);
strRight=str.Right(str.GetLength()-nPos-1);
if(strRight.Right(4)==".pas")
str=strLeft+strRight.Left(strRight.GetLength()-4)+"_LexAnanlysisResult.dat";
else
str=strLeft+strRight+"_LexAnanlysisResult.dat";
OutSymbolTab((LPSTR)(LPCSTR)str);
//--------------------------------
m_iVecotrSymbolSize=m_vectorSymbol.size();
SyntaxAnalysis();//语法分析
}
void CCompiler::SyntaxAnalysis_Prog()
{
SYNTAXERR seTemp;
if(strcmp("program",m_vectorSymbol[m_iCurPointer++].szStr))//语法出错:程序必须以Program开头
{
seTemp.iSyntaxErrCode=SE_PROGHEAD;
m_vectorSyntaxErr.push_back(seTemp);
}
if(m_iVecotrSymbolSize==m_iCurPointer)//语法出错:遇到意外的文件结束:Program后应有程序名,分号和程序块
{
seTemp.iSyntaxErrCode=SE_FE_PROGNEEDIDSYMBLOCK;
m_vectorSyntaxErr.push_back(seTemp);
return;
}
switch(SyntaxAnalysis_Id())
{
case ID_FIRSTERR:
seTemp.iSyntaxErrCode=SE_ID_PROGNAMEFIRST;//语法出错:定义程序名的变量名的第一个字符必须为字母
m_vectorSyntaxErr.push_back(seTemp);
break;
case ID_MIDERR:
seTemp.iSyntaxErrCode=SE_ID_PROGNAMEMID;//语法出错:定义程序名的变量名的中间字符或为字母
m_vectorSyntaxErr.push_back(seTemp);
break;
}
if(m_iVecotrSymbolSize==m_iCurPointer)//语法出错:遇到意外的文件结束:程序名后必须有分号和程序块
{
seTemp.iSyntaxErrCode=SE_FE_NEEDSYMBLOCK;
m_vectorSyntaxErr.push_back(seTemp);
return;
}
if(strcmp(";",m_vectorSymbol[m_iCurPointer++].szStr))//语法出错:定义程序名的变量名后必须以分号结束
{
seTemp.iSyntaxErrCode=SE_PROGTAIL;
m_vectorSyntaxErr.push_back(seTemp);
}
if(m_iVecotrSymbolSize==m_iCurPointer)//语法出错:遇到意外的文件结束:程序必须有程序块
{
seTemp.iSyntaxErrCode=SE_FE_NEEDBLOCK;
m_vectorSyntaxErr.push_back(seTemp);
return;
}
SyntaxAnalysis_Block();
if(m_iVecotrSymbolSize>m_iCurPointer)//语法出错:多余的文件尾-程序以程序块结束,程序块后面不应再有程序
{
seTemp.iSyntaxErrCode=SE_UNWANTEDTAIL;
m_vectorSyntaxErr.push_back(seTemp);
}
}
int CCompiler::SyntaxAnalysis_Id()
{
int iSize=strlen(m_vectorSymbol[m_iCurPointer].szStr);
if(!isalpha(m_vectorSymbol[m_iCurPointer].szStr[0]))
{
m_iCurPointer++;
return ID_FIRSTERR;
}
for(int i=1;i<iSize;i++)
{
if(!isalpha(m_vectorSymbol[m_iCurPointer].szStr[i]) && !isdigit(m_vectorSymbol[m_iCurPointer].szStr[i]))//语法出错
{
m_iCurPointer++;
return ID_MIDERR;
}
}
m_iCurPointer++;
return -1;
}
int CCompiler::SyntaxAnalysis_Block()
{
SYNTAXERR seTemp;
if(SyntaxAnalysis_Condecl()==FILEEND)
{
seTemp.iSyntaxErrCode=SE_FE_NEEDBODY;
m_vectorSyntaxErr.push_back(seTemp);
return FILEEND;
}
if(m_iVecotrSymbolSize==m_iCurPointer)//语法出错:遇到意外的文件结束:程序必须有程序体
{
seTemp.iSyntaxErrCode=SE_FE_NEEDBODY;
m_vectorSyntaxErr.push_back(seTemp);
return FILEEND;
}
if(SyntaxAnalysis_Vardecl()==FILEEND)
{
seTemp.iSyntaxErrCode=SE_FE_NEEDBODY;
m_vectorSyntaxErr.push_back(seTemp);
return FILEEND;
}
if(m_iVecotrSymbolSize==m_iCurPointer)//语法出错:遇到意外的文件结束:程序必须有程序体
{
seTemp.iSyntaxErrCode=SE_FE_NEEDBODY;
m_vectorSyntaxErr.push_back(seTemp);
return FILEEND;
}
if(SyntaxAnalysis_Proc()==FILEEND)
{
seTemp.iSyntaxErrCode=SE_FE_NEEDBODY;
m_vectorSyntaxErr.push_back(seTemp);
return FILEEND;
}
if(m_iVecotrSymbolSize==m_iCurPointer)//语法出错:遇到意外的文件结束:程序必须有程序体
{
seTemp.iSyntaxErrCode=SE_FE_NEEDBODY;
m_vectorSyntaxErr.push_back(seTemp);
return FILEEND;
}
return SyntaxAnalysis_Body();
}
int CCompiler::SyntaxAnalysis_Condecl()
{
SYNTAXERR seTemp;
if(strcmp("const",m_vectorSymbol[m_iCurPointer++].szStr))//语法出错:定义常量时必须以关键字Const开头
{
m_iCurPointer--;
return 0;//不像是常量定义,返回
}
if(m_iVecotrSymbolSize==m_iCurPointer)//语法出错:遇到意外的文件结束:关键字Const后面必须有变量名
{
seTemp.iSyntaxErrCode=SE_FE_CONSTEND;
m_vectorSyntaxErr.push_back(seTemp);
return FILEEND;//应该是常量定义
}
if(SyntaxAnalysis_Const()==FILEEND)
return FILEEND;
if(m_iVecotrSymbolSize==m_iCurPointer)
return 1;
while(!strcmp(",",m_vectorSymbol[m_iCurPointer].szStr))
{
m_iCurPointer++;
if(m_iVecotrSymbolSize==m_iCurPointer)//语法出错:遇到意外的文件结束:定义常量时,“,”后面应该有变量
{
seTemp.iSyntaxErrCode=SE_FE_CONSTSYMEND;
m_vectorSyntaxErr.push_back(seTemp);
return FILEEND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -