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

📄 parserthread.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
* This file is part of Code::Blocks Studio, an open-source cross-platform IDE
* Copyright (C) 2003  Yiannis An. Mandravellos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact e-mail: Yiannis An. Mandravellos <mandrav@codeblocks.org>
* Program URL   : http://www.codeblocks.org
*
* $Id: parserthread.cpp,v 1.22.2.1 2005/10/25 07:59:01 mandrav Exp $
* $Date: 2005/10/25 07:59:01 $
*/

#include <sdk.h>
#include "parserthread.h"
#include <wx/app.h>
#include <wx/log.h>
#include <wx/msgdlg.h>
#include <globals.h>

#include <cctype>

int THREAD_START = wxNewId();
int THREAD_END = wxNewId();
int NEW_TOKEN = wxNewId();
int FILE_NEEDS_PARSING = wxNewId();

ParserThread::ParserThread(wxEvtHandler* parent,bool* abortflag,
							const wxString& bufferOrFilename,
							bool isLocal,
							ParserThreadOptions& options,
							TokensArray* tokens)
	: m_pParent(parent),
	m_pTokens(tokens),
	m_pLastParent(0L),
	m_IsLocal(isLocal),
	m_StartBlockIndex(0),
	m_Options(options)
{
//	m_pAbort=abortflag;
	//ctor
	m_Tokens.m_Options.wantPreprocessor = options.wantPreprocessor;

	if (!bufferOrFilename.IsEmpty())
	{
		if (!options.useBuffer)
		{
			m_Filename = bufferOrFilename;
			m_Tokens.Init(m_Filename);
		}
		else
			m_Tokens.InitFromBuffer(bufferOrFilename);
	}
	m_LastScope = tsUndefined;
}

ParserThread::~ParserThread()
{
	//dtor
}

void ParserThread::Log(const wxString& log)
{
	wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, NEW_TOKEN);
	event.SetString(log);
	event.SetInt(m_Tokens.GetLineNumber());
	wxPostEvent(m_pParent, event);
	wxYield();
}

void ParserThread::SetTokens(TokensArray* tokens)
{
    m_pTokens = tokens;
}

void* ParserThread::DoRun()
{
//	wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, THREAD_START);
//    event.SetString(m_Filename);
//	event.SetInt((int)this);
//	wxPostEvent(m_pParent, event);
//
////    Log("ParserThread running for " + m_Filename);
//	Parse();
//
//	wxCommandEvent event1(wxEVT_COMMAND_MENU_SELECTED, THREAD_END);
//	event1.SetString(m_Filename);
//	event1.SetInt((int)this);
//	wxPostEvent(m_pParent, event1);

	return 0L;
}

wxChar ParserThread::SkipToOneOfChars(const wxString& chars, bool supportNesting)
{
	unsigned int level = m_Tokens.GetNestingLevel();
	while (1)
	{
		wxString token = m_Tokens.GetToken();
		if (token.IsEmpty())
			return '\0'; // eof

		if (!supportNesting ||
			(supportNesting && m_Tokens.GetNestingLevel() == level))
		{
			wxChar ch = token.GetChar(0);
			if (chars.Find(ch) != wxNOT_FOUND)
				return ch;
		}
	}
}

void ParserThread::SkipBlock()
{
	// skip tokens until we reach }
	// block nesting is taken into consideration too ;)

	// this is the nesting level we start at
	// we subtract 1 because we 're already inside the block
	// (since we 've read the {)
	unsigned int level = m_Tokens.GetNestingLevel() - 1;
	while (1)
	{
		wxString token = m_Tokens.GetToken();
		if (token.IsEmpty())
			break; // eof

		// if we reach the initial nesting level, we are done
		if (level == m_Tokens.GetNestingLevel())
			break;
	}
}

void ParserThread::SkipAngleBraces()
{
    int nestLvl = 0;
    while (true)
    {
        wxString tmp = m_Tokens.GetToken();
        if (tmp.Matches(_T("<")))
            ++nestLvl;
        else if (tmp.Matches(_T(">")))
            --nestLvl;
        else if (tmp.Matches(_T(";")))
        {
        	// unget token - leave ; on the stack
        	m_Tokens.UngetToken();
            break;
        }
        else if (tmp.IsEmpty())
            break;
        if (nestLvl <= 0)
            break;
    }
}

