LCOV - code coverage report
Current view: top level - src/regexp - regexp-ast.h (source / functions) Hit Total Coverage
Test: app.info Lines: 88 101 87.1 %
Date: 2019-04-17 Functions: 38 62 61.3 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_REGEXP_REGEXP_AST_H_
       6             : #define V8_REGEXP_REGEXP_AST_H_
       7             : 
       8             : #include "src/objects.h"
       9             : #include "src/objects/js-regexp.h"
      10             : #include "src/objects/string.h"
      11             : #include "src/utils.h"
      12             : #include "src/zone/zone-containers.h"
      13             : #include "src/zone/zone.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \
      19             :   VISIT(Disjunction)                      \
      20             :   VISIT(Alternative)                      \
      21             :   VISIT(Assertion)                        \
      22             :   VISIT(CharacterClass)                   \
      23             :   VISIT(Atom)                             \
      24             :   VISIT(Quantifier)                       \
      25             :   VISIT(Capture)                          \
      26             :   VISIT(Group)                            \
      27             :   VISIT(Lookaround)                       \
      28             :   VISIT(BackReference)                    \
      29             :   VISIT(Empty)                            \
      30             :   VISIT(Text)
      31             : 
      32             : #define FORWARD_DECLARE(Name) class RegExp##Name;
      33             : FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE)
      34             : #undef FORWARD_DECLARE
      35             : 
      36             : class RegExpCompiler;
      37             : class RegExpNode;
      38             : class RegExpTree;
      39             : 
      40         765 : class RegExpVisitor {
      41             :  public:
      42         765 :   virtual ~RegExpVisitor() = default;
      43             : #define MAKE_CASE(Name) \
      44             :   virtual void* Visit##Name(RegExp##Name*, void* data) = 0;
      45             :   FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
      46             : #undef MAKE_CASE
      47             : };
      48             : 
      49             : 
      50             : // A simple closed interval.
      51             : class Interval {
      52             :  public:
      53             :   Interval() : from_(kNone), to_(kNone) {}
      54      248173 :   Interval(int from, int to) : from_(from), to_(to) {}
      55             :   Interval Union(Interval that) {
      56       28289 :     if (that.from_ == kNone)
      57             :       return *this;
      58        1556 :     else if (from_ == kNone)
      59             :       return that;
      60             :     else
      61             :       return Interval(Min(from_, that.from_), Max(to_, that.to_));
      62             :   }
      63       47480 :   bool Contains(int value) { return (from_ <= value) && (value <= to_); }
      64             :   bool is_empty() { return from_ == kNone; }
      65             :   int from() const { return from_; }
      66             :   int to() const { return to_; }
      67             :   static Interval Empty() { return Interval(); }
      68             :   static const int kNone = -1;
      69             : 
      70             :  private:
      71             :   int from_;
      72             :   int to_;
      73             : };
      74             : 
      75             : 
      76             : // Represents code units in the range from from_ to to_, both ends are
      77             : // inclusive.
      78             : class CharacterRange {
      79             :  public:
      80          30 :   CharacterRange() : from_(0), to_(0) {}
      81             :   // For compatibility with the CHECK_OK macro
      82             :   CharacterRange(void* null) { DCHECK_NULL(null); }  // NOLINT
      83             :   V8_EXPORT_PRIVATE static void AddClassEscape(char type,
      84             :                                                ZoneList<CharacterRange>* ranges,
      85             :                                                Zone* zone);
      86             :   // Add class escapes. Add case equivalent closure for \w and \W if necessary.
      87             :   V8_EXPORT_PRIVATE static void AddClassEscape(
      88             :       char type, ZoneList<CharacterRange>* ranges,
      89             :       bool add_unicode_case_equivalents, Zone* zone);
      90             :   static Vector<const int> GetWordBounds();
      91             :   static inline CharacterRange Singleton(uc32 value) {
      92             :     return CharacterRange(value, value);
      93             :   }
      94             :   static inline CharacterRange Range(uc32 from, uc32 to) {
      95             :     DCHECK(0 <= from && to <= String::kMaxCodePoint);
      96             :     DCHECK(static_cast<uint32_t>(from) <= static_cast<uint32_t>(to));
      97             :     return CharacterRange(from, to);
      98             :   }
      99             :   static inline CharacterRange Everything() {
     100             :     return CharacterRange(0, String::kMaxCodePoint);
     101             :   }
     102       60215 :   static inline ZoneList<CharacterRange>* List(Zone* zone,
     103             :                                                CharacterRange range) {
     104             :     ZoneList<CharacterRange>* list =
     105             :         new (zone) ZoneList<CharacterRange>(1, zone);
     106       60215 :     list->Add(range, zone);
     107       60215 :     return list;
     108             :   }
     109      679875 :   bool Contains(uc32 i) { return from_ <= i && i <= to_; }
     110             :   uc32 from() const { return from_; }
     111             :   void set_from(uc32 value) { from_ = value; }
     112             :   uc32 to() const { return to_; }
     113             :   void set_to(uc32 value) { to_ = value; }
     114             :   bool is_valid() { return from_ <= to_; }
     115      273747 :   bool IsEverything(uc32 max) { return from_ == 0 && to_ >= max; }
     116             :   bool IsSingleton() { return (from_ == to_); }
     117             :   V8_EXPORT_PRIVATE static void AddCaseEquivalents(
     118             :       Isolate* isolate, Zone* zone, ZoneList<CharacterRange>* ranges,
     119             :       bool is_one_byte);
     120             :   // Whether a range list is in canonical form: Ranges ordered by from value,
     121             :   // and ranges non-overlapping and non-adjacent.
     122             :   V8_EXPORT_PRIVATE static bool IsCanonical(ZoneList<CharacterRange>* ranges);
     123             :   // Convert range list to canonical form. The characters covered by the ranges
     124             :   // will still be the same, but no character is in more than one range, and
     125             :   // adjacent ranges are merged. The resulting list may be shorter than the
     126             :   // original, but cannot be longer.
     127             :   static void Canonicalize(ZoneList<CharacterRange>* ranges);
     128             :   // Negate the contents of a character range in canonical form.
     129             :   static void Negate(ZoneList<CharacterRange>* src,
     130             :                      ZoneList<CharacterRange>* dst, Zone* zone);
     131             :   static const int kStartMarker = (1 << 24);
     132             :   static const int kPayloadMask = (1 << 24) - 1;
     133             : 
     134             :  private:
     135             :   CharacterRange(uc32 from, uc32 to) : from_(from), to_(to) {}
     136             : 
     137             :   uc32 from_;
     138             :   uc32 to_;
     139             : };
     140             : 
     141             : class CharacterSet final {
     142             :  public:
     143             :   explicit CharacterSet(uc16 standard_set_type)
     144       83020 :       : ranges_(nullptr), standard_set_type_(standard_set_type) {}
     145             :   explicit CharacterSet(ZoneList<CharacterRange>* ranges)
     146      249076 :       : ranges_(ranges), standard_set_type_(0) {}
     147             :   ZoneList<CharacterRange>* ranges(Zone* zone);
     148             :   uc16 standard_set_type() const { return standard_set_type_; }
     149             :   void set_standard_set_type(uc16 special_set_type) {
     150        9709 :     standard_set_type_ = special_set_type;
     151             :   }
     152             :   bool is_standard() { return standard_set_type_ != 0; }
     153             :   V8_EXPORT_PRIVATE void Canonicalize();
     154             : 
     155             :  private:
     156             :   ZoneList<CharacterRange>* ranges_;
     157             :   // If non-zero, the value represents a standard set (e.g., all whitespace
     158             :   // characters) without having to expand the ranges.
     159             :   uc16 standard_set_type_;
     160             : };
     161             : 
     162             : class TextElement final {
     163             :  public:
     164             :   enum TextType { ATOM, CHAR_CLASS };
     165             : 
     166             :   static TextElement Atom(RegExpAtom* atom);
     167             :   static TextElement CharClass(RegExpCharacterClass* char_class);
     168             : 
     169             :   int cp_offset() const { return cp_offset_; }
     170      379921 :   void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
     171             :   int length() const;
     172             : 
     173             :   TextType text_type() const { return text_type_; }
     174             : 
     175             :   RegExpTree* tree() const { return tree_; }
     176             : 
     177             :   RegExpAtom* atom() const {
     178             :     DCHECK(text_type() == ATOM);
     179             :     return reinterpret_cast<RegExpAtom*>(tree());
     180             :   }
     181             : 
     182             :   RegExpCharacterClass* char_class() const {
     183             :     DCHECK(text_type() == CHAR_CLASS);
     184             :     return reinterpret_cast<RegExpCharacterClass*>(tree());
     185             :   }
     186             : 
     187             :  private:
     188             :   TextElement(TextType text_type, RegExpTree* tree)
     189             :       : cp_offset_(-1), text_type_(text_type), tree_(tree) {}
     190             : 
     191             :   int cp_offset_;
     192             :   TextType text_type_;
     193             :   RegExpTree* tree_;
     194             : };
     195             : 
     196             : 
     197     5249855 : class RegExpTree : public ZoneObject {
     198             :  public:
     199             :   static const int kInfinity = kMaxInt;
     200           0 :   virtual ~RegExpTree() = default;
     201             :   virtual void* Accept(RegExpVisitor* visitor, void* data) = 0;
     202             :   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
     203             :                              RegExpNode* on_success) = 0;
     204     1110547 :   virtual bool IsTextElement() { return false; }
     205       83319 :   virtual bool IsAnchoredAtStart() { return false; }
     206       84319 :   virtual bool IsAnchoredAtEnd() { return false; }
     207             :   virtual int min_match() = 0;
     208             :   virtual int max_match() = 0;
     209             :   // Returns the interval of registers used for captures within this
     210             :   // expression.
     211     1026362 :   virtual Interval CaptureRegisters() { return Interval::Empty(); }
     212             :   virtual void AppendToText(RegExpText* text, Zone* zone);
     213             :   V8_EXPORT_PRIVATE std::ostream& Print(std::ostream& os,
     214             :                                         Zone* zone);  // NOLINT
     215             : #define MAKE_ASTYPE(Name)           \
     216             :   virtual RegExp##Name* As##Name(); \
     217             :   virtual bool Is##Name();
     218             :   FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ASTYPE)
     219             : #undef MAKE_ASTYPE
     220             : };
     221             : 
     222             : 
     223           0 : class RegExpDisjunction final : public RegExpTree {
     224             :  public:
     225             :   explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives);
     226             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     227             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     228             :   RegExpDisjunction* AsDisjunction() override;
     229             :   Interval CaptureRegisters() override;
     230             :   bool IsDisjunction() override;
     231             :   bool IsAnchoredAtStart() override;
     232             :   bool IsAnchoredAtEnd() override;
     233       21538 :   int min_match() override { return min_match_; }
     234       22906 :   int max_match() override { return max_match_; }
     235             :   ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
     236             : 
     237             :  private:
     238             :   bool SortConsecutiveAtoms(RegExpCompiler* compiler);
     239             :   void RationalizeConsecutiveAtoms(RegExpCompiler* compiler);
     240             :   void FixSingleCharacterDisjunctions(RegExpCompiler* compiler);
     241             :   ZoneList<RegExpTree*>* alternatives_;
     242             :   int min_match_;
     243             :   int max_match_;
     244             : };
     245             : 
     246             : 
     247           0 : class RegExpAlternative final : public RegExpTree {
     248             :  public:
     249             :   explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes);
     250             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     251             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     252             :   RegExpAlternative* AsAlternative() override;
     253             :   Interval CaptureRegisters() override;
     254             :   bool IsAlternative() override;
     255             :   bool IsAnchoredAtStart() override;
     256             :   bool IsAnchoredAtEnd() override;
     257       23672 :   int min_match() override { return min_match_; }
     258       37025 :   int max_match() override { return max_match_; }
     259             :   ZoneList<RegExpTree*>* nodes() { return nodes_; }
     260             : 
     261             :  private:
     262             :   ZoneList<RegExpTree*>* nodes_;
     263             :   int min_match_;
     264             :   int max_match_;
     265             : };
     266             : 
     267             : 
     268           0 : class RegExpAssertion final : public RegExpTree {
     269             :  public:
     270             :   enum AssertionType {
     271             :     START_OF_LINE,
     272             :     START_OF_INPUT,
     273             :     END_OF_LINE,
     274             :     END_OF_INPUT,
     275             :     BOUNDARY,
     276             :     NON_BOUNDARY
     277             :   };
     278             :   RegExpAssertion(AssertionType type, JSRegExp::Flags flags)
     279       11246 :       : assertion_type_(type), flags_(flags) {}
     280             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     281             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     282             :   RegExpAssertion* AsAssertion() override;
     283             :   bool IsAssertion() override;
     284             :   bool IsAnchoredAtStart() override;
     285             :   bool IsAnchoredAtEnd() override;
     286       10970 :   int min_match() override { return 0; }
     287       11382 :   int max_match() override { return 0; }
     288             :   AssertionType assertion_type() { return assertion_type_; }
     289             : 
     290             :  private:
     291             :   const AssertionType assertion_type_;
     292             :   const JSRegExp::Flags flags_;
     293             : };
     294             : 
     295             : 
     296           0 : class RegExpCharacterClass final : public RegExpTree {
     297             :  public:
     298             :   // NEGATED: The character class is negated and should match everything but
     299             :   //     the specified ranges.
     300             :   // CONTAINS_SPLIT_SURROGATE: The character class contains part of a split
     301             :   //     surrogate and should not be unicode-desugared (crbug.com/641091).
     302             :   enum Flag {
     303             :     NEGATED = 1 << 0,
     304             :     CONTAINS_SPLIT_SURROGATE = 1 << 1,
     305             :   };
     306             :   using CharacterClassFlags = base::Flags<Flag>;
     307             : 
     308      249071 :   RegExpCharacterClass(
     309             :       Zone* zone, ZoneList<CharacterRange>* ranges, JSRegExp::Flags flags,
     310             :       CharacterClassFlags character_class_flags = CharacterClassFlags())
     311             :       : set_(ranges),
     312             :         flags_(flags),
     313      498142 :         character_class_flags_(character_class_flags) {
     314             :     // Convert the empty set of ranges to the negated Everything() range.
     315      249071 :     if (ranges->is_empty()) {
     316         383 :       ranges->Add(CharacterRange::Everything(), zone);
     317             :       character_class_flags_ ^= NEGATED;
     318             :     }
     319      249071 :   }
     320             :   RegExpCharacterClass(uc16 type, JSRegExp::Flags flags)
     321             :       : set_(type),
     322             :         flags_(flags),
     323      166040 :         character_class_flags_(CharacterClassFlags()) {}
     324             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     325             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     326             :   RegExpCharacterClass* AsCharacterClass() override;
     327             :   bool IsCharacterClass() override;
     328      178972 :   bool IsTextElement() override { return true; }
     329      229313 :   int min_match() override { return 1; }
     330             :   // The character class may match two code units for unicode regexps.
     331             :   // TODO(yangguo): we should split this class for usage in TextElement, and
     332             :   //                make max_match() dependent on the character class content.
     333      110340 :   int max_match() override { return 2; }
     334             :   void AppendToText(RegExpText* text, Zone* zone) override;
     335             :   CharacterSet character_set() { return set_; }
     336             :   // TODO(lrn): Remove need for complex version if is_standard that
     337             :   // recognizes a mangled standard set and just do { return set_.is_special(); }
     338             :   bool is_standard(Zone* zone);
     339             :   // Returns a value representing the standard character set if is_standard()
     340             :   // returns true.
     341             :   // Currently used values are:
     342             :   // s : unicode whitespace
     343             :   // S : unicode non-whitespace
     344             :   // w : ASCII word character (digit, letter, underscore)
     345             :   // W : non-ASCII word character
     346             :   // d : ASCII digit
     347             :   // D : non-ASCII digit
     348             :   // . : non-newline
     349             :   // * : All characters, for advancing unanchored regexp
     350             :   uc16 standard_type() const { return set_.standard_set_type(); }
     351      805247 :   ZoneList<CharacterRange>* ranges(Zone* zone) { return set_.ranges(zone); }
     352             :   bool is_negated() const { return (character_class_flags_ & NEGATED) != 0; }
     353             :   JSRegExp::Flags flags() const { return flags_; }
     354             :   bool contains_split_surrogate() const {
     355             :     return (character_class_flags_ & CONTAINS_SPLIT_SURROGATE) != 0;
     356             :   }
     357             : 
     358             :  private:
     359             :   CharacterSet set_;
     360             :   const JSRegExp::Flags flags_;
     361             :   CharacterClassFlags character_class_flags_;
     362             : };
     363             : 
     364             : 
     365           0 : class RegExpAtom final : public RegExpTree {
     366             :  public:
     367             :   explicit RegExpAtom(Vector<const uc16> data, JSRegExp::Flags flags)
     368     1913840 :       : data_(data), flags_(flags) {}
     369             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     370             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     371             :   RegExpAtom* AsAtom() override;
     372             :   bool IsAtom() override;
     373       73608 :   bool IsTextElement() override { return true; }
     374     6861674 :   int min_match() override { return data_.length(); }
     375     6106038 :   int max_match() override { return data_.length(); }
     376             :   void AppendToText(RegExpText* text, Zone* zone) override;
     377             :   Vector<const uc16> data() { return data_; }
     378             :   int length() { return data_.length(); }
     379             :   JSRegExp::Flags flags() const { return flags_; }
     380             :   bool ignore_case() const { return (flags_ & JSRegExp::kIgnoreCase) != 0; }
     381             : 
     382             :  private:
     383             :   Vector<const uc16> data_;
     384             :   const JSRegExp::Flags flags_;
     385             : };
     386             : 
     387             : 
     388           0 : class RegExpText final : public RegExpTree {
     389             :  public:
     390       75072 :   explicit RegExpText(Zone* zone) : elements_(2, zone), length_(0) {}
     391             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     392             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     393             :   RegExpText* AsText() override;
     394             :   bool IsText() override;
     395          30 :   bool IsTextElement() override { return true; }
     396       35650 :   int min_match() override { return length_; }
     397       36812 :   int max_match() override { return length_; }
     398             :   void AppendToText(RegExpText* text, Zone* zone) override;
     399             :   void AddElement(TextElement elm, Zone* zone) {
     400      107006 :     elements_.Add(elm, zone);
     401      107006 :     length_ += elm.length();
     402             :   }
     403       18669 :   ZoneList<TextElement>* elements() { return &elements_; }
     404             : 
     405             :  private:
     406             :   ZoneList<TextElement> elements_;
     407             :   int length_;
     408             : };
     409             : 
     410             : 
     411           0 : class RegExpQuantifier final : public RegExpTree {
     412             :  public:
     413             :   enum QuantifierType { GREEDY, NON_GREEDY, POSSESSIVE };
     414     1451705 :   RegExpQuantifier(int min, int max, QuantifierType type, RegExpTree* body)
     415             :       : body_(body),
     416             :         min_(min),
     417             :         max_(max),
     418     1451705 :         quantifier_type_(type) {
     419     1451705 :     if (min > 0 && body->min_match() > kInfinity / min) {
     420           5 :       min_match_ = kInfinity;
     421             :     } else {
     422     1451700 :       min_match_ = min * body->min_match();
     423             :     }
     424     1451705 :     if (max > 0 && body->max_match() > kInfinity / max) {
     425       17739 :       max_match_ = kInfinity;
     426             :     } else {
     427     1433966 :       max_match_ = max * body->max_match();
     428             :     }
     429     1451705 :   }
     430             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     431             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     432             :   static RegExpNode* ToNode(int min, int max, bool is_greedy, RegExpTree* body,
     433             :                             RegExpCompiler* compiler, RegExpNode* on_success,
     434             :                             bool not_at_start = false);
     435             :   RegExpQuantifier* AsQuantifier() override;
     436             :   Interval CaptureRegisters() override;
     437             :   bool IsQuantifier() override;
     438     1449228 :   int min_match() override { return min_match_; }
     439     1453176 :   int max_match() override { return max_match_; }
     440             :   int min() { return min_; }
     441             :   int max() { return max_; }
     442             :   bool is_possessive() { return quantifier_type_ == POSSESSIVE; }
     443             :   bool is_non_greedy() { return quantifier_type_ == NON_GREEDY; }
     444      926334 :   bool is_greedy() { return quantifier_type_ == GREEDY; }
     445             :   RegExpTree* body() { return body_; }
     446             : 
     447             :  private:
     448             :   RegExpTree* body_;
     449             :   int min_;
     450             :   int max_;
     451             :   int min_match_;
     452             :   int max_match_;
     453             :   QuantifierType quantifier_type_;
     454             : };
     455             : 
     456             : 
     457           0 : class RegExpCapture final : public RegExpTree {
     458             :  public:
     459             :   explicit RegExpCapture(int index)
     460     1082055 :       : body_(nullptr), index_(index), name_(nullptr) {}
     461             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     462             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     463             :   static RegExpNode* ToNode(RegExpTree* body, int index,
     464             :                             RegExpCompiler* compiler, RegExpNode* on_success);
     465             :   RegExpCapture* AsCapture() override;
     466             :   bool IsAnchoredAtStart() override;
     467             :   bool IsAnchoredAtEnd() override;
     468             :   Interval CaptureRegisters() override;
     469             :   bool IsCapture() override;
     470       54736 :   int min_match() override { return body_->min_match(); }
     471       69793 :   int max_match() override { return body_->max_match(); }
     472             :   RegExpTree* body() { return body_; }
     473     1082046 :   void set_body(RegExpTree* body) { body_ = body; }
     474             :   int index() { return index_; }
     475             :   const ZoneVector<uc16>* name() const { return name_; }
     476        1216 :   void set_name(const ZoneVector<uc16>* name) { name_ = name; }
     477      115311 :   static int StartRegister(int index) { return index * 2; }
     478      118691 :   static int EndRegister(int index) { return index * 2 + 1; }
     479             : 
     480             :  private:
     481             :   RegExpTree* body_;
     482             :   int index_;
     483             :   const ZoneVector<uc16>* name_;
     484             : };
     485             : 
     486           0 : class RegExpGroup final : public RegExpTree {
     487             :  public:
     488       19983 :   explicit RegExpGroup(RegExpTree* body) : body_(body) {}
     489             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     490       10759 :   RegExpNode* ToNode(RegExpCompiler* compiler,
     491             :                      RegExpNode* on_success) override {
     492       10759 :     return body_->ToNode(compiler, on_success);
     493             :   }
     494             :   RegExpGroup* AsGroup() override;
     495         277 :   bool IsAnchoredAtStart() override { return body_->IsAnchoredAtStart(); }
     496         271 :   bool IsAnchoredAtEnd() override { return body_->IsAnchoredAtEnd(); }
     497             :   bool IsGroup() override;
     498       23747 :   int min_match() override { return body_->min_match(); }
     499       22989 :   int max_match() override { return body_->max_match(); }
     500       11956 :   Interval CaptureRegisters() override { return body_->CaptureRegisters(); }
     501             :   RegExpTree* body() { return body_; }
     502             : 
     503             :  private:
     504             :   RegExpTree* body_;
     505             : };
     506             : 
     507           0 : class RegExpLookaround final : public RegExpTree {
     508             :  public:
     509             :   enum Type { LOOKAHEAD, LOOKBEHIND };
     510             : 
     511             :   RegExpLookaround(RegExpTree* body, bool is_positive, int capture_count,
     512             :                    int capture_from, Type type)
     513             :       : body_(body),
     514             :         is_positive_(is_positive),
     515             :         capture_count_(capture_count),
     516             :         capture_from_(capture_from),
     517        3611 :         type_(type) {}
     518             : 
     519             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     520             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     521             :   RegExpLookaround* AsLookaround() override;
     522             :   Interval CaptureRegisters() override;
     523             :   bool IsLookaround() override;
     524             :   bool IsAnchoredAtStart() override;
     525        3228 :   int min_match() override { return 0; }
     526        4590 :   int max_match() override { return 0; }
     527             :   RegExpTree* body() { return body_; }
     528             :   bool is_positive() { return is_positive_; }
     529             :   int capture_count() { return capture_count_; }
     530             :   int capture_from() { return capture_from_; }
     531             :   Type type() { return type_; }
     532             : 
     533             :   class Builder {
     534             :    public:
     535             :     Builder(bool is_positive, RegExpNode* on_success,
     536             :             int stack_pointer_register, int position_register,
     537             :             int capture_register_count = 0, int capture_register_start = 0);
     538             :     RegExpNode* on_match_success() { return on_match_success_; }
     539             :     RegExpNode* ForMatch(RegExpNode* match);
     540             : 
     541             :    private:
     542             :     bool is_positive_;
     543             :     RegExpNode* on_match_success_;
     544             :     RegExpNode* on_success_;
     545             :     int stack_pointer_register_;
     546             :     int position_register_;
     547             :   };
     548             : 
     549             :  private:
     550             :   RegExpTree* body_;
     551             :   bool is_positive_;
     552             :   int capture_count_;
     553             :   int capture_from_;
     554             :   Type type_;
     555             : };
     556             : 
     557             : 
     558           0 : class RegExpBackReference final : public RegExpTree {
     559             :  public:
     560             :   explicit RegExpBackReference(JSRegExp::Flags flags)
     561         285 :       : capture_(nullptr), name_(nullptr), flags_(flags) {}
     562             :   RegExpBackReference(RegExpCapture* capture, JSRegExp::Flags flags)
     563        4502 :       : capture_(capture), name_(nullptr), flags_(flags) {}
     564             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     565             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     566             :   RegExpBackReference* AsBackReference() override;
     567             :   bool IsBackReference() override;
     568        4748 :   int min_match() override { return 0; }
     569             :   // The back reference may be recursive, e.g. /(\2)(\1)/. To avoid infinite
     570             :   // recursion, we give up. Ignorance is bliss.
     571        6576 :   int max_match() override { return kInfinity; }
     572             :   int index() { return capture_->index(); }
     573             :   RegExpCapture* capture() { return capture_; }
     574         185 :   void set_capture(RegExpCapture* capture) { capture_ = capture; }
     575             :   const ZoneVector<uc16>* name() const { return name_; }
     576         285 :   void set_name(const ZoneVector<uc16>* name) { name_ = name; }
     577             : 
     578             :  private:
     579             :   RegExpCapture* capture_;
     580             :   const ZoneVector<uc16>* name_;
     581             :   const JSRegExp::Flags flags_;
     582             : };
     583             : 
     584             : 
     585           0 : class RegExpEmpty final : public RegExpTree {
     586             :  public:
     587      330139 :   RegExpEmpty() = default;
     588             :   void* Accept(RegExpVisitor* visitor, void* data) override;
     589             :   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
     590             :   RegExpEmpty* AsEmpty() override;
     591             :   bool IsEmpty() override;
     592        1790 :   int min_match() override { return 0; }
     593        2070 :   int max_match() override { return 0; }
     594             : };
     595             : 
     596             : }  // namespace internal
     597             : }  // namespace v8
     598             : 
     599             : #endif  // V8_REGEXP_REGEXP_AST_H_

Generated by: LCOV version 1.10