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