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

📄 cjparser.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                // remove enclosing operation context

                spContext* pFailed = mpCurCtx;
                mpCurCtx = mpCurCtx->GetOutterContext();
                mpCurCtx->RemoveChild( pFailed );

                skip_to_eol( m_cur );
                //m_cur = savedPos;
            }
            else
            {
                // otherwise, successfully close operation context:

                clear_commets_queue();

                SkipFunctionBody( m_cur );

                mpCurCtx = mpCurCtx->GetOutterContext();

                // DBG::
                wxASSERT( mpCurCtx );

            }
        }
        else // otherwise it's declaration of a variable;
        {
            // now, the cursor point to the end of statement (';' token)

            if ( mCurCtxType != SP_CTX_CLASS )
            {
                // non-class members are ignored

                skip_token( m_cur ); // skip the end of statement
                continue;
            }

            ParseMemberVar( m_cur );
        }

    } while( 1 );
}

void CJSourceParser::AttachComments( spContext& ctx, wxChar* cur )
{
    if ( !mCommentsOn ) return;

    MCommentListT& lst = ctx.GetCommentList();

    wxChar* prevComEnd = 0;

    int tmpLnNo;
    store_line_no( tmpLnNo );

    // attach comments which were found before the given context

    for( int i = 0; i != _gCQSize; ++i )
    {
        spComment* pComment = new spComment();
        lst.push_back( pComment );

        // find the end of comment
        wxChar* start = _gCommentsQueue[i];

        pComment->mIsMultiline = ( *(start+1) == _T('*') );

        // first comment in the queue and multiline
        // comments are always treated as a begining
        // of the new paragraph in the comment text

        if ( i == 0 )
        {
            pComment->mStartsPar = true;
        }
        else if ( pComment->mIsMultiline )
        {
            pComment->mStartsPar = true;
        }
        else
        {
            // find out wheather there is a new-line
            // between to adjecent comments

            wxChar* prevLine = start;
            skip_to_prev_line(prevLine);

            if ( prevLine >= prevComEnd )
                pComment->mStartsPar = true;
            else
                pComment->mStartsPar = false;
        }

        prevComEnd = set_comment_text( pComment->m_Text, start );
    }

    // attach comments which are at the end of the line
    // of the given context (if any)

    if ( skip_to_next_comment_in_the_line( cur ) )
    {
        spComment* pComment = new spComment();
        lst.push_back( pComment );

        set_comment_text( pComment->m_Text, cur );

        pComment->mStartsPar = 1;
        pComment->mIsMultiline = ( *(cur+1) == _T('*') );

        // mark this comment, so that it would not
        // get in the comments list of the next context
        _gLastSuppresedComment = cur;
    }

    restore_line_no( tmpLnNo );

    clear_commets_queue();
}

void CJSourceParser::AddMacroNode( wxChar*& cur )
{
    wxChar* start = cur;

    int lineNo = get_line_no();

    skip_preprocessor_dir( cur );

    int tmpLnNo;
    store_line_no( tmpLnNo );

    if ( !mMacrosOn ) return;

    spPreprocessorLine* pPL = new spPreprocessorLine();
    pPL->mSrcLineNo = lineNo;

    AttachComments( *pPL, cur );

    get_string_between( start, cur, &pPL->m_Line );

    ++start; // skip '#'
    get_next_token( start );

    pPL->mDefType = SP_PREP_DEF_OTHER;

    // if we found a definition or redefinition,
    // determine the type exactly and assign
    // a name to the context

    if ( *start == _T('d') )
    {
        if ( cmp_tokens_fast( start, _T("define"), 6 ) )
        {
            char* tok = start+6;

            get_next_token( tok );

            pPL->m_Name = get_token_str( tok );

            skip_token( tok );
            get_next_token( tok);


            if ( tok > cur )
                pPL->mDefType = SP_PREP_DEF_DEFINE_SYMBOL;
            else
                pPL->mDefType = SP_PREP_DEF_REDEFINE_SYMBOL;
        }
    }
    else if ( *start == _T('i') )
    {
        if ( cmp_tokens_fast( start, _T("include"), 7 ) )
        {
            pPL->mDefType = SP_PREP_DEF_INCLUDE_FILE;
        }
        else if ( *++start == _T('f') )
        {
            // either "#if" or "#ifdef"
            cur = start;
            skip_token( cur );
            get_next_token( cur );

            wxString condition = get_token_str( cur );

            // currently, everything except '0' is true
            if ( condition == _T("0") ) {
                // skip until the following else or enif
                while ( cur < _gSrcEnd ) {
                    skip_to_eol( cur );
                    skip_eol( cur );

                    get_next_token( cur );
                    if ( *cur++ == _T('#') && *cur == _T('e') )
                        break;
                }
            }

            // TODO parse the condition...
        }
    }
    else if ( cmp_tokens_fast( start, _T("else"), 4 ) )
    {
        // skip until "#endif"
        while ( cur < _gSrcEnd ) {
            skip_to_eol( cur );
            skip_eol( cur );

            get_next_token( cur );
            if ( *cur++ == _T('#') && cmp_tokens_fast( cur, "endif", 5 ) )
                break;
        }
    }

    mpCurCtx->AddMember( pPL );

    skip_to_eol( cur );
    skip_eol( cur );

    restore_line_no( tmpLnNo );

    clear_commets_queue();
}

