• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_REGEXP_OPCODE_H
17 #define ECMASCRIPT_REGEXP_OPCODE_H
18 
19 #include <list>
20 
21 #include "ecmascript/mem/dyn_chunk.h"
22 
23 namespace panda {
24 namespace ecmascript {
25 class RegExpOpCode {
26 public:
27     enum : uint8_t {
28         OP_SAVE_START = 0U,
29         OP_SAVE_END,
30         OP_CHAR,
31         OP_GOTO,
32         OP_SPLIT_FIRST,
33         OP_SPLIT_NEXT,
34         OP_NEGATIVE_MATCH_AHEAD,
35         OP_MATCH_AHEAD,
36         OP_MATCH,
37         OP_LOOP,
38         OP_LOOP_GREEDY,
39         OP_PUSH_CHAR,
40         OP_CHECK_CHAR,
41         OP_PUSH,
42         OP_POP,
43         OP_SAVE_RESET,
44         OP_LINE_START,
45         OP_LINE_END,
46         OP_WORD_BOUNDARY,
47         OP_NOT_WORD_BOUNDARY,
48         OP_ALL,
49         OP_DOTS,
50         OP_MATCH_END,
51         OP_PREV,
52         OP_RANGE,
53         OP_BACKREFERENCE,
54         OP_BACKWARD_BACKREFERENCE,
55         OP_CHAR32,
56         OP_RANGE32,
57         OP_SPARSE,
58         OP_INVALID,
59     };
60 
61     static constexpr size_t OP_SIZE_ONE = 1;
62     static constexpr size_t OP_SIZE_TWO = 2;
63     static constexpr size_t OP_SIZE_THREE = 3;
64     static constexpr size_t OP_SIZE_FOUR = 4;
65     static constexpr size_t OP_SIZE_FIVE = 5;
66     static constexpr size_t OP_SIZE_SIX = 6;
67     static constexpr size_t OP_SIZE_EIGHT = 8;
68     static constexpr size_t OP_SIZE_NINE = 9;
69     static constexpr size_t OP_SIZE_THIRTEEN = 13;
70     static constexpr uint32_t INVALID_PARA = 0xffffffff;
71 
72     RegExpOpCode(uint8_t opCode, int size);
73     NO_COPY_SEMANTIC(RegExpOpCode);
74     NO_MOVE_SEMANTIC(RegExpOpCode);
75 
76     virtual ~RegExpOpCode() = default;
77     static RegExpOpCode *GetRegExpOpCode(const DynChunk &buf, int pcOffset);
78     static RegExpOpCode *GetRegExpOpCode(uint8_t opCode);
79     static void DumpRegExpOpCode(std::ostream &out, const DynChunk &buf, uint32_t size);
GetSize()80     inline uint8_t GetSize() const
81     {
82         return size_;
83     }
GetOpCode()84     inline uint8_t GetOpCode() const
85     {
86         return opCode_;
87     }
GetDynChunkfSize(const DynChunk & buf)88     inline int GetDynChunkfSize(const DynChunk &buf) const
89     {
90         return buf.size_;
91     }
92     virtual uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const = 0;
93 
94 private:
95     uint8_t opCode_ {0};
96     uint8_t size_ {0};
97 };
98 
99 class SaveStartOpCode : public RegExpOpCode {
100 public:
SaveStartOpCode()101     SaveStartOpCode() : RegExpOpCode(OP_SAVE_START, RegExpOpCode::OP_SIZE_TWO) {}
102     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
103     ~SaveStartOpCode() override = default;
104     NO_COPY_SEMANTIC(SaveStartOpCode);
105     NO_MOVE_SEMANTIC(SaveStartOpCode);
106     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
107 };
108 
109 class SaveEndOpCode : public RegExpOpCode {
110 public:
SaveEndOpCode()111     SaveEndOpCode() : RegExpOpCode(OP_SAVE_END, RegExpOpCode::OP_SIZE_TWO) {}
112     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
113     ~SaveEndOpCode() override = default;
114     NO_COPY_SEMANTIC(SaveEndOpCode);
115     NO_MOVE_SEMANTIC(SaveEndOpCode);
116     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
117 };
118 
119 class CharOpCode : public RegExpOpCode {
120 public:
CharOpCode()121     CharOpCode() : RegExpOpCode(OP_CHAR, RegExpOpCode::OP_SIZE_THREE) {}
122     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
123     ~CharOpCode() override = default;
124     NO_COPY_SEMANTIC(CharOpCode);
125     NO_MOVE_SEMANTIC(CharOpCode);
126     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
127 };
128 
129 class GotoOpCode : public RegExpOpCode {
130 public:
GotoOpCode()131     GotoOpCode() : RegExpOpCode(OP_GOTO, RegExpOpCode::OP_SIZE_FIVE) {}
132     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
133     void UpdateOpPara(DynChunk *buf, uint32_t offset, uint32_t para) const;
134     ~GotoOpCode() override = default;
135     NO_COPY_SEMANTIC(GotoOpCode);
136     NO_MOVE_SEMANTIC(GotoOpCode);
137     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
138 };
139 
140 class SplitNextOpCode : public RegExpOpCode {
141 public:
SplitNextOpCode()142     SplitNextOpCode() : RegExpOpCode(OP_SPLIT_NEXT, RegExpOpCode::OP_SIZE_FIVE) {}
143     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const;
144     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
145     ~SplitNextOpCode() override = default;
146     NO_COPY_SEMANTIC(SplitNextOpCode);
147     NO_MOVE_SEMANTIC(SplitNextOpCode);
148     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
149 };
150 
151 class SplitFirstOpCode : public RegExpOpCode {
152 public:
SplitFirstOpCode()153     SplitFirstOpCode() : RegExpOpCode(OP_SPLIT_FIRST, RegExpOpCode::OP_SIZE_FIVE) {}
154     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const;
155     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
156     ~SplitFirstOpCode() override = default;
157     NO_COPY_SEMANTIC(SplitFirstOpCode);
158     NO_MOVE_SEMANTIC(SplitFirstOpCode);
159     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
160 };
161 
162 class PushOpCode : public RegExpOpCode {
163 public:
PushOpCode()164     PushOpCode() : RegExpOpCode(OP_PUSH, RegExpOpCode::OP_SIZE_ONE) {}
165     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset) const;
166     ~PushOpCode() override = default;
167     NO_COPY_SEMANTIC(PushOpCode);
168     NO_MOVE_SEMANTIC(PushOpCode);
169     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
170 };
171 
172 class PopOpCode : public RegExpOpCode {
173 public:
PopOpCode()174     PopOpCode() : RegExpOpCode(OP_POP, RegExpOpCode::OP_SIZE_ONE) {}
175     uint32_t EmitOpCode(DynChunk *buf) const;
176     ~PopOpCode() override = default;
177     NO_COPY_SEMANTIC(PopOpCode);
178     NO_MOVE_SEMANTIC(PopOpCode);
179     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
180 };
181 
182 class PushCharOpCode : public RegExpOpCode {
183 public:
PushCharOpCode()184     PushCharOpCode() : RegExpOpCode(OP_PUSH_CHAR, RegExpOpCode::OP_SIZE_ONE) {}
185     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset) const;
186     ~PushCharOpCode() override = default;
187     NO_COPY_SEMANTIC(PushCharOpCode);
188     NO_MOVE_SEMANTIC(PushCharOpCode);
189     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
190 };
191 
192 class CheckCharOpCode : public RegExpOpCode {
193 public:
CheckCharOpCode()194     CheckCharOpCode() : RegExpOpCode(OP_CHECK_CHAR, RegExpOpCode::OP_SIZE_FIVE) {}
195     uint32_t EmitOpCode(DynChunk *buf, uint32_t offset) const;
196     ~CheckCharOpCode() override = default;
197     NO_COPY_SEMANTIC(CheckCharOpCode);
198     NO_MOVE_SEMANTIC(CheckCharOpCode);
199     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
200 };
201 
202 class LoopOpCode : public RegExpOpCode {
203 public:
LoopOpCode()204     LoopOpCode() : RegExpOpCode(OP_LOOP, RegExpOpCode::OP_SIZE_THIRTEEN) {}
205     uint32_t EmitOpCode(DynChunk *buf, uint32_t start, uint32_t min, uint32_t max) const;
206     ~LoopOpCode() override = default;
207     NO_COPY_SEMANTIC(LoopOpCode);
208     NO_MOVE_SEMANTIC(LoopOpCode);
209     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
210 };
211 
212 class LoopGreedyOpCode : public RegExpOpCode {
213 public:
LoopGreedyOpCode()214     LoopGreedyOpCode() : RegExpOpCode(OP_LOOP_GREEDY, RegExpOpCode::OP_SIZE_THIRTEEN) {}
215     uint32_t EmitOpCode(DynChunk *buf, uint32_t start, uint32_t min, uint32_t max) const;
216     ~LoopGreedyOpCode() override = default;
217     NO_COPY_SEMANTIC(LoopGreedyOpCode);
218     NO_MOVE_SEMANTIC(LoopGreedyOpCode);
219     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
220 };
221 
222 class SaveResetOpCode : public RegExpOpCode {
223 public:
SaveResetOpCode()224     SaveResetOpCode() : RegExpOpCode(OP_SAVE_RESET, RegExpOpCode::OP_SIZE_THREE) {}
225     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t start, uint32_t end) const;
226     ~SaveResetOpCode() override = default;
227     NO_COPY_SEMANTIC(SaveResetOpCode);
228     NO_MOVE_SEMANTIC(SaveResetOpCode);
229     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
230 };
231 
232 class MatchOpCode : public RegExpOpCode {
233 public:
MatchOpCode()234     MatchOpCode() : RegExpOpCode(OP_MATCH, RegExpOpCode::OP_SIZE_ONE) {}
235     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
236     ~MatchOpCode() override = default;
237     NO_COPY_SEMANTIC(MatchOpCode);
238     NO_MOVE_SEMANTIC(MatchOpCode);
239     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
240 };
241 
242 class MatchEndOpCode : public RegExpOpCode {
243 public:
MatchEndOpCode()244     MatchEndOpCode() : RegExpOpCode(OP_MATCH_END, RegExpOpCode::OP_SIZE_ONE) {}
245     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
246     ~MatchEndOpCode() override = default;
247     NO_COPY_SEMANTIC(MatchEndOpCode);
248     NO_MOVE_SEMANTIC(MatchEndOpCode);
249     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
250 };
251 
252 class LineStartOpCode : public RegExpOpCode {
253 public:
LineStartOpCode()254     LineStartOpCode() : RegExpOpCode(OP_LINE_START, RegExpOpCode::OP_SIZE_ONE) {}
255     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
256     ~LineStartOpCode() override = default;
257     NO_COPY_SEMANTIC(LineStartOpCode);
258     NO_MOVE_SEMANTIC(LineStartOpCode);
259     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
260 };
261 
262 class LineEndOpCode : public RegExpOpCode {
263 public:
LineEndOpCode()264     LineEndOpCode() : RegExpOpCode(OP_LINE_END, RegExpOpCode::OP_SIZE_ONE) {}
265     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
266     ~LineEndOpCode() override = default;
267     NO_COPY_SEMANTIC(LineEndOpCode);
268     NO_MOVE_SEMANTIC(LineEndOpCode);
269     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
270 };
271 
272 class WordBoundaryOpCode : public RegExpOpCode {
273 public:
WordBoundaryOpCode()274     WordBoundaryOpCode() : RegExpOpCode(OP_WORD_BOUNDARY, RegExpOpCode::OP_SIZE_ONE) {}
275     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
276     ~WordBoundaryOpCode() override = default;
277     NO_COPY_SEMANTIC(WordBoundaryOpCode);
278     NO_MOVE_SEMANTIC(WordBoundaryOpCode);
279     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
280 };
281 
282 class NotWordBoundaryOpCode : public RegExpOpCode {
283 public:
NotWordBoundaryOpCode()284     NotWordBoundaryOpCode() : RegExpOpCode(OP_NOT_WORD_BOUNDARY, RegExpOpCode::OP_SIZE_ONE) {}
285     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
286     ~NotWordBoundaryOpCode() override = default;
287     NO_COPY_SEMANTIC(NotWordBoundaryOpCode);
288     NO_MOVE_SEMANTIC(NotWordBoundaryOpCode);
289     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
290 };
291 
292 class AllOpCode : public RegExpOpCode {
293 public:
AllOpCode()294     AllOpCode() : RegExpOpCode(OP_ALL, RegExpOpCode::OP_SIZE_ONE) {}
295     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
296     ~AllOpCode() override = default;
297     NO_COPY_SEMANTIC(AllOpCode);
298     NO_MOVE_SEMANTIC(AllOpCode);
299     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
300 };
301 
302 class DotsOpCode : public RegExpOpCode {
303 public:
DotsOpCode()304     DotsOpCode() : RegExpOpCode(OP_DOTS, RegExpOpCode::OP_SIZE_ONE) {}
305     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
306     ~DotsOpCode() override = default;
307     NO_COPY_SEMANTIC(DotsOpCode);
308     NO_MOVE_SEMANTIC(DotsOpCode);
309     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
310 };
311 
312 class RangeSet {
313 public:
314     RangeSet() = default;
RangeSet(uint32_t value)315     explicit RangeSet(uint32_t value)
316     {
317         Insert(value, value);
318     }
RangeSet(uint32_t start,uint32_t end)319     RangeSet(uint32_t start, uint32_t end)
320     {
321         Insert(start, end);
322     }
RangeSet(const std::list<std::pair<uint32_t,uint32_t>> & rangeSet)323     explicit RangeSet(const std::list<std::pair<uint32_t, uint32_t>> &rangeSet)
324     {
325         rangeSet_ = rangeSet;
326     }
327     ~RangeSet() = default;
328 
IsIntersect(uint64_t start,uint64_t end,uint64_t start1,uint64_t end1)329     inline bool IsIntersect(uint64_t start, uint64_t end, uint64_t start1, uint64_t end1) const
330     {
331         return ((start1 > start) && (start1 < end)) || ((start > start1) && (start < end1));
332     }
IsAdjacent(uint64_t start,uint64_t end,uint64_t start1,uint64_t end1)333     inline bool IsAdjacent(uint64_t start, uint64_t end, uint64_t start1, uint64_t end1) const
334     {
335         return ((end == start1 || (end + 1) == start1)) || ((end1 == start) || (end1 + 1 == start));
336     }
337 
338     inline bool operator==(const RangeSet &other) const
339     {
340         return rangeSet_ == other.rangeSet_;
341     }
342 
IsContain(uint32_t value)343     inline bool IsContain(uint32_t value) const
344     {
345         for (auto range : rangeSet_) {
346             if (value >= range.first && value <= range.second) {
347                 return true;
348             }
349         }
350         return false;
351     }
HighestValue()352     inline uint32_t HighestValue() const
353     {
354         if (!rangeSet_.empty()) {
355             return rangeSet_.back().second;
356         }
357         return 0;
358     }
359     RangeSet(RangeSet const &) = default;
360     RangeSet &operator=(RangeSet const &) = default;
361     RangeSet(RangeSet &&) = default;
362     RangeSet &operator=(RangeSet &&) = default;
363 
364     void Insert(uint32_t start, uint32_t end);
365     void Insert(const RangeSet &s1);
366     void Invert(bool isUtf16);
367     void Inter(RangeSet &cr, const RangeSet &s1);
368     void Compress();
369 
370 private:
371     friend class RangeOpCode;
372     friend class Range32OpCode;
373     std::list<std::pair<uint32_t, uint32_t>> rangeSet_ {};
374 };
375 
376 class RangeOpCode : public RegExpOpCode {
377 public:
RangeOpCode()378     RangeOpCode() : RegExpOpCode(OP_RANGE, RegExpOpCode::OP_SIZE_ONE) {}
379     ~RangeOpCode() override = default;
380     NO_COPY_SEMANTIC(RangeOpCode);
381     NO_MOVE_SEMANTIC(RangeOpCode);
382     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
383     uint32_t InsertOpCode(DynChunk *buf, const RangeSet &rangeSet) const;
384 };
385 
386 class MatchAheadOpCode : public RegExpOpCode {
387 public:
MatchAheadOpCode()388     MatchAheadOpCode() : RegExpOpCode(OP_MATCH_AHEAD, RegExpOpCode::OP_SIZE_FIVE) {}
389     ~MatchAheadOpCode() override = default;
390     NO_COPY_SEMANTIC(MatchAheadOpCode);
391     NO_MOVE_SEMANTIC(MatchAheadOpCode);
392     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
393     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const;
394 };
395 
396 class NegativeMatchAheadOpCode : public RegExpOpCode {
397 public:
NegativeMatchAheadOpCode()398     NegativeMatchAheadOpCode() : RegExpOpCode(OP_NEGATIVE_MATCH_AHEAD, RegExpOpCode::OP_SIZE_FIVE) {}
399     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const;
400     ~NegativeMatchAheadOpCode() override = default;
401     NO_COPY_SEMANTIC(NegativeMatchAheadOpCode);
402     NO_MOVE_SEMANTIC(NegativeMatchAheadOpCode);
403     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
404 };
405 
406 class PrevOpCode : public RegExpOpCode {
407 public:
PrevOpCode()408     PrevOpCode() : RegExpOpCode(OP_PREV, RegExpOpCode::OP_SIZE_ONE) {}
409     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
410     ~PrevOpCode() override = default;
411     NO_COPY_SEMANTIC(PrevOpCode);
412     NO_MOVE_SEMANTIC(PrevOpCode);
413     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
414 };
415 
416 class BackReferenceOpCode : public RegExpOpCode {
417 public:
BackReferenceOpCode()418     BackReferenceOpCode() : RegExpOpCode(OP_BACKREFERENCE, RegExpOpCode::OP_SIZE_TWO) {}
419     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
420     ~BackReferenceOpCode() override = default;
421     NO_COPY_SEMANTIC(BackReferenceOpCode);
422     NO_MOVE_SEMANTIC(BackReferenceOpCode);
423     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
424 };
425 
426 class BackwardBackReferenceOpCode : public RegExpOpCode {
427 public:
BackwardBackReferenceOpCode()428     BackwardBackReferenceOpCode() : RegExpOpCode(OP_BACKWARD_BACKREFERENCE, RegExpOpCode::OP_SIZE_TWO) {}
429     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
430     ~BackwardBackReferenceOpCode() override = default;
431     NO_COPY_SEMANTIC(BackwardBackReferenceOpCode);
432     NO_MOVE_SEMANTIC(BackwardBackReferenceOpCode);
433     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
434 };
435 
436 class Char32OpCode : public RegExpOpCode {
437 public:
Char32OpCode()438     Char32OpCode() : RegExpOpCode(OP_CHAR32, RegExpOpCode::OP_SIZE_FIVE) {}
439     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
440     ~Char32OpCode() override = default;
441     NO_COPY_SEMANTIC(Char32OpCode);
442     NO_MOVE_SEMANTIC(Char32OpCode);
443     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
444 };
445 
446 class Range32OpCode : public RegExpOpCode {
447 public:
Range32OpCode()448     Range32OpCode() : RegExpOpCode(OP_RANGE32, RegExpOpCode::OP_SIZE_ONE) {}
449     ~Range32OpCode() override = default;
450     NO_COPY_SEMANTIC(Range32OpCode);
451     NO_MOVE_SEMANTIC(Range32OpCode);
452     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
453     uint32_t InsertOpCode(DynChunk *buf, const RangeSet &rangeSet) const;
454 };
455 
456 class SparseOpCode : public RegExpOpCode {
457 public:
SparseOpCode()458     SparseOpCode() : RegExpOpCode(OP_RANGE32, RegExpOpCode::OP_SIZE_ONE) {}
459     ~SparseOpCode() override = default;
460     NO_COPY_SEMANTIC(SparseOpCode);
461     NO_MOVE_SEMANTIC(SparseOpCode);
462     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
463 };
464 }  // namespace ecmascript
465 }  // namespace panda
466 #endif
467