load(libdir + "asserts.js"); // helper functions function Disjunction(alternatives) { return{ type: "Disjunction", alternatives: alternatives }; } function Alternative(nodes) { return { type: "Alternative", nodes: nodes }; } function Empty() { return { type: "Empty" }; } function Text(elements) { return { type: "Text", elements: elements }; } function Assertion(type) { return { type: "Assertion", assertion_type: type }; } function Atom(data) { return { type: "Atom", data: data }; } const kInfinity = 0x7FFFFFFF; function Quantifier(min, max, type, body) { return { type: "Quantifier", min: min, max: max, quantifier_type: type, body: body }; } function Lookahead(body) { return { type: "Lookahead", is_positive: true, body: body }; } function NegativeLookahead(body) { return { type: "Lookahead", is_positive: false, body: body }; } function BackReference(index) { return { type: "BackReference", index: index }; } function CharacterClass(ranges) { return { type: "CharacterClass", is_negated: false, ranges: ranges.map(([from, to]) => ({ from ,to })) }; } function NegativeCharacterClass(ranges) { return { type: "CharacterClass", is_negated: true, ranges: ranges.map(([from, to]) => ({ from ,to })) }; } function Capture(index, body) { return { type: "Capture", index: index, body: body }; } function AllSurrogateAndCharacterClass(ranges) { return Disjunction([ CharacterClass(ranges), Alternative([ CharacterClass([["\uD800", "\uDBFF"]]), NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]])) ]), Alternative([ Assertion("NOT_AFTER_LEAD_SURROGATE"), CharacterClass([["\uDC00", "\uDFFF"]]) ]), Text([ CharacterClass([["\uD800", "\uDBFF"]]), CharacterClass([["\uDC00", "\uDFFF"]]) ]) ]); } // testing functions var all_flags = [ "", "i", "m", "u", "im", "iu", "mu", "imu", ]; var no_unicode_flags = [ "", "i", "m", "im", ]; var unicode_flags = [ "u", "iu", "mu", "imu", ]; var no_multiline_flags = [ "", "i", "u", "iu", ]; var multiline_flags = [ "m", "im", "mu", "imu", ]; function test_flags(pattern, flags, match_only, expected) { for (var flag of flags) { assertDeepEq(parseRegExp(pattern, flag, match_only), expected); } } function make_mix(tree) { if (tree.type == "Atom") { return Atom("X" + tree.data + "Y"); } if (tree.type == "CharacterClass") { return Text([ Atom("X"), tree, Atom("Y") ]); } if (tree.type == "Alternative") { return Alternative([ Atom("X"), ...tree.nodes, Atom("Y") ]); } return Alternative([ Atom("X"), tree, Atom("Y") ]); } function test_mix(pattern, flags, expected) { test_flags(pattern, flags, false, expected); test_flags("X" + pattern + "Y", flags, false, make_mix(expected)); } function test(pattern, flags, expected) { test_flags(pattern, flags, false, expected); } function test_match_only(pattern, flags, expected) { test_flags(pattern, flags, true, expected); }