void CJSourceParser::ParseKeyword( char*& cur )
{
    // analyze token, which identifies the begining of a new context

    if ( CheckVisibilty( cur ) )
    {
        skip_token( cur );
        return;
    }

    if ( is_class_token( cur ) )
    {
        if ( is_forward_decl( cur ) )
        {
            // forward declarations are ignored;
            skip_token( cur );
            return;
        }

        if ( mNestingLevel == 0 )
        {
            // change context form global class context
            mCurCtxType = SP_CTX_CLASS;
        }

        ++mNestingLevel;

        // add information about new class (name, inheritance, etc)
        AddClassNode( cur );

        // the default visiblity for class members is 'private'
        mCurVis = SP_VIS_PRIVATE;

        return;
    }

    size_t len = get_token_len( cur );

    if ( cmp_tokens_fast( cur, "typedef", len  ) )
    {
        skip_token(cur);
        get_next_token(cur);

        if ( cmp_tokens_fast( cur, "struct", len ) ||
             cmp_tokens_fast( cur, "union",  len ) ||
             cmp_tokens_fast( cur, "class",  len )
           )
        {
            if ( mNestingLevel == 0 )
            {
                // change context form global class context
                mCurCtxType = SP_CTX_CLASS;
            }

            ++mNestingLevel;

            // add information about new class (name, inheritance, etc)
            AddClassNode( cur );

            // the default visiblity for class members is 'private'
            mCurVis = SP_VIS_PRIVATE;

            return;

            // FOR NOW:: typedef struct, etc are also ignored
            //skip_scope_block( cur );
        }

        if ( cmp_tokens_fast( cur, "enum", len  ) )
        {
            AddEnumNode( cur );
            return;
        }

        AddTypeDefNode( cur );

        return;
    }

    if ( cmp_tokens_fast( cur, "enum", len ) )
    {
        AddEnumNode( cur );
        return;
    }

    if ( cmp_tokens_fast( cur, "extern", len ) )
    {
        // extern's are ignored (both extern "C" and extern vars)
        while ( *cur != '{' &&
                *cur != ';' )
        {
            skip_token( cur );
            get_next_token( cur );
        }
        return;

    }
    if ( cmp_tokens_fast( cur, "enum", len ) )
    {
        // enumeration blocks are ignored

        skip_scope_block( cur );

        get_next_token( cur );
        skip_token( cur ); // skip ';' token;
        return;
    }

    if ( cmp_tokens_fast( cur, "package", len  ) )
    {
        // packages are ignored
        skip_statement( cur );
        return;
    };

    if ( cmp_tokens_fast( cur, "import", len  ) )
    {
        // import statements are ignored
        skip_statement( cur );
        return;
    }

    if ( cmp_tokens_fast( cur, "virtual", len  ) )
    {
        // probably the virtual method is in front of us;
        mIsVirtual = 1;
        skip_token( cur );
        return;
    }

    if ( cmp_tokens_fast( cur, "template", len  ) )
    {
        mIsTemplate = 1;
        skip_tempalate_statement( cur );
        return;
    }

    if ( cmp_tokens_fast( cur, "friend", len  ) )
    {
        skip_statement( cur );
        return;
    }

    // ingnore "unsigificant" tokens (i.e. which do not
    // affect the current parsing context)

    skip_token( cur );
}

