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

📄 cppparser.cpp

📁 这是一个能够自动生成文档的程序
💻 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 + -