• 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 
71     RegExpOpCode(uint8_t opCode, int size);
72     NO_COPY_SEMANTIC(RegExpOpCode);
73     NO_MOVE_SEMANTIC(RegExpOpCode);
74 
75     virtual ~RegExpOpCode() = default;
76     static RegExpOpCode *GetRegExpOpCode(const DynChunk &buf, int pcOffset);
77     static RegExpOpCode *GetRegExpOpCode(uint8_t opCode);
78     static void DumpRegExpOpCode(std::ostream &out, const DynChunk &buf);
GetSize()79     inline uint8_t GetSize() const
80     {
81         return size_;
82     }
GetOpCode()83     inline uint8_t GetOpCode() const
84     {
85         return opCode_;
86     }
GetDynChunkfSize(const DynChunk & buf)87     inline int GetDynChunkfSize(const DynChunk &buf) const
88     {
89         return buf.size_;
90     }
91     virtual uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const = 0;
92 
93 private:
94     uint8_t opCode_ {0};
95     uint8_t size_ {0};
96 };
97 
98 class SaveStartOpCode : public RegExpOpCode {
99 public:
SaveStartOpCode()100     SaveStartOpCode() : RegExpOpCode(OP_SAVE_START, RegExpOpCode::OP_SIZE_TWO) {}
101     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
102     ~SaveStartOpCode() override = default;
103     NO_COPY_SEMANTIC(SaveStartOpCode);
104     NO_MOVE_SEMANTIC(SaveStartOpCode);
105     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
106 };
107 
108 class SaveEndOpCode : public RegExpOpCode {
109 public:
SaveEndOpCode()110     SaveEndOpCode() : RegExpOpCode(OP_SAVE_END, RegExpOpCode::OP_SIZE_TWO) {}
111     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
112     ~SaveEndOpCode() override = default;
113     NO_COPY_SEMANTIC(SaveEndOpCode);
114     NO_MOVE_SEMANTIC(SaveEndOpCode);
115     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
116 };
117 
118 class CharOpCode : public RegExpOpCode {
119 public:
CharOpCode()120     CharOpCode() : RegExpOpCode(OP_CHAR, RegExpOpCode::OP_SIZE_THREE) {}
121     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
122     ~CharOpCode() override = default;
123     NO_COPY_SEMANTIC(CharOpCode);
124     NO_MOVE_SEMANTIC(CharOpCode);
125     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
126 };
127 
128 class GotoOpCode : public RegExpOpCode {
129 public:
GotoOpCode()130     GotoOpCode() : RegExpOpCode(OP_GOTO, RegExpOpCode::OP_SIZE_FIVE) {}
131     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
132     void UpdateOpPara(DynChunk *buf, uint32_t offset, uint32_t para) const;
133     ~GotoOpCode() override = default;
134     NO_COPY_SEMANTIC(GotoOpCode);
135     NO_MOVE_SEMANTIC(GotoOpCode);
136     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
137 };
138 
139 class SplitNextOpCode : public RegExpOpCode {
140 public:
SplitNextOpCode()141     SplitNextOpCode() : RegExpOpCode(OP_SPLIT_NEXT, RegExpOpCode::OP_SIZE_FIVE) {}
142     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const;
143     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
144     ~SplitNextOpCode() override = default;
145     NO_COPY_SEMANTIC(SplitNextOpCode);
146     NO_MOVE_SEMANTIC(SplitNextOpCode);
147     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
148 };
149 
150 class SplitFirstOpCode : public RegExpOpCode {
151 public:
SplitFirstOpCode()152     SplitFirstOpCode() : RegExpOpCode(OP_SPLIT_FIRST, RegExpOpCode::OP_SIZE_FIVE) {}
153     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const;
154     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
155     ~SplitFirstOpCode() override = default;
156     NO_COPY_SEMANTIC(SplitFirstOpCode);
157     NO_MOVE_SEMANTIC(SplitFirstOpCode);
158     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
159 };
160 
161 class PushOpCode : public RegExpOpCode {
162 public:
PushOpCode()163     PushOpCode() : RegExpOpCode(OP_PUSH, RegExpOpCode::OP_SIZE_ONE) {}
164     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset) const;
165     ~PushOpCode() override = default;
166     NO_COPY_SEMANTIC(PushOpCode);
167     NO_MOVE_SEMANTIC(PushOpCode);
168     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
169 };
170 
171 class PopOpCode : public RegExpOpCode {
172 public:
PopOpCode()173     PopOpCode() : RegExpOpCode(OP_POP, RegExpOpCode::OP_SIZE_ONE) {}
174     uint32_t EmitOpCode(DynChunk *buf) const;
175     ~PopOpCode() override = default;
176     NO_COPY_SEMANTIC(PopOpCode);
177     NO_MOVE_SEMANTIC(PopOpCode);
178     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
179 };
180 
181 class PushCharOpCode : public RegExpOpCode {
182 public:
PushCharOpCode()183     PushCharOpCode() : RegExpOpCode(OP_PUSH_CHAR, RegExpOpCode::OP_SIZE_ONE) {}
184     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset) const;
185     ~PushCharOpCode() override = default;
186     NO_COPY_SEMANTIC(PushCharOpCode);
187     NO_MOVE_SEMANTIC(PushCharOpCode);
188     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
189 };
190 
191 class CheckCharOpCode : public RegExpOpCode {
192 public:
CheckCharOpCode()193     CheckCharOpCode() : RegExpOpCode(OP_CHECK_CHAR, RegExpOpCode::OP_SIZE_FIVE) {}
194     uint32_t EmitOpCode(DynChunk *buf, uint32_t offset) const;
195     ~CheckCharOpCode() override = default;
196     NO_COPY_SEMANTIC(CheckCharOpCode);
197     NO_MOVE_SEMANTIC(CheckCharOpCode);
198     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
199 };
200 
201 class LoopOpCode : public RegExpOpCode {
202 public:
LoopOpCode()203     LoopOpCode() : RegExpOpCode(OP_LOOP, RegExpOpCode::OP_SIZE_THIRTEEN) {}
204     uint32_t EmitOpCode(DynChunk *buf, uint32_t start, uint32_t min, uint32_t max) const;
205     ~LoopOpCode() override = default;
206     NO_COPY_SEMANTIC(LoopOpCode);
207     NO_MOVE_SEMANTIC(LoopOpCode);
208     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
209 };
210 
211 class LoopGreedyOpCode : public RegExpOpCode {
212 public:
LoopGreedyOpCode()213     LoopGreedyOpCode() : RegExpOpCode(OP_LOOP_GREEDY, RegExpOpCode::OP_SIZE_THIRTEEN) {}
214     uint32_t EmitOpCode(DynChunk *buf, uint32_t start, uint32_t min, uint32_t max) const;
215     ~LoopGreedyOpCode() override = default;
216     NO_COPY_SEMANTIC(LoopGreedyOpCode);
217     NO_MOVE_SEMANTIC(LoopGreedyOpCode);
218     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
219 };
220 
221 class SaveResetOpCode : public RegExpOpCode {
222 public:
SaveResetOpCode()223     SaveResetOpCode() : RegExpOpCode(OP_SAVE_RESET, RegExpOpCode::OP_SIZE_THREE) {}
224     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t start, uint32_t end) const;
225     ~SaveResetOpCode() override = default;
226     NO_COPY_SEMANTIC(SaveResetOpCode);
227     NO_MOVE_SEMANTIC(SaveResetOpCode);
228     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
229 };
230 
231 class MatchOpCode : public RegExpOpCode {
232 public:
MatchOpCode()233     MatchOpCode() : RegExpOpCode(OP_MATCH, RegExpOpCode::OP_SIZE_ONE) {}
234     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
235     ~MatchOpCode() override = default;
236     NO_COPY_SEMANTIC(MatchOpCode);
237     NO_MOVE_SEMANTIC(MatchOpCode);
238     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
239 };
240 
241 class MatchEndOpCode : public RegExpOpCode {
242 public:
MatchEndOpCode()243     MatchEndOpCode() : RegExpOpCode(OP_MATCH_END, RegExpOpCode::OP_SIZE_ONE) {}
244     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
245     ~MatchEndOpCode() override = default;
246     NO_COPY_SEMANTIC(MatchEndOpCode);
247     NO_MOVE_SEMANTIC(MatchEndOpCode);
248     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
249 };
250 
251 class LineStartOpCode : public RegExpOpCode {
252 public:
LineStartOpCode()253     LineStartOpCode() : RegExpOpCode(OP_LINE_START, RegExpOpCode::OP_SIZE_ONE) {}
254     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
255     ~LineStartOpCode() override = default;
256     NO_COPY_SEMANTIC(LineStartOpCode);
257     NO_MOVE_SEMANTIC(LineStartOpCode);
258     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
259 };
260 
261 class LineEndOpCode : public RegExpOpCode {
262 public:
LineEndOpCode()263     LineEndOpCode() : RegExpOpCode(OP_LINE_END, RegExpOpCode::OP_SIZE_ONE) {}
264     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
265     ~LineEndOpCode() override = default;
266     NO_COPY_SEMANTIC(LineEndOpCode);
267     NO_MOVE_SEMANTIC(LineEndOpCode);
268     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
269 };
270 
271 class WordBoundaryOpCode : public RegExpOpCode {
272 public:
WordBoundaryOpCode()273     WordBoundaryOpCode() : RegExpOpCode(OP_WORD_BOUNDARY, RegExpOpCode::OP_SIZE_ONE) {}
274     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
275     ~WordBoundaryOpCode() override = default;
276     NO_COPY_SEMANTIC(WordBoundaryOpCode);
277     NO_MOVE_SEMANTIC(WordBoundaryOpCode);
278     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
279 };
280 
281 class NotWordBoundaryOpCode : public RegExpOpCode {
282 public:
NotWordBoundaryOpCode()283     NotWordBoundaryOpCode() : RegExpOpCode(OP_NOT_WORD_BOUNDARY, RegExpOpCode::OP_SIZE_ONE) {}
284     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
285     ~NotWordBoundaryOpCode() override = default;
286     NO_COPY_SEMANTIC(NotWordBoundaryOpCode);
287     NO_MOVE_SEMANTIC(NotWordBoundaryOpCode);
288     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
289 };
290 
291 class AllOpCode : public RegExpOpCode {
292 public:
AllOpCode()293     AllOpCode() : RegExpOpCode(OP_ALL, RegExpOpCode::OP_SIZE_ONE) {}
294     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
295     ~AllOpCode() override = default;
296     NO_COPY_SEMANTIC(AllOpCode);
297     NO_MOVE_SEMANTIC(AllOpCode);
298     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
299 };
300 
301 class DotsOpCode : public RegExpOpCode {
302 public:
DotsOpCode()303     DotsOpCode() : RegExpOpCode(OP_DOTS, RegExpOpCode::OP_SIZE_ONE) {}
304     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
305     ~DotsOpCode() override = default;
306     NO_COPY_SEMANTIC(DotsOpCode);
307     NO_MOVE_SEMANTIC(DotsOpCode);
308     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
309 };
310 
311 class RangeSet {
312 public:
313     RangeSet() = default;
RangeSet(uint32_t value)314     explicit RangeSet(uint32_t value)
315     {
316         Insert(value, value);
317     }
RangeSet(uint32_t start,uint32_t end)318     RangeSet(uint32_t start, uint32_t end)
319     {
320         Insert(start, end);
321     }
RangeSet(const std::list<std::pair<uint32_t,uint32_t>> & rangeSet)322     explicit RangeSet(const std::list<std::pair<uint32_t, uint32_t>> &rangeSet)
323     {
324         rangeSet_ = rangeSet;
325     }
326     ~RangeSet() = default;
327 
IsIntersect(uint64_t start,uint64_t end,uint64_t start1,uint64_t end1)328     inline bool IsIntersect(uint64_t start, uint64_t end, uint64_t start1, uint64_t end1) const
329     {
330         return ((start1 > start) && (start1 < end)) || ((start > start1) && (start < end1));
331     }
IsAdjacent(uint64_t start,uint64_t end,uint64_t start1,uint64_t end1)332     inline bool IsAdjacent(uint64_t start, uint64_t end, uint64_t start1, uint64_t end1) const
333     {
334         return ((end == start1 || (end + 1) == start1)) || ((end1 == start) || (end1 + 1 == start));
335     }
336 
337     inline bool operator==(const RangeSet &other) const
338     {
339         return rangeSet_ == other.rangeSet_;
340     }
341 
IsContain(uint32_t value)342     inline bool IsContain(uint32_t value) const
343     {
344         for (auto range : rangeSet_) {
345             if (value >= range.first && value <= range.second) {
346                 return true;
347             }
348         }
349         return false;
350     }
HighestValue()351     inline uint32_t HighestValue() const
352     {
353         if (!rangeSet_.empty()) {
354             return rangeSet_.back().second;
355         }
356         return 0;
357     }
358     RangeSet(RangeSet const &) = default;
359     RangeSet &operator=(RangeSet const &) = default;
360     RangeSet(RangeSet &&) = default;
361     RangeSet &operator=(RangeSet &&) = default;
362 
363     void Insert(uint32_t start, uint32_t end);
364     void Insert(const RangeSet &s1);
365     void Invert(bool isUtf16);
366     void Inter(RangeSet &cr, const RangeSet &s1);
367     void Compress();
368 
369 private:
370     friend class RangeOpCode;
371     friend class Range32OpCode;
372     std::list<std::pair<uint32_t, uint32_t>> rangeSet_ {};
373 };
374 
375 class RangeOpCode : public RegExpOpCode {
376 public:
RangeOpCode()377     RangeOpCode() : RegExpOpCode(OP_RANGE, RegExpOpCode::OP_SIZE_ONE) {}
378     ~RangeOpCode() override = default;
379     NO_COPY_SEMANTIC(RangeOpCode);
380     NO_MOVE_SEMANTIC(RangeOpCode);
381     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
382     uint32_t InsertOpCode(DynChunk *buf, const RangeSet &rangeSet) const;
383 };
384 
385 class MatchAheadOpCode : public RegExpOpCode {
386 public:
MatchAheadOpCode()387     MatchAheadOpCode() : RegExpOpCode(OP_MATCH_AHEAD, RegExpOpCode::OP_SIZE_FIVE) {}
388     ~MatchAheadOpCode() override = default;
389     NO_COPY_SEMANTIC(MatchAheadOpCode);
390     NO_MOVE_SEMANTIC(MatchAheadOpCode);
391     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
392     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const;
393 };
394 
395 class NegativeMatchAheadOpCode : public RegExpOpCode {
396 public:
NegativeMatchAheadOpCode()397     NegativeMatchAheadOpCode() : RegExpOpCode(OP_NEGATIVE_MATCH_AHEAD, RegExpOpCode::OP_SIZE_FIVE) {}
398     uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const;
399     ~NegativeMatchAheadOpCode() override = default;
400     NO_COPY_SEMANTIC(NegativeMatchAheadOpCode);
401     NO_MOVE_SEMANTIC(NegativeMatchAheadOpCode);
402     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
403 };
404 
405 class PrevOpCode : public RegExpOpCode {
406 public:
PrevOpCode()407     PrevOpCode() : RegExpOpCode(OP_PREV, RegExpOpCode::OP_SIZE_ONE) {}
408     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
409     ~PrevOpCode() override = default;
410     NO_COPY_SEMANTIC(PrevOpCode);
411     NO_MOVE_SEMANTIC(PrevOpCode);
412     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
413 };
414 
415 class BackReferenceOpCode : public RegExpOpCode {
416 public:
BackReferenceOpCode()417     BackReferenceOpCode() : RegExpOpCode(OP_BACKREFERENCE, RegExpOpCode::OP_SIZE_TWO) {}
418     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
419     ~BackReferenceOpCode() override = default;
420     NO_COPY_SEMANTIC(BackReferenceOpCode);
421     NO_MOVE_SEMANTIC(BackReferenceOpCode);
422     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
423 };
424 
425 class BackwardBackReferenceOpCode : public RegExpOpCode {
426 public:
BackwardBackReferenceOpCode()427     BackwardBackReferenceOpCode() : RegExpOpCode(OP_BACKWARD_BACKREFERENCE, RegExpOpCode::OP_SIZE_TWO) {}
428     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
429     ~BackwardBackReferenceOpCode() override = default;
430     NO_COPY_SEMANTIC(BackwardBackReferenceOpCode);
431     NO_MOVE_SEMANTIC(BackwardBackReferenceOpCode);
432     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
433 };
434 
435 class Char32OpCode : public RegExpOpCode {
436 public:
Char32OpCode()437     Char32OpCode() : RegExpOpCode(OP_CHAR32, RegExpOpCode::OP_SIZE_FIVE) {}
438     uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const;
439     ~Char32OpCode() override = default;
440     NO_COPY_SEMANTIC(Char32OpCode);
441     NO_MOVE_SEMANTIC(Char32OpCode);
442     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
443 };
444 
445 class Range32OpCode : public RegExpOpCode {
446 public:
Range32OpCode()447     Range32OpCode() : RegExpOpCode(OP_RANGE32, RegExpOpCode::OP_SIZE_ONE) {}
448     ~Range32OpCode() override = default;
449     NO_COPY_SEMANTIC(Range32OpCode);
450     NO_MOVE_SEMANTIC(Range32OpCode);
451     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
452     uint32_t InsertOpCode(DynChunk *buf, const RangeSet &rangeSet) const;
453 };
454 
455 class SparseOpCode : public RegExpOpCode {
456 public:
SparseOpCode()457     SparseOpCode() : RegExpOpCode(OP_RANGE32, RegExpOpCode::OP_SIZE_ONE) {}
458     ~SparseOpCode() override = default;
459     NO_COPY_SEMANTIC(SparseOpCode);
460     NO_MOVE_SEMANTIC(SparseOpCode);
461     uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override;
462 };
463 }  // namespace ecmascript
464 }  // namespace panda
465 #endif
466