bool ParserThread::ParseBufferForFunctions(const wxString& buffer)
{
    if (!m_pTokens)
        return false;
	m_pTokens->Clear();
	m_Tokens.InitFromBuffer(buffer);
	if (!m_Tokens.IsOK())
		return false;

	m_Str.Clear();
    m_EncounteredNamespaces.Clear();

	while (1)
	{
        if (!m_pTokens || TestDestroy())
            return false;

		wxString token = m_Tokens.GetToken();
		if (token.IsEmpty())
			break;
#if 0
	if (!m_Str.IsEmpty())
		Log(m_Str);
#endif
#if 0
	if (!token.IsEmpty())
		Log(token);
#endif

		if (token.Matches(_T(";")))
		{
			m_Str.Clear();
		}
		else if (token.Matches(_T("{")))
		{
			SkipBlock();
			m_Str.Clear();
		}
		else if (token.Matches(_T("}")))
		{
			m_Str.Clear();
		}
//		else if (token.Matches("::"))
//		{
//			m_Str.Clear();
//		}
		else if (token.Matches(_T("typedef")) ||
			token.Matches(_T(":")))
		{
			SkipToOneOfChars(_T(";}"), true);
			m_Str.Clear();
		}
		else if (token.Matches(_T("extern")) ||
			token.StartsWith(_T("__asm")))
		{
			SkipToOneOfChars(_T(";"));
			//m_Str.Clear();
		}
		else if (token.Matches(_T("#")))
		{
			m_Tokens.GetToken();
			m_Tokens.GetToken();
			m_Str.Clear();
		}
		else
		{
			wxString peek = m_Tokens.PeekToken();
			if (!peek.IsEmpty())
			{
				if (peek.GetChar(0) == '(')
				{
					// function
					// ignore some well-known wxWindows macros
					if (token.Matches(_T("BEGIN_EVENT_TABLE")))
					{
						// skip till after END_EVENT_TABLE
						while (!token.IsEmpty() && !token.Matches(_T("END_EVENT_TABLE")))
							token = m_Tokens.GetToken(); // skip args
						m_Tokens.GetToken(); // skip args
					}
					else if (!token.Matches(_T("*_EVENT_TABLE")) &&
						!token.Matches(_T("IMPLEMENT_APP")) &&
						!token.Matches(_T("WX_DECLARE_*")) &&
						!token.Matches(_T("WX_DEFINE_*")))
                    {
						if (m_Str.GetChar(0) == '~')
						{
                            token = _T('~') + token;
                            m_Str.Clear();
                        }
                        HandleFunction(token);
                    }
					else
						m_Tokens.GetToken(); // skip args
				}
				else
				{
					m_Str << token << _T(" ");
				}
			}
		}
	}
	return true;
}

