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

📄 cjparser.cpp

📁 wxGTK 是 wxWidgets 的 linux GTK+ (>2.2.3)版本。wxWidgets 是一个跨平台的 GUI 框架
💻 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 + -