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