📄 cjparser.cpp
字号:
// 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 + -