regex-partial-match 1.3.0 → 2.0.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.
Files changed (137) hide show
  1. package/README.md +120 -267
  2. package/lib/core/corePartialMatchRegExp.d.ts +24 -0
  3. package/lib/core/corePartialMatchRegExp.js +22 -0
  4. package/lib/core/index.d.ts +4 -0
  5. package/lib/core/index.js +2 -0
  6. package/lib/extend/index.d.ts +6 -7
  7. package/lib/extend/index.js +1 -1
  8. package/lib/features/index.d.ts +20 -0
  9. package/lib/features/index.js +23 -0
  10. package/lib/hitEnd/index.d.ts +45 -0
  11. package/lib/hitEnd/index.js +57 -0
  12. package/lib/hitEnd/matchHitEnd.d.ts +4 -0
  13. package/lib/hitEnd/matchHitEnd.js +51 -0
  14. package/lib/{partialMatchRegExp/isComplete → hitEnd}/partRole.d.ts +1 -1
  15. package/lib/hitEnd/partRole.js +17 -0
  16. package/lib/hitEnd/truncationProbe.d.ts +8 -0
  17. package/lib/hitEnd/truncationProbe.js +187 -0
  18. package/lib/hitEnd/truncationProbeCache.d.ts +14 -0
  19. package/lib/index.d.ts +4 -0
  20. package/lib/index.js +4 -0
  21. package/lib/modules/backreferences/asNativeAtom.d.ts +2 -0
  22. package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/asNativeAtom.js +2 -2
  23. package/lib/modules/backreferences/asPreScanPart.d.ts +2 -0
  24. package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/asPreScanPart.js +2 -2
  25. package/lib/modules/backreferences/backreferenceRecorder.d.ts +2 -0
  26. package/lib/modules/backreferences/backreferenceRecorder.js +38 -0
  27. package/lib/modules/backreferences/compileDynamic.d.ts +4 -0
  28. package/lib/modules/backreferences/compileDynamic.js +53 -0
  29. package/lib/modules/backreferences/compiledBackreferences.d.ts +9 -0
  30. package/lib/modules/backreferences/compiledBackreferences.js +9 -0
  31. package/lib/modules/backreferences/constants.d.ts +2 -0
  32. package/lib/modules/backreferences/constants.js +2 -0
  33. package/lib/modules/backreferences/execDynamic.d.ts +2 -0
  34. package/lib/modules/backreferences/execDynamic.js +43 -0
  35. package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/flagsAtBackreference.d.ts +1 -1
  36. package/lib/{partialMatchRegExp → modules/backreferences}/groupName.js +1 -1
  37. package/lib/modules/backreferences/index.d.ts +10 -0
  38. package/lib/modules/backreferences/index.js +20 -0
  39. package/lib/modules/backreferences/longestBakedPrefixEndingInput.js +46 -0
  40. package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/renderParts.d.ts +1 -1
  41. package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/renderParts.js +1 -1
  42. package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/resolvedFromScan.d.ts +1 -1
  43. package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/resolvedFromScan.js +2 -2
  44. package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/startsWithUnderFlags.js +1 -1
  45. package/lib/modules/carets/appendMultilineCaret.d.ts +7 -0
  46. package/lib/modules/carets/appendMultilineCaret.js +181 -0
  47. package/lib/modules/carets/caretRecorder.d.ts +2 -0
  48. package/lib/modules/carets/caretRecorder.js +164 -0
  49. package/lib/modules/carets/caretSyntax.d.ts +3 -0
  50. package/lib/modules/carets/caretSyntax.js +11 -0
  51. package/lib/modules/carets/index.d.ts +9 -0
  52. package/lib/modules/carets/index.js +18 -0
  53. package/lib/modules/carets/lineTerminator.d.ts +1 -0
  54. package/lib/modules/carets/lineTerminator.js +31 -0
  55. package/lib/modules/carets/needsCaretRules.d.ts +1 -0
  56. package/lib/modules/carets/needsCaretRules.js +15 -0
  57. package/lib/modules/carets/quantifierBounds.d.ts +3 -0
  58. package/lib/modules/carets/quantifierBounds.js +18 -0
  59. package/lib/modules/index.d.ts +3 -0
  60. package/lib/modules/index.js +2 -0
  61. package/lib/partialMatchRegExp/atomSyntax.d.ts +14 -1
  62. package/lib/partialMatchRegExp/atomSyntax.js +24 -1
  63. package/lib/partialMatchRegExp/backreferenceExpansion.d.ts +1 -6
  64. package/lib/partialMatchRegExp/backreferenceHook.d.ts +11 -0
  65. package/lib/partialMatchRegExp/backreferenceHook.js +1 -0
  66. package/lib/partialMatchRegExp/caretHook.d.ts +17 -0
  67. package/lib/partialMatchRegExp/caretHook.js +5 -0
  68. package/lib/partialMatchRegExp/compilePartial/compileWith.d.ts +3 -0
  69. package/lib/partialMatchRegExp/compilePartial/compileWith.js +36 -0
  70. package/lib/partialMatchRegExp/compilePartial/compiled.d.ts +17 -17
  71. package/lib/partialMatchRegExp/compilePartial/compiled.js +8 -21
  72. package/lib/partialMatchRegExp/compilePartial/constants.d.ts +4 -0
  73. package/lib/partialMatchRegExp/compilePartial/constants.js +4 -0
  74. package/lib/partialMatchRegExp/compilePartial/groupShape.d.ts +4 -0
  75. package/lib/partialMatchRegExp/compilePartial/groupShape.js +9 -0
  76. package/lib/partialMatchRegExp/compilePartial/toStatic.d.ts +2 -2
  77. package/lib/partialMatchRegExp/compilePartial/toStatic.js +2 -2
  78. package/lib/partialMatchRegExp/constants.d.ts +5 -0
  79. package/lib/partialMatchRegExp/constants.js +5 -0
  80. package/lib/partialMatchRegExp/createPartialMatchRegExp.d.ts +3 -0
  81. package/lib/partialMatchRegExp/createPartialMatchRegExp.js +21 -0
  82. package/lib/partialMatchRegExp/execFrom.d.ts +1 -0
  83. package/lib/partialMatchRegExp/execFrom.js +4 -0
  84. package/lib/partialMatchRegExp/index.d.ts +49 -3
  85. package/lib/partialMatchRegExp/index.js +31 -3
  86. package/lib/partialMatchRegExp/moduleHooks.d.ts +14 -0
  87. package/lib/partialMatchRegExp/moduleHooks.js +15 -0
  88. package/lib/partialMatchRegExp/opaqueModule.d.ts +9 -0
  89. package/lib/partialMatchRegExp/opaqueModule.js +1 -0
  90. package/lib/partialMatchRegExp/part.d.ts +2 -11
  91. package/lib/partialMatchRegExp/partialMatchInternals.d.ts +2 -1
  92. package/lib/partialMatchRegExp/partialMatchInternals.js +3 -1
  93. package/lib/partialMatchRegExp/quantifier.d.ts +6 -0
  94. package/lib/partialMatchRegExp/quantifier.js +9 -0
  95. package/lib/partialMatchRegExp/rawLookaroundInfo.d.ts +11 -0
  96. package/lib/partialMatchRegExp/rawLookaroundInfo.js +1 -0
  97. package/lib/partialMatchRegExp/regexFeatures.d.ts +1 -5
  98. package/lib/partialMatchRegExp/regexFeatures.js +2 -8
  99. package/lib/partialMatchRegExp/scope.d.ts +12 -0
  100. package/lib/partialMatchRegExp/scope.js +45 -0
  101. package/lib/partialMatchRegExp/walk.d.ts +13 -5
  102. package/lib/partialMatchRegExp/walk.js +211 -165
  103. package/lib/partialMatchRegExp/withModules.d.ts +13 -0
  104. package/lib/partialMatchRegExp/withModules.js +27 -0
  105. package/package.json +39 -56
  106. package/lib/partialMatchRegExp/compilePartial/asNativeAtom.d.ts +0 -2
  107. package/lib/partialMatchRegExp/compilePartial/asOptionalAtom.d.ts +0 -1
  108. package/lib/partialMatchRegExp/compilePartial/asOptionalAtom.js +0 -4
  109. package/lib/partialMatchRegExp/compilePartial/asPreScanPart.d.ts +0 -2
  110. package/lib/partialMatchRegExp/compilePartial/index.d.ts +0 -2
  111. package/lib/partialMatchRegExp/compilePartial/index.js +0 -79
  112. package/lib/partialMatchRegExp/compilePartial/longestBakedPrefixEndingInput.js +0 -50
  113. package/lib/partialMatchRegExp/compilePartial/reclassifyLegacyEscapes.d.ts +0 -2
  114. package/lib/partialMatchRegExp/compilePartial/reclassifyLegacyEscapes.js +0 -17
  115. package/lib/partialMatchRegExp/compilePartial/spliceOriginalSource.d.ts +0 -2
  116. package/lib/partialMatchRegExp/compilePartial/spliceOriginalSource.js +0 -12
  117. package/lib/partialMatchRegExp/isComplete/index.d.ts +0 -38
  118. package/lib/partialMatchRegExp/isComplete/index.js +0 -41
  119. package/lib/partialMatchRegExp/isComplete/isMatchComplete.d.ts +0 -3
  120. package/lib/partialMatchRegExp/isComplete/isMatchComplete.js +0 -14
  121. package/lib/partialMatchRegExp/isComplete/partRole.js +0 -28
  122. package/lib/partialMatchRegExp/isComplete/truncationProbe.d.ts +0 -8
  123. package/lib/partialMatchRegExp/isComplete/truncationProbe.js +0 -105
  124. package/lib/partialMatchRegExp/isComplete/truncationProbeCache.d.ts +0 -4
  125. package/lib/partialMatchRegExp/partialMatchRegExp.d.ts +0 -55
  126. package/lib/partialMatchRegExp/partialMatchRegExp.js +0 -114
  127. package/lib/partialMatchRegExp/preferLongerCaptures.d.ts +0 -1
  128. package/lib/partialMatchRegExp/preferLongerCaptures.js +0 -30
  129. /package/lib/{partialMatchRegExp/isComplete → hitEnd}/truncationProbeCache.js +0 -0
  130. /package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/caseFoldFlags.d.ts +0 -0
  131. /package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/caseFoldFlags.js +0 -0
  132. /package/lib/{partialMatchRegExp → modules/backreferences}/escapeAtom.d.ts +0 -0
  133. /package/lib/{partialMatchRegExp → modules/backreferences}/escapeAtom.js +0 -0
  134. /package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/flagsAtBackreference.js +0 -0
  135. /package/lib/{partialMatchRegExp → modules/backreferences}/groupName.d.ts +0 -0
  136. /package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/longestBakedPrefixEndingInput.d.ts +0 -0
  137. /package/lib/{partialMatchRegExp/compilePartial → modules/backreferences}/startsWithUnderFlags.d.ts +0 -0
