clarity-pattern-parser 6.0.2 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/TODO.md +1 -78
  2. package/dist/ast/Node.d.ts +1 -0
  3. package/dist/grammar/Grammar.d.ts +17 -0
  4. package/dist/grammar/patterns/andLiteral.d.ts +2 -0
  5. package/dist/grammar/patterns/comment.d.ts +2 -0
  6. package/dist/grammar/patterns/grammar.d.ts +2 -0
  7. package/dist/grammar/patterns/literal.d.ts +2 -0
  8. package/dist/grammar/patterns/name.d.ts +2 -0
  9. package/dist/grammar/patterns/orLiteral.d.ts +2 -0
  10. package/dist/grammar/patterns/pattern.d.ts +2 -0
  11. package/dist/grammar/patterns/regexLiteral.d.ts +2 -0
  12. package/dist/grammar/patterns/repeatLiteral.d.ts +3 -0
  13. package/dist/grammar/patterns/spaces.d.ts +2 -0
  14. package/dist/grammar/patterns/statement.d.ts +2 -0
  15. package/dist/index.browser.js +1161 -556
  16. package/dist/index.browser.js.map +1 -1
  17. package/dist/index.d.ts +5 -4
  18. package/dist/index.esm.js +1159 -555
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1159 -554
  21. package/dist/index.js.map +1 -1
  22. package/dist/intellisense/AutoComplete.d.ts +2 -6
  23. package/dist/patterns/And.d.ts +1 -1
  24. package/dist/patterns/Cursor.d.ts +1 -0
  25. package/dist/patterns/CursorHistory.d.ts +2 -1
  26. package/dist/patterns/FiniteRepeat.d.ts +39 -0
  27. package/dist/patterns/InfiniteRepeat.d.ts +47 -0
  28. package/dist/patterns/Literal.d.ts +1 -1
  29. package/dist/patterns/Not.d.ts +1 -1
  30. package/dist/patterns/Or.d.ts +1 -1
  31. package/dist/patterns/Pattern.d.ts +1 -1
  32. package/dist/patterns/Reference.d.ts +1 -1
  33. package/dist/patterns/Regex.d.ts +1 -1
  34. package/dist/patterns/Repeat.d.ts +18 -22
  35. package/jest.config.js +0 -1
  36. package/jest.coverage.config.js +13 -0
  37. package/package.json +3 -3
  38. package/src/ast/Node.test.ts +15 -0
  39. package/src/ast/Node.ts +12 -6
  40. package/src/grammar/Grammar.test.ts +306 -0
  41. package/src/grammar/Grammar.ts +249 -0
  42. package/src/grammar/patterns/andLiteral.ts +8 -0
  43. package/src/grammar/patterns/comment.ts +3 -0
  44. package/src/grammar/patterns/grammar.ts +19 -0
  45. package/src/grammar/patterns/literal.ts +5 -0
  46. package/src/grammar/patterns/name.ts +3 -0
  47. package/src/grammar/patterns/orLiteral.ts +8 -0
  48. package/src/grammar/patterns/pattern.ts +13 -0
  49. package/src/grammar/patterns/regexLiteral.ts +4 -0
  50. package/src/grammar/patterns/repeatLiteral.ts +72 -0
  51. package/src/grammar/patterns/spaces.ts +4 -0
  52. package/src/grammar/patterns/statement.ts +36 -0
  53. package/src/grammar/spec.md +142 -0
  54. package/src/index.ts +6 -3
  55. package/src/intellisense/AutoComplete.test.ts +21 -2
  56. package/src/intellisense/AutoComplete.ts +14 -25
  57. package/src/intellisense/Suggestion.ts +0 -1
  58. package/src/intellisense/css/cssValue.ts +1 -1
  59. package/src/intellisense/css/method.ts +1 -1
  60. package/src/intellisense/css/values.ts +1 -1
  61. package/src/intellisense/javascript/Javascript.test.ts +0 -1
  62. package/src/intellisense/javascript/arrayLiteral.ts +1 -1
  63. package/src/intellisense/javascript/expression.ts +1 -1
  64. package/src/intellisense/javascript/invocation.ts +1 -1
  65. package/src/intellisense/javascript/objectLiteral.ts +1 -1
  66. package/src/intellisense/javascript/parameters.ts +1 -1
  67. package/src/intellisense/javascript/stringLiteral.ts +2 -4
  68. package/src/patterns/And.test.ts +5 -5
  69. package/src/patterns/And.ts +11 -17
  70. package/src/patterns/Cursor.ts +4 -0
  71. package/src/patterns/CursorHistory.ts +34 -5
  72. package/src/patterns/FiniteRepeat.test.ts +481 -0
  73. package/src/patterns/FiniteRepeat.ts +231 -0
  74. package/src/patterns/InfiniteRepeat.test.ts +296 -0
  75. package/src/patterns/InfiniteRepeat.ts +329 -0
  76. package/src/patterns/Literal.test.ts +4 -4
  77. package/src/patterns/Literal.ts +1 -1
  78. package/src/patterns/Not.test.ts +11 -11
  79. package/src/patterns/Not.ts +1 -1
  80. package/src/patterns/Or.test.ts +9 -9
  81. package/src/patterns/Or.ts +1 -1
  82. package/src/patterns/Pattern.ts +1 -1
  83. package/src/patterns/Reference.test.ts +8 -8
  84. package/src/patterns/Reference.ts +1 -1
  85. package/src/patterns/Regex.test.ts +4 -4
  86. package/src/patterns/Regex.ts +1 -1
  87. package/src/patterns/Repeat.test.ts +160 -165
  88. package/src/patterns/Repeat.ts +95 -230
