From bcc1b8dc09752e28587c80eb8d75890e0b2381a8 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Wed, 9 Nov 2022 22:22:33 +0800 Subject: [PATCH] - fix: function pointers not correctly handle in code parser; - fix: var assignment not correctly handled in code parser; - fix: function args not correctly handled in code parser; --- NEWS.md | 3 + RedPandaIDE/parser/cppparser.cpp | 219 ++++++++++++++++++++----------- RedPandaIDE/parser/cppparser.h | 4 +- 3 files changed, 151 insertions(+), 75 deletions(-) diff --git a/NEWS.md b/NEWS.md index e4809e61..ff2778c6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,9 @@ Red Panda C++ Version 2.4 - enhancement: Rename filenames in bookmarks/breakpoints after a file is save-ased. - fix: Can't goto definition of classes and namespaces displayed in the class browser on whole project mode. - fix: macro defines parsed before not correctly applied in the succeeding parse. + - fix: function pointers not correctly handle in code parser; + - fix: var assignment not correctly handled in code parser; + - fix: function args not correctly handled in code parser; Red Panda C++ Version 2.3 diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index a5d42719..85da4cdc 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -1293,7 +1293,7 @@ PStatement CppParser::addStatement(const PStatement &parent, const QString &file if (this->isIdentChar(ch)) { QString spaces=(i>argStart)?" ":""; args+=spaces; - word += mTokenizer[i]->text[0]; + word += mTokenizer[i]->text; if (!typeGetted) { noNameArgs+=spaces+word; if (mCppTypeKeywords.contains(word) || !isCppKeyword(word)) @@ -1900,7 +1900,7 @@ void CppParser::checkAndHandleMethodOrVar(KeywordType keywordType) } // function call, skip it - mIndex=moveToNextBraceOrSkipNextSemicolon(mIndex,true); + mIndex=moveToEndOfStatement(mIndex,true); } } else if (mTokenizer[mIndex]->text.startsWith('*') || mTokenizer[mIndex]->text.startsWith('&') @@ -2573,11 +2573,7 @@ void CppParser::handleLambda(int index, int endIndex) } } - i=moveToNextBraceOrSkipNextSemicolon(i, true, bodyEnd); - if (itext=='{') { - //skip '}' - i=mTokenizer[i]->matchIndex+1; - } + i=moveToEndOfStatement(i, true, bodyEnd); } removeScopeLevel(mTokenizer[bodyEnd]->line); } @@ -3095,13 +3091,14 @@ bool CppParser::handleStatement() handleMethod(StatementKind::skDestructor, "", '~'+mTokenizer[mIndex]->text, mIndex+1, false, false); } else { //error - mIndex=moveToNextBraceOrSkipNextSemicolon(mIndex,false); + mIndex=moveToEndOfStatement(mIndex,false); } } else if (!isIdentChar(mTokenizer[mIndex]->text[0])) { - mIndex=moveToNextBraceOrSkipNextSemicolon(mIndex,false); + mIndex=moveToEndOfStatement(mIndex,true); } else if (mTokenizer[mIndex]->text.endsWith('.') || mTokenizer[mIndex]->text.endsWith("->")) { - mIndex=moveToNextBraceOrSkipNextSemicolon(mIndex,true); + mIndex=moveToEndOfStatement(mIndex,true); + } else if (checkForKeyword(keywordType)) { // includes template now handleKeyword(keywordType); } else if (keywordType==KeywordType::For) { // (for/catch) @@ -3581,7 +3578,6 @@ void CppParser::handleVar(const QString& typePrefix,bool isExtern,bool isStatic) // return false; // } - bool varAdded = false; QString tempType; while(mIndextext==';') { break; - } else if (mTokenizer[mIndex]->text=='(' - && mTokenizer[mIndex]->matchIndex+1matchIndex+1]->text=='(') { - //function pointer - QString cmd=mTokenizer[mIndex]->text; - int argStart=mTokenizer[mIndex]->matchIndex+1; - int argEnd=mTokenizer[argStart]->matchIndex; - if (cmd.startsWith('*')) - cmd=cmd.mid(1); - if (!cmd.isEmpty()) { - addChildStatement( - getCurrentScope(), - mCurrentFile, - lastType, - cmd, - mergeArgs(argStart,argEnd), - "", - "", - mTokenizer[mIndex]->line, - StatementKind::skVariable, - getScope(), - mClassScope, - //True, - !isExtern, - isStatic); // TODO: not supported to pass list - varAdded = true; - tempType=""; - } - mIndex=argEnd+1; } else if (isWordChar(mTokenizer[mIndex]->text[0])) { QString cmd=mTokenizer[mIndex]->text; - while (cmd.startsWith('*')) { - cmd=cmd.mid(1); - } - if (cmd=="const") { - tempType=mTokenizer[mIndex]->text; - } else { - QString suffix; - QString args; - cmd=mTokenizer[mIndex]->text; - parseCommandTypeAndArgs(cmd,suffix,args); + if (mTokenizer[mIndex+1]->text=='(' + && mTokenizer[mIndex+1]->matchIndex+1matchIndex+1]->text=='(') { + //function pointer + cmd = mTokenizer[mIndex+2]->text; + int argStart=mTokenizer[mIndex+1]->matchIndex+1; + int argEnd=mTokenizer[argStart]->matchIndex; + if (cmd.startsWith("*")) + cmd = cmd.mid(1); if (!cmd.isEmpty()) { + QString type=lastType; addChildStatement( getCurrentScope(), mCurrentFile, - (lastType+' '+tempType+suffix).trimmed(), + (lastType+" "+tempType+" "+mTokenizer[mIndex]->text).trimmed(), cmd, - args, + mergeArgs(argStart,argEnd), "", "", mTokenizer[mIndex]->line, @@ -3656,12 +3623,43 @@ void CppParser::handleVar(const QString& typePrefix,bool isExtern,bool isStatic) mClassScope, //True, !isExtern, - isStatic); // TODO: not supported to pass list - varAdded = true; - tempType=""; + isStatic); } + tempType=""; + mIndex=indexOfNextSemicolonOrLeftBrace(argEnd+1); + } else { + //normal var + while (cmd.startsWith('*')) { + cmd=cmd.mid(1); + } + if (cmd=="const") { + tempType=mTokenizer[mIndex]->text; + } else { + QString suffix; + QString args; + cmd=mTokenizer[mIndex]->text; + parseCommandTypeAndArgs(cmd,suffix,args); + if (!cmd.isEmpty()) { + addChildStatement( + getCurrentScope(), + mCurrentFile, + (lastType+' '+tempType+suffix).trimmed(), + cmd, + args, + "", + "", + mTokenizer[mIndex]->line, + StatementKind::skVariable, + getScope(), + mClassScope, + //True, + !isExtern, + isStatic); + tempType=""; + } + } + mIndex++; } - mIndex++; } else if (mTokenizer[mIndex]->text=='(') { mIndex=mTokenizer[mIndex]->matchIndex+1; } else if (mTokenizer[mIndex]->text=='=') { @@ -5073,6 +5071,25 @@ int CppParser::indexOfNextSemicolon(int index, int endIndex) return index; } +int CppParser::indexOfNextPeriodOrSemicolon(int index, int endIndex) +{ + if (endIndex<0) + endIndex=mTokenizer.tokenCount(); + while (indextext[0].unicode()) { + case ';': + case ',': + return index; + case '(': + index = mTokenizer[index]->matchIndex+1; + break; + default: + index++; + } + } + return index; +} + int CppParser::indexOfNextSemicolonOrLeftBrace(int index) { while (indextext[0].unicode()) { +// case ';': +// index++; +// stop=true; +// break; +// case '{': +// //skip '}' +// index = mTokenizer[index]->matchIndex+1; +// stop = true; +// break; +// case '(': +// index = mTokenizer[index]->matchIndex+1; +// break; +// default: +// index++; +// } +// } +// if (stop && checkLambda) { +// while (mTokenizer.lambdasCount()>0 && mTokenizer.indexOfFirstLambda()=startIndex) { +// handleLambda(i,index); +// } +// } +// } +// return index; +//} + +int CppParser::moveToEndOfStatement(int index, bool checkLambda, int endIndex) { int startIndex=index; if (endIndex<0) endIndex=mTokenizer.tokenCount(); - bool stop=false; - while (indextext[0].unicode()) { - case ';': - index++; - stop=true; - break; - case '{': - stop=true; - break; - case '(': - index = mTokenizer[index]->matchIndex+1; - break; - default: - index++; + if (index>=endIndex) + return index; + index--; // compensate for the first loop + + bool skip=true; + do { + index++; + bool stop = false; + while (indextext[0].unicode()) { + case ';': + stop=true; + break; + case '=': + stop=true; + break; + case '}': + stop=true; + skip=false; //don't skip the orphan '}' that we found + break; + case '{': + //move to '}' + index=mTokenizer[index]->matchIndex; + stop=true; + break; + case '(': + index = mTokenizer[index]->matchIndex+1; + break; + default: + index++; + } } - } - if (stop && checkLambda) { + } while (indextext=='='); + if (index0 && mTokenizer.indexOfFirstLambda()