Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
regexp_ast.cc
Go to the documentation of this file.
1// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/regexp_ast.h"
6
7#include "platform/utils.h"
8#include "vm/os.h"
9
10namespace dart {
11
12#define MAKE_ACCEPT(Name) \
13 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \
14 return visitor->Visit##Name(this, data); \
15 }
17#undef MAKE_ACCEPT
18
19#define MAKE_TYPE_CASE(Name) \
20 RegExp##Name* RegExpTree::As##Name() { \
21 return nullptr; \
22 } \
23 bool RegExpTree::Is##Name() const { \
24 return false; \
25 }
27#undef MAKE_TYPE_CASE
28
29#define MAKE_TYPE_CASE(Name) \
30 RegExp##Name* RegExp##Name::As##Name() { \
31 return this; \
32 } \
33 bool RegExp##Name::Is##Name() const { \
34 return true; \
35 }
37#undef MAKE_TYPE_CASE
38
41 for (intptr_t i = 0; i < children->length(); i++)
42 result = result.Union(children->At(i)->CaptureRegisters());
43 return result;
44}
45
49
53
57
62
66
70
74
77 for (intptr_t i = 0; i < nodes->length(); i++) {
78 RegExpTree* node = nodes->At(i);
79 if (node->IsAnchoredAtStart()) {
80 return true;
81 }
82 if (node->max_match() > 0) {
83 return false;
84 }
85 }
86 return false;
87}
88
91 for (intptr_t i = nodes->length() - 1; i >= 0; i--) {
92 RegExpTree* node = nodes->At(i);
93 if (node->IsAnchoredAtEnd()) {
94 return true;
95 }
96 if (node->max_match() > 0) {
97 return false;
98 }
99 }
100 return false;
101}
102
105 for (intptr_t i = 0; i < alternatives->length(); i++) {
106 if (!alternatives->At(i)->IsAnchoredAtStart()) return false;
107 }
108 return true;
109}
110
113 for (intptr_t i = 0; i < alternatives->length(); i++) {
114 if (!alternatives->At(i)->IsAnchoredAtEnd()) return false;
115 }
116 return true;
117}
118
120 return is_positive() && type() == LOOKAHEAD && body()->IsAnchoredAtStart();
121}
122
124 return body()->IsAnchoredAtStart();
125}
126
128 return body()->IsAnchoredAtEnd();
129}
130
131// Convert regular expression trees to a simple sexp representation.
132// This representation should be different from the input grammar
133// in as many cases as possible, to make it more difficult for incorrect
134// parses to look as correct ones which is likely if the input and
135// output formats are alike.
137 public:
139#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
141#undef MAKE_CASE
142};
143
144void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
145 OS::PrintErr("(|");
146 for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
147 OS::PrintErr(" ");
148 (*that->alternatives())[i]->Accept(this, data);
149 }
150 OS::PrintErr(")");
151 return nullptr;
152}
153
154void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
155 OS::PrintErr("(:");
156 for (intptr_t i = 0; i < that->nodes()->length(); i++) {
157 OS::PrintErr(" ");
158 (*that->nodes())[i]->Accept(this, data);
159 }
160 OS::PrintErr(")");
161 return nullptr;
162}
163
165 PrintUtf16(that.from());
166 if (!that.IsSingleton()) {
167 OS::PrintErr("-");
168 PrintUtf16(that.to());
169 }
170}
171
172void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
173 void* data) {
174 if (that->is_negated()) OS::PrintErr("^");
175 OS::PrintErr("[");
176 for (intptr_t i = 0; i < that->ranges()->length(); i++) {
177 if (i > 0) OS::PrintErr(" ");
178 VisitCharacterRange((*that->ranges())[i]);
179 }
180 OS::PrintErr("]");
181 return nullptr;
182}
183
184void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
185 switch (that->assertion_type()) {
187 OS::PrintErr("@^i");
188 break;
190 OS::PrintErr("@$i");
191 break;
193 OS::PrintErr("@^l");
194 break;
196 OS::PrintErr("@$l");
197 break;
199 OS::PrintErr("@b");
200 break;
202 OS::PrintErr("@B");
203 break;
204 }
205 return nullptr;
206}
207
208void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
209 OS::PrintErr("'");
210 ZoneGrowableArray<uint16_t>* chardata = that->data();
211 for (intptr_t i = 0; i < chardata->length(); i++) {
212 PrintUtf16(chardata->At(i));
213 }
214 OS::PrintErr("'");
215 return nullptr;
216}
217
218void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
219 if (that->elements()->length() == 1) {
220 (*that->elements())[0].tree()->Accept(this, data);
221 } else {
222 OS::PrintErr("(!");
223 for (intptr_t i = 0; i < that->elements()->length(); i++) {
224 OS::PrintErr(" ");
225 (*that->elements())[i].tree()->Accept(this, data);
226 }
227 OS::PrintErr(")");
228 }
229 return nullptr;
230}
231
232void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
233 OS::PrintErr("(# %" Pd " ", that->min());
234 if (that->max() == RegExpTree::kInfinity) {
235 OS::PrintErr("- ");
236 } else {
237 OS::PrintErr("%" Pd " ", that->max());
238 }
239 OS::PrintErr(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
240 that->body()->Accept(this, data);
241 OS::PrintErr(")");
242 return nullptr;
243}
244
245void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
246 OS::PrintErr("(^ ");
247 that->body()->Accept(this, data);
248 OS::PrintErr(")");
249 return nullptr;
250}
251
252void* RegExpUnparser::VisitLookaround(RegExpLookaround* that, void* data) {
253 OS::PrintErr("(");
254 OS::PrintErr("(%s %s",
255 (that->type() == RegExpLookaround::LOOKAHEAD ? "->" : "<-"),
256 (that->is_positive() ? "+ " : "- "));
257 that->body()->Accept(this, data);
258 OS::PrintErr(")");
259 return nullptr;
260}
261
262void* RegExpUnparser::VisitBackReference(RegExpBackReference* that, void*) {
263 OS::PrintErr("(<- %" Pd ")", that->index());
264 return nullptr;
265}
266
267void* RegExpUnparser::VisitEmpty(RegExpEmpty*, void*) {
268 OS::PrintErr("%%");
269 return nullptr;
270}
271
273 RegExpUnparser unparser;
274 Accept(&unparser, nullptr);
275}
276
278 ZoneGrowableArray<RegExpTree*>* alternatives)
279 : alternatives_(alternatives) {
280 ASSERT(alternatives->length() > 1);
281 RegExpTree* first_alternative = alternatives->At(0);
282 min_match_ = first_alternative->min_match();
283 max_match_ = first_alternative->max_match();
284 for (intptr_t i = 1; i < alternatives->length(); i++) {
285 RegExpTree* alternative = alternatives->At(i);
286 min_match_ = Utils::Minimum(min_match_, alternative->min_match());
287 max_match_ = Utils::Maximum(max_match_, alternative->max_match());
288 }
289}
290
291static intptr_t IncreaseBy(intptr_t previous, intptr_t increase) {
292 if (RegExpTree::kInfinity - previous < increase) {
294 } else {
295 return previous + increase;
296 }
297}
298
300 : nodes_(nodes) {
301 ASSERT(nodes->length() > 1);
302 min_match_ = 0;
303 max_match_ = 0;
304 for (intptr_t i = 0; i < nodes->length(); i++) {
305 RegExpTree* node = nodes->At(i);
306 intptr_t node_min_match = node->min_match();
307 min_match_ = IncreaseBy(min_match_, node_min_match);
308 intptr_t node_max_match = node->max_match();
309 max_match_ = IncreaseBy(max_match_, node_max_match);
310 }
311}
312
313} // namespace dart
const T & At(intptr_t index) const
intptr_t length() const
bool IsSingleton() const
Definition regexp.h:60
int32_t to() const
Definition regexp.h:56
int32_t from() const
Definition regexp.h:54
static Interval Empty()
Definition regexp.h:530
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
virtual Interval CaptureRegisters() const
Definition regexp_ast.cc:46
ZoneGrowableArray< RegExpTree * > * nodes() const
Definition regexp_ast.h:93
virtual bool IsAnchoredAtStart() const
Definition regexp_ast.cc:75
virtual bool IsAnchoredAtEnd() const
Definition regexp_ast.cc:89
RegExpAlternative(ZoneGrowableArray< RegExpTree * > *nodes)
virtual bool IsAnchoredAtEnd() const
Definition regexp_ast.cc:71
virtual bool IsAnchoredAtStart() const
Definition regexp_ast.cc:67
AssertionType assertion_type() const
Definition regexp_ast.h:121
virtual Interval CaptureRegisters() const
Definition regexp_ast.cc:58
RegExpTree * body() const
Definition regexp_ast.h:328
virtual bool IsAnchoredAtEnd() const
static intptr_t EndRegister(intptr_t index)
Definition regexp_ast.h:338
static intptr_t StartRegister(intptr_t index)
Definition regexp_ast.h:337
virtual bool IsAnchoredAtStart() const
intptr_t index() const
Definition regexp_ast.h:334
ZoneGrowableArray< CharacterRange > * ranges()
Definition regexp_ast.h:206
RegExpDisjunction(ZoneGrowableArray< RegExpTree * > *alternatives)
virtual bool IsAnchoredAtStart() const
ZoneGrowableArray< RegExpTree * > * alternatives() const
Definition regexp_ast.h:73
virtual bool IsAnchoredAtEnd() const
virtual Interval CaptureRegisters() const
Definition regexp_ast.cc:50
virtual bool IsAnchoredAtStart() const
RegExpTree * body() const
Definition regexp_ast.h:368
bool is_positive() const
Definition regexp_ast.h:369
virtual Interval CaptureRegisters() const
Definition regexp_ast.cc:54
RegExpTree * body() const
Definition regexp_ast.h:300
virtual Interval CaptureRegisters() const
Definition regexp_ast.cc:63
virtual intptr_t min_match() const =0
virtual bool IsAnchoredAtEnd() const
Definition regexp_ast.h:46
virtual Interval CaptureRegisters() const
Definition regexp_ast.h:51
virtual void * Accept(RegExpVisitor *visitor, void *data)=0
virtual intptr_t max_match() const =0
static constexpr intptr_t kInfinity
Definition regexp_ast.h:39
virtual bool IsAnchoredAtStart() const
Definition regexp_ast.h:45
void VisitCharacterRange(CharacterRange that)
static constexpr T Maximum(T x, T y)
Definition utils.h:26
static T Minimum(T x, T y)
Definition utils.h:21
#define ASSERT(E)
GAsyncResult * result
size_t length
static intptr_t IncreaseBy(intptr_t previous, intptr_t increase)
void PrintUtf16(uint16_t c)
static Interval ListCaptureRegisters(ZoneGrowableArray< RegExpTree * > *children)
Definition regexp_ast.cc:39
static int8_t data[kExtLength]
#define MAKE_CASE(CamelName, name)
#define Pd
Definition globals.h:408
#define FOR_EACH_REG_EXP_TREE_TYPE(VISIT)
Definition regexp.h:218
#define MAKE_ACCEPT(Name)
Definition regexp_ast.cc:12
#define MAKE_TYPE_CASE(Name)
Definition regexp_ast.cc:19