bool CJSourceParser::ParseNameAndRetVal( char*& cur, bool& isAMacro )
{
    isAMacro = false;

    // FOR NOW:: all functions in the global
    //           scope are ignored

    int lineNo = get_line_no();

    char* start = cur;

    bool isVirtual = false;
    while( *cur != '(' )
    {
        if ( get_token_str( cur ) == "virtual" )
            isVirtual = true;

        skip_token( cur );
        if ( !get_next_token( cur ) ) return false;
    }

    char* bracketPos = cur;
    char* savedPos   = cur + 1;

    int tmpLnNo;
    store_line_no( tmpLnNo );

    // skip gap between function name and start of paramters list
    while ( *(cur-1) == ' ' )
        --cur;

    // check if it's not a macro, and let plugin handle it, if so

    if ( mpPlugin )
    {
        skip_token_back( cur );

        char* tmp = cur;

        if ( mpPlugin->CanUnderstandContext( tmp, _gSrcEnd, mpCurCtx ) )
        {
            cur = tmp;

            mpPlugin->ParseContext( _gSrcStart, cur, _gSrcEnd, mpCurCtx );

            isAMacro = true;

            return false;
        }
    }

    spOperation* pOp = new spOperation();

    pOp->mSrcLineNo    = lineNo;
    pOp->mSrcOffset    = int( start - _gSrcStart );
    pOp->mHeaderLength = int( bracketPos - start );
    if ( mpCurCtx->GetContextType() == SP_CTX_CLASS )
        pOp->mScope = mpCurCtx->m_Name;

    mpCurCtx->AddMember( pOp );
    pOp->mVisibility = mCurVis;
    pOp->mIsVirtual = isVirtual;

    // add comments about operation
    AttachComments( *pOp, cur );

    // go backwards to method name
    skip_token_back( cur );

    pOp->m_Name = get_token_str( cur );

    // checker whether it's not an operator
    char chFirst = *pOp->m_Name.c_str();
    if ( !isalpha(chFirst) && chFirst != '_' && chFirst != '~' ) {
        // skip 'operator'
        skip_next_token_back( cur );
        skip_token_back( cur );

        wxString lastToken = get_token_str( cur );
        if ( lastToken == "operator" ) {
            lastToken += pOp->m_Name;
            pOp->m_Name = lastToken;
        }
        else {
            // ok, it wasn't an operator after all
            skip_token( cur );
        }
    }
    else if ( pOp->m_Name == "operator" ) {
        skip_token( cur );
        get_next_token( cur );
        wxString oper = get_token_str( cur );

        pOp->m_Name += oper;
    }

    // go backwards to method return type
    skip_next_token_back( cur );

    if ( cur >= start )
    {
        wxString rettype = wxString( start, size_t( cur-start ) );
        // FIXME just for now...
        wxString::size_type pos = 0;
        wxString toerase("WXDLLEXPORT ");
        while((pos = rettype.find(toerase, pos)) != wxString::npos)
            rettype.erase(pos, toerase.length());
        pOp->m_RetType = rettype;
    }

    arrange_indirection_tokens_between( pOp->m_RetType, pOp->m_Name );

    cur = savedPos;
    restore_line_no( tmpLnNo );

    // now, enter operation context
    mpCurCtx = pOp;

    return true;
}

bool CJSourceParser::ParseArguments( char*& cur )
{
    // DANGER-MACROS::

    // now cursor position is right after the first opening bracket
    // of the function declaration

    char* blocks    [16]; // used exclusivelly for iterative "lean out"
                          // of macros and misc. not-obviouse grammar
                          // (dirty,, but we cannot do it very nice,
                          //  we're not preprocessor-free C/C++ code)
    int   blockSizes[16];

    do
    {
        size_t blocksSkipped = 0;

        get_next_token( cur );

        bool first_blk = true;

        while( *cur != ')' && *cur != ',' )
        {
            blocks[blocksSkipped] = cur;

            if ( first_blk )
            {
                char* prev = cur;
                skip_token( cur );

                blockSizes[blocksSkipped] = size_t(cur-prev);

                first_blk = 0;
            }
            else
                blockSizes[blocksSkipped] = skip_block( cur );

            get_next_token( cur );
            ++blocksSkipped;
        }


        if ( blocksSkipped == 1 )
        {
            // check if the empty arg. list stressed with "void" inside
            if ( cmp_tokens_fast( blocks[0] , "void", 4 ) )
            {
                cur++;  // skip ')'

                break;
            }

            // FIXME:: TBD:: K&R-style function declarations!

            // if only one block enclosed, than it's probably
            // some macro, there should be at least two blocks,
            // one for argument type and another for it's identifier
            return false;
        }

        if ( blocksSkipped == 0 )
        {
            if ( *cur == 10 ) ++_gLineNo;
            ++cur; // skip ')'

            break; // function without paramters
        }

        // we should be in the operation context now
        spOperation* pOp = (spOperation*)mpCurCtx;

        spParameter* pPar = new spParameter();

        pOp->AddMember( pPar );
        // FOR NOW:: line number is not exact if argument list is mutiline
        pPar->mSrcLineNo = get_line_no();

        size_t nameBlock = blocksSkipped - 1;
        size_t typeBlock = nameBlock - 1;

        // check if default values present
        if ( *blocks[typeBlock] == '=' )
        {

⌨️ 快捷键说明

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