📄 cjparser.cpp
字号:
// expressions like "int = 5" are ignored,
// since name for paramters is required
if ( blocksSkipped == 3 )
{
if ( *cur == ')' )
{
++cur;
break;
}
else
continue;
}
pPar->m_InitVal = wxString( blocks[nameBlock], blockSizes[nameBlock] );
nameBlock = nameBlock - 2; // skip '=' token and default value block
typeBlock = nameBlock - 1;
}
// attach comments about the parameter
AttachComments( *pPar, blocks[nameBlock] );
// retrieve argument name
pPar->m_Name = wxString( blocks[nameBlock], blockSizes[nameBlock] );
// retreive argument type
size_t len = blockSizes[ typeBlock ];
len = size_t ( (blocks[ typeBlock ] + len) - blocks[ 0 ] );
pPar->m_Type = wxString( blocks[0], len );
arrange_indirection_tokens_between( pPar->m_Type, pPar->m_Name );
if ( *cur == ')' )
{
++cur;
break;
}
++cur; // skip comma
get_next_token(cur);
} while(1);
// skip possible whitespace between ')' and following "const"
while ( isspace(*cur) )
cur++;
// check if it was really a function not a macro,
// if so, than it should be terminated with semicolon ';'
// or opening implemenetaton bracket '{'
char* tok = cur;
int tmpLnNo;
store_line_no( tmpLnNo );
bool result = true;
do
{
if ( *tok == '{' || *tok == ';' )
{
restore_line_no(tmpLnNo);
break;
}
// check for unexpected tokens
if ( *tok == '=' || *tok == '0' )
{
skip_token(tok);
if ( !get_next_token(tok) ) return false;
continue;
}
if ( *tok == '}' ) return false;
// if initialization list found
if ( *tok == ':' )
{
restore_line_no(tmpLnNo);
break;
}
if ( cmp_tokens_fast( tok, "const", 5 ) )
{
((spOperation*)mpCurCtx)->mIsConstant = true;
skip_token(tok);
if ( !get_next_token(tok) ) return false;
continue;
}
if ( CheckVisibilty( tok ) ) return false;
// if next context found
if ( is_keyword( tok ) ) return false;
skip_token(tok);
if ( !get_next_token(tok) ) return false;
} while(1);
return result;
}
void CJSourceParser::ParseMemberVar( char*& cur )
{
MMemberListT& members = mpCurCtx->GetMembers();
bool firstMember = true;
wxString type;
// jump to the end of statement
// and start collecting same-type varibles
// back-to-front towards the type identifier
skip_statement( cur );
char* savedPos = cur;
int tmpLnNo;
store_line_no( tmpLnNo );
--cur; // rewind back to ';'
do
{
spAttribute* pAttr = new spAttribute();
// FOR NOW:: line not is not exact, if member declaration is multiline
pAttr->mSrcLineNo = get_line_no();
mpCurCtx->AddMember( pAttr );
pAttr->mVisibility = mCurVis;
pAttr->mIsConstant = 0;
if ( firstMember )
{
firstMember = 0;
}
skip_token_back( cur );
// attach comments about the attribute
AttachComments( *pAttr, cur );
pAttr->m_Name = get_token_str( cur );
// guessing that this going to be variable type
skip_next_token_back( cur );
skip_token_back( cur );
pAttr->m_Type = get_token_str( cur );
// if comma, than variable list continues
// otherwise the variable type reached - stop
if ( *cur == _T('=') )
{
// yes, we've mistaken, it was not a identifier,
// but it's default value
pAttr->m_InitVal = pAttr->m_Name;
// skip default value and '=' symbol
skip_next_token_back( cur );
skip_token_back( cur );
pAttr->m_Name = get_token_str( cur );
skip_next_token_back( cur );
skip_token_back( cur );
}
if ( *cur != ',' )
{
type = get_token_str( cur );
break;
}
} while(1);
size_t first = 0;
// set up types for all collected (same-type) attributes;
while ( first != members.size() - 1 )
{
spAttribute* pAttr = members[first++]->CastToAttribute();
if ( !pAttr )
continue;
if ( pAttr->m_Type.empty() )
pAttr->m_Type = type;
pAttr->mVisibility = mCurVis;
if ( !pAttr->m_Name.empty() )
arrange_indirection_tokens_between( pAttr->m_Type, pAttr->m_Name );
}
cur = savedPos;
restore_line_no( tmpLnNo );
clear_commets_queue();
}
void CJSourceParser::SkipFunction( char*& cur )
{
while ( *cur != '(' && cur < _gSrcEnd )
{
if (*cur == 10 ) ++_gLineNo;
++cur;
}
skip_next_token_back( cur ); // go back and skip function identifier
skip_token_back( cur ); // go back and skip return type
skip_block( cur ); // now, go ahead and skip whole declaration
SkipFunctionBody( cur );
}
void CJSourceParser::SkipFunctionBody( char*& cur )
{
// FIXME:: check for comments and quoted stirngs here
bool hasDefinition = false;
while( *cur != '{' && *cur != ';' )
{
if (*cur == 10 ) ++_gLineNo;
++cur;
}
if ( *cur == ';' )
{
++cur;
}
else
{
hasDefinition = true;
skip_scope_block( cur ); // skip the whole imp.
}
if ( mpCurCtx->GetType() == SP_CTX_OPERATION )
{
spOperation& op = *((spOperation*)mpCurCtx);
int curOfs = int ( cur - _gSrcStart );
op.mContextLength = curOfs - mpCurCtx->mSrcOffset;
op.mHasDefinition = hasDefinition;
// separate scope resolution token from the name of operation
for( size_t i = 0; i != op.m_Name.length(); ++i )
{
if ( op.m_Name[i] == ':' && op.m_Name[i+1] == ':' )
{
wxString unscoped( op.m_Name, i+2, op.m_Name.length() - ( i + 2 ) );
op.mScope = wxString( op.m_Name, 0, i );
op.m_Name = unscoped;
break;
}
}
}
}
bool CJSourceParser::CheckVisibilty( char*& cur )
{
size_t len = get_token_len( cur );
if ( cmp_tokens_fast( cur, "public:", len ) )
{
mCurVis = SP_VIS_PUBLIC;
return true;
}
if ( cmp_tokens_fast( cur, "protected:", len ) )
{
mCurVis = SP_VIS_PROTECTED;
return true;
}
if ( cmp_tokens_fast( cur, "private:", len ) )
{
mCurVis = SP_VIS_PRIVATE;
return true;
}
return false;
}
void CJSourceParser::AddClassNode( char*& cur )
{
char* ctxStart = cur;
wxString classkeyword = get_token_str( cur );
skip_token( cur ); // skip 'class' keyword
if ( !get_next_token( cur ) ) return;
// in C++
if ( *cur == ':' )
{
skip_token( cur );
get_next_token( cur );
}
// by default all class members are private
mCurVis = SP_VIS_PRIVATE;
spClass* pClass = new spClass();
if ( classkeyword == "class" )
pClass->mClassSubType = SP_CLTYPE_CLASS;
else if ( classkeyword == "struct" ) {
pClass->mClassSubType = SP_CLTYPE_STRUCTURE;
mCurVis = SP_VIS_PUBLIC;
}
else if ( classkeyword == "union" ) {
pClass->mClassSubType = SP_CLTYPE_UNION;
mCurVis = SP_VIS_PUBLIC;
}
else if ( classkeyword == "interface" )
pClass->mClassSubType = SP_CLTYPE_INTERFACE;
else {
pClass->mClassSubType = SP_CLTYPE_INVALID;
wxFAIL_MSG("unknown class keyword");
}
mpCurCtx->AddMember( pClass );
// attach comments about the class
AttachComments( *pClass, cur );
pClass->mSrcLineNo = get_line_no();
pClass->mSrcOffset = int( ctxStart - _gSrcStart );
char* nameTok = cur;
pClass->m_Name = get_token_str( cur );
bool isDerived = 0;
// DANGER-MACROS::
do
{
skip_token( cur );
if ( !get_next_token( cur ) ) return;
if ( *cur == ':' )
{
isDerived = 1;
char* tok = cur;
int tmpLn;
store_line_no( tmpLn );
skip_next_token_back( tok );
skip_token_back( tok );
restore_line_no( tmpLn );
// class name should precend ':' colon, thus
// the one which was captured before was
// proablty something else (like __dllexport MyClass : ... )
if ( nameTok != tok )
{
pClass->m_Name = get_token_str( tok );
}
}
if ( *cur == '{' )
break;
if ( *cur == ',' )
continue;
size_t len = get_token_len( cur );
// skip neglectable C++ modifieres
if ( cmp_tokens_fast( cur, "public", len ) )
continue;
if ( cmp_tokens_fast( cur, "protected", len ) )
continue;
if ( cmp_tokens_fast( cur, "private", len ) )
continue;
if ( cmp_tokens_fast( cur, "virtual", len ) )
continue;
// skip neglectable JAVA modifieres
if ( cmp_tokens_fast( cur, "extends", len ) )
{
isDerived = 1;
continue;
}
if ( cmp_tokens_fast( cur, "implements", len ) )
{
isDerived = 1;
continue;
}
// all we need to know is superclass or interface
char* tok = cur;
int tmpLn;
store_line_no( tmpLn );
skip_token(tok);
get_next_token(tok);
restore_line_no( tmpLn );
if ( *tok != ':' && *cur != ':' )
pClass->m_SuperClassNames.push_back( wxString( cur, len ) );
} while(1);
if ( !isDerived )
{
int tmpLn;
store_line_no( tmpLn );
while ( pClass->m_SuperClassNames.size() )
pClass->m_SuperClassNames.erase( &pClass->m_SuperClassNames[0] );
char* tok = cur;
// some non-obviouse token was following "class" keyword -
// we've confused it with class name - thus now we're reverting this mistake
skip_next_token_back( tok );
skip_token_back( tok );
pClass->m_Name = get_token_str( tok );
restore_line_no( tmpLn );
}
++cur; // skip opening curly brace
pClass->mHeaderLength = ( cur - ctxStart );
// now, enter the class context
mpCurCtx = pClass;
clear_commets_queue();
}
void CJSourceParser::AddEnumNode( wxChar*& cur )
{
// now the cursor is at "enum" keyword
wxChar* start = cur;
spEnumeration* pEnum = new spEnumeration();
mpCurCtx->AddMember( pEnum );
pEnum->mSrcLineNo = get_line_no();
AttachComments( *pEnum, cur );
skip_token( cur );
if ( !get_next_token( cur ) ) return;
// check if enumeration has got it's identifier
if ( *cur != '{' )
{
pEnum->m_Name = get_token_str( cur );
}
if ( !skip_imp_block( cur ) ) return;
get_string_between( start, cur, &pEnum->m_EnumContent );
if ( get_next_token(cur) )
{
// check if the identifier if after the {...} block
if ( *cur != ';' )
pEnum->m_Name = get_token_str( cur );
}
clear_commets_queue();
}
void CJSourceParser::AddTypeDefNode( wxChar*& cur )
{
// now the cursor at the token next to "typedef" keyword
if ( !get_next_token(cur) ) return;
wxChar* start = cur;
spTypeDef* pTDef = new spTypeDef();
mpCurCtx->AddMember( pTDef );
pTDef->mSrcLineNo = get_line_no();
AttachComments( *pTDef, cur );
skip_statement( cur );
int tmpLnNo;
store_line_no( tmpLnNo );
wxChar* tok = cur-1;
skip_next_token_back( tok );
wxChar* nameEnd = tok;
skip_token_back( tok );
wxChar* nameStart = tok;
skip_next_token_back( tok );
wxChar* typeEnd = tok;
// check if it's function prototype
if ( *nameStart == ')' )
{
typeEnd = nameStart+1;
// skip argument list
while ( *nameStart != '(' ) --nameStart;
// skip to function type definition
while ( *nameStart != ')' ) --nameStart;
skip_next_token_back( nameStart );
nameEnd = nameStart;
skip_token_back( nameStart );
if ( *nameStart == '*' ) ++nameStart;
}
get_string_between( start, typeEnd, &pTDef->m_OriginalType );
get_string_between( nameStart, nameEnd, &pTDef->m_Name );
clear_commets_queue();
restore_line_no( tmpLnNo );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -