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

📄 gcppparser.cpp

📁 一个非常有用的开源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*	Copyright (C) 2006, Mike Gashler	This library is free software; you can redistribute it and/or	modify it under the terms of the GNU Lesser General Public	License as published by the Free Software Foundation; either	version 2.1 of the License, or (at your option) any later version.	see http://www.gnu.org/copyleft/lesser.html*/#include "GCppParser.h"#include <string.h>#include <stdio.h>#ifdef WIN32#include <direct.h>#include <io.h>#else // WIN32#include <unistd.h>#endif // !WIN32#include "GArray.h"#include "GMacros.h"#include "GFile.h"#include "GHashTable.h"#include "GQueue.h"#include <stdlib.h>GCppObject::GCppObject(){	m_szFilename = NULL;	m_nLineNumber = 0;	m_pComment = NULL;}/*virtual*/ GCppObject::~GCppObject(){	delete(m_pComment);}// -------------------------------------------------------------------GCppScope::GCppScope(): GCppObject(){	m_pStringHeap = NULL;	m_pTypes = new GConstStringHashTable(7, true);	m_pVariables = new GConstStringHashTable(7, true);	m_pMethods = new GConstStringHashTable(7, true);	m_eCurrentAccess = PUBLIC;}#define DeleteHashTableContents(pht, typ) \{\	GHashTable htUnique(pht->GetCount() * 2);\	void* pValue;\	void* pTemp;\	GHashTableEnumerator e(pht);\	while(true)\	{\		const char* pKey = e.GetNext(&pValue);\		if(!pKey)\			break;\		if(!htUnique.Get(pValue, &pTemp))\		{\			htUnique.Add(pValue, NULL);\			delete((typ)pValue);\		}\	}\}GCppScope::~GCppScope(){	DeleteHashTableContents(m_pTypes, GCppType*);	delete(m_pTypes);	DeleteHashTableContents(m_pVariables, GCppVariable*);	delete(m_pVariables);	DeleteHashTableContents(m_pMethods, GCppMethod*);	delete(m_pMethods);	delete(m_pStringHeap);}// -------------------------------------------------------------------GCppType::GCppType(const char* szName): GCppScope(){	m_szName = szName;	m_bPrimitive = false;	m_bDeclaredInProjectFile = false;}GCppType::~GCppType(){}// -------------------------------------------------------------------const char* g_pPrimitiveTypes[] ={	"void",	"int",	"bool",	"short",	"long",	"float",	"double",	"char",	"__int64",	"PCONTEXT", // winnt.h	"HGDIOBJ", // wingdi.h	"HPALETTE", // wingdi.h	"HDC", // wingdi.h	"HBITMAP", // wingdi.h	"HBRUSH", // wingdi.h	"HFONT", // wingdi.h	"HPEN", // wingdi.h	"HMENU", // wingdi.h	"HACCEL", // wingdi.h};#define PRIMITIVE_TYPE_COUNT (sizeof(g_pPrimitiveTypes) / sizeof(const char*))// -------------------------------------------------------------------GCppMethod::GCppMethod(GCppType* pReturnType, GCppScope* pScope, const char* szName, GCppAccess eAccess, GCppMethodModifier eModifiers)	: GCppDeclaration(pReturnType, szName, eAccess){	m_eModifiers = eModifiers;	m_pParameters = new GPointerArray(4);	m_pLocals = NULL;	m_pCalls = NULL;	m_pScope = pScope;}GCppMethod::~GCppMethod(){	int n;	int nCount = m_pParameters->GetSize();	for(n = 0; n < nCount; n++)		delete((GCppVariable*)m_pParameters->GetPointer(n));	delete(m_pParameters);	if(m_pLocals)	{		DeleteHashTableContents(m_pLocals, GCppVariable*);		delete(m_pLocals);	}	delete(m_pCalls);}void GCppMethod::AddParameter(GCppVariable* pVar){	m_pParameters->AddPointer(pVar);}int GCppMethod::GetParameterCount(){	return m_pParameters->GetSize();}GCppVariable* GCppMethod::GetParameter(int n){	return (GCppVariable*)m_pParameters->GetPointer(n);}int GCppMethod::GetCallCount(){	return m_pCalls->GetSize();}GCppMethod* GCppMethod::GetCall(int n){	return (GCppMethod*)m_pCalls->GetPointer(n);}// -------------------------------------------------------------------void GCppToken::Reset(GCppFile* pFile, int nStart, int nLength, int nLine, int nCol){	if(pFile)		pFile->AddRef();	if(m_pFile)		m_pFile->Release();	m_pFile = pFile;	m_nStart = nStart;	m_nLength = nLength;	m_nLine = nLine;	m_nCol = nCol;}bool GCppToken::StartsWith(const char* szString){	int n;	for(n = 0; n < m_nLength && szString[n] != '\0'; n++)	{		if(m_pFile->m_pFile[m_nStart + n] != szString[n])			return false;	}	return true;}bool GCppToken::Equals(const char* szString){	int n;	for(n = 0; n < m_nLength; n++)	{		if(m_pFile->m_pFile[m_nStart + n] != szString[n])			return false;	}	if(szString[n] != '\0')		return false;	return true;}// -------------------------------------------------------------------GCppFile::GCppFile(char* pFile, const char* szOldDir, bool bProjectFile, const char* szFilename){	m_nFilePos = 0;	m_nLine = 1;	m_nLineStart = 0;	m_pFile = pFile;	m_nRefs = 0;	m_bProjectFile = bProjectFile;	m_szFilename = szFilename;	m_pPrevDir = new char[strlen(szOldDir) + 1];	strcpy(m_pPrevDir, szOldDir);}// -------------------------------------------------------------------GCppParser::GCppParser(){	m_eMethodModifiers = 0;	m_eVarModifiers = 0;	m_nFileStackPos = 0;	m_nTokenPos = 0;	m_nActiveTokens = 0;	m_nIfDefSkips = 0;	m_nErrorCount = 0;	m_nRecoveries = 0;	m_pIncludePaths = new GPointerArray(8);	m_pStringHeap = new GStringHeap(1024);	m_pDefines = new GConstStringHashTable(31, true);	m_pGlobalScope = new GCppScope();	m_pScopeStack[0] = m_pGlobalScope;	m_nScopeStackPointer = 1;	m_bRetainComments = false;	m_pComment = NULL;	// Add primitive types to the global scope	int n;	for(n = 0; n < (int)PRIMITIVE_TYPE_COUNT; n++)	{		GCppClass* pPrimitive = new GCppClass(g_pPrimitiveTypes[n]);		pPrimitive->m_bPrimitive = true;		m_pGlobalScope->m_pTypes->Add(g_pPrimitiveTypes[n], pPrimitive);	}}GCppParser::~GCppParser(){	delete(m_pIncludePaths);	delete(m_pDefines);	delete(m_pStringHeap);	delete(m_pGlobalScope);	delete(m_pComment);}void GCppParser::AddIncludePath(const char* szPath){	char* pPath = m_pStringHeap->Add(szPath);	m_pIncludePaths->AddPointer(pPath);}void GCppParser::AddDefine(const char* szDefine, const char* szValue){	GAssert(szDefine, "invalid parameter");	char* pDefine = m_pStringHeap->Add(szDefine);	char* pValue = NULL;	if(szValue)		pValue = m_pStringHeap->Add(szValue);	m_pDefines->Add(pDefine, pValue);}char* LoadFileToBuffer(const char* szFilename){	FILE* pFile = fopen(szFilename, "rb");	if(!pFile)		return NULL;	int nFileSize = filelength(fileno(pFile));	ArrayHolder<char*> hBuffer(new char[nFileSize + 1]);	if(!hBuffer.Get())	{		fclose(pFile);		return NULL;	}	int nBytesRead = fread(hBuffer.Get(), sizeof(char), nFileSize, pFile);	int err = ferror(pFile);	if(err != 0 || nBytesRead != nFileSize)	{		fclose(pFile);		return NULL;	}	hBuffer.Get()[nFileSize] = '\0';	fclose(pFile);	return hBuffer.Drop();}GCppScope* GCppParser::ParseCppFile(const char* szFilename){	// Parse the file	if(!PushFile(szFilename, true))		return NULL;	while(true)	{		GCppToken* pTok = GetToken(0);		if(pTok->GetLength() <= 0)			break;		ParseScope();	}	// Flush all the tokens to make sure they aren't holding on to any files	int n;	for(n = 0; n < MAX_LOOK_AHEAD; n++)		Advance();	// Return the global scope	GCppScope* pScope = m_pGlobalScope;	m_pGlobalScope = NULL;	pScope->m_pStringHeap = m_pStringHeap;	m_pStringHeap = NULL;	return pScope;}bool GCppParser::OnError(GCppToken* pTok, const char* szMessage){	m_nErrorCount++;	//GAssert(!GetCurrentFile()->IsProjectFile(), "break");	return false;}bool GCppParser::ParseScope(){	int n = m_nScopeStackPointer;	while(m_nScopeStackPointer >= n)	{		GCppToken* pTok = GetToken(0);		if(pTok->GetLength() <= 0)			break;		if(pTok->m_nLine == 284)		{			do {} while(false);			//GAssert(false, "Break");		}		if(!ParseScopeItem())		{			// Attempt to recover by skipping to the next ';' or '}' or '#"			m_nRecoveries++;			GAssert(m_nRecoveries == m_nErrorCount, "Someone didn't call OnError when an error was found!");			Advance();			int nScopeNests = 0;			while(true)			{				pTok = GetToken(0);				if(pTok->Equals("{"))					nScopeNests++;				else if(pTok->Equals("}"))					nScopeNests--;				if(nScopeNests <= 0)				{					if(pTok->GetLength() <= 0 || pTok->StartsWith("#"))						break;					if(pTok->Equals(";") || pTok->Equals("}"))					{						Advance();						break;					}				}				else if(pTok->GetLength() <= 0)					nScopeNests--;				Advance();			}		}	}	return true;}bool GCppParser::PushFile(const char* szFilename, bool bProjectFile){	// Separate the file and directory	char szDrive[32];	char szDir[256];	char szFile[256];	char szExt[256];	_splitpath(szFilename, szDrive, szDir, szFile, szExt);	char szNewDir[256];	char szNewFile[256];	_makepath(szNewDir, szDrive, szDir, NULL, NULL);	_makepath(szNewFile, NULL, NULL, szFile, szExt);	// Record the old directory and change to the new one	char szOldDir[256];	getcwd(szOldDir, 256);	chdir(szNewDir);	// Load the file	ArrayHolder<char*> hFile(LoadFileToBuffer(szNewFile));	if(!hFile.Get())	{		chdir(szOldDir);		OnError(GetToken(0), "file not found");		return false;	}	const char* szFN = m_pStringHeap->Add(szFilename);	PushBuffer(hFile.Drop(), szOldDir, bProjectFile, szFN);	return true;}// This takes ownership of szBufvoid GCppParser::PushBuffer(char* szBuf, const char* szOldDir, bool bProjectFile, const char* szFilename){	GAssert(m_nFileStackPos < MAX_INCLUDE_NESTING - 10, "deep #include nesting");	if(m_nFileStackPos >= MAX_INCLUDE_NESTING)	{		GAssert(false, "#include nesting too deep");		return;	}	// Push the new file on the stack	m_pFileStack[m_nFileStackPos] = new GCppFile(szBuf, szOldDir, bProjectFile, szFilename);	m_pFileStack[m_nFileStackPos]->AddRef();	m_nFileStackPos++;}bool GCppParser::PopFile(){	GAssert(m_nFileStackPos > 0, "Nothing to pop");	m_nFileStackPos--;	chdir(m_pFileStack[m_nFileStackPos]->GetOldDir());	m_pFileStack[m_nFileStackPos]->Release();	if(m_nFileStackPos <= 0)		return false; // indicates that the file stack is now empty	return true;}void GCppParser::PushScope(GCppScope* pNewScope){	GAssert(m_nScopeStackPointer < MAX_SCOPE_NESTING, "nesting that deep not supported");	m_pScopeStack[m_nScopeStackPointer] = pNewScope;	m_nScopeStackPointer++;	m_eMethodModifiers = 0;	m_eVarModifiers = 0;}bool GCppParser::PopScope(){	if(m_nScopeStackPointer <= 0)		return OnError(GetToken(0), "\"}\" without matching \"{\"");	m_nScopeStackPointer--;	m_eMethodModifiers = 0;	m_eVarModifiers = 0;	return true;}GCppToken* GCppParser::GetToken(int n){	GAssert(n < MAX_LOOK_AHEAD, "can't look that far ahead");	while(n >= m_nActiveTokens)		GetNextToken();	int nPos = m_nTokenPos + n;	if(nPos >= MAX_LOOK_AHEAD)		nPos -= MAX_LOOK_AHEAD;	return &m_tokens[nPos];}void GCppParser::Advance(){	if(m_nActiveTokens == 0)		GetNextToken();	m_nTokenPos++;	if(m_nTokenPos >= MAX_LOOK_AHEAD)		m_nTokenPos = 0;	m_nActiveTokens--;}void GCppParser::GetNextToken(){	GAssert(m_nActiveTokens < MAX_LOOK_AHEAD, "got all the tokens we can hold");	if(m_nFileStackPos <= 0)	{		int nNextToken = m_nTokenPos + m_nActiveTokens;		if(nNextToken >= MAX_LOOK_AHEAD)			nNextToken -= MAX_LOOK_AHEAD;		m_tokens[nNextToken].Reset(NULL, 0, 0, 0, 0);		m_nActiveTokens++;		return;	}		int nStart, nLength, nLine, nCol;	nLength = 0;	while(true)	{		FindNextToken(&nStart, &nLength, &nLine, &nCol);		// Check for macros		GCppFile* pFile = GetCurrentFile();		GAssert(pFile, "FindNextToken shouldn't pop files");		// If we hit the end of the file, see if there's still one on the stack		if(nLength <= 0)		{			if(PopFile())				continue;			else				pFile = NULL;		}		// Set the token value		int nNextToken = m_nTokenPos + m_nActiveTokens;		if(nNextToken >= MAX_LOOK_AHEAD)			nNextToken -= MAX_LOOK_AHEAD;		m_tokens[nNextToken].Reset(pFile, nStart, nLength, nLine, nCol);		m_nActiveTokens++;		// Do any necessary macro substitutions		const char* szMacro;		if(pFile && GetMacro(&pFile->m_pFile[nStart], nLength, &szMacro))		{			if(!ParseMacro(szMacro))				m_nRecoveries++;			continue;		}		// It's just a normal token, so we're done		break;	}}void GCppParser::OnNewLine(int nPos){	GCppFile* pFile = GetCurrentFile();	pFile->m_nLine++;	pFile->m_nLineStart = nPos + 1;}void GCppParser::FindNextToken(int* pnStart, int* pnLength, int* pnLine, int* pnCol){	// Find the start of the token	GAssert(m_nFileStackPos > 0, "No files on stack");	GCppFile* pCppFile = GetCurrentFile();	const char* pFile = pCppFile->m_pFile;	int nPos = pCppFile->m_nFilePos;	// Skip whitespace and comments, and process compiler directives	while(pFile[nPos] != '\0')

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -