work save

This commit is contained in:
royqh1979@gmail.com 2021-08-19 12:01:01 +08:00
parent c9a21b8a03
commit 33b47c3d80
2 changed files with 368 additions and 4 deletions

View File

@ -338,7 +338,7 @@ void CppParser::checkForSkipStatement()
}
}
bool CppParser::CheckForStructs()
bool CppParser::checkForStructs()
{
int dis = 0;
if ((mTokenizer[mIndex]->text == "friend")
@ -864,7 +864,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, const QString &sArgs, bool isStatic, bool isFriend)
{
bool isValid = true;
bool isDeclaration = false; // assume it's not a prototype
@ -1260,6 +1260,370 @@ void CppParser::handlePreprocessor()
mIndex++;
}
void CppParser::handleScope()
{
if (mTokenizer[mIndex]->text=="public")
mClassScope = StatementClassScope::scsPublic;
else if (mTokenizer[mIndex]->text=="private")
mClassScope = StatementClassScope::scsPrivate;
else if (mTokenizer[mIndex]->text=="protected")
mClassScope = StatementClassScope::scsProtected;
else
mClassScope = StatementClassScope::scsNone;
mIndex+=2; // the scope is followed by a ':'
}
bool CppParser::handleStatement()
{
QString S1,S2,S3;
bool isStatic, isFriend;
int idx=getCurrentBlockEndSkip();
int idx2=getCurrentBlockBeginSkip();
int idx3=getCurrentInlineNamespaceEndSkip();
if (mIndex >= idx2) {
//skip (previous handled) block begin
mBlockBeginSkips.pop_back();
if (mIndex == idx2)
mIndex++;
else if (mIndex<mTokenizer.tokenCount()) //error happens, but we must remove an (error) added scope
removeScopeLevel(mTokenizer[mIndex]->line);
} else if (mIndex >= idx) {
//skip (previous handled) block end
mBlockEndSkips.pop_back();
if (idx+1 < mTokenizer.tokenCount())
removeScopeLevel(mTokenizer[idx+1]->line);
if (mIndex == idx)
mIndex++;
} else if (mIndex >= idx3) {
//skip (previous handled) inline name space end
mInlineNamespaceEndSkips.pop_back();
if (mIndex == idx3)
mIndex++;
} else if (mTokenizer[mIndex]->text.startsWith('{')) {
PStatement block = addStatement(
getCurrentScope(),
mCurrentFile,
"", // override hint
"",
"",
"",
"",
//mTokenizer[mIndex]^.Line,
mTokenizer[mIndex]->line,
StatementKind::skBlock,
getScope(),
mClassScope,
true,
false);
addSoloScopeLevel(block,mTokenizer[mIndex]->line);
mIndex++;
} else if (mTokenizer[mIndex]->text[1] == '}') {
removeScopeLevel(mTokenizer[mIndex]->line);
mIndex++;
} else if (checkForPreprocessor()) {
handlePreprocessor();
} else if (checkForKeyword()) { // includes template now
handleKeyword();
} else if (checkForForBlock()) { // (for/catch)
handleForBlock();
} else if (checkForCatchBlock()) { // (for/catch)
handleCatchBlock();
} else if (checkForScope()) { // public /private/proteced
handleScope();
} else if (checkForEnum()) {
handleEnum();
} else if (checkForTypedef()) {
if (mIndex+1 < mTokenizer.tokenCount()) {
if (checkForTypedefStruct()) { // typedef struct something
mIndex++; // skip 'typedef'
handleStructs(true);
} else if (checkForTypedefEnum()) { // typedef enum something
mIndex++; // skip 'typedef'
handleEnum();
} else
handleOtherTypedefs(); // typedef Foo Bar
} else
mIndex++;
} else if (checkForNamespace()) {
handleNamespace();
} else if (checkForUsing()) {
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 (checkForVar()) {
handleVar();
} else
mIndex++;
checkForSkipStatement();
return mIndex < mTokenizer.tokenCount();
}
void CppParser::handleStructs(bool isTypedef)
{
bool isFriend = false;
QString prefix = mTokenizer[mIndex]->text;
if (prefix == "friend") {
isFriend = true;
mIndex++;
}
// Check if were dealing with a struct or union
prefix = mTokenizer[mIndex]->text;
bool isStruct = ("struct" == prefix) || ("union"==prefix);
int startLine = mTokenizer[mIndex]->line;
mIndex++; //skip struct/class/union
if (mIndex>=mTokenizer.tokenCount())
return;
// Do not modifiy index initially
int i = mIndex;
// Skip until the struct body starts
while ((i < mTokenizer.tokenCount()) && ! (
mTokenizer[i]->text.front() ==';'
|| mTokenizer[i]->text.front() =='{'))
i++;
// Forward class/struct decl *or* typedef, e.g. typedef struct some_struct synonym1, synonym2;
if ((i < mTokenizer.tokenCount()) && (mTokenizer[i]->text.front() == ';')) {
// typdef struct Foo Bar
if (isTypedef) {
QString oldType = mTokenizer[mIndex]->text;
while(true) {
// Add definition statement for the synonym
if ((mIndex + 1 < mTokenizer.tokenCount())
&& (mTokenizer[mIndex + 1]->text.front()==','
|| mTokenizer[mIndex + 1]->text.front()==';')) {
QString newType = mTokenizer[mIndex]->text;
addStatement(
getCurrentScope(),
mCurrentFile,
"typedef " + prefix + " " + oldType + ' ' + newType, // override hint
oldType,
newType,
"",
"",
startLine,
StatementKind::skTypedef,
getScope(),
mClassScope,
true,
false);
}
mIndex++;
if (mIndex >= mTokenizer.tokenCount())
break;
if (mTokenizer[mIndex]->text.front() == ';')
break;
}
} else {
if (isFriend) { // friend class
PStatement parentStatement = getCurrentScope();
if (parentStatement) {
parentStatement->friends.insert(mTokenizer[mIndex]->text);
}
} else {
// todo: Forward declaration, struct Foo. Don't mention in class browser
}
i++; // step over ;
mIndex = i;
}
// normal class/struct decl
} else {
PStatement firstSynonym;
// Add class/struct name BEFORE opening brace
if (mTokenizer[mIndex]->text.front() != '{') {
while(true) {
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() == ':')) {
QString command = mTokenizer[mIndex]->text;
if (!command.isEmpty()) {
firstSynonym = addStatement(
getCurrentScope(),
mCurrentFile,
"", // do not override hint
prefix, // type
command, // command
"", // args
"", // values
startLine,
StatementKind::skClass,
getScope(),
mClassScope,
true,
false);
command = "";
}
mIndex++;
} else if ((mIndex + 2 < mTokenizer.tokenCount())
&& (mTokenizer[mIndex + 1]->text == "final")
&& (mTokenizer[mIndex + 2]->text.front()==','
|| isblockChar(mTokenizer[mIndex + 2]->text.front()))) {
QString command = mTokenizer[mIndex]->text;
if (!command.isEmpty()) {
firstSynonym = addStatement(
getCurrentScope(),
mCurrentFile,
"", // do not override hint
prefix, // type
command, // command
"", // args
"", // values
startLine,
StatementKind::skClass,
getScope(),
mClassScope,
true,
false);
command="";
}
mIndex+=2;
} else
mIndex++;
if (mIndex >= mTokenizer.tokenCount())
break;
if (mTokenizer[mIndex]->text.front() == ':'
|| mTokenizer[mIndex]->text.front() == '{'
|| mTokenizer[mIndex]->text.front() == ';')
break;
}
}
// Walk to opening brace if we encountered inheritance statements
if ((mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() == ':')) {
if (firstSynonym)
setInheritance(mIndex, firstSynonym, isStruct); // set the _InheritanceList value
while ((mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() != '{'))
mIndex++; // skip decl after ':'
}
// Check for struct synonyms after close brace
if (isStruct) {
// Walk to closing brace
i = skipBraces(mIndex); // step onto closing brace
if ((i + 1 < mTokenizer.tokenCount()) && !(
mTokenizer[i + 1]->text.front() == ';'
|| mTokenizer[i + 1]->text.front() == '}')) {
// When encountering names again after struct body scanning, skip it
mSkipList.append(i+1); // add first name to skip statement so that we can skip it until the next ;
QString command = "";
QString args = "";
// Add synonym before opening brace
while(true) {
i++;
if (!(mTokenizer[i]->text.front() == '{'
|| mTokenizer[i]->text.front() == ','
|| mTokenizer[i]->text.front() == ';')) {
if ((mTokenizer[i]->text.front() == '_')
&& (mTokenizer[i]->text.back() == '_')) {
// skip possible gcc attributes
// start and end with 2 underscores (i.e. __attribute__)
// so, to avoid slow checks of strings, we just check the first and last letter of the token
// if both are underscores, we split
break;
} else {
if (mTokenizer[i]->text.endsWith(']')) { // cut-off array brackets
int pos = mTokenizer[i]->text.indexOf('[');
command += mTokenizer[i]->text.mid(0,pos) + ' ';
args = mTokenizer[i]->text.mid(pos);
} else if (mTokenizer[i]->text.front() == '*'
|| mTokenizer[i]->text.front() == '&') { // do not add spaces after pointer operator
command += mTokenizer[i]->text;
} else {
command += mTokenizer[i]->text + ' ';
}
}
} else {
command = command.trimmed();
if (!command.isEmpty() &&
( !firstSynonym
|| command!=firstSynonym->command )) {
//not define the struct yet, we define a unamed struct
if (!firstSynonym) {
firstSynonym = addStatement(
getCurrentScope(),
mCurrentFile,
"", // do not override hint
prefix,
"__"+command,
"",
"",
startLine,
StatementKind::skClass,
getScope(),
mClassScope,
true,
false);
}
if (isTypedef) {
//typedef
addStatement(
getCurrentScope(),
mCurrentFile,
"typedef " + firstSynonym->command + ' ' + command, // override hint
firstSynonym->command,
command,
"",
"",
mTokenizer[mIndex]->line,
StatementKind::skTypedef,
getScope(),
mClassScope,
true,
false); // typedef
} else {
//variable define
AddStatement(
getCurrentScope(),
mCurrentFile,
"", // do not override hint
firstSynonym->command,
command,
args,
"",
mTokenizer[i]->line,
StatementKind::skVariable,
getScope(),
mClassScope,
true,
false); // TODO: not supported to pass list
}
}
command = "";
}
if (i >= mTokenizer.tokenCount() - 1)
break;
if (mTokenizer[i]->text.front()=='{'
|| mTokenizer[i]->text.front()== ';')
break;
}
// Nothing worth mentioning after closing brace
// Proceed to set first synonym as current class
}
}
addSoloScopeLevel(firstSynonym,startLine);
// Step over {
if ((mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() == '{'))
mIndex++;
}
}
QString CppParser::expandMacroType(const QString &name)
{
//its done in the preprocessor

View File

@ -148,7 +148,7 @@ private:
bool checkForPreprocessor();
bool checkForScope();
void checkForSkipStatement();
bool CheckForStructs();
bool checkForStructs();
bool checkForTypedef();
bool checkForTypedefEnum();
bool checkForTypedefStruct();
@ -186,7 +186,7 @@ private:
void handleEnum();
void handleForBlock();
void handleKeyword();
void HandleMethod(
void handleMethod(
const QString& sType,
const QString& sName,
const QString& sArgs,