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

📄 cjparser.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     22/09/98
// RCS-ID:      $Id: cjparser.cpp,v 1.21 2005/09/23 12:56:18 MR Exp $
// Copyright:   (c) Aleskandars Gluchovas
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "cjparser.h"

#if defined( wxUSE_TEMPLATE_STL )

    #include <map>

#else

    #include "wxstlac.h"

#endif


/***** Implementation for class SJParser *****/

// statics used by inline'ed C helper-functions
static char* _gSrcStart = 0;
static char* _gSrcEnd   = 0;
static wxChar* _gLastSuppresedComment = 0;
static int   _gLineNo      = 0;

// FOR NOW:: comments queue is static
#define MAX_CQ_ENTRIES 128
static char* _gCommentsQueue[MAX_CQ_ENTRIES];
static int    _gCQSize = 0;

/***** keyword map related structures *****/

struct less_c_str
{
    inline bool operator()( char* x, char* y) const
    {     return ( strcmp( x,y ) < 0 );
    }
};

//WXSTL_MAP(CharPtrT,CharPtrT, LESS_THEN_FUNCTOR(CharPtrT));

#if defined( wxUSE_TEMPLATE_STL )

    typedef map< char*, char*, less_c_str > KeywordMapT;

#else

    typedef char* CharPtrT;
    typedef WXSTL_MAP( CharPtrT, CharPtrT ,less_c_str) KeywordMapT;

#endif

static KeywordMapT __gMultiLangMap;
static int         __gMapReady = 0;

static char* __gKeyWords[] =
{
    "public",
    "protected",
    "private",

    "class",
    "struct",
    "union",
    "enum",
    "interface",

    "package",
    "import",

    "typedef",
    "template",
    "friend",
    "const",
    "volatile",
    "mutable",
    "virtual",
    "inline",
    "static",
    "register",

    "final",
    "abstract",
    "native",

    "__stdcall",
    "extern",

    0
};

static void check_keyword_map()
{
    if ( !__gMapReady )
    {
        __gMapReady = 1;

        // "make sure" the address of the first member of non-polimorphic class
        // coinsides with the address of the instance

        char** keyword = __gKeyWords;

        while ( (*keyword) != 0 )
        {
            __gMultiLangMap.insert(
                KeywordMapT::value_type( *keyword, *keyword )
            );

            ++keyword;
        }
    }
}

/***** helper functions *****/

static inline void skip_to_eol( char*& cur )
{
    while( *(cur) != 10 && *cur != 13 && cur < _gSrcEnd) ++cur;
}

static inline void skip_eol( char*& cur )
{
    if ( *cur == 13 )

        cur += 2;
    else
        cur += 1;

    ++_gLineNo;
}

static inline bool skip_to_next_comment_in_the_line( char*& cur )
{
    do
    {
        while( cur < _gSrcEnd  &&
               *cur != 10 &&
               *cur != 13 &&
               *cur != '/'
             ) ++cur;

        if ( cur == _gSrcEnd ) return false;

        if ( *cur == '/' )
        {
            if ( (*(cur+1) == '*') ||
                 (*(cur+1) == '/') ) return true;
            else
            {
                ++cur;
                continue;
            }
        }

        return false;

    } while(1);
}

inline static void store_line_no( int& toVar )
{
    toVar = _gLineNo;
}

inline static void restore_line_no( int storedLineNo )
{
    _gLineNo = storedLineNo;
}

inline static int get_line_no()
{
    return _gLineNo;
}

static void skip_to_prev_line( char*& cur )
{
    while( cur >= _gSrcStart  &&
           *cur != 10 &&
           *cur != 13
           ) --cur;

    // NOTE:: '\n' is 13,10 for DOS
    //        '\n' is 10 for UNIX

    // NOTE1: '\n' symbol is not used here,
    //        to provide possibility of loading
    //        file as binary

    --cur;
    if ( *cur == 10 )
    {
        ++cur;
        return;
    }

    if ( *cur == 13 ) --cur;

    while( cur >= _gSrcStart  &&
           *cur != 10 &&
           *cur != 13
           ) --cur;

    ++cur; // move to the first character in the line
}

static inline void skip_comments( char*& cur )
{
    ++cur; // skip '/' token

    if ( *cur != '/' && *cur != '*' ) return;

    // first, store position of the comment into the queue
    // (which further will be attached to the next context
    //  found)

    if ( cur-1 != _gLastSuppresedComment )
    {
        if ( _gCQSize == MAX_CQ_ENTRIES )
        {
            size_t i = MAX_CQ_ENTRIES-1;

            while( i != 0 )
            {
                _gCommentsQueue[i-1] = _gCommentsQueue[i];
                --i;
            }

            --_gCQSize ;
        }

        _gCommentsQueue[_gCQSize++] = cur-1;
    }

    // if signle-line comment, skip it now
    if ( *cur == '/' )
    {
        skip_to_eol( cur );
        skip_eol( cur );
        return;
    }

    size_t level = 1;

    // check for multiline comment (handle nested multiline comments!)

    int line_len = 0;

    ++cur;
    ++cur;
    do
    {
        // TBD:: check eof cond.

        // detect and remove vertical columns of '*''s

        while ( *cur != '/' && cur < _gSrcEnd )
        {
            switch (*cur)
            {
                case '*' :
                    {
                        if ( *(cur+1) != '/' )
                        {
                            if ( line_len == 1 )

                                *cur = ' ';
                        }

                        break;
                    }

                case 13 : line_len = 0; break;
                case 10 : { line_len = 0; ++_gLineNo; } break;

                default : ++line_len;
            }

            ++cur;
        }

        if ( cur >= _gSrcEnd  ) return;

        ++cur;

        if ( *(cur-2) == '*' )
        {
            --level;
            if ( level == 0 )
                break;
        }
        else
        if ( *cur == '*' )
        {
            ++cur;
            ++cur;

            ++level;
        }

    } while(1);
}

static inline void clear_commets_queue()
{
    _gCQSize = 0;
}

static inline void skip_quoted_string( char*& cur )
{
    ++cur; // skip first quote '"'

    // check if quote wasn't prefixed
    if ( *(cur-2) == '\\' )
        return;

    do
    {
        while ( *cur != '"' && cur < _gSrcEnd )
        {
            if ( *cur == 10 ) ++_gLineNo;
            ++cur;
        }

        if ( cur >= _gSrcEnd ) return;

        ++cur; // skip the last quote

        // check if it wasn't prefixed

        if ( *(cur-2) != '\\' )
            break;

    } while (1);
}

// skips subsequent white space and comments
// (return false if the end of source code reached)

static inline bool get_next_token( char*& cur )
{
    for( ; cur < _gSrcEnd; ++cur )
    {
        switch( *(cur) )
        {
            case ' ' : continue;
            case '\t': continue;
            case 13  : continue;

            case 10  : { ++_gLineNo;continue; }

            case '/' : skip_comments( cur );
                       --cur;
                       continue;

            default : break;
        };

        break;
    }

    if ( cur >= _gSrcEnd )
        return false;
    else
        return true;
}

static inline void skip_preprocessor_dir( wxChar*& cur )
{
    do
    {
        skip_to_eol(cur);

        if ( *(cur-1) != _T('\\') )
            break;

        if ( cur < _gSrcEnd )
            skip_eol( cur );
        else
            break;

    } while(1);
}

static void skip_token( char*& cur )
{
    if ( *cur == '"' )
    {
        skip_quoted_string( cur );
        return;
    }

    if ( *cur == ',' ||
         *cur == ';' ||
         *cur == ')' ||
         *cur == '('
       )
    {
        ++cur;
        return;
    }

    // special case of "!=", "<=", ... 2 character composite tokens
    if ( *cur == '<' ||
         *cur == '>' ||
         *cur == '=' ||
         *cur == '!'
       )
    {
        cur++;
        if ( *cur == '=' )
            cur++;

        return;
    }

    ++cur; // leading character is always skipped

    for( ; cur < _gSrcEnd ; ++cur )
    {
        switch ( *cur )
        {
            case ' ' : break;
            case '\t': break;
            case 13  : break;
            case 10  : break;
            case ',' : break;
            case ';' : break;
            case '<' : break;
            case '>' : break;

            // FIXME:: QUICK-HACK:: to treat scope resolution
            //         tokens are a part of the string - e.g. SomeSpace::SubName would
            //         become one token

            case ':' : if ( *(cur+1) == ':' )
                       {
                           ++cur;
                           continue;
                       }

                       break;
            case '=' : break;
            case '(' : break;
            case ')' : break;
            case '{' : break;
            case '}' : break;

            default : continue;
        };
        break;
    }
}

static inline size_t get_token_len( char* tok )
{
    char* start = tok;

    skip_token( tok );

    return size_t( tok - start );
}

// returns true, if given tokens are equel

static inline bool cmp_tokens( char* tok1, char* tok2 )
{
    // NOTE:: the case one token includes
    //        other in it's entirely is not handled

    size_t len = get_token_len( tok1 );

    // assuming that tokens are non-zero length

    do
    {
        if ( *(tok1++) != *(tok2++) )
            return false;

        --len;

    } while ( --len );

    return true;
}

static inline bool cmp_tokens_fast( char* tok1, char* tok2, size_t len )
{
    do
    {
        if ( *(tok1++) != *(tok2++) )
            return false;

    } while ( --len );

    return true;
}

static inline void skip_tempalate_statement( char*& cur )
{
    size_t level = 0;

    // go one level deeper
    while( *cur != '<' && cur < _gSrcEnd )
    {
        if (*cur == 10 ) ++_gLineNo;
        ++cur;
    }

    // FIXME:: template should be checked statement for
    //         comments inside of it

    do
    {
        if ( *cur == '<' )
            ++level;
        else
            --level;

        ++cur; // skip '<' or '>' token

        if ( level == 0 )
            return;

        while( *cur != '<' && *cur != '>' && cur < _gSrcEnd )
        {
            if (*cur == 10 ) ++_gLineNo;
            ++cur;
        }

    } while (1);
}

static inline void skip_statement( char*& cur )
{
    for( ; cur < _gSrcEnd; ++cur )

        switch (*cur)
        {
            case  ';' : ++cur; // skip statement-terminator token
                        return;

            case  '"' : skip_quoted_string(cur);
                        --cur;
                        continue;

            case  10  : ++_gLineNo;

                        continue;
            case  '/' : skip_comments( cur );
                        --cur;
                        continue;
            default : continue;
        }
}

⌨️ 快捷键说明

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