this.visitAlternative(node, parents); break; case "Assertion": this.visitAssertion(node, parents); break; case "Backreference": this.visitBackreference(node, parents); break; case "CapturingGroup": this.visitCapturingGroup(node, parents); break; case "Character": this.visitCharacter(node, parents); break; case "CharacterClass": this.visitCharacterClass(node, parents); break; case "CharacterClassRange": this.visitCharacterClassRange(node, parents); break; case "CharacterSet": this.visitCharacterSet(node, parents); break; case "Flags": this.visitFlags(node, parents); break; case "Group": this.visitGroup(node, parents); break; case "Pattern": this.visitPattern(node, parents); break; case "Quantifier": this.visitQuantifier(node, parents); break; case "RegExpLiteral": this.visitRegExpLiteral(node, parents); break; default: throw new Error(`Unknown type: ${node.type}`); } } visitAlternative(node, parents) { if (this._handlers.onAlternativeEnter) { this._handlers.onAlternativeEnter(node, parents); } parents.push(node); for (const child of node.elements) { this.visitWithParents(child, parents); } parents.pop(); if (this._handlers.onAlternativeLeave) { this._handlers.onAlternativeLeave(node, parents); } } visitAssertion(node, parents) { if (this._handlers.onAssertionEnter) { this._handlers.onAssertionEnter(node, parents); } if (node.kind === "lookahead" || node.kind === "lookbehind") { parents.push(node); for (const child of node.alternatives) { this.visitWithParents(child, parents); } parents.pop(); } if (this._handlers.onAssertionLeave) { this._handlers.onAssertionLeave(node, parents); } } visitBackreference(node, parents) { if (this._handlers.onBackreferenceEnter) { this._handlers.onBackreferenceEnter(node, parents); } if (this._handlers.onBackreferenceLeave) { this._handlers.onBackreferenceLeave(node, parents); } } visitCapturingGroup(node, parents) { if (this._handlers.onCapturingGroupEnter) { this._handlers.onCapturingGroupEnter(node, parents); } parents.push(node); for (const child of node.alternatives) { this.visitWithParents(child, parents); } parents.pop(); if (this._handlers.onCapturingGroupLeave) { this._handlers.onCapturingGroupLeave(node, parents); } } visitCharacter(node, parents) { if (this._handlers.onCharacterEnter) { this._handlers.onCharacterEnter(node, parents); } if (this._handlers.onCharacterLeave) { this._handlers.onCharacterLeave(node, parents); } } visitCharacterClass(node, parents) { if (this._handlers.onCharacterClassEnter) { this._handlers.onCharacterClassEnter(node, parents); } parents.push(node); for (const child of node.elements) { this.visitWithParents(child, parents); } parents.pop(); if (this._handlers.onCharacterClassLeave) { this._handlers.onCharacterClassLeave(node, parents); } } visitCharacterClassRange(node, parents) { if (this._handlers.onCharacterClassRangeEnter) { this._handlers.onCharacterClassRangeEnter(node, parents); } parents.push(node); this.visitCharacter(node.min, parents); this.visitCharacter(node.max, parents); parents.pop(); if (this._handlers.onCharacterClassRangeLeave) { this._handlers.onCharacterClassRangeLeave(node, parents); } } visitCharacterSet(node, parents) { if (this._handlers.onCharacterSetEnter) { this._handlers.onCharacterSetEnter(node, parents); } if (this._handlers.onCharacterSetLeave) { this._handlers.onCharacterSetLeave(node, parents); } } visitFlags(node, parents) { if (this._handlers.onFlagsEnter) { this._handlers.onFlagsEnter(node, parents); } if (this._handlers.onFlagsLeave) { this._handlers.onFlagsLeave(node, parents); } } visitGroup(node, parents) { if (this._handlers.onGroupEnter) { this._handlers.onGroupEnter(node, parents); } parents.push(node); for (const child of node.alternatives) { this.visitWithParents(child, parents); } parents.pop(); if (this._handlers.onGroupLeave) { this._handlers.onGroupLeave(node, parents); } } visitPattern(node, parents) { if (this._handlers.onPatternEnter) { this._handlers.onPatternEnter(node, parents); } parents.push(node); for (const child of node.alternatives) { this.visitWithParents(child, parents); } parents.pop(); if (this._handlers.onPatternLeave) { this._handlers.onPatternLeave(node, parents); } } visitQuantifier(node, parents) { if (this._handlers.onQuantifierEnter) { this._handlers.onQuantifierEnter(node, parents); } parents.push(node); this.visitWithParents(node.element, parents); parents.pop(); if (this._handlers.onQuantifierLeave) { this._handlers.onQuantifierLeave(node, parents); } } visitRegExpLiteral(node, parents) { if (this._handlers.onRegExpLiteralEnter) { this._handlers.onRegExpLiteralEnter(node, parents); } parents.push(node); this.visitWithParents(node.pattern, parents); this.visitWithParents(node.flags, parents); parents.pop(); if (this._handlers.onRegExpLiteralLeave) { this._handlers.onRegExpLiteralLeave(node, parents); } } } function parseRegExpLiteral(source, options) { return new RegExpParser(options).parseLiteral(String(source)); } function validateRegExpLiteral(source, options) { return new RegExpValidator(options).validateLiteral(source); } function visitRegExpAST(node, handlers) { new RegExpVisitor(handlers).visit(node); } exports.AST = ast; exports.RegExpParser = RegExpParser; exports.RegExpValidator = RegExpValidator; exports.RegExpVisitor = RegExpVisitor; exports.parseRegExpLiteral = parseRegExpLiteral; exports.validateRegExpLiteral = validateRegExpLiteral; exports.visitRegExpAST = visitRegExpAST;