clarity-pattern-parser 5.0.0 → 6.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.
- package/README.md +328 -38
- package/TODO.md +55 -1
- package/dist/ast/Node.d.ts +8 -2
- package/dist/index.browser.js +470 -205
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.esm.js +469 -206
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +470 -205
- package/dist/index.js.map +1 -1
- package/dist/intellisense/AutoComplete.d.ts +28 -0
- package/dist/intellisense/Suggestion.d.ts +11 -0
- package/dist/intellisense/SuggestionOption.d.ts +4 -0
- package/dist/patterns/And.d.ts +7 -7
- package/dist/patterns/Cursor.d.ts +6 -4
- package/dist/patterns/CursorHistory.d.ts +2 -2
- package/dist/patterns/Literal.d.ts +7 -8
- package/dist/patterns/Not.d.ts +8 -5
- package/dist/patterns/Or.d.ts +7 -5
- package/dist/patterns/Pattern.d.ts +7 -4
- package/dist/patterns/Reference.d.ts +10 -7
- package/dist/patterns/Regex.d.ts +7 -8
- package/dist/patterns/Repeat.d.ts +7 -7
- package/package.json +1 -1
- package/src/ast/Node.test.ts +110 -0
- package/src/ast/Node.ts +71 -5
- package/src/index.ts +14 -3
- package/src/intellisense/AutoComplete.test.ts +90 -12
- package/src/intellisense/AutoComplete.ts +66 -12
- package/src/intellisense/Suggestion.ts +3 -4
- package/src/intellisense/javascript/Javascript.test.ts +56 -56
- package/src/intellisense/javascript/escapedCharacter.ts +0 -1
- package/src/intellisense/javascript/exponent.ts +0 -2
- package/src/intellisense/javascript/fraction.ts +0 -2
- package/src/patterns/And.test.ts +63 -52
- package/src/patterns/And.ts +58 -36
- package/src/patterns/Cursor.ts +17 -14
- package/src/patterns/CursorHistory.ts +8 -8
- package/src/patterns/Literal.test.ts +70 -38
- package/src/patterns/Literal.ts +31 -42
- package/src/patterns/Not.test.ts +88 -8
- package/src/patterns/Not.ts +54 -14
- package/src/patterns/Or.test.ts +117 -13
- package/src/patterns/Or.ts +36 -13
- package/src/patterns/Pattern.ts +7 -4
- package/src/patterns/Reference.test.ts +117 -28
- package/src/patterns/Reference.ts +58 -32
- package/src/patterns/Regex.test.ts +67 -35
- package/src/patterns/Regex.ts +31 -43
- package/src/patterns/Repeat.test.ts +63 -41
- package/src/patterns/Repeat.ts +51 -38
- package/src/patterns/getNextPattern.test.ts +0 -39
- package/src/patterns/getNextPattern.ts +0 -18
package/dist/index.esm.js
CHANGED
|
@@ -23,6 +23,9 @@ class Node {
|
|
|
23
23
|
get children() {
|
|
24
24
|
return this._children;
|
|
25
25
|
}
|
|
26
|
+
get hasChildren() {
|
|
27
|
+
return this._children.length > 0;
|
|
28
|
+
}
|
|
26
29
|
get value() {
|
|
27
30
|
return this.toString();
|
|
28
31
|
}
|
|
@@ -72,22 +75,54 @@ class Node {
|
|
|
72
75
|
}
|
|
73
76
|
spliceChildren(index, deleteCount, ...items) {
|
|
74
77
|
const removedItems = this._children.splice(index, deleteCount, ...items);
|
|
75
|
-
items.forEach(i => i._parent = this);
|
|
76
78
|
removedItems.forEach(i => i._parent = null);
|
|
79
|
+
items.forEach(i => i._parent = this);
|
|
77
80
|
return removedItems;
|
|
78
81
|
}
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
nextSibling() {
|
|
83
|
+
if (this._parent == null) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const children = this._parent._children;
|
|
87
|
+
const index = children.indexOf(this);
|
|
88
|
+
if (index > -1 && index < children.length - 1) {
|
|
89
|
+
return children[index + 1];
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
previousSibling() {
|
|
94
|
+
if (this._parent == null) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const children = this._parent._children;
|
|
98
|
+
const index = children.indexOf(this);
|
|
99
|
+
if (index > -1 && index > 0) {
|
|
100
|
+
return children[index - 1];
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
81
103
|
}
|
|
82
|
-
|
|
104
|
+
find(predicate) {
|
|
105
|
+
return this.findAll(predicate)[0] || null;
|
|
106
|
+
}
|
|
107
|
+
findAll(predicate) {
|
|
83
108
|
const matches = [];
|
|
84
109
|
this.walkUp(n => {
|
|
85
|
-
if (
|
|
110
|
+
if (predicate(n)) {
|
|
86
111
|
matches.push(n);
|
|
87
112
|
}
|
|
88
113
|
});
|
|
89
114
|
return matches;
|
|
90
115
|
}
|
|
116
|
+
findAncester(predicate) {
|
|
117
|
+
let parent = this._parent;
|
|
118
|
+
while (parent != null) {
|
|
119
|
+
if (predicate(parent)) {
|
|
120
|
+
return parent;
|
|
121
|
+
}
|
|
122
|
+
parent = parent._parent;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
91
126
|
walkUp(callback) {
|
|
92
127
|
this.children.forEach(c => c.walkUp(callback));
|
|
93
128
|
callback(this);
|
|
@@ -96,6 +131,20 @@ class Node {
|
|
|
96
131
|
callback(this);
|
|
97
132
|
this.children.forEach(c => c.walkDown(callback));
|
|
98
133
|
}
|
|
134
|
+
flatten() {
|
|
135
|
+
const nodes = [];
|
|
136
|
+
this.walkDown((node) => {
|
|
137
|
+
if (!node.hasChildren) {
|
|
138
|
+
nodes.push(node);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return nodes;
|
|
142
|
+
}
|
|
143
|
+
reduce() {
|
|
144
|
+
const value = this.toString();
|
|
145
|
+
this.removeAllChildren();
|
|
146
|
+
this._value = value;
|
|
147
|
+
}
|
|
99
148
|
clone() {
|
|
100
149
|
return new Node(this._type, this._name, this._firstIndex, this._lastIndex, this._children.map((c) => c.clone()), this._value);
|
|
101
150
|
}
|
|
@@ -140,15 +189,18 @@ class CursorHistory {
|
|
|
140
189
|
this._nodes = [];
|
|
141
190
|
this._errors = [];
|
|
142
191
|
}
|
|
192
|
+
get isRecording() {
|
|
193
|
+
return this._isRecording;
|
|
194
|
+
}
|
|
195
|
+
get rootMatch() {
|
|
196
|
+
return this._rootMatch;
|
|
197
|
+
}
|
|
143
198
|
get leafMatch() {
|
|
144
199
|
return this._leafMatch;
|
|
145
200
|
}
|
|
146
201
|
get furthestError() {
|
|
147
202
|
return this._furthestError;
|
|
148
203
|
}
|
|
149
|
-
get isRecording() {
|
|
150
|
-
return this._isRecording;
|
|
151
|
-
}
|
|
152
204
|
get errors() {
|
|
153
205
|
return this._errors;
|
|
154
206
|
}
|
|
@@ -161,9 +213,6 @@ class CursorHistory {
|
|
|
161
213
|
get patterns() {
|
|
162
214
|
return this._patterns;
|
|
163
215
|
}
|
|
164
|
-
get rootMatch() {
|
|
165
|
-
return this._rootMatch;
|
|
166
|
-
}
|
|
167
216
|
recordMatch(pattern, node) {
|
|
168
217
|
if (this._isRecording) {
|
|
169
218
|
this._patterns.push(pattern);
|
|
@@ -206,17 +255,17 @@ class Cursor {
|
|
|
206
255
|
return this._index === 0;
|
|
207
256
|
}
|
|
208
257
|
get isOnLast() {
|
|
209
|
-
return this._index === this.
|
|
258
|
+
return this._index === this.getLastIndex();
|
|
210
259
|
}
|
|
211
260
|
get isRecording() {
|
|
212
261
|
return this._history.isRecording;
|
|
213
262
|
}
|
|
214
|
-
get leafMatch() {
|
|
215
|
-
return this._history.leafMatch;
|
|
216
|
-
}
|
|
217
263
|
get rootMatch() {
|
|
218
264
|
return this._history.rootMatch;
|
|
219
265
|
}
|
|
266
|
+
get leafMatch() {
|
|
267
|
+
return this._history.leafMatch;
|
|
268
|
+
}
|
|
220
269
|
get furthestError() {
|
|
221
270
|
return this._history.furthestError;
|
|
222
271
|
}
|
|
@@ -247,14 +296,14 @@ class Cursor {
|
|
|
247
296
|
hasNext() {
|
|
248
297
|
return this._index + 1 < this._length;
|
|
249
298
|
}
|
|
250
|
-
hasPrevious() {
|
|
251
|
-
return this._index - 1 >= 0;
|
|
252
|
-
}
|
|
253
299
|
next() {
|
|
254
300
|
if (this.hasNext()) {
|
|
255
301
|
this._index++;
|
|
256
302
|
}
|
|
257
303
|
}
|
|
304
|
+
hasPrevious() {
|
|
305
|
+
return this._index - 1 >= 0;
|
|
306
|
+
}
|
|
258
307
|
previous() {
|
|
259
308
|
if (this.hasPrevious()) {
|
|
260
309
|
this._index--;
|
|
@@ -269,7 +318,10 @@ class Cursor {
|
|
|
269
318
|
this._index = 0;
|
|
270
319
|
}
|
|
271
320
|
moveToLastChar() {
|
|
272
|
-
this._index = this.
|
|
321
|
+
this._index = this.getLastIndex();
|
|
322
|
+
}
|
|
323
|
+
getLastIndex() {
|
|
324
|
+
return this._length - 1;
|
|
273
325
|
}
|
|
274
326
|
getChars(first, last) {
|
|
275
327
|
return this._text.slice(first, last + 1);
|
|
@@ -289,22 +341,6 @@ class Cursor {
|
|
|
289
341
|
stopRecording() {
|
|
290
342
|
this._history.stopRecording();
|
|
291
343
|
}
|
|
292
|
-
_getLastIndex() {
|
|
293
|
-
return this._length - 1;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function getNextPattern(pattern) {
|
|
298
|
-
const parent = pattern.parent;
|
|
299
|
-
if (parent == null) {
|
|
300
|
-
return null;
|
|
301
|
-
}
|
|
302
|
-
const patternIndex = parent.children.indexOf(pattern);
|
|
303
|
-
const nextPattern = parent.children[patternIndex + 1] || null;
|
|
304
|
-
if (nextPattern == null) {
|
|
305
|
-
return parent.getNextPattern();
|
|
306
|
-
}
|
|
307
|
-
return nextPattern;
|
|
308
344
|
}
|
|
309
345
|
|
|
310
346
|
class Regex {
|
|
@@ -331,8 +367,6 @@ class Regex {
|
|
|
331
367
|
this._cursor = null;
|
|
332
368
|
this._substring = "";
|
|
333
369
|
this._tokens = [];
|
|
334
|
-
this._hasContextualTokenAggregation = false;
|
|
335
|
-
this._isRetrievingContextualTokens = false;
|
|
336
370
|
this._type = "regex";
|
|
337
371
|
this._name = name;
|
|
338
372
|
this._isOptional = isOptional;
|
|
@@ -352,11 +386,16 @@ class Regex {
|
|
|
352
386
|
throw new Error("Invalid Arguments: The regex string cannot end with a '$' because it is expected to be in the middle of a string.");
|
|
353
387
|
}
|
|
354
388
|
}
|
|
355
|
-
|
|
389
|
+
test(text) {
|
|
390
|
+
const cursor = new Cursor(text);
|
|
391
|
+
const ast = this.parse(cursor);
|
|
392
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
393
|
+
}
|
|
394
|
+
exec(text) {
|
|
356
395
|
const cursor = new Cursor(text);
|
|
357
396
|
const ast = this.parse(cursor);
|
|
358
397
|
return {
|
|
359
|
-
ast,
|
|
398
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
360
399
|
cursor
|
|
361
400
|
};
|
|
362
401
|
}
|
|
@@ -383,7 +422,7 @@ class Regex {
|
|
|
383
422
|
processResult(cursor, result) {
|
|
384
423
|
const currentIndex = cursor.index;
|
|
385
424
|
const newIndex = currentIndex + result[0].length - 1;
|
|
386
|
-
this._node = new Node("regex", this._name, currentIndex, newIndex,
|
|
425
|
+
this._node = new Node("regex", this._name, currentIndex, newIndex, undefined, result[0]);
|
|
387
426
|
cursor.moveTo(newIndex);
|
|
388
427
|
cursor.recordMatch(this, this._node);
|
|
389
428
|
}
|
|
@@ -396,47 +435,35 @@ class Regex {
|
|
|
396
435
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
397
436
|
const pattern = new Regex(name, this._originalRegexString, isOptional);
|
|
398
437
|
pattern._tokens = this._tokens.slice();
|
|
399
|
-
pattern._hasContextualTokenAggregation =
|
|
400
|
-
this._hasContextualTokenAggregation;
|
|
401
438
|
return pattern;
|
|
402
439
|
}
|
|
403
440
|
getTokens() {
|
|
404
|
-
const parent = this._parent;
|
|
405
|
-
if (this._hasContextualTokenAggregation &&
|
|
406
|
-
parent != null &&
|
|
407
|
-
!this._isRetrievingContextualTokens) {
|
|
408
|
-
this._isRetrievingContextualTokens = true;
|
|
409
|
-
const tokens = this._tokens;
|
|
410
|
-
const aggregateTokens = [];
|
|
411
|
-
const nextTokens = parent.getNextTokens(this);
|
|
412
|
-
for (let nextToken of nextTokens) {
|
|
413
|
-
for (let token of tokens) {
|
|
414
|
-
aggregateTokens.push(token + nextToken);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
this._isRetrievingContextualTokens = false;
|
|
418
|
-
return aggregateTokens;
|
|
419
|
-
}
|
|
420
441
|
return this._tokens;
|
|
421
442
|
}
|
|
422
|
-
|
|
443
|
+
getTokensAfter(_childReference) {
|
|
423
444
|
return [];
|
|
424
445
|
}
|
|
425
|
-
|
|
426
|
-
|
|
446
|
+
getNextTokens() {
|
|
447
|
+
if (this.parent == null) {
|
|
448
|
+
return [];
|
|
449
|
+
}
|
|
450
|
+
return this.parent.getTokensAfter(this);
|
|
451
|
+
}
|
|
452
|
+
getPatternsAfter(_childReference) {
|
|
453
|
+
return [];
|
|
454
|
+
}
|
|
455
|
+
getNextPatterns() {
|
|
456
|
+
if (this.parent == null) {
|
|
457
|
+
return [];
|
|
458
|
+
}
|
|
459
|
+
return this.parent.getPatternsAfter(this);
|
|
427
460
|
}
|
|
428
|
-
findPattern(
|
|
461
|
+
findPattern(_predicate) {
|
|
429
462
|
return null;
|
|
430
463
|
}
|
|
431
464
|
setTokens(tokens) {
|
|
432
465
|
this._tokens = tokens;
|
|
433
466
|
}
|
|
434
|
-
enableContextualTokenAggregation() {
|
|
435
|
-
this._hasContextualTokenAggregation = true;
|
|
436
|
-
}
|
|
437
|
-
disableContextualTokenAggregation() {
|
|
438
|
-
this._hasContextualTokenAggregation = false;
|
|
439
|
-
}
|
|
440
467
|
}
|
|
441
468
|
|
|
442
469
|
function clonePatterns(patterns, isOptional) {
|
|
@@ -506,7 +533,6 @@ class And {
|
|
|
506
533
|
this._parent = null;
|
|
507
534
|
this._children = children;
|
|
508
535
|
this._firstIndex = -1;
|
|
509
|
-
this._shouldReduceAst = false;
|
|
510
536
|
this._nodes = [];
|
|
511
537
|
}
|
|
512
538
|
_assignChildrenToParent(children) {
|
|
@@ -514,11 +540,16 @@ class And {
|
|
|
514
540
|
child.parent = this;
|
|
515
541
|
}
|
|
516
542
|
}
|
|
517
|
-
|
|
543
|
+
test(text) {
|
|
544
|
+
const cursor = new Cursor(text);
|
|
545
|
+
const ast = this.parse(cursor);
|
|
546
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
547
|
+
}
|
|
548
|
+
exec(text) {
|
|
518
549
|
const cursor = new Cursor(text);
|
|
519
550
|
const ast = this.parse(cursor);
|
|
520
551
|
return {
|
|
521
|
-
ast,
|
|
552
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
522
553
|
cursor
|
|
523
554
|
};
|
|
524
555
|
}
|
|
@@ -552,34 +583,43 @@ class And {
|
|
|
552
583
|
if (hasMorePatterns) {
|
|
553
584
|
if (hadMatch) {
|
|
554
585
|
if (cursor.hasNext()) {
|
|
586
|
+
// We had a match. Increment the cursor and use the next pattern.
|
|
555
587
|
cursor.next();
|
|
556
588
|
continue;
|
|
557
589
|
}
|
|
558
590
|
else {
|
|
591
|
+
// We are at the end of the text, it may still be valid, if all the
|
|
592
|
+
// following patterns are optional.
|
|
559
593
|
if (this.areRemainingPatternsOptional(i)) {
|
|
560
594
|
passed = true;
|
|
561
595
|
break;
|
|
562
596
|
}
|
|
597
|
+
// We didn't finish the parsing sequence.
|
|
563
598
|
cursor.recordErrorAt(cursor.index + 1, this);
|
|
564
599
|
break;
|
|
565
600
|
}
|
|
566
601
|
}
|
|
567
602
|
else {
|
|
603
|
+
// An optional pattern did not matched, try from the same spot on the next
|
|
604
|
+
// pattern.
|
|
568
605
|
cursor.moveTo(runningCursorIndex);
|
|
569
606
|
continue;
|
|
570
607
|
}
|
|
571
608
|
}
|
|
572
609
|
else {
|
|
610
|
+
// If we don't have any results from what we parsed then record error.
|
|
573
611
|
const lastNode = this.getLastValidNode();
|
|
574
612
|
if (lastNode === null) {
|
|
575
613
|
cursor.recordErrorAt(cursor.index, this);
|
|
576
614
|
break;
|
|
577
615
|
}
|
|
616
|
+
// The sequence was parsed fully.
|
|
578
617
|
passed = true;
|
|
579
618
|
break;
|
|
580
619
|
}
|
|
581
620
|
}
|
|
582
621
|
else {
|
|
622
|
+
// The pattern failed.
|
|
583
623
|
cursor.moveTo(this._firstIndex);
|
|
584
624
|
break;
|
|
585
625
|
}
|
|
@@ -607,18 +647,9 @@ class And {
|
|
|
607
647
|
createNode(cursor) {
|
|
608
648
|
const children = filterOutNull(this._nodes);
|
|
609
649
|
const lastIndex = children[children.length - 1].lastIndex;
|
|
610
|
-
|
|
650
|
+
cursor.getChars(this._firstIndex, lastIndex);
|
|
611
651
|
cursor.moveTo(lastIndex);
|
|
612
|
-
|
|
613
|
-
children.length = 0;
|
|
614
|
-
}
|
|
615
|
-
return new Node("and", this._name, this._firstIndex, lastIndex, children, this._shouldReduceAst ? value : undefined);
|
|
616
|
-
}
|
|
617
|
-
enableAstReduction() {
|
|
618
|
-
this._shouldReduceAst = true;
|
|
619
|
-
}
|
|
620
|
-
disableAstReduction() {
|
|
621
|
-
this._shouldReduceAst = false;
|
|
652
|
+
return new Node("and", this._name, this._firstIndex, lastIndex, children);
|
|
622
653
|
}
|
|
623
654
|
getTokens() {
|
|
624
655
|
const tokens = [];
|
|
@@ -630,13 +661,25 @@ class And {
|
|
|
630
661
|
}
|
|
631
662
|
return tokens;
|
|
632
663
|
}
|
|
633
|
-
|
|
664
|
+
getTokensAfter(childReference) {
|
|
665
|
+
const patterns = this.getPatternsAfter(childReference);
|
|
666
|
+
const tokens = [];
|
|
667
|
+
patterns.forEach(p => tokens.push(...p.getTokens()));
|
|
668
|
+
return tokens;
|
|
669
|
+
}
|
|
670
|
+
getNextTokens() {
|
|
671
|
+
if (this.parent == null) {
|
|
672
|
+
return [];
|
|
673
|
+
}
|
|
674
|
+
return this.parent.getTokensAfter(this);
|
|
675
|
+
}
|
|
676
|
+
getPatternsAfter(childReference) {
|
|
634
677
|
let nextSibling = null;
|
|
635
678
|
let nextSiblingIndex = -1;
|
|
636
679
|
let index = -1;
|
|
637
|
-
const
|
|
680
|
+
const patterns = [];
|
|
638
681
|
for (let i = 0; i < this._children.length; i++) {
|
|
639
|
-
if (this._children[i] ===
|
|
682
|
+
if (this._children[i] === childReference) {
|
|
640
683
|
if (i + 1 < this._children.length) {
|
|
641
684
|
nextSibling = this._children[i + 1];
|
|
642
685
|
}
|
|
@@ -645,39 +688,44 @@ class And {
|
|
|
645
688
|
break;
|
|
646
689
|
}
|
|
647
690
|
}
|
|
691
|
+
// The child reference isn't one of the child patterns.
|
|
648
692
|
if (index === -1) {
|
|
649
693
|
return [];
|
|
650
694
|
}
|
|
695
|
+
// The reference pattern is the last child. So ask the parent for the next pattern.
|
|
651
696
|
if (nextSiblingIndex === this._children.length && this._parent !== null) {
|
|
652
|
-
return this._parent.
|
|
697
|
+
return this._parent.getPatternsAfter(this);
|
|
653
698
|
}
|
|
699
|
+
// Next pattern isn't optional so send it back as the next patterns.
|
|
654
700
|
if (nextSibling !== null && !nextSibling.isOptional) {
|
|
655
|
-
return nextSibling
|
|
701
|
+
return [nextSibling];
|
|
656
702
|
}
|
|
703
|
+
// Send back as many optional patterns as possible.
|
|
657
704
|
if (nextSibling !== null && nextSibling.isOptional) {
|
|
658
705
|
for (let i = nextSiblingIndex; i < this._children.length; i++) {
|
|
659
706
|
const child = this._children[i];
|
|
660
|
-
|
|
707
|
+
patterns.push(child);
|
|
661
708
|
if (!child.isOptional) {
|
|
662
709
|
break;
|
|
663
710
|
}
|
|
664
711
|
if (i === this._children.length - 1 && this._parent !== null) {
|
|
665
|
-
|
|
712
|
+
patterns.push(...this._parent.getPatternsAfter(this));
|
|
666
713
|
}
|
|
667
714
|
}
|
|
668
715
|
}
|
|
669
|
-
return
|
|
716
|
+
return patterns;
|
|
670
717
|
}
|
|
671
|
-
|
|
672
|
-
|
|
718
|
+
getNextPatterns() {
|
|
719
|
+
if (this.parent == null) {
|
|
720
|
+
return [];
|
|
721
|
+
}
|
|
722
|
+
return this.parent.getPatternsAfter(this);
|
|
673
723
|
}
|
|
674
|
-
findPattern(
|
|
675
|
-
return findPattern(this,
|
|
724
|
+
findPattern(predicate) {
|
|
725
|
+
return findPattern(this, predicate);
|
|
676
726
|
}
|
|
677
727
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
678
|
-
|
|
679
|
-
and._shouldReduceAst = this._shouldReduceAst;
|
|
680
|
-
return and;
|
|
728
|
+
return new And(name, this._children, isOptional);
|
|
681
729
|
}
|
|
682
730
|
}
|
|
683
731
|
|
|
@@ -712,14 +760,17 @@ class Literal {
|
|
|
712
760
|
this._parent = null;
|
|
713
761
|
this._firstIndex = 0;
|
|
714
762
|
this._lastIndex = 0;
|
|
715
|
-
this._hasContextualTokenAggregation = false;
|
|
716
|
-
this._isRetrievingContextualTokens = false;
|
|
717
763
|
}
|
|
718
|
-
|
|
764
|
+
test(text) {
|
|
765
|
+
const cursor = new Cursor(text);
|
|
766
|
+
const ast = this.parse(cursor);
|
|
767
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
768
|
+
}
|
|
769
|
+
exec(text) {
|
|
719
770
|
const cursor = new Cursor(text);
|
|
720
771
|
const ast = this.parse(cursor);
|
|
721
772
|
return {
|
|
722
|
-
ast,
|
|
773
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
723
774
|
cursor
|
|
724
775
|
};
|
|
725
776
|
}
|
|
@@ -762,45 +813,35 @@ class Literal {
|
|
|
762
813
|
return passed;
|
|
763
814
|
}
|
|
764
815
|
_createNode() {
|
|
765
|
-
return new Node("literal", this._name, this._firstIndex, this._lastIndex,
|
|
816
|
+
return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
|
|
766
817
|
}
|
|
767
818
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
768
819
|
const clone = new Literal(name, this._literal, isOptional);
|
|
769
|
-
clone._hasContextualTokenAggregation = this._hasContextualTokenAggregation;
|
|
770
820
|
return clone;
|
|
771
821
|
}
|
|
772
822
|
getTokens() {
|
|
773
|
-
|
|
774
|
-
if (this._hasContextualTokenAggregation &&
|
|
775
|
-
parent != null &&
|
|
776
|
-
!this._isRetrievingContextualTokens) {
|
|
777
|
-
this._isRetrievingContextualTokens = true;
|
|
778
|
-
const aggregateTokens = [];
|
|
779
|
-
const nextTokens = parent.getNextTokens(this);
|
|
780
|
-
for (const nextToken of nextTokens) {
|
|
781
|
-
aggregateTokens.push(this._literal + nextToken);
|
|
782
|
-
}
|
|
783
|
-
this._isRetrievingContextualTokens = false;
|
|
784
|
-
return aggregateTokens;
|
|
785
|
-
}
|
|
786
|
-
else {
|
|
787
|
-
return [this._literal];
|
|
788
|
-
}
|
|
823
|
+
return [this._literal];
|
|
789
824
|
}
|
|
790
|
-
|
|
825
|
+
getTokensAfter(_lastMatched) {
|
|
791
826
|
return [];
|
|
792
827
|
}
|
|
793
|
-
|
|
794
|
-
|
|
828
|
+
getNextTokens() {
|
|
829
|
+
if (this.parent == null) {
|
|
830
|
+
return [];
|
|
831
|
+
}
|
|
832
|
+
return this.parent.getTokensAfter(this);
|
|
795
833
|
}
|
|
796
|
-
|
|
797
|
-
return
|
|
834
|
+
getPatternsAfter() {
|
|
835
|
+
return [];
|
|
798
836
|
}
|
|
799
|
-
|
|
800
|
-
this.
|
|
837
|
+
getNextPatterns() {
|
|
838
|
+
if (this.parent == null) {
|
|
839
|
+
return [];
|
|
840
|
+
}
|
|
841
|
+
return this.parent.getPatternsAfter(this);
|
|
801
842
|
}
|
|
802
|
-
|
|
803
|
-
|
|
843
|
+
findPattern(_predicate) {
|
|
844
|
+
return null;
|
|
804
845
|
}
|
|
805
846
|
}
|
|
806
847
|
|
|
@@ -811,9 +852,6 @@ class Not {
|
|
|
811
852
|
get name() {
|
|
812
853
|
return this._name;
|
|
813
854
|
}
|
|
814
|
-
get isOptional() {
|
|
815
|
-
return false;
|
|
816
|
-
}
|
|
817
855
|
get parent() {
|
|
818
856
|
return this._parent;
|
|
819
857
|
}
|
|
@@ -823,6 +861,9 @@ class Not {
|
|
|
823
861
|
get children() {
|
|
824
862
|
return this._children;
|
|
825
863
|
}
|
|
864
|
+
get isOptional() {
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
826
867
|
constructor(name, pattern) {
|
|
827
868
|
this._type = "not";
|
|
828
869
|
this._name = name;
|
|
@@ -830,7 +871,12 @@ class Not {
|
|
|
830
871
|
this._children = [pattern.clone(pattern.name, false)];
|
|
831
872
|
this._children[0].parent = this;
|
|
832
873
|
}
|
|
833
|
-
|
|
874
|
+
test(text) {
|
|
875
|
+
const cursor = new Cursor(text);
|
|
876
|
+
this.parse(cursor);
|
|
877
|
+
return !cursor.hasError;
|
|
878
|
+
}
|
|
879
|
+
exec(text) {
|
|
834
880
|
const cursor = new Cursor(text);
|
|
835
881
|
const ast = this.parse(cursor);
|
|
836
882
|
return {
|
|
@@ -856,17 +902,41 @@ class Not {
|
|
|
856
902
|
const not = new Not(name, this._children[0]);
|
|
857
903
|
return not;
|
|
858
904
|
}
|
|
859
|
-
getNextPattern() {
|
|
860
|
-
return getNextPattern(this);
|
|
861
|
-
}
|
|
862
905
|
getTokens() {
|
|
906
|
+
const parent = this._parent;
|
|
907
|
+
if (parent != null) {
|
|
908
|
+
return parent.getTokensAfter(this);
|
|
909
|
+
}
|
|
863
910
|
return [];
|
|
864
911
|
}
|
|
865
|
-
|
|
912
|
+
getTokensAfter(_childReference) {
|
|
913
|
+
const parent = this._parent;
|
|
914
|
+
if (parent != null) {
|
|
915
|
+
return parent.getTokensAfter(this);
|
|
916
|
+
}
|
|
866
917
|
return [];
|
|
867
918
|
}
|
|
868
|
-
|
|
869
|
-
|
|
919
|
+
getNextTokens() {
|
|
920
|
+
if (this.parent == null) {
|
|
921
|
+
return [];
|
|
922
|
+
}
|
|
923
|
+
return this.parent.getTokensAfter(this);
|
|
924
|
+
}
|
|
925
|
+
getPatternsAfter(_childReference) {
|
|
926
|
+
const parent = this._parent;
|
|
927
|
+
if (parent != null) {
|
|
928
|
+
return parent.getPatternsAfter(this);
|
|
929
|
+
}
|
|
930
|
+
return [];
|
|
931
|
+
}
|
|
932
|
+
getNextPatterns() {
|
|
933
|
+
if (this.parent == null) {
|
|
934
|
+
return [];
|
|
935
|
+
}
|
|
936
|
+
return this.parent.getPatternsAfter(this);
|
|
937
|
+
}
|
|
938
|
+
findPattern(predicate) {
|
|
939
|
+
return predicate(this._children[0]) ? this._children[0] : null;
|
|
870
940
|
}
|
|
871
941
|
}
|
|
872
942
|
|
|
@@ -900,7 +970,6 @@ class Or {
|
|
|
900
970
|
this._parent = null;
|
|
901
971
|
this._children = children;
|
|
902
972
|
this._isOptional = isOptional;
|
|
903
|
-
this._node = null;
|
|
904
973
|
this._firstIndex = 0;
|
|
905
974
|
}
|
|
906
975
|
_assignChildrenToParent(children) {
|
|
@@ -908,17 +977,21 @@ class Or {
|
|
|
908
977
|
child.parent = this;
|
|
909
978
|
}
|
|
910
979
|
}
|
|
911
|
-
|
|
980
|
+
test(text) {
|
|
981
|
+
const cursor = new Cursor(text);
|
|
982
|
+
const ast = this.parse(cursor);
|
|
983
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
984
|
+
}
|
|
985
|
+
exec(text) {
|
|
912
986
|
const cursor = new Cursor(text);
|
|
913
987
|
const ast = this.parse(cursor);
|
|
914
988
|
return {
|
|
915
|
-
ast,
|
|
989
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
916
990
|
cursor
|
|
917
991
|
};
|
|
918
992
|
}
|
|
919
993
|
parse(cursor) {
|
|
920
994
|
this._firstIndex = cursor.index;
|
|
921
|
-
this._node = null;
|
|
922
995
|
const node = this._tryToParse(cursor);
|
|
923
996
|
if (node != null) {
|
|
924
997
|
cursor.resolveError();
|
|
@@ -950,17 +1023,32 @@ class Or {
|
|
|
950
1023
|
}
|
|
951
1024
|
return tokens;
|
|
952
1025
|
}
|
|
953
|
-
|
|
1026
|
+
getTokensAfter(_childReference) {
|
|
954
1027
|
if (this._parent === null) {
|
|
955
1028
|
return [];
|
|
956
1029
|
}
|
|
957
|
-
return this._parent.
|
|
1030
|
+
return this._parent.getTokensAfter(this);
|
|
958
1031
|
}
|
|
959
|
-
|
|
960
|
-
|
|
1032
|
+
getNextTokens() {
|
|
1033
|
+
if (this._parent == null) {
|
|
1034
|
+
return [];
|
|
1035
|
+
}
|
|
1036
|
+
return this._parent.getTokensAfter(this);
|
|
1037
|
+
}
|
|
1038
|
+
getPatternsAfter(_childReference) {
|
|
1039
|
+
if (this._parent === null) {
|
|
1040
|
+
return [];
|
|
1041
|
+
}
|
|
1042
|
+
return this._parent.getPatternsAfter(this);
|
|
1043
|
+
}
|
|
1044
|
+
getNextPatterns() {
|
|
1045
|
+
if (this.parent == null) {
|
|
1046
|
+
return [];
|
|
1047
|
+
}
|
|
1048
|
+
return this.parent.getPatternsAfter(this);
|
|
961
1049
|
}
|
|
962
|
-
findPattern(
|
|
963
|
-
return findPattern(this,
|
|
1050
|
+
findPattern(predicate) {
|
|
1051
|
+
return findPattern(this, predicate);
|
|
964
1052
|
}
|
|
965
1053
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
966
1054
|
const or = new Or(name, this._children, isOptional);
|
|
@@ -999,7 +1087,6 @@ class Repeat {
|
|
|
999
1087
|
this._pattern = children[0];
|
|
1000
1088
|
this._divider = children[1];
|
|
1001
1089
|
this._firstIndex = -1;
|
|
1002
|
-
this._shouldReduceAst = false;
|
|
1003
1090
|
this._nodes = [];
|
|
1004
1091
|
}
|
|
1005
1092
|
_assignChildrenToParent(children) {
|
|
@@ -1007,11 +1094,16 @@ class Repeat {
|
|
|
1007
1094
|
child.parent = this;
|
|
1008
1095
|
}
|
|
1009
1096
|
}
|
|
1010
|
-
|
|
1097
|
+
test(text) {
|
|
1098
|
+
const cursor = new Cursor(text);
|
|
1099
|
+
const ast = this.parse(cursor);
|
|
1100
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1101
|
+
}
|
|
1102
|
+
exec(text) {
|
|
1011
1103
|
const cursor = new Cursor(text);
|
|
1012
1104
|
const ast = this.parse(cursor);
|
|
1013
1105
|
return {
|
|
1014
|
-
ast,
|
|
1106
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1015
1107
|
cursor
|
|
1016
1108
|
};
|
|
1017
1109
|
}
|
|
@@ -1022,7 +1114,7 @@ class Repeat {
|
|
|
1022
1114
|
if (passed) {
|
|
1023
1115
|
cursor.resolveError();
|
|
1024
1116
|
const node = this.createNode(cursor);
|
|
1025
|
-
if (node) {
|
|
1117
|
+
if (node != null) {
|
|
1026
1118
|
cursor.recordMatch(this, node);
|
|
1027
1119
|
}
|
|
1028
1120
|
return node;
|
|
@@ -1041,7 +1133,7 @@ class Repeat {
|
|
|
1041
1133
|
const repeatedNode = this._pattern.parse(cursor);
|
|
1042
1134
|
if (cursor.hasError) {
|
|
1043
1135
|
const lastValidNode = this.getLastValidNode();
|
|
1044
|
-
if (lastValidNode) {
|
|
1136
|
+
if (lastValidNode != null) {
|
|
1045
1137
|
passed = true;
|
|
1046
1138
|
}
|
|
1047
1139
|
else {
|
|
@@ -1058,13 +1150,13 @@ class Repeat {
|
|
|
1058
1150
|
break;
|
|
1059
1151
|
}
|
|
1060
1152
|
cursor.next();
|
|
1061
|
-
if (this._divider) {
|
|
1153
|
+
if (this._divider != null) {
|
|
1062
1154
|
const dividerNode = this._divider.parse(cursor);
|
|
1063
1155
|
if (cursor.hasError) {
|
|
1064
1156
|
passed = true;
|
|
1065
1157
|
break;
|
|
1066
1158
|
}
|
|
1067
|
-
else if (dividerNode) {
|
|
1159
|
+
else if (dividerNode != null) {
|
|
1068
1160
|
this._nodes.push(dividerNode);
|
|
1069
1161
|
if (!cursor.hasNext()) {
|
|
1070
1162
|
passed = true;
|
|
@@ -1093,12 +1185,9 @@ class Repeat {
|
|
|
1093
1185
|
}
|
|
1094
1186
|
}
|
|
1095
1187
|
const lastIndex = children[children.length - 1].lastIndex;
|
|
1096
|
-
|
|
1188
|
+
cursor.getChars(this._firstIndex, lastIndex);
|
|
1097
1189
|
cursor.moveTo(lastIndex);
|
|
1098
|
-
|
|
1099
|
-
children = [];
|
|
1100
|
-
}
|
|
1101
|
-
return new Node("repeat", this._name, this._firstIndex, lastIndex, children, this._shouldReduceAst ? value : undefined);
|
|
1190
|
+
return new Node("repeat", this._name, this._firstIndex, lastIndex, children, undefined);
|
|
1102
1191
|
}
|
|
1103
1192
|
getLastValidNode() {
|
|
1104
1193
|
const nodes = this._nodes.filter((node) => node !== null);
|
|
@@ -1107,51 +1196,61 @@ class Repeat {
|
|
|
1107
1196
|
}
|
|
1108
1197
|
return nodes[nodes.length - 1];
|
|
1109
1198
|
}
|
|
1110
|
-
enableAstReduction() {
|
|
1111
|
-
this._shouldReduceAst = true;
|
|
1112
|
-
}
|
|
1113
|
-
disableAstReduction() {
|
|
1114
|
-
this._shouldReduceAst = false;
|
|
1115
|
-
}
|
|
1116
1199
|
getTokens() {
|
|
1117
1200
|
return this._pattern.getTokens();
|
|
1118
1201
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1202
|
+
getTokensAfter(childReference) {
|
|
1203
|
+
const patterns = this.getPatternsAfter(childReference);
|
|
1121
1204
|
const tokens = [];
|
|
1205
|
+
patterns.forEach(p => tokens.push(...p.getTokens()));
|
|
1206
|
+
return tokens;
|
|
1207
|
+
}
|
|
1208
|
+
getNextTokens() {
|
|
1209
|
+
if (this.parent == null) {
|
|
1210
|
+
return [];
|
|
1211
|
+
}
|
|
1212
|
+
return this.parent.getTokensAfter(this);
|
|
1213
|
+
}
|
|
1214
|
+
getPatternsAfter(childReference) {
|
|
1215
|
+
let index = -1;
|
|
1216
|
+
const patterns = [];
|
|
1122
1217
|
for (let i = 0; i < this._children.length; i++) {
|
|
1123
|
-
if (this._children[i] ===
|
|
1218
|
+
if (this._children[i] === childReference) {
|
|
1124
1219
|
index = i;
|
|
1125
1220
|
}
|
|
1126
1221
|
}
|
|
1222
|
+
// If the last match isn't a child of this pattern.
|
|
1127
1223
|
if (index === -1) {
|
|
1128
1224
|
return [];
|
|
1129
1225
|
}
|
|
1226
|
+
// If the last match was the repeated patterns, then suggest the divider.
|
|
1130
1227
|
if (index === 0 && this._divider) {
|
|
1131
|
-
|
|
1228
|
+
patterns.push(this._children[1]);
|
|
1132
1229
|
if (this._parent) {
|
|
1133
|
-
|
|
1230
|
+
patterns.push(...this._parent.getPatternsAfter(this));
|
|
1134
1231
|
}
|
|
1135
1232
|
}
|
|
1233
|
+
// Suggest the pattern because the divider was the last match.
|
|
1136
1234
|
if (index === 1) {
|
|
1137
|
-
|
|
1235
|
+
patterns.push(this._children[0]);
|
|
1138
1236
|
}
|
|
1139
1237
|
if (index === 0 && !this._divider && this._parent) {
|
|
1140
|
-
|
|
1141
|
-
|
|
1238
|
+
patterns.push(this._children[0]);
|
|
1239
|
+
patterns.push(...this._parent.getPatternsAfter(this));
|
|
1142
1240
|
}
|
|
1143
|
-
return
|
|
1241
|
+
return patterns;
|
|
1144
1242
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1243
|
+
getNextPatterns() {
|
|
1244
|
+
if (this.parent == null) {
|
|
1245
|
+
return [];
|
|
1246
|
+
}
|
|
1247
|
+
return this.parent.getPatternsAfter(this);
|
|
1147
1248
|
}
|
|
1148
|
-
findPattern(
|
|
1149
|
-
return findPattern(this,
|
|
1249
|
+
findPattern(predicate) {
|
|
1250
|
+
return findPattern(this, predicate);
|
|
1150
1251
|
}
|
|
1151
1252
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
1152
|
-
|
|
1153
|
-
repeat._shouldReduceAst = this._shouldReduceAst;
|
|
1154
|
-
return repeat;
|
|
1253
|
+
return new Repeat(name, this._pattern, this._divider, isOptional);
|
|
1155
1254
|
}
|
|
1156
1255
|
}
|
|
1157
1256
|
|
|
@@ -1162,9 +1261,6 @@ class Reference {
|
|
|
1162
1261
|
get name() {
|
|
1163
1262
|
return this._name;
|
|
1164
1263
|
}
|
|
1165
|
-
get isOptional() {
|
|
1166
|
-
return this._isOptional;
|
|
1167
|
-
}
|
|
1168
1264
|
get parent() {
|
|
1169
1265
|
return this._parent;
|
|
1170
1266
|
}
|
|
@@ -1174,6 +1270,9 @@ class Reference {
|
|
|
1174
1270
|
get children() {
|
|
1175
1271
|
return this._children;
|
|
1176
1272
|
}
|
|
1273
|
+
get isOptional() {
|
|
1274
|
+
return this._isOptional;
|
|
1275
|
+
}
|
|
1177
1276
|
constructor(name, isOptional = false) {
|
|
1178
1277
|
this._type = "reference";
|
|
1179
1278
|
this._name = name;
|
|
@@ -1182,35 +1281,22 @@ class Reference {
|
|
|
1182
1281
|
this._pattern = null;
|
|
1183
1282
|
this._children = [];
|
|
1184
1283
|
}
|
|
1185
|
-
|
|
1284
|
+
test(text) {
|
|
1285
|
+
const cursor = new Cursor(text);
|
|
1286
|
+
const ast = this.parse(cursor);
|
|
1287
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1288
|
+
}
|
|
1289
|
+
exec(text) {
|
|
1186
1290
|
const cursor = new Cursor(text);
|
|
1187
1291
|
const ast = this.parse(cursor);
|
|
1188
1292
|
return {
|
|
1189
|
-
ast,
|
|
1293
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1190
1294
|
cursor
|
|
1191
1295
|
};
|
|
1192
1296
|
}
|
|
1193
1297
|
parse(cursor) {
|
|
1194
1298
|
return this._getPatternSafely().parse(cursor);
|
|
1195
1299
|
}
|
|
1196
|
-
clone(name = this._name, isOptional = this._isOptional) {
|
|
1197
|
-
return new Reference(name, isOptional);
|
|
1198
|
-
}
|
|
1199
|
-
getTokens() {
|
|
1200
|
-
return this._getPatternSafely().getTokens();
|
|
1201
|
-
}
|
|
1202
|
-
getNextTokens(_lastMatched) {
|
|
1203
|
-
if (this.parent == null) {
|
|
1204
|
-
return [];
|
|
1205
|
-
}
|
|
1206
|
-
return this.parent.getNextTokens(this);
|
|
1207
|
-
}
|
|
1208
|
-
getNextPattern() {
|
|
1209
|
-
return getNextPattern(this);
|
|
1210
|
-
}
|
|
1211
|
-
findPattern(_isMatch) {
|
|
1212
|
-
return null;
|
|
1213
|
-
}
|
|
1214
1300
|
_getPatternSafely() {
|
|
1215
1301
|
if (this._pattern === null) {
|
|
1216
1302
|
const pattern = this._findPattern();
|
|
@@ -1243,7 +1329,184 @@ class Reference {
|
|
|
1243
1329
|
}
|
|
1244
1330
|
return node;
|
|
1245
1331
|
}
|
|
1332
|
+
getTokens() {
|
|
1333
|
+
return this._getPatternSafely().getTokens();
|
|
1334
|
+
}
|
|
1335
|
+
getTokensAfter(_lastMatched) {
|
|
1336
|
+
if (this._parent == null) {
|
|
1337
|
+
return [];
|
|
1338
|
+
}
|
|
1339
|
+
return this._parent.getTokensAfter(this);
|
|
1340
|
+
}
|
|
1341
|
+
getNextTokens() {
|
|
1342
|
+
if (this.parent == null) {
|
|
1343
|
+
return [];
|
|
1344
|
+
}
|
|
1345
|
+
return this.parent.getTokensAfter(this);
|
|
1346
|
+
}
|
|
1347
|
+
getPatternsAfter(_childReference) {
|
|
1348
|
+
if (this._parent == null) {
|
|
1349
|
+
return [];
|
|
1350
|
+
}
|
|
1351
|
+
return this._parent.getPatternsAfter(this);
|
|
1352
|
+
}
|
|
1353
|
+
getNextPatterns() {
|
|
1354
|
+
if (this.parent == null) {
|
|
1355
|
+
return [];
|
|
1356
|
+
}
|
|
1357
|
+
return this.parent.getPatternsAfter(this);
|
|
1358
|
+
}
|
|
1359
|
+
findPattern(_predicate) {
|
|
1360
|
+
return null;
|
|
1361
|
+
}
|
|
1362
|
+
clone(name = this._name, isOptional = this._isOptional) {
|
|
1363
|
+
return new Reference(name, isOptional);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
const defaultOptions = { greedyPatternNames: [], customTokens: {} };
|
|
1368
|
+
class AutoComplete {
|
|
1369
|
+
constructor(pattern, options = defaultOptions) {
|
|
1370
|
+
this._pattern = pattern;
|
|
1371
|
+
this._options = options;
|
|
1372
|
+
this._text = "";
|
|
1373
|
+
}
|
|
1374
|
+
suggest(text) {
|
|
1375
|
+
if (text.length === 0) {
|
|
1376
|
+
return {
|
|
1377
|
+
isComplete: false,
|
|
1378
|
+
options: this.createSuggestionsFromRoot(),
|
|
1379
|
+
nextPatterns: [this._pattern],
|
|
1380
|
+
cursor: null,
|
|
1381
|
+
ast: null
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
this._text = text;
|
|
1385
|
+
this._cursor = new Cursor(text);
|
|
1386
|
+
const ast = this._pattern.parse(this._cursor);
|
|
1387
|
+
const leafPattern = this._cursor.leafMatch.pattern;
|
|
1388
|
+
const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1389
|
+
const options = this.createSuggestionsFromTokens();
|
|
1390
|
+
let nextPatterns = [this._pattern];
|
|
1391
|
+
if (leafPattern != null) {
|
|
1392
|
+
nextPatterns = leafPattern.getNextPatterns();
|
|
1393
|
+
}
|
|
1394
|
+
return {
|
|
1395
|
+
isComplete: isComplete,
|
|
1396
|
+
options: options,
|
|
1397
|
+
nextPatterns,
|
|
1398
|
+
cursor: this._cursor,
|
|
1399
|
+
ast,
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
createSuggestionsFromRoot() {
|
|
1403
|
+
const suggestions = [];
|
|
1404
|
+
const tokens = this._pattern.getTokens();
|
|
1405
|
+
for (const token of tokens) {
|
|
1406
|
+
suggestions.push(this.createSuggestion("", token));
|
|
1407
|
+
}
|
|
1408
|
+
return suggestions;
|
|
1409
|
+
}
|
|
1410
|
+
createSuggestionsFromTokens() {
|
|
1411
|
+
const leafMatch = this._cursor.leafMatch;
|
|
1412
|
+
if (!leafMatch.pattern) {
|
|
1413
|
+
return this.createSuggestions(-1, this._getTokensForPattern(this._pattern));
|
|
1414
|
+
}
|
|
1415
|
+
const leafPattern = leafMatch.pattern;
|
|
1416
|
+
leafMatch.node;
|
|
1417
|
+
const parent = leafMatch.pattern.parent;
|
|
1418
|
+
if (parent !== null && leafMatch.node != null) {
|
|
1419
|
+
const patterns = leafPattern.getNextPatterns();
|
|
1420
|
+
const tokens = patterns.reduce((acc, pattern) => {
|
|
1421
|
+
acc.push(...this._getTokensForPattern(pattern));
|
|
1422
|
+
return acc;
|
|
1423
|
+
}, []);
|
|
1424
|
+
return this.createSuggestions(leafMatch.node.lastIndex, tokens);
|
|
1425
|
+
}
|
|
1426
|
+
else {
|
|
1427
|
+
return [];
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
_getTokensForPattern(pattern) {
|
|
1431
|
+
if (this._options.greedyPatternNames.includes(pattern.name)) {
|
|
1432
|
+
const greedyTokens = pattern.getTokens();
|
|
1433
|
+
const nextPatterns = pattern.getNextPatterns();
|
|
1434
|
+
const tokens = [];
|
|
1435
|
+
const nextPatternTokens = nextPatterns.reduce((acc, pattern) => {
|
|
1436
|
+
acc.push(...this._getTokensForPattern(pattern));
|
|
1437
|
+
return acc;
|
|
1438
|
+
}, []);
|
|
1439
|
+
for (let token of greedyTokens) {
|
|
1440
|
+
for (let nextPatternToken of nextPatternTokens) {
|
|
1441
|
+
tokens.push(token + nextPatternToken);
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
return tokens;
|
|
1445
|
+
}
|
|
1446
|
+
else {
|
|
1447
|
+
const tokens = pattern.getTokens();
|
|
1448
|
+
const customTokens = this._options.customTokens[pattern.name] || [];
|
|
1449
|
+
tokens.push(...customTokens);
|
|
1450
|
+
return tokens;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
createSuggestions(lastIndex, tokens) {
|
|
1454
|
+
let substring = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
|
|
1455
|
+
const suggestionStrings = [];
|
|
1456
|
+
const options = [];
|
|
1457
|
+
for (const token of tokens) {
|
|
1458
|
+
const suggestion = substring + token;
|
|
1459
|
+
const startsWith = suggestion.startsWith(substring);
|
|
1460
|
+
const alreadyExist = suggestionStrings.includes(suggestion);
|
|
1461
|
+
const isSameAsText = suggestion === this._text;
|
|
1462
|
+
if (startsWith && !alreadyExist && !isSameAsText) {
|
|
1463
|
+
suggestionStrings.push(suggestion);
|
|
1464
|
+
options.push(this.createSuggestion(this._cursor.text, suggestion));
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
const reducedOptions = getFurthestOptions(options);
|
|
1468
|
+
reducedOptions.sort((a, b) => a.text.localeCompare(b.text));
|
|
1469
|
+
return reducedOptions;
|
|
1470
|
+
}
|
|
1471
|
+
createSuggestion(fullText, suggestion) {
|
|
1472
|
+
const furthestMatch = findMatchIndex(suggestion, fullText);
|
|
1473
|
+
const text = suggestion.slice(furthestMatch);
|
|
1474
|
+
return {
|
|
1475
|
+
text: text,
|
|
1476
|
+
startIndex: furthestMatch,
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
function findMatchIndex(str1, str2) {
|
|
1481
|
+
let matchCount = 0;
|
|
1482
|
+
let minLength = str1.length;
|
|
1483
|
+
if (str2.length < minLength) {
|
|
1484
|
+
minLength = str2.length;
|
|
1485
|
+
}
|
|
1486
|
+
for (let i = 0; i < minLength; i++) {
|
|
1487
|
+
if (str1[i] === str2[i]) {
|
|
1488
|
+
matchCount++;
|
|
1489
|
+
}
|
|
1490
|
+
else {
|
|
1491
|
+
break;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
return matchCount;
|
|
1495
|
+
}
|
|
1496
|
+
function getFurthestOptions(options) {
|
|
1497
|
+
let furthestOptions = [];
|
|
1498
|
+
let furthestIndex = -1;
|
|
1499
|
+
for (const option of options) {
|
|
1500
|
+
if (option.startIndex > furthestIndex) {
|
|
1501
|
+
furthestIndex = option.startIndex;
|
|
1502
|
+
furthestOptions = [];
|
|
1503
|
+
}
|
|
1504
|
+
if (option.startIndex === furthestIndex) {
|
|
1505
|
+
furthestOptions.push(option);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
return furthestOptions;
|
|
1246
1509
|
}
|
|
1247
1510
|
|
|
1248
|
-
export { And, Cursor, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat };
|
|
1511
|
+
export { And, AutoComplete, Cursor, CursorHistory, Literal, Node, Not, Or, ParseError, Reference, Regex, Repeat };
|
|
1249
1512
|
//# sourceMappingURL=index.esm.js.map
|