Index: src/jsregexp.cc |
=================================================================== |
--- src/jsregexp.cc (revision 994) |
+++ src/jsregexp.cc (working copy) |
@@ -2695,6 +2695,48 @@ |
// |
// TODO(someone): clear captures on repetition and handle empty |
// matches. |
+ |
+ // 15.10.2.5 RepeatMatcher algorithm. |
+ // The parser has already eliminated the case where max is 0. In the case |
+ // where max_match is zero the parser has removed the quantifier if min was |
+ // > 0 and removed the atom if min was 0. See AddQuantifierToAtom. |
+ |
+ // If we know that we cannot match zero length then things are a little |
+ // simpler since we don't need to make the special zero length match check |
+ // from step 2.1. If the min and max are small we can unroll a little in |
+ // this case. |
+ if (max == 0) return on_success; // This can happen due to recursion. |
+ if (body->min_match() > 0) { |
+ if (min > 0 && min <= 3) { |
Lasse Reichstein
2008/12/18 12:34:17
static const int kMaxUnrollRepetition = 3;
|
+ int new_max = (max == kInfinity) ? max : max - min; |
+ // Recurse once to get the loop or optional matches after the fixed ones. |
+ RegExpNode* answer = |
+ ToNode(0, new_max, is_greedy, body, compiler, on_success); |
+ // Unroll the forced matches from 0 to min. This can cause chains of |
+ // TextNodes (which the parser does not generate). |
Lasse Reichstein
2008/12/18 12:34:17
Will these chains of text nodes normalied at a lat
|
+ for (int i = 0; i < min; i++) { |
+ answer = body->ToNode(compiler, answer); |
+ } |
+ return answer; |
+ } |
+ if (max <= 3) { |
Lasse Reichstein
2008/12/18 12:34:17
Same constant, or another?
|
+ ASSERT(min == 0); |
+ // Unroll the optional matches up to max. |
+ RegExpNode* answer = on_success; |
+ for (int i = 0; i < max; i++) { |
+ ChoiceNode* alternation = new ChoiceNode(2); |
+ if (is_greedy) { |
+ alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler, answer))); |
+ alternation->AddAlternative(GuardedAlternative(on_success)); |
+ } else { |
+ alternation->AddAlternative(GuardedAlternative(on_success)); |
+ alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler, answer))); |
+ } |
+ answer = alternation; |
+ } |
+ return answer; |
+ } |
+ } |
bool has_min = min > 0; |
bool has_max = max < RegExpTree::kInfinity; |
bool needs_counter = has_min || has_max; |