clarity-pattern-parser 11.4.2 → 11.5.1
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/ast/Node.d.ts +5 -5
- package/dist/index.browser.js +50 -14
- package/dist/index.browser.js.map +1 -1
- package/dist/index.esm.js +50 -14
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +50 -14
- package/dist/index.js.map +1 -1
- package/dist/patterns/Expression.d.ts +1 -0
- package/package.json +1 -1
- package/src/ast/Node.test.ts +38 -0
- package/src/ast/Node.ts +41 -14
- package/src/patterns/Expression.ts +8 -1
package/package.json
CHANGED
package/src/ast/Node.test.ts
CHANGED
|
@@ -477,4 +477,42 @@ describe("Node", () => {
|
|
|
477
477
|
expect(result.isEqual(expected)).toBeTruthy();
|
|
478
478
|
});
|
|
479
479
|
|
|
480
|
+
test("Find All", () => {
|
|
481
|
+
const a = new Node("a", "a", 0, 0, [], "A");
|
|
482
|
+
const b = new Node("b", "b", 0, 0, [], "B");
|
|
483
|
+
const a2 = a.clone();
|
|
484
|
+
const parent = new Node("parent", "parent", 0, 0, [a, b, a2]);
|
|
485
|
+
|
|
486
|
+
const result = parent.findAll(n => n.name === "a");
|
|
487
|
+
expect(result).toEqual([a, a2]);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
test("Breadth First Early Exit", () => {
|
|
491
|
+
const a = new Node("a", "a", 0, 0, [], "A");
|
|
492
|
+
const b = new Node("b", "b", 0, 0, [], "B");
|
|
493
|
+
const a2 = a.clone();
|
|
494
|
+
const parent = new Node("parent", "parent", 0, 0, [a, b, a2]);
|
|
495
|
+
|
|
496
|
+
let count = 0;
|
|
497
|
+
parent.walkBreadthFirst(n => {
|
|
498
|
+
count++;
|
|
499
|
+
if (n.name === "a") {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
return true;
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
expect(count).toBe(2);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
test("Find All (Breadth First)", () => {
|
|
509
|
+
const a = new Node("a", "a", 0, 0, [], "A");
|
|
510
|
+
const b = new Node("b", "b", 0, 0, [], "B");
|
|
511
|
+
const a2 = a.clone();
|
|
512
|
+
const parent = new Node("parent", "parent", 0, 0, [a, b, a2]);
|
|
513
|
+
|
|
514
|
+
const result = parent.findAll(n => n.name === "a", true);
|
|
515
|
+
expect(result).toEqual([a, a2]);
|
|
516
|
+
});
|
|
517
|
+
|
|
480
518
|
});
|
package/src/ast/Node.ts
CHANGED
|
@@ -190,16 +190,40 @@ export class Node {
|
|
|
190
190
|
return null;
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
find(predicate: (node: Node) => boolean): Node | null {
|
|
194
|
-
|
|
193
|
+
find(predicate: (node: Node) => boolean, breadthFirst = false): Node | null {
|
|
194
|
+
let match: Node | null = null;
|
|
195
|
+
|
|
196
|
+
if (breadthFirst) {
|
|
197
|
+
this.walkBreadthFirst(n => {
|
|
198
|
+
if (predicate(n)) {
|
|
199
|
+
match = n;
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
} else {
|
|
204
|
+
this.walkUp(n => {
|
|
205
|
+
if (predicate(n)) {
|
|
206
|
+
match = n;
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return match;
|
|
195
213
|
}
|
|
196
214
|
|
|
197
|
-
findAll(predicate: (node: Node) => boolean): Node[] {
|
|
215
|
+
findAll(predicate: (node: Node) => boolean, breadthFirst = false): Node[] {
|
|
198
216
|
const matches: Node[] = [];
|
|
199
217
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
218
|
+
if (breadthFirst) {
|
|
219
|
+
this.walkBreadthFirst(n => {
|
|
220
|
+
if (predicate(n)) { matches.push(n); }
|
|
221
|
+
});
|
|
222
|
+
} else {
|
|
223
|
+
this.walkUp(n => {
|
|
224
|
+
if (predicate(n)) { matches.push(n);}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
203
227
|
|
|
204
228
|
return matches;
|
|
205
229
|
}
|
|
@@ -229,28 +253,31 @@ export class Node {
|
|
|
229
253
|
return null;
|
|
230
254
|
}
|
|
231
255
|
|
|
232
|
-
walkUp(callback: (node: Node) => void) {
|
|
256
|
+
walkUp(callback: (node: Node) => boolean | void): boolean {
|
|
233
257
|
const childrenCopy = this._children.slice();
|
|
234
258
|
|
|
235
|
-
childrenCopy.
|
|
236
|
-
callback(this);
|
|
259
|
+
const result = childrenCopy.every(c => c.walkUp(callback));
|
|
260
|
+
return (callback(this) ?? true) && result;
|
|
237
261
|
}
|
|
238
262
|
|
|
239
|
-
walkDown(callback: (node: Node) => void) {
|
|
263
|
+
walkDown(callback: (node: Node) => boolean | void): boolean {
|
|
240
264
|
const childrenCopy = this._children.slice();
|
|
241
265
|
|
|
242
|
-
callback(this);
|
|
243
|
-
childrenCopy.forEach(c => c.walkDown(callback));
|
|
266
|
+
return (callback(this) ?? true) && childrenCopy.every(c => c.walkDown(callback));
|
|
244
267
|
}
|
|
245
268
|
|
|
246
|
-
walkBreadthFirst(callback: (node: Node) => void):
|
|
269
|
+
walkBreadthFirst(callback: (node: Node) => boolean | void): boolean {
|
|
247
270
|
const queue: Node[] = [this];
|
|
248
271
|
|
|
249
272
|
while (queue.length > 0) {
|
|
250
273
|
const current = queue.shift() as Node;
|
|
251
|
-
callback(current)
|
|
274
|
+
if (callback(current) === false) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
252
277
|
queue.push(...current.children);
|
|
253
278
|
}
|
|
279
|
+
|
|
280
|
+
return true;
|
|
254
281
|
}
|
|
255
282
|
|
|
256
283
|
transform(visitors: Record<string, (node: Node) => Node>) {
|
|
@@ -17,6 +17,7 @@ export class Expression implements Pattern {
|
|
|
17
17
|
private _name: string;
|
|
18
18
|
private _originalName: string;
|
|
19
19
|
private _parent: Pattern | null;
|
|
20
|
+
private _cachedParent: Pattern | null;
|
|
20
21
|
private _firstIndex: number;
|
|
21
22
|
private _originalPatterns: Pattern[];
|
|
22
23
|
private _patterns: Pattern[];
|
|
@@ -92,6 +93,7 @@ export class Expression implements Pattern {
|
|
|
92
93
|
this._name = name;
|
|
93
94
|
this._originalName = name;
|
|
94
95
|
this._parent = null;
|
|
96
|
+
this._cachedParent = null;
|
|
95
97
|
this._firstIndex = 0;
|
|
96
98
|
this._atomPatterns = [];
|
|
97
99
|
this._prefixPatterns = [];
|
|
@@ -278,7 +280,8 @@ export class Expression implements Pattern {
|
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
build() {
|
|
281
|
-
if (!this._hasOrganized) {
|
|
283
|
+
if (!this._hasOrganized || this._cachedParent !== this.parent) {
|
|
284
|
+
this._cachedParent = this.parent;
|
|
282
285
|
this._hasOrganized = true;
|
|
283
286
|
this._organizePatterns(this._originalPatterns);
|
|
284
287
|
this._cacheAncestors();
|
|
@@ -491,6 +494,7 @@ export class Expression implements Pattern {
|
|
|
491
494
|
}
|
|
492
495
|
|
|
493
496
|
getTokens(): string[] {
|
|
497
|
+
this.build();
|
|
494
498
|
const atomTokens = this._atomPatterns.map(p => p.getTokens()).flat();
|
|
495
499
|
const prefixTokens = this.prefixPatterns.map(p => p.getTokens()).flat();
|
|
496
500
|
|
|
@@ -498,6 +502,7 @@ export class Expression implements Pattern {
|
|
|
498
502
|
}
|
|
499
503
|
|
|
500
504
|
getTokensAfter(childReference: Pattern): string[] {
|
|
505
|
+
this.build();
|
|
501
506
|
if (this._prefixPatterns.includes(childReference) || this._binaryPatterns.includes(childReference)) {
|
|
502
507
|
const atomTokens = this._atomPatterns.map(p => p.getTokens()).flat();
|
|
503
508
|
const prefixTokens = this.prefixPatterns.map(p => p.getTokens()).flat();
|
|
@@ -534,6 +539,7 @@ export class Expression implements Pattern {
|
|
|
534
539
|
}
|
|
535
540
|
|
|
536
541
|
getPatterns(): Pattern[] {
|
|
542
|
+
this.build();
|
|
537
543
|
const atomPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
|
|
538
544
|
const prefixPatterns = this.prefixPatterns.map(p => p.getPatterns()).flat();
|
|
539
545
|
|
|
@@ -541,6 +547,7 @@ export class Expression implements Pattern {
|
|
|
541
547
|
}
|
|
542
548
|
|
|
543
549
|
getPatternsAfter(childReference: Pattern): Pattern[] {
|
|
550
|
+
this.build();
|
|
544
551
|
if (this._prefixPatterns.includes(childReference) || this._binaryPatterns.includes(childReference)) {
|
|
545
552
|
const atomPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
|
|
546
553
|
const prefixPatterns = this.prefixPatterns.map(p => p.getPatterns()).flat();
|