RedPanda-CPP/RedPandaIDE/parser/parserutils.h

406 lines
13 KiB
C
Raw Permalink Normal View History

2021-12-26 23:18:28 +08:00
/*
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
2021-08-05 23:13:21 +08:00
#ifndef PARSER_UTILS_H
#define PARSER_UTILS_H
2021-08-06 11:28:02 +08:00
#include <QMap>
2021-08-05 23:13:21 +08:00
#include <QObject>
2021-08-06 10:58:24 +08:00
#include <QSet>
2022-01-04 16:50:54 +08:00
#include <QVector>
2021-08-05 23:13:21 +08:00
#include <memory>
#include <functional>
2021-08-24 15:05:10 +08:00
using GetFileStreamCallBack = std::function<bool (const QString&, QStringList&)>;
2024-04-03 10:37:29 +08:00
enum class ParserLanguage {
C,
CPlusPlus,
#ifdef ENABLE_SDCC
SDCC,
#endif
};
inline uint qHash(const ParserLanguage& value, uint seed) {
2024-04-03 10:37:29 +08:00
return qHash((int)value, seed);
}
struct CodeSnippet {
2021-08-24 15:05:10 +08:00
QString caption; //Name
QString prefix; //Prefix used in code suggestion
QString code; //Code body
QString desc; //Description
int section; //Section in the menu
};
2021-09-30 12:52:22 +08:00
using PCodeSnippet = std::shared_ptr<CodeSnippet>;
2021-08-24 15:05:10 +08:00
2021-08-05 23:13:21 +08:00
// preprocess/ macro define
struct Define {
2021-08-07 18:02:57 +08:00
QString name;
2021-08-05 23:13:21 +08:00
QString args;
QString value;
QString filename;
bool hardCoded;// if true, don't free memory (points to hard defines)
2021-08-27 16:38:55 +08:00
QList<bool> argUsed;
int varArgIndex;
2021-08-05 23:13:21 +08:00
QString formatValue; // format template to format values
};
using PDefine = std::shared_ptr<Define>;
2021-08-07 18:02:57 +08:00
using DefineMap = QHash<QString,PDefine>;
using PDefineMap = std::shared_ptr<DefineMap>;
2022-11-01 09:02:17 +08:00
enum class KeywordType {
SkipItself, // skip itself
2022-11-04 20:27:35 +08:00
SkipNextSemicolon, // move to ; and skip it
SkipNextColon, // move to : and skip it
SkipNextParenthesis, // move to ) and skip it
MoveToLeftBrace,// move to {
// MoveToRightBrace, // move to }
2022-11-01 09:02:17 +08:00
For, //for
Catch, //catch
Public, // public
Private,
Protected,
Friend,
Struct, // struct/class/enum
2022-11-01 09:02:17 +08:00
Enum, //enum
Inline, // inline
Namespace, //namespace
Typedef, //typedef
Using, //using
2022-11-04 23:44:11 +08:00
DeclType, // decltype
2023-03-12 12:42:44 +08:00
Operator, //operator
Concept, //concept
Requires, //requires
2022-11-04 20:27:35 +08:00
None, // It's a keyword but don't process here
Extern,
2022-11-04 20:27:35 +08:00
NotKeyword
2021-08-05 23:13:21 +08:00
};
2024-04-03 10:37:29 +08:00
enum class StatementKind {
Unknown,
Namespace,
NamespaceAlias,
Class,
Preprocessor,
EnumType,
EnumClassType,
Typedef,
Constructor,
Destructor,
Function,
Variable,
GlobalVariable,
LocalVariable,
Enum,
Operator,
Parameter,
Block,
Lambda,
UserCodeSnippet, // user code template
Keyword, // keywords
KeywordType, //keywords for type (for color management)
Alias, // using alias
2021-08-05 23:13:21 +08:00
};
inline uint qHash(const StatementKind& value, uint seed) {
2024-04-03 10:37:29 +08:00
return qHash((int)value, seed);
}
2021-08-06 10:58:24 +08:00
enum class StatementScope {
2022-11-01 09:02:17 +08:00
Global,
Local,
ClassLocal
2021-08-06 10:58:24 +08:00
};
enum class StatementAccessibility {
2022-11-01 09:02:17 +08:00
None,
Private,
Protected,
Public
2021-08-06 10:58:24 +08:00
};
enum class MemberOperatorType {
2024-04-03 10:37:29 +08:00
Arrow,
Dot,
DColon,
Other
2021-08-06 10:58:24 +08:00
};
2021-12-06 11:37:37 +08:00
enum class EvalStatementKind {
Namespace,
Type,
Variable,
Literal,
Function
};
struct StatementMatchPosition{
2023-10-27 20:16:44 +08:00
uint16_t start;
uint16_t end;
};
2024-04-03 10:37:29 +08:00
enum class StatementProperty {
None = 0x0,
Static = 0x0001,
HasDefinition = 0x0002,
InProject = 0x0004,
InSystemHeader = 0x0008,
Inherited = 0x0010,
Virtual = 0x0020,
Override = 0x0040,
Constexpr = 0x0080,
FunctionPointer = 0x0100,
OperatorOverloading = 0x0200,
DummyStatement = 0x0400
2022-11-16 10:29:20 +08:00
};
Q_DECLARE_FLAGS(StatementProperties, StatementProperty)
Q_DECLARE_OPERATORS_FOR_FLAGS(StatementProperties)
using PStatementMathPosition = std::shared_ptr<StatementMatchPosition>;
2021-08-06 10:58:24 +08:00
struct Statement;
using PStatement = std::shared_ptr<Statement>;
2021-08-11 11:47:47 +08:00
using StatementList = QList<PStatement>;
2021-08-07 14:08:51 +08:00
using PStatementList = std::shared_ptr<StatementList>;
2021-08-15 16:49:37 +08:00
using StatementMap = QMultiMap<QString, PStatement>;
2021-08-06 10:58:24 +08:00
struct Statement {
std::weak_ptr<Statement> parentScope; // parent class/struct/namespace scope, use weak pointer to prevent circular reference
2021-08-06 10:58:24 +08:00
QString type; // type "int"
QString command; // identifier/name of statement "foo"
QString args; // args "(int a,float b)"
QString value; // Used for macro defines/typedef, "100" in "#defin COUNT 100"
QString templateSpecializationParams;
2021-08-06 10:58:24 +08:00
StatementKind kind; // kind of statement class/variable/function/etc
StatementScope scope; // global/local/classlocal
StatementAccessibility accessibility; // protected/private/public
2021-08-06 10:58:24 +08:00
int line; // declaration
int definitionLine; // definition
QString fileName; // declaration
2021-08-06 11:28:02 +08:00
QString definitionFileName; // definition
2021-08-07 14:08:51 +08:00
StatementMap children; // functions can be overloaded,so we use list to save children with the same name
2021-08-06 11:28:02 +08:00
QSet<QString> friends; // friend class / functions
2021-08-07 14:08:51 +08:00
QString fullName; // fullname(including class and namespace), ClassA::foo
2021-08-19 17:08:01 +08:00
QSet<QString> usingList; // using namespaces
2021-08-06 11:28:02 +08:00
QString noNameArgs;// Args without name
2024-03-23 09:03:20 +08:00
QSet<QString> lambdaCaptures;
2022-11-16 10:29:20 +08:00
StatementProperties properties;
2022-09-27 14:01:38 +08:00
// fields for code completion
int usageCount; //Usage Count
2023-10-27 20:16:44 +08:00
uint16_t matchPosTotal; // total of matched positions
uint16_t matchPosSpan; // distance between the first match pos and the last match pos;
uint16_t firstMatchLength; // length of first match;
uint16_t caseMatched; // if match with case
QList<PStatementMathPosition> matchPositions;
2022-11-16 10:29:20 +08:00
// definiton line/filename is valid
bool hasDefinition() {
2024-04-03 10:37:29 +08:00
return properties.testFlag(StatementProperty::HasDefinition);
}
2022-11-16 10:29:20 +08:00
void setHasDefinition(bool on) {
2024-04-03 10:37:29 +08:00
properties.setFlag(StatementProperty::HasDefinition,on);
2022-11-16 10:29:20 +08:00
}
// statement in project
bool inProject() {
2024-04-03 10:37:29 +08:00
return properties.testFlag(StatementProperty::InProject);
2022-11-16 10:29:20 +08:00
}
void setInProject(bool on) {
2024-04-03 10:37:29 +08:00
properties.setFlag(StatementProperty::InProject, on);
2022-11-16 10:29:20 +08:00
}
// statement in system header (#include <>)
bool inSystemHeader() {
2024-04-03 10:37:29 +08:00
return properties.testFlag(StatementProperty::InSystemHeader);
}
2022-11-16 10:29:20 +08:00
void setInSystemHeader(bool on) {
2024-04-03 10:37:29 +08:00
properties.setFlag(StatementProperty::InSystemHeader, on);
2022-11-16 10:29:20 +08:00
}
bool isStatic() {
2024-04-03 10:37:29 +08:00
return properties.testFlag(StatementProperty::Static);
2022-11-16 10:29:20 +08:00
} // static function / variable
void setIsStatic(bool on) {
2024-04-03 10:37:29 +08:00
properties.setFlag(StatementProperty::Static, on);
2022-11-16 10:29:20 +08:00
}
bool isInherited() {
2024-04-03 10:37:29 +08:00
return properties.testFlag(StatementProperty::Inherited);
} // inherted member;
2022-11-16 10:29:20 +08:00
2021-08-06 11:28:02 +08:00
};
2021-08-07 14:08:51 +08:00
2021-12-06 11:37:37 +08:00
struct EvalStatement;
using PEvalStatement = std::shared_ptr<EvalStatement>;
2021-12-07 08:23:27 +08:00
/**
* @brief Statement for evaluation result
* Ex. (Test*)(y+1)
* it's baseStatement is the statement for y
* it's effetiveTypeStatement is Test
*/
2021-12-06 11:37:37 +08:00
struct EvalStatement {
QString baseType; // type "int"
QString templateParams;
2021-12-06 11:37:37 +08:00
EvalStatementKind kind; // namespace / type / variable / function / literal
int pointerLevel; // 0 for "int", 1 for "int *", 2 for "int **"...
QString definitionString; // std::vector<int> etc...
2021-12-06 11:37:37 +08:00
PStatement baseStatement; // if not literal or primitive type, the base statement
PStatement typeStatement;
2021-12-07 08:23:27 +08:00
PStatement effectiveTypeStatement;
2021-12-06 11:37:37 +08:00
public:
2021-12-07 14:48:20 +08:00
EvalStatement (const QString& baseType,
EvalStatementKind kind,
const PStatement& baseStatement,
const PStatement& typeStatement,
const PStatement& effectiveTypeStatement,
int pointerLevel=0,
const QString& templateParams=QString());
2021-12-07 08:23:27 +08:00
void assignType(const PEvalStatement& typeStatement);
2021-12-06 11:37:37 +08:00
};
2021-08-07 14:08:51 +08:00
struct UsingNamespace {
QStringList namespaces; // List['std','foo'] for using namespace std::foo;
QString filename;
int line;
bool fromHeader;
};
using PUsingNamespace = std::shared_ptr<UsingNamespace>;
2021-08-22 05:50:26 +08:00
struct CppScope {
int startLine;
PStatement statement;
};
using PCppScope = std::shared_ptr<CppScope>;
class CppScopes {
public:
2024-04-09 18:10:44 +08:00
PStatement findScopeAtLine(int line) const;
2021-08-22 05:50:26 +08:00
void addScope(int line, PStatement scopeStatement);
PStatement lastScope() const {
if (mScopes.isEmpty())
return PStatement();
return mScopes.back()->statement;
}
void removeLastScope() {
if (!mScopes.isEmpty())
mScopes.pop_back();
}
void clear() { mScopes.clear(); }
2021-08-22 05:50:26 +08:00
private:
QVector<PCppScope> mScopes;
};
2024-02-28 09:41:20 +08:00
struct ClassInheritanceInfo {
std::weak_ptr<Statement> derivedClass;
QString file;
QString parentClassName;
bool isGlobal;
bool isStruct;
StatementAccessibility visibility;
// QString parentClassFilename;
bool handled;
};
using PClassInheritanceInfo = std::shared_ptr<ClassInheritanceInfo>;
2024-04-09 18:10:44 +08:00
class ParsedFileInfo {
public:
ParsedFileInfo(const QString& fileName): mFileName {fileName} { }
2024-04-09 18:10:44 +08:00
ParsedFileInfo(const ParsedFileInfo&)=delete;
ParsedFileInfo& operator=(const ParsedFileInfo&)=delete;
void insertBranch(int level, bool branchTrue) { mBranches.insert(level, branchTrue); }
2024-04-09 18:10:44 +08:00
bool isLineVisible(int line) const;
void addInclude(const QString &fileName) { mIncludes.insert(fileName); }
void addDirectInclude(const QString &fileName) { mDirectIncludes.append(fileName); }
bool including(const QString &fileName) const { return mIncludes.contains(fileName); }
PStatement findScopeAtLine(int line) const { return mScopes.findScopeAtLine(line); }
void addStatement(const PStatement &statement) { mStatements.insert(statement->fullName,statement); }
void clearStatements() { mStatements.clear(); }
void addScope(int line, const PStatement &scope) { mScopes.addScope(line,scope); }
void removeLastScope() { mScopes.removeLastScope(); }
PStatement lastScope() const { return mScopes.lastScope(); }
void addUsing(const QString &usingSymbol) { mUsings.insert(usingSymbol); }
void addHandledInheritances(std::weak_ptr<ClassInheritanceInfo> classInheritanceInfo) { mHandledInheritances.append(classInheritanceInfo); }
void clearHandledInheritances() { mHandledInheritances.clear(); }
QString fileName() const { return mFileName; }
const StatementMap& statements() const { return mStatements; }
const QSet<QString>& usings() const { return mUsings; }
const QStringList& directIncludes() const { return mDirectIncludes; }
const QSet<QString>& includes() const { return mIncludes; }
const QList<std::weak_ptr<ClassInheritanceInfo> >& handledInheritances() const { return mHandledInheritances; }
2024-04-09 18:10:44 +08:00
private:
QString mFileName;
QSet<QString> mIncludes;
QStringList mDirectIncludes; //We need order here.
QSet<QString> mUsings; // namespaces it usings
StatementMap mStatements; // but we don't save temporary statements (full name as key)
CppScopes mScopes; // int is start line of the statement scope
QMap<int,bool> mBranches;
QList<std::weak_ptr<ClassInheritanceInfo>> mHandledInheritances;
2021-08-07 14:08:51 +08:00
};
2024-04-09 19:39:35 +08:00
using PParsedFileInfo = std::shared_ptr<ParsedFileInfo>;
2021-08-07 14:08:51 +08:00
extern QStringList CppDirectives;
extern QStringList JavadocTags;
2022-11-01 09:02:17 +08:00
extern QMap<QString,KeywordType> CppKeywords;
#ifdef ENABLE_SDCC
extern QMap<QString,KeywordType> SDCCKeywords;
extern QSet<QString> SDCCTypeKeywords;
#endif
extern QSet<QString> CppControlKeyWords;
2021-08-25 00:20:07 +08:00
extern QSet<QString> CKeywords;
2021-08-07 14:08:51 +08:00
extern QSet<QString> CppTypeKeywords;
extern QSet<QString> STLPointers;
extern QSet<QString> STLContainers;
extern QSet<QString> STLMaps;
2021-08-07 14:08:51 +08:00
extern QSet<QString> STLElementMethods;
extern QSet<QString> STLIterators;
extern QSet<QString> MemberOperators;
extern QSet<QString> IOManipulators;
extern QSet<QString> AutoTypes;
2021-08-07 14:08:51 +08:00
void initParser();
2021-08-10 21:27:24 +08:00
2021-08-22 21:23:58 +08:00
QString getHeaderFilename(const QString& relativeTo, const QString& line,
2021-10-04 22:32:34 +08:00
const QStringList& includePaths, const QStringList& projectIncludePaths);
2021-08-10 21:27:24 +08:00
2021-08-22 21:23:58 +08:00
QString getLocalHeaderFilename(const QString& relativeTo, const QString& fileName);
2021-08-10 21:27:24 +08:00
2021-10-04 22:32:34 +08:00
QString getSystemHeaderFilename(const QString& fileName, const QStringList& includePaths);
2021-08-19 23:49:23 +08:00
bool isSystemHeaderFile(const QString& fileName, const QSet<QString>& includePaths);
bool isHFile(const QString& filename);
bool isCFile(const QString& filename);
bool isCppFile(const QString& filename);
bool isCppKeyword(const QString& word);
bool isCppControlKeyword(const QString& word);
2021-08-25 00:20:07 +08:00
bool isScopeTypeKind(StatementKind kind);
bool isTypeKind(StatementKind kind);
2021-08-25 00:20:07 +08:00
MemberOperatorType getOperatorType(const QString& phrase, int index);
QStringList getOwnerExpressionAndMember(
const QStringList expression,
QString& memberOperator,
QStringList& memberExpression);
bool isMemberOperator(QString token);
StatementKind getKindOfStatement(const PStatement& statement);
2021-08-24 15:05:10 +08:00
2021-08-05 23:13:21 +08:00
#endif // PARSER_UTILS_H