Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: src/jsregexp.cc

Issue 10992: Implement $ for non-multiline. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/jsregexp.h ('k') | src/regexp-macro-assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 } 985 }
986 #endif 986 #endif
987 return array; 987 return array;
988 } 988 }
989 989
990 990
991 bool RegExpNode::GoTo(RegExpCompiler* compiler) { 991 bool RegExpNode::GoTo(RegExpCompiler* compiler) {
992 // TODO(erikcorry): Implement support. 992 // TODO(erikcorry): Implement support.
993 if (info_.follows_word_interest || 993 if (info_.follows_word_interest ||
994 info_.follows_newline_interest || 994 info_.follows_newline_interest ||
995 info_.follows_start_interest || 995 info_.follows_start_interest) {
996 info_.at_end) {
997 return false; 996 return false;
998 } 997 }
999 if (label_.is_bound()) { 998 if (label_.is_bound()) {
1000 compiler->macro_assembler()->GoTo(&label_); 999 compiler->macro_assembler()->GoTo(&label_);
1001 return true; 1000 return true;
1002 } else { 1001 } else {
1003 if (compiler->recursion_depth() > RegExpCompiler::kMaxRecursion) { 1002 if (compiler->recursion_depth() > RegExpCompiler::kMaxRecursion) {
1004 compiler->macro_assembler()->GoTo(&label_); 1003 compiler->macro_assembler()->GoTo(&label_);
1005 compiler->AddWork(this); 1004 compiler->AddWork(this);
1006 return true; 1005 return true;
1007 } else { 1006 } else {
1008 compiler->IncrementRecursionDepth(); 1007 compiler->IncrementRecursionDepth();
1009 bool how_it_went = Emit(compiler); 1008 bool how_it_went = Emit(compiler);
1010 compiler->DecrementRecursionDepth(); 1009 compiler->DecrementRecursionDepth();
1011 return how_it_went; 1010 return how_it_went;
1012 } 1011 }
1013 } 1012 }
1014 } 1013 }
1015 1014
1016 1015
1016 // EndNodes are special. Because they can be very common and they are very
1017 // short we normally inline them. That is, if we are asked to emit a GoTo
1018 // we just emit the entire node. Since they don't have successors this
1019 // works.
1017 bool EndNode::GoTo(RegExpCompiler* compiler) { 1020 bool EndNode::GoTo(RegExpCompiler* compiler) {
1018 if (info()->follows_word_interest || 1021 if (info()->follows_word_interest ||
1019 info()->follows_newline_interest || 1022 info()->follows_newline_interest ||
1020 info()->follows_start_interest || 1023 info()->follows_start_interest) {
1021 info()->at_end) {
1022 return false; 1024 return false;
1023 } 1025 }
1024 if (!label()->is_bound()) { 1026 return Emit(compiler);
1025 Bind(compiler->macro_assembler());
1026 }
1027 switch (action_) {
1028 case ACCEPT:
1029 compiler->macro_assembler()->Succeed();
1030 break;
1031 case BACKTRACK:
1032 compiler->macro_assembler()->Backtrack();
1033 break;
1034 }
1035 return true;
1036 } 1027 }
1037 1028
1038 1029
1039 Label* RegExpNode::label() { 1030 Label* RegExpNode::label() {
1040 return &label_; 1031 return &label_;
1041 } 1032 }
1042 1033
1043 1034
1044 bool EndNode::Emit(RegExpCompiler* compiler) { 1035 bool EndNode::Emit(RegExpCompiler* compiler) {
1045 RegExpMacroAssembler* macro = compiler->macro_assembler(); 1036 RegExpMacroAssembler* macro = compiler->macro_assembler();
1046 switch (action_) { 1037 switch (action_) {
1047 case ACCEPT: 1038 case ACCEPT:
1048 Bind(macro); 1039 if (!label()->is_bound()) Bind(macro);
1040 if (info()->at_end) {
1041 Label succeed;
1042 // LoadCurrentCharacter will go to the label if we are at the end of the
1043 // input string.
1044 macro->LoadCurrentCharacter(0, &succeed);
1045 macro->Backtrack();
1046 macro->Bind(&succeed);
1047 }
1049 macro->Succeed(); 1048 macro->Succeed();
1050 return true; 1049 return true;
1051 case BACKTRACK: 1050 case BACKTRACK:
1052 Bind(macro); 1051 if (!label()->is_bound()) Bind(macro);
1052 ASSERT(!info()->at_end);
1053 macro->Backtrack(); 1053 macro->Backtrack();
1054 return true; 1054 return true;
1055 } 1055 }
1056 return false; 1056 return false;
1057 } 1057 }
1058 1058
1059 1059
1060 void GuardedAlternative::AddGuard(Guard* guard) { 1060 void GuardedAlternative::AddGuard(Guard* guard) {
1061 if (guards_ == NULL) 1061 if (guards_ == NULL)
1062 guards_ = new ZoneList<Guard*>(1); 1062 guards_ = new ZoneList<Guard*>(1);
(...skipping 18 matching lines...) Expand all
1081 } 1081 }
1082 1082
1083 1083
1084 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) { 1084 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) {
1085 ActionNode* result = new ActionNode(STORE_POSITION, on_success); 1085 ActionNode* result = new ActionNode(STORE_POSITION, on_success);
1086 result->data_.u_position_register.reg = reg; 1086 result->data_.u_position_register.reg = reg;
1087 return result; 1087 return result;
1088 } 1088 }
1089 1089
1090 1090
1091 ActionNode* ActionNode::SavePosition(int reg, RegExpNode* on_success) {
1092 ActionNode* result = new ActionNode(SAVE_POSITION, on_success);
1093 result->data_.u_position_register.reg = reg;
1094 return result;
1095 }
1096
1097
1098 ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) { 1091 ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) {
1099 ActionNode* result = new ActionNode(RESTORE_POSITION, on_success); 1092 ActionNode* result = new ActionNode(RESTORE_POSITION, on_success);
1100 result->data_.u_position_register.reg = reg; 1093 result->data_.u_position_register.reg = reg;
1101 return result; 1094 return result;
1102 } 1095 }
1103 1096
1104 1097
1105 ActionNode* ActionNode::BeginSubmatch(int reg, RegExpNode* on_success) { 1098 ActionNode* ActionNode::BeginSubmatch(int stack_reg,
1099 int position_reg,
1100 RegExpNode* on_success) {
1106 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success); 1101 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success);
1107 result->data_.u_submatch_stack_pointer_register.reg = reg; 1102 result->data_.u_submatch.stack_pointer_register = stack_reg;
1103 result->data_.u_submatch.current_position_register = position_reg;
1108 return result; 1104 return result;
1109 } 1105 }
1110 1106
1111 1107
1112 ActionNode* ActionNode::EscapeSubmatch(int reg, RegExpNode* on_success) { 1108 ActionNode* ActionNode::EscapeSubmatch(int stack_reg,
1109 bool restore_position,
1110 int position_reg,
1111 RegExpNode* on_success) {
1113 ActionNode* result = new ActionNode(ESCAPE_SUBMATCH, on_success); 1112 ActionNode* result = new ActionNode(ESCAPE_SUBMATCH, on_success);
1114 result->data_.u_submatch_stack_pointer_register.reg = reg; 1113 result->data_.u_submatch.stack_pointer_register = stack_reg;
1114 if (restore_position) {
1115 result->data_.u_submatch.current_position_register = position_reg;
1116 } else {
1117 result->data_.u_submatch.current_position_register = -1;
1118 }
1115 return result; 1119 return result;
1116 } 1120 }
1117 1121
1118 1122
1119 #define DEFINE_ACCEPT(Type) \ 1123 #define DEFINE_ACCEPT(Type) \
1120 void Type##Node::Accept(NodeVisitor* visitor) { \ 1124 void Type##Node::Accept(NodeVisitor* visitor) { \
1121 visitor->Visit##Type(this); \ 1125 visitor->Visit##Type(this); \
1122 } 1126 }
1123 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) 1127 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT)
1124 #undef DEFINE_ACCEPT 1128 #undef DEFINE_ACCEPT
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1313 } 1317 }
1314 macro_assembler->Bind(&success); 1318 macro_assembler->Bind(&success);
1315 } 1319 }
1316 1320
1317 1321
1318 1322
1319 bool TextNode::Emit(RegExpCompiler* compiler) { 1323 bool TextNode::Emit(RegExpCompiler* compiler) {
1320 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 1324 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
1321 Bind(macro_assembler); 1325 Bind(macro_assembler);
1322 int element_count = elms_->length(); 1326 int element_count = elms_->length();
1327 ASSERT(element_count != 0);
1323 int cp_offset = 0; 1328 int cp_offset = 0;
1329 if (info()->at_end) {
1330 macro_assembler->Backtrack();
1331 return true;
1332 }
1324 // First, handle straight character matches. 1333 // First, handle straight character matches.
1325 for (int i = 0; i < element_count; i++) { 1334 for (int i = 0; i < element_count; i++) {
1326 TextElement elm = elms_->at(i); 1335 TextElement elm = elms_->at(i);
1327 if (elm.type == TextElement::ATOM) { 1336 if (elm.type == TextElement::ATOM) {
1328 Vector<const uc16> quarks = elm.data.u_atom->data(); 1337 Vector<const uc16> quarks = elm.data.u_atom->data();
1329 if (compiler->ignore_case()) { 1338 if (compiler->ignore_case()) {
1330 EmitAtomNonLetters(macro_assembler, 1339 EmitAtomNonLetters(macro_assembler,
1331 elm, 1340 elm,
1332 quarks, 1341 quarks,
1333 on_failure_->label(), 1342 on_failure_->label(),
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 bool ok = on_success()->GoTo(compiler); 1483 bool ok = on_success()->GoTo(compiler);
1475 if (!ok) { 1484 if (!ok) {
1476 undo.Unuse(); 1485 undo.Unuse();
1477 return false; 1486 return false;
1478 } 1487 }
1479 macro->Bind(&undo); 1488 macro->Bind(&undo);
1480 macro->PopRegister(data_.u_position_register.reg); 1489 macro->PopRegister(data_.u_position_register.reg);
1481 macro->Backtrack(); 1490 macro->Backtrack();
1482 break; 1491 break;
1483 } 1492 }
1484 case SAVE_POSITION:
1485 macro->WriteCurrentPositionToRegister(
1486 data_.u_position_register.reg);
1487 break;
1488 case RESTORE_POSITION: 1493 case RESTORE_POSITION:
1489 macro->ReadCurrentPositionFromRegister( 1494 macro->ReadCurrentPositionFromRegister(
1490 data_.u_position_register.reg); 1495 data_.u_position_register.reg);
1491 break; 1496 break;
1492 case BEGIN_SUBMATCH: 1497 case BEGIN_SUBMATCH:
1498 macro->WriteCurrentPositionToRegister(
1499 data_.u_submatch.current_position_register);
1493 macro->WriteStackPointerToRegister( 1500 macro->WriteStackPointerToRegister(
1494 data_.u_submatch_stack_pointer_register.reg); 1501 data_.u_submatch.stack_pointer_register);
1495 break; 1502 break;
1496 case ESCAPE_SUBMATCH: 1503 case ESCAPE_SUBMATCH:
1504 if (info()->at_end) {
1505 Label at_end;
1506 // Load current character jumps to the label if we are beyond the string
1507 // end.
1508 macro->LoadCurrentCharacter(0, &at_end);
1509 macro->Backtrack();
1510 macro->Bind(&at_end);
1511 }
1512 if (data_.u_submatch.current_position_register != -1) {
1513 macro->ReadCurrentPositionFromRegister(
1514 data_.u_submatch.current_position_register);
1515 }
1497 macro->ReadStackPointerFromRegister( 1516 macro->ReadStackPointerFromRegister(
1498 data_.u_submatch_stack_pointer_register.reg); 1517 data_.u_submatch.stack_pointer_register);
1499 break; 1518 break;
1500 default: 1519 default:
1501 UNREACHABLE(); 1520 UNREACHABLE();
1502 return false; 1521 return false;
1503 } 1522 }
1504 return on_success()->GoTo(compiler); 1523 return on_success()->GoTo(compiler);
1505 } 1524 }
1506 1525
1507 1526
1508 bool BackReferenceNode::Emit(RegExpCompiler* compiler) { 1527 bool BackReferenceNode::Emit(RegExpCompiler* compiler) {
1509 RegExpMacroAssembler* macro = compiler->macro_assembler(); 1528 RegExpMacroAssembler* macro = compiler->macro_assembler();
1510 Bind(macro); 1529 Bind(macro);
1511 // Check whether the registers are uninitialized and always 1530 // Check whether the registers are uninitialized and always
1512 // succeed if they are. 1531 // succeed if they are.
1513 macro->IfRegisterLT(start_reg_, 0, on_success()->label()); 1532 macro->IfRegisterLT(start_reg_, 0, on_success()->label());
1514 macro->IfRegisterLT(end_reg_, 0, on_success()->label()); 1533 macro->IfRegisterLT(end_reg_, 0, on_success()->label());
1515 ASSERT_EQ(start_reg_ + 1, end_reg_); 1534 ASSERT_EQ(start_reg_ + 1, end_reg_);
1516 if (compiler->ignore_case()) { 1535 if (info()->at_end) {
1517 macro->CheckNotBackReferenceIgnoreCase(start_reg_, on_failure_->label()); 1536 // If we are constrained to match at the end of the input then succeed
1537 // iff the back reference is empty.
1538 macro->CheckNotRegistersEqual(start_reg_, end_reg_, on_failure_->label());
1518 } else { 1539 } else {
1519 macro->CheckNotBackReference(start_reg_, on_failure_->label()); 1540 if (compiler->ignore_case()) {
1541 macro->CheckNotBackReferenceIgnoreCase(start_reg_, on_failure_->label());
1542 } else {
1543 macro->CheckNotBackReference(start_reg_, on_failure_->label());
1544 }
1520 } 1545 }
1521 return on_success()->GoTo(compiler); 1546 return on_success()->GoTo(compiler);
1522 } 1547 }
1523 1548
1524 1549
1525 // ------------------------------------------------------------------- 1550 // -------------------------------------------------------------------
1526 // Dot/dotty output 1551 // Dot/dotty output
1527 1552
1528 1553
1529 #ifdef DEBUG 1554 #ifdef DEBUG
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1744 that->data_.u_store_register.value); 1769 that->data_.u_store_register.value);
1745 break; 1770 break;
1746 case ActionNode::INCREMENT_REGISTER: 1771 case ActionNode::INCREMENT_REGISTER:
1747 stream()->Add("label=\"$%i++\", shape=octagon", 1772 stream()->Add("label=\"$%i++\", shape=octagon",
1748 that->data_.u_increment_register.reg); 1773 that->data_.u_increment_register.reg);
1749 break; 1774 break;
1750 case ActionNode::STORE_POSITION: 1775 case ActionNode::STORE_POSITION:
1751 stream()->Add("label=\"$%i:=$pos\", shape=octagon", 1776 stream()->Add("label=\"$%i:=$pos\", shape=octagon",
1752 that->data_.u_position_register.reg); 1777 that->data_.u_position_register.reg);
1753 break; 1778 break;
1754 case ActionNode::SAVE_POSITION:
1755 stream()->Add("label=\"$%i:=$pos\", shape=octagon",
1756 that->data_.u_position_register.reg);
1757 break;
1758 case ActionNode::RESTORE_POSITION: 1779 case ActionNode::RESTORE_POSITION:
1759 stream()->Add("label=\"$pos:=$%i\", shape=octagon", 1780 stream()->Add("label=\"$pos:=$%i\", shape=octagon",
1760 that->data_.u_position_register.reg); 1781 that->data_.u_position_register.reg);
1761 break; 1782 break;
1762 case ActionNode::BEGIN_SUBMATCH: 1783 case ActionNode::BEGIN_SUBMATCH:
1763 stream()->Add("label=\"begin\", shape=septagon"); 1784 stream()->Add("label=\"$%i:=$pos,begin\", shape=septagon",
1785 that->data_.u_submatch.current_position_register);
1764 break; 1786 break;
1765 case ActionNode::ESCAPE_SUBMATCH: 1787 case ActionNode::ESCAPE_SUBMATCH:
1766 stream()->Add("label=\"escape\", shape=septagon"); 1788 stream()->Add("label=\"escape\", shape=septagon");
1767 break; 1789 break;
1768 } 1790 }
1769 stream()->Add("];\n"); 1791 stream()->Add("];\n");
1770 PrintAttributes(that); 1792 PrintAttributes(that);
1771 stream()->Add(" n%p -> n%p;\n", that, that->on_success()); 1793 stream()->Add(" n%p -> n%p;\n", that, that->on_success());
1772 Visit(that->on_success()); 1794 Visit(that->on_success());
1773 } 1795 }
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1984 // if [body] 2006 // if [body]
1985 // then 2007 // then
1986 // $pos = $reg 2008 // $pos = $reg
1987 // escape submatch scope (drop all backtracks created in scope) 2009 // escape submatch scope (drop all backtracks created in scope)
1988 // succeed 2010 // succeed
1989 // else 2011 // else
1990 // end submatch scope (nothing to clean up, just exit the scope) 2012 // end submatch scope (nothing to clean up, just exit the scope)
1991 // fail 2013 // fail
1992 return ActionNode::BeginSubmatch( 2014 return ActionNode::BeginSubmatch(
1993 stack_pointer_register, 2015 stack_pointer_register,
1994 ActionNode::SavePosition( 2016 position_register,
1995 position_register, 2017 body()->ToNode(
1996 body()->ToNode( 2018 compiler,
1997 compiler, 2019 ActionNode::EscapeSubmatch(
1998 ActionNode::RestorePosition( 2020 stack_pointer_register,
1999 position_register, 2021 true, // Also restore input position.
2000 ActionNode::EscapeSubmatch(stack_pointer_register, 2022 position_register,
2001 on_success)), 2023 on_success),
2002 on_failure))); 2024 on_failure));
2003 } else { 2025 } else {
2004 // begin submatch scope 2026 // begin submatch scope
2005 // try 2027 // try
2006 // first if (body) 2028 // first if (body)
2007 // then 2029 // then
2008 // escape submatch scope 2030 // escape submatch scope
2009 // fail 2031 // fail
2010 // else 2032 // else
2011 // backtrack 2033 // backtrack
2012 // second 2034 // second
2013 // end submatch scope 2035 // end submatch scope
2014 // restore current position 2036 // restore current position
2015 // succeed 2037 // succeed
2016 ChoiceNode* try_node = 2038 ChoiceNode* try_node =
2017 new ChoiceNode(1, ActionNode::RestorePosition(position_register, 2039 new ChoiceNode(1, ActionNode::RestorePosition(position_register,
2018 on_success)); 2040 on_success));
2019 RegExpNode* body_node = body()->ToNode( 2041 RegExpNode* body_node = body()->ToNode(
2020 compiler, 2042 compiler,
2021 ActionNode::EscapeSubmatch(stack_pointer_register, on_failure), 2043 ActionNode::EscapeSubmatch(stack_pointer_register,
2044 false, // Don't also restore position
2045 0, // Unused arguments.
2046 on_failure),
2022 compiler->backtrack()); 2047 compiler->backtrack());
2023 GuardedAlternative body_alt(body_node); 2048 GuardedAlternative body_alt(body_node);
2024 try_node->AddAlternative(body_alt); 2049 try_node->AddAlternative(body_alt);
2025 return ActionNode::BeginSubmatch(stack_pointer_register, 2050 return ActionNode::BeginSubmatch(stack_pointer_register,
2026 ActionNode::SavePosition( 2051 position_register,
2027 position_register, 2052 try_node);
2028 try_node));
2029 } 2053 }
2030 } 2054 }
2031 2055
2032 2056
2033 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, 2057 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
2034 RegExpNode* on_success, 2058 RegExpNode* on_success,
2035 RegExpNode* on_failure) { 2059 RegExpNode* on_failure) {
2036 return ToNode(body(), index(), compiler, on_success, on_failure); 2060 return ToNode(body(), index(), compiler, on_success, on_failure);
2037 } 2061 }
2038 2062
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
2263 2287
2264 RegExpNode* ActionNode::PropagateForward(NodeInfo* info) { 2288 RegExpNode* ActionNode::PropagateForward(NodeInfo* info) {
2265 NodeInfo full_info(*this->info()); 2289 NodeInfo full_info(*this->info());
2266 full_info.AddFromPreceding(info); 2290 full_info.AddFromPreceding(info);
2267 RegExpNode* sibling = GetSibling(&full_info); 2291 RegExpNode* sibling = GetSibling(&full_info);
2268 if (sibling != NULL) return sibling; 2292 if (sibling != NULL) return sibling;
2269 EnsureSiblings(); 2293 EnsureSiblings();
2270 ActionNode* action = new ActionNode(*this); 2294 ActionNode* action = new ActionNode(*this);
2271 action->info()->AddFromPreceding(&full_info); 2295 action->info()->AddFromPreceding(&full_info);
2272 AddSibling(action); 2296 AddSibling(action);
2273 action->set_on_success(action->on_success()->PropagateForward(info)); 2297 if (type_ != ESCAPE_SUBMATCH) {
2298 action->set_on_success(action->on_success()->PropagateForward(info));
2299 }
2274 return action; 2300 return action;
2275 } 2301 }
2276 2302
2277 2303
2278 RegExpNode* ChoiceNode::PropagateForward(NodeInfo* info) { 2304 RegExpNode* ChoiceNode::PropagateForward(NodeInfo* info) {
2279 NodeInfo full_info(*this->info()); 2305 NodeInfo full_info(*this->info());
2280 full_info.AddFromPreceding(info); 2306 full_info.AddFromPreceding(info);
2281 RegExpNode* sibling = GetSibling(&full_info); 2307 RegExpNode* sibling = GetSibling(&full_info);
2282 if (sibling != NULL) return sibling; 2308 if (sibling != NULL) return sibling;
2283 EnsureSiblings(); 2309 EnsureSiblings();
2284 ChoiceNode* choice = new ChoiceNode(*this); 2310 ChoiceNode* choice = new ChoiceNode(*this);
2285 choice->info()->AddFromPreceding(&full_info); 2311 choice->info()->AddFromPreceding(&full_info);
2286 AddSibling(choice); 2312 AddSibling(choice);
2287 ZoneList<GuardedAlternative>* old_alternatives = alternatives(); 2313 ZoneList<GuardedAlternative>* old_alternatives = alternatives();
2288 int count = old_alternatives->length(); 2314 int count = old_alternatives->length();
2289 choice->alternatives_ = new ZoneList<GuardedAlternative>(count); 2315 choice->alternatives_ = new ZoneList<GuardedAlternative>(count);
2290 for (int i = 0; i < count; i++) { 2316 for (int i = 0; i < count; i++) {
2291 GuardedAlternative alternative = old_alternatives->at(i); 2317 GuardedAlternative alternative = old_alternatives->at(i);
2292 alternative.set_node(alternative.node()->PropagateForward(info)); 2318 alternative.set_node(alternative.node()->PropagateForward(info));
2293 choice->alternatives()->Add(alternative); 2319 choice->alternatives()->Add(alternative);
2294 } 2320 }
2321 if (!choice->on_failure_->IsBacktrack()) {
2322 choice->on_failure_ = choice->on_failure_->PropagateForward(info);
2323 }
2295 return choice; 2324 return choice;
2296 } 2325 }
2297 2326
2298 2327
2299 RegExpNode* EndNode::PropagateForward(NodeInfo* info) { 2328 RegExpNode* EndNode::PropagateForward(NodeInfo* info) {
2300 return PropagateToEndpoint(this, info); 2329 return PropagateToEndpoint(this, info);
2301 } 2330 }
2302 2331
2303 2332
2304 RegExpNode* BackReferenceNode::PropagateForward(NodeInfo* info) { 2333 RegExpNode* BackReferenceNode::PropagateForward(NodeInfo* info) {
2305 return PropagateToEndpoint(this, info); 2334 NodeInfo full_info(*this->info());
2335 full_info.AddFromPreceding(info);
2336 RegExpNode* sibling = GetSibling(&full_info);
2337 if (sibling != NULL) return sibling;
2338 EnsureSiblings();
2339 BackReferenceNode* back_ref = new BackReferenceNode(*this);
2340 back_ref->info()->AddFromPreceding(&full_info);
2341 AddSibling(back_ref);
2342 // TODO(erikcorry): A back reference has to have two successors (by default
Christian Plesner Hansen 2008/11/28 08:44:53 I wonder if maybe we always have to propagate to t
2343 // the same node). The first is used if the back reference matches a non-
2344 // empty back reference, the second if it matches an empty one. This doesn't
2345 // matter for at_end, which is the only one implemented right now, but it will
2346 // matter for other pieces of info.
2347 back_ref->set_on_success(back_ref->on_success()->PropagateForward(info));
2348 return back_ref;
2306 } 2349 }
2307 2350
2308 2351
2309 RegExpNode* TextNode::PropagateForward(NodeInfo* info) { 2352 RegExpNode* TextNode::PropagateForward(NodeInfo* info) {
2310 return PropagateToEndpoint(this, info); 2353 return PropagateToEndpoint(this, info);
2311 } 2354 }
2312 2355
2313 2356
2314 // ------------------------------------------------------------------- 2357 // -------------------------------------------------------------------
2315 // Splay tree 2358 // Splay tree
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
2665 captured_body, 2708 captured_body,
2666 compiler.backtrack()); 2709 compiler.backtrack());
2667 if (node_return != NULL) *node_return = node; 2710 if (node_return != NULL) *node_return = node;
2668 Analysis analysis(ignore_case); 2711 Analysis analysis(ignore_case);
2669 analysis.EnsureAnalyzed(node); 2712 analysis.EnsureAnalyzed(node);
2670 2713
2671 if (!FLAG_irregexp) { 2714 if (!FLAG_irregexp) {
2672 return Handle<FixedArray>::null(); 2715 return Handle<FixedArray>::null();
2673 } 2716 }
2674 2717
2718 if (is_multiline && !FLAG_attempt_multiline_irregexp) {
2719 return Handle<FixedArray>::null();
2720 }
2721
2675 if (FLAG_irregexp_native) { 2722 if (FLAG_irregexp_native) {
2676 #ifdef ARM 2723 #ifdef ARM
2677 UNIMPLEMENTED(); 2724 UNIMPLEMENTED();
2678 #else // IA32 2725 #else // IA32
2679 RegExpMacroAssemblerIA32 macro_assembler(RegExpMacroAssemblerIA32::UC16, 2726 RegExpMacroAssemblerIA32 macro_assembler(RegExpMacroAssemblerIA32::UC16,
2680 (input->capture_count + 1) * 2); 2727 (input->capture_count + 1) * 2);
2681 return compiler.Assemble(&macro_assembler, 2728 return compiler.Assemble(&macro_assembler,
2682 node, 2729 node,
2683 input->capture_count); 2730 input->capture_count);
2684 #endif 2731 #endif
2685 } 2732 }
2686 byte codes[1024]; 2733 byte codes[1024];
2687 IrregexpAssembler assembler(Vector<byte>(codes, 1024)); 2734 IrregexpAssembler assembler(Vector<byte>(codes, 1024));
2688 RegExpMacroAssemblerIrregexp macro_assembler(&assembler); 2735 RegExpMacroAssemblerIrregexp macro_assembler(&assembler);
2689 return compiler.Assemble(&macro_assembler, 2736 return compiler.Assemble(&macro_assembler,
2690 node, 2737 node,
2691 input->capture_count); 2738 input->capture_count);
2692 } 2739 }
2693 2740
2694 2741
2695 }} // namespace v8::internal 2742 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/regexp-macro-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698