1 /*! @author Toru Nagashima <https://github.com/mysticatea> */
4 Object.defineProperty(exports, '__esModule', { value: true });
8 var ast = /*#__PURE__*/Object.freeze({
12 function isIdStart(cp) {
21 return isLargeIdStart(cp);
23 function isIdContinue(cp) {
38 return isLargeIdStart(cp) || isLargeIdContinue(cp);
40 function isLargeIdStart(cp) {
2688 function isLargeIdContinue(cp) {
4665 const PropertyData = {
4681 "Changes_When_Casefolded",
4683 "Changes_When_Casemapped",
4685 "Changes_When_Lowercased",
4687 "Changes_When_NFKC_Casefolded",
4689 "Changes_When_Titlecased",
4691 "Changes_When_Uppercased",
4694 "Default_Ignorable_Code_Point",
4703 "Emoji_Modifier_Base",
4704 "Emoji_Presentation",
4713 "IDS_Binary_Operator",
4715 "IDS_Trinary_Operator",
4725 "Logical_Order_Exception",
4730 "Noncharacter_Code_Point",
4734 "Pattern_White_Space",
4739 "Regional_Indicator",
4741 "Sentence_Terminal",
4745 "Terminal_Punctuation",
4747 "Unified_Ideograph",
4751 "Variation_Selector",
4760 General_Category: new Set([
4763 "Close_Punctuation",
4765 "Connector_Punctuation",
4779 "Final_Punctuation",
4783 "Initial_Punctuation",
4814 "Other_Punctuation",
4818 "Paragraph_Separator",
4846 "Anatolian_Hieroglyphs",
4876 "Canadian_Aboriginal",
4880 "Caucasian_Albanian",
4904 "Egyptian_Hieroglyphs",
4941 "Inscriptional_Pahlavi",
4943 "Inscriptional_Parthian",
4998 "Meroitic_Hieroglyphs",
5028 "Old_North_Arabian",
5034 "Old_South_Arabian",
5123 PropertyData.gc = PropertyData.General_Category;
5124 PropertyData.sc = PropertyData.Script_Extensions = PropertyData.scx =
5125 PropertyData.Script;
5127 const Backspace = 0x08;
5128 const CharacterTabulation = 0x09;
5129 const LineFeed = 0x0a;
5130 const LineTabulation = 0x0b;
5131 const FormFeed = 0x0c;
5132 const CarriageReturn = 0x0d;
5133 const ExclamationMark = 0x21;
5134 const DollarSign = 0x24;
5135 const LeftParenthesis = 0x28;
5136 const RightParenthesis = 0x29;
5137 const Asterisk = 0x2a;
5138 const PlusSign = 0x2b;
5140 const HyphenMinus = 0x2d;
5141 const FullStop = 0x2e;
5142 const Solidus = 0x2f;
5143 const DigitZero = 0x30;
5144 const DigitOne = 0x31;
5145 const DigitSeven = 0x37;
5146 const DigitNine = 0x39;
5148 const LessThanSign = 0x3c;
5149 const EqualsSign = 0x3d;
5150 const GreaterThanSign = 0x3e;
5151 const QuestionMark = 0x3f;
5152 const LatinCapitalLetterA = 0x41;
5153 const LatinCapitalLetterB = 0x42;
5154 const LatinCapitalLetterD = 0x44;
5155 const LatinCapitalLetterF = 0x46;
5156 const LatinCapitalLetterP = 0x50;
5157 const LatinCapitalLetterS = 0x53;
5158 const LatinCapitalLetterW = 0x57;
5159 const LatinCapitalLetterZ = 0x5a;
5160 const LowLine = 0x5f;
5161 const LatinSmallLetterA = 0x61;
5162 const LatinSmallLetterB = 0x62;
5163 const LatinSmallLetterC = 0x63;
5164 const LatinSmallLetterD = 0x64;
5165 const LatinSmallLetterF = 0x66;
5166 const LatinSmallLetterG = 0x67;
5167 const LatinSmallLetterI = 0x69;
5168 const LatinSmallLetterK = 0x6b;
5169 const LatinSmallLetterM = 0x6d;
5170 const LatinSmallLetterN = 0x6e;
5171 const LatinSmallLetterP = 0x70;
5172 const LatinSmallLetterR = 0x72;
5173 const LatinSmallLetterS = 0x73;
5174 const LatinSmallLetterT = 0x74;
5175 const LatinSmallLetterU = 0x75;
5176 const LatinSmallLetterV = 0x76;
5177 const LatinSmallLetterW = 0x77;
5178 const LatinSmallLetterX = 0x78;
5179 const LatinSmallLetterY = 0x79;
5180 const LatinSmallLetterZ = 0x7a;
5181 const LeftSquareBracket = 0x5b;
5182 const ReverseSolidus = 0x5c;
5183 const RightSquareBracket = 0x5d;
5184 const CircumflexAccent = 0x5e;
5185 const LeftCurlyBracket = 0x7b;
5186 const VerticalLine = 0x7c;
5187 const RightCurlyBracket = 0x7d;
5188 const ZeroWidthNonJoiner = 0x200c;
5189 const ZeroWidthJoiner = 0x200d;
5190 const LineSeparator = 0x2028;
5191 const ParagraphSeparator = 0x2029;
5192 const MinCodePoint = 0x00;
5193 const MaxCodePoint = 0x10ffff;
5194 function isLatinLetter(code) {
5195 return ((code >= LatinCapitalLetterA && code <= LatinCapitalLetterZ) ||
5196 (code >= LatinSmallLetterA && code <= LatinSmallLetterZ));
5198 function isDecimalDigit(code) {
5199 return code >= DigitZero && code <= DigitNine;
5201 function isOctalDigit(code) {
5202 return code >= DigitZero && code <= DigitSeven;
5204 function isHexDigit(code) {
5205 return ((code >= DigitZero && code <= DigitNine) ||
5206 (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) ||
5207 (code >= LatinSmallLetterA && code <= LatinSmallLetterF));
5209 function isLineTerminator(code) {
5210 return (code === LineFeed ||
5211 code === CarriageReturn ||
5212 code === LineSeparator ||
5213 code === ParagraphSeparator);
5215 function isValidUnicode(code) {
5216 return code >= MinCodePoint && code <= MaxCodePoint;
5218 function digitToInt(code) {
5219 if (code >= LatinSmallLetterA && code <= LatinSmallLetterF) {
5220 return code - LatinSmallLetterA + 10;
5222 if (code >= LatinCapitalLetterA && code <= LatinCapitalLetterF) {
5223 return code - LatinCapitalLetterA + 10;
5225 return code - DigitZero;
5228 const legacyImpl = {
5230 return i < end ? s.charCodeAt(i) : -1;
5236 const unicodeImpl = {
5238 return i < end ? s.codePointAt(i) : -1;
5241 return c > 0xffff ? 2 : 1;
5246 this._impl = legacyImpl;
5264 get currentCodePoint() {
5267 get nextCodePoint() {
5270 get nextCodePoint2() {
5273 get nextCodePoint3() {
5276 reset(source, start, end, uFlag) {
5277 this._impl = uFlag ? unicodeImpl : legacyImpl;
5283 const impl = this._impl;
5285 this._cp1 = impl.at(this._s, this._end, index);
5286 this._w1 = impl.width(this._cp1);
5287 this._cp2 = impl.at(this._s, this._end, index + this._w1);
5288 this._w2 = impl.width(this._cp2);
5289 this._cp3 = impl.at(this._s, this._end, index + this._w1 + this._w2);
5290 this._w3 = impl.width(this._cp3);
5291 this._cp4 = impl.at(this._s, this._end, index + this._w1 + this._w2 + this._w3);
5294 if (this._cp1 !== -1) {
5295 const impl = this._impl;
5296 this._i += this._w1;
5297 this._cp1 = this._cp2;
5298 this._w1 = this._w2;
5299 this._cp2 = this._cp3;
5300 this._w2 = impl.width(this._cp2);
5301 this._cp3 = this._cp4;
5302 this._w3 = impl.width(this._cp3);
5303 this._cp4 = impl.at(this._s, this._end, this._i + this._w1 + this._w2 + this._w3);
5307 if (this._cp1 === cp) {
5314 if (this._cp1 === cp1 && this._cp2 === cp2) {
5321 eat3(cp1, cp2, cp3) {
5322 if (this._cp1 === cp1 && this._cp2 === cp2 && this._cp3 === cp3) {
5332 class RegExpSyntaxError extends SyntaxError {
5333 constructor(source, uFlag, index, message) {
5335 if (source[0] !== "/") {
5336 source = `/${source}/${uFlag ? "u" : ""}`;
5338 source = `: ${source}`;
5340 super(`Invalid regular expression${source}: ${message}`);
5345 function isSyntaxCharacter(cp) {
5346 return (cp === CircumflexAccent ||
5347 cp === DollarSign ||
5348 cp === ReverseSolidus ||
5352 cp === QuestionMark ||
5353 cp === LeftParenthesis ||
5354 cp === RightParenthesis ||
5355 cp === LeftSquareBracket ||
5356 cp === RightSquareBracket ||
5357 cp === LeftCurlyBracket ||
5358 cp === RightCurlyBracket ||
5359 cp === VerticalLine);
5361 function isRegExpIdentifierStart(cp) {
5362 return isIdStart(cp) || cp === DollarSign || cp === LowLine;
5364 function isRegExpIdentifierPart(cp) {
5365 return (isIdContinue(cp) ||
5366 cp === DollarSign ||
5368 cp === ZeroWidthNonJoiner ||
5369 cp === ZeroWidthJoiner);
5371 function isUnicodePropertyNameCharacter(cp) {
5372 return isLatinLetter(cp) || cp === LowLine;
5374 function isUnicodePropertyValueCharacter(cp) {
5375 return isUnicodePropertyNameCharacter(cp) || isDecimalDigit(cp);
5377 function isValidUnicodeProperty(name, value) {
5378 return PropertyData.hasOwnProperty(name) && PropertyData[name].has(value);
5380 function isValidUnicodePropertyName(name) {
5381 return PropertyData.$LONE.has(name);
5383 class RegExpValidator {
5384 constructor(options) {
5385 this._reader = new Reader();
5386 this._uFlag = false;
5387 this._nFlag = false;
5388 this._lastIntValue = 0;
5389 this._lastMinValue = 0;
5390 this._lastMaxValue = 0;
5391 this._lastStrValue = "";
5392 this._lastKeyValue = "";
5393 this._lastValValue = "";
5394 this._lastAssertionIsQuantifiable = false;
5395 this._numCapturingParens = 0;
5396 this._groupNames = new Set();
5397 this._backreferenceNames = new Set();
5398 this._options = options || {};
5400 validateLiteral(source, start = 0, end = source.length) {
5401 this._uFlag = this._nFlag = false;
5402 this.reset(source, start, end);
5403 this.onLiteralEnter(start);
5404 if (this.eat(Solidus) && this.eatRegExpBody() && this.eat(Solidus)) {
5405 const flagStart = this.index;
5406 const uFlag = source.indexOf("u", flagStart) !== -1;
5407 this.validateFlags(source, flagStart, end);
5408 this.validatePattern(source, start + 1, flagStart - 1, uFlag);
5410 else if (start >= end) {
5411 this.raise("Empty");
5414 const c = String.fromCodePoint(this.currentCodePoint);
5415 this.raise(`Unexpected character '${c}'`);
5417 this.onLiteralLeave(start, end);
5419 validateFlags(source, start = 0, end = source.length) {
5420 const existingFlags = new Set();
5422 let ignoreCase = false;
5423 let multiline = false;
5425 let unicode = false;
5427 for (let i = start; i < end; ++i) {
5428 const flag = source.charCodeAt(i);
5429 if (existingFlags.has(flag)) {
5430 this.raise(`Duplicated flag '${source[i]}'`);
5432 existingFlags.add(flag);
5433 if (flag === LatinSmallLetterG) {
5436 else if (flag === LatinSmallLetterI) {
5439 else if (flag === LatinSmallLetterM) {
5442 else if (flag === LatinSmallLetterU && this.ecmaVersion >= 2015) {
5445 else if (flag === LatinSmallLetterY && this.ecmaVersion >= 2015) {
5448 else if (flag === LatinSmallLetterS && this.ecmaVersion >= 2018) {
5452 this.raise(`Invalid flag '${source[i]}'`);
5455 this.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll);
5457 validatePattern(source, start = 0, end = source.length, uFlag = false) {
5458 this._uFlag = uFlag && this.ecmaVersion >= 2015;
5459 this._nFlag = uFlag && this.ecmaVersion >= 2018;
5460 this.reset(source, start, end);
5463 this.ecmaVersion >= 2018 &&
5464 this._groupNames.size > 0) {
5471 return Boolean(this._options.strict || this._uFlag);
5474 return this._options.ecmaVersion || 2018;
5476 onLiteralEnter(start) {
5477 if (this._options.onLiteralEnter) {
5478 this._options.onLiteralEnter(start);
5481 onLiteralLeave(start, end) {
5482 if (this._options.onLiteralLeave) {
5483 this._options.onLiteralLeave(start, end);
5486 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll) {
5487 if (this._options.onFlags) {
5488 this._options.onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll);
5491 onPatternEnter(start) {
5492 if (this._options.onPatternEnter) {
5493 this._options.onPatternEnter(start);
5496 onPatternLeave(start, end) {
5497 if (this._options.onPatternLeave) {
5498 this._options.onPatternLeave(start, end);
5501 onDisjunctionEnter(start) {
5502 if (this._options.onDisjunctionEnter) {
5503 this._options.onDisjunctionEnter(start);
5506 onDisjunctionLeave(start, end) {
5507 if (this._options.onDisjunctionLeave) {
5508 this._options.onDisjunctionLeave(start, end);
5511 onAlternativeEnter(start, index) {
5512 if (this._options.onAlternativeEnter) {
5513 this._options.onAlternativeEnter(start, index);
5516 onAlternativeLeave(start, end, index) {
5517 if (this._options.onAlternativeLeave) {
5518 this._options.onAlternativeLeave(start, end, index);
5521 onGroupEnter(start) {
5522 if (this._options.onGroupEnter) {
5523 this._options.onGroupEnter(start);
5526 onGroupLeave(start, end) {
5527 if (this._options.onGroupLeave) {
5528 this._options.onGroupLeave(start, end);
5531 onCapturingGroupEnter(start, name) {
5532 if (this._options.onCapturingGroupEnter) {
5533 this._options.onCapturingGroupEnter(start, name);
5536 onCapturingGroupLeave(start, end, name) {
5537 if (this._options.onCapturingGroupLeave) {
5538 this._options.onCapturingGroupLeave(start, end, name);
5541 onQuantifier(start, end, min, max, greedy) {
5542 if (this._options.onQuantifier) {
5543 this._options.onQuantifier(start, end, min, max, greedy);
5546 onLookaroundAssertionEnter(start, kind, negate) {
5547 if (this._options.onLookaroundAssertionEnter) {
5548 this._options.onLookaroundAssertionEnter(start, kind, negate);
5551 onLookaroundAssertionLeave(start, end, kind, negate) {
5552 if (this._options.onLookaroundAssertionLeave) {
5553 this._options.onLookaroundAssertionLeave(start, end, kind, negate);
5556 onEdgeAssertion(start, end, kind) {
5557 if (this._options.onEdgeAssertion) {
5558 this._options.onEdgeAssertion(start, end, kind);
5561 onWordBoundaryAssertion(start, end, kind, negate) {
5562 if (this._options.onWordBoundaryAssertion) {
5563 this._options.onWordBoundaryAssertion(start, end, kind, negate);
5566 onAnyCharacterSet(start, end, kind) {
5567 if (this._options.onAnyCharacterSet) {
5568 this._options.onAnyCharacterSet(start, end, kind);
5571 onEscapeCharacterSet(start, end, kind, negate) {
5572 if (this._options.onEscapeCharacterSet) {
5573 this._options.onEscapeCharacterSet(start, end, kind, negate);
5576 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
5577 if (this._options.onUnicodePropertyCharacterSet) {
5578 this._options.onUnicodePropertyCharacterSet(start, end, kind, key, value, negate);
5581 onCharacter(start, end, value) {
5582 if (this._options.onCharacter) {
5583 this._options.onCharacter(start, end, value);
5586 onBackreference(start, end, ref) {
5587 if (this._options.onBackreference) {
5588 this._options.onBackreference(start, end, ref);
5591 onCharacterClassEnter(start, negate) {
5592 if (this._options.onCharacterClassEnter) {
5593 this._options.onCharacterClassEnter(start, negate);
5596 onCharacterClassLeave(start, end, negate) {
5597 if (this._options.onCharacterClassLeave) {
5598 this._options.onCharacterClassLeave(start, end, negate);
5601 onCharacterClassRange(start, end, min, max) {
5602 if (this._options.onCharacterClassRange) {
5603 this._options.onCharacterClassRange(start, end, min, max);
5607 return this._reader.source;
5610 return this._reader.index;
5612 get currentCodePoint() {
5613 return this._reader.currentCodePoint;
5615 get nextCodePoint() {
5616 return this._reader.nextCodePoint;
5618 get nextCodePoint2() {
5619 return this._reader.nextCodePoint2;
5621 get nextCodePoint3() {
5622 return this._reader.nextCodePoint3;
5624 reset(source, start, end) {
5625 this._reader.reset(source, start, end, this._uFlag);
5628 this._reader.rewind(index);
5631 this._reader.advance();
5634 return this._reader.eat(cp);
5637 return this._reader.eat2(cp1, cp2);
5639 eat3(cp1, cp2, cp3) {
5640 return this._reader.eat3(cp1, cp2, cp3);
5643 throw new RegExpSyntaxError(this.source, this._uFlag, this.index, message);
5646 const start = this.index;
5647 let inClass = false;
5648 let escaped = false;
5650 const cp = this.currentCodePoint;
5651 if (cp === -1 || isLineTerminator(cp)) {
5652 const kind = inClass ? "character class" : "regular expression";
5653 this.raise(`Unterminated ${kind}`);
5658 else if (cp === ReverseSolidus) {
5661 else if (cp === LeftSquareBracket) {
5664 else if (cp === RightSquareBracket) {
5667 else if ((cp === Solidus && !inClass) ||
5668 (cp === Asterisk && this.index === start)) {
5673 return this.index !== start;
5676 const start = this.index;
5677 this._numCapturingParens = this.countCapturingParens();
5678 this._groupNames.clear();
5679 this._backreferenceNames.clear();
5680 this.onPatternEnter(start);
5682 const cp = this.currentCodePoint;
5683 if (this.currentCodePoint !== -1) {
5684 if (cp === RightParenthesis) {
5685 this.raise("Unmatched ')'");
5687 if (cp === ReverseSolidus) {
5688 this.raise("\\ at end of pattern");
5690 if (cp === RightSquareBracket || cp === RightCurlyBracket) {
5691 this.raise("Lone quantifier brackets");
5693 const c = String.fromCodePoint(cp);
5694 this.raise(`Unexpected character '${c}'`);
5696 for (const name of this._backreferenceNames) {
5697 if (!this._groupNames.has(name)) {
5698 this.raise("Invalid named capture referenced");
5701 this.onPatternLeave(start, this.index);
5703 countCapturingParens() {
5704 const start = this.index;
5705 let inClass = false;
5706 let escaped = false;
5709 while ((cp = this.currentCodePoint) !== -1) {
5713 else if (cp === ReverseSolidus) {
5716 else if (cp === LeftSquareBracket) {
5719 else if (cp === RightSquareBracket) {
5722 else if (cp === LeftParenthesis &&
5724 (this.nextCodePoint !== QuestionMark ||
5725 (this.nextCodePoint2 === LessThanSign &&
5726 this.nextCodePoint3 !== EqualsSign &&
5727 this.nextCodePoint3 !== ExclamationMark))) {
5736 const start = this.index;
5738 this.onDisjunctionEnter(start);
5739 this.alternative(i++);
5740 while (this.eat(VerticalLine)) {
5741 this.alternative(i++);
5743 if (this.eatQuantifier(true)) {
5744 this.raise("Nothing to repeat");
5746 if (this.eat(LeftCurlyBracket)) {
5747 this.raise("Lone quantifier brackets");
5749 this.onDisjunctionLeave(start, this.index);
5752 const start = this.index;
5753 this.onAlternativeEnter(start, i);
5754 while (this.currentCodePoint !== -1 && this.eatTerm()) {
5756 this.onAlternativeLeave(start, this.index, i);
5759 if (this.eatAssertion()) {
5760 if (this._lastAssertionIsQuantifiable) {
5761 this.eatQuantifier();
5765 if (this.strict ? this.eatAtom() : this.eatExtendedAtom()) {
5766 this.eatQuantifier();
5772 const start = this.index;
5773 this._lastAssertionIsQuantifiable = false;
5774 if (this.eat(CircumflexAccent)) {
5775 this.onEdgeAssertion(start, this.index, "start");
5778 if (this.eat(DollarSign)) {
5779 this.onEdgeAssertion(start, this.index, "end");
5782 if (this.eat2(ReverseSolidus, LatinCapitalLetterB)) {
5783 this.onWordBoundaryAssertion(start, this.index, "word", true);
5786 if (this.eat2(ReverseSolidus, LatinSmallLetterB)) {
5787 this.onWordBoundaryAssertion(start, this.index, "word", false);
5790 if (this.eat2(LeftParenthesis, QuestionMark)) {
5791 const lookbehind = this.ecmaVersion >= 2018 && this.eat(LessThanSign);
5793 if (this.eat(EqualsSign) || (negate = this.eat(ExclamationMark))) {
5794 const kind = lookbehind ? "lookbehind" : "lookahead";
5795 this.onLookaroundAssertionEnter(start, kind, negate);
5797 if (!this.eat(RightParenthesis)) {
5798 this.raise("Unterminated group");
5800 this._lastAssertionIsQuantifiable = !lookbehind && !this.strict;
5801 this.onLookaroundAssertionLeave(start, this.index, kind, negate);
5808 eatQuantifier(noError = false) {
5809 const start = this.index;
5813 if (this.eat(Asterisk)) {
5815 max = Number.POSITIVE_INFINITY;
5817 else if (this.eat(PlusSign)) {
5819 max = Number.POSITIVE_INFINITY;
5821 else if (this.eat(QuestionMark)) {
5825 else if (this.eatBracedQuantifier(noError)) {
5826 min = this._lastMinValue;
5827 max = this._lastMaxValue;
5832 greedy = !this.eat(QuestionMark);
5834 this.onQuantifier(start, this.index, min, max, greedy);
5838 eatBracedQuantifier(noError) {
5839 const start = this.index;
5840 if (this.eat(LeftCurlyBracket)) {
5841 this._lastMinValue = 0;
5842 this._lastMaxValue = Number.POSITIVE_INFINITY;
5843 if (this.eatDecimalDigits()) {
5844 this._lastMinValue = this._lastMaxValue = this._lastIntValue;
5845 if (this.eat(Comma)) {
5846 this._lastMaxValue = this.eatDecimalDigits()
5847 ? this._lastIntValue
5848 : Number.POSITIVE_INFINITY;
5850 if (this.eat(RightCurlyBracket)) {
5851 if (!noError && this._lastMaxValue < this._lastMinValue) {
5852 this.raise("numbers out of order in {} quantifier");
5857 if (!noError && this.strict) {
5858 this.raise("Incomplete quantifier");
5865 return (this.eatPatternCharacter() ||
5867 this.eatReverseSolidusAtomEscape() ||
5868 this.eatCharacterClass() ||
5869 this.eatUncapturingGroup() ||
5870 this.eatCapturingGroup());
5873 if (this.eat(FullStop)) {
5874 this.onAnyCharacterSet(this.index - 1, this.index, "any");
5879 eatReverseSolidusAtomEscape() {
5880 const start = this.index;
5881 if (this.eat(ReverseSolidus)) {
5882 if (this.eatAtomEscape()) {
5889 eatUncapturingGroup() {
5890 const start = this.index;
5891 if (this.eat3(LeftParenthesis, QuestionMark, Colon)) {
5892 this.onGroupEnter(start);
5894 if (!this.eat(RightParenthesis)) {
5895 this.raise("Unterminated group");
5897 this.onGroupLeave(start, this.index);
5902 eatCapturingGroup() {
5903 const start = this.index;
5904 if (this.eat(LeftParenthesis)) {
5905 this._lastStrValue = "";
5906 if (this.ecmaVersion >= 2018) {
5907 this.groupSpecifier();
5909 else if (this.currentCodePoint === QuestionMark) {
5910 this.raise("Invalid group");
5912 const name = this._lastStrValue || null;
5913 this.onCapturingGroupEnter(start, name);
5915 if (!this.eat(RightParenthesis)) {
5916 this.raise("Unterminated group");
5918 this.onCapturingGroupLeave(start, this.index, name);
5924 return (this.eatDot() ||
5925 this.eatReverseSolidusAtomEscape() ||
5926 this.eatReverseSolidusFollowedByC() ||
5927 this.eatCharacterClass() ||
5928 this.eatUncapturingGroup() ||
5929 this.eatCapturingGroup() ||
5930 this.eatInvalidBracedQuantifier() ||
5931 this.eatExtendedPatternCharacter());
5933 eatReverseSolidusFollowedByC() {
5934 if (this.currentCodePoint === ReverseSolidus &&
5935 this.nextCodePoint === LatinSmallLetterC) {
5936 this._lastIntValue = this.currentCodePoint;
5938 this.onCharacter(this.index - 1, this.index, ReverseSolidus);
5943 eatInvalidBracedQuantifier() {
5944 if (this.eatBracedQuantifier(true)) {
5945 this.raise("Nothing to repeat");
5949 eatSyntaxCharacter() {
5950 if (isSyntaxCharacter(this.currentCodePoint)) {
5951 this._lastIntValue = this.currentCodePoint;
5957 eatPatternCharacter() {
5958 const start = this.index;
5959 const cp = this.currentCodePoint;
5960 if (cp !== -1 && !isSyntaxCharacter(cp)) {
5962 this.onCharacter(start, this.index, cp);
5967 eatExtendedPatternCharacter() {
5968 const start = this.index;
5969 const cp = this.currentCodePoint;
5971 cp !== CircumflexAccent &&
5972 cp !== DollarSign &&
5973 cp !== ReverseSolidus &&
5977 cp !== QuestionMark &&
5978 cp !== LeftParenthesis &&
5979 cp !== RightParenthesis &&
5980 cp !== LeftSquareBracket &&
5981 cp !== VerticalLine) {
5983 this.onCharacter(start, this.index, cp);
5989 this._lastStrValue = "";
5990 if (this.eat(QuestionMark)) {
5991 if (this.eatGroupName()) {
5992 if (!this._groupNames.has(this._lastStrValue)) {
5993 this._groupNames.add(this._lastStrValue);
5996 this.raise("Duplicate capture group name");
5998 this.raise("Invalid group");
6002 this._lastStrValue = "";
6003 if (this.eat(LessThanSign)) {
6004 if (this.eatRegExpIdentifierName() && this.eat(GreaterThanSign)) {
6007 this.raise("Invalid capture group name");
6011 eatRegExpIdentifierName() {
6012 this._lastStrValue = "";
6013 if (this.eatRegExpIdentifierStart()) {
6014 this._lastStrValue += String.fromCodePoint(this._lastIntValue);
6015 while (this.eatRegExpIdentifierPart()) {
6016 this._lastStrValue += String.fromCodePoint(this._lastIntValue);
6022 eatRegExpIdentifierStart() {
6023 const start = this.index;
6024 let cp = this.currentCodePoint;
6026 if (cp === ReverseSolidus && this.eatRegExpUnicodeEscapeSequence()) {
6027 cp = this._lastIntValue;
6029 if (isRegExpIdentifierStart(cp)) {
6030 this._lastIntValue = cp;
6033 if (this.index !== start) {
6038 eatRegExpIdentifierPart() {
6039 const start = this.index;
6040 let cp = this.currentCodePoint;
6042 if (cp === ReverseSolidus && this.eatRegExpUnicodeEscapeSequence()) {
6043 cp = this._lastIntValue;
6045 if (isRegExpIdentifierPart(cp)) {
6046 this._lastIntValue = cp;
6049 if (this.index !== start) {
6055 if (this.eatBackreference() ||
6056 this.eatCharacterClassEscape() ||
6057 this.eatCharacterEscape() ||
6058 (this._nFlag && this.eatKGroupName())) {
6061 if (this.strict || this._uFlag) {
6062 this.raise("Invalid escape");
6066 eatBackreference() {
6067 const start = this.index;
6068 if (this.eatDecimalEscape()) {
6069 const n = this._lastIntValue;
6070 if (n <= this._numCapturingParens) {
6071 this.onBackreference(start - 1, this.index, n);
6075 this.raise("Invalid escape");
6082 const start = this.index;
6083 if (this.eat(LatinSmallLetterK)) {
6084 if (this.eatGroupName()) {
6085 const groupName = this._lastStrValue;
6086 this._backreferenceNames.add(groupName);
6087 this.onBackreference(start - 1, this.index, groupName);
6090 this.raise("Invalid named reference");
6094 eatCharacterEscape() {
6095 const start = this.index;
6096 if (this.eatControlEscape() ||
6097 this.eatCControlLetter() ||
6099 this.eatHexEscapeSequence() ||
6100 this.eatRegExpUnicodeEscapeSequence() ||
6101 (!this.strict && this.eatLegacyOctalEscapeSequence()) ||
6102 this.eatIdentityEscape()) {
6103 this.onCharacter(start - 1, this.index, this._lastIntValue);
6108 eatCControlLetter() {
6109 const start = this.index;
6110 if (this.eat(LatinSmallLetterC)) {
6111 if (this.eatControlLetter()) {
6119 if (this.currentCodePoint === DigitZero &&
6120 !isDecimalDigit(this.nextCodePoint)) {
6121 this._lastIntValue = 0;
6127 eatControlEscape() {
6128 if (this.eat(LatinSmallLetterT)) {
6129 this._lastIntValue = CharacterTabulation;
6132 if (this.eat(LatinSmallLetterN)) {
6133 this._lastIntValue = LineFeed;
6136 if (this.eat(LatinSmallLetterV)) {
6137 this._lastIntValue = LineTabulation;
6140 if (this.eat(LatinSmallLetterF)) {
6141 this._lastIntValue = FormFeed;
6144 if (this.eat(LatinSmallLetterR)) {
6145 this._lastIntValue = CarriageReturn;
6150 eatControlLetter() {
6151 const cp = this.currentCodePoint;
6152 if (isLatinLetter(cp)) {
6154 this._lastIntValue = cp % 0x20;
6159 eatRegExpUnicodeEscapeSequence() {
6160 const start = this.index;
6161 if (this.eat(LatinSmallLetterU)) {
6162 if (this.eatFixedHexDigits(4)) {
6163 const lead = this._lastIntValue;
6164 if (this._uFlag && lead >= 0xd800 && lead <= 0xdbff) {
6165 const leadSurrogateEnd = this.index;
6166 if (this.eat(ReverseSolidus) &&
6167 this.eat(LatinSmallLetterU) &&
6168 this.eatFixedHexDigits(4)) {
6169 const trail = this._lastIntValue;
6170 if (trail >= 0xdc00 && trail <= 0xdfff) {
6171 this._lastIntValue =
6172 (lead - 0xd800) * 0x400 +
6178 this.rewind(leadSurrogateEnd);
6179 this._lastIntValue = lead;
6184 this.eat(LeftCurlyBracket) &&
6185 this.eatHexDigits() &&
6186 this.eat(RightCurlyBracket) &&
6187 isValidUnicode(this._lastIntValue)) {
6190 if (this.strict || this._uFlag) {
6191 this.raise("Invalid unicode escape");
6197 eatIdentityEscape() {
6199 if (this.eatSyntaxCharacter()) {
6202 if (this.eat(Solidus)) {
6203 this._lastIntValue = Solidus;
6208 if (this.isValidIdentityEscape(this.currentCodePoint)) {
6209 this._lastIntValue = this.currentCodePoint;
6215 isValidIdentityEscape(cp) {
6220 return !isIdContinue(cp);
6222 return (cp !== LatinSmallLetterC &&
6223 (!this._nFlag || cp !== LatinSmallLetterK));
6225 eatDecimalEscape() {
6226 this._lastIntValue = 0;
6227 let cp = this.currentCodePoint;
6228 if (cp >= DigitOne && cp <= DigitNine) {
6230 this._lastIntValue = 10 * this._lastIntValue + (cp - DigitZero);
6232 } while ((cp = this.currentCodePoint) >= DigitZero &&
6238 eatCharacterClassEscape() {
6239 const start = this.index;
6240 if (this.eat(LatinSmallLetterD)) {
6241 this._lastIntValue = -1;
6242 this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
6245 if (this.eat(LatinCapitalLetterD)) {
6246 this._lastIntValue = -1;
6247 this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
6250 if (this.eat(LatinSmallLetterS)) {
6251 this._lastIntValue = -1;
6252 this.onEscapeCharacterSet(start - 1, this.index, "space", false);
6255 if (this.eat(LatinCapitalLetterS)) {
6256 this._lastIntValue = -1;
6257 this.onEscapeCharacterSet(start - 1, this.index, "space", true);
6260 if (this.eat(LatinSmallLetterW)) {
6261 this._lastIntValue = -1;
6262 this.onEscapeCharacterSet(start - 1, this.index, "word", false);
6265 if (this.eat(LatinCapitalLetterW)) {
6266 this._lastIntValue = -1;
6267 this.onEscapeCharacterSet(start - 1, this.index, "word", true);
6272 this.ecmaVersion >= 2018 &&
6273 (this.eat(LatinSmallLetterP) ||
6274 (negate = this.eat(LatinCapitalLetterP)))) {
6275 this._lastIntValue = -1;
6276 if (this.eat(LeftCurlyBracket) &&
6277 this.eatUnicodePropertyValueExpression() &&
6278 this.eat(RightCurlyBracket)) {
6279 this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
6282 this.raise("Invalid property name");
6286 eatUnicodePropertyValueExpression() {
6287 const start = this.index;
6288 if (this.eatUnicodePropertyName() && this.eat(EqualsSign)) {
6289 this._lastKeyValue = this._lastStrValue;
6290 if (this.eatUnicodePropertyValue()) {
6291 this._lastValValue = this._lastStrValue;
6292 if (isValidUnicodeProperty(this._lastKeyValue, this._lastValValue)) {
6295 this.raise("Invalid property name");
6299 if (this.eatLoneUnicodePropertyNameOrValue()) {
6300 const nameOrValue = this._lastStrValue;
6301 if (isValidUnicodeProperty("General_Category", nameOrValue)) {
6302 this._lastKeyValue = "General_Category";
6303 this._lastValValue = nameOrValue;
6306 if (isValidUnicodePropertyName(nameOrValue)) {
6307 this._lastKeyValue = nameOrValue;
6308 this._lastValValue = "";
6311 this.raise("Invalid property name");
6315 eatUnicodePropertyName() {
6316 this._lastStrValue = "";
6317 while (isUnicodePropertyNameCharacter(this.currentCodePoint)) {
6318 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
6321 return this._lastStrValue !== "";
6323 eatUnicodePropertyValue() {
6324 this._lastStrValue = "";
6325 while (isUnicodePropertyValueCharacter(this.currentCodePoint)) {
6326 this._lastStrValue += String.fromCodePoint(this.currentCodePoint);
6329 return this._lastStrValue !== "";
6331 eatLoneUnicodePropertyNameOrValue() {
6332 return this.eatUnicodePropertyValue();
6334 eatCharacterClass() {
6335 const start = this.index;
6336 if (this.eat(LeftSquareBracket)) {
6337 const negate = this.eat(CircumflexAccent);
6338 this.onCharacterClassEnter(start, negate);
6340 if (!this.eat(RightSquareBracket)) {
6341 this.raise("Unterminated character class");
6343 this.onCharacterClassLeave(start, this.index, negate);
6349 let start = this.index;
6350 while (this.eatClassAtom()) {
6351 const left = this._lastIntValue;
6352 const hyphenStart = this.index;
6353 if (this.eat(HyphenMinus)) {
6354 this.onCharacter(hyphenStart, this.index, HyphenMinus);
6355 if (this.eatClassAtom()) {
6356 const right = this._lastIntValue;
6357 if (left === -1 || right === -1) {
6359 this.raise("Invalid character class");
6362 else if (left > right) {
6363 this.raise("Range out of order in character class");
6366 this.onCharacterClassRange(start, this.index, left, right);
6374 const start = this.index;
6375 if (this.eat(ReverseSolidus)) {
6376 if (this.eatClassEscape()) {
6380 this.raise("Invalid escape");
6384 const cp = this.currentCodePoint;
6385 if (cp !== -1 && cp !== RightSquareBracket) {
6387 this._lastIntValue = cp;
6388 this.onCharacter(start, this.index, cp);
6394 const start = this.index;
6395 if (this.eat(LatinSmallLetterB)) {
6396 this._lastIntValue = Backspace;
6397 this.onCharacter(start - 1, this.index, Backspace);
6400 if (this._uFlag && this.eat(HyphenMinus)) {
6401 this._lastIntValue = HyphenMinus;
6402 this.onCharacter(start - 1, this.index, HyphenMinus);
6405 if (!this._uFlag && this.eat(LatinSmallLetterC)) {
6406 if (this.eatClassControlLetter()) {
6407 this.onCharacter(start - 1, this.index, this._lastIntValue);
6412 return this.eatCharacterClassEscape() || this.eatCharacterEscape();
6414 eatClassControlLetter() {
6415 const cp = this.currentCodePoint;
6416 if (isDecimalDigit(cp) || cp === LowLine) {
6418 this._lastIntValue = cp % 0x20;
6423 eatHexEscapeSequence() {
6424 const start = this.index;
6425 if (this.eat(LatinSmallLetterX)) {
6426 if (this.eatFixedHexDigits(2)) {
6430 this.raise("Invalid escape");
6436 eatDecimalDigits() {
6437 const start = this.index;
6438 this._lastIntValue = 0;
6439 while (isDecimalDigit(this.currentCodePoint)) {
6440 this._lastIntValue =
6441 10 * this._lastIntValue + digitToInt(this.currentCodePoint);
6444 return this.index !== start;
6447 const start = this.index;
6448 this._lastIntValue = 0;
6449 while (isHexDigit(this.currentCodePoint)) {
6450 this._lastIntValue =
6451 16 * this._lastIntValue + digitToInt(this.currentCodePoint);
6454 return this.index !== start;
6456 eatLegacyOctalEscapeSequence() {
6457 if (this.eatOctalDigit()) {
6458 const n1 = this._lastIntValue;
6459 if (this.eatOctalDigit()) {
6460 const n2 = this._lastIntValue;
6461 if (n1 <= 3 && this.eatOctalDigit()) {
6462 this._lastIntValue = n1 * 64 + n2 * 8 + this._lastIntValue;
6465 this._lastIntValue = n1 * 8 + n2;
6469 this._lastIntValue = n1;
6476 const cp = this.currentCodePoint;
6477 if (isOctalDigit(cp)) {
6479 this._lastIntValue = cp - DigitZero;
6482 this._lastIntValue = 0;
6485 eatFixedHexDigits(length) {
6486 const start = this.index;
6487 this._lastIntValue = 0;
6488 for (let i = 0; i < length; ++i) {
6489 const cp = this.currentCodePoint;
6490 if (!isHexDigit(cp)) {
6494 this._lastIntValue = 16 * this._lastIntValue + digitToInt(cp);
6501 const DummyPattern = {};
6502 const DummyFlags = {};
6503 const DummyCapturingGroup = {};
6504 class RegExpParserState {
6505 constructor(options) {
6506 this._node = DummyPattern;
6507 this._flags = DummyFlags;
6508 this._backreferences = [];
6509 this._capturingGroups = [];
6511 this.strict = Boolean(options && options.strict);
6512 this.ecmaVersion = (options && options.ecmaVersion) || 2018;
6515 if (this._node.type !== "Pattern") {
6516 throw new Error("UnknownError");
6521 if (this._flags.type !== "Flags") {
6522 throw new Error("UnknownError");
6526 onFlags(start, end, global, ignoreCase, multiline, unicode, sticky, dotAll) {
6532 raw: this.source.slice(start, end),
6541 onPatternEnter(start) {
6550 this._backreferences.length = 0;
6551 this._capturingGroups.length = 0;
6553 onPatternLeave(start, end) {
6554 this._node.end = end;
6555 this._node.raw = this.source.slice(start, end);
6556 for (const reference of this._backreferences) {
6557 const ref = reference.ref;
6558 const group = typeof ref === "number"
6559 ? this._capturingGroups[ref - 1]
6560 : this._capturingGroups.find(g => g.name === ref);
6561 reference.resolved = group;
6562 group.references.push(reference);
6565 onAlternativeEnter(start) {
6566 const parent = this._node;
6567 if (parent.type !== "Assertion" &&
6568 parent.type !== "CapturingGroup" &&
6569 parent.type !== "Group" &&
6570 parent.type !== "Pattern") {
6571 throw new Error("UnknownError");
6574 type: "Alternative",
6581 parent.alternatives.push(this._node);
6583 onAlternativeLeave(start, end) {
6584 const node = this._node;
6585 if (node.type !== "Alternative") {
6586 throw new Error("UnknownError");
6589 node.raw = this.source.slice(start, end);
6590 this._node = node.parent;
6592 onGroupEnter(start) {
6593 const parent = this._node;
6594 if (parent.type !== "Alternative") {
6595 throw new Error("UnknownError");
6605 parent.elements.push(this._node);
6607 onGroupLeave(start, end) {
6608 const node = this._node;
6609 if (node.type !== "Group" || node.parent.type !== "Alternative") {
6610 throw new Error("UnknownError");
6613 node.raw = this.source.slice(start, end);
6614 this._node = node.parent;
6616 onCapturingGroupEnter(start, name) {
6617 const parent = this._node;
6618 if (parent.type !== "Alternative") {
6619 throw new Error("UnknownError");
6622 type: "CapturingGroup",
6631 parent.elements.push(this._node);
6632 this._capturingGroups.push(this._node);
6634 onCapturingGroupLeave(start, end) {
6635 const node = this._node;
6636 if (node.type !== "CapturingGroup" ||
6637 node.parent.type !== "Alternative") {
6638 throw new Error("UnknownError");
6641 node.raw = this.source.slice(start, end);
6642 this._node = node.parent;
6644 onQuantifier(start, end, min, max, greedy) {
6645 const parent = this._node;
6646 if (parent.type !== "Alternative") {
6647 throw new Error("UnknownError");
6649 const element = parent.elements.pop();
6650 if (element == null ||
6651 element.type === "Quantifier" ||
6652 (element.type === "Assertion" && element.kind !== "lookahead")) {
6653 throw new Error("UnknownError");
6658 start: element.start,
6660 raw: this.source.slice(element.start, end),
6666 parent.elements.push(node);
6667 element.parent = node;
6669 onLookaroundAssertionEnter(start, kind, negate) {
6670 const parent = this._node;
6671 if (parent.type !== "Alternative") {
6672 throw new Error("UnknownError");
6684 parent.elements.push(this._node);
6686 onLookaroundAssertionLeave(start, end) {
6687 const node = this._node;
6688 if (node.type !== "Assertion" || node.parent.type !== "Alternative") {
6689 throw new Error("UnknownError");
6692 node.raw = this.source.slice(start, end);
6693 this._node = node.parent;
6695 onEdgeAssertion(start, end, kind) {
6696 const parent = this._node;
6697 if (parent.type !== "Alternative") {
6698 throw new Error("UnknownError");
6700 parent.elements.push({
6705 raw: this.source.slice(start, end),
6709 onWordBoundaryAssertion(start, end, kind, negate) {
6710 const parent = this._node;
6711 if (parent.type !== "Alternative") {
6712 throw new Error("UnknownError");
6714 parent.elements.push({
6719 raw: this.source.slice(start, end),
6724 onAnyCharacterSet(start, end, kind) {
6725 const parent = this._node;
6726 if (parent.type !== "Alternative") {
6727 throw new Error("UnknownError");
6729 parent.elements.push({
6730 type: "CharacterSet",
6734 raw: this.source.slice(start, end),
6738 onEscapeCharacterSet(start, end, kind, negate) {
6739 const parent = this._node;
6740 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
6741 throw new Error("UnknownError");
6743 parent.elements.push({
6744 type: "CharacterSet",
6748 raw: this.source.slice(start, end),
6753 onUnicodePropertyCharacterSet(start, end, kind, key, value, negate) {
6754 const parent = this._node;
6755 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
6756 throw new Error("UnknownError");
6758 parent.elements.push({
6759 type: "CharacterSet",
6763 raw: this.source.slice(start, end),
6770 onCharacter(start, end, value) {
6771 const parent = this._node;
6772 if (parent.type !== "Alternative" && parent.type !== "CharacterClass") {
6773 throw new Error("UnknownError");
6775 parent.elements.push({
6780 raw: this.source.slice(start, end),
6784 onBackreference(start, end, ref) {
6785 const parent = this._node;
6786 if (parent.type !== "Alternative") {
6787 throw new Error("UnknownError");
6790 type: "Backreference",
6794 raw: this.source.slice(start, end),
6796 resolved: DummyCapturingGroup,
6798 parent.elements.push(node);
6799 this._backreferences.push(node);
6801 onCharacterClassEnter(start, negate) {
6802 const parent = this._node;
6803 if (parent.type !== "Alternative") {
6804 throw new Error("UnknownError");
6807 type: "CharacterClass",
6815 parent.elements.push(this._node);
6817 onCharacterClassLeave(start, end) {
6818 const node = this._node;
6819 if (node.type !== "CharacterClass" ||
6820 node.parent.type !== "Alternative") {
6821 throw new Error("UnknownError");
6824 node.raw = this.source.slice(start, end);
6825 this._node = node.parent;
6827 onCharacterClassRange(start, end) {
6828 const parent = this._node;
6829 if (parent.type !== "CharacterClass") {
6830 throw new Error("UnknownError");
6832 const elements = parent.elements;
6833 const max = elements.pop();
6834 const hyphen = elements.pop();
6835 const min = elements.pop();
6839 min.type !== "Character" ||
6840 max.type !== "Character" ||
6841 hyphen.type !== "Character" ||
6842 hyphen.value !== HyphenMinus) {
6843 throw new Error("UnknownError");
6846 type: "CharacterClassRange",
6850 raw: this.source.slice(start, end),
6856 elements.push(node);
6859 class RegExpParser {
6860 constructor(options) {
6861 this._state = new RegExpParserState(options);
6862 this._validator = new RegExpValidator(this._state);
6864 parseLiteral(source, start = 0, end = source.length) {
6865 this._state.source = source;
6866 this._validator.validateLiteral(source, start, end);
6867 const pattern = this._state.pattern;
6868 const flags = this._state.flags;
6870 type: "RegExpLiteral",
6878 pattern.parent = literal;
6879 flags.parent = literal;
6882 parseFlags(source, start = 0, end = source.length) {
6883 this._state.source = source;
6884 this._validator.validateFlags(source, start, end);
6885 return this._state.flags;
6887 parsePattern(source, start = 0, end = source.length, uFlag = false) {
6888 this._state.source = source;
6889 this._validator.validatePattern(source, start, end, uFlag);
6890 return this._state.pattern;
6894 class RegExpVisitor {
6895 constructor(handlers) {
6896 this._handlers = handlers;
6899 switch (node.type) {
6901 this.visitAlternative(node);
6904 this.visitAssertion(node);
6906 case "Backreference":
6907 this.visitBackreference(node);
6909 case "CapturingGroup":
6910 this.visitCapturingGroup(node);
6913 this.visitCharacter(node);
6915 case "CharacterClass":
6916 this.visitCharacterClass(node);
6918 case "CharacterClassRange":
6919 this.visitCharacterClassRange(node);
6921 case "CharacterSet":
6922 this.visitCharacterSet(node);
6925 this.visitFlags(node);
6928 this.visitGroup(node);
6931 this.visitPattern(node);
6934 this.visitQuantifier(node);
6936 case "RegExpLiteral":
6937 this.visitRegExpLiteral(node);
6940 throw new Error(`Unknown type: ${node.type}`);
6943 visitAlternative(node) {
6944 if (this._handlers.onAlternativeEnter) {
6945 this._handlers.onAlternativeEnter(node);
6947 node.elements.forEach(this.visit, this);
6948 if (this._handlers.onAlternativeLeave) {
6949 this._handlers.onAlternativeLeave(node);
6952 visitAssertion(node) {
6953 if (this._handlers.onAssertionEnter) {
6954 this._handlers.onAssertionEnter(node);
6956 if (node.kind === "lookahead" || node.kind === "lookbehind") {
6957 node.alternatives.forEach(this.visit, this);
6959 if (this._handlers.onAssertionLeave) {
6960 this._handlers.onAssertionLeave(node);
6963 visitBackreference(node) {
6964 if (this._handlers.onBackreferenceEnter) {
6965 this._handlers.onBackreferenceEnter(node);
6967 if (this._handlers.onBackreferenceLeave) {
6968 this._handlers.onBackreferenceLeave(node);
6971 visitCapturingGroup(node) {
6972 if (this._handlers.onCapturingGroupEnter) {
6973 this._handlers.onCapturingGroupEnter(node);
6975 node.alternatives.forEach(this.visit, this);
6976 if (this._handlers.onCapturingGroupLeave) {
6977 this._handlers.onCapturingGroupLeave(node);
6980 visitCharacter(node) {
6981 if (this._handlers.onCharacterEnter) {
6982 this._handlers.onCharacterEnter(node);
6984 if (this._handlers.onCharacterLeave) {
6985 this._handlers.onCharacterLeave(node);
6988 visitCharacterClass(node) {
6989 if (this._handlers.onCharacterClassEnter) {
6990 this._handlers.onCharacterClassEnter(node);
6992 node.elements.forEach(this.visit, this);
6993 if (this._handlers.onCharacterClassLeave) {
6994 this._handlers.onCharacterClassLeave(node);
6997 visitCharacterClassRange(node) {
6998 if (this._handlers.onCharacterClassRangeEnter) {
6999 this._handlers.onCharacterClassRangeEnter(node);
7001 this.visitCharacter(node.min);
7002 this.visitCharacter(node.max);
7003 if (this._handlers.onCharacterClassRangeLeave) {
7004 this._handlers.onCharacterClassRangeLeave(node);
7007 visitCharacterSet(node) {
7008 if (this._handlers.onCharacterSetEnter) {
7009 this._handlers.onCharacterSetEnter(node);
7011 if (this._handlers.onCharacterSetLeave) {
7012 this._handlers.onCharacterSetLeave(node);
7016 if (this._handlers.onFlagsEnter) {
7017 this._handlers.onFlagsEnter(node);
7019 if (this._handlers.onFlagsLeave) {
7020 this._handlers.onFlagsLeave(node);
7024 if (this._handlers.onGroupEnter) {
7025 this._handlers.onGroupEnter(node);
7027 node.alternatives.forEach(this.visit, this);
7028 if (this._handlers.onGroupLeave) {
7029 this._handlers.onGroupLeave(node);
7032 visitPattern(node) {
7033 if (this._handlers.onPatternEnter) {
7034 this._handlers.onPatternEnter(node);
7036 node.alternatives.forEach(this.visit, this);
7037 if (this._handlers.onPatternLeave) {
7038 this._handlers.onPatternLeave(node);
7041 visitQuantifier(node) {
7042 if (this._handlers.onQuantifierEnter) {
7043 this._handlers.onQuantifierEnter(node);
7045 this.visit(node.element);
7046 if (this._handlers.onQuantifierLeave) {
7047 this._handlers.onQuantifierLeave(node);
7050 visitRegExpLiteral(node) {
7051 if (this._handlers.onRegExpLiteralEnter) {
7052 this._handlers.onRegExpLiteralEnter(node);
7054 this.visitPattern(node.pattern);
7055 this.visitFlags(node.flags);
7056 if (this._handlers.onRegExpLiteralLeave) {
7057 this._handlers.onRegExpLiteralLeave(node);
7062 function parseRegExpLiteral(source, options) {
7063 return new RegExpParser(options).parseLiteral(String(source));
7065 function validateRegExpLiteral(source, options) {
7066 return new RegExpValidator(options).validateLiteral(source);
7068 function visitRegExpAST(node, handlers) {
7069 new RegExpVisitor(handlers).visit(node);
7073 exports.RegExpParser = RegExpParser;
7074 exports.RegExpValidator = RegExpValidator;
7075 exports.parseRegExpLiteral = parseRegExpLiteral;
7076 exports.validateRegExpLiteral = validateRegExpLiteral;
7077 exports.visitRegExpAST = visitRegExpAST;
7078 //# sourceMappingURL=index.js.map