bool ParserThread::Parse()
{
    if (!m_pTokens)
        return false;
#if 0
	if (!m_Options.useBuffer)
		Log("Parsing " + m_Filename);
#endif

	if (!m_Tokens.IsOK())
	{
		//Log("Cannot parse " + m_Filename);
		return false;
    }

	if (m_Options.useBuffer)
		m_StartBlockIndex = m_pTokens->GetCount();
    else
        m_StartBlockIndex = 0;
	m_Str.Clear();
	m_LastToken.Clear();
    m_EncounteredNamespaces.Clear();

	while (1)
	{
		if (!m_pTokens || TestDestroy())
			break;

		wxString token = m_Tokens.GetToken();
		if (token.IsEmpty())
			break;
#if 0
	if (!m_Str.IsEmpty())
		Log(m_Str);
#endif
#if 0
	if (!token.IsEmpty())
		Log(token);
#endif

		if (token.Matches(_T(";")))
		{
			m_Str.Clear();
		}
		else if (token.Matches(_T("delete")) ||
                token.Matches(_T(".")) ||
				(token.Matches(_T(">")) && m_LastToken.Matches(_T("-"))))
		{
			m_Str.Clear();
			SkipToOneOfChars(_T(";}"));
		}
		else if (token.Matches(_T("{")))
		{
			if (!m_Options.useBuffer || m_Options.bufferSkipBlocks)
				SkipBlock();
			m_Str.Clear();
		}
		else if (token.Matches(_T("}")))
		{
			m_pLastParent = 0L;
			m_LastScope = tsUndefined;
			m_Str.Clear();
			// the only time we get to find a } is when recursively called by e.g. HandleClass
			// we have to return now...
			if (!m_Options.useBuffer)
                break;
		}
		else if (token.Matches(_T(":")))
		{
			if (m_LastToken.Matches(_T("public")))
				m_LastScope = tsPublic;
			else if (m_LastToken.Matches(_T("protected")))
				m_LastScope = tsProtected;
			else if (m_LastToken.Matches(_T("private")))
				m_LastScope = tsPrivate;
			m_Str.Clear();
		}
		else if (token.Matches(_T("while")) ||
			token.Matches(_T("if")) ||
			token.Matches(_T("do")) ||
			token.Matches(_T("else")) ||
			token.Matches(_T("for")) ||
			token.Matches(_T("switch")))
		{
			if (!m_Options.useBuffer || m_Options.bufferSkipBlocks)
				SkipToOneOfChars(_T(";}"), true);
			else
				m_Tokens.GetToken(); //skip args
			m_Str.Clear();
		}
		else if (token.Matches(_T("typedef")) ||
			token.Matches(_T("return")) ||
			token.Matches(_T(":")))
		{
			SkipToOneOfChars(_T(";}"), true);
			m_Str.Clear();
		}
		else if (token.Matches(_T("extern")))
		{
            // check for "C"
            m_Str = m_Tokens.GetToken();
            if (m_Str.Matches(_T("\"C\"")))
            {
                m_Tokens.GetToken(); // "eat" {
                Parse(); // time for recursion ;)
            }
            else
                SkipToOneOfChars(_T(";")); // skip externs
//                m_Tokens.UngetToken(); // nope, return the token back...
            m_Str.Clear();
        }
        else if (token.StartsWith(_T("__asm")))
		{
			SkipToOneOfChars(_T(";"), true);
			//m_Str.Clear();
		}
		else if (token.Matches(_T("static")) ||
			token.Matches(_T("virtual")) ||
			token.Matches(_T("inline")))
		{
			// do nothing (skip it)
			//m_Str.Clear();
		}
		else if (token.Matches(_T("#")))
		{
			token = m_Tokens.GetToken();
			if (token.Matches(_T("include")))
				HandleIncludes();
			else if (token.Matches(_T("define")))
				HandleDefines();
			m_Str.Clear();
		}
		else if (token.Matches(_T("using"))) // using namespace ?
		{
            SkipToOneOfChars(_T(";}"), true);
			m_Str.Clear();
		}
		else if (token.Matches(_T("namespace")))
		{
			m_Str.Clear();
			HandleNamespace();
		}
		else if (token.Matches(_T("template")))
		{
			m_Str.Clear();
			SkipToOneOfChars(_T(">;"), true);
		}
		else if (token.Matches(_T("class")))
		{
			m_Str.Clear();
			HandleClass();
		}
		else if (token.Matches(_T("struct")))
		{
			m_Str.Clear();
			HandleClass(false);
		}
		else if (token.Matches(_T("enum")))
		{
			m_Str.Clear();
			HandleEnum();
		}
		else if (token.Matches(_T("union")))
        {
            SkipToOneOfChars(_T("{;"));
//            if (m_Tokens.GetToken() == "{")
            {
                Token* oldparent = m_pLastParent;
                Parse();
                m_Str.Clear();
                m_pLastParent = oldparent;
            }
        }
#if 1
		else if (token.Matches(_T("operator")))
		{
			wxString func = token;
			while (1)
			{
				token = m_Tokens.GetToken();
				if (!token.IsEmpty())
				{
					if (token.GetChar(0) == '(')
					{
						// check for operator()()
						wxString peek = m_Tokens.PeekToken();
						if (!peek.IsEmpty() && peek.GetChar(0) != '(')
							m_Tokens.UngetToken();
						else
							func << token;
						break;
					}
					else
						func << token;
				}
				else
					break;
			}
			HandleFunction(func, true);
			m_Str.Clear();
		}
#endif
		else
		{
			wxString peek = m_Tokens.PeekToken();
			if (!peek.IsEmpty())
			{
				if (peek.GetChar(0) == '(' && !m_Options.useBuffer)
				{
					if (!m_Options.useBuffer || m_Options.bufferSkipBlocks)
					{
						// function
						// ignore some well-known wxWindows macros
						if (token.Matches(_T("BEGIN_EVENT_TABLE")))
						{
							// skip till after END_EVENT_TABLE
							while (!token.IsEmpty() && !token.Matches(_T("END_EVENT_TABLE")))
								token = m_Tokens.GetToken(); // skip args
							m_Tokens.GetToken(); // skip args
						}
						else if (!token.Matches(_T("*_EVENT_TABLE*")) &&
							!token.Matches(_T("IMPLEMENT_APP")) &&
							!token.Matches(_T("IMPLEMENT_DYNAMIC_CLASS")) &&
							!token.Matches(_T("WX_DECLARE_*")) &&
							!token.Matches(_T("WX_DEFINE_*")))
                        {
//                            Log("m_Str='"+m_Str+"'");
//                            Log("token='"+token+"'");
//                            Log("peek='"+peek+"'");
							HandleFunction(token);
                        }
						else
							m_Tokens.GetToken(); // skip args
					}
					else
						m_Tokens.GetToken(); // eat args when parsing block
					m_Str.Clear();
				}
				else if (peek.Matches(_T(",")))
				{
                    // example decl to encounter a comma: int x,y,z;
                    // token should hold the var (x/y/z)
                    // m_Str should hold the type (int)
                    DoAddToken(tkVariable, token);
                    // skip comma (we had peeked it)
                    m_Tokens.GetToken();
				}
				else if (peek.Matches(_T("<")))
				{
                    // a template, e.g. someclass<void>::memberfunc
                    // we have to skip <>, so we 're left with someclass::memberfunc
                    SkipAngleBraces();
                    peek = m_Tokens.PeekToken();
                    if (peek.Matches(_T("::")))
                    {

⌨️ 快捷键说明

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