Skip to content

Commit 363a004

Browse files
committed
Avoid extra processing if not needed
1 parent 2131a00 commit 363a004

File tree

1 file changed

+15
-11
lines changed

1 file changed

+15
-11
lines changed

src/index.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function recursion(expression) {
4242
// duplicated by recursion and refer to a group inside the expression being recursed.
4343
// Additionally, numbered backrefs inside and outside of the recursed expression would need to
4444
// be adjusted based on any capturing groups added by recursion.
45-
throw new Error(`Numbered backrefs cannot be used with recursion; use named backref instead`);
45+
throw new Error(`Numbered backrefs cannot be used with recursion; use named backref`);
4646
}
4747
if (hasUnescaped(expression, String.raw`\(\?\(DEFINE\)`, Context.DEFAULT)) {
4848
throw new Error(`DEFINE groups cannot be used with recursion`);
@@ -66,7 +66,7 @@ export function recursion(expression) {
6666
const pre = expression.slice(0, match.index);
6767
const post = expression.slice(token.lastIndex);
6868
assertNoFollowingRecursion(post);
69-
return makeRecursive(pre, post, maxDepth);
69+
return makeRecursive(pre, post, maxDepth, false);
7070
// \g<name&R=N>
7171
} else if (gRName) {
7272
const maxDepth = +gRDepth;
@@ -86,7 +86,7 @@ export function recursion(expression) {
8686
const post = recursiveGroupContents.slice(pre.length + m.length);
8787
assertNoFollowingRecursion(post);
8888
return expression.slice(0, startPos) +
89-
makeRecursive(pre, post, maxDepth) +
89+
makeRecursive(pre, post, maxDepth, true) +
9090
expression.slice(startPos + recursiveGroupContents.length);
9191
}
9292

@@ -116,27 +116,31 @@ function assertNoFollowingRecursion(remainingExpression) {
116116
@param {string} pre
117117
@param {string} post
118118
@param {number} maxDepth
119+
@param {boolean} isSubpattern
119120
@returns {string}
120121
*/
121-
function makeRecursive(pre, post, maxDepth) {
122+
function makeRecursive(pre, post, maxDepth, isSubpattern) {
122123
const namesInRecursed = new Set();
123-
forEachUnescaped(pre + post, namedCapturingDelim, ({groups: {captureName}}) => {
124-
namesInRecursed.add(captureName);
125-
}, Context.DEFAULT);
124+
// Avoid this work if not needed
125+
if (isSubpattern) {
126+
forEachUnescaped(pre + post, namedCapturingDelim, ({groups: {captureName}}) => {
127+
namesInRecursed.add(captureName);
128+
}, Context.DEFAULT);
129+
}
126130
const reps = maxDepth - 1;
127131
// Depth 2: 'pre(?:pre(?:)post)post'
128132
// Depth 3: 'pre(?:pre(?:pre(?:)post)post)post'
129133
return `${pre}${
130-
repeatWithDepth(`(?:${pre}`, reps, namesInRecursed)
134+
repeatWithDepth(`(?:${pre}`, reps, isSubpattern ? namesInRecursed: null)
131135
}(?:)${
132-
repeatWithDepth(`${post})`, reps, namesInRecursed, 'backward')
136+
repeatWithDepth(`${post})`, reps, isSubpattern ? namesInRecursed: null, 'backward')
133137
}${post}`;
134138
}
135139

136140
/**
137141
@param {string} expression
138142
@param {number} reps
139-
@param {Set<string>} namesInRecursed
143+
@param {Set<string> | null} namesInRecursed
140144
@param {'forward' | 'backward'} [direction]
141145
@returns {string}
142146
*/
@@ -150,7 +154,7 @@ function repeatWithDepth(expression, reps, namesInRecursed, direction = 'forward
150154
expression,
151155
String.raw`${namedCapturingDelim}|\\k<(?<backref>[^>]+)>`,
152156
({0: m, groups: {captureName, backref}}) => {
153-
if (backref && !namesInRecursed.has(backref)) {
157+
if (backref && namesInRecursed && !namesInRecursed.has(backref)) {
154158
return m;
155159
}
156160
const suffix = `_$${captureNum}`;

0 commit comments

Comments
 (0)