| 1 | /* |
| 2 | * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) |
| 3 | * |
| 4 | * This program is free software: you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by |
| 6 | * the Free Software Foundation, either version 3 of the License, or |
| 7 | * (at your option) any later version. |
| 8 | * |
| 9 | * This program is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU General Public License |
| 15 | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
| 16 | */ |
| 17 | #ifndef PARSER_UTILS_H |
| 18 | #define PARSER_UTILS_H |
| 19 | #include <QMap> |
| 20 | #include <QObject> |
| 21 | #include <QSet> |
| 22 | #include <QVector> |
| 23 | #include <memory> |
| 24 | |
| 25 | enum class ParserLanguage { |
| 26 | C, |
| 27 | CPlusPlus |
| 28 | }; |
| 29 | |
| 30 | struct CodeSnippet { |
| 31 | QString caption; //Name |
| 32 | QString prefix; //Prefix used in code suggestion |
| 33 | QString code; //Code body |
| 34 | QString desc; //Description |
| 35 | int section; //Section in the menu |
| 36 | }; |
| 37 | |
| 38 | using PCodeSnippet = std::shared_ptr<CodeSnippet>; |
| 39 | |
| 40 | // preprocess/ macro define |
| 41 | struct Define { |
| 42 | QString name; |
| 43 | QString args; |
| 44 | QString value; |
| 45 | QString filename; |
| 46 | bool hardCoded;// if true, don't free memory (points to hard defines) |
| 47 | QStringList argList; // args list to format values |
| 48 | QList<bool> argUsed; |
| 49 | QString formatValue; // format template to format values |
| 50 | }; |
| 51 | |
| 52 | using PDefine = std::shared_ptr<Define>; |
| 53 | |
| 54 | using DefineMap = QHash<QString,PDefine>; |
| 55 | using PDefineMap = std::shared_ptr<DefineMap>; |
| 56 | |
| 57 | enum class SkipType { |
| 58 | skItself, // skip itself |
| 59 | skToSemicolon, // skip to ; |
| 60 | skToColon, // skip to : |
| 61 | skToRightParenthesis, // skip to ) |
| 62 | skToLeftBrace,// Skip to { |
| 63 | skToRightBrace, // skip to } |
| 64 | skNone // It's a keyword but don't process here |
| 65 | }; |
| 66 | |
| 67 | |
| 68 | enum StatementKind { |
| 69 | skUnknown, |
| 70 | skPreprocessor, |
| 71 | skEnumType, |
| 72 | skEnumClassType, |
| 73 | skEnum, |
| 74 | skTypedef, |
| 75 | skClass, |
| 76 | skFunction, |
| 77 | skOperator, |
| 78 | skConstructor, |
| 79 | skDestructor, |
| 80 | skVariable, |
| 81 | skParameter, |
| 82 | skNamespace, |
| 83 | skNamespaceAlias, |
| 84 | skBlock, |
| 85 | skUserCodeSnippet, // user code template |
| 86 | skKeyword, // keywords |
| 87 | skGlobalVariable, |
| 88 | skLocalVariable, |
| 89 | skAlias |
| 90 | }; |
| 91 | |
| 92 | using StatementKindSet = QSet<StatementKind>; |
| 93 | |
| 94 | enum class StatementScope { |
| 95 | ssGlobal, |
| 96 | ssLocal, |
| 97 | ssClassLocal |
| 98 | }; |
| 99 | |
| 100 | enum class StatementClassScope { |
| 101 | scsNone, |
| 102 | scsPrivate, |
| 103 | scsProtected, |
| 104 | scsPublic |
| 105 | }; |
| 106 | |
| 107 | enum class MemberOperatorType { |
| 108 | otArrow, |
| 109 | otDot, |
| 110 | otDColon, |
| 111 | otOther |
| 112 | }; |
| 113 | |
| 114 | struct RemovedStatement{ |
| 115 | QString type; // type "int" |
| 116 | QString command; // identifier/name of statement "foo" |
| 117 | int definitionLine; // definition |
| 118 | QString definitionFileName; // definition |
| 119 | QString fullName; // fullname(including class and namespace) |
| 120 | QString noNameArgs; // Args without name |
| 121 | }; |
| 122 | |
| 123 | enum class EvalStatementKind { |
| 124 | Namespace, |
| 125 | Type, |
| 126 | Variable, |
| 127 | Literal, |
| 128 | Function |
| 129 | }; |
| 130 | |
| 131 | using PRemovedStatement = std::shared_ptr<RemovedStatement>; |
| 132 | |
| 133 | struct StatementMatchPosition{ |
| 134 | int start; |
| 135 | int end; |
| 136 | }; |
| 137 | |
| 138 | using PStatementMathPosition = std::shared_ptr<StatementMatchPosition>; |
| 139 | |
| 140 | struct Statement; |
| 141 | using PStatement = std::shared_ptr<Statement>; |
| 142 | using StatementList = QList<PStatement>; |
| 143 | using PStatementList = std::shared_ptr<StatementList>; |
| 144 | using StatementMap = QMultiMap<QString, PStatement>; |
| 145 | struct Statement { |
| 146 | std::weak_ptr<Statement> parentScope; // parent class/struct/namespace scope, don't use auto pointer to prevent circular reference |
| 147 | QString type; // type "int" |
| 148 | QString command; // identifier/name of statement "foo" |
| 149 | QString args; // args "(int a,float b)" |
| 150 | QString value; // Used for macro defines/typedef, "100" in "#defin COUNT 100" |
| 151 | StatementKind kind; // kind of statement class/variable/function/etc |
| 152 | QList<std::weak_ptr<Statement>> inheritanceList; // list of statements this one inherits from, can be nil |
| 153 | StatementScope scope; // global/local/classlocal |
| 154 | StatementClassScope classScope; // protected/private/public |
| 155 | bool hasDefinition; // definiton line/filename is valid |
| 156 | int line; // declaration |
| 157 | int definitionLine; // definition |
| 158 | QString fileName; // declaration |
| 159 | QString definitionFileName; // definition |
| 160 | bool inProject; // statement in project |
| 161 | bool ; // statement in system header (#include <>) |
| 162 | StatementMap children; // functions can be overloaded,so we use list to save children with the same name |
| 163 | QSet<QString> friends; // friend class / functions |
| 164 | bool isStatic; // static function / variable |
| 165 | bool isInherited; // inherted member; |
| 166 | QString fullName; // fullname(including class and namespace), ClassA::foo |
| 167 | QSet<QString> usingList; // using namespaces |
| 168 | QString noNameArgs;// Args without name |
| 169 | |
| 170 | // fields for code completion |
| 171 | int usageCount; //Usage Count |
| 172 | int matchPosTotal; // total of matched positions |
| 173 | int matchPosSpan; // distance between the first match pos and the last match pos; |
| 174 | int firstMatchLength; // length of first match; |
| 175 | int caseMatched; // if match with case |
| 176 | QList<PStatementMathPosition> matchPositions; |
| 177 | }; |
| 178 | |
| 179 | struct EvalStatement; |
| 180 | using PEvalStatement = std::shared_ptr<EvalStatement>; |
| 181 | /** |
| 182 | * @brief Statement for evaluation result |
| 183 | * Ex. (Test*)(y+1) |
| 184 | * it's baseStatement is the statement for y |
| 185 | * it's effetiveTypeStatement is Test |
| 186 | */ |
| 187 | struct EvalStatement { |
| 188 | QString baseType; // type "int" |
| 189 | EvalStatementKind kind; // namespace / type / variable / function / literal |
| 190 | int pointerLevel; // 0 for "int", 1 for "int *", 2 for "int **"... |
| 191 | PStatement baseStatement; // if not literal or primitive type, the base statement |
| 192 | PStatement effectiveTypeStatement; |
| 193 | public: |
| 194 | EvalStatement (const QString& baseType, |
| 195 | EvalStatementKind kind, |
| 196 | const PStatement& baseStatement, |
| 197 | const PStatement& typeStatement, |
| 198 | int pointerLevel = 0); |
| 199 | void assignType(const PEvalStatement& typeStatement); |
| 200 | |
| 201 | }; |
| 202 | |
| 203 | |
| 204 | struct UsingNamespace { |
| 205 | QStringList namespaces; // List['std','foo'] for using namespace std::foo; |
| 206 | QString filename; |
| 207 | int line; |
| 208 | bool ; |
| 209 | }; |
| 210 | using PUsingNamespace = std::shared_ptr<UsingNamespace>; |
| 211 | |
| 212 | struct CppScope { |
| 213 | int startLine; |
| 214 | PStatement statement; |
| 215 | }; |
| 216 | |
| 217 | using PCppScope = std::shared_ptr<CppScope>; |
| 218 | class CppScopes { |
| 219 | |
| 220 | public: |
| 221 | PStatement findScopeAtLine(int line); |
| 222 | void addScope(int line, PStatement scopeStatement); |
| 223 | PStatement lastScope(); |
| 224 | void removeLastScope(); |
| 225 | void clear(); |
| 226 | private: |
| 227 | QVector<PCppScope> mScopes; |
| 228 | }; |
| 229 | |
| 230 | struct FileIncludes { |
| 231 | QString baseFile; |
| 232 | QMap<QString, bool> includeFiles; // true means the file is directly included, false means included indirectly |
| 233 | QStringList directIncludes; // |
| 234 | QSet<QString> usings; // namespaces it usings |
| 235 | StatementMap statements; // but we don't save temporary statements (full name as key) |
| 236 | StatementMap declaredStatements; // statements declared in this file (full name as key) |
| 237 | CppScopes scopes; // int is start line of the statement scope |
| 238 | QSet<QString> dependingFiles; // The files I depeneds on |
| 239 | QSet<QString> dependedFiles; // the files depends on me |
| 240 | }; |
| 241 | using PFileIncludes = std::shared_ptr<FileIncludes>; |
| 242 | |
| 243 | extern QStringList CppDirectives; |
| 244 | extern QStringList JavadocTags; |
| 245 | extern QMap<QString,SkipType> CppKeywords; |
| 246 | extern QSet<QString> CppControlKeyWords; |
| 247 | extern QSet<QString> CKeywords; |
| 248 | extern QSet<QString> CppTypeKeywords; |
| 249 | extern QSet<QString> STLPointers; |
| 250 | extern QSet<QString> STLContainers; |
| 251 | extern QSet<QString> STLElementMethods; |
| 252 | extern QSet<QString> MemberOperators; |
| 253 | extern QSet<QString> IOManipulators; |
| 254 | |
| 255 | void initParser(); |
| 256 | |
| 257 | QString (const QString& relativeTo, const QString& line, |
| 258 | const QStringList& includePaths, const QStringList& projectIncludePaths); |
| 259 | |
| 260 | QString (const QString& relativeTo, const QString& fileName); |
| 261 | |
| 262 | QString (const QString& fileName, const QStringList& includePaths); |
| 263 | bool (const QString& fileName, const QSet<QString>& includePaths); |
| 264 | bool isHFile(const QString& filename); |
| 265 | bool isCFile(const QString& filename); |
| 266 | bool isCppFile(const QString& filename); |
| 267 | bool isCppKeyword(const QString& word); |
| 268 | bool isCppControlKeyword(const QString& word); |
| 269 | bool isScopeTypeKind(StatementKind kind); |
| 270 | MemberOperatorType getOperatorType(const QString& phrase, int index); |
| 271 | QStringList getOwnerExpressionAndMember( |
| 272 | const QStringList expression, |
| 273 | QString& memberOperator, |
| 274 | QStringList& memberExpression); |
| 275 | bool isMemberOperator(QString token); |
| 276 | StatementKind getKindOfStatement(const PStatement& statement); |
| 277 | |
| 278 | #endif // PARSER_UTILS_H |
| 279 | |