@@ -9,7 +9,7 @@ export interface Match {
9
9
 
10
10
  export class CursorHistory {
11
11
  private _isRecording: boolean = false;
12
- private _leafMatch: Match = { pattern: null, node: null };
12
+ private _leafMatches: Match[] = [{ pattern: null, node: null }];
13
13
  private _furthestError: ParseError | null = null;
14
14
  private _currentError: ParseError | null = null;
15
15
  private _rootMatch: Match = { pattern: null, node: null };
@@ -26,7 +26,11 @@ export class CursorHistory {
26
26
  }
27
27
 
28
28
  get leafMatch(): Match {
29
- return this._leafMatch;
29
+ return this._leafMatches[this._leafMatches.length - 1];
30
+ }
31
+
32
+ get leafMatches() {
33
+ return this._leafMatches;
30
34
  }
31
35
 
32
36
  get furthestError(): ParseError | null {
@@ -57,13 +61,38 @@ export class CursorHistory {
57
61
 
58
62
  this._rootMatch.pattern = pattern;
59
63
  this._rootMatch.node = node;
64
+ const leafMatch = this._leafMatches[this._leafMatches.length - 1];
60
65
 
61
66
  const isFurthestMatch =
62
- this._leafMatch.node === null || node.lastIndex > this._leafMatch.node.lastIndex;
67
+ leafMatch.node === null || node.lastIndex > leafMatch.node.lastIndex;
68
+
69
+ const isSameIndexMatch =
70
+ leafMatch.node === null || node.lastIndex === leafMatch.node.lastIndex
63
71
 
64
72
  if (isFurthestMatch) {
65
- this._leafMatch.pattern = pattern;
66
- this._leafMatch.node = node;
73
+ // This is to save on GC churn.
74
+ const match = this._leafMatches.pop() as Match;
75
+ match.pattern = pattern;
76
+ match.node = node;
77
+
78
+ this._leafMatches.length = 0;
79
+ this._leafMatches.push(match);
80
+ } else if (isSameIndexMatch) {
81
+ const isAncestor = this._leafMatches.some((m) => {
82
+ let parent = m.pattern?.parent;
83
+
84
+ while (parent != null) {
85
+ if (parent == pattern.parent) {
86
+ return true;
87
+ }
88
+ parent = parent.parent
89
+ }
90
+ return false;
91
+ })
92
+
93
+ if (!isAncestor) {
94
+ this._leafMatches.unshift({ pattern, node });
95
+ }
67
96
  }
68
97
  }
69
98
 
@@ -0,0 +1,481 @@
1
+ import { FiniteRepeat } from "./FiniteRepeat";
2
+ import { Cursor } from "./Cursor";
3
+ import { Regex } from "./Regex";
4
+ import { Node } from "../ast/Node";
5
+ import { Literal } from "./Literal";
6
+ import { And } from "./And";
7
+
8
+ describe("BoundedRepeat", () => {
9
+ test("Bounds Without Divider", () => {
10
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, {
11
+ min: 2
12
+ });
13
+
14
+ let cursor = new Cursor("1");
15
+ let result = numbers.parse(cursor);
16
+ let expected: Node | null = null;
17
+ expect(result).toBeNull();
18
+ expect(cursor.hasError).toBeTruthy();
19
+
20
+ cursor = new Cursor("12");
21
+ result = numbers.parse(cursor);
22
+ expected = new Node("finite-repeat", "numbers", 0, 1, [
23
+ new Node("regex", "number", 0, 0, [], "1"),
24
+ new Node("regex", "number", 1, 1, [], "2"),
25
+ ]);
26
+
27
+ expect(result).toEqual(expected);
28
+ expect(cursor.hasError).toBeFalsy();
29
+
30
+ cursor = new Cursor("123");
31
+ result = numbers.parse(cursor);
32
+ expected = new Node("finite-repeat", "numbers", 0, 2, [
33
+ new Node("regex", "number", 0, 0, [], "1"),
34
+ new Node("regex", "number", 1, 1, [], "2"),
35
+ new Node("regex", "number", 2, 2, [], "3"),
36
+ ]);
37
+
38
+ expect(result).toEqual(expected);
39
+ expect(cursor.hasError).toBeFalsy();
40
+
41
+ cursor = new Cursor("1234");
42
+ result = numbers.parse(cursor);
43
+ expected = new Node("finite-repeat", "numbers", 0, 2, [
44
+ new Node("regex", "number", 0, 0, [], "1"),
45
+ new Node("regex", "number", 1, 1, [], "2"),
46
+ new Node("regex", "number", 2, 2, [], "3"),
47
+ ]);
48
+
49
+ expect(result).toEqual(expected);
50
+ expect(cursor.hasError).toBeFalsy();
51
+ expect(cursor.index).toBe(2);
52
+
53
+ cursor = new Cursor("12f");
54
+ result = numbers.parse(cursor);
55
+ expected = new Node("finite-repeat", "numbers", 0, 1, [
56
+ new Node("regex", "number", 0, 0, [], "1"),
57
+ new Node("regex", "number", 1, 1, [], "2"),
58
+ ]);
59
+
60
+ expect(result).toEqual(expected);
61
+ expect(cursor.hasError).toBeFalsy();
62
+ });
63
+
64
+ test("Bounds Are Equal Without Divider", () => {
65
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { min: 3});
66
+
67
+ let cursor = new Cursor("1");
68
+ let result = numbers.parse(cursor);
69
+ let expected: Node | null = null;
70
+ expect(result).toBeNull();
71
+ expect(cursor.hasError).toBeTruthy();
72
+
73
+ cursor = new Cursor("12");
74
+ result = numbers.parse(cursor);
75
+ expected = null;
76
+
77
+ expect(result).toBeNull();
78
+ expect(cursor.hasError).toBeTruthy();
79
+
80
+ cursor = new Cursor("123");
81
+ result = numbers.parse(cursor);
82
+ expected = new Node("finite-repeat", "numbers", 0, 2, [
83
+ new Node("regex", "number", 0, 0, [], "1"),
84
+ new Node("regex", "number", 1, 1, [], "2"),
85
+ new Node("regex", "number", 2, 2, [], "3"),
86
+ ]);
87
+
88
+ expect(result).toEqual(expected);
89
+ expect(cursor.hasError).toBeFalsy();
90
+
91
+ cursor = new Cursor("1234");
92
+ result = numbers.parse(cursor);
93
+ expected = new Node("finite-repeat", "numbers", 0, 2, [
94
+ new Node("regex", "number", 0, 0, [], "1"),
95
+ new Node("regex", "number", 1, 1, [], "2"),
96
+ new Node("regex", "number", 2, 2, [], "3"),
97
+ ]);
98
+
99
+ expect(result).toEqual(expected);
100
+ expect(cursor.hasError).toBeFalsy();
101
+ expect(cursor.index).toBe(2);
102
+
103
+ });
104
+
105
+ test("Bounds With Divider", () => {
106
+ const divider = new Literal("comma", ",");
107
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { divider, min: 2, trimDivider: true });
108
+
109
+ let cursor = new Cursor("1,");
110
+ let result = numbers.parse(cursor);
111
+ let expected: Node | null = null;
112
+ expect(result).toBeNull();
113
+ expect(cursor.hasError).toBeTruthy();
114
+
115
+ cursor = new Cursor("1,2");
116
+ result = numbers.parse(cursor);
117
+ expected = new Node("finite-repeat", "numbers", 0, 2, [
118
+ new Node("regex", "number", 0, 0, [], "1"),
119
+ new Node("literal", "comma", 1, 1, [], ","),
120
+ new Node("regex", "number", 2, 2, [], "2"),
121
+ ]);
122
+
123
+ expect(result).toEqual(expected);
124
+ expect(cursor.hasError).toBeFalsy();
125
+
126
+ cursor = new Cursor("1,2,3,");
127
+ result = numbers.parse(cursor);
128
+ expected = new Node("finite-repeat", "numbers", 0, 4, [
129
+ new Node("regex", "number", 0, 0, [], "1"),
130
+ new Node("literal", "comma", 1, 1, [], ","),
131
+ new Node("regex", "number", 2, 2, [], "2"),
132
+ new Node("literal", "comma", 3, 3, [], ","),
133
+ new Node("regex", "number", 4, 4, [], "3"),
134
+ ]);
135
+
136
+ expect(result).toEqual(expected);
137
+ expect(cursor.hasError).toBeFalsy();
138
+
139
+ cursor = new Cursor("1,2,3,4");
140
+ result = numbers.parse(cursor);
141
+ expected = new Node("finite-repeat", "numbers", 0, 4, [
142
+ new Node("regex", "number", 0, 0, [], "1"),
143
+ new Node("literal", "comma", 1, 1, [], ","),
144
+ new Node("regex", "number", 2, 2, [], "2"),
145
+ new Node("literal", "comma", 3, 3, [], ","),
146
+ new Node("regex", "number", 4, 4, [], "3"),
147
+ ]);
148
+
149
+ expect(result).toEqual(expected);
150
+ expect(cursor.hasError).toBeFalsy();
151
+ });
152
+
153
+ test("Optional Repeating Pattern", () => {
154
+ const digit = new Regex("digit", "\\d+", true);
155
+ const divider = new Regex("divider", "\\s");
156
+ const integer = new FiniteRepeat("number", digit, 4, { divider });
157
+ const cursor = new Cursor(
158
+ "\n" +
159
+ "3\n" +
160
+ "\n" +
161
+ "\n"
162
+ );
163
+ const result = integer.parse(cursor);
164
+ const expected = new Node("finite-repeat", "number", 0, 4, [
165
+ new Node("regex", "divider", 0, 0, [], "\n"),
166
+ new Node("regex", "digit", 1, 1, [], "3"),
167
+ new Node("regex", "divider", 2, 2, [], "\n"),
168
+ new Node("regex", "divider", 3, 3, [], "\n"),
169
+ new Node("regex", "divider", 4, 4, [], "\n"),
170
+ ]);
171
+
172
+ expect(result).toEqual(expected)
173
+ expect(cursor.hasError).toBeFalsy()
174
+ });
175
+
176
+ test("Bounds Are Equal With Divider", () => {
177
+ const divider = new Literal("comma", ",");
178
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { divider, min: 3, trimDivider: true });
179
+
180
+ let cursor = new Cursor("1,");
181
+ let result = numbers.parse(cursor);
182
+ let expected: Node | null = null;
183
+ expect(result).toBeNull();
184
+ expect(cursor.hasError).toBeTruthy();
185
+
186
+ cursor = new Cursor("1,2");
187
+ result = numbers.parse(cursor);
188
+ expected = null;
189
+
190
+ expect(result).toEqual(expected);
191
+ expect(cursor.hasError).toBeTruthy();
192
+
193
+ cursor = new Cursor("1,2,3,");
194
+ result = numbers.parse(cursor);
195
+ expected = new Node("finite-repeat", "numbers", 0, 4, [
196
+ new Node("regex", "number", 0, 0, [], "1"),
197
+ new Node("literal", "comma", 1, 1, [], ","),
198
+ new Node("regex", "number", 2, 2, [], "2"),
199
+ new Node("literal", "comma", 3, 3, [], ","),
200
+ new Node("regex", "number", 4, 4, [], "3"),
201
+ ]);
202
+
203
+ expect(result).toEqual(expected);
204
+ expect(cursor.hasError).toBeFalsy();
205
+
206
+ cursor = new Cursor("1,2,3,4");
207
+ result = numbers.parse(cursor);
208
+ expected = new Node("finite-repeat", "numbers", 0, 4, [
209
+ new Node("regex", "number", 0, 0, [], "1"),
210
+ new Node("literal", "comma", 1, 1, [], ","),
211
+ new Node("regex", "number", 2, 2, [], "2"),
212
+ new Node("literal", "comma", 3, 3, [], ","),
213
+ new Node("regex", "number", 4, 4, [], "3"),
214
+ ]);
215
+
216
+ expect(result).toEqual(expected);
217
+ expect(cursor.hasError).toBeFalsy();
218
+ });
219
+
220
+ test("Test", () => {
221
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3);
222
+ const result = numbers.test("1");
223
+
224
+ expect(result).toBeTruthy();
225
+ });
226
+
227
+ test("Exec", () => {
228
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3);
229
+ const result = numbers.exec("1");
230
+
231
+ expect(result.ast).not.toBeNull();
232
+ expect(result.cursor.hasError).toBeFalsy();
233
+ });
234
+
235
+ test("Fail", () => {
236
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3);
237
+ const result = numbers.exec("f");
238
+
239
+ expect(result.ast).toBeNull();
240
+ expect(result.cursor.hasError).toBeTruthy();
241
+ });
242
+
243
+ test("Optional", () => {
244
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { min: 0 });
245
+ const result = numbers.exec("f");
246
+
247
+ expect(result.ast).toBeNull();
248
+ expect(result.cursor.hasError).toBeFalsy();
249
+ });
250
+
251
+ test("Optional With Multiple Matches But Still Below Min", () => {
252
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { min: 0 });
253
+ const result = numbers.exec("12f");
254
+
255
+ expect(result.ast).toBeNull();
256
+ expect(result.cursor.hasError).toBeFalsy();
257
+ });
258
+
259
+ test("Properties", () => {
260
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { min: 0 });
261
+
262
+ expect(numbers.type).toBe("finite-repeat");
263
+ expect(numbers.name).toBe("numbers");
264
+ expect(numbers.parent).toBeNull();
265
+ expect(numbers.children.length).toBe(3);
266
+ expect(numbers.min).toBe(0);
267
+ expect(numbers.max).toBe(3);
268
+ expect(numbers.isOptional).toBeTruthy();
269
+ });
270
+
271
+ test("Clone", () => {
272
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { min: 0 });
273
+ const clone = numbers.clone() as FiniteRepeat;
274
+
275
+ expect(clone.type).toBe(numbers.type);
276
+ expect(clone.name).toBe(numbers.name);
277
+ expect(clone.parent).toBeNull();
278
+ expect(clone.children.length).toBe(numbers.children.length);
279
+ expect(clone.min).toBe(numbers.min);
280
+ expect(clone.max).toBe(numbers.max);
281
+ expect(clone.isOptional).toBe(numbers.isOptional);
282
+ });
283
+
284
+ test("Clone With Custom Overrides", () => {
285
+ const numbers = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { min: 0 });
286
+ let clone = numbers.clone();
287
+ let expected = new FiniteRepeat("numbers", new Regex("number", "\\d"), 3, { min: 0 });
288
+
289
+ expect(clone).toEqual(expected);
290
+
291
+ clone = numbers.clone("cloned-numbers");
292
+ expected = new FiniteRepeat("cloned-numbers", new Regex("number", "\\d"), 3, { min: 0 });
293
+
294
+ expect(clone).toEqual(expected);
295
+
296
+ clone = numbers.clone("cloned-numbers", true);
297
+ expected = new FiniteRepeat("cloned-numbers", new Regex("number", "\\d"), 3, { min: 0 });
298
+
299
+ expect(clone).toEqual(expected);
300
+
301
+ clone = numbers.clone("cloned-numbers", false);
302
+ expected = new FiniteRepeat("cloned-numbers", new Regex("number", "\\d"), 3, { min: 1 });
303
+
304
+ expect(clone).toEqual(expected);
305
+ });
306
+
307
+ test("Get Tokens", () => {
308
+ const numbers = new FiniteRepeat(
309
+ "numbers",
310
+ new Literal("one", "1"),
311
+ 3,
312
+ {
313
+ divider: new Literal("comma", ","),
314
+ min: 0
315
+ });
316
+
317
+ const tokens = numbers.getTokens();
318
+
319
+ expect(tokens).toEqual(["1"]);
320
+ });
321
+
322
+ test("Get Tokens After Without Parent", () => {
323
+ const numbers = new FiniteRepeat(
324
+ "numbers",
325
+ new Literal("one", "1"),
326
+ 2,
327
+ {
328
+ divider: new Literal("comma", ","),
329
+ min: 0,
330
+ trimDivider: true
331
+ });
332
+
333
+ let child = numbers.children[0];
334
+ let tokens = numbers.getTokensAfter(child);
335
+
336
+ expect(tokens).toEqual([","]);
337
+
338
+ child = numbers.children[2];
339
+ tokens = numbers.getTokensAfter(child);
340
+
341
+ expect(tokens).toEqual([]);
342
+
343
+ child = numbers.children[3];
344
+ tokens = numbers.getTokensAfter(child);
345
+
346
+ expect(tokens).toEqual([]);
347
+ });
348
+
349
+ test("Get Tokens After With Parent", () => {
350
+ const numbers = new FiniteRepeat(
351
+ "numbers",
352
+ new Literal("one", "1"),
353
+ 2,
354
+ {
355
+ divider: new Literal("comma", ","),
356
+ trimDivider: true,
357
+ min: 0
358
+ });
359
+
360
+ const parent = new And("parent", [numbers, new Literal("b", "B")]);
361
+ const numbersClone = parent.children[0];
362
+ let child = numbersClone.children[0];
363
+ let tokens = numbersClone.getTokensAfter(child);
364
+
365
+ expect(tokens).toEqual([","]);
366
+
367
+ child = numbersClone.children[2];
368
+ tokens = numbersClone.getTokensAfter(child);
369
+
370
+ expect(tokens).toEqual(["B"]);
371
+
372
+ child = numbersClone.children[3];
373
+ tokens = numbersClone.getTokensAfter(child);
374
+
375
+ expect(tokens).toEqual([]);
376
+
377
+ });
378
+
379
+ test("Get Next Tokens", () => {
380
+ const numbers = new FiniteRepeat(
381
+ "numbers",
382
+ new Literal("one", "1"),
383
+ 2,
384
+ {
385
+ divider: new Literal("comma", ","),
386
+ min: 0
387
+ }
388
+ );
389
+
390
+ const parent = new And("parent", [numbers, new Literal("b", "B")]);
391
+ const numbersClone = parent.children[0];
392
+ const tokens = numbersClone.getNextTokens();
393
+
394
+
395
+ expect(tokens).toEqual(["B"]);
396
+ });
397
+
398
+ test("Get Next Tokens Without Parent", () => {
399
+ const numbers = new FiniteRepeat(
400
+ "numbers",
401
+ new Literal("one", "1"),
402
+ 2,
403
+ {
404
+ divider: new Literal("comma", ","),
405
+ min: 0
406
+ }
407
+ );
408
+
409
+ const tokens = numbers.getNextTokens();
410
+
411
+
412
+ expect(tokens).toEqual([]);
413
+ });
414
+
415
+ test("Get Patterns", () => {
416
+ const numbers = new FiniteRepeat(
417
+ "numbers",
418
+ new Literal("one", "1"),
419
+ 2,
420
+ {
421
+ divider: new Literal("comma", ","),
422
+ min: 0
423
+ }
424
+ );
425
+
426
+ const patterns = numbers.getPatterns();
427
+
428
+ expect(patterns).toEqual([numbers.children[0]]);
429
+ });
430
+
431
+ test("Get Next Patterns Without Parent", () => {
432
+ const numbers = new FiniteRepeat(
433
+ "numbers",
434
+ new Literal("one", "1"),
435
+ 2,
436
+ {
437
+ divider: new Literal("comma", ","),
438
+ min: 0
439
+ }
440
+ );
441
+
442
+ const patterns = numbers.getNextPatterns();
443
+
444
+ expect(patterns).toEqual([]);
445
+ });
446
+
447
+ test("Get Next Patterns With Parent", () => {
448
+ const numbers = new FiniteRepeat(
449
+ "numbers",
450
+ new Literal("one", "1"),
451
+ 2,
452
+ {
453
+ divider: new Literal("comma", ","),
454
+ min: 0
455
+ }
456
+ );
457
+
458
+ const parent = new And("parent", [numbers, new Literal("b", "B")]);
459
+ const numbersClone = parent.children[0];
460
+
461
+ const patterns = numbersClone.getNextPatterns();
462
+
463
+ expect(patterns).toEqual([parent.children[1]]);
464
+ });
465
+
466
+ test("Find Pattern", () => {
467
+ const numbers = new FiniteRepeat(
468
+ "numbers",
469
+ new Literal("one", "1"),
470
+ 2,
471
+ {
472
+ divider: new Literal("comma", ","),
473
+ min: 0
474
+ }
475
+ );
476
+
477
+ const comma = numbers.find(p => p.name === "comma");
478
+ expect(comma).toBe(numbers.children[1]);
479
+ });
480
+
481
+ });