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

📄 parser.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
* 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: parser.cpp,v 1.25.2.1 2005/10/25 07:59:01 mandrav Exp $
* $Date: 2005/10/25 07:59:01 $
*/

#include <sdk.h>
#include <wx/log.h>
#include <wx/app.h>
#include <wx/filename.h>
#include <wx/tokenzr.h>
#include <wx/intl.h>
#include <wx/progdlg.h>
#include "parser.h"
#ifndef STANDALONE
	#include <configmanager.h>
	#include <messagemanager.h>
	#include <manager.h>
	#include <globals.h>
#endif // STANDALONE

static const char CACHE_MAGIC[] = "CCCACHE_1_0";
static char CACHE_MAGIC_READ[] = "           ";
static wxMutex s_mutexListProtection;
int PARSER_END = wxNewId();
static int idPool = wxNewId();

BEGIN_EVENT_TABLE(Parser, wxEvtHandler)
//	EVT_MENU(NEW_TOKEN, Parser::OnNewToken)
//	EVT_MENU(FILE_NEEDS_PARSING, Parser::OnParseFile)
	EVT_THREADTASK_STARTED(idPool, Parser::OnStartThread)
	EVT_THREADTASK_ENDED(idPool, Parser::OnEndThread)
    EVT_THREADTASK_ALLDONE(idPool, Parser::OnAllThreadsDone)
END_EVENT_TABLE()

Parser::Parser(wxEvtHandler* parent)
	: m_MaxThreadsCount(8),
	m_pParent(parent)
#ifndef STANDALONE
	,m_pImageList(0L)
