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");