From fb4b0185a6eb6a3ce1b3ca7aa3eedd70ee78821f Mon Sep 17 00:00:00 2001 From: Steven Levithan Date: Mon, 18 Nov 2024 20:46:11 +0100 Subject: [PATCH] Util organization --- src/generate.js | 3 ++- src/parse.js | 25 ++----------------------- src/subclass.js | 13 ++----------- src/transform.js | 9 +++++---- src/traverse.js | 18 +++++++++++++++++- src/utils-node.js | 30 ++++++++++++++++++++++++++++++ src/utils.js | 7 ------- 7 files changed, 58 insertions(+), 47 deletions(-) create mode 100644 src/utils-node.js diff --git a/src/generate.js b/src/generate.js index 0640123..26535fc 100644 --- a/src/generate.js +++ b/src/generate.js @@ -1,8 +1,9 @@ import {getOptions} from './options.js'; -import {AstAssertionKinds, AstCharacterSetKinds, AstTypes, isLookaround} from './parse.js'; +import {AstAssertionKinds, AstCharacterSetKinds, AstTypes} from './parse.js'; import {traverse} from './traverse.js'; import {getIgnoreCaseMatchChars, JsUnicodePropertiesPostEs2018, UnicodePropertiesWithSpecificCase} from './unicode.js'; import {cp, getNewCurrentFlags, isMinTarget, r} from './utils.js'; +import {isLookaround} from './utils-node.js'; /** Generates a Regex+ compatible `pattern`, `flags`, and `options` from a Regex+ AST. diff --git a/src/parse.js b/src/parse.js index 001bb25..6d8fa94 100644 --- a/src/parse.js +++ b/src/parse.js @@ -1,7 +1,8 @@ import {TokenCharacterSetKinds, TokenDirectiveKinds, TokenGroupKinds, TokenTypes} from './tokenize.js'; import {traverse} from './traverse.js'; import {JsUnicodePropertiesMap, JsUnicodePropertiesOfStringsMap, PosixProperties, slug} from './unicode.js'; -import {getOrCreate, hasOnlyChild, r, throwIfNot} from './utils.js'; +import {getOrCreate, r, throwIfNot} from './utils.js'; +import {hasOnlyChild} from './utils-node.js'; const AstTypes = { Alternative: 'Alternative', @@ -25,21 +26,6 @@ const AstTypes = { Recursion: 'Recursion', }; -const AstTypeAliases = { - AnyGroup: 'AnyGroup', - AnyNode: 'AnyNode', -}; - -function getAstTypeAliases(node) { - const {type} = node; - const types = [AstTypeAliases.AnyNode]; - if (isLookaround(node) || type === AstTypes.CapturingGroup || type === AstTypes.Group) { - types.push(AstTypeAliases.AnyGroup); - } - types.push(type); - return types; -} - const AstAssertionKinds = { line_end: 'line_end', line_start: 'line_start', @@ -686,11 +672,6 @@ function getOptimizedGroup(node) { return node; } -function isLookaround({type, kind}) { - return type === AstTypes.Assertion && - (kind === AstAssertionKinds.lookahead || kind === AstAssertionKinds.lookbehind); -} - function isValidGroupNameOniguruma(name) { return !/^(?:[-\d]|$)/.test(name); } @@ -737,7 +718,5 @@ export { createSubroutine, createUnicodeProperty, createVariableLengthCharacterSet, - getAstTypeAliases, - isLookaround, parse, }; diff --git a/src/subclass.js b/src/subclass.js index 95e30b3..264a2d8 100644 --- a/src/subclass.js +++ b/src/subclass.js @@ -1,5 +1,5 @@ -import {AstAssertionKinds, AstTypes, isLookaround} from './parse.js'; -import {hasOnlyChild} from './utils.js'; +import {AstAssertionKinds, AstTypes} from './parse.js'; +import {hasOnlyChild, isLookaround, isZeroLengthNode} from './utils-node.js'; import {RegExpSubclass} from 'regex/internals'; // Special case AST transformation handling that requires coupling with a `RegExp` subclass (see @@ -157,17 +157,8 @@ function isLoneGLookaround(node, options) { ); } -function isZeroLengthNode(node) { - return ( - node.type === AstTypes.Assertion || - node.type === AstTypes.Directive || - (node.type === AstTypes.Quantifier && !node.min) - ); -} - export { applySubclassStrategies, EmulatedRegExp, isLoneGLookaround, - isZeroLengthNode, }; diff --git a/src/transform.js b/src/transform.js index 7abbeb9..038812b 100644 --- a/src/transform.js +++ b/src/transform.js @@ -1,10 +1,11 @@ import {Accuracy, Target} from './options.js'; -import {AstAssertionKinds, AstCharacterSetKinds, AstDirectiveKinds, AstTypes, AstVariableLengthCharacterSetKinds, createAlternative, createBackreference, createCapturingGroup, createGroup, createLookaround, createUnicodeProperty, isLookaround, parse} from './parse.js'; -import {applySubclassStrategies, isLoneGLookaround, isZeroLengthNode} from './subclass.js'; +import {AstAssertionKinds, AstCharacterSetKinds, AstDirectiveKinds, AstTypes, AstVariableLengthCharacterSetKinds, createAlternative, createBackreference, createCapturingGroup, createGroup, createLookaround, createUnicodeProperty, parse} from './parse.js'; +import {applySubclassStrategies, isLoneGLookaround} from './subclass.js'; import {tokenize} from './tokenize.js'; import {traverse} from './traverse.js'; import {JsUnicodeProperties, PosixClassesMap} from './unicode.js'; import {cp, getNewCurrentFlags, getOrCreate, isMinTarget, r} from './utils.js'; +import {isLookaround, isZeroLengthNode} from './utils-node.js'; import emojiRegex from 'emoji-regex-xs'; /** @@ -338,13 +339,13 @@ const SecondPassVisitor = { } }, - Recursion({node}, {reffedNodesByReferencer}) { + Recursion({node, parent}, {reffedNodesByReferencer}) { // Recursion nodes are created during the current traversal; they're only traversed here if a // recursion node created during traversal is then copied by a subroutine expansion, e.g. with // `(?\g)\g` const {ref} = node; // Immediate parent is an alternative or quantifier; can skip - let reffed = node.parent; + let reffed = parent; while ((reffed = reffed.parent)) { if (reffed.type === AstTypes.CapturingGroup && (reffed.name === ref || reffed.number === ref)) { break; diff --git a/src/traverse.js b/src/traverse.js index 9c9abeb..509a9d9 100644 --- a/src/traverse.js +++ b/src/traverse.js @@ -1,5 +1,6 @@ -import {AstTypes, getAstTypeAliases, isLookaround} from './parse.js'; +import {AstTypes} from './parse.js'; import {throwIfNot} from './utils.js'; +import {isLookaround} from './utils-node.js'; function traverse(path, state, visitor) { let ast = path.node; @@ -99,6 +100,21 @@ function traverse(path, state, visitor) { traverseNode(path.node, path.parent, path.key, path.container); } +const AstTypeAliases = { + AnyGroup: 'AnyGroup', + AnyNode: 'AnyNode', +}; + +function getAstTypeAliases(node) { + const {type} = node; + const types = [AstTypeAliases.AnyNode]; + if (type === AstTypes.CapturingGroup || type === AstTypes.Group || isLookaround(node)) { + types.push(AstTypeAliases.AnyGroup); + } + types.push(type); + return types; +} + function setParent(node, parent) { // The traverser can work with ASTs whose nodes include or don't include `parent` props, so only // update the parent if a prop for it exists diff --git a/src/utils-node.js b/src/utils-node.js new file mode 100644 index 0000000..13a92f2 --- /dev/null +++ b/src/utils-node.js @@ -0,0 +1,30 @@ +import {AstAssertionKinds, AstTypes} from './parse.js'; + +function hasOnlyChild({alternatives}, kidFn) { + return ( + alternatives.length === 1 && + alternatives[0].elements.length === 1 && + (!kidFn || kidFn(alternatives[0].elements[0])) + ); +} + +function isLookaround({type, kind}) { + return ( + type === AstTypes.Assertion && + (kind === AstAssertionKinds.lookahead || kind === AstAssertionKinds.lookbehind) + ); +} + +function isZeroLengthNode({type, min}) { + return ( + type === AstTypes.Assertion || + type === AstTypes.Directive || + (type === AstTypes.Quantifier && !min) + ); +} + +export { + hasOnlyChild, + isLookaround, + isZeroLengthNode, +}; diff --git a/src/utils.js b/src/utils.js index 3818388..182fac3 100644 --- a/src/utils.js +++ b/src/utils.js @@ -44,12 +44,6 @@ function getOrCreate(map, key, defaultValue) { return map.get(key); } -function hasOnlyChild(node, kidFn) { - return node.alternatives.length === 1 && - node.alternatives[0].elements.length === 1 && - (!kidFn || kidFn(node.alternatives[0].elements[0])); -} - /** @param {keyof Target} target @param {keyof Target} min @@ -73,7 +67,6 @@ export { envSupportsFlagV, getNewCurrentFlags, getOrCreate, - hasOnlyChild, isMinTarget, r, throwIfNot,