#endif
    ,m_abort_flag(false),
    m_UsingCache(false),
    m_CacheFilesCount(0),
    m_CacheTokensCount(0),
    m_Pool(this, idPool)
{
	ReadOptions();
#ifndef STANDALONE
	m_pImageList = new wxImageList(16, 16);
	wxBitmap bmp;
	wxString prefix;
    prefix = ConfigManager::Get()->Read(_T("data_path")) + _T("/images/codecompletion/");
    // bitmaps must be added by order of PARSER_IMG_* consts
    bmp.LoadFile(prefix + _T("class_folder.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_CLASS_FOLDER
    bmp.LoadFile(prefix + _T("class.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_CLASS
    bmp.LoadFile(prefix + _T("ctor_private.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_CTOR_PRIVATE
    bmp.LoadFile(prefix + _T("ctor_protected.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_CTOR_PROTECTED
    bmp.LoadFile(prefix + _T("ctor_public.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_CTOR_PUBLIC
    bmp.LoadFile(prefix + _T("dtor_private.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_DTOR_PRIVATE
    bmp.LoadFile(prefix + _T("dtor_protected.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_DTOR_PROTECTED
    bmp.LoadFile(prefix + _T("dtor_public.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_DTOR_PUBLIC
    bmp.LoadFile(prefix + _T("method_private.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_FUNC_PRIVATE
    bmp.LoadFile(prefix + _T("method_protected.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_FUNC_PRIVATE
    bmp.LoadFile(prefix + _T("method_public.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_FUNC_PUBLIC
    bmp.LoadFile(prefix + _T("var_private.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_VAR_PRIVATE
    bmp.LoadFile(prefix + _T("var_protected.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_VAR_PROTECTED
    bmp.LoadFile(prefix + _T("var_public.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_VAR_PUBLIC
    bmp.LoadFile(prefix + _T("preproc.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_PREPROCESSOR
    bmp.LoadFile(prefix + _T("enum.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_ENUM
    bmp.LoadFile(prefix + _T("enumerator.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_ENUMERATOR
    bmp.LoadFile(prefix + _T("namespace.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_NAMESPACE
    bmp.LoadFile(prefix + _T("symbols_folder.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_SYMBOLS_FOLDER
    bmp.LoadFile(prefix + _T("enums_folder.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_ENUMS_FOLDER
    bmp.LoadFile(prefix + _T("preproc_folder.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_PREPROC_FOLDER
    bmp.LoadFile(prefix + _T("others_folder.png"), wxBITMAP_TYPE_PNG);
    m_pImageList->Add(bmp); // PARSER_IMG_OTHERS_FOLDER
#endif // STANDALONE
    ConnectEvents();
}

Parser::~Parser()
{
    DisconnectEvents();
	Clear();
#ifndef STANDALONE
	delete m_pImageList;
#endif // STANDALONE
}

void Parser::ConnectEvents()
{
//    Connect(EVT_THREADTASK_STARTED, -1, cbEVT_THREADTASK_STARTED,
//            (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
//            &Parser::OnStartThread);
//    Connect(EVT_THREADTASK_ENDED, -1, cbEVT_THREADTASK_ENDED,
//            (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
//            &Parser::OnEndThread);
    Connect(NEW_TOKEN, -1, wxEVT_COMMAND_MENU_SELECTED,
            (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
            &Parser::OnNewToken);
    Connect(FILE_NEEDS_PARSING, -1, wxEVT_COMMAND_MENU_SELECTED,
            (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
            &Parser::OnParseFile);
}

void Parser::DisconnectEvents()
{
//    Disconnect(EVT_THREADTASK_STARTED, -1, cbEVT_THREADTASK_STARTED);//,
//    Disconnect(EVT_THREADTASK_ENDED, -1, cbEVT_THREADTASK_ENDED);//,
    Disconnect(NEW_TOKEN, -1, wxEVT_COMMAND_MENU_SELECTED);//,
    Disconnect(FILE_NEEDS_PARSING, -1, wxEVT_COMMAND_MENU_SELECTED);//,
}

void Parser::ReadOptions()
{
#ifdef STANDALONE
	m_Options.followLocalIncludes = true;
	m_Options.followGlobalIncludes = false;
	m_Options.caseSensitive = true;
	m_Options.wantPreprocessor = false;
	m_Options.useSmartSense = true;
	m_BrowserOptions.showInheritance = false;
	m_BrowserOptions.viewFlat = false;
#else // !STANDALONE
	m_MaxThreadsCount = ConfigManager::Get()->Read(_T("/code_completion/max_threads"), 8);
	m_Options.followLocalIncludes = ConfigManager::Get()->Read(_T("/code_completion/parser_follow_local_includes"), 1L);
	m_Options.followGlobalIncludes = ConfigManager::Get()->Read(_T("/code_completion/parser_follow_global_includes"), 0L);
	m_Options.caseSensitive = ConfigManager::Get()->Read(_T("/code_completion/case_sensitive"), 0L);
	m_Options.useSmartSense = ConfigManager::Get()->Read(_T("/code_completion/use_SmartSense"), 1);
	m_Options.wantPreprocessor = ConfigManager::Get()->Read(_T("/code_completion/want_preprocessor"), 0L);
	m_BrowserOptions.showInheritance = ConfigManager::Get()->Read(_T("/code_completion/browser_show_inheritance"), 0L);
	m_BrowserOptions.viewFlat = ConfigManager::Get()->Read(_T("/code_completion/browser_view_flat"), 0L);
#endif // STANDALONE
}

void Parser::WriteOptions()
{
#ifndef STANDALONE
	ConfigManager::Get()->Write(_T("/code_completion/max_threads"), (int)m_MaxThreadsCount);
	ConfigManager::Get()->Write(_T("/code_completion/parser_follow_local_includes"), m_Options.followLocalIncludes);
	ConfigManager::Get()->Write(_T("/code_completion/parser_follow_global_includes"), m_Options.followGlobalIncludes);
	ConfigManager::Get()->Write(_T("/code_completion/case_sensitive"), m_Options.caseSensitive);
	ConfigManager::Get()->Write(_T("/code_completion/use_SmartSense"), m_Options.useSmartSense);
	ConfigManager::Get()->Write(_T("/code_completion/want_preprocessor"), m_Options.wantPreprocessor);
	ConfigManager::Get()->Write(_T("/code_completion/browser_show_inheritance"), m_BrowserOptions.showInheritance);
	ConfigManager::Get()->Write(_T("/code_completion/browser_view_flat"), m_BrowserOptions.viewFlat);
#endif // STANDALONE
}

bool Parser::CacheNeedsUpdate()
{
    if (m_UsingCache)
    {
        ClearTemporaries(); // no temps in counting
        if (m_CacheFilesCount == (int)m_ParsedFiles.GetCount() &&
            m_CacheTokensCount == (int)m_Tokens.GetCount())
        {
            // in-mem data and cache seem to be in sync
            // @warning: this is *not* bulletproof!
            // consider a token name change, for example...
            // maybe use a CRC of some kind?
            return false;
        }
    }
    return true;
}

bool Parser::ReadFromCache(wxFile* f)
{
    // File format is like this:
    //
    // CACHE_MAGIC
    // Number of parsed files
    // Number of tokens
    // Parsed files
    // Tokens
    // EOF

    // keep a backup of include dirs
    wxArrayString dirs = m_IncludeDirs;
    Manager::Get()->GetMessageManager()->DebugLog(_("Clearing Cache"));
    Clear();
    // restore backup
    m_IncludeDirs = dirs;

    Manager::Get()->GetMessageManager()->DebugLog(_("Begin reading..."));
    if (f->Read(CACHE_MAGIC_READ, sizeof(CACHE_MAGIC_READ)) != sizeof(CACHE_MAGIC_READ) ||
        strncmp(CACHE_MAGIC, CACHE_MAGIC_READ, sizeof(CACHE_MAGIC_READ) != 0))
    {
        return false;
    }
    int fcount = 0;
    int tcount = 0;
    Manager::Get()->GetMessageManager()->DebugLog(_("Reading fcount..."));
    if (!LoadIntFromFile(f, &fcount)) return false;
    Manager::Get()->GetMessageManager()->DebugLog(_("Reading tcount..."));
    if (!LoadIntFromFile(f, &tcount)) return false;

    wxProgressDialog* progress = 0;
    unsigned int counter = 0;

    // display cache progress?
    if (ConfigManager::Get()->Read(_T("/code_completion/show_cache_progress"), 1L))
    {
        Manager::Get()->GetMessageManager()->DebugLog(_("Creating progress dialog..."));
        progress = new wxProgressDialog(_("Code-completion plugin"),
                                        _("Please wait while loading code-completion cache..."),
                                        fcount + tcount);
    }

    // m_ParsedFiles
    Manager::Get()->GetMessageManager()->DebugLog(_("Reading data from cache NOW"));
    wxString file;
    for (int i = 0; i < fcount && !f->Eof(); ++i)
    {
        if (!LoadStringFromFile(f, file))
        {
            delete progress;
            return false;
        }
        m_ParsedFiles.Add(file);
        if (progress)
            progress->Update(++counter);
    }

    Manager::Get()->GetMessageManager()->DebugLog(_("Calculating tokens..."));
    // m_Tokens
    for (int i = 0; i < tcount && !f->Eof(); ++i)
    {
        // update m_Int for inheritance to be serialized properly
        Token* token = new Token;
        token->m_Int = i;
        m_Tokens.Add(token);
    }
    for (int i = 0; i < tcount && !f->Eof(); ++i)
    {
        Token* token = m_Tokens[i];
        if (!token->SerializeIn(f))
        {
            delete progress;
            return false;
        }
        if (progress)
            progress->Update(++counter);
    }

    Manager::Get()->GetMessageManager()->DebugLog(_("Updating linking pointers..."));
    // now we must update linking pointers in tokens
    for (int i = 0; i < tcount; ++i)
    {
        Token* token = m_Tokens[i];
        token->m_pParent = token->m_ParentIndex != -1 ? m_Tokens[token->m_ParentIndex] : 0;
        // sanity check
        if (token->m_pParent == token)
            token->m_pParent = 0;

        for (unsigned int j = 0; j < token->m_AncestorsIndices.GetCount(); ++j)
        {
            if (token->m_AncestorsIndices[j] != -1)
            {
                Token* ancestor = m_Tokens[token->m_AncestorsIndices[j]];
                if (ancestor != token) // sanity check
                    token->m_Ancestors.Add(ancestor);
            }
        }

        for (unsigned int j = 0; j < token->m_ChildrenIndices.GetCount(); ++j)
        {
            if (token->m_ChildrenIndices[j] != -1)
            {
                Token* child = m_Tokens[token->m_ChildrenIndices[j]];
                if (child != token) // sanity check
                    token->m_Children.Add(child);
            }
        }
    }

//    LinkInheritance(); // fix ancestors relationships

    Manager::Get()->GetMessageManager()->DebugLog(_("Cleaning up subroutine..."));
    m_UsingCache = true;
    m_CacheFilesCount = m_ParsedFiles.GetCount();
    m_CacheTokensCount = m_Tokens.GetCount();

    Manager::Get()->GetMessageManager()->DebugLog(_("Deleting progress dialog (if any)..."));
    if (progress)
        delete progress;

    Manager::Get()->GetMessageManager()->DebugLog(_("Finished reading from cache."));
    return true;
}

bool Parser::WriteToCache(wxFile* f)
{
    // File format is like this:
    //
    // CACHE_MAGIC
    // Number of parsed files
    // Number of tokens
    // Parsed files
    // Tokens
    // EOF

    ClearTemporaries(); // no temps in cache

    unsigned int tcount = m_Tokens.GetCount();
    unsigned int fcount = m_ParsedFiles.GetCount();
    unsigned int counter = 0;

    wxProgressDialog* progress = 0;

⌨️ 快捷键说明

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