1 /*
2     SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
3     SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen@gmail.com>
4 
5     SPDX-License-Identifier: MIT
6 */
7 
8 #ifndef KSYNTAXHIGHLIGHTING_RULE_P_H
9 #define KSYNTAXHIGHLIGHTING_RULE_P_H
10 
11 #include "contextswitch_p.h"
12 #include "definition.h"
13 #include "definitionref_p.h"
14 #include "foldingregion.h"
15 #include "format.h"
16 #include "keywordlist_p.h"
17 #include "matchresult_p.h"
18 
19 #include <QRegularExpression>
20 #include <QString>
21 
22 #include <memory>
23 
24 QT_BEGIN_NAMESPACE
25 class QXmlStreamReader;
26 QT_END_NAMESPACE
27 
28 namespace KSyntaxHighlighting
29 {
30 class WordDelimiters;
31 
32 class Rule
33 {
34 public:
35     Rule() = default;
36     virtual ~Rule();
37 
38     typedef std::shared_ptr<Rule> Ptr;
39 
40     Definition definition() const;
41     void setDefinition(const Definition &def);
42 
attributeFormat()43     const Format &attributeFormat() const
44     {
45         return m_attributeFormat;
46     }
47 
context()48     const ContextSwitch &context() const
49     {
50         return m_context;
51     }
52 
isLookAhead()53     bool isLookAhead() const
54     {
55         return m_lookAhead;
56     }
57 
isDynamic()58     bool isDynamic() const
59     {
60         return m_dynamic;
61     }
62 
firstNonSpace()63     bool firstNonSpace() const
64     {
65         return m_firstNonSpace;
66     }
67 
requiredColumn()68     int requiredColumn() const
69     {
70         return m_column;
71     }
72 
beginRegion()73     const FoldingRegion &beginRegion() const
74     {
75         return m_beginRegion;
76     }
77 
endRegion()78     const FoldingRegion &endRegion() const
79     {
80         return m_endRegion;
81     }
82 
83     bool load(QXmlStreamReader &reader);
84     void resolveContext();
85     void resolveAttributeFormat(Context *lookupContext);
resolvePostProcessing()86     virtual void resolvePostProcessing()
87     {
88     }
89 
90     virtual MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const = 0;
91 
92     static Rule::Ptr create(QStringView name);
93 
94 protected:
95     virtual bool doLoad(QXmlStreamReader &reader);
96 
97     bool isWordDelimiter(QChar c) const;
98 
99     void loadAdditionalWordDelimiters(QXmlStreamReader &reader);
100 
101 private:
102     Q_DISABLE_COPY(Rule)
103 
104     DefinitionRef m_def;
105     QString m_attribute;
106     Format m_attributeFormat;
107     ContextSwitch m_context;
108     int m_column = -1;
109     FoldingRegion m_beginRegion;
110     FoldingRegion m_endRegion;
111     bool m_firstNonSpace = false;
112     bool m_lookAhead = false;
113 
114     // cache for DefinitionData::wordDelimiters, is accessed VERY often
115     WordDelimiters *m_wordDelimiters = nullptr;
116 
117     QString m_additionalDeliminator;
118     QString m_weakDeliminator;
119 
120 protected:
121     bool m_dynamic = false;
122 };
123 
124 class AnyChar : public Rule
125 {
126 protected:
127     bool doLoad(QXmlStreamReader &reader) override;
128     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
129 
130 private:
131     QString m_chars;
132 };
133 
134 class DetectChar : public Rule
135 {
136 protected:
137     bool doLoad(QXmlStreamReader &reader) override;
138     MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override;
139 
140 private:
141     QChar m_char;
142     int m_captureIndex = 0;
143 };
144 
145 class Detect2Char : public Rule
146 {
147 protected:
148     bool doLoad(QXmlStreamReader &reader) override;
149     MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override;
150 
151 private:
152     QChar m_char1;
153     QChar m_char2;
154 };
155 
156 class DetectIdentifier : public Rule
157 {
158 protected:
159     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
160 };
161 
162 class DetectSpaces : public Rule
163 {
164 protected:
165     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
166 };
167 
168 class Float : public Rule
169 {
170 protected:
171     bool doLoad(QXmlStreamReader &reader) override;
172     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
173 };
174 
175 class IncludeRules : public Rule
176 {
177 public:
178     QString contextName() const;
179     QString definitionName() const;
180     bool includeAttribute() const;
181 
182 protected:
183     bool doLoad(QXmlStreamReader &reader) override;
184     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
185 
186 private:
187     QString m_contextName;
188     QString m_defName;
189     bool m_includeAttribute;
190 };
191 
192 class Int : public Rule
193 {
194 protected:
195     bool doLoad(QXmlStreamReader &reader) override;
196     MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override;
197 };
198 
199 class HlCChar : public Rule
200 {
201 protected:
202     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
203 };
204 
205 class HlCHex : public Rule
206 {
207 protected:
208     bool doLoad(QXmlStreamReader &reader) override;
209     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
210 };
211 
212 class HlCOct : public Rule
213 {
214 protected:
215     bool doLoad(QXmlStreamReader &reader) override;
216     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
217 };
218 
219 class HlCStringChar : public Rule
220 {
221 protected:
222     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
223 };
224 
225 class KeywordListRule : public Rule
226 {
227 protected:
228     bool doLoad(QXmlStreamReader &reader) override;
229     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
230 
231 private:
232     KeywordList *m_keywordList;
233     bool m_hasCaseSensitivityOverride;
234     Qt::CaseSensitivity m_caseSensitivityOverride;
235 };
236 
237 class LineContinue : public Rule
238 {
239 protected:
240     bool doLoad(QXmlStreamReader &reader) override;
241     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
242 
243 private:
244     QChar m_char;
245 };
246 
247 class RangeDetect : public Rule
248 {
249 protected:
250     bool doLoad(QXmlStreamReader &reader) override;
251     MatchResult doMatch(const QString &text, int offset, const QStringList &) const override;
252 
253 private:
254     QChar m_begin;
255     QChar m_end;
256 };
257 
258 class RegExpr : public Rule
259 {
260 protected:
261     void resolvePostProcessing() override;
262     bool doLoad(QXmlStreamReader &reader) override;
263     MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override;
264 
265 private:
266     QRegularExpression m_regexp;
267     bool m_isResolved = false;
268 };
269 
270 class StringDetect : public Rule
271 {
272 protected:
273     bool doLoad(QXmlStreamReader &reader) override;
274     MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override;
275 
276 private:
277     QString m_string;
278     Qt::CaseSensitivity m_caseSensitivity;
279 };
280 
281 class WordDetect : public Rule
282 {
283 protected:
284     bool doLoad(QXmlStreamReader &reader) override;
285     MatchResult doMatch(const QString &text, int offset, const QStringList &captures) const override;
286 
287 private:
288     QString m_word;
289     Qt::CaseSensitivity m_caseSensitivity;
290 };
291 
292 }
293 
294 #endif // KSYNTAXHIGHLIGHTING_RULE_P_H
295