📄 cppparser.cpp
字号:
#include "stdafx.h"
#include "CppParser.h"
#include "Enum.h"
#include "Scope.h"
#include "Type.h"
#include "Symbols.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CCppParser::CCppParser()
{
mSkip = FALSE;
mSkipCount = 0;
}
CCppParser::~CCppParser()
{
ClearContent();
}
BOOL CCppParser::ParseFile(LPCTSTR iPathName)
{
CPage* pPage = gPages.AddPage(iPathName);
if(pPage == NULL)
return FALSE;
mSkip = FALSE;
mSkipCount = 0;
gpCurrPage = pPage;
ParsePage(pPage);
gpCurrPage = NULL;
return TRUE;
}
BOOL CCppParser::ParsePage(CPage* ipPage)
{
char* pCode = NULL;
//映射文件内存到pCode;
HANDLE hFile = ::CreateFile(ipPage->GetPathName(), GENERIC_READ, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return FALSE;
int fileSize = ::GetFileSize(hFile, NULL);
HANDLE hMapFile = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if(hMapFile == NULL)
{
::CloseHandle(hFile);
return FALSE;
}
LPVOID pViewOfFile = ::MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if(pViewOfFile == NULL)
{
::CloseHandle(hFile);
::CloseHandle(hMapFile);
return FALSE;
}
pCode = (char*)pViewOfFile;
TEST_TRACE(pCode);
TEST_TRACE(strlen(pCode));
ParseCode(pCode);
::UnmapViewOfFile(pViewOfFile);
::CloseHandle(hMapFile);
::CloseHandle(hFile);
return TRUE;
}
NOTEST
void CCppParser::ClearContent()
{
POSITION pos = NULL;
}
BOOL CCppParser::ParseCode(char* ipCode)
{
CList<CToken*, CToken*> list;
ReadTokenList(list, ipCode);
Preprocessor(list);
CTokenReader::DeleteInvalidToken(list);
POSITION pos = list.GetHeadPosition();
CToken* pToken = NULL;
while(pos != NULL)
{
POSITION currPos = pos;
pToken = list.GetNext(pos);
if(pToken->IsType(TT_WORD))
ParseWord(list, pos, currPos, pToken->GetContent());
else if(pToken->IsType(TT_RSQUARE))
gScope.ExitScope();
}
//删除临时Token
ClearTokenList(list);
return TRUE;
}
BOOL CCppParser::Preprocessor(CTokenList& ioList)
{
try
{
POSITION pos = ioList.GetHeadPosition();
while(pos != NULL)
{
POSITION currPos = pos;
CToken* pToken = ioList.GetNext(pos);
UINT type = pToken->GetType();
if(IsSkip())
{
if(type != TT_PREPROCESSOR)
continue;
}
if(type == TT_PREPROCESSOR) // #开始的代码
{
ParsePreprocessor(ioList, pos);
POSITION tempPos = currPos;
while(TRUE)
{
POSITION deletePos = tempPos;
CToken* pTemp = ioList.GetNext(tempPos);
delete pTemp;
ioList.RemoveAt(deletePos);
if(tempPos == pos)
break;
}
}
else if(type == TT_WORD) // 宏展开
{
CIdenItem* pIden = gIdens.UnwindMacro(pToken->GetContent(), gpCurrPage, ioList, pos);
//展开间接宏
while(pIden != NULL && pIden->type == ID_MACRO && pos != NULL)
{
pToken = ioList.GetNext(pos);
pIden = gIdens.UnwindMacro(pToken->GetContent(), gpCurrPage, ioList, pos);
}
}
else if(type == TT_EOL)
{
ioList.RemoveAt(currPos);
delete pToken;
pToken = NULL;
}
}
}
catch(CCodeException& e)
{
CString msg;
msg.Format("%s\n %d行 %d列", e.GetPathName(), e.GetLine(),
e.GetColumn());
::AfxMessageBox(msg);
}
/*输出预处理结果
CString newCode;
POSITION newPos = ioList.GetHeadPosition();
CTokenReader::TokenListToString(newCode, ioList, newPos);
CStdioFile file;
CString path;
if(gpCurrPage != NULL)
path = gpCurrPage->GetPathName();
path += "2";
file.Open(path, CFile::modeCreate | CFile::modeWrite);
file.WriteString(newCode);
*/
return TRUE;
}
void CCppParser::ReadTokenList(CTokenList& oList, LPCTSTR ipCode)
{
CTokenReader reader;
reader.SetCode(ipCode);
while(TRUE)
{
CToken* pToken = reader.NextToken();
if(pToken == NULL) break;
TEST_TRACE(pToken);
if(pToken->GetType() == TT_SINCOMMENT || pToken->GetType() == TT_MULCOMMENT)
{
gpCurrPage->AddComment(pToken); //由gpCurrPage删除
//delete pToken;
}
else
{
if(pToken->IsFormalToken() && gpCurrPage != NULL)
gpCurrPage->AddDividing(pToken->GetLine());
oList.AddTail(pToken);
}
}
}
void CCppParser::ClearTokenList(CTokenList& iList)
{
CTokenReader reader;
reader.ClearTokenList(iList);
}
BOOL CCppParser::ParsePreprocessor(CTokenList& ioList, POSITION& ioPos)
{
CToken* pToken = NULL;
while(ioPos != NULL)
{
NEXT_TOKEN_OR_BREAK();
//if(pToken->GetType() != TT_WORD)
// TOKEN_EXCEPTION();
KEYWORD key = gIdens.QueryKeyword(pToken->GetContent());
if(IsSkip())
{
switch(key)
{
//编译开关
case KEY_IF: //#if !defined #if defined
SetSkipCount(1);
goto THEEND;
case KEY_ELIF: //#elif !defined #elif defined
case KEY_ELSEIF: //#elseif !defined #elseif defined
//else
// SetSkipCount(1); //忽略
goto THEEND;
case KEY_IFDEF: //#ifdef
SetSkipCount(1);
goto THEEND;
case KEY_IFNDEF: //#ifndef
SetSkipCount(1);
goto THEEND;
case KEY_ELSE: //#else
if(GetSkipCount() == 0)
ResetSkip();
goto THEEND;
case KEY_ENDIF: //#endif
if(GetSkipCount() == 0)
SetSkip(FALSE);
else
SetSkipCount(-1);
goto THEEND;
default:
goto THEEND;
}
}
else
{
switch(key)
{
//编译开关
case KEY_IF: //#if !defined #if defined
ParsePreprocessorIf(ioList, ioPos);
goto THEEND;
case KEY_ELIF: //#elif !defined #elif defined
case KEY_ELSEIF: //#elseif !defined #elseif defined
ParsePreprocessorIf(ioList, ioPos);
goto THEEND;
case KEY_IFDEF: //#ifdef
ParsePreprocessorIfdef(ioList, ioPos);
goto THEEND;
case KEY_IFNDEF: //#ifndef
ParsePreprocessorIfdef(ioList, ioPos, TRUE);
goto THEEND;
case KEY_ELSE: //#else
if(GetSkipCount() == 0)
ResetSkip();
goto THEEND;
case KEY_ENDIF: //#endif
if(GetSkipCount() == 0)
SetSkip(FALSE);
else
SetSkipCount(-1);
goto THEEND;
//宏定义与取消宏定义
case KEY_DEFINE:
ParsePreprocessorDefine(ioList, ioPos); //读取定义到行尾
return TRUE;
//goto THEEND;
case KEY_UNDEF:
ParsePreprocessorUndefine(ioList, ioPos);
goto THEEND;
//包含文件
case KEY_INCLUDE:
ParsePreprocessorInclude(ioList, ioPos);
goto THEEND;
//
case KEY_ERROR: //忽略
case KEY_PRAGMA:
//读取本行内容并忽略
goto THEEND;
break;
default:
goto THEEND;
break;
}
}
}
THEEND:
GotoNextLine(ioList, ioPos, pToken);
return TRUE;
}
void CCppParser::ParsePreprocessorIf(CTokenList& ioList, POSITION& ioPos)
{
BOOL not = FALSE; //是否有 !
CToken* pToken;
NEXT_TOKEN_OR_RETURN();
//是否 !
if(pToken->GetType() == TT_LOGIC_NOT)
{
not = TRUE;
NEXT_TOKEN_OR_RETURN();
}
//#if 后面如果不是 defined 或 !defined,直接跳过
KEYWORD key = gIdens.QueryKeyword(pToken->GetContent());
if(key != KEY_DEFINED)
goto THEEND;
NEXT_TOKEN_OR_RETURN();
if(pToken->GetType() == TT_LPARAN) //类似于 if defined(_VUNIT),跳过(
{
NEXT_TOKEN_OR_RETURN();
}
//是否已定义
if(gIdens.IsDefinedMacro(pToken->GetContent(), gpCurrPage)) //已定义
{
if(not) SetSkip();
}
else //未定义
{
if(!not) SetSkip();
}
THEEND:
GotoNextLine(ioList, ioPos, pToken);
}
void CCppParser::ParsePreprocessorIfdef(CTokenList& ioList, POSITION& ioPos, BOOL iNot/*=FALSE*/)
{
ASSERT(ioPos != NULL);
CToken* pToken = ioList.GetNext(ioPos);
if(gIdens.IsDefinedMacro(pToken->GetContent(), gpCurrPage)) //已定义
{
if(iNot) SetSkip();
}
else //未定义
{
if(!iNot) SetSkip();
}
}
void CCppParser::ParsePreprocessorDefine(CTokenList& ioList, POSITION& ioPos)
{
CToken* pToken;
NEXT_TOKEN_OR_RETURN();
//#define 后面只能有标识符
//if(pToken->GetType() != TT_WORD)
// TOKEN_EXCEPTION();
//由mIdens删除
CMacro* pMacro = new CMacro(gpCurrPage);
//宏名称
pMacro->SetName(pToken->GetContent());
pMacro->ParseContent(ioList, ioPos);
gIdens.AddIdentifier(pMacro->GetName(), ID_MACRO, pMacro);
}
void CCppParser::ParsePreprocessorUndefine(CTokenList& ioList, POSITION& ioPos)
{
CToken* pToken;
NEXT_TOKEN_OR_RETURN();
//#undef 后面只能有 标识符
if(pToken->GetType() != TT_WORD)
TOKEN_EXCEPTION();
//标识符不能是关键字
KEYWORD key = gIdens.QueryKeyword(pToken->GetContent());
if(key != KEY_NOT)
TOKEN_EXCEPTION();
gIdens.DeleteIdentifier(pToken->GetContent());
}
void CCppParser::ParsePreprocessorInclude(CTokenList& ioList, POSITION& ioPos)
{
CString fileName;
CToken* pToken;
BOOL beginOfUserDir = TRUE;
NEXT_TOKEN_OR_RETURN();
if(pToken->GetType() == TT_STRING) //#include "FileName.h"
{
fileName = pToken->GetContent();
if(fileName.GetLength() > 2)
{
fileName.Delete(fileName.GetLength()-1);
fileName.Delete(0);
}
}
else if(pToken->GetType() == TT_LT) //#inlcude <fileName.h>
{
beginOfUserDir = FALSE;
while(TRUE)
{
NEXT_TOKEN_OR_BREAK();
if(pToken->GetType() == TT_GT)
break;
fileName += pToken->GetContent();
}
}
//类似于 #include <filename>
if(fileName.Find('.') == -1) fileName += ".h";
CString pathName;
if(gPages.FindCodePage(pathName, fileName, beginOfUserDir))
{
CPage* pPage = gPages.AddPage(pathName);
if(pPage != NULL)
{
TRACE1("%s\n", pathName);
CPage* oldCurrPage = gpCurrPage;
gpCurrPage = pPage;
ParsePage(pPage);
gpCurrPage = oldCurrPage;
if(gpCurrPage != NULL)
{
gpCurrPage->AddIncludePage(pPage);
}
}
}
}
void CCppParser::GotoNextLine(CTokenList& ioList, POSITION& ioPos, CToken* ipCurrToken)
{
if(ipCurrToken != NULL && ipCurrToken->IsType(TT_EOL))
return;
CToken* pToken = NULL;
while(TRUE)
{
NEXT_TOKEN_OR_BREAK();
if(pToken->IsType(TT_EOL))
break;
}
}
void CCppParser::ParseWord(CTokenList& ioList, POSITION& ioPos, POSITION& iCurrPos, LPCTSTR iWord)
{
CIdenItem* pIden = gIdens.Search(iWord);
KEYWORD key = KEY_NOT;
if(pIden != NULL) key = pIden->keyIndex;
switch(key)
{
//定义名字空间
case KEY_NAMESPACE:
ParseNameSpace(ioList, ioPos);
break;
//枚举
case KEY_ENUM:
CType::ParseEnum(ioList, ioPos);
break;
//自定义数据类型
case KEY_STRUCT:
CType::ParseType(ioList, ioPos, TYPE_STRUCT, TRIM_PUBLIC);
break;
case KEY_UNION:
CType::ParseType(ioList, ioPos, TYPE_UNION, TRIM_PUBLIC);
break;
case KEY_CLASS:
CType::ParseType(ioList, ioPos, TYPE_CLASS, TRIM_PRIVATE);
break;
case KEY_INTERFACE:
CType::ParseType(ioList, ioPos, TYPE_INTERFACE, TRIM_PRIVATE);
break;
//别名
case KEY_TYPEDEF:
CType::ParseTypedef(ioList, ioPos);
break;
//模板声明
case KEY_TEMPLATE:
ParseTemplate(ioList, ioPos);
break;
//其他不能根据开头关键字才判别内容的代码
//从currpos开始,即从当前标识符开始
default:
ioPos = iCurrPos;
ParseGlobalFuncOrVar(ioList, ioPos);
break;
}
}
void CCppParser::ParseNameSpace(CTokenList& ioList, POSITION& ioPos)
{
CToken* pToken = NULL;
NEXT_TOKEN_OR_RETURN();
if(pToken->GetType() == TT_LSQUARE) //{, 未命名的名字空间
{
gScope.EnterScope();
}
else
{
if(pToken->GetType() != TT_WORD)
TOKEN_EXCEPTION();
gScope.EnterScope(pToken->GetContent());
NEXT_TOKEN_OR_RETURN();
if(pToken->GetType() != TT_LSQUARE) //{, 这里应该出现{
TOKEN_EXCEPTION();
}
TEST_TRACE(gScope);
}
void CCppParser::ParseGlobalFuncOrVar(CTokenList& ioList, POSITION& ioPos)
{
CTokenList list;
BOOL definition = FALSE;
UINT symType;
if(CIdentifier::BeforeParseUnknowCode(ioList, ioPos, list, symType, definition))
{
if(symType == SYM_VARIABLE)
{
CVariableList varList;
CVariable::ParseVariable(list, TRIM_PUBLIC, varList);
POSITION pos = varList.GetHeadPosition();
while(pos != NULL)
{
CVariable* pVar = varList.GetNext(pos);
ASSERT(pVar != NULL);
//加入符号表时会并定义合并到声明中, 返回FALSE表示被合并,
//合并后该指针已被删除,所以只能在返回TRUE时加入到gSymbols
CString fullName;
pVar->GetFullName(fullName);
if(gIdens.AddIdentifier(fullName, ID_VARIABLE, pVar, NULL))
gSymbols.AddVariable(pVar, gpCurrPage);
}
}
else if(symType == SYM_FUNCTION)
{
CExFunction* pFunc;
if(!definition)
pFunc = CExFunction::ParseFunction(list, TRIM_PUBLIC);
else
pFunc = CExFunction::ParseFunction(list, TRIM_PUBLIC, definition, &ioList, &ioPos);
TEST_TRACE(pFunc);
//加入符号表时会并定义合并到声明中,返回FALSE表示被合并,
//合并后该指针已被删除,所以只能在返回TRUE时加入到gSymbols
CString fullName;
pFunc->GetFullName(fullName);
if(gIdens.AddIdentifier(fullName, ID_FUNCTION, pFunc, NULL))
gSymbols.AddFunction(pFunc, gpCurrPage);
}
else
{
ASSERT(FALSE);
}
}
}
void CCppParser::ParseTemplate(CTokenList& ioList, POSITION& ioPos)
{
ASSERT(ioPos != NULL);
CToken* pToken = ioList.GetAt(ioPos);
if(!pToken->IsType(TT_LT)) // <
return;
while(TRUE)
{
NEXT_TOKEN_OR_BREAK();
if(pToken->IsType(TT_GT)) // >
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -