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

📄 cjparser.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// "reversed" versions of skip_token() and get_next_token()

static inline void skip_token_back( char*& cur )
{
    // FIXME:: now, when moving backwards, neither strings nor
    //         comment blocks are checked

    --cur; // skip to the trailing character

    if ( *cur == ',' ||
         *cur == ')' ||
         *cur == '('
       )
       return;


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

            default : continue;
        };

        break;
    }

    ++cur; // get to the leading character of the token
}

static inline void skip_next_token_back( char*& cur )
{
    --cur; // skip leading character of the current token

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

    for( ; cur < _gSrcEnd; --cur )
    {
        switch ( *cur )
        {
            case ' ' : continue;
            case '\t': continue;
            case 13  : continue;
            case 10  : continue;
            case ',' : continue;
            case '(' : continue;

            default : break;
        };

        break;
    }

    ++cur; // position after the trailing charcter of the prev token
}

static wxString get_token_str( char* cur )
{
    return wxString( cur, get_token_len( cur ) );
}

// skips token or whole expression which may have
// nested  expressions between '(' ')' brackets.
//
// Upon return, the cursor points to the terminating bracket ')',
//
// Return value is the size of the block

static size_t skip_block( char*& cur )
{
    size_t level = 0; // nesting level

    char* start = cur;

    // NOTE:: assumed that block not necessarely starts
    //        with bracket rightaway

    if ( *cur == '(' )
    {
        ++level;
    }

    do
    {
        skip_token( cur );

        char* savedPos = cur;
        int tmpLnNo;
        store_line_no( tmpLnNo );

        get_next_token( cur );

        if ( cur >= _gSrcEnd ) return 0;

        if ( *cur == '(' )
        {
            ++level;
        }
        else
        if ( *cur == ')' )
        {
            if ( level == 0 )
            {
                cur = savedPos;
                restore_line_no( tmpLnNo );

                return size_t(cur-start);
            }

            --level;

            if ( level == 0 )
            {
                ++cur;

                // QUICK-HACK::to easily handle function prototypes ,
                // it works, besause theoretically there should
                // be no cast-expressions in non-implementation
                // scope (e.g. "time( (long*)(ptr+1) )" should not
                // appear in the declarations, thus it is most likelly
                // for the ")(" fragment to be within a function
                // prototype in the declarations scope

                if ( *cur == '(' )
                {
                    ++level;
                    continue;
                }

                else return size_t(cur-start);
            }
        }
        else
        {
            if ( level == 0 )
            {
                cur = savedPos;
                restore_line_no( tmpLnNo );

                return size_t(cur-start);
            }
        }

    } while(1);
}

// returns 0, if end of source reached
static inline bool skip_imp_block( char*& cur )
{
    while( *cur != '{' && cur < _gSrcEnd )
    {
        skip_token( cur );
        if ( !get_next_token( cur ) ) return false;
    }

    while( *cur != '}' && cur < _gSrcEnd )
    {
        skip_token( cur );
        if ( !get_next_token( cur ) ) return false;
    }

    ++cur;

    return true;
}

static bool is_class_token( char*& cur )
{
    // FIXME:: the below mess should be cleaned in it's entirely

    if ( *cur == 'i' )
        if ( *(cur+1) == 'n' )

            return cmp_tokens_fast( cur, "interface", 9 );

    if ( *cur == 'c' )
        if ( *(cur+1) == 'l' )

            return cmp_tokens_fast( cur, "class", 5 );

    if ( *cur == 's' )
        if ( *(cur+1) == 't' )

            return cmp_tokens_fast( cur, "struct", 6 );

    if ( *cur == 'u' )
        if ( *(cur+1) == 'n' )

            return cmp_tokens_fast( cur, "union", 5 );

    return false;
}

inline static bool is_forward_decl( char* cur )
{
    do
    {
        switch( *cur )
        {
            case ':' : return false;
            case '{' : return false;
            case '(' : return false;

            case ';' : return true;

            default : break;
        };

        ++cur;

    } while (cur < _gSrcEnd); // prevent running out of bounds

    return false;
}

inline static bool is_function( char* cur, bool& isAMacro )
{
    isAMacro = false;

    int tmpLnNo;
    store_line_no( tmpLnNo );

    // NOTE:: comments and quoted strings are not checked here

    // first,check for "single-line hanginging macros" like:
    // ___UNICODE
    //

    char* eol = cur;
    skip_to_eol( eol );

    skip_token( cur );
    get_next_token( cur );

    if ( cur > eol )
    {
        isAMacro = true;
        restore_line_no( tmpLnNo );

        return true;
    }

    // it's not a macro, go to the begining of arg. list

    do
    {
        // if bracket found, it's a function or a begining
        // of some macro
        if ( *cur == '(' )
        {
            restore_line_no( tmpLnNo );
            return true;
        }

        // end of statement found without any brackets in it
        // - it cannot be a function

        if ( *cur == ';' )
        {
            restore_line_no( tmpLnNo );
            return false;
        }

        ++cur;

    } while( cur < _gSrcEnd);

    isAMacro = 1;
    restore_line_no( tmpLnNo );

    return false;
}

// upon return the cursor is positioned after the
// terminating curly brace

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

    for( ; cur < _gSrcEnd ; ++cur )

        switch( *cur )
        {
            case '/' : skip_comments( cur );
                       --cur;
                       continue;
            case '"' : skip_quoted_string( cur );
                       --cur;
                       continue;

            case '{' : ++level;
                       continue;

            case '}'  :--level;
                       if ( level == 0 )
                       {
                           ++cur; // skip final closing curly brace
                           return;
                       }

            case 10 : ++_gLineNo; continue;

            default : continue;
        };
}

// moves tokens like '*' '**', '***', '&' from the name
// to the type

static void arrange_indirection_tokens_between( wxString& type,
                                                wxString& identifier )
{
    // TBD:: FIXME:: return value of operators !

    while ( identifier[0u] == _T('*') ||
            identifier[0u] == _T('&')
          )
    {
        type += identifier[0u];
        identifier.erase(0,1);

        if ( !identifier.length() ) return;
    }
}


// the only function where multi-lang keyword map is accessed

static bool is_keyword( char* cur )
{
    size_t len = get_token_len( cur );

    // put a terminating zero after the given token
    char tmp = *(cur + len);
    *(cur+len) = '\0';

    KeywordMapT::iterator i;

    i = __gMultiLangMap.find( cur );

    // restore original character suppresed by terminating zero
    *(cur + len) = tmp;

    return i == __gMultiLangMap.end() ? false : true;
}

static inline void get_string_between( wxChar* start, wxChar* end,
                                       wxString* pStr )
{
    char saved = *end;

    *end  = _T('\0');
    *pStr = start;
    *end  = saved;
}

static wxChar* set_comment_text( wxString& text, wxChar* start )
{
    wxChar* end = start;

    // to avoid poluting the queue with this comment
    _gLastSuppresedComment = start;

    skip_comments( end );

    if ( *(end-1) == _T('/') )
        end -= 2;

    start += 2;

    // skip multiple leading '/''s or '*''s
    while( *start == _T('/') && start < end ) ++start;
    while( *start == _T('*') && start < end ) ++start;

    get_string_between( start, end, &text );

    return end;
}

/***** Implementation for class CJSourceParser *****/

CJSourceParser::CJSourceParser( bool collectCommnets, bool collectMacros )
    : mpStart(0),
      mpEnd(0),
      mpCurCtx( 0 ),
      mCommentsOn( collectCommnets ),
      mMacrosOn  ( collectMacros )
{
    check_keyword_map();
}

spFile* CJSourceParser::Parse( char* start, char* end )
{
    // set up state variables
    mCurVis       = SP_VIS_PRIVATE;

    spFile* pTopCtx = new spFile();
    mpCurCtx        = pTopCtx;

    mIsVirtual    = 0;
    mIsTemplate   = 0;
    mNestingLevel = 0;

    m_cur = start;

    mpStart = start;
    mpEnd   = end;

    _gSrcEnd   = mpEnd; // let all the C-functions "smell" the end of file
    _gSrcStart = start;

    _gLineNo   = 0;

    clear_commets_queue();

    // main parsing loop

    do
    {
        if ( !get_next_token( m_cur ) )
            // end of source reached
            return pTopCtx;

        if ( memcmp( m_cur, "ScriptSection( const string&",
                     strlen( "ScriptSection( const string&" )
                   ) == 0
            )
        {
            // int o = 0;
            // ++o;
        }

        switch (*m_cur)
        {
            case '#' :
                {
                    AddMacroNode( m_cur );
                    continue;
                }

            case ':' :
                {
                    skip_token( m_cur );
                    continue;
                }

            case ';' :
                {
                    skip_token( m_cur );
                    continue;
                }

            case ')' :
                {
                    skip_token( m_cur );
                    continue;
                }

            case '=' :
                {
                    skip_token( m_cur );
                    continue;
                }

            default: break;
        }

        // 'const' is a part of the return type, not a keyword here
        if ( strncmp(m_cur, "const", 5) != 0 && is_keyword( m_cur ) )
        {
            // parses, token, if token identifies
            // the container context (e.g. class/namespace)
            // the corresponding context object is created
            // and set as current context

            ParseKeyword( m_cur );
            continue;
        }

        if ( *m_cur >= _T('0') && *m_cur <= _T('9') )
        {
            skip_token( m_cur );
            continue;
        }

        if ( *m_cur == _T('}') )
        {
            if ( mCurCtxType != SP_CTX_CLASS )
            {
                // FOR NOW:: disable the below assertion

                // DBG:: unexpected closing-bracket found
                //ASSERT(0);

                skip_token( m_cur ); // just skip it
                continue;
            }

            if ( mpCurCtx->GetType() == SP_CTX_CLASS )
            {
                int curOfs = ( (m_cur+1) - _gSrcStart );

                mpCurCtx->mContextLength = ( curOfs - mpCurCtx->mSrcOffset );
            }

            --mNestingLevel;

            // terminate operation/class/namespace context
            // TBD:: check if it's really this type of context

            wxASSERT( mpCurCtx );
            mpCurCtx = mpCurCtx->GetOutterContext();
            wxASSERT( mpCurCtx );

            if ( mNestingLevel == 0 )
            {

                mCurCtxType = SP_CTX_FILE;

                // not-nested class delclaration finished,
                // rest template flag in any case
                mIsTemplate = 0;
            }

            skip_token( m_cur );
            continue;
        }

        bool isAMacro = false;

        if ( is_function( m_cur, isAMacro ) )
        {
            if ( isAMacro )
            {
                skip_token( m_cur );
                continue;
            }

            char* savedPos = m_cur;

            int tmpLnNo;
            store_line_no( tmpLnNo );
            wxUnusedVar( tmpLnNo );

            isAMacro = false;

            if ( !ParseNameAndRetVal( m_cur, isAMacro ) )
            {
                if ( !isAMacro )
                {
                    m_cur = savedPos;
                    SkipFunction( m_cur );
                }
                continue;
            }

            if ( !ParseArguments( m_cur ) )
            {
                // failure while parsing arguments,

⌨️ 快捷键说明

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