@@ -0,0 +1,12 @@
1
+ export declare const CASE_INSENSITIVE = 1;
2
+ export declare const MULTILINE = 2;
3
+ export declare const DOT_ALL = 4;
4
+ export declare const UNICODE = 8;
5
+ export declare const UNICODE_SETS = 16;
6
+ export declare const WITHIN_LOOKAROUND = 32;
7
+ export declare const WITHIN_GROUP = 64;
8
+ export declare const WITHIN_RAW_LOOKAROUND = 128;
9
+ export declare function scopeOf(regex: RegExp): number;
10
+ export type ModifiersHook = (scope: number, modifiers: string) => number;
11
+ export declare function scopeWithModifiers(scope: number, modifiers: string): number;
12
+ export declare function flagsOf(scope: number): string;
@@ -0,0 +1,45 @@
1
+ export const CASE_INSENSITIVE = 1;
2
+ export const MULTILINE = 2;
3
+ export const DOT_ALL = 4;
4
+ export const UNICODE = 8;
5
+ export const UNICODE_SETS = 16;
6
+ export const WITHIN_LOOKAROUND = 32;
7
+ export const WITHIN_GROUP = 64;
8
+ export const WITHIN_RAW_LOOKAROUND = 128;
9
+ const MODIFIER_REMOVAL = "-";
10
+ function modifierBit(modifier) {
11
+ switch (modifier) {
12
+ case "i":
13
+ return CASE_INSENSITIVE;
14
+ case "m":
15
+ return MULTILINE;
16
+ default:
17
+ return DOT_ALL;
18
+ }
19
+ }
20
+ export function scopeOf(regex) {
21
+ return ((regex.ignoreCase ? CASE_INSENSITIVE : 0) |
22
+ (regex.multiline ? MULTILINE : 0) |
23
+ (regex.dotAll ? DOT_ALL : 0) |
24
+ (regex.unicode ? UNICODE : 0) |
25
+ (regex.unicodeSets ? UNICODE | UNICODE_SETS : 0));
26
+ }
27
+ export function scopeWithModifiers(scope, modifiers) {
28
+ let removing = false;
29
+ for (let index = 0; index < modifiers.length; index++) {
30
+ const modifier = modifiers[index];
31
+ if (modifier === MODIFIER_REMOVAL)
32
+ removing = true;
33
+ else if (removing)
34
+ scope &= ~modifierBit(modifier);
35
+ else
36
+ scope |= modifierBit(modifier);
37
+ }
38
+ return scope;
39
+ }
40
+ export function flagsOf(scope) {
41
+ return ((scope & CASE_INSENSITIVE ? "i" : "") +
42
+ (scope & MULTILINE ? "m" : "") +
43
+ (scope & DOT_ALL ? "s" : "") +
44
+ (scope & UNICODE_SETS ? "v" : scope & UNICODE ? "u" : ""));
45
+ }
@@ -1,8 +1,16 @@
1
- import type { Part, RawLookaroundInfo } from "./part.ts";
2
- export declare function walk(regex: RegExp, declaresNamedGroup: boolean): {
1
+ import type { Part } from "./part.ts";
2
+ import { type CaretHook, type CaretRecorder } from "./caretHook.ts";
3
+ import type { BackreferenceRecorder, BackreferenceHook } from "./backreferenceHook.ts";
4
+ import type { RawLookaroundInfo } from "./rawLookaroundInfo.ts";
5
+ import { type ModifiersHook } from "./scope.ts";
6
+ export interface Hooks {
7
+ caret?: CaretHook;
8
+ backreference?: BackreferenceHook;
9
+ modifiers?: ModifiersHook;
10
+ }
11
+ export declare function walk(regex: RegExp, declaresNamedGroup: boolean, groupLimit: number, caretRecorder: CaretRecorder | undefined, backreferenceRecorder: BackreferenceRecorder | undefined, withModifiers: Hooks["modifiers"]): {
3
12
  parts: Part[];
4
- groupCount: number;
5
13
  featureMask: number;
6
- rawLookarounds: readonly RawLookaroundInfo[];
7
- namedGroupOpenings: readonly string[];
14
+ needs: number;
15
+ rawLookarounds: RawLookaroundInfo[] | undefined;
8
16
  };
@@ -1,69 +1,95 @@
1
- import { DISJUNCTION_TO_END_OF_INPUT, OPTIONAL_ATOM_OPENING } from "./atomSyntax.js";
2
- import { groupNameOf, decodeGroupName } from "./groupName.js";
3
- import { FEATURE_BIT } from "./regexFeatures.js";
4
- const OCCURRENCES_REGEX = /\{\d+,?\d*\}/y;
5
- const NOT_NUMBERS_REGEX = /\D/g;
6
- const LITERAL_K_ATOM = OPTIONAL_ATOM_OPENING + "k" + DISJUNCTION_TO_END_OF_INPUT;
7
- const NO_RAW_LOOKAROUNDS = [];
8
- const NO_NAMED_GROUP_OPENINGS = [];
9
- const declaresGroupNamed = (closedGroupNames, name) => { var _a; return (_a = closedGroupNames === null || closedGroupNames === void 0 ? void 0 : closedGroupNames.has(decodeGroupName(name))) !== null && _a !== void 0 ? _a : false; };
10
- export function walk(regex, declaresNamedGroup) {
1
+ import { NOT_NUMBERS_REGEX, LITERAL_BACKSLASH, LITERAL_K } from "./constants.js";
2
+ import { asOptionalAtom, isWordBoundaryAtom, DISJUNCTION_TO_END_OF_INPUT, END_ANCHOR, isRawLookaround, GROUP_CLOSING, LOOKAHEAD_OPENING, START_ANCHOR } from "./atomSyntax.js";
3
+ import { legacyEscapeAtoms } from "./legacyEscape.js";
4
+ import { ON_ALTERNATIVE, ON_CARET, ON_END, ON_GROUP, ON_LOOKAHEAD } from "./caretHook.js";
5
+ import { BACKREFERENCES_MODULE, CARETS_MODULE } from "./moduleHooks.js";
6
+ import { OCCURRENCES_REGEX } from "./quantifier.js";
7
+ import { MULTILINE, UNICODE, UNICODE_SETS, WITHIN_GROUP, WITHIN_LOOKAROUND, WITHIN_RAW_LOOKAROUND, scopeOf } from "./scope.js";
8
+ const ASCII_LETTER = /[a-z]/iy;
9
+ const TWO_HEX_DIGITS = /[0-9a-f]{2}/iy;
10
+ const FOUR_HEX_DIGITS = /[0-9a-f]{4}/iy;
11
+ function matchesAt(source, start, pattern) {
12
+ pattern.lastIndex = start;
13
+ return pattern.test(source);
14
+ }
15
+ const isZeroWidth = (part) => typeof part === "string" &&
16
+ (part === START_ANCHOR ||
17
+ part === END_ANCHOR ||
18
+ isWordBoundaryAtom(part) ||
19
+ isRawLookaround(part));
20
+ export function walk(regex, declaresNamedGroup, groupLimit, caretRecorder, backreferenceRecorder, withModifiers) {
11
21
  const source = regex.source;
12
- const isUnicode = regex.unicode || regex.unicodeSets;
13
22
  let i = 0;
14
23
  let groupCount = 0;
15
24
  let featureMask = 0;
25
+ let needs = 0;
26
+ let rawLookaroundCount = 0;
27
+ let outermostRawLookaroundCount = 0;
16
28
  let rawLookarounds;
17
- let namedGroupOpenings;
18
- let closedGroupNumbers;
19
- let closedGroupNames;
20
- let namedBackreferencesSeen;
21
- let currentRawLookaroundBackreferences;
29
+ let rawReferences;
30
+ let lastBodyRunsOut = false;
22
31
  function extractSlice(length) {
23
32
  return source.slice(i, (i += length));
24
33
  }
25
- function process(withinLookaround, declaresNamedGroup, caseInsensitive) {
34
+ function process(scope) {
35
+ var _a;
26
36
  const result = [];
37
+ const caretFrame = caretRecorder === null || caretRecorder === void 0 ? void 0 : caretRecorder(result, scope);
38
+ let alternativeStart = 0;
39
+ let alternativeRunsOut = false;
40
+ let everyAlternativeRunsOut = true;
27
41
  function appendOptional(length) {
28
- result.push("(?:" + extractSlice(length) + DISJUNCTION_TO_END_OF_INPUT);
42
+ if (result.length === alternativeStart)
43
+ alternativeRunsOut = true;
44
+ result.push(asOptionalAtom(extractSlice(length)));
29
45
  }
30
46
  function appendRaw(length) {
31
47
  result.push(extractSlice(length));
32
48
  }
49
+ function appendBackreference(backreference) {
50
+ if (backreferenceRecorder)
51
+ backreferenceRecorder.backreference(backreference, scope);
52
+ else if (!(scope & WITHIN_RAW_LOOKAROUND))
53
+ needs |= BACKREFERENCES_MODULE;
54
+ result.push(backreference);
55
+ }
33
56
  function appendDigitRun(forcedRef) {
34
- featureMask |= FEATURE_BIT.backreference;
57
+ if (result.length === alternativeStart)
58
+ alternativeRunsOut = true;
59
+ featureMask |= 512 /* Feature.backreference */;
35
60
  NOT_NUMBERS_REGEX.lastIndex = i + 1;
36
61
  const nextNonDigit = NOT_NUMBERS_REGEX.exec(source);
37
62
  const start = i;
38
63
  const end = nextNonDigit ? nextNonDigit.index : source.length;
39
64
  const ref = forcedRef !== null && forcedRef !== void 0 ? forcedRef : Number(source.slice(start + 1, end));
40
65
  i = end;
41
- const backreference = {
42
- ref,
43
- start,
44
- end,
45
- forward: !(closedGroupNumbers === null || closedGroupNumbers === void 0 ? void 0 : closedGroupNumbers.has(ref)),
46
- caseInsensitive
47
- };
48
- result.push(backreference);
49
- currentRawLookaroundBackreferences === null || currentRawLookaroundBackreferences === void 0 ? void 0 : currentRawLookaroundBackreferences.push(backreference);
66
+ if (scope & WITHIN_RAW_LOOKAROUND)
67
+ (rawReferences !== null && rawReferences !== void 0 ? rawReferences : (rawReferences = [])).push({ ref, start, end });
68
+ if (ref >= 1 && ref <= groupLimit) {
69
+ appendBackreference({ ref });
70
+ return;
71
+ }
72
+ for (const atom of legacyEscapeAtoms(source.slice(start + 1, end))) {
73
+ result.push(asOptionalAtom(atom));
74
+ }
50
75
  }
51
76
  function appendRawLookaround(prefixLength) {
52
77
  const start = i;
53
78
  i += prefixLength;
54
79
  const groupCountBefore = groupCount;
55
- const isOutermost = currentRawLookaroundBackreferences === undefined;
56
- const backreferences = currentRawLookaroundBackreferences !== null && currentRawLookaroundBackreferences !== void 0 ? currentRawLookaroundBackreferences : [];
57
- if (isOutermost)
58
- currentRawLookaroundBackreferences = backreferences;
59
- process(true, declaresNamedGroup, caseInsensitive);
60
- if (isOutermost) {
61
- (rawLookarounds !== null && rawLookarounds !== void 0 ? rawLookarounds : (rawLookarounds = [])).push({
62
- sourceStart: start,
63
- capturingGroupsOpened: groupCount - groupCountBefore,
64
- backreferences
65
- });
66
- currentRawLookaroundBackreferences = undefined;
80
+ rawLookaroundCount++;
81
+ process(scope | WITHIN_LOOKAROUND | WITHIN_RAW_LOOKAROUND);
82
+ if (!(scope & WITHIN_RAW_LOOKAROUND)) {
83
+ const capturingGroupsOpened = groupCount - groupCountBefore;
84
+ if (rawReferences || capturingGroupsOpened) {
85
+ (rawLookarounds !== null && rawLookarounds !== void 0 ? rawLookarounds : (rawLookarounds = []))[outermostRawLookaroundCount] = {
86
+ sourceStart: start,
87
+ capturingGroupsOpened,
88
+ references: rawReferences !== null && rawReferences !== void 0 ? rawReferences : []
89
+ };
90
+ rawReferences = undefined;
91
+ }
92
+ outermostRawLookaroundCount++;
67
93
  }
68
94
  result.push(source.slice(start, i));
69
95
  }
@@ -72,56 +98,51 @@ export function walk(regex, declaresNamedGroup) {
72
98
  case "\\":
73
99
  switch (source[i + 1]) {
74
100
  case "c":
75
- featureMask |= FEATURE_BIT.controlLetterEscape;
76
- appendOptional(3);
101
+ if (scope & UNICODE || matchesAt(source, i + 2, ASCII_LETTER)) {
102
+ featureMask |= 67108864 /* Feature.controlLetterEscape */;
103
+ appendOptional(3);
104
+ }
105
+ else {
106
+ featureMask |= 536870912 /* Feature.otherEscape */;
107
+ i++;
108
+ if (result.length === alternativeStart)
109
+ alternativeRunsOut = true;
110
+ result.push(asOptionalAtom(LITERAL_BACKSLASH));
111
+ }
77
112
  break;
78
113
  case "k": {
79
114
  const referenceEnd = source[i + 2] === "<" ? source.indexOf(">", i) : -1;
80
115
  if (referenceEnd !== -1 && declaresNamedGroup) {
81
- featureMask |= FEATURE_BIT.namedBackreference;
82
- const start = i;
116
+ featureMask |= 1024 /* Feature.namedBackreference */;
83
117
  const ref = source.slice(i + 3, referenceEnd);
84
118
  i = referenceEnd + 1;
85
- const namedBackreference = {
86
- ref,
87
- start,
88
- end: i,
89
- forward: !declaresGroupNamed(closedGroupNames, ref),
90
- caseInsensitive
91
- };
92
- result.push(namedBackreference);
93
- currentRawLookaroundBackreferences === null || currentRawLookaroundBackreferences === void 0 ? void 0 : currentRawLookaroundBackreferences.push(namedBackreference);
94
- (namedBackreferencesSeen !== null && namedBackreferencesSeen !== void 0 ? namedBackreferencesSeen : (namedBackreferencesSeen = [])).push(namedBackreference);
95
- }
96
- else if (currentRawLookaroundBackreferences) {
97
- const start = i;
98
- i += 2;
99
- currentRawLookaroundBackreferences.push({
100
- ref: "",
101
- start,
102
- end: i,
103
- caseInsensitive
104
- });
119
+ if (result.length === alternativeStart)
120
+ alternativeRunsOut = true;
121
+ appendBackreference({ ref });
105
122
  }
106
123
  else {
107
- result.push(LITERAL_K_ATOM);
108
124
  i += 2;
125
+ if (result.length === alternativeStart)
126
+ alternativeRunsOut = true;
127
+ result.push(asOptionalAtom(LITERAL_K));
109
128
  }
110
129
  break;
111
130
  }
112
131
  case "u":
113
- featureMask |= FEATURE_BIT.unicodeEscapeSequence;
114
- if (isUnicode && source[i + 2] === "{") {
115
- appendOptional(source.indexOf("}", i) - i + 1);
132
+ if (scope & UNICODE ||
133
+ matchesAt(source, i + 2, FOUR_HEX_DIGITS)) {
134
+ featureMask |= 268435456 /* Feature.unicodeEscapeSequence */;
135
+ appendOptional(source[i + 2] === "{" ? source.indexOf("}", i) - i + 1 : 6);
116
136
  }
117
137
  else {
118
- appendOptional(6);
138
+ featureMask |= 536870912 /* Feature.otherEscape */;
139
+ appendOptional(2);
119
140
  }
120
141
  break;
121
142
  case "p":
122
143
  case "P":
123
- if (isUnicode) {
124
- featureMask |= FEATURE_BIT.unicodePropertyEscape;
144
+ if (scope & UNICODE) {
145
+ featureMask |= 8388608 /* Feature.unicodePropertyEscape */;
125
146
  appendOptional(source.indexOf("}", i) - i + 1);
126
147
  }
127
148
  else {
@@ -129,15 +150,21 @@ export function walk(regex, declaresNamedGroup) {
129
150
  }
130
151
  break;
131
152
  case "x":
132
- featureMask |= FEATURE_BIT.hexEscapeSequence;
133
- appendOptional(4);
153
+ if (scope & UNICODE || matchesAt(source, i + 2, TWO_HEX_DIGITS)) {
154
+ featureMask |= 134217728 /* Feature.hexEscapeSequence */;
155
+ appendOptional(4);
156
+ }
157
+ else {
158
+ featureMask |= 536870912 /* Feature.otherEscape */;
159
+ appendOptional(2);
160
+ }
134
161
  break;
135
162
  case "b":
136
- featureMask |= FEATURE_BIT.wordBoundary;
163
+ featureMask |= 8 /* Feature.wordBoundary */;
137
164
  appendOptional(2);
138
165
  break;
139
166
  case "B":
140
- featureMask |= FEATURE_BIT.nonWordBoundary;
167
+ featureMask |= 16 /* Feature.nonWordBoundary */;
141
168
  appendOptional(2);
142
169
  break;
143
170
  case "f":
@@ -145,12 +172,12 @@ export function walk(regex, declaresNamedGroup) {
145
172
  case "r":
146
173
  case "t":
147
174
  case "v":
148
- featureMask |= FEATURE_BIT.controlEscape;
175
+ featureMask |= 33554432 /* Feature.controlEscape */;
149
176
  appendOptional(2);
150
177
  break;
151
178
  case "0":
152
- if (isUnicode) {
153
- featureMask |= FEATURE_BIT.otherEscape;
179
+ if (scope & UNICODE) {
180
+ featureMask |= 536870912 /* Feature.otherEscape */;
154
181
  appendOptional(2);
155
182
  }
156
183
  else {
@@ -174,17 +201,17 @@ export function walk(regex, declaresNamedGroup) {
174
201
  case "W":
175
202
  case "s":
176
203
  case "S":
177
- featureMask |= FEATURE_BIT.characterClassEscape;
204
+ featureMask |= 16777216 /* Feature.characterClassEscape */;
178
205
  appendOptional(2);
179
206
  break;
180
207
  default:
181
- featureMask |= FEATURE_BIT.otherEscape;
208
+ featureMask |= 536870912 /* Feature.otherEscape */;
182
209
  appendOptional(2);
183
210
  break;
184
211
  }
185
212
  break;
186
213
  case "[": {
187
- featureMask |= FEATURE_BIT.characterClass;
214
+ featureMask |= 131072 /* Feature.characterClass */;
188
215
  let depth = 1, j = i + 1, previousSetOperatorCharacter;
189
216
  while (depth) {
190
217
  const character = source[j];
@@ -194,8 +221,8 @@ export function walk(regex, declaresNamedGroup) {
194
221
  previousSetOperatorCharacter = undefined;
195
222
  continue;
196
223
  case "[":
197
- if (regex.unicodeSets) {
198
- featureMask |= FEATURE_BIT.nestedCharacterClass;
224
+ if (scope & UNICODE_SETS) {
225
+ featureMask |= 262144 /* Feature.nestedCharacterClass */;
199
226
  depth++;
200
227
  }
201
228
  break;
@@ -203,13 +230,15 @@ export function walk(regex, declaresNamedGroup) {
203
230
  depth--;
204
231
  break;
205
232
  case "&":
206
- if (regex.unicodeSets && previousSetOperatorCharacter === "&") {
207
- featureMask |= FEATURE_BIT.classIntersection;
233
+ if (scope & UNICODE_SETS &&
234
+ previousSetOperatorCharacter === "&") {
235
+ featureMask |= 524288 /* Feature.classIntersection */;
208
236
  }
209
237
  break;
210
238
  case "-":
211
- if (regex.unicodeSets && previousSetOperatorCharacter === "-") {
212
- featureMask |= FEATURE_BIT.classSubtraction;
239
+ if (scope & UNICODE_SETS &&
240
+ previousSetOperatorCharacter === "-") {
241
+ featureMask |= 1048576 /* Feature.classSubtraction */;
213
242
  }
214
243
  break;
215
244
  }
@@ -219,29 +248,47 @@ export function walk(regex, declaresNamedGroup) {
219
248
  appendOptional(j - i);
220
249
  break;
221
250
  }
222
- case "^":
223
- featureMask |= FEATURE_BIT.startAnchor;
224
- appendRaw(1);
251
+ case "^": {
252
+ featureMask |= 2 /* Feature.startAnchor */;
253
+ i++;
254
+ const leadsAlternative = result.length === alternativeStart;
255
+ if (caretFrame)
256
+ caretFrame(ON_CARET);
257
+ else {
258
+ if (!(scope & WITHIN_RAW_LOOKAROUND) &&
259
+ (scope & (WITHIN_GROUP | WITHIN_LOOKAROUND) ||
260
+ (scope & MULTILINE &&
261
+ !result.slice(alternativeStart).every(isZeroWidth))))
262
+ needs |= CARETS_MODULE;
263
+ result.push(START_ANCHOR);
264
+ }
265
+ if (leadsAlternative)
266
+ alternativeStart = result.length;
225
267
  break;
268
+ }
226
269
  case "$":
227
- featureMask |= FEATURE_BIT.endAnchor;
270
+ featureMask |= 4 /* Feature.endAnchor */;
228
271
  appendRaw(1);
229
272
  break;
230
273
  case "|":
231
- featureMask |= FEATURE_BIT.disjunction;
274
+ featureMask |= 2097152 /* Feature.disjunction */;
275
+ caretFrame === null || caretFrame === void 0 ? void 0 : caretFrame(ON_ALTERNATIVE);
276
+ everyAlternativeRunsOut && (everyAlternativeRunsOut = alternativeRunsOut || result.length === alternativeStart);
277
+ alternativeRunsOut = false;
278
+ alternativeStart = result.length + 1;
232
279
  appendRaw(1);
233
280
  break;
234
281
  case "*":
235
282
  case "+":
236
283
  case "?":
237
- featureMask |= FEATURE_BIT.quantifier;
284
+ featureMask |= 4194304 /* Feature.quantifier */;
238
285
  appendRaw(1);
239
286
  break;
240
287
  case "{": {
241
288
  OCCURRENCES_REGEX.lastIndex = i;
242
289
  const regExpExecArray = OCCURRENCES_REGEX.exec(source);
243
290
  if (regExpExecArray) {
244
- featureMask |= FEATURE_BIT.quantifier;
291
+ featureMask |= 4194304 /* Feature.quantifier */;
245
292
  appendRaw(regExpExecArray[0].length);
246
293
  }
247
294
  else {
@@ -249,118 +296,117 @@ export function walk(regex, declaresNamedGroup) {
249
296
  }
250
297
  break;
251
298
  }
252
- case "(":
299
+ case "(": {
300
+ let opening;
301
+ let groupScope = scope;
302
+ let closing = DISJUNCTION_TO_END_OF_INPUT;
303
+ let groupNumber = 0;
253
304
  if (source[i + 1] == "?") {
254
305
  switch (source[i + 2]) {
255
306
  case ":":
256
- featureMask |= FEATURE_BIT.nonCapturingGroup;
257
- result.push("(?:");
258
- i += 3;
259
- result.push(...process(withinLookaround, declaresNamedGroup, caseInsensitive), DISJUNCTION_TO_END_OF_INPUT);
307
+ featureMask |= 16384 /* Feature.nonCapturingGroup */;
308
+ opening = extractSlice(3);
260
309
  break;
261
- case "=":
262
- featureMask |= FEATURE_BIT.lookahead;
263
- result.push("(?=");
310
+ case "=": {
311
+ featureMask |= 32 /* Feature.lookahead */;
264
312
  i += 3;
265
- result.push(...process(true, declaresNamedGroup, caseInsensitive), ")");
313
+ const body = process(scope | WITHIN_LOOKAROUND);
314
+ caretFrame === null || caretFrame === void 0 ? void 0 : caretFrame(ON_LOOKAHEAD, body, scope, source, i);
315
+ result.push(LOOKAHEAD_OPENING, ...body, GROUP_CLOSING);
266
316
  break;
317
+ }
267
318
  case "-":
268
319
  case "i":
269
320
  case "s":
270
321
  case "m": {
271
322
  const flagsStart = i + 2, colonIndex = source.indexOf(":", flagsStart);
272
323
  const modifiers = source.slice(flagsStart, colonIndex);
273
- const [additions, removals] = modifiers.split("-");
274
- featureMask |= removals
275
- ? FEATURE_BIT.modifierGroupWithRemoval
276
- : FEATURE_BIT.modifierGroup;
277
- const modifierGroupCaseInsensitive = (removals === null || removals === void 0 ? void 0 : removals.includes("i"))
278
- ? false
279
- : caseInsensitive || additions.includes("i");
280
- result.push("(?" + modifiers + ":");
281
- i = colonIndex + 1;
282
- result.push(...process(withinLookaround, declaresNamedGroup, modifierGroupCaseInsensitive), ")");
324
+ const removalIndex = modifiers.indexOf("-");
325
+ featureMask |=
326
+ removalIndex === -1 || removalIndex === modifiers.length - 1
327
+ ? 32768 /* Feature.modifierGroup */
328
+ : 65536 /* Feature.modifierGroupWithRemoval */;
329
+ groupScope = (_a = withModifiers === null || withModifiers === void 0 ? void 0 : withModifiers(scope, modifiers)) !== null && _a !== void 0 ? _a : scope;
330
+ closing = GROUP_CLOSING;
331
+ opening = extractSlice(colonIndex + 1 - i);
283
332
  break;
284
333
  }
285
334
  case "!":
286
- featureMask |= FEATURE_BIT.negativeLookahead;
335
+ featureMask |= 64 /* Feature.negativeLookahead */;
287
336
  appendRawLookaround(3);
288
337
  break;
289
338
  case "<":
290
339
  switch (source[i + 3]) {
291
340
  case "=":
292
- featureMask |= FEATURE_BIT.lookbehind;
341
+ featureMask |= 128 /* Feature.lookbehind */;
293
342
  appendRawLookaround(4);
294
343
  break;
295
344
  case "!":
296
- featureMask |= FEATURE_BIT.negativeLookbehind;
345
+ featureMask |= 256 /* Feature.negativeLookbehind */;
297
346
  appendRawLookaround(4);
298
347
  break;
299
- default: {
300
- featureMask |= FEATURE_BIT.namedGroup;
301
- featureMask |= FEATURE_BIT.capturingGroup;
302
- if (withinLookaround)
303
- featureMask |= FEATURE_BIT.lookaroundCapture;
304
- const groupNumber = ++groupCount;
305
- const opening = extractSlice(source.indexOf(">", i) - i + 1);
306
- (namedGroupOpenings !== null && namedGroupOpenings !== void 0 ? namedGroupOpenings : (namedGroupOpenings = [])).push(opening);
307
- const declaredName = decodeGroupName(groupNameOf(opening));
308
- result.push(opening);
309
- result.push(...process(withinLookaround, declaresNamedGroup, caseInsensitive), DISJUNCTION_TO_END_OF_INPUT);
310
- (closedGroupNumbers !== null && closedGroupNumbers !== void 0 ? closedGroupNumbers : (closedGroupNumbers = new Set())).add(groupNumber);
311
- (closedGroupNames !== null && closedGroupNames !== void 0 ? closedGroupNames : (closedGroupNames = new Set())).add(declaredName);
348
+ default:
349
+ featureMask |= 2048 /* Feature.namedGroup */;
350
+ featureMask |= 4096 /* Feature.capturingGroup */;
351
+ if (scope & WITHIN_LOOKAROUND)
352
+ featureMask |= 8192 /* Feature.lookaroundCapture */;
353
+ groupNumber = ++groupCount;
354
+ opening = extractSlice(source.indexOf(">", i) - i + 1);
312
355
  break;
313
- }
314
356
  }
315
357
  break;
316
358
  }
317
359
  }
318
360
  else {
319
- featureMask |= FEATURE_BIT.capturingGroup;
320
- if (withinLookaround)
321
- featureMask |= FEATURE_BIT.lookaroundCapture;
322
- const groupNumber = ++groupCount;
323
- appendRaw(1);
324
- result.push(...process(withinLookaround, declaresNamedGroup, caseInsensitive), DISJUNCTION_TO_END_OF_INPUT);
325
- (closedGroupNumbers !== null && closedGroupNumbers !== void 0 ? closedGroupNumbers : (closedGroupNumbers = new Set())).add(groupNumber);
361
+ featureMask |= 4096 /* Feature.capturingGroup */;
362
+ if (scope & WITHIN_LOOKAROUND)
363
+ featureMask |= 8192 /* Feature.lookaroundCapture */;
364
+ groupNumber = ++groupCount;
365
+ opening = extractSlice(1);
326
366
  }
367
+ if (opening === undefined)
368
+ break;
369
+ const opensAlternative = result.length === alternativeStart;
370
+ const rawLookaroundsBefore = rawLookaroundCount;
371
+ const body = process(groupScope | WITHIN_GROUP);
372
+ const runsOut = lastBodyRunsOut;
373
+ const containsRawLookaround = rawLookaroundCount !== rawLookaroundsBefore;
374
+ const caretGroup = caretFrame === null || caretFrame === void 0 ? void 0 : caretFrame(ON_GROUP, body, groupScope, source, i, closing, containsRawLookaround);
375
+ if (caretGroup)
376
+ closing = caretGroup.closing;
377
+ if (!containsRawLookaround && runsOut && !(caretGroup === null || caretGroup === void 0 ? void 0 : caretGroup.forced)) {
378
+ closing = GROUP_CLOSING;
379
+ if (opensAlternative && !(caretGroup === null || caretGroup === void 0 ? void 0 : caretGroup.stays))
380
+ alternativeRunsOut = true;
381
+ }
382
+ else if (containsRawLookaround)
383
+ closing = DISJUNCTION_TO_END_OF_INPUT;
384
+ result.push(opening, ...body, closing);
385
+ if (groupNumber)
386
+ backreferenceRecorder === null || backreferenceRecorder === void 0 ? void 0 : backreferenceRecorder.groupClosed(groupNumber, opening);
327
387
  break;
388
+ }
328
389
  case ")":
329
390
  ++i;
391
+ caretFrame === null || caretFrame === void 0 ? void 0 : caretFrame(ON_END);
392
+ lastBodyRunsOut =
393
+ everyAlternativeRunsOut &&
394
+ (alternativeRunsOut || result.length === alternativeStart);
330
395
  return result;
331
396
  default:
332
- featureMask |= FEATURE_BIT.patternCharacter;
397
+ featureMask |= 1 /* Feature.patternCharacter */;
398
+ appendOptional(
333
399
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- i < source.length is the loop invariant, so codePointAt(i) is always defined
334
- appendOptional(isUnicode && source.codePointAt(i) > 0xffff ? 2 : 1);
400
+ scope & UNICODE && source.codePointAt(i) > 0xffff ? 2 : 1);
335
401
  break;
336
402
  }
337
403
  }
404
+ caretFrame === null || caretFrame === void 0 ? void 0 : caretFrame(ON_END);
405
+ lastBodyRunsOut =
406
+ everyAlternativeRunsOut &&
407
+ (alternativeRunsOut || result.length === alternativeStart);
338
408
  return result;
339
409
  }
340
- const parts = process(false, declaresNamedGroup, regex.flags.includes("i"));
341
- if (namedGroupOpenings && namedBackreferencesSeen) {
342
- const seenOnce = new Set();
343
- let duplicated;
344
- for (const opening of namedGroupOpenings) {
345
- const name = decodeGroupName(groupNameOf(opening));
346
- if (seenOnce.has(name))
347
- (duplicated !== null && duplicated !== void 0 ? duplicated : (duplicated = new Set())).add(name);
348
- else
349
- seenOnce.add(name);
350
- }
351
- if (duplicated) {
352
- for (const backreference of namedBackreferencesSeen) {
353
- if (duplicated.has(decodeGroupName(backreference.ref))) {
354
- backreference.forward = true;
355
- }
356
- }
357
- }
358
- }
359
- return {
360
- parts,
361
- groupCount,
362
- featureMask,
363
- rawLookarounds: rawLookarounds !== null && rawLookarounds !== void 0 ? rawLookarounds : NO_RAW_LOOKAROUNDS,
364
- namedGroupOpenings: namedGroupOpenings !== null && namedGroupOpenings !== void 0 ? namedGroupOpenings : NO_NAMED_GROUP_OPENINGS
365
- };
410
+ const parts = process(scopeOf(regex));
411
+ return { parts, featureMask, needs, rawLookarounds };
366
412
  }