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 "definitionref_p.h" |
13 | #include "foldingregion.h" |
14 | #include "format.h" |
15 | #include "highlightingdata_p.hpp" |
16 | #include "keywordlist_p.h" |
17 | #include "matchresult_p.h" |
18 | #include "worddelimiters_p.h" |
19 | |
20 | #include <QRegularExpression> |
21 | #include <QString> |
22 | |
23 | #include <memory> |
24 | |
25 | namespace KSyntaxHighlighting |
26 | { |
27 | class WordDelimiters; |
28 | class DefinitionData; |
29 | class IncludeRules; |
30 | class DynamicRegexpCache; |
31 | |
32 | class Rule |
33 | { |
34 | public: |
35 | Rule() = default; |
36 | virtual ~Rule(); |
37 | |
38 | typedef std::shared_ptr<Rule> Ptr; |
39 | |
40 | const Format &attributeFormat() const |
41 | { |
42 | return m_attributeFormat; |
43 | } |
44 | |
45 | const ContextSwitch &context() const |
46 | { |
47 | return m_context; |
48 | } |
49 | |
50 | bool isLookAhead() const |
51 | { |
52 | return m_lookAhead; |
53 | } |
54 | |
55 | bool isDynamic() const |
56 | { |
57 | return m_dynamic; |
58 | } |
59 | |
60 | bool firstNonSpace() const |
61 | { |
62 | return m_firstNonSpace; |
63 | } |
64 | |
65 | int requiredColumn() const |
66 | { |
67 | return m_column; |
68 | } |
69 | |
70 | const FoldingRegion &beginRegion() const |
71 | { |
72 | return m_beginRegion; |
73 | } |
74 | |
75 | const FoldingRegion &endRegion() const |
76 | { |
77 | return m_endRegion; |
78 | } |
79 | |
80 | const IncludeRules *castToIncludeRules() const; |
81 | |
82 | bool isLineContinue() const |
83 | { |
84 | return m_type == Type::LineContinue; |
85 | } |
86 | |
87 | // If true, then the rule uses the skipOffset parameter of MatchResult. |
88 | // This is used by AbstractHighlighter::highlightLine() to look for a rule |
89 | // in the skipOffsets cache only if it can be found there. |
90 | bool hasSkipOffset() const |
91 | { |
92 | return m_hasSkipOffset; |
93 | } |
94 | |
95 | virtual MatchResult doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &dynamicRegexpCache) const = 0; |
96 | |
97 | static Rule::Ptr create(DefinitionData &def, const HighlightingContextData::Rule &ruleData, QStringView lookupContextName); |
98 | |
99 | private: |
100 | Q_DISABLE_COPY(Rule) |
101 | |
102 | bool resolveCommon(DefinitionData &def, const HighlightingContextData::Rule &ruleData, QStringView lookupContextName); |
103 | |
104 | enum class Type : quint8 { |
105 | OtherRule, |
106 | LineContinue, |
107 | IncludeRules, |
108 | }; |
109 | |
110 | private: |
111 | Format m_attributeFormat; |
112 | ContextSwitch m_context; |
113 | int m_column = -1; |
114 | FoldingRegion m_beginRegion; |
115 | FoldingRegion m_endRegion; |
116 | Type m_type; |
117 | bool m_firstNonSpace = false; |
118 | bool m_lookAhead = false; |
119 | |
120 | protected: |
121 | bool m_hasSkipOffset = false; |
122 | bool m_dynamic = false; |
123 | }; |
124 | |
125 | class AnyChar final : public Rule |
126 | { |
127 | public: |
128 | AnyChar(const HighlightingContextData::Rule::AnyChar &data); |
129 | |
130 | protected: |
131 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
132 | |
133 | private: |
134 | WordDelimiters m_chars; |
135 | }; |
136 | |
137 | class DetectChar final : public Rule |
138 | { |
139 | public: |
140 | DetectChar(const HighlightingContextData::Rule::DetectChar &data); |
141 | |
142 | protected: |
143 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
144 | |
145 | private: |
146 | QChar m_char; |
147 | int m_captureIndex = 0; |
148 | }; |
149 | |
150 | class Detect2Chars final : public Rule |
151 | { |
152 | public: |
153 | Detect2Chars(const HighlightingContextData::Rule::Detect2Chars &data); |
154 | |
155 | protected: |
156 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
157 | |
158 | private: |
159 | QChar m_char1; |
160 | QChar m_char2; |
161 | }; |
162 | |
163 | class DetectIdentifier final : public Rule |
164 | { |
165 | protected: |
166 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
167 | }; |
168 | |
169 | class DetectSpaces final : public Rule |
170 | { |
171 | protected: |
172 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
173 | }; |
174 | |
175 | class Float final : public Rule |
176 | { |
177 | public: |
178 | Float(DefinitionData &def, const HighlightingContextData::Rule::Float &data); |
179 | |
180 | protected: |
181 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
182 | |
183 | private: |
184 | WordDelimiters m_wordDelimiters; |
185 | }; |
186 | |
187 | class IncludeRules final : public Rule |
188 | { |
189 | public: |
190 | IncludeRules(const HighlightingContextData::Rule::IncludeRules &data); |
191 | |
192 | const QString &contextName() const |
193 | { |
194 | return m_contextName; |
195 | } |
196 | |
197 | bool includeAttribute() const |
198 | { |
199 | return m_includeAttribute; |
200 | } |
201 | |
202 | protected: |
203 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
204 | |
205 | private: |
206 | QString m_contextName; |
207 | bool m_includeAttribute; |
208 | }; |
209 | |
210 | class Int final : public Rule |
211 | { |
212 | public: |
213 | Int(DefinitionData &def, const HighlightingContextData::Rule::Int &data); |
214 | |
215 | protected: |
216 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
217 | |
218 | private: |
219 | WordDelimiters m_wordDelimiters; |
220 | }; |
221 | |
222 | class HlCChar final : public Rule |
223 | { |
224 | protected: |
225 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
226 | }; |
227 | |
228 | class HlCHex final : public Rule |
229 | { |
230 | public: |
231 | HlCHex(DefinitionData &def, const HighlightingContextData::Rule::HlCHex &data); |
232 | |
233 | protected: |
234 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
235 | |
236 | private: |
237 | WordDelimiters m_wordDelimiters; |
238 | }; |
239 | |
240 | class HlCOct final : public Rule |
241 | { |
242 | public: |
243 | HlCOct(DefinitionData &def, const HighlightingContextData::Rule::HlCOct &data); |
244 | |
245 | protected: |
246 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
247 | |
248 | private: |
249 | WordDelimiters m_wordDelimiters; |
250 | }; |
251 | |
252 | class HlCStringChar final : public Rule |
253 | { |
254 | protected: |
255 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
256 | }; |
257 | |
258 | class KeywordListRule final : public Rule |
259 | { |
260 | public: |
261 | KeywordListRule(const KeywordList &keywordList, DefinitionData &def, const HighlightingContextData::Rule::Keyword &data); |
262 | |
263 | static Rule::Ptr create(DefinitionData &def, const HighlightingContextData::Rule::Keyword &data, QStringView lookupContextName); |
264 | |
265 | protected: |
266 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
267 | |
268 | private: |
269 | WordDelimiters m_wordDelimiters; |
270 | const KeywordList &m_keywordList; |
271 | Qt::CaseSensitivity m_caseSensitivity; |
272 | }; |
273 | |
274 | class LineContinue final : public Rule |
275 | { |
276 | public: |
277 | LineContinue(const HighlightingContextData::Rule::LineContinue &data); |
278 | |
279 | protected: |
280 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
281 | |
282 | private: |
283 | QChar m_char; |
284 | }; |
285 | |
286 | class RangeDetect final : public Rule |
287 | { |
288 | public: |
289 | RangeDetect(const HighlightingContextData::Rule::RangeDetect &data); |
290 | |
291 | protected: |
292 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
293 | |
294 | private: |
295 | QChar m_begin; |
296 | QChar m_end; |
297 | }; |
298 | |
299 | class RegExpr final : public Rule |
300 | { |
301 | public: |
302 | RegExpr(const HighlightingContextData::Rule::RegExpr &data); |
303 | |
304 | protected: |
305 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
306 | |
307 | private: |
308 | void resolve(); |
309 | QRegularExpression m_regexp; |
310 | bool m_isResolved = false; |
311 | }; |
312 | |
313 | class DynamicRegExpr final : public Rule |
314 | { |
315 | public: |
316 | DynamicRegExpr(const HighlightingContextData::Rule::RegExpr &data); |
317 | |
318 | protected: |
319 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
320 | |
321 | private: |
322 | void resolve(); |
323 | QString m_pattern; |
324 | QRegularExpression::PatternOptions m_patternOptions; |
325 | bool m_isResolved = false; |
326 | }; |
327 | |
328 | class StringDetect final : public Rule |
329 | { |
330 | public: |
331 | StringDetect(const HighlightingContextData::Rule::StringDetect &data); |
332 | |
333 | protected: |
334 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
335 | |
336 | private: |
337 | QString m_string; |
338 | Qt::CaseSensitivity m_caseSensitivity; |
339 | }; |
340 | |
341 | class DynamicStringDetect final : public Rule |
342 | { |
343 | public: |
344 | DynamicStringDetect(const HighlightingContextData::Rule::StringDetect &data); |
345 | |
346 | protected: |
347 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
348 | |
349 | private: |
350 | QString m_string; |
351 | Qt::CaseSensitivity m_caseSensitivity; |
352 | }; |
353 | |
354 | class WordDetect final : public Rule |
355 | { |
356 | public: |
357 | WordDetect(DefinitionData &def, const HighlightingContextData::Rule::WordDetect &data); |
358 | |
359 | protected: |
360 | MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override; |
361 | |
362 | private: |
363 | WordDelimiters m_wordDelimiters; |
364 | QString m_word; |
365 | Qt::CaseSensitivity m_caseSensitivity; |
366 | }; |
367 | |
368 | } |
369 | |
370 | #endif // KSYNTAXHIGHLIGHTING_RULE_P_H |
371 | |