@ptolemy2002/rgx 13.3.4 → 13.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/class/group.d.ts +5 -1
- package/dist/class/group.js +26 -6
- package/dist/errors/base.d.ts +1 -1
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.js +2 -0
- package/dist/errors/invalidRegexLocalizableFlagDiff.d.ts +6 -0
- package/dist/errors/invalidRegexLocalizableFlagDiff.js +15 -0
- package/dist/errors/invalidRegexLocalizableFlags.d.ts +6 -0
- package/dist/errors/invalidRegexLocalizableFlags.js +15 -0
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.js +1 -0
- package/dist/internal/localizableVanillaRegexFlagDiff.d.ts +2 -0
- package/dist/internal/localizableVanillaRegexFlagDiff.js +17 -0
- package/dist/resolve.js +2 -15
- package/dist/typeGuards.d.ts +4 -0
- package/dist/typeGuards.js +22 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +3 -1
- package/dist/walker/base.d.ts +4 -0
- package/dist/walker/base.js +45 -27
- package/package.json +1 -1
package/dist/class/group.d.ts
CHANGED
|
@@ -4,10 +4,12 @@ import { CloneDepth } from "@ptolemy2002/immutability-utils";
|
|
|
4
4
|
export type RGXGroupTokenArgs = {
|
|
5
5
|
name?: string | null;
|
|
6
6
|
capturing?: boolean;
|
|
7
|
+
flags?: string;
|
|
7
8
|
};
|
|
8
9
|
export declare class RGXGroupToken extends RGXClassToken {
|
|
9
10
|
tokens: RGXTokenCollection;
|
|
10
11
|
_name: string | null;
|
|
12
|
+
_flags: string;
|
|
11
13
|
_capturing: boolean;
|
|
12
14
|
static check: (value: unknown) => value is RGXGroupToken;
|
|
13
15
|
static assert: (value: unknown) => asserts value is RGXGroupToken;
|
|
@@ -15,9 +17,11 @@ export declare class RGXGroupToken extends RGXClassToken {
|
|
|
15
17
|
set name(value: string | null);
|
|
16
18
|
get capturing(): boolean;
|
|
17
19
|
set capturing(value: boolean);
|
|
20
|
+
get flags(): string;
|
|
21
|
+
set flags(value: string);
|
|
18
22
|
get rgxIsGroup(): true;
|
|
19
23
|
get rgxGroupWrap(): false;
|
|
20
|
-
constructor({ name, capturing }?: RGXGroupTokenArgs, tokens?: RGXTokenCollectionInput);
|
|
24
|
+
constructor({ name, capturing, flags }?: RGXGroupTokenArgs, tokens?: RGXTokenCollectionInput);
|
|
21
25
|
toRgx(): RegExp;
|
|
22
26
|
clone(depth?: CloneDepth): RGXGroupToken;
|
|
23
27
|
}
|
package/dist/class/group.js
CHANGED
|
@@ -25,6 +25,13 @@ class RGXGroupToken extends base_1.RGXClassToken {
|
|
|
25
25
|
this.name = null; // Non-capturing groups cannot have names
|
|
26
26
|
this._capturing = value;
|
|
27
27
|
}
|
|
28
|
+
get flags() {
|
|
29
|
+
return this._flags;
|
|
30
|
+
}
|
|
31
|
+
set flags(value) {
|
|
32
|
+
(0, typeGuards_1.assertValidRegexLocalizableFlags)(value);
|
|
33
|
+
this._flags = value;
|
|
34
|
+
}
|
|
28
35
|
get rgxIsGroup() {
|
|
29
36
|
return true;
|
|
30
37
|
}
|
|
@@ -32,12 +39,14 @@ class RGXGroupToken extends base_1.RGXClassToken {
|
|
|
32
39
|
// When this token is resolved, it will wrap itself in a group, so we don't want the resolver to group wrap it again.
|
|
33
40
|
return false;
|
|
34
41
|
}
|
|
35
|
-
constructor({ name = null, capturing = true } = {}, tokens = []) {
|
|
42
|
+
constructor({ name = null, capturing = true, flags = '' } = {}, tokens = []) {
|
|
36
43
|
super();
|
|
37
44
|
this._name = null;
|
|
45
|
+
this._flags = '';
|
|
38
46
|
this._capturing = true;
|
|
39
47
|
this.name = name;
|
|
40
48
|
this.capturing = capturing;
|
|
49
|
+
this.flags = flags;
|
|
41
50
|
if (tokens instanceof collection_1.RGXTokenCollection && tokens.mode === 'union')
|
|
42
51
|
this.tokens = new collection_1.RGXTokenCollection(tokens, 'concat');
|
|
43
52
|
else
|
|
@@ -46,18 +55,29 @@ class RGXGroupToken extends base_1.RGXClassToken {
|
|
|
46
55
|
toRgx() {
|
|
47
56
|
// The collection token doesn't group itself, so this is safe.
|
|
48
57
|
let result = this.tokens.toRgx().source;
|
|
49
|
-
|
|
58
|
+
const hasFlags = this.flags.length > 0;
|
|
59
|
+
// This will return the flags that are not present in the flags variable, preceded by a "-" if there are any.
|
|
60
|
+
const flagsNotPresent = (0, internal_1.localizableVanillaRegexFlagDiff)("ims", this.flags);
|
|
61
|
+
if (this.name !== null) {
|
|
50
62
|
result = `(?<${this.name}>${result})`;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
63
|
+
}
|
|
64
|
+
else if (!this.capturing) {
|
|
65
|
+
if (!hasFlags)
|
|
66
|
+
result = `(?:${result})`;
|
|
67
|
+
else
|
|
68
|
+
result = `(?${this.flags}${flagsNotPresent}:${result})`;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
54
71
|
result = `(${result})`;
|
|
72
|
+
}
|
|
73
|
+
if ((this.name !== null || this.capturing) && hasFlags)
|
|
74
|
+
result = `(?${this.flags}${flagsNotPresent}:${result})`;
|
|
55
75
|
return (0, utils_1.createRegex)(result);
|
|
56
76
|
}
|
|
57
77
|
clone(depth = "max") {
|
|
58
78
|
if (depth === 0)
|
|
59
79
|
return this;
|
|
60
|
-
return new RGXGroupToken({ name: this.name, capturing: this._capturing }, this.tokens.clone((0, immutability_utils_1.depthDecrement)(depth, 1)));
|
|
80
|
+
return new RGXGroupToken({ name: this.name, capturing: this._capturing, flags: this.flags }, this.tokens.clone((0, immutability_utils_1.depthDecrement)(depth, 1)));
|
|
61
81
|
}
|
|
62
82
|
}
|
|
63
83
|
exports.RGXGroupToken = RGXGroupToken;
|
package/dist/errors/base.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'NOT_SUPPORTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT' | 'CONSTANT_CONFLICT' | 'INVALID_CONSTANT_KEY' | 'INSERTION_REJECTED' | 'REGEX_NOT_MATCHED_AT_POSITION' | 'REGEX_NOT_MATCHED_AFTER_POSITION' | 'PART_VALIDATION_FAILED' | 'INVALID_LEXER_MODE' | 'LEXEME_NOT_MATCHED_AT_POSITION' | 'INVALID_RGX_LEXER' | 'INVALID_RGX_WALKER' | 'INVALID_RGX_PART' | 'NOT_DIRECT_REGEXP' | 'CURRENT_TOKEN_NOT_FOUND';
|
|
1
|
+
export type RGXErrorCode = 'UNKNOWN' | 'INVALID_RGX_TOKEN' | 'INVALID_REGEX_STRING' | 'INVALID_REGEX_FLAGS' | 'INVALID_VANILLA_REGEX_FLAGS' | 'NOT_IMPLEMENTED' | 'NOT_SUPPORTED' | 'INVALID_IDENTIFIER' | 'OUT_OF_BOUNDS' | 'INVALID_FLAG_TRANSFORMER_KEY' | 'FLAG_TRANSFORMER_CONFLICT' | 'CONSTANT_CONFLICT' | 'INVALID_CONSTANT_KEY' | 'INSERTION_REJECTED' | 'REGEX_NOT_MATCHED_AT_POSITION' | 'REGEX_NOT_MATCHED_AFTER_POSITION' | 'PART_VALIDATION_FAILED' | 'INVALID_LEXER_MODE' | 'LEXEME_NOT_MATCHED_AT_POSITION' | 'INVALID_RGX_LEXER' | 'INVALID_RGX_WALKER' | 'INVALID_RGX_PART' | 'NOT_DIRECT_REGEXP' | 'CURRENT_TOKEN_NOT_FOUND' | 'INVALID_REGEX_LOCALIZABLE_FLAG_DIFF' | 'INVALID_REGEX_LOCALIZABLE_FLAGS';
|
|
2
2
|
export declare class RGXError extends Error {
|
|
3
3
|
_message: string;
|
|
4
4
|
code: RGXErrorCode;
|
package/dist/errors/index.d.ts
CHANGED
package/dist/errors/index.js
CHANGED
|
@@ -38,3 +38,5 @@ __exportStar(require("./invalidWalker"), exports);
|
|
|
38
38
|
__exportStar(require("./invalidPart"), exports);
|
|
39
39
|
__exportStar(require("./notDirectRegexp"), exports);
|
|
40
40
|
__exportStar(require("./currentTokenNotFound"), exports);
|
|
41
|
+
__exportStar(require("./invalidRegexLocalizableFlagDiff"), exports);
|
|
42
|
+
__exportStar(require("./invalidRegexLocalizableFlags"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RGXInvalidRegexLocalizableFlagDiffError = void 0;
|
|
4
|
+
const errors_1 = require("./");
|
|
5
|
+
class RGXInvalidRegexLocalizableFlagDiffError extends errors_1.RGXError {
|
|
6
|
+
constructor(message, got) {
|
|
7
|
+
super(message, 'INVALID_REGEX_LOCALIZABLE_FLAG_DIFF');
|
|
8
|
+
this.name = 'RGXInvalidRegexLocalizableFlagDiffError';
|
|
9
|
+
this.got = got;
|
|
10
|
+
}
|
|
11
|
+
calcMessage(message) {
|
|
12
|
+
return `${message}; Got: ${JSON.stringify(this.got)}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.RGXInvalidRegexLocalizableFlagDiffError = RGXInvalidRegexLocalizableFlagDiffError;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RGXInvalidRegexLocalizableFlagsError = void 0;
|
|
4
|
+
const errors_1 = require("./");
|
|
5
|
+
class RGXInvalidRegexLocalizableFlagsError extends errors_1.RGXError {
|
|
6
|
+
constructor(message, got) {
|
|
7
|
+
super(message, 'INVALID_REGEX_LOCALIZABLE_FLAGS');
|
|
8
|
+
this.name = 'RGXInvalidRegexLocalizableFlagsError';
|
|
9
|
+
this.got = got;
|
|
10
|
+
}
|
|
11
|
+
calcMessage(message) {
|
|
12
|
+
return `${message}; Got: ${JSON.stringify(this.got)}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.RGXInvalidRegexLocalizableFlagsError = RGXInvalidRegexLocalizableFlagsError;
|
package/dist/internal/index.d.ts
CHANGED
package/dist/internal/index.js
CHANGED
|
@@ -19,3 +19,4 @@ __exportStar(require("./taggedTemplateToArray"), exports);
|
|
|
19
19
|
__exportStar(require("./isConstructor"), exports);
|
|
20
20
|
__exportStar(require("./getProxy"), exports);
|
|
21
21
|
__exportStar(require("./assureAcceptance"), exports);
|
|
22
|
+
__exportStar(require("./localizableVanillaRegexFlagDiff"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.localizableVanillaRegexFlagDiff = localizableVanillaRegexFlagDiff;
|
|
4
|
+
function localizableVanillaRegexFlagDiff(prev, next) {
|
|
5
|
+
// Remove anything other than the "ims" flags from both strings, as
|
|
6
|
+
// other flags are not localizable (including our custom flags).
|
|
7
|
+
prev = prev.replaceAll(/[^ims]/g, '');
|
|
8
|
+
next = next.replaceAll(/[^ims]/g, '');
|
|
9
|
+
// Format <added flags>-<removed flags>
|
|
10
|
+
const added = [...new Set(next.split(''))].filter(flag => !prev.includes(flag)).join('');
|
|
11
|
+
const removed = [...new Set(prev.split(''))].filter(flag => !next.includes(flag)).join('');
|
|
12
|
+
if (added === '' && removed === '')
|
|
13
|
+
return '';
|
|
14
|
+
if (removed === '')
|
|
15
|
+
return `${added}`;
|
|
16
|
+
return `${added}-${removed}`;
|
|
17
|
+
}
|
package/dist/resolve.js
CHANGED
|
@@ -39,25 +39,12 @@ const class_1 = require("./class");
|
|
|
39
39
|
const e = __importStar(require("./errors"));
|
|
40
40
|
const ExtRegExp_1 = require("./ExtRegExp");
|
|
41
41
|
const tg = __importStar(require("./typeGuards"));
|
|
42
|
+
const internal_1 = require("./internal");
|
|
42
43
|
function escapeRegex(value) {
|
|
43
44
|
const result = value.replaceAll(/[\-\^\$.*+?^${}()|[\]\\]/g, '\\$&');
|
|
44
45
|
tg.assertValidRegexString(result);
|
|
45
46
|
return result;
|
|
46
47
|
}
|
|
47
|
-
function localizableVanillaRegexFlagDiff(prev, next) {
|
|
48
|
-
// Remove anything other than the "ims" flags from both strings, as
|
|
49
|
-
// other flags are not localizable (including our custom flags).
|
|
50
|
-
prev = prev.replaceAll(/[^ims]/g, '');
|
|
51
|
-
next = next.replaceAll(/[^ims]/g, '');
|
|
52
|
-
// Format <added flags>-<removed flags>
|
|
53
|
-
const added = [...new Set(next.split(''))].filter(flag => !prev.includes(flag)).join('');
|
|
54
|
-
const removed = [...new Set(prev.split(''))].filter(flag => !next.includes(flag)).join('');
|
|
55
|
-
if (added === '' && removed === '')
|
|
56
|
-
return '';
|
|
57
|
-
if (removed === '')
|
|
58
|
-
return `${added}`;
|
|
59
|
-
return `${added}-${removed}`;
|
|
60
|
-
}
|
|
61
48
|
function hasParenErrors(pattern) {
|
|
62
49
|
let depth = 0;
|
|
63
50
|
let charClassDepth = 0;
|
|
@@ -95,7 +82,7 @@ function resolveRGXToken(token, { groupWrap = true, topLevel = true, currentFlag
|
|
|
95
82
|
if (tg.isRGXNoOpToken(token))
|
|
96
83
|
return '';
|
|
97
84
|
if (tg.isRGXLiteralToken(token)) {
|
|
98
|
-
const localizableFlagDiff = localizableVanillaRegexFlagDiff(currentFlags, token.flags);
|
|
85
|
+
const localizableFlagDiff = (0, internal_1.localizableVanillaRegexFlagDiff)(currentFlags, token.flags);
|
|
99
86
|
currentFlags = token.flags;
|
|
100
87
|
if (!localizableFlagDiff) {
|
|
101
88
|
if (groupWrap)
|
package/dist/typeGuards.d.ts
CHANGED
|
@@ -24,3 +24,7 @@ export declare function isValidVanillaRegexFlags(value: string): value is t.Vali
|
|
|
24
24
|
export declare function assertValidVanillaRegexFlags(value: string): asserts value is t.ValidVanillaRegexFlags;
|
|
25
25
|
export declare function isValidIdentifier(value: string): value is t.ValidIdentifier;
|
|
26
26
|
export declare function assertValidIdentifier(value: string): asserts value is t.ValidIdentifier;
|
|
27
|
+
export declare function isValidRegexLocalizableFlagDiff(value: string): value is t.ValidRegexLocalizableFlagDiff;
|
|
28
|
+
export declare function assertValidRegexLocalizableFlagDiff(value: string): asserts value is t.ValidRegexLocalizableFlagDiff;
|
|
29
|
+
export declare function isValidRegexLocalizableFlags(value: string): value is t.ValidRegexLocalizableFlags;
|
|
30
|
+
export declare function assertValidRegexLocalizableFlags(value: string): asserts value is t.ValidRegexLocalizableFlags;
|
package/dist/typeGuards.js
CHANGED
|
@@ -61,6 +61,10 @@ exports.isValidVanillaRegexFlags = isValidVanillaRegexFlags;
|
|
|
61
61
|
exports.assertValidVanillaRegexFlags = assertValidVanillaRegexFlags;
|
|
62
62
|
exports.isValidIdentifier = isValidIdentifier;
|
|
63
63
|
exports.assertValidIdentifier = assertValidIdentifier;
|
|
64
|
+
exports.isValidRegexLocalizableFlagDiff = isValidRegexLocalizableFlagDiff;
|
|
65
|
+
exports.assertValidRegexLocalizableFlagDiff = assertValidRegexLocalizableFlagDiff;
|
|
66
|
+
exports.isValidRegexLocalizableFlags = isValidRegexLocalizableFlags;
|
|
67
|
+
exports.assertValidRegexLocalizableFlags = assertValidRegexLocalizableFlags;
|
|
64
68
|
const e = __importStar(require("./errors"));
|
|
65
69
|
const is_callable_1 = __importDefault(require("is-callable"));
|
|
66
70
|
const internal_1 = require("./internal");
|
|
@@ -295,3 +299,21 @@ function assertValidIdentifier(value) {
|
|
|
295
299
|
throw new e.RGXInvalidIdentifierError("Invalid identifier", value);
|
|
296
300
|
}
|
|
297
301
|
}
|
|
302
|
+
function isValidRegexLocalizableFlagDiff(value) {
|
|
303
|
+
if (value === '')
|
|
304
|
+
return true;
|
|
305
|
+
return /^[ims]+(-[ims]+)?$/.test(value);
|
|
306
|
+
}
|
|
307
|
+
function assertValidRegexLocalizableFlagDiff(value) {
|
|
308
|
+
if (!isValidRegexLocalizableFlagDiff(value)) {
|
|
309
|
+
throw new e.RGXInvalidRegexLocalizableFlagDiffError("Invalid localizable flag diff", value);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function isValidRegexLocalizableFlags(value) {
|
|
313
|
+
return /^[ims]*$/.test(value);
|
|
314
|
+
}
|
|
315
|
+
function assertValidRegexLocalizableFlags(value) {
|
|
316
|
+
if (!isValidRegexLocalizableFlags(value)) {
|
|
317
|
+
throw new e.RGXInvalidRegexLocalizableFlagsError("Invalid localizable flags", value);
|
|
318
|
+
}
|
|
319
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -50,6 +50,12 @@ export type ValidRegexFlags = Branded<string, [ValidRegexFlagsBrandSymbol]> | Va
|
|
|
50
50
|
export declare const validIdentifierSymbol: unique symbol;
|
|
51
51
|
export type ValidIdentifierBrandSymbol = typeof validIdentifierSymbol;
|
|
52
52
|
export type ValidIdentifier = Branded<string, [ValidIdentifierBrandSymbol]>;
|
|
53
|
+
export declare const validRegexLocalizableFlagsSymbol: unique symbol;
|
|
54
|
+
export type ValidRegexLocalizableFlagsBrandSymbol = typeof validRegexLocalizableFlagsSymbol;
|
|
55
|
+
export type ValidRegexLocalizableFlags = Branded<string, [ValidRegexLocalizableFlagsBrandSymbol]>;
|
|
56
|
+
export declare const validRegexLocalizableFlagDiffSymbol: unique symbol;
|
|
57
|
+
export type ValidRegexLocalizableFlagDiffBrandSymbol = typeof validRegexLocalizableFlagDiffSymbol;
|
|
58
|
+
export type ValidRegexLocalizableFlagDiff = Branded<string, [ValidRegexLocalizableFlagDiffBrandSymbol]>;
|
|
53
59
|
export type RGXOptions = {
|
|
54
60
|
multiline?: boolean;
|
|
55
61
|
verbatim?: boolean;
|
package/dist/types.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validIdentifierSymbol = exports.validRegexFlagsSymbol = exports.validVanillaRegexFlagsSymbol = exports.validRegexSymbol = void 0;
|
|
3
|
+
exports.validRegexLocalizableFlagDiffSymbol = exports.validRegexLocalizableFlagsSymbol = exports.validIdentifierSymbol = exports.validRegexFlagsSymbol = exports.validVanillaRegexFlagsSymbol = exports.validRegexSymbol = void 0;
|
|
4
4
|
exports.validRegexSymbol = Symbol('rgx.ValidRegex');
|
|
5
5
|
exports.validVanillaRegexFlagsSymbol = Symbol('rgx.ValidVanillaRegexFlags');
|
|
6
6
|
exports.validRegexFlagsSymbol = Symbol('rgx.ValidRegexFlags');
|
|
7
7
|
exports.validIdentifierSymbol = Symbol('rgx.ValidIdentifier');
|
|
8
|
+
exports.validRegexLocalizableFlagsSymbol = Symbol('rgx.ValidRegexLocalizableFlags');
|
|
9
|
+
exports.validRegexLocalizableFlagDiffSymbol = Symbol('rgx.ValidRegexLocalizableFlagDiff');
|
package/dist/walker/base.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export type RGXTryWalkOptions = {
|
|
|
14
14
|
revertShare?: boolean;
|
|
15
15
|
revertCaptures?: boolean;
|
|
16
16
|
};
|
|
17
|
+
export type RGXWalkerSnapshotKey = "sourcePosition" | "tokenPosition" | "reduced" | "share" | "captures" | "namedCaptures";
|
|
17
18
|
export type RGXTokenOrPart<R, S = unknown, T = any> = RGXToken | RGXPart<R, S, T>;
|
|
18
19
|
export type RGXWalkerStepDirective = "stop" | "skip" | "silent";
|
|
19
20
|
export declare class RGXWalker<R, S = unknown> {
|
|
@@ -30,6 +31,7 @@ export declare class RGXWalker<R, S = unknown> {
|
|
|
30
31
|
contiguous: boolean;
|
|
31
32
|
private _stopped;
|
|
32
33
|
private _didReachEnd;
|
|
34
|
+
private _snapshots;
|
|
33
35
|
static check: (value: unknown) => value is RGXWalker<unknown, unknown>;
|
|
34
36
|
static assert: (value: unknown) => asserts value is RGXWalker<unknown, unknown>;
|
|
35
37
|
get sourcePosition(): number;
|
|
@@ -61,6 +63,8 @@ export declare class RGXWalker<R, S = unknown> {
|
|
|
61
63
|
stepToToken(predicate: (token: RGXTokenOrPart<R>) => boolean): this;
|
|
62
64
|
stepToPart(predicate?: (part: RGXPart<R, S, unknown>) => boolean): this;
|
|
63
65
|
walk(): R;
|
|
66
|
+
snapshot(name: string, ...keys: Array<RGXWalkerSnapshotKey | false>): this;
|
|
67
|
+
restore(name: string): this;
|
|
64
68
|
tryWalk({ revertReduced, revertShare, revertCaptures }?: RGXTryWalkOptions): boolean;
|
|
65
69
|
clone(depth?: CloneDepth): RGXWalker<R, S>;
|
|
66
70
|
}
|
package/dist/walker/base.js
CHANGED
|
@@ -55,6 +55,7 @@ class RGXWalker {
|
|
|
55
55
|
this._stopped = false;
|
|
56
56
|
// Only relevant in infinite mode, tracking whether we've reached the end yet.
|
|
57
57
|
this._didReachEnd = false;
|
|
58
|
+
this._snapshots = new Map();
|
|
58
59
|
this.source = source;
|
|
59
60
|
this.sourcePosition = options.startingSourcePosition ?? 0;
|
|
60
61
|
this.tokens = tokens;
|
|
@@ -184,13 +185,13 @@ class RGXWalker {
|
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
// Returns a directive on handled validation failure, null on success. Unhandled errors are rethrown.
|
|
187
|
-
validateCapture(token, captureResult
|
|
188
|
+
validateCapture(token, captureResult) {
|
|
188
189
|
try {
|
|
189
190
|
token.validate(captureResult, { part: token, walker: this });
|
|
190
191
|
return null;
|
|
191
192
|
}
|
|
192
193
|
catch (e) {
|
|
193
|
-
this.
|
|
194
|
+
this.restore("step"); // Reset source position on validation failure
|
|
194
195
|
if (e instanceof errors_1.RGXPartValidationFailedError) {
|
|
195
196
|
const control = token.afterValidationFailure?.(e, { part: token, walker: this });
|
|
196
197
|
// If this happens, afterValidationFailure itself stopped the walker, so we just need to respect that.
|
|
@@ -205,7 +206,7 @@ class RGXWalker {
|
|
|
205
206
|
throw e;
|
|
206
207
|
}
|
|
207
208
|
}
|
|
208
|
-
handleAfterCapture(token, captureResult, silent
|
|
209
|
+
handleAfterCapture(token, captureResult, silent) {
|
|
209
210
|
const control = token.afterCapture?.(captureResult, { part: token, walker: this });
|
|
210
211
|
if (!silent && (control === "skip" || control === "silent" || control === "stop-silent")) {
|
|
211
212
|
this.unregisterLastCapture(token);
|
|
@@ -214,7 +215,7 @@ class RGXWalker {
|
|
|
214
215
|
if (this.stopped)
|
|
215
216
|
return "stop";
|
|
216
217
|
if (control === "skip") {
|
|
217
|
-
this.
|
|
218
|
+
this.restore("step");
|
|
218
219
|
return "skip";
|
|
219
220
|
}
|
|
220
221
|
if (control === "stop" || control === "stop-silent")
|
|
@@ -247,9 +248,9 @@ class RGXWalker {
|
|
|
247
248
|
silent = dir === "silent";
|
|
248
249
|
}
|
|
249
250
|
const branchedToken = isPart ? createBranchGroups(token.token) : createBranchGroups(token);
|
|
250
|
-
//
|
|
251
|
-
//
|
|
252
|
-
|
|
251
|
+
// Snapshot the source position so validateCapture and handleAfterCapture
|
|
252
|
+
// can restore it on skip/failure.
|
|
253
|
+
this.snapshot("step", "sourcePosition");
|
|
253
254
|
let captureAttempt;
|
|
254
255
|
try {
|
|
255
256
|
captureAttempt = this.attemptCapture(branchedToken, isPart ? token : null);
|
|
@@ -287,7 +288,7 @@ class RGXWalker {
|
|
|
287
288
|
groups: captureAttempt.groups ?? null
|
|
288
289
|
};
|
|
289
290
|
if (isPart) {
|
|
290
|
-
const dir = this.validateCapture(token, captureResult
|
|
291
|
+
const dir = this.validateCapture(token, captureResult);
|
|
291
292
|
if (dir === "stop") {
|
|
292
293
|
this._stopped = true;
|
|
293
294
|
return null;
|
|
@@ -300,7 +301,7 @@ class RGXWalker {
|
|
|
300
301
|
if (!silent)
|
|
301
302
|
this.registerCapture(captureResult, token);
|
|
302
303
|
if (isPart) {
|
|
303
|
-
const dir = this.handleAfterCapture(token, captureResult, silent
|
|
304
|
+
const dir = this.handleAfterCapture(token, captureResult, silent);
|
|
304
305
|
if (dir === "stop") {
|
|
305
306
|
this.advanceToken();
|
|
306
307
|
this._stopped = true;
|
|
@@ -341,31 +342,48 @@ class RGXWalker {
|
|
|
341
342
|
this.stepToToken(() => false);
|
|
342
343
|
return this.reduced;
|
|
343
344
|
}
|
|
345
|
+
snapshot(name, ...keys) {
|
|
346
|
+
const filteredKeys = keys.filter((k) => k !== false);
|
|
347
|
+
const snap = {};
|
|
348
|
+
for (const key of filteredKeys) {
|
|
349
|
+
if (key === "sourcePosition" || key === "tokenPosition") {
|
|
350
|
+
snap[key] = this[key];
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
snap[key] = (0, immutability_utils_1.extClone)(this[key], "max");
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
this._snapshots.set(name, snap);
|
|
357
|
+
return this;
|
|
358
|
+
}
|
|
359
|
+
restore(name) {
|
|
360
|
+
const snap = this._snapshots.get(name);
|
|
361
|
+
if (!snap)
|
|
362
|
+
return this;
|
|
363
|
+
if ("sourcePosition" in snap)
|
|
364
|
+
this.sourcePosition = snap.sourcePosition;
|
|
365
|
+
if ("tokenPosition" in snap)
|
|
366
|
+
this.tokenPosition = snap.tokenPosition;
|
|
367
|
+
if ("reduced" in snap)
|
|
368
|
+
this.reduced = snap.reduced;
|
|
369
|
+
if ("share" in snap)
|
|
370
|
+
this.share = snap.share;
|
|
371
|
+
if ("captures" in snap)
|
|
372
|
+
this.captures = snap.captures;
|
|
373
|
+
if ("namedCaptures" in snap)
|
|
374
|
+
this.namedCaptures = snap.namedCaptures;
|
|
375
|
+
return this;
|
|
376
|
+
}
|
|
344
377
|
tryWalk({ revertReduced = false, revertShare = false, revertCaptures = false } = {}) {
|
|
345
|
-
|
|
346
|
-
const prevTokenPosition = this.tokenPosition;
|
|
347
|
-
const prevReduced = revertReduced ? (0, immutability_utils_1.extClone)(this.reduced, "max") : this.reduced;
|
|
348
|
-
const prevShare = revertShare ? (0, immutability_utils_1.extClone)(this.share, "max") : this.share;
|
|
349
|
-
const prevCaptures = revertCaptures ? (0, immutability_utils_1.extClone)(this.captures, "max") : this.captures;
|
|
350
|
-
const prevNamedCaptures = revertCaptures ? (0, immutability_utils_1.extClone)(this.namedCaptures, "max") : this.namedCaptures;
|
|
378
|
+
this.snapshot("tryWalk", "sourcePosition", "tokenPosition", revertReduced && "reduced", revertShare && "share", revertCaptures && "captures", revertCaptures && "namedCaptures");
|
|
351
379
|
try {
|
|
352
380
|
this.walk();
|
|
353
381
|
return true;
|
|
354
382
|
}
|
|
355
383
|
catch (e) {
|
|
356
|
-
this.
|
|
357
|
-
|
|
358
|
-
if (revertReduced)
|
|
359
|
-
this.reduced = prevReduced;
|
|
360
|
-
if (revertShare)
|
|
361
|
-
this.share = prevShare;
|
|
362
|
-
if (revertCaptures)
|
|
363
|
-
this.captures = prevCaptures;
|
|
364
|
-
if (revertCaptures)
|
|
365
|
-
this.namedCaptures = prevNamedCaptures;
|
|
366
|
-
if (isMatchError(e)) {
|
|
384
|
+
this.restore("tryWalk");
|
|
385
|
+
if (isMatchError(e))
|
|
367
386
|
return false;
|
|
368
|
-
}
|
|
369
387
|
throw e;
|
|
370
388
|
}
|
|
371
389
|
}
|