clarity-pattern-parser 8.4.14 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/TODO.md +4 -1
  2. package/dist/grammar/Grammar.d.ts +18 -10
  3. package/dist/grammar/patterns/andLiteral.d.ts +2 -0
  4. package/dist/grammar/patterns/anonymousPattern.d.ts +2 -0
  5. package/dist/grammar/patterns/inlinePattern.d.ts +1 -0
  6. package/dist/grammar/patterns/literals.d.ts +3 -0
  7. package/dist/grammar/patterns/pattern.d.ts +2 -2
  8. package/dist/grammar/patterns.d.ts +2 -0
  9. package/dist/index.browser.js +472 -185
  10. package/dist/index.browser.js.map +1 -1
  11. package/dist/index.d.ts +3 -1
  12. package/dist/index.esm.js +471 -186
  13. package/dist/index.esm.js.map +1 -1
  14. package/dist/index.js +472 -185
  15. package/dist/index.js.map +1 -1
  16. package/dist/patterns/And.d.ts +4 -1
  17. package/dist/patterns/Cursor.d.ts +5 -0
  18. package/dist/patterns/CursorHistory.d.ts +7 -0
  19. package/dist/patterns/FiniteRepeat.d.ts +4 -1
  20. package/dist/patterns/InfiniteRepeat.d.ts +5 -4
  21. package/dist/patterns/Literal.d.ts +6 -5
  22. package/dist/patterns/Not.d.ts +5 -4
  23. package/dist/patterns/Or.d.ts +5 -4
  24. package/dist/patterns/Pattern.d.ts +4 -2
  25. package/dist/patterns/Reference.d.ts +5 -4
  26. package/dist/patterns/Regex.d.ts +5 -4
  27. package/dist/patterns/Repeat.d.ts +3 -0
  28. package/dist/patterns/arePatternsEqual.d.ts +2 -0
  29. package/package.json +1 -1
  30. package/src/grammar/Grammar.test.ts +126 -72
  31. package/src/grammar/Grammar.ts +241 -158
  32. package/src/grammar/patterns/anonymousPattern.ts +23 -0
  33. package/src/grammar/patterns/body.ts +9 -6
  34. package/src/grammar/patterns/comment.ts +3 -2
  35. package/src/grammar/patterns/grammar.ts +15 -12
  36. package/src/grammar/patterns/import.ts +18 -12
  37. package/src/grammar/patterns/literal.ts +2 -3
  38. package/src/grammar/patterns/literals.ts +20 -0
  39. package/src/grammar/patterns/optionsLiteral.ts +19 -0
  40. package/src/grammar/patterns/pattern.ts +23 -9
  41. package/src/grammar/patterns/regexLiteral.ts +1 -0
  42. package/src/grammar/patterns/repeatLiteral.ts +30 -25
  43. package/src/grammar/patterns/sequenceLiteral.ts +24 -0
  44. package/src/grammar/patterns/spaces.ts +8 -6
  45. package/src/grammar/patterns/statement.ts +8 -20
  46. package/src/grammar/patterns.test.ts +38 -0
  47. package/src/grammar/patterns.ts +24 -0
  48. package/src/grammar/spec.md +4 -12
  49. package/src/index.ts +11 -5
  50. package/src/intellisense/AutoComplete.test.ts +41 -40
  51. package/src/intellisense/css/method.ts +2 -2
  52. package/src/intellisense/css/unit.ts +2 -2
  53. package/src/intellisense/css/value.ts +1 -1
  54. package/src/intellisense/javascript/Javascript.test.ts +31 -32
  55. package/src/intellisense/javascript/arrayLiteral.ts +7 -6
  56. package/src/intellisense/javascript/assignment.ts +6 -6
  57. package/src/intellisense/javascript/deleteStatement.ts +2 -2
  58. package/src/intellisense/javascript/escapedCharacter.ts +6 -6
  59. package/src/intellisense/javascript/exponent.ts +6 -6
  60. package/src/intellisense/javascript/expression.ts +18 -17
  61. package/src/intellisense/javascript/fraction.ts +3 -3
  62. package/src/intellisense/javascript/infixOperator.ts +10 -10
  63. package/src/intellisense/javascript/integer.ts +1 -1
  64. package/src/intellisense/javascript/invocation.ts +8 -7
  65. package/src/intellisense/javascript/literal.ts +3 -3
  66. package/src/intellisense/javascript/numberLiteral.ts +5 -4
  67. package/src/intellisense/javascript/objectAccess.ts +2 -3
  68. package/src/intellisense/javascript/objectLiteral.ts +8 -7
  69. package/src/intellisense/javascript/optionalSpaces.ts +2 -1
  70. package/src/intellisense/javascript/parameters.ts +5 -5
  71. package/src/intellisense/javascript/prefixOperator.ts +3 -4
  72. package/src/intellisense/javascript/propertyAccess.ts +9 -8
  73. package/src/intellisense/javascript/stringLiteral.ts +14 -15
  74. package/src/patterns/Cursor.ts +42 -4
  75. package/src/patterns/CursorHistory.ts +20 -4
  76. package/src/patterns/FiniteRepeat.test.ts +52 -51
  77. package/src/patterns/FiniteRepeat.ts +60 -38
  78. package/src/patterns/InfiniteRepeat.test.ts +36 -49
  79. package/src/patterns/InfiniteRepeat.ts +70 -37
  80. package/src/patterns/Literal.test.ts +16 -27
  81. package/src/patterns/Literal.ts +34 -27
  82. package/src/patterns/Not.test.ts +7 -7
  83. package/src/patterns/Not.ts +24 -6
  84. package/src/patterns/Optional.test.ts +164 -0
  85. package/src/patterns/Optional.ts +143 -0
  86. package/src/patterns/{Or.test.ts → Options.test.ts} +51 -49
  87. package/src/patterns/{Or.ts → Options.ts} +32 -23
  88. package/src/patterns/Pattern.ts +6 -5
  89. package/src/patterns/Reference.test.ts +21 -22
  90. package/src/patterns/Reference.ts +26 -15
  91. package/src/patterns/Regex.test.ts +15 -15
  92. package/src/patterns/Regex.ts +29 -19
  93. package/src/patterns/Repeat.test.ts +12 -22
  94. package/src/patterns/Repeat.ts +22 -21
  95. package/src/patterns/{And.test.ts → Sequence.test.ts} +78 -78
  96. package/src/patterns/{And.ts → Sequence.ts} +40 -29
  97. package/src/patterns/arePatternsEqual.ts +12 -0
  98. package/src/patterns/clonePatterns.ts +2 -2
  99. package/src/grammar/patterns/andLiteral.ts +0 -8
  100. package/src/grammar/patterns/orLiteral.ts +0 -8
