If you look at the source code of the parser in our C::B's code, you will see such code:
void ParserThread::HandleFunction(wxString& name, bool isOperator, bool isPointer)
{
TRACE(_T("HandleFunction() : Adding function '")+name+_T("': m_Str='")+m_Str+_T("'"));
int lineNr = m_Tokenizer.GetLineNumber();
wxString args = m_Tokenizer.GetToken();
wxString peek = m_Tokenizer.PeekToken();
TRACE(_T("HandleFunction() : name='")+name+_T("', args='")+args+_T("', peek='")+peek+_T("'"));
// special case for function pointers
if (isPointer)
{
int pos = name.find(ParserConsts::ptr);
// pattern: m_Str AAA (*BBB) (...);
// pattern: m_Str AAA (*BBB) (...) = some_function;
if (pos != wxNOT_FOUND && (peek == ParserConsts::semicolon || peek == ParserConsts::equals))
{
name.RemoveLast(); // remove ")"
name.Remove(0, pos+1).Trim(false); // remove "(* "
// pattern: m_Str AAA (*BBB[X][Y]) (...);
// Trim(true) for safety, in case the name contains a trailing space
pos = name.find(ParserConsts::oparray_chr);
if (pos != wxNOT_FOUND)
name.Remove(pos).Trim(true);
TRACE(_T("HandleFunction() : Add token name='")+name+_T("', args='")+args+_T("', return type='") + m_Str+ _T("'"));
Token* newToken = DoAddToken(tkFunction, name, lineNr, 0, 0, args);
if (newToken)
{
newToken->m_IsConst = false;
newToken->m_TemplateArgument = m_TemplateArgument;
if (!m_TemplateArgument.IsEmpty() && newToken->m_TemplateMap.empty())
ResolveTemplateArgs(newToken);
}
else
{
TRACE(_T("HandleFunction() : Unable to create/add new token: ") + name);
}
m_TemplateArgument.Clear();
}
return;
}
if (!m_Str.StartsWith(ParserConsts::kw_friend))
{
int lineStart = 0;
int lineEnd = 0;
bool isCtor = m_Str.IsEmpty();
bool isDtor = m_Str.StartsWith(ParserConsts::tilde);
Token* localParent = 0;
if ((isCtor || isDtor) && !m_EncounteredTypeNamespaces.empty())
{
// probably a ctor/dtor
std::queue<wxString> q = m_EncounteredTypeNamespaces; // preserve m_EncounteredTypeNamespaces; needed in DoAddToken()
localParent = FindTokenFromQueue(q, m_LastParent);
TRACE(_T("HandleFunction() : Ctor/Dtor '%s', m_Str='%s', localParent='%s'"),
name.wx_str(),
m_Str.wx_str(),
localParent ? localParent->m_Name.wx_str() : _T("<none>"));
}
else
{
std::queue<wxString> q = m_EncounteredNamespaces; // preserve m_EncounteredNamespaces; needed in DoAddToken()
localParent = FindTokenFromQueue(q, m_LastParent);
TRACE(_T("HandleFunction() : !(Ctor/Dtor) '%s', m_Str='%s', localParent='%s'"),
name.wx_str(),
m_Str.wx_str(),
localParent ? localParent->m_Name.wx_str() : _T("<none>"));
}
bool isCtorOrDtor = m_LastParent && name == m_LastParent->m_Name;
if (!isCtorOrDtor)
isCtorOrDtor = localParent && name == localParent->m_Name;
if (!isCtorOrDtor && m_Options.useBuffer)
isCtorOrDtor = isCtor || isDtor;
TRACE(_T("HandleFunction() : Adding function '%s', ': m_Str='%s', enc_ns='%s'."),
name.wx_str(),
m_Str.wx_str(),
m_EncounteredNamespaces.size() ? m_EncounteredNamespaces.front().wx_str() : wxT("nil"));
bool isImpl = false;
bool isConst = false;
bool isNoExcept = false;
while (!peek.IsEmpty()) // !eof
{
if (peek == ParserConsts::colon) // probably a ctor with member initializers
{
SkipToOneOfChars(ParserConsts::opbrace);
m_Tokenizer.UngetToken(); // leave brace there
peek = m_Tokenizer.PeekToken();
continue;
}
else if (peek == ParserConsts::opbrace)// function implementation
{
isImpl = true;
m_Tokenizer.GetToken(); // eat {
lineStart = m_Tokenizer.GetLineNumber();
SkipBlock(); // skip to matching }
lineEnd = m_Tokenizer.GetLineNumber();
break;
}
else if (peek == ParserConsts::clbrace || peek == ParserConsts::semicolon)
break; // function decl
Now, you can see the last line is: if we see a semicolon, we found a "function declaration". So the best fix is adding the handling of the colon.