work save
This commit is contained in:
parent
4afe1f4315
commit
f8ab38b634
|
@ -904,18 +904,19 @@ void CppParser::parseHardDefines()
|
|||
});
|
||||
for (const PDefine& define:mPreprocessor.hardDefines()) {
|
||||
addStatement(
|
||||
PStatement(), // defines don't belong to any scope
|
||||
"",
|
||||
"", // define has no type
|
||||
define->name,
|
||||
define->value,
|
||||
define->args,
|
||||
-1,
|
||||
StatementKind::skPreprocessor,
|
||||
StatementScope::ssGlobal,
|
||||
StatementClassScope::scsNone,
|
||||
true,
|
||||
false);
|
||||
PStatement(), // defines don't belong to any scope
|
||||
"",
|
||||
"", // define has no type
|
||||
define->name,
|
||||
define->args,
|
||||
"",
|
||||
define->value,
|
||||
-1,
|
||||
StatementKind::skPreprocessor,
|
||||
StatementScope::ssGlobal,
|
||||
StatementClassScope::scsNone,
|
||||
true,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1133,18 +1134,19 @@ PStatement CppParser::addInheritedStatement(const PStatement& derived, const PSt
|
|||
{
|
||||
|
||||
PStatement statement = addStatement(
|
||||
derived,
|
||||
inherit->fileName,
|
||||
inherit->type, // "Type" is already in use
|
||||
inherit->command,
|
||||
inherit->args,
|
||||
inherit->value,
|
||||
inherit->line,
|
||||
inherit->kind,
|
||||
inherit->scope,
|
||||
access,
|
||||
true,
|
||||
inherit->isStatic);
|
||||
derived,
|
||||
inherit->fileName,
|
||||
inherit->type, // "Type" is already in use
|
||||
inherit->command,
|
||||
inherit->args,
|
||||
inherit->noNameArgs,
|
||||
inherit->value,
|
||||
inherit->line,
|
||||
inherit->kind,
|
||||
inherit->scope,
|
||||
access,
|
||||
true,
|
||||
inherit->isStatic);
|
||||
statement->isInherited = true;
|
||||
return statement;
|
||||
}
|
||||
|
@ -1152,6 +1154,7 @@ PStatement CppParser::addInheritedStatement(const PStatement& derived, const PSt
|
|||
PStatement CppParser::addChildStatement(const PStatement& parent, const QString &fileName,
|
||||
const QString &aType,
|
||||
const QString &command, const QString &args,
|
||||
const QString& noNameArgs,
|
||||
const QString &value, int line, StatementKind kind,
|
||||
const StatementScope& scope, const StatementClassScope& classScope,
|
||||
bool isDefinition, bool isStatic)
|
||||
|
@ -1162,6 +1165,7 @@ PStatement CppParser::addChildStatement(const PStatement& parent, const QString
|
|||
aType,
|
||||
command,
|
||||
args,
|
||||
noNameArgs,
|
||||
value,
|
||||
line,
|
||||
kind,
|
||||
|
@ -1176,6 +1180,7 @@ PStatement CppParser::addStatement(const PStatement& parent,
|
|||
const QString &aType,
|
||||
const QString &command,
|
||||
const QString &args,
|
||||
const QString &noNameArgs,
|
||||
const QString &value,
|
||||
int line, StatementKind kind,
|
||||
const StatementScope& scope,
|
||||
|
@ -1192,13 +1197,11 @@ PStatement CppParser::addStatement(const PStatement& parent,
|
|||
// qDebug()<<command<<fileName<<line<<kind<<parent->fullName;
|
||||
// }
|
||||
|
||||
QString noNameArgs = "";
|
||||
if (kind == StatementKind::skConstructor
|
||||
|| kind == StatementKind::skFunction
|
||||
|| kind == StatementKind::skDestructor
|
||||
|| kind == StatementKind::skVariable
|
||||
) {
|
||||
noNameArgs = removeArgNames(args);
|
||||
//find
|
||||
if (isDefinition) {
|
||||
PStatement oldStatement = findStatementInScope(newCommand,noNameArgs,kind,parent);
|
||||
|
@ -1270,18 +1273,96 @@ PStatement CppParser::addStatement(const PStatement& parent,
|
|||
return result;
|
||||
}
|
||||
|
||||
PStatement CppParser::addStatement(const PStatement &parent, const QString &fileName, const QString &aType, const QString &command, int argStart, int argEnd, const QString &value, int line, StatementKind kind, const StatementScope &scope, const StatementClassScope &classScope, bool isDefinition, bool isStatic)
|
||||
{
|
||||
QString args("(");
|
||||
QString noNameArgs("(");
|
||||
|
||||
int start=argStart+1;
|
||||
bool typeGetted = false;
|
||||
int braceLevel=0;
|
||||
QString word;
|
||||
for (int i=start;i<argEnd;i++) {
|
||||
QChar ch=mTokenizer[i]->text[0];
|
||||
if (this->isLetterChar(ch)) {
|
||||
QString spaces=(i>argStart)?" ":"";
|
||||
args+=spaces;
|
||||
word += mTokenizer[i]->text[0];
|
||||
if (!typeGetted) {
|
||||
noNameArgs+=spaces+word;
|
||||
if (mCppTypeKeywords.contains(word) || !isCppKeyword(word))
|
||||
typeGetted = true;
|
||||
} else {
|
||||
if (isCppKeyword(word)) {
|
||||
noNameArgs+=spaces+word;
|
||||
}
|
||||
}
|
||||
word="";
|
||||
} else if (this->isDigitChar(ch)) {
|
||||
args+=" ";
|
||||
} else {
|
||||
switch(ch.unicode()) {
|
||||
case ',':
|
||||
if (braceLevel==0)
|
||||
typeGetted=false;
|
||||
break;
|
||||
case '{':
|
||||
case '[':
|
||||
case '<':
|
||||
case '(':
|
||||
braceLevel++;
|
||||
break;
|
||||
case '}':
|
||||
case ']':
|
||||
case '>':
|
||||
case ')':
|
||||
braceLevel--;
|
||||
break;
|
||||
//todo: * and & processing
|
||||
case '*':
|
||||
case '&':
|
||||
if (braceLevel==0)
|
||||
word+=ch;
|
||||
break;
|
||||
}
|
||||
noNameArgs+= mTokenizer[i]->text;
|
||||
}
|
||||
args+=mTokenizer[i]->text;
|
||||
}
|
||||
|
||||
args.push_back(")");
|
||||
noNameArgs.push_back(")");
|
||||
return addStatement(
|
||||
parent,
|
||||
fileName,
|
||||
aType,
|
||||
command,
|
||||
args,
|
||||
noNameArgs,
|
||||
value,
|
||||
line,
|
||||
kind,
|
||||
scope,
|
||||
classScope,
|
||||
isDefinition,
|
||||
isStatic);
|
||||
}
|
||||
|
||||
void CppParser::setInheritance(int index, const PStatement& classStatement, bool isStruct)
|
||||
{
|
||||
// Clear it. Assume it is assigned
|
||||
StatementClassScope lastInheritScopeType = StatementClassScope::scsNone;
|
||||
// Assemble a list of statements in text form we inherit from
|
||||
while (true) {
|
||||
StatementClassScope inheritScopeType = getClassScope(index);
|
||||
if (inheritScopeType == StatementClassScope::scsNone) {
|
||||
if (mTokenizer[index]->text.front()!=','
|
||||
&& mTokenizer[index]->text.front()!=':'
|
||||
&& mTokenizer[index]->text.front()!='(') {
|
||||
QString basename = mTokenizer[index]->text;
|
||||
StatementClassScope inheritScopeType = getClassScope(mTokenizer[index]->text);
|
||||
QString currentText = mTokenizer[index]->text;
|
||||
if (currentText=='(') {
|
||||
//skip to matching ')'
|
||||
index=mTokenizer[index]->matchIndex;
|
||||
} else if (inheritScopeType == StatementClassScope::scsNone) {
|
||||
if (currentText.front()!=','
|
||||
&& currentText.front()!=':') {
|
||||
QString basename = currentText;
|
||||
//remove template staff
|
||||
if (basename.endsWith('>')) {
|
||||
int pBegin = basename.indexOf('<');
|
||||
|
@ -1525,7 +1606,8 @@ bool CppParser::checkForKeyword()
|
|||
return st!=SkipType::skNone;
|
||||
}
|
||||
|
||||
bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, bool &isStatic, bool &isFriend)
|
||||
bool CppParser::checkForMethod(QString &sType, QString &sName, int &argStartIndex,
|
||||
int &argEndIndex, , bool &isStatic, bool &isFriend)
|
||||
{
|
||||
PStatement scope = getCurrentScope();
|
||||
|
||||
|
@ -1546,7 +1628,6 @@ bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, b
|
|||
|
||||
sType = ""; // should contain type "int"
|
||||
sName = ""; // should contain function name "foo::function"
|
||||
sArgs = ""; // should contain argument list "(int a)"
|
||||
|
||||
bool bTypeOK = false;
|
||||
bool bNameOK = false;
|
||||
|
@ -1558,20 +1639,34 @@ bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, b
|
|||
// Gather data for the string parts
|
||||
while ((mIndex < mTokenizer.tokenCount()) && !isSeperator(mTokenizer[mIndex]->text[0])) {
|
||||
if ((mIndex + 1 < mTokenizer.tokenCount())
|
||||
&& (mTokenizer[mIndex + 1]->text[0] == '(')) { // and start of a function
|
||||
&& (mTokenizer[mIndex + 1]->text == '(')) { // and start of a function
|
||||
int indexAfter = mTokenizer[mIndex + 1]->matchIndex+1;
|
||||
//it's not a function define
|
||||
if ((mIndex+2 < mTokenizer.tokenCount()) && (mTokenizer[mIndex + 2]->text[0] == ','))
|
||||
if ((indexAfter < mTokenizer.tokenCount()) && (mTokenizer[indexAfter]->text[0] == ','))
|
||||
break;
|
||||
|
||||
if ((mIndex+2 < mTokenizer.tokenCount()) && (mTokenizer[mIndex + 2]->text[0] == ';')) {
|
||||
if (isNotFuncArgs(mTokenizer[mIndex + 1]->text))
|
||||
if ((indexAfter < mTokenizer.tokenCount()) && (mTokenizer[indexAfter]->text[0] == ';')) {
|
||||
//function can only be defined in global/namespaces/classes
|
||||
if (!mCurrentScope.isEmpty()) {
|
||||
PStatement currentScope=mCurrentScope.last();
|
||||
//in namespace, it might be function or object initilization
|
||||
if (currentScope->kind == StatementKind::skNamespace
|
||||
&& isNotFuncArgs(mIndex + 1,mTokenizer[mIndex + 1]->matchIndex)) {
|
||||
break;
|
||||
//not in class, it can't be a valid function definition
|
||||
} else if (currentScope->kind != StatementKind::skClass)
|
||||
break;
|
||||
//variable can't be initialized in class definition, it must be a function
|
||||
} else if (isNotFuncArgs(mIndex + 1,mTokenizer[mIndex + 1]->matchIndex))
|
||||
break;
|
||||
}
|
||||
sName = mTokenizer[mIndex]->text;
|
||||
sArgs = mTokenizer[mIndex + 1]->text;
|
||||
argStartIndex = mIndex+1;
|
||||
argEndIndex = mTokenizer[mIndex + 1]->matchIndex;
|
||||
bTypeOK = !sType.isEmpty();
|
||||
bNameOK = !sName.isEmpty();
|
||||
bArgsOK = !sArgs.isEmpty();
|
||||
bArgsOK = true;
|
||||
mIndex = argEndIndex;
|
||||
|
||||
// Allow constructor/destructor too
|
||||
if (!bTypeOK) {
|
||||
|
@ -1619,7 +1714,6 @@ bool CppParser::checkForMethod(QString &sType, QString &sName, QString &sArgs, b
|
|||
if (bTypeOK && bNameOK && bArgsOK) {
|
||||
sType = sType.trimmed(); // should contain type "int"
|
||||
sName = sName.trimmed(); // should contain function name "foo::function"
|
||||
sArgs = sArgs.trimmed(); // should contain argument list "(int a)"
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
@ -1972,18 +2066,19 @@ void CppParser::handleCatchBlock()
|
|||
}
|
||||
// add a block
|
||||
PStatement block = addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skBlock,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skBlock,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
addSoloScopeLevel(block,startLine,false);
|
||||
if (!mTokenizer[mIndex]->text.contains("..."))
|
||||
scanMethodArgs(block,mTokenizer[mIndex]->text);
|
||||
|
@ -2044,6 +2139,7 @@ void CppParser::handleEnum()
|
|||
enumName,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skEnumClassType,
|
||||
getScope(),
|
||||
|
@ -2058,6 +2154,7 @@ void CppParser::handleEnum()
|
|||
enumName,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skEnumType,
|
||||
getScope(),
|
||||
|
@ -2099,6 +2196,7 @@ void CppParser::handleEnum()
|
|||
cmd,
|
||||
args,
|
||||
"",
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skEnum,
|
||||
getScope(),
|
||||
|
@ -2115,6 +2213,7 @@ void CppParser::handleEnum()
|
|||
cmd,
|
||||
args,
|
||||
"",
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skEnum,
|
||||
getScope(),
|
||||
|
@ -2123,18 +2222,19 @@ void CppParser::handleEnum()
|
|||
false);
|
||||
}
|
||||
addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
lastType,
|
||||
cmd,
|
||||
args,
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skEnum,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
lastType,
|
||||
cmd,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skEnum,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
}
|
||||
}
|
||||
mIndex ++ ;
|
||||
|
@ -2180,6 +2280,7 @@ void CppParser::handleForBlock()
|
|||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skBlock,
|
||||
getScope(),
|
||||
|
@ -2232,7 +2333,7 @@ void CppParser::handleKeyword()
|
|||
}
|
||||
}
|
||||
|
||||
void CppParser::handleMethod(const QString &sType, const QString &sName, const QString &sArgs, bool isStatic, bool isFriend)
|
||||
void CppParser::handleMethod(const QString &sType, const QString &sName, int argStart, int argEnd, bool isStatic, bool isFriend)
|
||||
{
|
||||
bool isValid = true;
|
||||
bool isDeclaration = false; // assume it's not a prototype
|
||||
|
@ -2309,7 +2410,8 @@ void CppParser::handleMethod(const QString &sType, const QString &sName, const Q
|
|||
mCurrentFile,
|
||||
sType,
|
||||
scopelessName,
|
||||
sArgs,
|
||||
argStart,
|
||||
argEnd,
|
||||
"",
|
||||
//mTokenizer[mIndex - 1]^.Line,
|
||||
startLine,
|
||||
|
@ -2330,6 +2432,7 @@ void CppParser::handleMethod(const QString &sType, const QString &sName, const Q
|
|||
"this",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skVariable,
|
||||
StatementScope::ssLocal,
|
||||
|
@ -2344,6 +2447,7 @@ void CppParser::handleMethod(const QString &sType, const QString &sName, const Q
|
|||
"static const char ",
|
||||
"__func__",
|
||||
"[]",
|
||||
"",
|
||||
"\""+scopelessName+"\"",
|
||||
startLine+1,
|
||||
StatementKind::skVariable,
|
||||
|
@ -2357,7 +2461,8 @@ void CppParser::handleMethod(const QString &sType, const QString &sName, const Q
|
|||
mCurrentFile,
|
||||
sType,
|
||||
scopelessName,
|
||||
sArgs,
|
||||
argStart,
|
||||
argEnd,
|
||||
"",
|
||||
//mTokenizer[mIndex - 1]^.Line,
|
||||
startLine,
|
||||
|
@ -2428,6 +2533,7 @@ void CppParser::handleNamespace()
|
|||
aliasName, // name of the alias namespace
|
||||
command, // command
|
||||
"", // args
|
||||
"", // noname args
|
||||
"", // values
|
||||
//mTokenizer[mIndex]^.Line,
|
||||
startLine,
|
||||
|
@ -2452,18 +2558,19 @@ void CppParser::handleNamespace()
|
|||
mIndex++; //skip '{'
|
||||
} else {
|
||||
PStatement namespaceStatement = addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"", // type
|
||||
command, // command
|
||||
"", // args
|
||||
"", // values
|
||||
startLine,
|
||||
StatementKind::skNamespace,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"", // type
|
||||
command, // command
|
||||
"", // args
|
||||
"", // noname args
|
||||
"", // values
|
||||
startLine,
|
||||
StatementKind::skNamespace,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
addSoloScopeLevel(namespaceStatement,startLine);
|
||||
|
||||
// Skip to '{'
|
||||
|
@ -2505,6 +2612,7 @@ void CppParser::handleOtherTypedefs()
|
|||
newType,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skTypedef,
|
||||
getScope(),
|
||||
|
@ -2549,12 +2657,14 @@ void CppParser::handleOtherTypedefs()
|
|||
int p = newType.lastIndexOf(' ');
|
||||
if (p>=0)
|
||||
newType.truncate(p+1);
|
||||
QString args=mTokenizer[mIndex + 1]->text;
|
||||
addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
oldType,
|
||||
newType,
|
||||
mTokenizer[mIndex + 1]->text,
|
||||
args,
|
||||
removeArgNames(args),
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skTypedef,
|
||||
|
@ -2577,6 +2687,7 @@ void CppParser::handleOtherTypedefs()
|
|||
newType,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skTypedef,
|
||||
getScope(),
|
||||
|
@ -2639,43 +2750,46 @@ void CppParser::handlePreprocessor()
|
|||
mPreprocessor.getDefineParts(s,name,args,value);
|
||||
|
||||
addStatement(
|
||||
nullptr, // defines don't belong to any scope
|
||||
mCurrentFile,
|
||||
"", // define has no type
|
||||
name,
|
||||
args,
|
||||
value,
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skPreprocessor,
|
||||
StatementScope::ssGlobal,
|
||||
StatementClassScope::scsNone,
|
||||
true,
|
||||
false);
|
||||
nullptr, // defines don't belong to any scope
|
||||
mCurrentFile,
|
||||
"", // define has no type
|
||||
name,
|
||||
args,
|
||||
"",// noname args
|
||||
value,
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skPreprocessor,
|
||||
StatementScope::ssGlobal,
|
||||
StatementClassScope::scsNone,
|
||||
true,
|
||||
false);
|
||||
} // TODO: undef ( define has limited scope)
|
||||
handlePreprocessorEnd:
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
StatementClassScope CppParser::getClassScope(int index) {
|
||||
if (mTokenizer[index]->text=="public")
|
||||
return StatementClassScope::scsPublic;
|
||||
else if (mTokenizer[index]->text=="private")
|
||||
return StatementClassScope::scsPrivate;
|
||||
else if (mTokenizer[index]->text=="protected")
|
||||
return StatementClassScope::scsProtected;
|
||||
else
|
||||
return StatementClassScope::scsNone;
|
||||
StatementClassScope CppParser::getClassScope(const QString& text) {
|
||||
if (!text.isEmpty() && text[0]=='p') {
|
||||
if (text=="public")
|
||||
return StatementClassScope::scsPublic;
|
||||
else if (text=="private")
|
||||
return StatementClassScope::scsPrivate;
|
||||
else if (text=="protected")
|
||||
return StatementClassScope::scsProtected;
|
||||
}
|
||||
return StatementClassScope::scsNone;
|
||||
}
|
||||
|
||||
void CppParser::handleScope()
|
||||
{
|
||||
mClassScope = getClassScope(mIndex);
|
||||
mClassScope = getClassScope(mTokenizer[mIndex]->text);
|
||||
mIndex+=2; // the scope is followed by a ':'
|
||||
}
|
||||
|
||||
bool CppParser::handleStatement()
|
||||
{
|
||||
QString S1,S2,S3;
|
||||
QString funcType,funcName;
|
||||
int argStart,argEnd;
|
||||
bool isStatic, isFriend;
|
||||
int idx=getCurrentBlockEndSkip();
|
||||
int idx2=getCurrentBlockBeginSkip();
|
||||
|
@ -2701,19 +2815,20 @@ bool CppParser::handleStatement()
|
|||
mIndex++;
|
||||
} else if (mTokenizer[mIndex]->text.startsWith('{')) {
|
||||
PStatement block = addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
//mTokenizer[mIndex]^.Line,
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skBlock,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
//mTokenizer[mIndex]^.Line,
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skBlock,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false);
|
||||
addSoloScopeLevel(block,mTokenizer[mIndex]->line);
|
||||
mIndex++;
|
||||
} else if (mTokenizer[mIndex]->text[0] == '}') {
|
||||
|
@ -2749,8 +2864,8 @@ bool CppParser::handleStatement()
|
|||
handleUsing();
|
||||
} else if (checkForStructs()) {
|
||||
handleStructs(false);
|
||||
} else if (checkForMethod(S1, S2, S3, isStatic, isFriend)) {
|
||||
handleMethod(S1, S2, S3, isStatic, isFriend); // don't recalculate parts
|
||||
} else if (checkForMethod(funcType, funcName, argStart,argEnd, isStatic, isFriend)) {
|
||||
handleMethod(funcType, funcName, argStart, argEnd, isStatic, isFriend); // don't recalculate parts
|
||||
} else if (checkForVar()) {
|
||||
handleVar();
|
||||
} else
|
||||
|
@ -2805,8 +2920,9 @@ void CppParser::handleStructs(bool isTypedef)
|
|||
mCurrentFile,
|
||||
oldType,
|
||||
newType,
|
||||
"",
|
||||
"",
|
||||
"", // args
|
||||
"", // noname args
|
||||
"", // values
|
||||
startLine,
|
||||
StatementKind::skTypedef,
|
||||
getScope(),
|
||||
|
@ -2852,6 +2968,7 @@ void CppParser::handleStructs(bool isTypedef)
|
|||
prefix, // type
|
||||
command, // command
|
||||
"", // args
|
||||
"", // no name args,
|
||||
"", // values
|
||||
startLine,
|
||||
StatementKind::skClass,
|
||||
|
@ -2875,6 +2992,7 @@ void CppParser::handleStructs(bool isTypedef)
|
|||
prefix, // type
|
||||
command, // command
|
||||
"", // args
|
||||
"", // no name args
|
||||
"", // values
|
||||
startLine,
|
||||
StatementKind::skClass,
|
||||
|
@ -2958,6 +3076,7 @@ void CppParser::handleStructs(bool isTypedef)
|
|||
"__"+command,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skClass,
|
||||
getScope(),
|
||||
|
@ -2968,18 +3087,19 @@ void CppParser::handleStructs(bool isTypedef)
|
|||
if (isTypedef) {
|
||||
//typedef
|
||||
addStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
firstSynonym->command,
|
||||
command,
|
||||
"",
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skTypedef,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false); // typedef
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
firstSynonym->command,
|
||||
command,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skTypedef,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
true,
|
||||
false); // typedef
|
||||
} else {
|
||||
//variable define
|
||||
addStatement(
|
||||
|
@ -2989,6 +3109,7 @@ void CppParser::handleStructs(bool isTypedef)
|
|||
command,
|
||||
args,
|
||||
"",
|
||||
"",
|
||||
mTokenizer[i]->line,
|
||||
StatementKind::skVariable,
|
||||
getScope(),
|
||||
|
@ -3019,6 +3140,7 @@ void CppParser::handleStructs(bool isTypedef)
|
|||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
startLine,
|
||||
StatementKind::skBlock,
|
||||
getScope(),
|
||||
|
@ -3064,6 +3186,8 @@ void CppParser::handleUsing()
|
|||
aliasName, // name of the alias (type)
|
||||
fullName, // command
|
||||
"", // args
|
||||
"",
|
||||
"",
|
||||
"", // values
|
||||
startLine,
|
||||
StatementKind::skTypedef,
|
||||
|
@ -3248,19 +3372,20 @@ void CppParser::handleVar()
|
|||
// Add a statement for every struct we are in
|
||||
if (!lastType.isEmpty()) {
|
||||
addChildStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
lastType,
|
||||
cmd,
|
||||
args,
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skVariable,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
//True,
|
||||
!isExtern,
|
||||
isStatic); // TODO: not supported to pass list
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
lastType,
|
||||
cmd,
|
||||
args,
|
||||
"",
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skVariable,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
//True,
|
||||
!isExtern,
|
||||
isStatic); // TODO: not supported to pass list
|
||||
varAdded = true;
|
||||
}
|
||||
}
|
||||
|
@ -3337,6 +3462,7 @@ void CppParser::internalParse(const QString &fileName)
|
|||
if (!handleStatement())
|
||||
break;
|
||||
}
|
||||
mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
||||
#ifdef QT_DEBUG
|
||||
// mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
||||
//
|
||||
|
@ -4361,14 +4487,16 @@ int CppParser::calcKeyLenForStruct(const QString &word)
|
|||
return -1;
|
||||
}
|
||||
|
||||
void CppParser::scanMethodArgs(const PStatement& functionStatement, const QString &argStr)
|
||||
void CppParser::scanMethodArgs(const PStatement& functionStatement, int argStart, int argEnd)
|
||||
{
|
||||
// Split up argument string by ,
|
||||
int i = 1; // assume it starts with ( and ends with )
|
||||
int i = argStart+1; // assume it starts with ( and ends with )
|
||||
int paramStart = i;
|
||||
|
||||
QString args;
|
||||
while (i < argStr.length()) {
|
||||
// Keep going and stop on top of the variable name
|
||||
QString lastType = "";
|
||||
bool isFunctionPointer = false;
|
||||
bool varAdded = false;
|
||||
while (i < argEnd) {
|
||||
if ((argStr[i] == ',') ||
|
||||
((i == argStr.length()-1) && (argStr[i] == ')'))) {
|
||||
// We've found "int* a" for example
|
||||
|
@ -4380,14 +4508,8 @@ void CppParser::scanMethodArgs(const PStatement& functionStatement, const QStrin
|
|||
s.truncate(assignPos);
|
||||
s = s.trimmed();
|
||||
}
|
||||
// we don't support function pointer parameters now, till we can tokenize function parameters
|
||||
// {
|
||||
// // Can be a function pointer. If so, scan after last )
|
||||
// BracePos := LastPos(')', S);
|
||||
// if (BracePos > 0) then // it's a function pointer... begin
|
||||
// SpacePos := LastPos(' ', Copy(S, BracePos, MaxInt)) // start search at brace
|
||||
// end else begin
|
||||
// }
|
||||
//todo: we don't support function pointer parameters now, till we can tokenize function parameters
|
||||
|
||||
//skip []
|
||||
int varEndPos = s.length()-1;
|
||||
int bracketLevel = 0;
|
||||
|
@ -4442,6 +4564,162 @@ void CppParser::scanMethodArgs(const PStatement& functionStatement, const QStrin
|
|||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if ((mIndex + 2 < mTokenizer.tokenCount())
|
||||
&& (mTokenizer[mIndex + 1]->text.front() == '(')
|
||||
&& (mTokenizer[mIndex + 2]->text.front() == '(')) {
|
||||
isFunctionPointer = mTokenizer[mIndex + 1]->text.indexOf('*') >= 0;
|
||||
if (!isFunctionPointer)
|
||||
break; // inline constructor
|
||||
} else if ((mIndex + 1 < mTokenizer.tokenCount())
|
||||
&& (mTokenizer[mIndex + 1]->text.front()=='('
|
||||
|| mTokenizer[mIndex + 1]->text.front()==','
|
||||
|| mTokenizer[mIndex + 1]->text.front()==';'
|
||||
|| mTokenizer[mIndex + 1]->text.front()==':'
|
||||
|| mTokenizer[mIndex + 1]->text.front()=='}'
|
||||
|| mTokenizer[mIndex + 1]->text.front()=='#'
|
||||
|| mTokenizer[mIndex + 1]->text.front()=='{')) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// we've made a mistake, this is a typedef , not a variable definition.
|
||||
if (mTokenizer[mIndex]->text == "typedef")
|
||||
return;
|
||||
|
||||
// struct/class/union is part of the type signature
|
||||
// but we dont store it in the type cache, so must trim it to find the type info
|
||||
if (mTokenizer[mIndex]->text!="struct"
|
||||
&& mTokenizer[mIndex]->text!="class"
|
||||
&& mTokenizer[mIndex]->text!="union") {
|
||||
if (mTokenizer[mIndex]->text == ':') {
|
||||
lastType += ':';
|
||||
} else {
|
||||
QString s=expandMacroType(mTokenizer[mIndex]->text);
|
||||
if (s == "extern") {
|
||||
isExtern = true;
|
||||
} else {
|
||||
if (!s.isEmpty())
|
||||
lastType += ' '+s;
|
||||
if (s == "static")
|
||||
isStatic = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
mIndex++;
|
||||
if(mIndex >= mTokenizer.tokenCount())
|
||||
break;
|
||||
if (isFunctionPointer)
|
||||
break;
|
||||
}
|
||||
lastType = lastType.trimmed();
|
||||
|
||||
// Don't bother entering the scanning loop when we have failed
|
||||
if (mIndex >= mTokenizer.tokenCount())
|
||||
return;
|
||||
|
||||
// Find the variable name
|
||||
while (true) {
|
||||
|
||||
// Skip bit identifiers,
|
||||
// e.g.:
|
||||
// handle
|
||||
// unsigned short bAppReturnCode:8,reserved:6,fBusy:1,fAck:1
|
||||
// as
|
||||
// unsigned short bAppReturnCode,reserved,fBusy,fAck
|
||||
if ( (mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() == ':')) {
|
||||
while ( (mIndex < mTokenizer.tokenCount())
|
||||
&& !(
|
||||
mTokenizer[mIndex]->text.front() == ','
|
||||
|| isblockChar(';')
|
||||
))
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
// Skip inline constructors,
|
||||
// e.g.:
|
||||
// handle
|
||||
// int a(3)
|
||||
// as
|
||||
// int a
|
||||
if (!isFunctionPointer &&
|
||||
mIndex < mTokenizer.tokenCount() &&
|
||||
mTokenizer[mIndex]->text.front() == '(') {
|
||||
while ((mIndex < mTokenizer.tokenCount())
|
||||
&& !(
|
||||
mTokenizer[mIndex]->text.front() == ','
|
||||
|| isblockChar(mTokenizer[mIndex]->text.front())
|
||||
))
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
// Did we stop on top of the variable name?
|
||||
if (mIndex < mTokenizer.tokenCount()) {
|
||||
if (mTokenizer[mIndex]->text.front()!=','
|
||||
&& mTokenizer[mIndex]->text.front()!=';') {
|
||||
QString cmd;
|
||||
QString args;
|
||||
if (isFunctionPointer && (mIndex + 1 < mTokenizer.tokenCount())) {
|
||||
QString s = mTokenizer[mIndex]->text;
|
||||
cmd = s.mid(2,s.length()-3).trimmed(); // (*foo) -> foo
|
||||
args = mTokenizer[mIndex + 1]->text; // (int a,int b)
|
||||
lastType += "(*)" + args; // void(int a,int b)
|
||||
mIndex++;
|
||||
} else if (mTokenizer[mIndex]->text.back() == ']') { //array; break args
|
||||
int pos = mTokenizer[mIndex]->text.indexOf('[');
|
||||
cmd = mTokenizer[mIndex]->text.mid(0,pos);
|
||||
args = mTokenizer[mIndex]->text.mid(pos);
|
||||
} else {
|
||||
cmd = mTokenizer[mIndex]->text;
|
||||
args = "";
|
||||
}
|
||||
|
||||
// Add a statement for every struct we are in
|
||||
if (!lastType.isEmpty()) {
|
||||
addChildStatement(
|
||||
getCurrentScope(),
|
||||
mCurrentFile,
|
||||
lastType,
|
||||
cmd,
|
||||
args,
|
||||
"",
|
||||
"",
|
||||
mTokenizer[mIndex]->line,
|
||||
StatementKind::skVariable,
|
||||
getScope(),
|
||||
mClassScope,
|
||||
//True,
|
||||
!isExtern,
|
||||
isStatic); // TODO: not supported to pass list
|
||||
varAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Step over the variable name
|
||||
if (isblockChar(mTokenizer[mIndex]->text.front())) {
|
||||
break;
|
||||
}
|
||||
mIndex++;
|
||||
}
|
||||
if (mIndex >= mTokenizer.tokenCount())
|
||||
break;
|
||||
if (isblockChar(mTokenizer[mIndex]->text.front()))
|
||||
break;
|
||||
}
|
||||
if (varAdded && (mIndex < mTokenizer.tokenCount())
|
||||
&& (mTokenizer[mIndex]->text == '{')) {
|
||||
// skip { } like A x {new A};
|
||||
int i=skipBraces(mIndex);
|
||||
if (i!=mIndex)
|
||||
mIndex = i+1;
|
||||
}
|
||||
// Skip ; and ,
|
||||
if ( (mIndex < mTokenizer.tokenCount()) &&
|
||||
(mTokenizer[mIndex]->text.front() == ';'
|
||||
|| mTokenizer[mIndex]->text.front() == ','))
|
||||
mIndex++;
|
||||
|
||||
}
|
||||
|
||||
QString CppParser::splitPhrase(const QString &phrase, QString &sClazz,
|
||||
|
@ -4622,50 +4900,43 @@ QString CppParser::removeArgNames(const QString &args)
|
|||
return result;
|
||||
}
|
||||
|
||||
bool CppParser::isNotFuncArgs(const QString &args)
|
||||
bool CppParser::isNotFuncArgs(int startIndex, int endIndex)
|
||||
{
|
||||
int i=1; //skip '('
|
||||
int endPos = args.length()-1;//skip ')'
|
||||
bool lastCharIsId=false;
|
||||
//no args, it must be a function
|
||||
if (endIndex-startIndex==1)
|
||||
return false;
|
||||
int i=startIndex+1; //skip '('
|
||||
int endPos = endIndex;
|
||||
QString word = "";
|
||||
while (i<endPos) {
|
||||
if (args[i] == '"' || args[i]=='\'') {
|
||||
// args contains a string/char, can't be a func define
|
||||
QChar ch=mTokenizer[i]->text[0];
|
||||
switch(ch.unicode()) {
|
||||
// args contains a string/char, can't be a func define
|
||||
case '"':
|
||||
case '\'':
|
||||
return true;
|
||||
} else if ( isLetterChar(args[i])) {
|
||||
word += args[i];
|
||||
lastCharIsId = true;
|
||||
i++;
|
||||
} else if ((args[i] == ':') && (args[i+1] == ':')) {
|
||||
lastCharIsId = false;
|
||||
word += "::";
|
||||
i+=2;
|
||||
} else if (isDigitChar(args[i])) {
|
||||
if (!lastCharIsId)
|
||||
case '(':
|
||||
case '[':
|
||||
case '{':
|
||||
i=mTokenizer[i]->matchIndex+1;
|
||||
continue;
|
||||
}
|
||||
if (isDigitChar(ch))
|
||||
return true;
|
||||
if (isLetterChar(ch)) {
|
||||
QString currentText=mTokenizer[i]->text;
|
||||
if (currentText=="true" || currentText=="false" || currentText=="nullptr"
|
||||
|| currentText=="const")
|
||||
return true;
|
||||
word+=args[i];
|
||||
i++;
|
||||
} else if (isSpaceChar(args[i]) || isLineChar(args[i])) {
|
||||
if (!word.isEmpty())
|
||||
break;
|
||||
i++;
|
||||
} else if (word.isEmpty()) {
|
||||
return true;
|
||||
} else
|
||||
break;
|
||||
PStatement statement =findStatementOf(mCurrentFile,word,getCurrentScope(),true);
|
||||
if (statement &&
|
||||
!isTypeStatement(statement->kind))
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
//function with no args
|
||||
if (i>endPos && word.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isCppKeyword(word)) {
|
||||
return word == "true" || word == "false" || word == "nullptr";
|
||||
}
|
||||
PStatement statement =findStatementOf(mCurrentFile,word,getCurrentScope(),true);
|
||||
if (statement &&
|
||||
!isTypeStatement(statement->kind))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ private:
|
|||
const QString& aType, // "Type" is already in use
|
||||
const QString& command,
|
||||
const QString& args,
|
||||
const QString& noNameArgs,
|
||||
const QString& value,
|
||||
int line,
|
||||
StatementKind kind,
|
||||
|
@ -173,6 +174,21 @@ private:
|
|||
const QString &aType, // "Type" is already in use
|
||||
const QString &command,
|
||||
const QString &args,
|
||||
const QString &noNameArgs,
|
||||
const QString& value,
|
||||
int line,
|
||||
StatementKind kind,
|
||||
const StatementScope& scope,
|
||||
const StatementClassScope& classScope,
|
||||
bool isDefinition,
|
||||
bool isStatic);
|
||||
PStatement addStatement(
|
||||
const PStatement& parent,
|
||||
const QString &fileName,
|
||||
const QString &aType, // "Type" is already in use
|
||||
const QString &command,
|
||||
int argStart,
|
||||
int argEnd,
|
||||
const QString& value,
|
||||
int line,
|
||||
StatementKind kind,
|
||||
|
@ -195,8 +211,8 @@ private:
|
|||
bool checkForEnum();
|
||||
bool checkForForBlock();
|
||||
bool checkForKeyword();
|
||||
bool checkForMethod(QString &sType, QString &sName, QString &sArgs,
|
||||
bool &isStatic, bool &isFriend); // caching of results
|
||||
bool checkForMethod(QString &sType, QString &sName, int &argStartIndex,
|
||||
int &argEndIndex, bool &isStatic, bool &isFriend); // caching of results
|
||||
bool checkForNamespace();
|
||||
bool checkForPreprocessor();
|
||||
bool checkForScope();
|
||||
|
@ -343,7 +359,7 @@ private:
|
|||
int& pointerLevel);
|
||||
|
||||
int getBracketEnd(const QString& s, int startAt);
|
||||
StatementClassScope getClassScope(int index);
|
||||
StatementClassScope getClassScope(const QString& text);
|
||||
int getCurrentBlockBeginSkip();
|
||||
int getCurrentBlockEndSkip();
|
||||
int getCurrentInlineNamespaceEndSkip();
|
||||
|
@ -376,7 +392,8 @@ private:
|
|||
void handleMethod(
|
||||
const QString& sType,
|
||||
const QString& sName,
|
||||
const QString& sArgs,
|
||||
int argStart,
|
||||
int argEnd,
|
||||
bool isStatic,
|
||||
bool isFriend);
|
||||
void handleNamespace();
|
||||
|
@ -410,7 +427,8 @@ private:
|
|||
// }
|
||||
void scanMethodArgs(
|
||||
const PStatement& functionStatement,
|
||||
const QString& argStr);
|
||||
int argStart,
|
||||
int argEnd);
|
||||
QString splitPhrase(const QString& phrase, QString& sClazz,
|
||||
QString& sOperator, QString &sMember);
|
||||
|
||||
|
@ -493,7 +511,7 @@ private:
|
|||
return ch=='\n' || ch=='\r';
|
||||
}
|
||||
|
||||
bool isNotFuncArgs(const QString& args);
|
||||
bool isNotFuncArgs(int startIndex, int endIndex);
|
||||
|
||||
/**
|
||||
* @brief Test if a statement is a class/struct/union/namespace/function
|
||||
|
|
|
@ -30,6 +30,9 @@ void CppTokenizer::clear()
|
|||
mBuffer.clear();
|
||||
mBufferStr.clear();
|
||||
mLastToken.clear();
|
||||
mUnmatchedBraces.clear();
|
||||
mUnmatchedBrackets.clear();
|
||||
mUnmatchedParenthesis.clear();
|
||||
}
|
||||
|
||||
void CppTokenizer::tokenize(const QStringList &buffer)
|
||||
|
@ -48,16 +51,26 @@ void CppTokenizer::tokenize(const QStringList &buffer)
|
|||
mCurrent = mStart;
|
||||
mLineCount = mStart;
|
||||
QString s = "";
|
||||
bool bSkipBlocks = false;
|
||||
mCurrentLine = 1;
|
||||
|
||||
TokenType tokenType;
|
||||
while (true) {
|
||||
mLastToken = s;
|
||||
s = getNextToken(true, true, bSkipBlocks);
|
||||
s = getNextToken(&tokenType, true, false);
|
||||
simplify(s);
|
||||
if (s.isEmpty())
|
||||
break;
|
||||
else
|
||||
addToken(s,mCurrentLine);
|
||||
addToken(s,mCurrentLine,tokenType);
|
||||
}
|
||||
while (!mUnmatchedBraces.isEmpty()) {
|
||||
mTokenList[mUnmatchedBraces.back()]->matchIndex=mTokenList.count()-1;
|
||||
}
|
||||
while (!mUnmatchedBrackets.isEmpty()) {
|
||||
mTokenList[mUnmatchedBrackets.back()]->matchIndex=mTokenList.count()-1;
|
||||
}
|
||||
while (!mUnmatchedParenthesis.isEmpty()) {
|
||||
mTokenList[mUnmatchedParenthesis.back()]->matchIndex=mTokenList.count()-1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +81,7 @@ void CppTokenizer::dumpTokens(const QString &fileName)
|
|||
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
QTextStream stream(&file);
|
||||
foreach (const PToken& token,mTokenList) {
|
||||
stream<<QString("%1,%2").arg(token->line).arg(token->text)
|
||||
stream<<QString("%1,%2,%3").arg(token->line).arg(token->text).arg(token->matchIndex)
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||
<<Qt::endl;
|
||||
#else
|
||||
|
@ -93,11 +106,55 @@ int CppTokenizer::tokenCount()
|
|||
return mTokenList.count();
|
||||
}
|
||||
|
||||
void CppTokenizer::addToken(const QString &sText, int iLine)
|
||||
void CppTokenizer::addToken(const QString &sText, int iLine, TokenType tokenType)
|
||||
{
|
||||
PToken token = std::make_shared<Token>();
|
||||
token->text = sText;
|
||||
token->line = iLine;
|
||||
switch(tokenType) {
|
||||
case TokenType::LeftBrace:
|
||||
token->matchIndex=-1;
|
||||
mUnmatchedBraces.push_back(mTokenList.count());
|
||||
break;
|
||||
case TokenType::RightBrace:
|
||||
if (mUnmatchedBraces.isEmpty()) {
|
||||
token->matchIndex=-1;
|
||||
} else {
|
||||
token->matchIndex = mUnmatchedBraces.last();
|
||||
mTokenList[token->matchIndex]->matchIndex=mTokenList.count();
|
||||
mUnmatchedBraces.pop_back();
|
||||
}
|
||||
break;
|
||||
case TokenType::LeftBracket:
|
||||
token->matchIndex=-1;
|
||||
mUnmatchedBrackets.push_back(mTokenList.count());
|
||||
break;
|
||||
case TokenType::RightBracket:
|
||||
if (mUnmatchedBrackets.isEmpty()) {
|
||||
token->matchIndex=-1;
|
||||
} else {
|
||||
token->matchIndex = mUnmatchedBrackets.last();
|
||||
mTokenList[token->matchIndex]->matchIndex=mTokenList.count();
|
||||
mUnmatchedBrackets.pop_back();
|
||||
}
|
||||
break;
|
||||
case TokenType::LeftParenthesis:
|
||||
token->matchIndex=-1;
|
||||
mUnmatchedParenthesis.push_back(mTokenList.count());
|
||||
break;
|
||||
case TokenType::RightParenthesis:
|
||||
if (mUnmatchedParenthesis.isEmpty()) {
|
||||
token->matchIndex=-1;
|
||||
} else {
|
||||
token->matchIndex = mUnmatchedParenthesis.last();
|
||||
mTokenList[token->matchIndex]->matchIndex=mTokenList.count();
|
||||
mUnmatchedParenthesis.pop_back();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mTokenList.append(token);
|
||||
}
|
||||
|
||||
|
@ -139,12 +196,13 @@ QString CppTokenizer::getForInit()
|
|||
// Step into the init statement
|
||||
mCurrent++;
|
||||
|
||||
TokenType tokenType;
|
||||
// Process until ; or end of file
|
||||
while (true) {
|
||||
QString s = getNextToken(true, true, false);
|
||||
QString s = getNextToken(&tokenType, true, false);
|
||||
simplify(s);
|
||||
if (!s.isEmpty())
|
||||
addToken(s,mCurrentLine);
|
||||
addToken(s,mCurrentLine,tokenType);
|
||||
if ( (s == "") || (s == ";") || (s==":"))
|
||||
break;
|
||||
// : is used in for-each loop
|
||||
|
@ -156,10 +214,11 @@ QString CppTokenizer::getForInit()
|
|||
return "";
|
||||
}
|
||||
|
||||
QString CppTokenizer::getNextToken(bool /* bSkipParenthesis */, bool bSkipArray, bool bSkipBlock)
|
||||
QString CppTokenizer::getNextToken(TokenType *pTokenType, bool bSkipArray, bool bSkipBlock)
|
||||
{
|
||||
QString result;
|
||||
bool done = false;
|
||||
*pTokenType=TokenType::Normal;
|
||||
while (true) {
|
||||
skipToNextToken();
|
||||
if (*mCurrent == 0)
|
||||
|
@ -179,10 +238,10 @@ QString CppTokenizer::getNextToken(bool /* bSkipParenthesis */, bool bSkipArray,
|
|||
countLines();
|
||||
result = getForInit();
|
||||
done = (result != "");
|
||||
} else if (isArguments()) {
|
||||
countLines();
|
||||
result = getArguments();
|
||||
done = (result != "");
|
||||
// } else if (isArguments()) {
|
||||
// countLines();
|
||||
// result = getArguments();
|
||||
// done = (result != "");
|
||||
} else if (isWord()) {
|
||||
countLines();
|
||||
result = getWord(false, bSkipArray, bSkipBlock);
|
||||
|
@ -214,7 +273,33 @@ QString CppTokenizer::getNextToken(bool /* bSkipParenthesis */, bool bSkipArray,
|
|||
}
|
||||
break;
|
||||
case '{':
|
||||
*pTokenType=TokenType::LeftBrace;
|
||||
countLines();
|
||||
result = *mCurrent;
|
||||
advance();
|
||||
done = true;
|
||||
break;
|
||||
case '}':
|
||||
*pTokenType=TokenType::RightBrace;
|
||||
countLines();
|
||||
result = *mCurrent;
|
||||
advance();
|
||||
done = true;
|
||||
break;
|
||||
case '(':
|
||||
*pTokenType=TokenType::LeftParenthesis;
|
||||
countLines();
|
||||
result = *mCurrent;
|
||||
advance();
|
||||
done = true;
|
||||
break;
|
||||
case ')':
|
||||
*pTokenType=TokenType::RightParenthesis;
|
||||
countLines();
|
||||
result = *mCurrent;
|
||||
advance();
|
||||
done = true;
|
||||
break;
|
||||
case ';':
|
||||
case ',': //just return the brace or the ';'
|
||||
countLines();
|
||||
|
@ -625,7 +710,7 @@ void CppTokenizer::advance()
|
|||
case '=': {
|
||||
if (mTokenList.size()>2
|
||||
&& mTokenList[mTokenList.size()-2]->text == "using") {
|
||||
addToken("=",mCurrentLine);
|
||||
addToken("=", mCurrentLine, TokenType::Normal);
|
||||
mCurrent++;
|
||||
} else
|
||||
skipAssignment();
|
||||
|
|
|
@ -22,10 +22,22 @@
|
|||
|
||||
class CppTokenizer
|
||||
{
|
||||
enum class TokenType {
|
||||
Normal,
|
||||
LeftBrace,
|
||||
RightBrace,
|
||||
LeftParenthesis,
|
||||
RightParenthesis,
|
||||
LeftBracket,
|
||||
RightBracket,
|
||||
Assignment,
|
||||
};
|
||||
|
||||
public:
|
||||
struct Token {
|
||||
QString text;
|
||||
int line;
|
||||
int matchIndex;
|
||||
};
|
||||
using PToken = std::shared_ptr<Token>;
|
||||
using TokenList = QVector<PToken>;
|
||||
|
@ -39,7 +51,7 @@ public:
|
|||
int tokenCount();
|
||||
bool isIdentChar(const QChar& ch);
|
||||
private:
|
||||
void addToken(const QString& sText, int iLine);
|
||||
void addToken(const QString& sText, int iLine, TokenType tokenType);
|
||||
void advance();
|
||||
void countLines();
|
||||
PToken getToken(int index);
|
||||
|
@ -47,7 +59,7 @@ private:
|
|||
QString getArguments();
|
||||
QString getForInit();
|
||||
QString getNextToken(
|
||||
bool bSkipParenthesis = false,
|
||||
TokenType *pTokenType,
|
||||
bool bSkipArray = false,
|
||||
bool bSkipBlock = false);
|
||||
QString getNumber();
|
||||
|
@ -92,6 +104,9 @@ private:
|
|||
int mCurrentLine;
|
||||
QString mLastToken;
|
||||
TokenList mTokenList;
|
||||
QList<int> mUnmatchedBraces; // stack of indices for unmatched '{'
|
||||
QList<int> mUnmatchedBrackets; // stack of indices for unmatched '['
|
||||
QList<int> mUnmatchedParenthesis;// stack of indices for unmatched '('
|
||||
};
|
||||
|
||||
using PCppTokenizer = std::shared_ptr<CppTokenizer>;
|
||||
|
|
Loading…
Reference in New Issue