clarity-pattern-parser 5.0.0 → 6.0.2
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 +63 -7
- package/dist/ast/Node.d.ts +8 -2
- package/dist/index.browser.js +520 -205
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.esm.js +519 -206
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +520 -205
- package/dist/index.js.map +1 -1
- package/dist/intellisense/AutoComplete.d.ts +34 -0
- package/dist/intellisense/Suggestion.d.ts +10 -0
- package/dist/intellisense/SuggestionOption.d.ts +4 -0
- package/dist/patterns/And.d.ts +8 -7
- package/dist/patterns/Cursor.d.ts +6 -4
- package/dist/patterns/CursorHistory.d.ts +2 -2
- package/dist/patterns/Literal.d.ts +8 -8
- package/dist/patterns/Not.d.ts +9 -5
- package/dist/patterns/Or.d.ts +8 -5
- package/dist/patterns/Pattern.d.ts +8 -4
- package/dist/patterns/Reference.d.ts +11 -7
- package/dist/patterns/Regex.d.ts +8 -8
- package/dist/patterns/Repeat.d.ts +8 -7
- package/package.json +1 -1
- package/src/ast/Node.test.ts +116 -0
- package/src/ast/Node.ts +71 -5
- package/src/index.ts +14 -3
- package/src/intellisense/AutoComplete.test.ts +168 -23
- package/src/intellisense/AutoComplete.ts +102 -21
- package/src/intellisense/Suggestion.ts +3 -4
- package/src/intellisense/javascript/Javascript.test.ts +86 -62
- package/src/intellisense/javascript/{expressionStatement.ts → assignment.ts} +7 -8
- package/src/intellisense/javascript/escapedCharacter.ts +0 -1
- package/src/intellisense/javascript/exponent.ts +0 -2
- package/src/intellisense/javascript/expression.ts +44 -26
- package/src/intellisense/javascript/fraction.ts +0 -2
- package/src/intellisense/javascript/infixOperator.ts +6 -2
- package/src/intellisense/javascript/keywords.ts +3 -0
- package/src/intellisense/javascript/objectAccess.ts +9 -0
- package/src/intellisense/javascript/objectLiteral.ts +3 -3
- package/src/intellisense/javascript/propertyAccess.ts +8 -3
- package/src/intellisense/javascript/stringLiteral.ts +16 -8
- package/src/patterns/And.test.ts +74 -50
- package/src/patterns/And.ts +72 -36
- package/src/patterns/Cursor.ts +17 -14
- package/src/patterns/CursorHistory.ts +8 -8
- package/src/patterns/Literal.test.ts +79 -38
- package/src/patterns/Literal.ts +34 -41
- package/src/patterns/Not.test.ts +99 -8
- package/src/patterns/Not.ts +58 -14
- package/src/patterns/Or.test.ts +128 -13
- package/src/patterns/Or.ts +46 -13
- package/src/patterns/Pattern.ts +8 -4
- package/src/patterns/Reference.test.ts +127 -28
- package/src/patterns/Reference.ts +62 -32
- package/src/patterns/Regex.test.ts +76 -35
- package/src/patterns/Regex.ts +35 -43
- package/src/patterns/Repeat.test.ts +72 -41
- package/src/patterns/Repeat.ts +55 -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;
|
|
85
96
|
}
|
|
86
|
-
|
|
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;
|
|
107
|
+
}
|
|
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,38 @@ 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
|
+
getPatterns() {
|
|
457
|
+
return [this];
|
|
431
458
|
}
|
|
432
|
-
|
|
459
|
+
getPatternsAfter(_childReference) {
|
|
460
|
+
return [];
|
|
461
|
+
}
|
|
462
|
+
getNextPatterns() {
|
|
463
|
+
if (this.parent == null) {
|
|
464
|
+
return [];
|
|
465
|
+
}
|
|
466
|
+
return this.parent.getPatternsAfter(this);
|
|
467
|
+
}
|
|
468
|
+
findPattern(_predicate) {
|
|
433
469
|
return null;
|
|
434
470
|
}
|
|
435
471
|
setTokens(tokens) {
|
|
436
472
|
this._tokens = tokens;
|
|
437
473
|
}
|
|
438
|
-
enableContextualTokenAggregation() {
|
|
439
|
-
this._hasContextualTokenAggregation = true;
|
|
440
|
-
}
|
|
441
|
-
disableContextualTokenAggregation() {
|
|
442
|
-
this._hasContextualTokenAggregation = false;
|
|
443
|
-
}
|
|
444
474
|
}
|
|
445
475
|
|
|
446
476
|
function clonePatterns(patterns, isOptional) {
|
|
@@ -510,7 +540,6 @@ class And {
|
|
|
510
540
|
this._parent = null;
|
|
511
541
|
this._children = children;
|
|
512
542
|
this._firstIndex = -1;
|
|
513
|
-
this._shouldReduceAst = false;
|
|
514
543
|
this._nodes = [];
|
|
515
544
|
}
|
|
516
545
|
_assignChildrenToParent(children) {
|
|
@@ -518,11 +547,16 @@ class And {
|
|
|
518
547
|
child.parent = this;
|
|
519
548
|
}
|
|
520
549
|
}
|
|
521
|
-
|
|
550
|
+
test(text) {
|
|
551
|
+
const cursor = new Cursor(text);
|
|
552
|
+
const ast = this.parse(cursor);
|
|
553
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
554
|
+
}
|
|
555
|
+
exec(text) {
|
|
522
556
|
const cursor = new Cursor(text);
|
|
523
557
|
const ast = this.parse(cursor);
|
|
524
558
|
return {
|
|
525
|
-
ast,
|
|
559
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
526
560
|
cursor
|
|
527
561
|
};
|
|
528
562
|
}
|
|
@@ -556,34 +590,43 @@ class And {
|
|
|
556
590
|
if (hasMorePatterns) {
|
|
557
591
|
if (hadMatch) {
|
|
558
592
|
if (cursor.hasNext()) {
|
|
593
|
+
// We had a match. Increment the cursor and use the next pattern.
|
|
559
594
|
cursor.next();
|
|
560
595
|
continue;
|
|
561
596
|
}
|
|
562
597
|
else {
|
|
598
|
+
// We are at the end of the text, it may still be valid, if all the
|
|
599
|
+
// following patterns are optional.
|
|
563
600
|
if (this.areRemainingPatternsOptional(i)) {
|
|
564
601
|
passed = true;
|
|
565
602
|
break;
|
|
566
603
|
}
|
|
604
|
+
// We didn't finish the parsing sequence.
|
|
567
605
|
cursor.recordErrorAt(cursor.index + 1, this);
|
|
568
606
|
break;
|
|
569
607
|
}
|
|
570
608
|
}
|
|
571
609
|
else {
|
|
610
|
+
// An optional pattern did not matched, try from the same spot on the next
|
|
611
|
+
// pattern.
|
|
572
612
|
cursor.moveTo(runningCursorIndex);
|
|
573
613
|
continue;
|
|
574
614
|
}
|
|
575
615
|
}
|
|
576
616
|
else {
|
|
617
|
+
// If we don't have any results from what we parsed then record error.
|
|
577
618
|
const lastNode = this.getLastValidNode();
|
|
578
619
|
if (lastNode === null) {
|
|
579
620
|
cursor.recordErrorAt(cursor.index, this);
|
|
580
621
|
break;
|
|
581
622
|
}
|
|
623
|
+
// The sequence was parsed fully.
|
|
582
624
|
passed = true;
|
|
583
625
|
break;
|
|
584
626
|
}
|
|
585
627
|
}
|
|
586
628
|
else {
|
|
629
|
+
// The pattern failed.
|
|
587
630
|
cursor.moveTo(this._firstIndex);
|
|
588
631
|
break;
|
|
589
632
|
}
|
|
@@ -611,18 +654,9 @@ class And {
|
|
|
611
654
|
createNode(cursor) {
|
|
612
655
|
const children = filterOutNull(this._nodes);
|
|
613
656
|
const lastIndex = children[children.length - 1].lastIndex;
|
|
614
|
-
|
|
657
|
+
cursor.getChars(this._firstIndex, lastIndex);
|
|
615
658
|
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;
|
|
659
|
+
return new Node("and", this._name, this._firstIndex, lastIndex, children);
|
|
626
660
|
}
|
|
627
661
|
getTokens() {
|
|
628
662
|
const tokens = [];
|
|
@@ -634,13 +668,35 @@ class And {
|
|
|
634
668
|
}
|
|
635
669
|
return tokens;
|
|
636
670
|
}
|
|
637
|
-
|
|
671
|
+
getTokensAfter(childReference) {
|
|
672
|
+
const patterns = this.getPatternsAfter(childReference);
|
|
673
|
+
const tokens = [];
|
|
674
|
+
patterns.forEach(p => tokens.push(...p.getTokens()));
|
|
675
|
+
return tokens;
|
|
676
|
+
}
|
|
677
|
+
getNextTokens() {
|
|
678
|
+
if (this.parent == null) {
|
|
679
|
+
return [];
|
|
680
|
+
}
|
|
681
|
+
return this.parent.getTokensAfter(this);
|
|
682
|
+
}
|
|
683
|
+
getPatterns() {
|
|
684
|
+
const patterns = [];
|
|
685
|
+
for (const pattern of this._children) {
|
|
686
|
+
patterns.push(...pattern.getPatterns());
|
|
687
|
+
if (!pattern.isOptional) {
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return patterns;
|
|
692
|
+
}
|
|
693
|
+
getPatternsAfter(childReference) {
|
|
638
694
|
let nextSibling = null;
|
|
639
695
|
let nextSiblingIndex = -1;
|
|
640
696
|
let index = -1;
|
|
641
|
-
const
|
|
697
|
+
const patterns = [];
|
|
642
698
|
for (let i = 0; i < this._children.length; i++) {
|
|
643
|
-
if (this._children[i] ===
|
|
699
|
+
if (this._children[i] === childReference) {
|
|
644
700
|
if (i + 1 < this._children.length) {
|
|
645
701
|
nextSibling = this._children[i + 1];
|
|
646
702
|
}
|
|
@@ -649,39 +705,44 @@ class And {
|
|
|
649
705
|
break;
|
|
650
706
|
}
|
|
651
707
|
}
|
|
708
|
+
// The child reference isn't one of the child patterns.
|
|
652
709
|
if (index === -1) {
|
|
653
710
|
return [];
|
|
654
711
|
}
|
|
712
|
+
// The reference pattern is the last child. So ask the parent for the next pattern.
|
|
655
713
|
if (nextSiblingIndex === this._children.length && this._parent !== null) {
|
|
656
|
-
return this._parent.
|
|
714
|
+
return this._parent.getPatternsAfter(this);
|
|
657
715
|
}
|
|
716
|
+
// Next pattern isn't optional so send it back as the next patterns.
|
|
658
717
|
if (nextSibling !== null && !nextSibling.isOptional) {
|
|
659
|
-
return nextSibling
|
|
718
|
+
return [nextSibling];
|
|
660
719
|
}
|
|
720
|
+
// Send back as many optional patterns as possible.
|
|
661
721
|
if (nextSibling !== null && nextSibling.isOptional) {
|
|
662
722
|
for (let i = nextSiblingIndex; i < this._children.length; i++) {
|
|
663
723
|
const child = this._children[i];
|
|
664
|
-
|
|
724
|
+
patterns.push(child);
|
|
665
725
|
if (!child.isOptional) {
|
|
666
726
|
break;
|
|
667
727
|
}
|
|
668
728
|
if (i === this._children.length - 1 && this._parent !== null) {
|
|
669
|
-
|
|
729
|
+
patterns.push(...this._parent.getPatternsAfter(this));
|
|
670
730
|
}
|
|
671
731
|
}
|
|
672
732
|
}
|
|
673
|
-
return
|
|
733
|
+
return patterns;
|
|
674
734
|
}
|
|
675
|
-
|
|
676
|
-
|
|
735
|
+
getNextPatterns() {
|
|
736
|
+
if (this.parent == null) {
|
|
737
|
+
return [];
|
|
738
|
+
}
|
|
739
|
+
return this.parent.getPatternsAfter(this);
|
|
677
740
|
}
|
|
678
|
-
findPattern(
|
|
679
|
-
return findPattern(this,
|
|
741
|
+
findPattern(predicate) {
|
|
742
|
+
return findPattern(this, predicate);
|
|
680
743
|
}
|
|
681
744
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
682
|
-
|
|
683
|
-
and._shouldReduceAst = this._shouldReduceAst;
|
|
684
|
-
return and;
|
|
745
|
+
return new And(name, this._children, isOptional);
|
|
685
746
|
}
|
|
686
747
|
}
|
|
687
748
|
|
|
@@ -716,14 +777,17 @@ class Literal {
|
|
|
716
777
|
this._parent = null;
|
|
717
778
|
this._firstIndex = 0;
|
|
718
779
|
this._lastIndex = 0;
|
|
719
|
-
this._hasContextualTokenAggregation = false;
|
|
720
|
-
this._isRetrievingContextualTokens = false;
|
|
721
780
|
}
|
|
722
|
-
|
|
781
|
+
test(text) {
|
|
782
|
+
const cursor = new Cursor(text);
|
|
783
|
+
const ast = this.parse(cursor);
|
|
784
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
785
|
+
}
|
|
786
|
+
exec(text) {
|
|
723
787
|
const cursor = new Cursor(text);
|
|
724
788
|
const ast = this.parse(cursor);
|
|
725
789
|
return {
|
|
726
|
-
ast,
|
|
790
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
727
791
|
cursor
|
|
728
792
|
};
|
|
729
793
|
}
|
|
@@ -766,45 +830,38 @@ class Literal {
|
|
|
766
830
|
return passed;
|
|
767
831
|
}
|
|
768
832
|
_createNode() {
|
|
769
|
-
return new Node("literal", this._name, this._firstIndex, this._lastIndex,
|
|
833
|
+
return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._literal);
|
|
770
834
|
}
|
|
771
835
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
772
836
|
const clone = new Literal(name, this._literal, isOptional);
|
|
773
|
-
clone._hasContextualTokenAggregation = this._hasContextualTokenAggregation;
|
|
774
837
|
return clone;
|
|
775
838
|
}
|
|
776
839
|
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
|
-
}
|
|
840
|
+
return [this._literal];
|
|
793
841
|
}
|
|
794
|
-
|
|
842
|
+
getTokensAfter(_lastMatched) {
|
|
795
843
|
return [];
|
|
796
844
|
}
|
|
797
|
-
|
|
798
|
-
|
|
845
|
+
getNextTokens() {
|
|
846
|
+
if (this.parent == null) {
|
|
847
|
+
return [];
|
|
848
|
+
}
|
|
849
|
+
return this.parent.getTokensAfter(this);
|
|
799
850
|
}
|
|
800
|
-
|
|
801
|
-
return
|
|
851
|
+
getPatterns() {
|
|
852
|
+
return [this];
|
|
853
|
+
}
|
|
854
|
+
getPatternsAfter() {
|
|
855
|
+
return [];
|
|
802
856
|
}
|
|
803
|
-
|
|
804
|
-
this.
|
|
857
|
+
getNextPatterns() {
|
|
858
|
+
if (this.parent == null) {
|
|
859
|
+
return [];
|
|
860
|
+
}
|
|
861
|
+
return this.parent.getPatternsAfter(this);
|
|
805
862
|
}
|
|
806
|
-
|
|
807
|
-
|
|
863
|
+
findPattern(_predicate) {
|
|
864
|
+
return null;
|
|
808
865
|
}
|
|
809
866
|
}
|
|
810
867
|
|
|
@@ -815,9 +872,6 @@ class Not {
|
|
|
815
872
|
get name() {
|
|
816
873
|
return this._name;
|
|
817
874
|
}
|
|
818
|
-
get isOptional() {
|
|
819
|
-
return false;
|
|
820
|
-
}
|
|
821
875
|
get parent() {
|
|
822
876
|
return this._parent;
|
|
823
877
|
}
|
|
@@ -827,6 +881,9 @@ class Not {
|
|
|
827
881
|
get children() {
|
|
828
882
|
return this._children;
|
|
829
883
|
}
|
|
884
|
+
get isOptional() {
|
|
885
|
+
return false;
|
|
886
|
+
}
|
|
830
887
|
constructor(name, pattern) {
|
|
831
888
|
this._type = "not";
|
|
832
889
|
this._name = name;
|
|
@@ -834,7 +891,12 @@ class Not {
|
|
|
834
891
|
this._children = [pattern.clone(pattern.name, false)];
|
|
835
892
|
this._children[0].parent = this;
|
|
836
893
|
}
|
|
837
|
-
|
|
894
|
+
test(text) {
|
|
895
|
+
const cursor = new Cursor(text);
|
|
896
|
+
this.parse(cursor);
|
|
897
|
+
return !cursor.hasError;
|
|
898
|
+
}
|
|
899
|
+
exec(text) {
|
|
838
900
|
const cursor = new Cursor(text);
|
|
839
901
|
const ast = this.parse(cursor);
|
|
840
902
|
return {
|
|
@@ -860,17 +922,44 @@ class Not {
|
|
|
860
922
|
const not = new Not(name, this._children[0]);
|
|
861
923
|
return not;
|
|
862
924
|
}
|
|
863
|
-
getNextPattern() {
|
|
864
|
-
return getNextPattern(this);
|
|
865
|
-
}
|
|
866
925
|
getTokens() {
|
|
926
|
+
const parent = this._parent;
|
|
927
|
+
if (parent != null) {
|
|
928
|
+
return parent.getTokensAfter(this);
|
|
929
|
+
}
|
|
930
|
+
return [];
|
|
931
|
+
}
|
|
932
|
+
getTokensAfter(_childReference) {
|
|
933
|
+
const parent = this._parent;
|
|
934
|
+
if (parent != null) {
|
|
935
|
+
return parent.getTokensAfter(this);
|
|
936
|
+
}
|
|
867
937
|
return [];
|
|
868
938
|
}
|
|
869
|
-
getNextTokens(
|
|
939
|
+
getNextTokens() {
|
|
940
|
+
if (this.parent == null) {
|
|
941
|
+
return [];
|
|
942
|
+
}
|
|
943
|
+
return this.parent.getTokensAfter(this);
|
|
944
|
+
}
|
|
945
|
+
getPatterns() {
|
|
946
|
+
return [...this.getNextPatterns().map(p => p.getPatterns()).flat()];
|
|
947
|
+
}
|
|
948
|
+
getPatternsAfter(_childReference) {
|
|
949
|
+
const parent = this._parent;
|
|
950
|
+
if (parent != null) {
|
|
951
|
+
return parent.getPatternsAfter(this);
|
|
952
|
+
}
|
|
870
953
|
return [];
|
|
871
954
|
}
|
|
872
|
-
|
|
873
|
-
|
|
955
|
+
getNextPatterns() {
|
|
956
|
+
if (this.parent == null) {
|
|
957
|
+
return [];
|
|
958
|
+
}
|
|
959
|
+
return this.parent.getPatternsAfter(this);
|
|
960
|
+
}
|
|
961
|
+
findPattern(predicate) {
|
|
962
|
+
return predicate(this._children[0]) ? this._children[0] : null;
|
|
874
963
|
}
|
|
875
964
|
}
|
|
876
965
|
|
|
@@ -904,7 +993,6 @@ class Or {
|
|
|
904
993
|
this._parent = null;
|
|
905
994
|
this._children = children;
|
|
906
995
|
this._isOptional = isOptional;
|
|
907
|
-
this._node = null;
|
|
908
996
|
this._firstIndex = 0;
|
|
909
997
|
}
|
|
910
998
|
_assignChildrenToParent(children) {
|
|
@@ -912,17 +1000,21 @@ class Or {
|
|
|
912
1000
|
child.parent = this;
|
|
913
1001
|
}
|
|
914
1002
|
}
|
|
915
|
-
|
|
1003
|
+
test(text) {
|
|
1004
|
+
const cursor = new Cursor(text);
|
|
1005
|
+
const ast = this.parse(cursor);
|
|
1006
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1007
|
+
}
|
|
1008
|
+
exec(text) {
|
|
916
1009
|
const cursor = new Cursor(text);
|
|
917
1010
|
const ast = this.parse(cursor);
|
|
918
1011
|
return {
|
|
919
|
-
ast,
|
|
1012
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
920
1013
|
cursor
|
|
921
1014
|
};
|
|
922
1015
|
}
|
|
923
1016
|
parse(cursor) {
|
|
924
1017
|
this._firstIndex = cursor.index;
|
|
925
|
-
this._node = null;
|
|
926
1018
|
const node = this._tryToParse(cursor);
|
|
927
1019
|
if (node != null) {
|
|
928
1020
|
cursor.resolveError();
|
|
@@ -954,17 +1046,39 @@ class Or {
|
|
|
954
1046
|
}
|
|
955
1047
|
return tokens;
|
|
956
1048
|
}
|
|
957
|
-
|
|
1049
|
+
getTokensAfter(_childReference) {
|
|
1050
|
+
if (this._parent === null) {
|
|
1051
|
+
return [];
|
|
1052
|
+
}
|
|
1053
|
+
return this._parent.getTokensAfter(this);
|
|
1054
|
+
}
|
|
1055
|
+
getNextTokens() {
|
|
1056
|
+
if (this._parent == null) {
|
|
1057
|
+
return [];
|
|
1058
|
+
}
|
|
1059
|
+
return this._parent.getTokensAfter(this);
|
|
1060
|
+
}
|
|
1061
|
+
getPatterns() {
|
|
1062
|
+
const patterns = [];
|
|
1063
|
+
for (const pattern of this._children) {
|
|
1064
|
+
patterns.push(...pattern.getPatterns());
|
|
1065
|
+
}
|
|
1066
|
+
return patterns;
|
|
1067
|
+
}
|
|
1068
|
+
getPatternsAfter(_childReference) {
|
|
958
1069
|
if (this._parent === null) {
|
|
959
1070
|
return [];
|
|
960
1071
|
}
|
|
961
|
-
return this._parent.
|
|
1072
|
+
return this._parent.getPatternsAfter(this);
|
|
962
1073
|
}
|
|
963
|
-
|
|
964
|
-
|
|
1074
|
+
getNextPatterns() {
|
|
1075
|
+
if (this.parent == null) {
|
|
1076
|
+
return [];
|
|
1077
|
+
}
|
|
1078
|
+
return this.parent.getPatternsAfter(this);
|
|
965
1079
|
}
|
|
966
|
-
findPattern(
|
|
967
|
-
return findPattern(this,
|
|
1080
|
+
findPattern(predicate) {
|
|
1081
|
+
return findPattern(this, predicate);
|
|
968
1082
|
}
|
|
969
1083
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
970
1084
|
const or = new Or(name, this._children, isOptional);
|
|
@@ -1003,7 +1117,6 @@ class Repeat {
|
|
|
1003
1117
|
this._pattern = children[0];
|
|
1004
1118
|
this._divider = children[1];
|
|
1005
1119
|
this._firstIndex = -1;
|
|
1006
|
-
this._shouldReduceAst = false;
|
|
1007
1120
|
this._nodes = [];
|
|
1008
1121
|
}
|
|
1009
1122
|
_assignChildrenToParent(children) {
|
|
@@ -1011,11 +1124,16 @@ class Repeat {
|
|
|
1011
1124
|
child.parent = this;
|
|
1012
1125
|
}
|
|
1013
1126
|
}
|
|
1014
|
-
|
|
1127
|
+
test(text) {
|
|
1128
|
+
const cursor = new Cursor(text);
|
|
1129
|
+
const ast = this.parse(cursor);
|
|
1130
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1131
|
+
}
|
|
1132
|
+
exec(text) {
|
|
1015
1133
|
const cursor = new Cursor(text);
|
|
1016
1134
|
const ast = this.parse(cursor);
|
|
1017
1135
|
return {
|
|
1018
|
-
ast,
|
|
1136
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1019
1137
|
cursor
|
|
1020
1138
|
};
|
|
1021
1139
|
}
|
|
@@ -1026,7 +1144,7 @@ class Repeat {
|
|
|
1026
1144
|
if (passed) {
|
|
1027
1145
|
cursor.resolveError();
|
|
1028
1146
|
const node = this.createNode(cursor);
|
|
1029
|
-
if (node) {
|
|
1147
|
+
if (node != null) {
|
|
1030
1148
|
cursor.recordMatch(this, node);
|
|
1031
1149
|
}
|
|
1032
1150
|
return node;
|
|
@@ -1045,7 +1163,7 @@ class Repeat {
|
|
|
1045
1163
|
const repeatedNode = this._pattern.parse(cursor);
|
|
1046
1164
|
if (cursor.hasError) {
|
|
1047
1165
|
const lastValidNode = this.getLastValidNode();
|
|
1048
|
-
if (lastValidNode) {
|
|
1166
|
+
if (lastValidNode != null) {
|
|
1049
1167
|
passed = true;
|
|
1050
1168
|
}
|
|
1051
1169
|
else {
|
|
@@ -1062,13 +1180,13 @@ class Repeat {
|
|
|
1062
1180
|
break;
|
|
1063
1181
|
}
|
|
1064
1182
|
cursor.next();
|
|
1065
|
-
if (this._divider) {
|
|
1183
|
+
if (this._divider != null) {
|
|
1066
1184
|
const dividerNode = this._divider.parse(cursor);
|
|
1067
1185
|
if (cursor.hasError) {
|
|
1068
1186
|
passed = true;
|
|
1069
1187
|
break;
|
|
1070
1188
|
}
|
|
1071
|
-
else if (dividerNode) {
|
|
1189
|
+
else if (dividerNode != null) {
|
|
1072
1190
|
this._nodes.push(dividerNode);
|
|
1073
1191
|
if (!cursor.hasNext()) {
|
|
1074
1192
|
passed = true;
|
|
@@ -1097,12 +1215,9 @@ class Repeat {
|
|
|
1097
1215
|
}
|
|
1098
1216
|
}
|
|
1099
1217
|
const lastIndex = children[children.length - 1].lastIndex;
|
|
1100
|
-
|
|
1218
|
+
cursor.getChars(this._firstIndex, lastIndex);
|
|
1101
1219
|
cursor.moveTo(lastIndex);
|
|
1102
|
-
|
|
1103
|
-
children = [];
|
|
1104
|
-
}
|
|
1105
|
-
return new Node("repeat", this._name, this._firstIndex, lastIndex, children, this._shouldReduceAst ? value : undefined);
|
|
1220
|
+
return new Node("repeat", this._name, this._firstIndex, lastIndex, children, undefined);
|
|
1106
1221
|
}
|
|
1107
1222
|
getLastValidNode() {
|
|
1108
1223
|
const nodes = this._nodes.filter((node) => node !== null);
|
|
@@ -1111,51 +1226,64 @@ class Repeat {
|
|
|
1111
1226
|
}
|
|
1112
1227
|
return nodes[nodes.length - 1];
|
|
1113
1228
|
}
|
|
1114
|
-
enableAstReduction() {
|
|
1115
|
-
this._shouldReduceAst = true;
|
|
1116
|
-
}
|
|
1117
|
-
disableAstReduction() {
|
|
1118
|
-
this._shouldReduceAst = false;
|
|
1119
|
-
}
|
|
1120
1229
|
getTokens() {
|
|
1121
1230
|
return this._pattern.getTokens();
|
|
1122
1231
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1232
|
+
getTokensAfter(childReference) {
|
|
1233
|
+
const patterns = this.getPatternsAfter(childReference);
|
|
1125
1234
|
const tokens = [];
|
|
1235
|
+
patterns.forEach(p => tokens.push(...p.getTokens()));
|
|
1236
|
+
return tokens;
|
|
1237
|
+
}
|
|
1238
|
+
getNextTokens() {
|
|
1239
|
+
if (this.parent == null) {
|
|
1240
|
+
return [];
|
|
1241
|
+
}
|
|
1242
|
+
return this.parent.getTokensAfter(this);
|
|
1243
|
+
}
|
|
1244
|
+
getPatterns() {
|
|
1245
|
+
return this._pattern.getPatterns();
|
|
1246
|
+
}
|
|
1247
|
+
getPatternsAfter(childReference) {
|
|
1248
|
+
let index = -1;
|
|
1249
|
+
const patterns = [];
|
|
1126
1250
|
for (let i = 0; i < this._children.length; i++) {
|
|
1127
|
-
if (this._children[i] ===
|
|
1251
|
+
if (this._children[i] === childReference) {
|
|
1128
1252
|
index = i;
|
|
1129
1253
|
}
|
|
1130
1254
|
}
|
|
1255
|
+
// If the last match isn't a child of this pattern.
|
|
1131
1256
|
if (index === -1) {
|
|
1132
1257
|
return [];
|
|
1133
1258
|
}
|
|
1259
|
+
// If the last match was the repeated patterns, then suggest the divider.
|
|
1134
1260
|
if (index === 0 && this._divider) {
|
|
1135
|
-
|
|
1261
|
+
patterns.push(this._children[1]);
|
|
1136
1262
|
if (this._parent) {
|
|
1137
|
-
|
|
1263
|
+
patterns.push(...this._parent.getPatternsAfter(this));
|
|
1138
1264
|
}
|
|
1139
1265
|
}
|
|
1266
|
+
// Suggest the pattern because the divider was the last match.
|
|
1140
1267
|
if (index === 1) {
|
|
1141
|
-
|
|
1268
|
+
patterns.push(this._children[0]);
|
|
1142
1269
|
}
|
|
1143
1270
|
if (index === 0 && !this._divider && this._parent) {
|
|
1144
|
-
|
|
1145
|
-
|
|
1271
|
+
patterns.push(this._children[0]);
|
|
1272
|
+
patterns.push(...this._parent.getPatternsAfter(this));
|
|
1146
1273
|
}
|
|
1147
|
-
return
|
|
1274
|
+
return patterns;
|
|
1148
1275
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1276
|
+
getNextPatterns() {
|
|
1277
|
+
if (this.parent == null) {
|
|
1278
|
+
return [];
|
|
1279
|
+
}
|
|
1280
|
+
return this.parent.getPatternsAfter(this);
|
|
1151
1281
|
}
|
|
1152
|
-
findPattern(
|
|
1153
|
-
return findPattern(this,
|
|
1282
|
+
findPattern(predicate) {
|
|
1283
|
+
return findPattern(this, predicate);
|
|
1154
1284
|
}
|
|
1155
1285
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
1156
|
-
|
|
1157
|
-
repeat._shouldReduceAst = this._shouldReduceAst;
|
|
1158
|
-
return repeat;
|
|
1286
|
+
return new Repeat(name, this._pattern, this._divider, isOptional);
|
|
1159
1287
|
}
|
|
1160
1288
|
}
|
|
1161
1289
|
|
|
@@ -1166,9 +1294,6 @@ class Reference {
|
|
|
1166
1294
|
get name() {
|
|
1167
1295
|
return this._name;
|
|
1168
1296
|
}
|
|
1169
|
-
get isOptional() {
|
|
1170
|
-
return this._isOptional;
|
|
1171
|
-
}
|
|
1172
1297
|
get parent() {
|
|
1173
1298
|
return this._parent;
|
|
1174
1299
|
}
|
|
@@ -1178,6 +1303,9 @@ class Reference {
|
|
|
1178
1303
|
get children() {
|
|
1179
1304
|
return this._children;
|
|
1180
1305
|
}
|
|
1306
|
+
get isOptional() {
|
|
1307
|
+
return this._isOptional;
|
|
1308
|
+
}
|
|
1181
1309
|
constructor(name, isOptional = false) {
|
|
1182
1310
|
this._type = "reference";
|
|
1183
1311
|
this._name = name;
|
|
@@ -1186,35 +1314,22 @@ class Reference {
|
|
|
1186
1314
|
this._pattern = null;
|
|
1187
1315
|
this._children = [];
|
|
1188
1316
|
}
|
|
1189
|
-
|
|
1317
|
+
test(text) {
|
|
1318
|
+
const cursor = new Cursor(text);
|
|
1319
|
+
const ast = this.parse(cursor);
|
|
1320
|
+
return (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1321
|
+
}
|
|
1322
|
+
exec(text) {
|
|
1190
1323
|
const cursor = new Cursor(text);
|
|
1191
1324
|
const ast = this.parse(cursor);
|
|
1192
1325
|
return {
|
|
1193
|
-
ast,
|
|
1326
|
+
ast: (ast === null || ast === void 0 ? void 0 : ast.value) === text ? ast : null,
|
|
1194
1327
|
cursor
|
|
1195
1328
|
};
|
|
1196
1329
|
}
|
|
1197
1330
|
parse(cursor) {
|
|
1198
1331
|
return this._getPatternSafely().parse(cursor);
|
|
1199
1332
|
}
|
|
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
1333
|
_getPatternSafely() {
|
|
1219
1334
|
if (this._pattern === null) {
|
|
1220
1335
|
const pattern = this._findPattern();
|
|
@@ -1247,10 +1362,210 @@ class Reference {
|
|
|
1247
1362
|
}
|
|
1248
1363
|
return node;
|
|
1249
1364
|
}
|
|
1365
|
+
getTokens() {
|
|
1366
|
+
return this._getPatternSafely().getTokens();
|
|
1367
|
+
}
|
|
1368
|
+
getTokensAfter(_lastMatched) {
|
|
1369
|
+
if (this._parent == null) {
|
|
1370
|
+
return [];
|
|
1371
|
+
}
|
|
1372
|
+
return this._parent.getTokensAfter(this);
|
|
1373
|
+
}
|
|
1374
|
+
getNextTokens() {
|
|
1375
|
+
if (this.parent == null) {
|
|
1376
|
+
return [];
|
|
1377
|
+
}
|
|
1378
|
+
return this.parent.getTokensAfter(this);
|
|
1379
|
+
}
|
|
1380
|
+
getPatterns() {
|
|
1381
|
+
return this._getPatternSafely().getPatterns();
|
|
1382
|
+
}
|
|
1383
|
+
getPatternsAfter(_childReference) {
|
|
1384
|
+
if (this._parent == null) {
|
|
1385
|
+
return [];
|
|
1386
|
+
}
|
|
1387
|
+
return this._parent.getPatternsAfter(this);
|
|
1388
|
+
}
|
|
1389
|
+
getNextPatterns() {
|
|
1390
|
+
if (this.parent == null) {
|
|
1391
|
+
return [];
|
|
1392
|
+
}
|
|
1393
|
+
return this.parent.getPatternsAfter(this);
|
|
1394
|
+
}
|
|
1395
|
+
findPattern(_predicate) {
|
|
1396
|
+
return null;
|
|
1397
|
+
}
|
|
1398
|
+
clone(name = this._name, isOptional = this._isOptional) {
|
|
1399
|
+
return new Reference(name, isOptional);
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
const defaultOptions = { greedyPatternNames: [], customTokens: {} };
|
|
1404
|
+
class AutoComplete {
|
|
1405
|
+
constructor(pattern, options = defaultOptions) {
|
|
1406
|
+
this._pattern = pattern;
|
|
1407
|
+
this._options = options;
|
|
1408
|
+
this._text = "";
|
|
1409
|
+
}
|
|
1410
|
+
/**
|
|
1411
|
+
* @deprecated Use suggestFor instead.
|
|
1412
|
+
* @param text The text to suggest for.
|
|
1413
|
+
*/
|
|
1414
|
+
suggest(text) {
|
|
1415
|
+
return this.suggestFor(text);
|
|
1416
|
+
}
|
|
1417
|
+
suggestFor(text) {
|
|
1418
|
+
if (text.length === 0) {
|
|
1419
|
+
return {
|
|
1420
|
+
isComplete: false,
|
|
1421
|
+
options: this._createSuggestionsFromRoot(),
|
|
1422
|
+
errorAtIndex: 0,
|
|
1423
|
+
cursor: null,
|
|
1424
|
+
ast: null
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
this._text = text;
|
|
1428
|
+
this._cursor = new Cursor(text);
|
|
1429
|
+
const ast = this._pattern.parse(this._cursor);
|
|
1430
|
+
const leafPattern = this._cursor.leafMatch.pattern;
|
|
1431
|
+
const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === text;
|
|
1432
|
+
const options = this._createSuggestionsFromTokens();
|
|
1433
|
+
[this._pattern];
|
|
1434
|
+
let errorAtIndex = null;
|
|
1435
|
+
if (leafPattern != null) {
|
|
1436
|
+
leafPattern.getNextPatterns();
|
|
1437
|
+
}
|
|
1438
|
+
if (this._cursor.hasError && this._cursor.furthestError != null) {
|
|
1439
|
+
errorAtIndex = this._cursor.furthestError.index;
|
|
1440
|
+
errorAtIndex = options.reduce((errorAtIndex, option) => Math.max(errorAtIndex, option.startIndex), errorAtIndex);
|
|
1441
|
+
}
|
|
1442
|
+
return {
|
|
1443
|
+
isComplete: isComplete,
|
|
1444
|
+
options: options,
|
|
1445
|
+
errorAtIndex,
|
|
1446
|
+
cursor: this._cursor,
|
|
1447
|
+
ast,
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
_createSuggestionsFromRoot() {
|
|
1451
|
+
const suggestions = [];
|
|
1452
|
+
const tokens = this._pattern.getTokens();
|
|
1453
|
+
for (const token of tokens) {
|
|
1454
|
+
suggestions.push(this._createSuggestion("", token));
|
|
1455
|
+
}
|
|
1456
|
+
return suggestions;
|
|
1457
|
+
}
|
|
1458
|
+
_createSuggestionsFromTokens() {
|
|
1459
|
+
const leafMatch = this._cursor.leafMatch;
|
|
1460
|
+
if (!leafMatch.pattern) {
|
|
1461
|
+
return this._createSuggestions(-1, this._getTokensForPattern(this._pattern));
|
|
1462
|
+
}
|
|
1463
|
+
const leafPattern = leafMatch.pattern;
|
|
1464
|
+
const parent = leafMatch.pattern.parent;
|
|
1465
|
+
if (parent !== null && leafMatch.node != null) {
|
|
1466
|
+
const patterns = leafPattern.getNextPatterns();
|
|
1467
|
+
const tokens = patterns.reduce((acc, pattern) => {
|
|
1468
|
+
acc.push(...this._getTokensForPattern(pattern));
|
|
1469
|
+
return acc;
|
|
1470
|
+
}, []);
|
|
1471
|
+
return this._createSuggestions(leafMatch.node.lastIndex, tokens);
|
|
1472
|
+
}
|
|
1473
|
+
else {
|
|
1474
|
+
return [];
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
_getTokensForPattern(pattern) {
|
|
1478
|
+
const augmentedTokens = this._getAugmentedTokens(pattern);
|
|
1479
|
+
if (this._options.greedyPatternNames != null && this._options.greedyPatternNames.includes(pattern.name)) {
|
|
1480
|
+
const nextPatterns = pattern.getNextPatterns();
|
|
1481
|
+
const tokens = [];
|
|
1482
|
+
const nextPatternTokens = nextPatterns.reduce((acc, pattern) => {
|
|
1483
|
+
acc.push(...this._getTokensForPattern(pattern));
|
|
1484
|
+
return acc;
|
|
1485
|
+
}, []);
|
|
1486
|
+
for (let token of augmentedTokens) {
|
|
1487
|
+
for (let nextPatternToken of nextPatternTokens) {
|
|
1488
|
+
tokens.push(token + nextPatternToken);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
return tokens;
|
|
1492
|
+
}
|
|
1493
|
+
else {
|
|
1494
|
+
return augmentedTokens;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
_getAugmentedTokens(pattern) {
|
|
1498
|
+
const customTokensMap = this._options.customTokens || {};
|
|
1499
|
+
const leafPatterns = pattern.getPatterns();
|
|
1500
|
+
const tokens = customTokensMap[pattern.name] || [];
|
|
1501
|
+
leafPatterns.forEach(p => {
|
|
1502
|
+
const augmentedTokens = customTokensMap[p.name] || [];
|
|
1503
|
+
tokens.push(...p.getTokens(), ...augmentedTokens);
|
|
1504
|
+
});
|
|
1505
|
+
return tokens;
|
|
1506
|
+
}
|
|
1507
|
+
_createSuggestions(lastIndex, tokens) {
|
|
1508
|
+
let substring = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
|
|
1509
|
+
const suggestionStrings = [];
|
|
1510
|
+
const options = [];
|
|
1511
|
+
for (const token of tokens) {
|
|
1512
|
+
const suggestion = substring + token;
|
|
1513
|
+
const startsWith = suggestion.startsWith(substring);
|
|
1514
|
+
const alreadyExist = suggestionStrings.includes(suggestion);
|
|
1515
|
+
const isSameAsText = suggestion === this._text;
|
|
1516
|
+
if (startsWith && !alreadyExist && !isSameAsText) {
|
|
1517
|
+
suggestionStrings.push(suggestion);
|
|
1518
|
+
options.push(this._createSuggestion(this._cursor.text, suggestion));
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
const reducedOptions = getFurthestOptions(options);
|
|
1522
|
+
reducedOptions.sort((a, b) => a.text.localeCompare(b.text));
|
|
1523
|
+
return reducedOptions;
|
|
1524
|
+
}
|
|
1525
|
+
_createSuggestion(fullText, suggestion) {
|
|
1526
|
+
const furthestMatch = findMatchIndex(suggestion, fullText);
|
|
1527
|
+
const text = suggestion.slice(furthestMatch);
|
|
1528
|
+
return {
|
|
1529
|
+
text: text,
|
|
1530
|
+
startIndex: furthestMatch,
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
function findMatchIndex(str1, str2) {
|
|
1535
|
+
let matchCount = 0;
|
|
1536
|
+
let minLength = str1.length;
|
|
1537
|
+
if (str2.length < minLength) {
|
|
1538
|
+
minLength = str2.length;
|
|
1539
|
+
}
|
|
1540
|
+
for (let i = 0; i < minLength; i++) {
|
|
1541
|
+
if (str1[i] === str2[i]) {
|
|
1542
|
+
matchCount++;
|
|
1543
|
+
}
|
|
1544
|
+
else {
|
|
1545
|
+
break;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
return matchCount;
|
|
1549
|
+
}
|
|
1550
|
+
function getFurthestOptions(options) {
|
|
1551
|
+
let furthestOptions = [];
|
|
1552
|
+
let furthestIndex = -1;
|
|
1553
|
+
for (const option of options) {
|
|
1554
|
+
if (option.startIndex > furthestIndex) {
|
|
1555
|
+
furthestIndex = option.startIndex;
|
|
1556
|
+
furthestOptions = [];
|
|
1557
|
+
}
|
|
1558
|
+
if (option.startIndex === furthestIndex) {
|
|
1559
|
+
furthestOptions.push(option);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
return furthestOptions;
|
|
1250
1563
|
}
|
|
1251
1564
|
|
|
1252
1565
|
exports.And = And;
|
|
1566
|
+
exports.AutoComplete = AutoComplete;
|
|
1253
1567
|
exports.Cursor = Cursor;
|
|
1568
|
+
exports.CursorHistory = CursorHistory;
|
|
1254
1569
|
exports.Literal = Literal;
|
|
1255
1570
|
exports.Node = Node;
|
|
1256
1571
|
exports.Not = Not;
|