blob: 32b043d6e0e9034104c7891f5d8e6ec9583713eb [file] [log] [blame]
description(
"This page tests handling of characters which, according to ECMA 262, are not regular expression PatternCharacters. Those characters are: ^ $ \\ . * + ? ( ) [ ] { } |"
);
// We test two cases, to match the two cases in the WREC parser.
// Test 1: the character stand-alone.
// Test 2: the character following a PatternCharacter.
var regexp;
// ^: Always allowed, always an assertion.
regexp = /^/g;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('')");
shouldBe("regexp.lastIndex", "0");
regexp = /\n^/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('\\n\\n')");
shouldBe("regexp.lastIndex", "1");
// $: Always allowed, always an assertion.
regexp = /$/g;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('')");
shouldBe("regexp.lastIndex", "0");
regexp = /\n$/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('\\n\\n')");
shouldBe("regexp.lastIndex", "1");
// \: Only allowed as a prefix. Contrary to spec, always treated as an
// IdentityEscape when followed by an invalid escape postfix.
regexp = /\z/;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('z')"); // invalid postfix => IdentityEscape
regexp = /a\z/;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('az')"); // invalid postfix => IdentityEscape
regexp = /\_/;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('_')"); // invalid postfix => IdentityEscape
regexp = /a\_/;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a_')"); // invalid postfix => IdentityEscape
debug("\nTesting regexp: " + "[invalid \\ variations]");
shouldThrow("/\\/"); // no postfix => not allowed
shouldThrow("/a\\/"); // no postfix => not allowed
// .: Always allowed, always a non-newline wildcard.
regexp = /./;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a')");
shouldBeFalse("regexp.test('\\n')");
regexp = /a./;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('aa')");
shouldBeFalse("regexp.test('a\\n')");
// *: Only allowed as a postfix to a PatternCharacter. Behaves as a {0,Infinity} quantifier.
regexp = /a*/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('b')");
shouldBe("regexp.lastIndex", "0");
shouldBeTrue("regexp.test('aaba')");
shouldBe("regexp.lastIndex", "2");
debug("\nTesting regexp: " + "[invalid * variations]");
shouldThrow("/*/"); // Unterminated comment.
shouldThrow("/^*/"); // Prefixed by ^ to avoid confusion with comment syntax.
// +: Only allowed as a postfix to a PatternCharacter. Behaves as a {1,Infinity} quantifier.
regexp = /a+/gm;
debug("\nTesting regexp: " + regexp);
shouldBeFalse("regexp.test('b')");
shouldBeTrue("regexp.test('aaba')");
shouldBe("regexp.lastIndex", "2");
debug("\nTesting regexp: " + "[invalid + variations]");
shouldThrow("/+/");
// ?: Only allowed as a postfix to a PatternCharacter. Behaves as a {0,1} quantifier.
regexp = /a?/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('b')");
shouldBe("regexp.lastIndex", "0");
shouldBeTrue("regexp.test('aaba')");
shouldBe("regexp.lastIndex", "1");
debug("\nTesting regexp: " + "[invalid ? variations]");
shouldThrow("/?/");
// (: Only allowed if it matches a ).
debug("\nTesting regexp: " + "[invalid ( variations]");
shouldThrow("/(/");
shouldThrow("/a(/");
// ): Only allowed if it matches a (.
debug("\nTesting regexp: " + "[invalid ) variations]");
shouldThrow("/)/");
shouldThrow("/a)/");
// [: Only allowed if it matches a ] and the stuff in between is a valid character class.
debug("\nTesting regexp: " + "[invalid [ variations]");
shouldThrow("/[/");
shouldThrow("/a[/");
shouldThrow("/[b-a]/");
shouldThrow("/a[b-a]/");
// ]: Closes a ]. Contrary to spec, if no [ was seen, acts as a regular PatternCharacter.
regexp = /]/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test(']')");
shouldBe("regexp.lastIndex", "1");
regexp = /a]/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a]')");
shouldBe("regexp.lastIndex", "2");
// {: Begins a quantifier. Contrary to spec, if no } is seen, or if the stuff in
// between does not lex as a quantifier, acts as a regular PatternCharacter. If
// the stuff in between does lex as a quantifier, but the quantifier is invalid,
// acts as a syntax error.
regexp = /{/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('{')");
shouldBe("regexp.lastIndex", "1");
regexp = /a{/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a{')");
shouldBe("regexp.lastIndex", "2");
regexp = /{a/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('{a')");
shouldBe("regexp.lastIndex", "2");
regexp = /a{a/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a{a')");
shouldBe("regexp.lastIndex", "3");
regexp = /{1,/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('{1,')");
shouldBe("regexp.lastIndex", "3");
regexp = /a{1,/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a{1,')");
shouldBe("regexp.lastIndex", "4");
regexp = /{1,a/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('{1,a')");
shouldBe("regexp.lastIndex", "4");
regexp = /{1,0/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('{1,0')");
shouldBe("regexp.lastIndex", "4");
regexp = /{1, 0}/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('{1, 0}')");
shouldBe("regexp.lastIndex", "6");
regexp = /a{1, 0}/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a{1, 0}')");
shouldBe("regexp.lastIndex", "7");
try { regexp = new RegExp("a{1,0", "gm"); } catch(e) { regexp = e; }; // Work around exception thrown in Firefox -- probably too weird to be worth matching.
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a{1,0')");
shouldBe("regexp.lastIndex", "5");
regexp = /a{0}/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a')");
shouldBe("regexp.lastIndex", "0");
shouldBeTrue("regexp.test('b')");
shouldBe("regexp.lastIndex", "0");
debug("\nTesting regexp: " + "[invalid {} variations]");
shouldThrow("/{0}/");
shouldThrow("/{1,0}/");
shouldThrow("/a{1,0}/");
// }: Ends a quantifier. Same rules as for {.
regexp = /}/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('}')");
shouldBe("regexp.lastIndex", "1");
regexp = /a}/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('a}')");
shouldBe("regexp.lastIndex", "2");
// |: Always allowed, always separates two alternatives.
regexp = new RegExp("", "gm");
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('')");
shouldBe("regexp.lastIndex", "0");
regexp = /|/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('|')");
shouldBe("regexp.lastIndex", "0");
regexp = /a|/gm;
debug("\nTesting regexp: " + regexp);
shouldBeTrue("regexp.test('|')");
shouldBe("regexp.lastIndex", "0");