Author: [EMAIL PROTECTED]
Date: Fri Nov 28 00:53:53 2008
New Revision: 862
Modified:
branches/bleeding_edge/src/assembler-irregexp.cc
branches/bleeding_edge/src/assembler-irregexp.h
branches/bleeding_edge/src/bytecodes-irregexp.h
branches/bleeding_edge/src/flag-definitions.h
branches/bleeding_edge/src/interpreter-irregexp.cc
branches/bleeding_edge/src/jsregexp.cc
branches/bleeding_edge/src/jsregexp.h
branches/bleeding_edge/src/regexp-macro-assembler-ia32.cc
branches/bleeding_edge/src/regexp-macro-assembler-ia32.h
branches/bleeding_edge/src/regexp-macro-assembler-irregexp.cc
branches/bleeding_edge/src/regexp-macro-assembler-irregexp.h
branches/bleeding_edge/src/regexp-macro-assembler-tracer.cc
branches/bleeding_edge/src/regexp-macro-assembler-tracer.h
branches/bleeding_edge/src/regexp-macro-assembler.h
branches/bleeding_edge/test/cctest/test-regexp.cc
branches/bleeding_edge/test/mjsunit/regexp.js
Log:
Implement $ for non-multiline.
Review URL: http://codereview.chromium.org/10992
Modified: branches/bleeding_edge/src/assembler-irregexp.cc
==============================================================================
--- branches/bleeding_edge/src/assembler-irregexp.cc (original)
+++ branches/bleeding_edge/src/assembler-irregexp.cc Fri Nov 28 00:53:53
2008
@@ -247,6 +247,16 @@
}
+void IrregexpAssembler::CheckNotRegistersEqual(int reg1,
+ int reg2,
+ Label* on_not_equal) {
+ Emit(BC_CHECK_NOT_REGS_EQUAL);
+ Emit(reg1);
+ Emit(reg2);
+ EmitOrLink(on_not_equal);
+}
+
+
void IrregexpAssembler::CheckRegister(int byte_code,
int reg_index,
uint16_t vs,
Modified: branches/bleeding_edge/src/assembler-irregexp.h
==============================================================================
--- branches/bleeding_edge/src/assembler-irregexp.h (original)
+++ branches/bleeding_edge/src/assembler-irregexp.h Fri Nov 28 00:53:53 2008
@@ -103,6 +103,7 @@
// on_mismatch label will never be called.
void CheckNotBackReference(int capture_index, Label* on_mismatch);
void CheckNotBackReferenceNoCase(int capture_index, Label* on_mismatch);
+ void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
// Checks a register for strictly-less-than or greater-than-or-equal.
void CheckRegisterLT(int reg_index, uint16_t vs, Label* on_less_than);
Modified: branches/bleeding_edge/src/bytecodes-irregexp.h
==============================================================================
--- branches/bleeding_edge/src/bytecodes-irregexp.h (original)
+++ branches/bleeding_edge/src/bytecodes-irregexp.h Fri Nov 28 00:53:53 2008
@@ -58,12 +58,13 @@
V(CHECK_GT, 23, 7) /* check_gr uc16
addr32 */ \
V(CHECK_NOT_BACK_REF, 24, 6) /* check_not_back_ref capture_idx
addr32 */ \
V(CHECK_NOT_BACK_REF_NO_CASE, 25, 6) /* check_not_back_ref_no_case
captu... */ \
-V(LOOKUP_MAP1, 26, 11) /* l_map1 start16 bit_map_addr32
addr32 */ \
-V(LOOKUP_MAP2, 27, 99) /* l_map2 start16
half_nibble_map_addr32* */ \
-V(LOOKUP_MAP8, 28, 99) /* l_map8 start16 byte_map
addr32* */ \
-V(LOOKUP_HI_MAP8, 29, 99) /* l_himap8 start8 byte_map_addr32
addr32* */ \
-V(CHECK_REGISTER_LT, 30, 8) /* check_reg_lt register_index value16
addr32 */ \
-V(CHECK_REGISTER_GE, 31, 8) /* check_reg_ge register_index value16
addr32 */
+V(CHECK_NOT_REGS_EQUAL, 26, 7) /* check_not_regs_equal reg1 reg2
addr32 */ \
+V(LOOKUP_MAP1, 27, 11) /* l_map1 start16 bit_map_addr32
addr32 */ \
+V(LOOKUP_MAP2, 28, 99) /* l_map2 start16
half_nibble_map_addr32* */ \
+V(LOOKUP_MAP8, 29, 99) /* l_map8 start16 byte_map
addr32* */ \
+V(LOOKUP_HI_MAP8, 30, 99) /* l_himap8 start8 byte_map_addr32
addr32* */ \
+V(CHECK_REGISTER_LT, 31, 8) /* check_reg_lt register_index value16
addr32 */ \
+V(CHECK_REGISTER_GE, 32, 8) /* check_reg_ge register_index value16
addr32 */
#define DECLARE_BYTECODES(name, code, length) \
static const int BC_##name = code;
Modified: branches/bleeding_edge/src/flag-definitions.h
==============================================================================
--- branches/bleeding_edge/src/flag-definitions.h (original)
+++ branches/bleeding_edge/src/flag-definitions.h Fri Nov 28 00:53:53 2008
@@ -204,6 +204,7 @@
DEFINE_bool(trace_regexps, false, "trace Irregexp execution")
DEFINE_bool(irregexp_native, false, "use native code Irregexp
implementation (IA32 only)")
DEFINE_bool(disable_jscre, false, "abort if JSCRE is used. Only useful
with --irregexp")
+DEFINE_bool(attempt_multiline_irregexp, false, "attempt to use Irregexp
for multiline regexps")
// Testing flags test/cctest/test-{flags,api,serialization}.cc
DEFINE_bool(testing_bool_flag, true, "testing_bool_flag")
Modified: branches/bleeding_edge/src/interpreter-irregexp.cc
==============================================================================
--- branches/bleeding_edge/src/interpreter-irregexp.cc (original)
+++ branches/bleeding_edge/src/interpreter-irregexp.cc Fri Nov 28 00:53:53
2008
@@ -323,6 +323,13 @@
pc = code_base + Load32(new_pc);
break;
}
+ BYTECODE(CHECK_NOT_REGS_EQUAL)
+ if (registers[pc[1]] == registers[pc[2]]) {
+ pc += BC_CHECK_NOT_REGS_EQUAL_LENGTH;
+ } else {
+ pc = code_base + Load32(pc + 3);
+ }
+ break;
BYTECODE(CHECK_NOT_BACK_REF) {
int from = registers[pc[1]];
int len = registers[pc[1] + 1] - from;
Modified: branches/bleeding_edge/src/jsregexp.cc
==============================================================================
--- branches/bleeding_edge/src/jsregexp.cc (original)
+++ branches/bleeding_edge/src/jsregexp.cc Fri Nov 28 00:53:53 2008
@@ -992,8 +992,7 @@
// TODO(erikcorry): Implement support.
if (info_.follows_word_interest ||
info_.follows_newline_interest ||
- info_.follows_start_interest ||
- info_.at_end) {
+ info_.follows_start_interest) {
return false;
}
if (label_.is_bound()) {
@@ -1014,25 +1013,17 @@
}
+// EndNodes are special. Because they can be very common and they are very
+// short we normally inline them. That is, if we are asked to emit a GoTo
+// we just emit the entire node. Since they don't have successors this
+// works.
bool EndNode::GoTo(RegExpCompiler* compiler) {
if (info()->follows_word_interest ||
info()->follows_newline_interest ||
- info()->follows_start_interest ||
- info()->at_end) {
+ info()->follows_start_interest) {
return false;
}
- if (!label()->is_bound()) {
- Bind(compiler->macro_assembler());
- }
- switch (action_) {
- case ACCEPT:
- compiler->macro_assembler()->Succeed();
- break;
- case BACKTRACK:
- compiler->macro_assembler()->Backtrack();
- break;
- }
- return true;
+ return Emit(compiler);
}
@@ -1045,11 +1036,20 @@
RegExpMacroAssembler* macro = compiler->macro_assembler();
switch (action_) {
case ACCEPT:
- Bind(macro);
+ if (!label()->is_bound()) Bind(macro);
+ if (info()->at_end) {
+ Label succeed;
+ // LoadCurrentCharacter will go to the label if we are at the end
of the
+ // input string.
+ macro->LoadCurrentCharacter(0, &succeed);
+ macro->Backtrack();
+ macro->Bind(&succeed);
+ }
macro->Succeed();
return true;
case BACKTRACK:
- Bind(macro);
+ if (!label()->is_bound()) Bind(macro);
+ ASSERT(!info()->at_end);
macro->Backtrack();
return true;
}
@@ -1088,13 +1088,6 @@
}
-ActionNode* ActionNode::SavePosition(int reg, RegExpNode* on_success) {
- ActionNode* result = new ActionNode(SAVE_POSITION, on_success);
- result->data_.u_position_register.reg = reg;
- return result;
-}
-
-
ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) {
ActionNode* result = new ActionNode(RESTORE_POSITION, on_success);
result->data_.u_position_register.reg = reg;
@@ -1102,16 +1095,27 @@
}
-ActionNode* ActionNode::BeginSubmatch(int reg, RegExpNode* on_success) {
+ActionNode* ActionNode::BeginSubmatch(int stack_reg,
+ int position_reg,
+ RegExpNode* on_success) {
ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success);
- result->data_.u_submatch_stack_pointer_register.reg = reg;
+ result->data_.u_submatch.stack_pointer_register = stack_reg;
+ result->data_.u_submatch.current_position_register = position_reg;
return result;
}
-ActionNode* ActionNode::EscapeSubmatch(int reg, RegExpNode* on_success) {
+ActionNode* ActionNode::EscapeSubmatch(int stack_reg,
+ bool restore_position,
+ int position_reg,
+ RegExpNode* on_success) {
ActionNode* result = new ActionNode(ESCAPE_SUBMATCH, on_success);
- result->data_.u_submatch_stack_pointer_register.reg = reg;
+ result->data_.u_submatch.stack_pointer_register = stack_reg;
+ if (restore_position) {
+ result->data_.u_submatch.current_position_register = position_reg;
+ } else {
+ result->data_.u_submatch.current_position_register = -1;
+ }
return result;
}
@@ -1320,7 +1324,12 @@
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
Bind(macro_assembler);
int element_count = elms_->length();
+ ASSERT(element_count != 0);
int cp_offset = 0;
+ if (info()->at_end) {
+ macro_assembler->Backtrack();
+ return true;
+ }
// First, handle straight character matches.
for (int i = 0; i < element_count; i++) {
TextElement elm = elms_->at(i);
@@ -1481,21 +1490,31 @@
macro->Backtrack();
break;
}
- case SAVE_POSITION:
- macro->WriteCurrentPositionToRegister(
- data_.u_position_register.reg);
- break;
case RESTORE_POSITION:
macro->ReadCurrentPositionFromRegister(
data_.u_position_register.reg);
break;
case BEGIN_SUBMATCH:
+ macro->WriteCurrentPositionToRegister(
+ data_.u_submatch.current_position_register);
macro->WriteStackPointerToRegister(
- data_.u_submatch_stack_pointer_register.reg);
+ data_.u_submatch.stack_pointer_register);
break;
case ESCAPE_SUBMATCH:
+ if (info()->at_end) {
+ Label at_end;
+ // Load current character jumps to the label if we are beyond the
string
+ // end.
+ macro->LoadCurrentCharacter(0, &at_end);
+ macro->Backtrack();
+ macro->Bind(&at_end);
+ }
+ if (data_.u_submatch.current_position_register != -1) {
+ macro->ReadCurrentPositionFromRegister(
+ data_.u_submatch.current_position_register);
+ }
macro->ReadStackPointerFromRegister(
- data_.u_submatch_stack_pointer_register.reg);
+ data_.u_submatch.stack_pointer_register);
break;
default:
UNREACHABLE();
@@ -1513,10 +1532,16 @@
macro->IfRegisterLT(start_reg_, 0, on_success()->label());
macro->IfRegisterLT(end_reg_, 0, on_success()->label());
ASSERT_EQ(start_reg_ + 1, end_reg_);
- if (compiler->ignore_case()) {
- macro->CheckNotBackReferenceIgnoreCase(start_reg_,
on_failure_->label());
+ if (info()->at_end) {
+ // If we are constrained to match at the end of the input then succeed
+ // iff the back reference is empty.
+ macro->CheckNotRegistersEqual(start_reg_, end_reg_,
on_failure_->label());
} else {
- macro->CheckNotBackReference(start_reg_, on_failure_->label());
+ if (compiler->ignore_case()) {
+ macro->CheckNotBackReferenceIgnoreCase(start_reg_,
on_failure_->label());
+ } else {
+ macro->CheckNotBackReference(start_reg_, on_failure_->label());
+ }
}
return on_success()->GoTo(compiler);
}
@@ -1751,16 +1776,13 @@
stream()->Add("label=\"$%i:=$pos\", shape=octagon",
that->data_.u_position_register.reg);
break;
- case ActionNode::SAVE_POSITION:
- stream()->Add("label=\"$%i:=$pos\", shape=octagon",
- that->data_.u_position_register.reg);
- break;
case ActionNode::RESTORE_POSITION:
stream()->Add("label=\"$pos:=$%i\", shape=octagon",
that->data_.u_position_register.reg);
break;
case ActionNode::BEGIN_SUBMATCH:
- stream()->Add("label=\"begin\", shape=septagon");
+ stream()->Add("label=\"$%i:=$pos,begin\", shape=septagon",
+ that->data_.u_submatch.current_position_register);
break;
case ActionNode::ESCAPE_SUBMATCH:
stream()->Add("label=\"escape\", shape=septagon");
@@ -1991,15 +2013,15 @@
// fail
return ActionNode::BeginSubmatch(
stack_pointer_register,
- ActionNode::SavePosition(
- position_register,
- body()->ToNode(
- compiler,
- ActionNode::RestorePosition(
- position_register,
- ActionNode::EscapeSubmatch(stack_pointer_register,
- on_success)),
- on_failure)));
+ position_register,
+ body()->ToNode(
+ compiler,
+ ActionNode::EscapeSubmatch(
+ stack_pointer_register,
+ true, // Also restore input position.
+ position_register,
+ on_success),
+ on_failure));
} else {
// begin submatch scope
// try
@@ -2018,14 +2040,16 @@
on_success));
RegExpNode* body_node = body()->ToNode(
compiler,
- ActionNode::EscapeSubmatch(stack_pointer_register, on_failure),
+ ActionNode::EscapeSubmatch(stack_pointer_register,
+ false, // Don't also restore
position
+ 0, // Unused arguments.
+ on_failure),
compiler->backtrack());
GuardedAlternative body_alt(body_node);
try_node->AddAlternative(body_alt);
return ActionNode::BeginSubmatch(stack_pointer_register,
- ActionNode::SavePosition(
- position_register,
- try_node));
+ position_register,
+ try_node);
}
}
@@ -2270,7 +2294,9 @@
ActionNode* action = new ActionNode(*this);
action->info()->AddFromPreceding(&full_info);
AddSibling(action);
- action->set_on_success(action->on_success()->PropagateForward(info));
+ if (type_ != ESCAPE_SUBMATCH) {
+ action->set_on_success(action->on_success()->PropagateForward(info));
+ }
return action;
}
@@ -2292,6 +2318,9 @@
alternative.set_node(alternative.node()->PropagateForward(info));
choice->alternatives()->Add(alternative);
}
+ if (!choice->on_failure_->IsBacktrack()) {
+ choice->on_failure_ = choice->on_failure_->PropagateForward(info);
+ }
return choice;
}
@@ -2302,7 +2331,21 @@
RegExpNode* BackReferenceNode::PropagateForward(NodeInfo* info) {
- return PropagateToEndpoint(this, info);
+ NodeInfo full_info(*this->info());
+ full_info.AddFromPreceding(info);
+ RegExpNode* sibling = GetSibling(&full_info);
+ if (sibling != NULL) return sibling;
+ EnsureSiblings();
+ BackReferenceNode* back_ref = new BackReferenceNode(*this);
+ back_ref->info()->AddFromPreceding(&full_info);
+ AddSibling(back_ref);
+ // TODO(erikcorry): A back reference has to have two successors (by
default
+ // the same node). The first is used if the back reference matches a
non-
+ // empty back reference, the second if it matches an empty one. This
doesn't
+ // matter for at_end, which is the only one implemented right now, but
it will
+ // matter for other pieces of info.
+ back_ref->set_on_success(back_ref->on_success()->PropagateForward(info));
+ return back_ref;
}
@@ -2669,6 +2712,10 @@
analysis.EnsureAnalyzed(node);
if (!FLAG_irregexp) {
+ return Handle<FixedArray>::null();
+ }
+
+ if (is_multiline && !FLAG_attempt_multiline_irregexp) {
return Handle<FixedArray>::null();
}
Modified: branches/bleeding_edge/src/jsregexp.h
==============================================================================
--- branches/bleeding_edge/src/jsregexp.h (original)
+++ branches/bleeding_edge/src/jsregexp.h Fri Nov 28 00:53:53 2008
@@ -576,7 +576,6 @@
STORE_REGISTER,
INCREMENT_REGISTER,
STORE_POSITION,
- SAVE_POSITION,
RESTORE_POSITION,
BEGIN_SUBMATCH,
ESCAPE_SUBMATCH
@@ -584,10 +583,14 @@
static ActionNode* StoreRegister(int reg, int val, RegExpNode*
on_success);
static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
static ActionNode* StorePosition(int reg, RegExpNode* on_success);
- static ActionNode* SavePosition(int reg, RegExpNode* on_success);
static ActionNode* RestorePosition(int reg, RegExpNode* on_success);
- static ActionNode* BeginSubmatch(int reg, RegExpNode* on_success);
- static ActionNode* EscapeSubmatch(int reg, RegExpNode* on_success);
+ static ActionNode* BeginSubmatch(int stack_pointer_reg,
+ int position_reg,
+ RegExpNode* on_success);
+ static ActionNode* EscapeSubmatch(int stack_pointer_reg,
+ bool and_restore_position,
+ int restore_reg,
+ RegExpNode* on_success);
virtual void Accept(NodeVisitor* visitor);
virtual bool Emit(RegExpCompiler* compiler);
virtual RegExpNode* PropagateForward(NodeInfo* info);
@@ -604,8 +607,9 @@
int reg;
} u_position_register;
struct {
- int reg;
- } u_submatch_stack_pointer_register;
+ int stack_pointer_register;
+ int current_position_register;
+ } u_submatch;
} data_;
ActionNode(Type type, RegExpNode* on_success)
: SeqRegExpNode(on_success),
Modified: branches/bleeding_edge/src/regexp-macro-assembler-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler-ia32.cc (original)
+++ branches/bleeding_edge/src/regexp-macro-assembler-ia32.cc Fri Nov 28
00:53:53 2008
@@ -236,6 +236,16 @@
}
+void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1,
+ int reg2,
+ Label* on_not_equal)
{
+ __ mov(eax, register_location(reg1));
+ __ mov(ecx, register_location(reg2));
+ __ cmp(ecx, Operand(eax));
+ BranchOrBacktrack(not_equal, on_not_equal);
+}
+
+
void RegExpMacroAssemblerIA32::CheckNotCharacter(uc16 c, Label*
on_not_equal) {
__ cmp(edx, c);
BranchOrBacktrack(not_equal, on_not_equal);
Modified: branches/bleeding_edge/src/regexp-macro-assembler-ia32.h
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler-ia32.h (original)
+++ branches/bleeding_edge/src/regexp-macro-assembler-ia32.h Fri Nov 28
00:53:53 2008
@@ -52,6 +52,7 @@
virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
Label* on_no_match);
+ virtual void CheckNotRegistersEqual(int reg1, int reg2, Label*
on_not_equal);
virtual void CheckNotCharacter(uc16 c, Label* on_not_equal);
virtual void CheckNotCharacterAfterOr(uc16 c, uc16 mask, Label*
on_not_equal);
virtual void CheckNotCharacterAfterMinusOr(uc16 c,
Modified: branches/bleeding_edge/src/regexp-macro-assembler-irregexp.cc
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler-irregexp.cc
(original)
+++ branches/bleeding_edge/src/regexp-macro-assembler-irregexp.cc Fri Nov
28 00:53:53 2008
@@ -206,6 +206,13 @@
}
+void RegExpMacroAssemblerIrregexp::CheckNotRegistersEqual(int reg1,
+ int reg2,
+ Label*
on_not_equal) {
+ assembler_->CheckNotRegistersEqual(reg1, reg2, on_not_equal);
+}
+
+
void RegExpMacroAssemblerIrregexp::CheckBitmap(uc16 start,
Label* bitmap,
Label* on_zero) {
Modified: branches/bleeding_edge/src/regexp-macro-assembler-irregexp.h
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler-irregexp.h
(original)
+++ branches/bleeding_edge/src/regexp-macro-assembler-irregexp.h Fri Nov
28
00:53:53 2008
@@ -67,6 +67,7 @@
virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
Label* on_no_match);
+ virtual void CheckNotRegistersEqual(int reg1, int reg2, Label*
on_not_equal);
virtual void CheckCharacters(Vector<const uc16> str,
int cp_offset,
Label* on_failure);
Modified: branches/bleeding_edge/src/regexp-macro-assembler-tracer.cc
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler-tracer.cc (original)
+++ branches/bleeding_edge/src/regexp-macro-assembler-tracer.cc Fri Nov 28
00:53:53 2008
@@ -194,6 +194,18 @@
assembler_->CheckNotBackReferenceIgnoreCase(start_reg, on_no_match);
}
+
+void RegExpMacroAssemblerTracer::CheckNotRegistersEqual(int reg1,
+ int reg2,
+ Label*
on_not_equal) {
+ PrintF(" CheckNotRegistersEqual(reg1=%d, reg2=%d, label[%08x]);\n",
+ reg1,
+ reg2,
+ on_not_equal);
+ assembler_->CheckNotRegistersEqual(reg1, reg2, on_not_equal);
+}
+
+
void RegExpMacroAssemblerTracer::CheckCharacters(Vector<const uc16> str,
int cp_offset,
Label* on_failure) {
Modified: branches/bleeding_edge/src/regexp-macro-assembler-tracer.h
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler-tracer.h (original)
+++ branches/bleeding_edge/src/regexp-macro-assembler-tracer.h Fri Nov 28
00:53:53 2008
@@ -54,6 +54,7 @@
virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
Label* on_no_match);
+ virtual void CheckNotRegistersEqual(int reg1, int reg2, Label*
on_not_equal);
virtual void CheckNotCharacter(uc16 c, Label* on_not_equal);
virtual void CheckNotCharacterAfterOr(uc16 c,
uc16 or_with,
Modified: branches/bleeding_edge/src/regexp-macro-assembler.h
==============================================================================
--- branches/bleeding_edge/src/regexp-macro-assembler.h (original)
+++ branches/bleeding_edge/src/regexp-macro-assembler.h Fri Nov 28 00:53:53
2008
@@ -93,6 +93,7 @@
virtual void CheckNotCharacterAfterMinusOr(uc16 c,
uc16 minus_then_or_with,
Label* on_not_equal) = 0;
+ virtual void CheckNotRegistersEqual(int reg1, int reg2, Label*
on_not_equal) = 0;
// Dispatch after looking the current character up in a byte map. The
// destinations vector has up to 256 labels.
virtual void DispatchByteMap(
Modified: branches/bleeding_edge/test/cctest/test-regexp.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-regexp.cc (original)
+++ branches/bleeding_edge/test/cctest/test-regexp.cc Fri Nov 28 00:53:53
2008
@@ -1226,5 +1226,5 @@
TEST(Graph) {
V8::Initialize(NULL);
- Execute("(?:foo|bar$)", false, true);
+ Execute("foo$(?!bar)", false, true);
}
Modified: branches/bleeding_edge/test/mjsunit/regexp.js
==============================================================================
--- branches/bleeding_edge/test/mjsunit/regexp.js (original)
+++ branches/bleeding_edge/test/mjsunit/regexp.js Fri Nov 28 00:53:53 2008
@@ -244,3 +244,23 @@
assertEquals("bar$000", "foox".replace(re, "bar$000"), "$000");
assertEquals("barx", "foox".replace(re, "bar$01"), "$01 2");
assertEquals("barx5", "foox".replace(re, "bar$15"), "$15");
+
+assertFalse(/()foo$\1/.test("football"), "football1");
+assertFalse(/foo$(?=ball)/.test("football"), "football2");
+assertFalse(/foo$(?!bar)/.test("football"), "football3");
+assertTrue(/()foo$\1/.test("foo"), "football4");
+assertTrue(/foo$(?=(ball)?)/.test("foo"), "football5");
+assertTrue(/()foo$(?!bar)/.test("foo"), "football6");
+assertFalse(/(x?)foo$\1/.test("football"), "football7");
+assertFalse(/foo$(?=ball)/.test("football"), "football8");
+assertFalse(/foo$(?!bar)/.test("football"), "football9");
+assertTrue(/(x?)foo$\1/.test("foo"), "football10");
+assertTrue(/foo$(?=(ball)?)/.test("foo"), "football11");
+assertTrue(/foo$(?!bar)/.test("foo"), "football12");
+
+// Check that the back reference has two successors. See
+// BackReferenceNode::PropagateForward.
+assertFalse(/f(o)\b\1/.test('foo'));
+assertTrue(/f(o)\B\1/.test('foo'));
+
+assertFalse(/f(o)$\1/.test('foo'), "backref detects at_end");
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---