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
25enum class ParserLanguage {
26 C,
27 CPlusPlus
28};
29
30struct 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
38using PCodeSnippet = std::shared_ptr<CodeSnippet>;
39
40// preprocess/ macro define
41struct 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
52using PDefine = std::shared_ptr<Define>;
53
54using DefineMap = QHash<QString,PDefine>;
55using PDefineMap = std::shared_ptr<DefineMap>;
56
57enum 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
68enum 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
92using StatementKindSet = QSet<StatementKind>;
93
94enum class StatementScope {
95 ssGlobal,
96 ssLocal,
97 ssClassLocal
98};
99
100enum class StatementClassScope {
101 scsNone,
102 scsPrivate,
103 scsProtected,
104 scsPublic
105};
106
107enum class MemberOperatorType {
108 otArrow,
109 otDot,
110 otDColon,
111 otOther
112};
113
114struct 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
123enum class EvalStatementKind {
124 Namespace,
125 Type,
126 Variable,
127 Literal,
128 Function
129};
130
131using PRemovedStatement = std::shared_ptr<RemovedStatement>;
132
133struct StatementMatchPosition{
134 int start;
135 int end;
136};
137
138using PStatementMathPosition = std::shared_ptr<StatementMatchPosition>;
139
140struct Statement;
141using PStatement = std::shared_ptr<Statement>;
142using StatementList = QList<PStatement>;
143using PStatementList = std::shared_ptr<StatementList>;
144using StatementMap = QMultiMap<QString, PStatement>;
145struct 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 inSystemHeader; // 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
179struct EvalStatement;
180using 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 */
187struct 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;
193public:
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
204struct UsingNamespace {
205 QStringList namespaces; // List['std','foo'] for using namespace std::foo;
206 QString filename;
207 int line;
208 bool fromHeader;
209};
210using PUsingNamespace = std::shared_ptr<UsingNamespace>;
211
212struct CppScope {
213 int startLine;
214 PStatement statement;
215};
216
217using PCppScope = std::shared_ptr<CppScope>;
218class CppScopes {
219
220public:
221 PStatement findScopeAtLine(int line);
222 void addScope(int line, PStatement scopeStatement);
223 PStatement lastScope();
224 void removeLastScope();
225 void clear();
226private:
227 QVector<PCppScope> mScopes;
228};
229
230struct 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};
241using PFileIncludes = std::shared_ptr<FileIncludes>;
242
243extern QStringList CppDirectives;
244extern QStringList JavadocTags;
245extern QMap<QString,SkipType> CppKeywords;
246extern QSet<QString> CppControlKeyWords;
247extern QSet<QString> CKeywords;
248extern QSet<QString> CppTypeKeywords;
249extern QSet<QString> STLPointers;
250extern QSet<QString> STLContainers;
251extern QSet<QString> STLElementMethods;
252extern QSet<QString> MemberOperators;
253extern QSet<QString> IOManipulators;
254
255void initParser();
256
257QString getHeaderFilename(const QString& relativeTo, const QString& line,
258 const QStringList& includePaths, const QStringList& projectIncludePaths);
259
260QString getLocalHeaderFilename(const QString& relativeTo, const QString& fileName);
261
262QString getSystemHeaderFilename(const QString& fileName, const QStringList& includePaths);
263bool isSystemHeaderFile(const QString& fileName, const QSet<QString>& includePaths);
264bool isHFile(const QString& filename);
265bool isCFile(const QString& filename);
266bool isCppFile(const QString& filename);
267bool isCppKeyword(const QString& word);
268bool isCppControlKeyword(const QString& word);
269bool isScopeTypeKind(StatementKind kind);
270MemberOperatorType getOperatorType(const QString& phrase, int index);
271QStringList getOwnerExpressionAndMember(
272 const QStringList expression,
273 QString& memberOperator,
274 QStringList& memberExpression);
275bool isMemberOperator(QString token);
276StatementKind getKindOfStatement(const PStatement& statement);
277
278#endif // PARSER_UTILS_H
279