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