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

📄 compiler.cpp

📁 一个非常好的词法分析程序,加上语法的分析是一个难得一见的好实例
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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 + -