OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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(¯o_assembler, | 2728 return compiler.Assemble(¯o_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(¯o_assembler, | 2736 return compiler.Assemble(¯o_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 |
OLD | NEW |