File indexing completed on 2024-05-12 04:02:20

0001 /*
0002     SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
0003     SPDX-FileCopyrightText: 2020 Jonathan Poelen <jonathan.poelen@gmail.com>
0004 
0005     SPDX-License-Identifier: MIT
0006 */
0007 
0008 #ifndef KSYNTAXHIGHLIGHTING_RULE_P_H
0009 #define KSYNTAXHIGHLIGHTING_RULE_P_H
0010 
0011 #include "contextswitch_p.h"
0012 #include "definitionref_p.h"
0013 #include "foldingregion.h"
0014 #include "format.h"
0015 #include "highlightingdata_p.hpp"
0016 #include "keywordlist_p.h"
0017 #include "matchresult_p.h"
0018 #include "worddelimiters_p.h"
0019 
0020 #include <QRegularExpression>
0021 #include <QString>
0022 
0023 #include <memory>
0024 
0025 namespace KSyntaxHighlighting
0026 {
0027 class WordDelimiters;
0028 class DefinitionData;
0029 class IncludeRules;
0030 class DynamicRegexpCache;
0031 
0032 class Rule
0033 {
0034 public:
0035     Rule() = default;
0036     virtual ~Rule();
0037 
0038     typedef std::shared_ptr<Rule> Ptr;
0039 
0040     const Format &attributeFormat() const
0041     {
0042         return m_attributeFormat;
0043     }
0044 
0045     const ContextSwitch &context() const
0046     {
0047         return m_context;
0048     }
0049 
0050     bool isLookAhead() const
0051     {
0052         return m_lookAhead;
0053     }
0054 
0055     bool isDynamic() const
0056     {
0057         return m_dynamic;
0058     }
0059 
0060     bool firstNonSpace() const
0061     {
0062         return m_firstNonSpace;
0063     }
0064 
0065     int requiredColumn() const
0066     {
0067         return m_column;
0068     }
0069 
0070     const FoldingRegion &beginRegion() const
0071     {
0072         return m_beginRegion;
0073     }
0074 
0075     const FoldingRegion &endRegion() const
0076     {
0077         return m_endRegion;
0078     }
0079 
0080     const IncludeRules *castToIncludeRules() const;
0081 
0082     bool isLineContinue() const
0083     {
0084         return m_type == Type::LineContinue;
0085     }
0086 
0087     // If true, then the rule uses the skipOffset parameter of MatchResult.
0088     // This is used by AbstractHighlighter::highlightLine() to look for a rule
0089     // in the skipOffsets cache only if it can be found there.
0090     bool hasSkipOffset() const
0091     {
0092         return m_hasSkipOffset;
0093     }
0094 
0095     virtual MatchResult doMatch(QStringView text, int offset, const QStringList &captures, DynamicRegexpCache &dynamicRegexpCache) const = 0;
0096 
0097     static Rule::Ptr create(DefinitionData &def, const HighlightingContextData::Rule &ruleData, QStringView lookupContextName);
0098 
0099 private:
0100     Q_DISABLE_COPY(Rule)
0101 
0102     bool resolveCommon(DefinitionData &def, const HighlightingContextData::Rule &ruleData, QStringView lookupContextName);
0103 
0104     enum class Type : quint8 {
0105         OtherRule,
0106         LineContinue,
0107         IncludeRules,
0108     };
0109 
0110 private:
0111     Format m_attributeFormat;
0112     ContextSwitch m_context;
0113     int m_column = -1;
0114     FoldingRegion m_beginRegion;
0115     FoldingRegion m_endRegion;
0116     Type m_type;
0117     bool m_firstNonSpace = false;
0118     bool m_lookAhead = false;
0119 
0120 protected:
0121     bool m_hasSkipOffset = false;
0122     bool m_dynamic = false;
0123 };
0124 
0125 class AnyChar final : public Rule
0126 {
0127 public:
0128     AnyChar(const HighlightingContextData::Rule::AnyChar &data);
0129 
0130 protected:
0131     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0132 
0133 private:
0134     WordDelimiters m_chars;
0135 };
0136 
0137 class DetectChar final : public Rule
0138 {
0139 public:
0140     DetectChar(const HighlightingContextData::Rule::DetectChar &data);
0141 
0142 protected:
0143     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0144 
0145 private:
0146     QChar m_char;
0147     int m_captureIndex = 0;
0148 };
0149 
0150 class Detect2Chars final : public Rule
0151 {
0152 public:
0153     Detect2Chars(const HighlightingContextData::Rule::Detect2Chars &data);
0154 
0155 protected:
0156     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0157 
0158 private:
0159     QChar m_char1;
0160     QChar m_char2;
0161 };
0162 
0163 class DetectIdentifier final : public Rule
0164 {
0165 protected:
0166     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0167 };
0168 
0169 class DetectSpaces final : public Rule
0170 {
0171 protected:
0172     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0173 };
0174 
0175 class Float final : public Rule
0176 {
0177 public:
0178     Float(DefinitionData &def, const HighlightingContextData::Rule::Float &data);
0179 
0180 protected:
0181     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0182 
0183 private:
0184     WordDelimiters m_wordDelimiters;
0185 };
0186 
0187 class IncludeRules final : public Rule
0188 {
0189 public:
0190     IncludeRules(const HighlightingContextData::Rule::IncludeRules &data);
0191 
0192     const QString &contextName() const
0193     {
0194         return m_contextName;
0195     }
0196 
0197     bool includeAttribute() const
0198     {
0199         return m_includeAttribute;
0200     }
0201 
0202 protected:
0203     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0204 
0205 private:
0206     QString m_contextName;
0207     bool m_includeAttribute;
0208 };
0209 
0210 class Int final : public Rule
0211 {
0212 public:
0213     Int(DefinitionData &def, const HighlightingContextData::Rule::Int &data);
0214 
0215 protected:
0216     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0217 
0218 private:
0219     WordDelimiters m_wordDelimiters;
0220 };
0221 
0222 class HlCChar final : public Rule
0223 {
0224 protected:
0225     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0226 };
0227 
0228 class HlCHex final : public Rule
0229 {
0230 public:
0231     HlCHex(DefinitionData &def, const HighlightingContextData::Rule::HlCHex &data);
0232 
0233 protected:
0234     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0235 
0236 private:
0237     WordDelimiters m_wordDelimiters;
0238 };
0239 
0240 class HlCOct final : public Rule
0241 {
0242 public:
0243     HlCOct(DefinitionData &def, const HighlightingContextData::Rule::HlCOct &data);
0244 
0245 protected:
0246     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0247 
0248 private:
0249     WordDelimiters m_wordDelimiters;
0250 };
0251 
0252 class HlCStringChar final : public Rule
0253 {
0254 protected:
0255     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0256 };
0257 
0258 class KeywordListRule final : public Rule
0259 {
0260 public:
0261     KeywordListRule(const KeywordList &keywordList, DefinitionData &def, const HighlightingContextData::Rule::Keyword &data);
0262 
0263     static Rule::Ptr create(DefinitionData &def, const HighlightingContextData::Rule::Keyword &data, QStringView lookupContextName);
0264 
0265 protected:
0266     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0267 
0268 private:
0269     WordDelimiters m_wordDelimiters;
0270     const KeywordList &m_keywordList;
0271     Qt::CaseSensitivity m_caseSensitivity;
0272 };
0273 
0274 class LineContinue final : public Rule
0275 {
0276 public:
0277     LineContinue(const HighlightingContextData::Rule::LineContinue &data);
0278 
0279 protected:
0280     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0281 
0282 private:
0283     QChar m_char;
0284 };
0285 
0286 class RangeDetect final : public Rule
0287 {
0288 public:
0289     RangeDetect(const HighlightingContextData::Rule::RangeDetect &data);
0290 
0291 protected:
0292     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0293 
0294 private:
0295     QChar m_begin;
0296     QChar m_end;
0297 };
0298 
0299 class RegExpr final : public Rule
0300 {
0301 public:
0302     RegExpr(const HighlightingContextData::Rule::RegExpr &data);
0303 
0304 protected:
0305     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0306 
0307 private:
0308     void resolve();
0309     QRegularExpression m_regexp;
0310     bool m_isResolved = false;
0311 };
0312 
0313 class DynamicRegExpr final : public Rule
0314 {
0315 public:
0316     DynamicRegExpr(const HighlightingContextData::Rule::RegExpr &data);
0317 
0318 protected:
0319     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0320 
0321 private:
0322     void resolve();
0323     QString m_pattern;
0324     QRegularExpression::PatternOptions m_patternOptions;
0325     bool m_isResolved = false;
0326 };
0327 
0328 class StringDetect final : public Rule
0329 {
0330 public:
0331     StringDetect(const HighlightingContextData::Rule::StringDetect &data);
0332 
0333 protected:
0334     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0335 
0336 private:
0337     QString m_string;
0338     Qt::CaseSensitivity m_caseSensitivity;
0339 };
0340 
0341 class DynamicStringDetect final : public Rule
0342 {
0343 public:
0344     DynamicStringDetect(const HighlightingContextData::Rule::StringDetect &data);
0345 
0346 protected:
0347     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0348 
0349 private:
0350     QString m_string;
0351     Qt::CaseSensitivity m_caseSensitivity;
0352 };
0353 
0354 class WordDetect final : public Rule
0355 {
0356 public:
0357     WordDetect(DefinitionData &def, const HighlightingContextData::Rule::WordDetect &data);
0358 
0359 protected:
0360     MatchResult doMatch(QStringView text, int offset, const QStringList &, DynamicRegexpCache &) const override;
0361 
0362 private:
0363     WordDelimiters m_wordDelimiters;
0364     QString m_word;
0365     Qt::CaseSensitivity m_caseSensitivity;
0366 };
0367 
0368 }
0369 
0370 #endif // KSYNTAXHIGHLIGHTING_RULE_P_H