@pattern-algebra/core 0.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 (154) hide show
  1. package/README.md +571 -0
  2. package/dist/automaton/complement.d.ts +20 -0
  3. package/dist/automaton/complement.d.ts.map +1 -0
  4. package/dist/automaton/complement.js +36 -0
  5. package/dist/automaton/complement.js.map +1 -0
  6. package/dist/automaton/complement.test.d.ts +2 -0
  7. package/dist/automaton/complement.test.d.ts.map +1 -0
  8. package/dist/automaton/complement.test.js +114 -0
  9. package/dist/automaton/complement.test.js.map +1 -0
  10. package/dist/automaton/determinize.d.ts +41 -0
  11. package/dist/automaton/determinize.d.ts.map +1 -0
  12. package/dist/automaton/determinize.js +310 -0
  13. package/dist/automaton/determinize.js.map +1 -0
  14. package/dist/automaton/determinize.test.d.ts +2 -0
  15. package/dist/automaton/determinize.test.d.ts.map +1 -0
  16. package/dist/automaton/determinize.test.js +134 -0
  17. package/dist/automaton/determinize.test.js.map +1 -0
  18. package/dist/automaton/emptiness.d.ts +41 -0
  19. package/dist/automaton/emptiness.d.ts.map +1 -0
  20. package/dist/automaton/emptiness.js +262 -0
  21. package/dist/automaton/emptiness.js.map +1 -0
  22. package/dist/automaton/emptiness.test.d.ts +2 -0
  23. package/dist/automaton/emptiness.test.d.ts.map +1 -0
  24. package/dist/automaton/emptiness.test.js +154 -0
  25. package/dist/automaton/emptiness.test.js.map +1 -0
  26. package/dist/automaton/index.d.ts +10 -0
  27. package/dist/automaton/index.d.ts.map +1 -0
  28. package/dist/automaton/index.js +11 -0
  29. package/dist/automaton/index.js.map +1 -0
  30. package/dist/automaton/intersect.d.ts +35 -0
  31. package/dist/automaton/intersect.d.ts.map +1 -0
  32. package/dist/automaton/intersect.js +302 -0
  33. package/dist/automaton/intersect.js.map +1 -0
  34. package/dist/automaton/pattern-algebra.d.ts +62 -0
  35. package/dist/automaton/pattern-algebra.d.ts.map +1 -0
  36. package/dist/automaton/pattern-algebra.js +309 -0
  37. package/dist/automaton/pattern-algebra.js.map +1 -0
  38. package/dist/automaton/pattern-algebra.test.d.ts +2 -0
  39. package/dist/automaton/pattern-algebra.test.d.ts.map +1 -0
  40. package/dist/automaton/pattern-algebra.test.js +223 -0
  41. package/dist/automaton/pattern-algebra.test.js.map +1 -0
  42. package/dist/compile/automaton-builder.d.ts +47 -0
  43. package/dist/compile/automaton-builder.d.ts.map +1 -0
  44. package/dist/compile/automaton-builder.js +211 -0
  45. package/dist/compile/automaton-builder.js.map +1 -0
  46. package/dist/compile/compiler.d.ts +32 -0
  47. package/dist/compile/compiler.d.ts.map +1 -0
  48. package/dist/compile/compiler.js +47 -0
  49. package/dist/compile/compiler.js.map +1 -0
  50. package/dist/compile/index.d.ts +8 -0
  51. package/dist/compile/index.d.ts.map +1 -0
  52. package/dist/compile/index.js +8 -0
  53. package/dist/compile/index.js.map +1 -0
  54. package/dist/compile/quick-reject.d.ts +28 -0
  55. package/dist/compile/quick-reject.d.ts.map +1 -0
  56. package/dist/compile/quick-reject.js +147 -0
  57. package/dist/compile/quick-reject.js.map +1 -0
  58. package/dist/containment/analysis.d.ts +60 -0
  59. package/dist/containment/analysis.d.ts.map +1 -0
  60. package/dist/containment/analysis.js +378 -0
  61. package/dist/containment/analysis.js.map +1 -0
  62. package/dist/containment/containment.d.ts +23 -0
  63. package/dist/containment/containment.d.ts.map +1 -0
  64. package/dist/containment/containment.js +681 -0
  65. package/dist/containment/containment.js.map +1 -0
  66. package/dist/containment/containment.test.d.ts +2 -0
  67. package/dist/containment/containment.test.d.ts.map +1 -0
  68. package/dist/containment/containment.test.js +209 -0
  69. package/dist/containment/containment.test.js.map +1 -0
  70. package/dist/containment/index.d.ts +7 -0
  71. package/dist/containment/index.d.ts.map +1 -0
  72. package/dist/containment/index.js +7 -0
  73. package/dist/containment/index.js.map +1 -0
  74. package/dist/core-alpha.d.ts +1253 -0
  75. package/dist/core-beta.d.ts +1253 -0
  76. package/dist/core-public.d.ts +1253 -0
  77. package/dist/core-unstripped.d.ts +1253 -0
  78. package/dist/index.d.ts +32 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +49 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/match/index.d.ts +8 -0
  83. package/dist/match/index.d.ts.map +1 -0
  84. package/dist/match/index.js +8 -0
  85. package/dist/match/index.js.map +1 -0
  86. package/dist/match/matcher.d.ts +40 -0
  87. package/dist/match/matcher.d.ts.map +1 -0
  88. package/dist/match/matcher.js +256 -0
  89. package/dist/match/matcher.js.map +1 -0
  90. package/dist/match/matcher.test.d.ts +2 -0
  91. package/dist/match/matcher.test.d.ts.map +1 -0
  92. package/dist/match/matcher.test.js +185 -0
  93. package/dist/match/matcher.test.js.map +1 -0
  94. package/dist/match/path-utils.d.ts +132 -0
  95. package/dist/match/path-utils.d.ts.map +1 -0
  96. package/dist/match/path-utils.js +223 -0
  97. package/dist/match/path-utils.js.map +1 -0
  98. package/dist/match/path-utils.test.d.ts +2 -0
  99. package/dist/match/path-utils.test.d.ts.map +1 -0
  100. package/dist/match/path-utils.test.js +193 -0
  101. package/dist/match/path-utils.test.js.map +1 -0
  102. package/dist/match/segment-matcher.d.ts +25 -0
  103. package/dist/match/segment-matcher.d.ts.map +1 -0
  104. package/dist/match/segment-matcher.js +267 -0
  105. package/dist/match/segment-matcher.js.map +1 -0
  106. package/dist/parse/brace-expansion.d.ts +34 -0
  107. package/dist/parse/brace-expansion.d.ts.map +1 -0
  108. package/dist/parse/brace-expansion.js +294 -0
  109. package/dist/parse/brace-expansion.js.map +1 -0
  110. package/dist/parse/brace-expansion.test.d.ts +2 -0
  111. package/dist/parse/brace-expansion.test.d.ts.map +1 -0
  112. package/dist/parse/brace-expansion.test.js +105 -0
  113. package/dist/parse/brace-expansion.test.js.map +1 -0
  114. package/dist/parse/index.d.ts +8 -0
  115. package/dist/parse/index.d.ts.map +1 -0
  116. package/dist/parse/index.js +8 -0
  117. package/dist/parse/index.js.map +1 -0
  118. package/dist/parse/parser.d.ts +15 -0
  119. package/dist/parse/parser.d.ts.map +1 -0
  120. package/dist/parse/parser.js +526 -0
  121. package/dist/parse/parser.js.map +1 -0
  122. package/dist/parse/parser.test.d.ts +2 -0
  123. package/dist/parse/parser.test.d.ts.map +1 -0
  124. package/dist/parse/parser.test.js +266 -0
  125. package/dist/parse/parser.test.js.map +1 -0
  126. package/dist/parse/validator.d.ts +30 -0
  127. package/dist/parse/validator.d.ts.map +1 -0
  128. package/dist/parse/validator.js +115 -0
  129. package/dist/parse/validator.js.map +1 -0
  130. package/dist/parse/validator.test.d.ts +2 -0
  131. package/dist/parse/validator.test.d.ts.map +1 -0
  132. package/dist/parse/validator.test.js +45 -0
  133. package/dist/parse/validator.test.js.map +1 -0
  134. package/dist/types/ast.d.ts +158 -0
  135. package/dist/types/ast.d.ts.map +1 -0
  136. package/dist/types/ast.js +2 -0
  137. package/dist/types/ast.js.map +1 -0
  138. package/dist/types/automaton.d.ts +150 -0
  139. package/dist/types/automaton.d.ts.map +1 -0
  140. package/dist/types/automaton.js +2 -0
  141. package/dist/types/automaton.js.map +1 -0
  142. package/dist/types/containment.d.ts +257 -0
  143. package/dist/types/containment.d.ts.map +1 -0
  144. package/dist/types/containment.js +5 -0
  145. package/dist/types/containment.js.map +1 -0
  146. package/dist/types/errors.d.ts +37 -0
  147. package/dist/types/errors.d.ts.map +1 -0
  148. package/dist/types/errors.js +24 -0
  149. package/dist/types/errors.js.map +1 -0
  150. package/dist/types/index.d.ts +10 -0
  151. package/dist/types/index.d.ts.map +1 -0
  152. package/dist/types/index.js +6 -0
  153. package/dist/types/index.js.map +1 -0
  154. package/package.json +48 -0
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Automaton intersection using product construction.
3
+ * @packageDocumentation
4
+ */
5
+ /**
6
+ * Compute the intersection of two automata using product construction.
7
+ *
8
+ * The resulting automaton accepts a string iff both input automata accept it.
9
+ * L(A ∩ B) = L(A) ∩ L(B)
10
+ *
11
+ * @param a - First automaton
12
+ * @param b - Second automaton
13
+ * @returns Intersection automaton
14
+ *
15
+ * @public
16
+ */
17
+ export function intersect(a, b) {
18
+ return productConstruction(a, b, 'intersection');
19
+ }
20
+ /**
21
+ * Compute the union of two automata using NFA construction.
22
+ *
23
+ * The resulting automaton accepts a string iff either input automaton accepts it.
24
+ * L(A ∪ B) = L(A) ∪ L(B)
25
+ *
26
+ * We use NFA union: create a new initial state with epsilon transitions
27
+ * to both automata's initial states, then merge the states.
28
+ *
29
+ * @param a - First automaton
30
+ * @param b - Second automaton
31
+ * @returns Union automaton (NFA)
32
+ *
33
+ * @public
34
+ */
35
+ export function union(a, b) {
36
+ // Renumber states: a's states stay as-is, b's states are shifted by a.states.length
37
+ const aOffset = 0;
38
+ const bOffset = a.states.length;
39
+ const newInitialState = a.states.length + b.states.length;
40
+ // Copy a's states
41
+ const states = a.states.map((state) => ({
42
+ id: state.id + aOffset,
43
+ accepting: state.accepting,
44
+ transitions: state.transitions.map((t) => renumberTransition(t, aOffset)),
45
+ }));
46
+ // Copy b's states with renumbered IDs
47
+ for (const state of b.states) {
48
+ states.push({
49
+ id: state.id + bOffset,
50
+ accepting: state.accepting,
51
+ transitions: state.transitions.map((t) => renumberTransition(t, bOffset)),
52
+ });
53
+ }
54
+ // Create new initial state with epsilon transitions to both original initial states
55
+ states.push({
56
+ id: newInitialState,
57
+ accepting: false,
58
+ transitions: [
59
+ { type: 'epsilon', target: a.initialState + aOffset },
60
+ { type: 'epsilon', target: b.initialState + bOffset },
61
+ ],
62
+ });
63
+ // Accepting states from both automata
64
+ const acceptingStates = [...a.acceptingStates.map((s) => s + aOffset), ...b.acceptingStates.map((s) => s + bOffset)];
65
+ return {
66
+ states,
67
+ initialState: newInitialState,
68
+ acceptingStates,
69
+ isDeterministic: false, // NFA union is non-deterministic
70
+ };
71
+ }
72
+ /**
73
+ * Renumber a transition's targets by adding an offset.
74
+ */
75
+ function renumberTransition(t, offset) {
76
+ switch (t.type) {
77
+ case 'literal':
78
+ return { ...t, target: t.target + offset };
79
+ case 'wildcard':
80
+ return { ...t, target: t.target + offset };
81
+ case 'epsilon':
82
+ return { ...t, target: t.target + offset };
83
+ case 'globstar':
84
+ return { ...t, selfLoop: t.selfLoop + offset, exit: t.exit + offset };
85
+ }
86
+ }
87
+ /**
88
+ * Product construction for intersection or union.
89
+ */
90
+ function productConstruction(a, b, mode) {
91
+ // Map from (stateA, stateB) pair to product state ID
92
+ const pairToState = new Map();
93
+ const productStates = [];
94
+ const getPairKey = (sa, sb) => `${sa},${sb}`;
95
+ const getOrCreateState = (sa, sb) => {
96
+ const key = getPairKey(sa, sb);
97
+ let stateId = pairToState.get(key);
98
+ if (stateId === undefined) {
99
+ stateId = productStates.length;
100
+ pairToState.set(key, stateId);
101
+ const acceptA = a.states[sa]?.accepting ?? false;
102
+ const acceptB = b.states[sb]?.accepting ?? false;
103
+ // For intersection: accepting iff both accept
104
+ // For union: accepting iff either accepts
105
+ const accepting = mode === 'intersection' ? acceptA && acceptB : acceptA || acceptB;
106
+ productStates.push({
107
+ id: stateId,
108
+ transitions: [],
109
+ accepting,
110
+ });
111
+ }
112
+ return stateId;
113
+ };
114
+ // Start with initial states
115
+ const initialState = getOrCreateState(a.initialState, b.initialState);
116
+ // Worklist of state pairs to process
117
+ const worklist = [
118
+ { stateId: initialState, sa: a.initialState, sb: b.initialState },
119
+ ];
120
+ const processed = new Set();
121
+ while (worklist.length > 0) {
122
+ const { stateId, sa, sb } = worklist.pop();
123
+ const key = getPairKey(sa, sb);
124
+ if (processed.has(key))
125
+ continue;
126
+ processed.add(key);
127
+ const stateA = a.states[sa];
128
+ const stateB = b.states[sb];
129
+ const transitions = [];
130
+ // For each pair of transitions that can fire together
131
+ for (const transA of stateA?.transitions ?? []) {
132
+ for (const transB of stateB?.transitions ?? []) {
133
+ const combined = combineTransitions(transA, transB);
134
+ if (combined) {
135
+ const targetState = getOrCreateState(combined.targetA, combined.targetB);
136
+ transitions.push({
137
+ ...combined.transition,
138
+ target: targetState,
139
+ });
140
+ const targetKey = getPairKey(combined.targetA, combined.targetB);
141
+ if (!processed.has(targetKey)) {
142
+ worklist.push({
143
+ stateId: targetState,
144
+ sa: combined.targetA,
145
+ sb: combined.targetB,
146
+ });
147
+ }
148
+ }
149
+ }
150
+ }
151
+ productStates[stateId] = {
152
+ ...productStates[stateId],
153
+ transitions,
154
+ };
155
+ }
156
+ const acceptingStates = productStates.filter((s) => s.accepting).map((s) => s.id);
157
+ return {
158
+ states: productStates,
159
+ initialState,
160
+ acceptingStates,
161
+ isDeterministic: a.isDeterministic && b.isDeterministic,
162
+ };
163
+ }
164
+ /**
165
+ * Combine two transitions if they can fire on the same input.
166
+ */
167
+ function combineTransitions(transA, transB) {
168
+ // Skip epsilon transitions in product (they're handled differently)
169
+ if (transA.type === 'epsilon' || transB.type === 'epsilon') {
170
+ return null;
171
+ }
172
+ // Literal + Literal: must be same literal
173
+ if (transA.type === 'literal' && transB.type === 'literal') {
174
+ if (transA.segment === transB.segment) {
175
+ return {
176
+ transition: { type: 'literal', segment: transA.segment },
177
+ targetA: transA.target,
178
+ targetB: transB.target,
179
+ };
180
+ }
181
+ return null;
182
+ }
183
+ // Literal + Wildcard: literal must match wildcard pattern
184
+ if (transA.type === 'literal' && transB.type === 'wildcard') {
185
+ if (transB.pattern.test(transA.segment)) {
186
+ return {
187
+ transition: { type: 'literal', segment: transA.segment },
188
+ targetA: transA.target,
189
+ targetB: transB.target,
190
+ };
191
+ }
192
+ return null;
193
+ }
194
+ // Wildcard + Literal: literal must match wildcard pattern
195
+ if (transA.type === 'wildcard' && transB.type === 'literal') {
196
+ if (transA.pattern.test(transB.segment)) {
197
+ return {
198
+ transition: { type: 'literal', segment: transB.segment },
199
+ targetA: transA.target,
200
+ targetB: transB.target,
201
+ };
202
+ }
203
+ return null;
204
+ }
205
+ // Wildcard + Wildcard: compute intersection of patterns
206
+ if (transA.type === 'wildcard' && transB.type === 'wildcard') {
207
+ // Create a combined matcher that tests both patterns
208
+ const combinedPattern = createIntersectionPattern(transA.pattern, transB.pattern);
209
+ return {
210
+ transition: {
211
+ type: 'wildcard',
212
+ pattern: combinedPattern,
213
+ patternSource: `(${transA.patternSource})∩(${transB.patternSource})`,
214
+ },
215
+ targetA: transA.target,
216
+ targetB: transB.target,
217
+ };
218
+ }
219
+ // Globstar transitions
220
+ if (transA.type === 'globstar' || transB.type === 'globstar') {
221
+ return handleGlobstarProduct(transA, transB);
222
+ }
223
+ return null;
224
+ }
225
+ /**
226
+ * Create a pattern that matches the intersection of two patterns.
227
+ *
228
+ * Since true regex intersection is complex (undecidable in general),
229
+ * we create a composite matcher that tests both patterns.
230
+ *
231
+ * @param patternA - First pattern to test
232
+ * @param patternB - Second pattern to test
233
+ * @returns A SegmentMatcher that matches if both patterns match
234
+ */
235
+ function createIntersectionPattern(patternA, patternB) {
236
+ return {
237
+ test: (str) => patternA.test(str) && patternB.test(str),
238
+ source: `(${patternA.source})∩(${patternB.source})`,
239
+ };
240
+ }
241
+ /**
242
+ * Handle product of globstar transitions.
243
+ */
244
+ function handleGlobstarProduct(transA, transB) {
245
+ // Globstar matches any segment, so it can combine with anything
246
+ if (transA.type === 'globstar' && transB.type === 'globstar') {
247
+ // Both globstars: product stays in globstar state for both
248
+ return {
249
+ transition: {
250
+ type: 'wildcard',
251
+ pattern: /^.+$/,
252
+ patternSource: '**',
253
+ },
254
+ targetA: transA.selfLoop,
255
+ targetB: transB.selfLoop,
256
+ };
257
+ }
258
+ if (transA.type === 'globstar') {
259
+ // A is globstar, B is something else
260
+ if (transB.type === 'literal') {
261
+ return {
262
+ transition: { type: 'literal', segment: transB.segment },
263
+ targetA: transA.selfLoop, // Stay in globstar
264
+ targetB: transB.target,
265
+ };
266
+ }
267
+ if (transB.type === 'wildcard') {
268
+ return {
269
+ transition: {
270
+ type: 'wildcard',
271
+ pattern: transB.pattern,
272
+ patternSource: transB.patternSource,
273
+ },
274
+ targetA: transA.selfLoop,
275
+ targetB: transB.target,
276
+ };
277
+ }
278
+ }
279
+ if (transB.type === 'globstar') {
280
+ // B is globstar, A is something else
281
+ if (transA.type === 'literal') {
282
+ return {
283
+ transition: { type: 'literal', segment: transA.segment },
284
+ targetA: transA.target,
285
+ targetB: transB.selfLoop,
286
+ };
287
+ }
288
+ if (transA.type === 'wildcard') {
289
+ return {
290
+ transition: {
291
+ type: 'wildcard',
292
+ pattern: transA.pattern,
293
+ patternSource: transA.patternSource,
294
+ },
295
+ targetA: transA.target,
296
+ targetB: transB.selfLoop,
297
+ };
298
+ }
299
+ }
300
+ return null;
301
+ }
302
+ //# sourceMappingURL=intersect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intersect.js","sourceRoot":"","sources":["../../src/automaton/intersect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Pattern-level set operations (pattern algebra).
3
+ *
4
+ * These functions operate on CompiledPattern objects and return new
5
+ * CompiledPattern objects, providing a higher-level API than the raw
6
+ * automaton operations.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ import type { CompiledPattern } from '../types';
11
+ /**
12
+ * Compute the intersection of two patterns.
13
+ *
14
+ * The result matches paths that match BOTH input patterns.
15
+ * L(result) = L(a) ∩ L(b)
16
+ *
17
+ * @param a - First pattern
18
+ * @param b - Second pattern
19
+ * @returns Pattern matching paths in both a and b
20
+ *
21
+ * @public
22
+ */
23
+ export declare function patternIntersect(a: CompiledPattern, b: CompiledPattern): CompiledPattern;
24
+ /**
25
+ * Compute the union of two patterns.
26
+ *
27
+ * The result matches paths that match EITHER input pattern.
28
+ * L(result) = L(a) ∪ L(b)
29
+ *
30
+ * @param a - First pattern
31
+ * @param b - Second pattern
32
+ * @returns Pattern matching paths in a or b (or both)
33
+ *
34
+ * @public
35
+ */
36
+ export declare function patternUnion(a: CompiledPattern, b: CompiledPattern): CompiledPattern;
37
+ /**
38
+ * Compute the complement of a pattern.
39
+ *
40
+ * The result matches paths that do NOT match the input pattern.
41
+ * L(result) = Σ* - L(a)
42
+ *
43
+ * @param a - Pattern to complement
44
+ * @returns Pattern matching paths not matched by a
45
+ *
46
+ * @public
47
+ */
48
+ export declare function patternComplement(a: CompiledPattern): CompiledPattern;
49
+ /**
50
+ * Compute the difference of two patterns.
51
+ *
52
+ * The result matches paths that match a but NOT b.
53
+ * L(result) = L(a) - L(b) = L(a) ∩ L(¬b)
54
+ *
55
+ * @param a - Pattern to subtract from
56
+ * @param b - Pattern to subtract
57
+ * @returns Pattern matching paths in a but not in b
58
+ *
59
+ * @public
60
+ */
61
+ export declare function patternDifference(a: CompiledPattern, b: CompiledPattern): CompiledPattern;
62
+ //# sourceMappingURL=pattern-algebra.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-algebra.d.ts","sourceRoot":"","sources":["../../src/automaton/pattern-algebra.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAA+C,MAAM,UAAU,CAAA;AAS5F;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,eAAe,GAAG,eAAe,CAkBxF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,eAAe,GAAG,eAAe,CAkBpF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,eAAe,GAAG,eAAe,CAqBrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,eAAe,GAAG,eAAe,CAyBzF"}
@@ -0,0 +1,309 @@
1
+ /**
2
+ * Pattern-level set operations (pattern algebra).
3
+ *
4
+ * These functions operate on CompiledPattern objects and return new
5
+ * CompiledPattern objects, providing a higher-level API than the raw
6
+ * automaton operations.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ import { intersect, union } from './intersect';
11
+ import { complement } from './complement';
12
+ import { determinize } from './determinize';
13
+ // =============================================================================
14
+ // PATTERN SET OPERATIONS
15
+ // =============================================================================
16
+ /**
17
+ * Compute the intersection of two patterns.
18
+ *
19
+ * The result matches paths that match BOTH input patterns.
20
+ * L(result) = L(a) ∩ L(b)
21
+ *
22
+ * @param a - First pattern
23
+ * @param b - Second pattern
24
+ * @returns Pattern matching paths in both a and b
25
+ *
26
+ * @public
27
+ */
28
+ export function patternIntersect(a, b) {
29
+ // Determinize inputs to handle epsilon transitions properly
30
+ const dfaA = a.automaton.isDeterministic ? a.automaton : determinize(a.automaton);
31
+ const dfaB = b.automaton.isDeterministic ? b.automaton : determinize(b.automaton);
32
+ const automaton = intersect(dfaA, dfaB);
33
+ const source = `(${a.source}) ∩ (${b.source})`;
34
+ const ast = createSyntheticAst(source, 'intersection', [a.ast, b.ast]);
35
+ const quickReject = mergeQuickRejectForIntersection(a.quickReject, b.quickReject);
36
+ return {
37
+ source,
38
+ ast,
39
+ quickReject,
40
+ automaton,
41
+ isUnbounded: a.isUnbounded && b.isUnbounded,
42
+ minSegments: Math.max(a.minSegments, b.minSegments),
43
+ maxSegments: computeIntersectionMaxSegments(a.maxSegments, b.maxSegments),
44
+ };
45
+ }
46
+ /**
47
+ * Compute the union of two patterns.
48
+ *
49
+ * The result matches paths that match EITHER input pattern.
50
+ * L(result) = L(a) ∪ L(b)
51
+ *
52
+ * @param a - First pattern
53
+ * @param b - Second pattern
54
+ * @returns Pattern matching paths in a or b (or both)
55
+ *
56
+ * @public
57
+ */
58
+ export function patternUnion(a, b) {
59
+ // Determinize inputs to handle epsilon transitions properly
60
+ const dfaA = a.automaton.isDeterministic ? a.automaton : determinize(a.automaton);
61
+ const dfaB = b.automaton.isDeterministic ? b.automaton : determinize(b.automaton);
62
+ const automaton = union(dfaA, dfaB);
63
+ const source = `(${a.source}) ∪ (${b.source})`;
64
+ const ast = createSyntheticAst(source, 'union', [a.ast, b.ast]);
65
+ const quickReject = mergeQuickRejectForUnion(a.quickReject, b.quickReject);
66
+ return {
67
+ source,
68
+ ast,
69
+ quickReject,
70
+ automaton,
71
+ isUnbounded: a.isUnbounded || b.isUnbounded,
72
+ minSegments: Math.min(a.minSegments, b.minSegments),
73
+ maxSegments: computeUnionMaxSegments(a.maxSegments, b.maxSegments, a.isUnbounded, b.isUnbounded),
74
+ };
75
+ }
76
+ /**
77
+ * Compute the complement of a pattern.
78
+ *
79
+ * The result matches paths that do NOT match the input pattern.
80
+ * L(result) = Σ* - L(a)
81
+ *
82
+ * @param a - Pattern to complement
83
+ * @returns Pattern matching paths not matched by a
84
+ *
85
+ * @public
86
+ */
87
+ export function patternComplement(a) {
88
+ // Determinize input (complement already does this, but be explicit)
89
+ const dfa = a.automaton.isDeterministic ? a.automaton : determinize(a.automaton);
90
+ const automaton = complement(dfa);
91
+ const source = `¬(${a.source})`;
92
+ const ast = createSyntheticAst(source, 'complement', [a.ast]);
93
+ // Complement has no useful quick-reject filters
94
+ // (the complement of any bounded set is unbounded)
95
+ const quickReject = {};
96
+ return {
97
+ source,
98
+ ast,
99
+ quickReject,
100
+ automaton,
101
+ // Complement is always unbounded (matches infinite set of paths)
102
+ isUnbounded: true,
103
+ minSegments: 0,
104
+ maxSegments: undefined,
105
+ };
106
+ }
107
+ /**
108
+ * Compute the difference of two patterns.
109
+ *
110
+ * The result matches paths that match a but NOT b.
111
+ * L(result) = L(a) - L(b) = L(a) ∩ L(¬b)
112
+ *
113
+ * @param a - Pattern to subtract from
114
+ * @param b - Pattern to subtract
115
+ * @returns Pattern matching paths in a but not in b
116
+ *
117
+ * @public
118
+ */
119
+ export function patternDifference(a, b) {
120
+ // A \ B = A ∩ ¬B
121
+ // Determinize inputs to handle epsilon transitions properly
122
+ const dfaA = a.automaton.isDeterministic ? a.automaton : determinize(a.automaton);
123
+ const dfaB = b.automaton.isDeterministic ? b.automaton : determinize(b.automaton);
124
+ const bComplement = complement(dfaB);
125
+ const automaton = intersect(dfaA, bComplement);
126
+ const source = `(${a.source}) \\ (${b.source})`;
127
+ const ast = createSyntheticAst(source, 'difference', [a.ast, b.ast]);
128
+ // Difference inherits quick-reject from a (paths must match a)
129
+ // But we can't use b's filters since we're excluding b
130
+ const quickReject = a.quickReject;
131
+ return {
132
+ source,
133
+ ast,
134
+ quickReject,
135
+ automaton,
136
+ // Difference of A and B has same unbounded status as A
137
+ // (we're only removing paths from A)
138
+ isUnbounded: a.isUnbounded,
139
+ minSegments: a.minSegments,
140
+ maxSegments: a.maxSegments,
141
+ };
142
+ }
143
+ /**
144
+ * Create a synthetic AST for algebraic pattern operations.
145
+ */
146
+ function createSyntheticAst(source, _operation, operands) {
147
+ // For synthetic patterns, we create an alternation node containing
148
+ // references to the original patterns. This preserves the structure
149
+ // while indicating this is a computed pattern.
150
+ const root = {
151
+ type: 'alternation',
152
+ branches: operands.map((p) => p.root),
153
+ };
154
+ return {
155
+ source,
156
+ root,
157
+ // Synthetic patterns inherit absoluteness from operands
158
+ isAbsolute: operands.some((p) => p.isAbsolute),
159
+ isNegation: false,
160
+ };
161
+ }
162
+ /**
163
+ * Merge quick-reject filters for intersection (AND semantics).
164
+ *
165
+ * For intersection, a path must satisfy BOTH patterns, so we take
166
+ * the more restrictive constraint for each field.
167
+ */
168
+ function mergeQuickRejectForIntersection(a, b) {
169
+ return {
170
+ requiredPrefix: mergePrefix(a.requiredPrefix, b.requiredPrefix, 'intersection'),
171
+ requiredSuffix: mergeSuffix(a.requiredSuffix, b.requiredSuffix, 'intersection'),
172
+ minLength: mergeMinLength(a.minLength, b.minLength, 'intersection'),
173
+ requiredLiterals: mergeLiterals(a.requiredLiterals, b.requiredLiterals, 'intersection'),
174
+ };
175
+ }
176
+ /**
177
+ * Merge quick-reject filters for union (OR semantics).
178
+ *
179
+ * For union, a path need only satisfy ONE pattern, so we take
180
+ * the less restrictive (common) constraint for each field.
181
+ */
182
+ function mergeQuickRejectForUnion(a, b) {
183
+ return {
184
+ requiredPrefix: mergePrefix(a.requiredPrefix, b.requiredPrefix, 'union'),
185
+ requiredSuffix: mergeSuffix(a.requiredSuffix, b.requiredSuffix, 'union'),
186
+ minLength: mergeMinLength(a.minLength, b.minLength, 'union'),
187
+ requiredLiterals: mergeLiterals(a.requiredLiterals, b.requiredLiterals, 'union'),
188
+ };
189
+ }
190
+ /**
191
+ * Merge prefix constraints.
192
+ */
193
+ function mergePrefix(a, b, mode) {
194
+ if (a === undefined)
195
+ return mode === 'intersection' ? b : undefined;
196
+ if (b === undefined)
197
+ return mode === 'intersection' ? a : undefined;
198
+ if (mode === 'intersection') {
199
+ // For intersection, take longer prefix if one is substring of other
200
+ if (a.startsWith(b))
201
+ return a;
202
+ if (b.startsWith(a))
203
+ return b;
204
+ // Incompatible prefixes - keep the longer one (will likely reject more)
205
+ return a.length >= b.length ? a : b;
206
+ }
207
+ else {
208
+ // For union, take common prefix only
209
+ let common = '';
210
+ for (let i = 0; i < Math.min(a.length, b.length); i++) {
211
+ if (a[i] === b[i]) {
212
+ common += a[i];
213
+ }
214
+ else {
215
+ break;
216
+ }
217
+ }
218
+ return common || undefined;
219
+ }
220
+ }
221
+ /**
222
+ * Merge suffix constraints.
223
+ */
224
+ function mergeSuffix(a, b, mode) {
225
+ if (a === undefined)
226
+ return mode === 'intersection' ? b : undefined;
227
+ if (b === undefined)
228
+ return mode === 'intersection' ? a : undefined;
229
+ if (mode === 'intersection') {
230
+ // For intersection, take longer suffix if one is substring of other
231
+ if (a.endsWith(b))
232
+ return a;
233
+ if (b.endsWith(a))
234
+ return b;
235
+ // Incompatible suffixes - keep the longer one
236
+ return a.length >= b.length ? a : b;
237
+ }
238
+ else {
239
+ // For union, take common suffix only
240
+ let common = '';
241
+ for (let i = 0; i < Math.min(a.length, b.length); i++) {
242
+ if (a[a.length - 1 - i] === b[b.length - 1 - i]) {
243
+ common = a[a.length - 1 - i] + common;
244
+ }
245
+ else {
246
+ break;
247
+ }
248
+ }
249
+ return common || undefined;
250
+ }
251
+ }
252
+ /**
253
+ * Merge minLength constraints.
254
+ */
255
+ function mergeMinLength(a, b, mode) {
256
+ if (a === undefined)
257
+ return mode === 'intersection' ? b : undefined;
258
+ if (b === undefined)
259
+ return mode === 'intersection' ? a : undefined;
260
+ if (mode === 'intersection') {
261
+ // For intersection, take max (more restrictive)
262
+ return Math.max(a, b);
263
+ }
264
+ else {
265
+ // For union, take min (less restrictive)
266
+ return Math.min(a, b);
267
+ }
268
+ }
269
+ /**
270
+ * Merge requiredLiterals constraints.
271
+ */
272
+ function mergeLiterals(a, b, mode) {
273
+ if (a === undefined)
274
+ return mode === 'intersection' ? b : undefined;
275
+ if (b === undefined)
276
+ return mode === 'intersection' ? a : undefined;
277
+ if (mode === 'intersection') {
278
+ // For intersection, union of sets (all must be present)
279
+ const combined = new Set([...a, ...b]);
280
+ return combined.size > 0 ? [...combined] : undefined;
281
+ }
282
+ else {
283
+ // For union, intersection of sets (must be in all branches)
284
+ const bSet = new Set(b);
285
+ const common = a.filter((lit) => bSet.has(lit));
286
+ return common.length > 0 ? common : undefined;
287
+ }
288
+ }
289
+ /**
290
+ * Compute maxSegments for intersection.
291
+ */
292
+ function computeIntersectionMaxSegments(a, b) {
293
+ if (a === undefined)
294
+ return b;
295
+ if (b === undefined)
296
+ return a;
297
+ return Math.min(a, b);
298
+ }
299
+ /**
300
+ * Compute maxSegments for union.
301
+ */
302
+ function computeUnionMaxSegments(a, b, aUnbounded, bUnbounded) {
303
+ if (aUnbounded || bUnbounded)
304
+ return undefined;
305
+ if (a === undefined || b === undefined)
306
+ return undefined;
307
+ return Math.max(a, b);
308
+ }
309
+ //# sourceMappingURL=pattern-algebra.js.map