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,