@@ -1,11 +1,14 @@
1
- import { And } from "../patterns/And";
1
+ import { Sequence } from "../patterns/Sequence";
2
+ import { arePatternsEqual } from "../patterns/arePatternsEqual";
2
3
  import { Literal } from "../patterns/Literal";
3
4
  import { Not } from "../patterns/Not";
4
- import { Or } from "../patterns/Or";
5
+ import { Options } from "../patterns/Options";
5
6
  import { Pattern } from "../patterns/Pattern";
7
+ import { Reference } from "../patterns/Reference";
6
8
  import { Regex } from "../patterns/Regex";
7
9
  import { Repeat } from "../patterns/Repeat";
8
10
  import { Grammar } from "./Grammar";
11
+ import { Optional } from "../patterns/Optional";
9
12
 
10
13
  describe("Grammar", () => {
11
14
  test("Literal", () => {
@@ -14,10 +17,10 @@ describe("Grammar", () => {
14
17
  `;
15
18
 
16
19
  const patterns = Grammar.parseString(expression);
17
- const namePattern = patterns.get("name");
20
+ const namePattern = patterns["name"];
18
21
  const expected = new Literal("name", "John");
19
22
 
20
- expect(namePattern).toEqual(expected);
23
+ expect(arePatternsEqual(namePattern, expected)).toBeTruthy();
21
24
  });
22
25
 
23
26
  test("Literal With Escaped Characters", () => {
@@ -25,10 +28,21 @@ describe("Grammar", () => {
25
28
  chars = "\\n\\r\\t\\b\\f\\v\\0\\x00\\u0000\\"\\\\"
26
29
  `;
27
30
  const patterns = Grammar.parseString(expression);
28
- const namePattern = patterns.get("chars");
31
+ const namePattern = patterns["chars"];
29
32
  const expected = new Literal("chars", "\n\r\t\b\f\v\0\x00\u0000\"\\");
30
33
 
31
- expect(namePattern).toEqual(expected);
34
+ expect(arePatternsEqual(namePattern, expected)).toBeTruthy();
35
+ });
36
+
37
+ test("Literal With Escaped Quotes", () => {
38
+ const expression = `
39
+ content = "With Con\\"tent"
40
+ `;
41
+ const patterns = Grammar.parseString(expression);
42
+ const namePattern = patterns["content"];
43
+ const expected = new Literal("content", "With Con\"tent");
44
+
45
+ expect(arePatternsEqual(namePattern, expected)).toBeTruthy();
32
46
  });
33
47
 
34
48
  test("Regex", () => {
@@ -37,10 +51,10 @@ describe("Grammar", () => {
37
51
  `;
38
52
 
39
53
  const patterns = Grammar.parseString(expression);
40
- const pattern = patterns.get("name");
54
+ const pattern = patterns["name"];
41
55
  const name = new Regex("name", "\\w");
42
56
 
43
- expect(pattern).toEqual(name);
57
+ expect(arePatternsEqual(pattern, name)).toBeTruthy();
44
58
  });
45
59
 
46
60
  test("Or", () => {
@@ -51,12 +65,12 @@ describe("Grammar", () => {
51
65
  `;
52
66
 
53
67
  const patterns = Grammar.parseString(expression);
54
- const pattern = patterns.get("names");
68
+ const pattern = patterns["names"];
55
69
  const john = new Literal("john", "John");
56
70
  const jane = new Literal("jane", "Jane");
57
- const names = new Or("names", [john, jane], false, true);
71
+ const names = new Options("names", [john, jane], true);
58
72
 
59
- expect(pattern).toEqual(names);
73
+ expect(arePatternsEqual(pattern, names)).toBeTruthy();
60
74
  });
61
75
 
62
76
  test("And", () => {
@@ -64,17 +78,17 @@ describe("Grammar", () => {
64
78
  space = " "
65
79
  first-name = /\\w/
66
80
  last-name = /\\w/
67
- full-name = first-name & space & last-name
81
+ full-name = first-name + space + last-name
68
82
  `;
69
83
 
70
84
  const patterns = Grammar.parseString(expression);
71
- const pattern = patterns.get("full-name");
85
+ const pattern = patterns["full-name"];
72
86
  const space = new Literal("space", " ");
73
87
  const firstName = new Regex("first-name", "\\w");
74
88
  const lastName = new Regex("last-name", "\\w");
75
- const fullName = new And("full-name", [firstName, space, lastName]);
89
+ const fullName = new Sequence("full-name", [firstName, space, lastName]);
76
90
 
77
- expect(pattern).toEqual(fullName);
91
+ expect(arePatternsEqual(pattern, fullName)).toBeTruthy();
78
92
  });
79
93
 
80
94
  test("And With Optional Pattern", () => {
@@ -83,20 +97,20 @@ describe("Grammar", () => {
83
97
  first-name = /\\w/
84
98
  last-name = /\\w/
85
99
  middle-name = /\\w/
86
- middle-name-with-space = middle-name & space
87
- full-name = first-name & space & middle-name-with-space? & last-name
100
+ middle-name-with-space = middle-name + space
101
+ full-name = first-name + space + middle-name-with-space? + last-name
88
102
  `;
89
103
 
90
104
  const patterns = Grammar.parseString(expression);
91
- const pattern = patterns.get("full-name");
105
+ const pattern = patterns["full-name"];
92
106
  const space = new Literal("space", " ");
93
107
  const firstName = new Regex("first-name", "\\w");
94
108
  const lastName = new Regex("last-name", "\\w");
95
109
  const middleName = new Regex("middle-name", "\\w");
96
- const middleNameWithSpace = new And("middle-name-with-space", [middleName, space], true);
97
- const fullName = new And("full-name", [firstName, space, middleNameWithSpace, lastName]);
110
+ const middleNameWithSpace = new Optional("optional-middle-name-with-space", new Sequence("middle-name-with-space", [middleName, space]));
111
+ const fullName = new Sequence("full-name", [firstName, space, middleNameWithSpace, lastName]);
98
112
 
99
- expect(pattern).toEqual(fullName);
113
+ expect(arePatternsEqual(pattern, fullName)).toBeTruthy();
100
114
  });
101
115
 
102
116
  test("And With Not Pattern", () => {
@@ -106,22 +120,21 @@ describe("Grammar", () => {
106
120
  last-name = /\\w/
107
121
  middle-name = /\\w/
108
122
  jack = "Jack"
109
- middle-name-with-space = middle-name & space
110
- full-name = !jack & first-name & space & middle-name-with-space? & last-name
123
+ middle-name-with-space = middle-name + space
124
+ full-name = !jack + first-name + space + middle-name-with-space? + last-name
111
125
  `;
112
126
 
113
127
  const patterns = Grammar.parseString(expression);
114
- const pattern = patterns.get("full-name");
128
+ const pattern = patterns["full-name"];
115
129
  const space = new Literal("space", " ");
116
130
  const firstName = new Regex("first-name", "\\w");
117
131
  const lastName = new Regex("last-name", "\\w");
118
132
  const middleName = new Regex("middle-name", "\\w");
119
133
  const jack = new Literal("jack", "Jack");
120
134
  const notJack = new Not("not-jack", jack);
121
- const middleNameWithSpace = new And("middle-name-with-space", [middleName, space], true);
122
- const fullName = new And("full-name", [notJack, firstName, space, middleNameWithSpace, lastName]);
123
-
124
- expect(pattern).toEqual(fullName);
135
+ const middleNameWithSpace = new Optional("optional-middle-name-with-space", new Sequence("middle-name-with-space", [middleName, space]));
136
+ const fullName = new Sequence("full-name", [notJack, firstName, space, middleNameWithSpace, lastName]);
137
+ expect(arePatternsEqual(pattern, fullName)).toBeTruthy();
125
138
  });
126
139
 
127
140
  test("Repeat", () => {
@@ -131,11 +144,11 @@ describe("Grammar", () => {
131
144
  `;
132
145
 
133
146
  const patterns = Grammar.parseString(expression);
134
- const pattern = patterns.get("digits");
147
+ const pattern = patterns["digits"];
135
148
  const digit = new Regex("digit", "\\d");
136
149
  const digits = new Repeat("digits", digit);
137
150
 
138
- expect(pattern).toEqual(digits);
151
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
139
152
  });
140
153
 
141
154
  test("Repeat Zero Or More", () => {
@@ -145,11 +158,11 @@ describe("Grammar", () => {
145
158
  `;
146
159
 
147
160
  const patterns = Grammar.parseString(expression);
148
- const pattern = patterns.get("digits");
161
+ const pattern = patterns["digits"];
149
162
  const digit = new Regex("digit", "\\d");
150
- const digits = new Repeat("digits", digit, { min: 0 });
163
+ const digits = new Optional("digits", new Repeat("digits", digit, { min: 0 }));
151
164
 
152
- expect(pattern).toEqual(digits);
165
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
153
166
  });
154
167
 
155
168
  test("Repeat Lower Limit", () => {
@@ -159,11 +172,11 @@ describe("Grammar", () => {
159
172
  `;
160
173
 
161
174
  const patterns = Grammar.parseString(expression);
162
- const pattern = patterns.get("digits");
175
+ const pattern = patterns["digits"];
163
176
  const digit = new Regex("digit", "\\d+");
164
177
  const digits = new Repeat("digits", digit, { min: 1 });
165
178
 
166
- expect(pattern).toEqual(digits);
179
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
167
180
  });
168
181
 
169
182
  test("Repeat Bounded", () => {
@@ -173,11 +186,10 @@ describe("Grammar", () => {
173
186
  `;
174
187
 
175
188
  const patterns = Grammar.parseString(expression);
176
- const pattern = patterns.get("digits");
189
+ const pattern = patterns["digits"];
177
190
  const digit = new Regex("digit", "\\d+");
178
191
  const digits = new Repeat("digits", digit, { min: 1, max: 3 });
179
-
180
- expect(pattern).toEqual(digits);
192
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
181
193
  });
182
194
 
183
195
  test("Repeat Upper Limit", () => {
@@ -187,11 +199,11 @@ describe("Grammar", () => {
187
199
  `;
188
200
 
189
201
  const patterns = Grammar.parseString(expression);
190
- const pattern = patterns.get("digits");
202
+ const pattern = patterns["digits"];
191
203
  const digit = new Regex("digit", "\\d+");
192
204
  const digits = new Repeat("digits", digit, { min: 0, max: 3 });
193
205
 
194
- expect(pattern).toEqual(digits);
206
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
195
207
  });
196
208
 
197
209
  test("Repeat Exact", () => {
@@ -201,11 +213,11 @@ describe("Grammar", () => {
201
213
  `;
202
214
 
203
215
  const patterns = Grammar.parseString(expression);
204
- const pattern = patterns.get("digits");
216
+ const pattern = patterns["digits"];
205
217
  const digit = new Regex("digit", "\\d+");
206
218
  const digits = new Repeat("digits", digit, { min: 3, max: 3 });
207
219
 
208
- expect(pattern).toEqual(digits);
220
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
209
221
  });
210
222
 
211
223
  test("Repeat Divider", () => {
@@ -216,28 +228,44 @@ describe("Grammar", () => {
216
228
  `;
217
229
 
218
230
  const patterns = Grammar.parseString(expression);
219
- const pattern = patterns.get("digits");
231
+ const pattern = patterns["digits"];
220
232
  const digit = new Regex("digit", "\\d+");
221
233
  const divider = new Literal("comma", ",");
222
234
  const digits = new Repeat("digits", digit, { divider, min: 3, max: 3 });
223
235
 
224
- expect(pattern).toEqual(digits);
236
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
225
237
  });
226
238
 
227
239
  test("Repeat Divider With Trim Divider", () => {
228
240
  const expression = `
229
241
  digit = /\\d+/
230
242
  comma = ","
231
- digits = (digit, comma){3} -t
243
+ digits = (digit, comma trim)+
244
+ `;
245
+
246
+ const patterns = Grammar.parseString(expression);
247
+ const pattern = patterns["digits"];
248
+ const digit = new Regex("digit", "\\d+");
249
+ const divider = new Literal("comma", ",");
250
+ const digits = new Repeat("digits", digit, { divider, min: 1, trimDivider: true });
251
+ debugger;
252
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
253
+ });
254
+
255
+ test("Repeat Divider With Trim Divider And Bounds", () => {
256
+ const expression = `
257
+ digit = /\\d+/
258
+ comma = ","
259
+ digits = (digit, comma trim){3, 3}
232
260
  `;
233
261
 
234
262
  const patterns = Grammar.parseString(expression);
235
- const pattern = patterns.get("digits");
263
+ const pattern = patterns["digits"];
236
264
  const digit = new Regex("digit", "\\d+");
237
265
  const divider = new Literal("comma", ",");
238
266
  const digits = new Repeat("digits", digit, { divider, min: 3, max: 3, trimDivider: true });
239
267
 
240
- expect(pattern).toEqual(digits);
268
+ expect(arePatternsEqual(pattern, digits)).toBeTruthy();
241
269
  });
242
270
 
243
271
  test("Reference", () => {
@@ -248,15 +276,15 @@ describe("Grammar", () => {
248
276
  close-bracket = "]"
249
277
  spaces = /\\s+/
250
278
  items = digit | array
251
- array-items = (items, divider)* -t
252
- array = open-bracket & spaces? & array-items? & spaces? & close-bracket
279
+ array-items = (items, divider trim)*
280
+ array = open-bracket + spaces? + array-items + spaces? + close-bracket
253
281
  `;
254
282
 
255
283
  const patterns = Grammar.parseString(expression);
256
- const pattern = patterns.get("array") as Pattern;
284
+ const pattern = patterns["array"] as Pattern;
257
285
 
258
286
  let text = "[1, []]";
259
- let result = pattern.exec(text);
287
+ let result = pattern.exec(text, true);
260
288
 
261
289
  expect(result.ast?.value).toEqual("[1, []]");
262
290
  });
@@ -269,14 +297,14 @@ describe("Grammar", () => {
269
297
 
270
298
  const patterns = Grammar.parseString(expression);
271
299
 
272
- const name = patterns.get("name");
300
+ const name = patterns["name"];
273
301
  const expectedName = new Regex("name", "regex");
274
302
 
275
- const alias = patterns.get("alias");
303
+ const alias = patterns["alias"];
276
304
  const expectedAlias = new Regex("alias", "regex");
277
305
 
278
- expect(name).toEqual(expectedName);
279
- expect(alias).toEqual(expectedAlias);
306
+ expect(arePatternsEqual(name, expectedName)).toBeTruthy();
307
+ expect(arePatternsEqual(alias, expectedAlias)).toBeTruthy();
280
308
  });
281
309
 
282
310
  test("Bad Grammar At Beginning", () => {
@@ -295,7 +323,7 @@ describe("Grammar", () => {
295
323
  age = /()
296
324
  `;
297
325
  Grammar.parseString(expression);
298
- }).toThrowError("[Parse Error] Found: ' age = /()\n ', expected: ' age = !' or ' age = (' or ' age = [Pattern Name]' or ' age = [Regular Expression]' or ' age = [String]'.")
326
+ }).toThrow();
299
327
 
300
328
  });
301
329
 
@@ -305,15 +333,15 @@ describe("Grammar", () => {
305
333
  import { first-name } from "some/path/to/file.cpat"
306
334
  last-name = "Doe"
307
335
  space = " "
308
- full-name = first-name & space & last-name
309
- `
336
+ full-name = first-name + space + last-name
337
+ `;
310
338
  function resolveImport(resource: string) {
311
339
  expect(resource).toBe("some/path/to/file.cpat");
312
340
  return Promise.resolve({ expression: importExpression, resource });
313
341
  }
314
342
 
315
343
  const patterns = await Grammar.parse(expression, { resolveImport });
316
- const fullname = patterns.get("full-name") as Pattern;
344
+ const fullname = patterns["full-name"] as Pattern;
317
345
  const result = fullname.exec("John Doe");
318
346
 
319
347
  expect(result?.ast?.value).toBe("John Doe");
@@ -321,7 +349,7 @@ describe("Grammar", () => {
321
349
 
322
350
  test("Imports", async () => {
323
351
  const importExpression = `first-name = "John"`;
324
- const spaceExpression = `space = " "`
352
+ const spaceExpression = `space = " "`;
325
353
 
326
354
  const pathMap: Record<string, string> = {
327
355
  "space.cpat": spaceExpression,
@@ -332,14 +360,14 @@ describe("Grammar", () => {
332
360
  import { first-name } from "first-name.cpat"
333
361
  import { space } from "space.cpat"
334
362
  last-name = "Doe"
335
- full-name = first-name & space & last-name
336
- `
363
+ full-name = first-name + space + last-name
364
+ `;
337
365
  function resolveImport(resource: string) {
338
366
  return Promise.resolve({ expression: pathMap[resource], resource });
339
367
  }
340
368
 
341
369
  const patterns = await Grammar.parse(expression, { resolveImport });
342
- const fullname = patterns.get("full-name") as Pattern;
370
+ const fullname = patterns["full-name"] as Pattern;
343
371
  const result = fullname.exec("John Doe");
344
372
  expect(result?.ast?.value).toBe("John Doe");
345
373
  });
@@ -349,13 +377,13 @@ describe("Grammar", () => {
349
377
  const spaceExpression = `
350
378
  use params { custom-space }
351
379
  space = custom-space
352
- `
380
+ `;
353
381
  const expression = `
354
382
  import { first-name } from "first-name.cpat"
355
383
  import { space } from "space.cpat" with params { custom-space = " " }
356
384
  last-name = "Doe"
357
- full-name = first-name & space & last-name
358
- `
385
+ full-name = first-name + space + last-name
386
+ `;
359
387
 
360
388
  const pathMap: Record<string, string> = {
361
389
  "space.cpat": spaceExpression,
@@ -367,7 +395,7 @@ describe("Grammar", () => {
367
395
  }
368
396
 
369
397
  const patterns = await Grammar.parse(expression, { resolveImport });
370
- const fullname = patterns.get("full-name") as Pattern;
398
+ const fullname = patterns["full-name"] as Pattern;
371
399
  const result = fullname.exec("John Doe");
372
400
  expect(result?.ast?.value).toBe("John Doe");
373
401
  });
@@ -380,7 +408,7 @@ describe("Grammar", () => {
380
408
  }
381
409
 
382
410
  name
383
- `
411
+ `;
384
412
 
385
413
  const resource1 = `
386
414
  use-this = "Use This"
@@ -402,7 +430,7 @@ describe("Grammar", () => {
402
430
  return Promise.resolve({ expression: pathMap[resource], resource });
403
431
  }
404
432
  const patterns = await Grammar.parse(expression, { resolveImport });
405
- const pattern = patterns.get("name") as Literal;
433
+ const pattern = patterns["name"] as Literal;
406
434
 
407
435
  const result = pattern.exec("Use This");
408
436
 
@@ -416,7 +444,7 @@ describe("Grammar", () => {
416
444
  param = alias
417
445
  }
418
446
  name = export-value
419
- `
447
+ `;
420
448
 
421
449
  const resource1 = `
422
450
  value = "Value"
@@ -427,7 +455,7 @@ describe("Grammar", () => {
427
455
  param
428
456
  }
429
457
  export-value = param
430
- `
458
+ `;
431
459
 
432
460
  const pathMap: Record<string, string> = {
433
461
  "resource1": resource1,
@@ -438,9 +466,35 @@ describe("Grammar", () => {
438
466
  return Promise.resolve({ expression: pathMap[resource], resource });
439
467
  }
440
468
  const patterns = await Grammar.parse(expression, { resolveImport });
441
- const pattern = patterns.get("name") as Literal;
469
+ const pattern = patterns["name"] as Literal;
442
470
 
443
471
  const result = pattern.exec("Value");
444
472
  expect(result.ast?.value).toBe("Value");
445
473
  });
474
+
475
+ test("Anonymous Patterns", () => {
476
+ const expression = `
477
+ complex-expression = !"NOT_THIS" + "Text"? + /regex/ + ("Text" <|> /regex/ <|> (pattern)+) + (pattern | pattern)
478
+ `;
479
+
480
+ const patterns = Grammar.parseString(expression);
481
+ const expected = new Sequence("complex-expression", [
482
+ new Not("not-NOT_THIS", new Literal("NOT_THIS", "NOT_THIS")),
483
+ new Optional("Text", new Literal("Text", "Text")),
484
+ new Regex("regex", "regex"),
485
+ new Options("anonymous", [
486
+ new Literal("Text", "Text"),
487
+ new Regex("regex", "regex"),
488
+ new Repeat("anonymous", new Reference("pattern")),
489
+ ],
490
+ true
491
+ ),
492
+ new Options("anonymous", [
493
+ new Reference("pattern"),
494
+ new Reference("pattern")
495
+ ])
496
+ ]);
497
+
498
+ expect(arePatternsEqual(patterns["complex-expression"], expected)).toBeTruthy();
499
+ });
446
500
  });