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,20 +1,21 @@
1
1
  import { Cursor } from "./Cursor";
2
- import { And } from "./And";
2
+ import { Sequence } from "./Sequence";
3
3
  import { Literal } from "./Literal";
4
- import { Node } from "../ast/Node"
4
+ import { Node } from "../ast/Node";
5
+ import { Optional } from "./Optional";
5
6
 
6
- describe("And", () => {
7
+ describe("Sequence", () => {
7
8
  test("No Patterns", () => {
8
9
  expect(() => {
9
- new And("empty", [])
10
- }).toThrowError()
10
+ new Sequence("empty", []);
11
+ }).toThrowError();
11
12
  });
12
13
 
13
14
  test("One Pattern Match Successful", () => {
14
- const sequence = new And("sequence", [new Literal("a", "A")]);
15
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
15
16
  const cursor = new Cursor("A");
16
17
  const result = sequence.parse(cursor);
17
- const expected = new Node("and", "sequence", 0, 0, [
18
+ const expected = new Node("sequence", "sequence", 0, 0, [
18
19
  new Node("literal", "a", 0, 0, [], "A")
19
20
  ]);
20
21
 
@@ -24,7 +25,7 @@ describe("And", () => {
24
25
  });
25
26
 
26
27
  test("One Pattern Match Fails", () => {
27
- const sequence = new And("sequence", [new Literal("a", "A")]);
28
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
28
29
  const cursor = new Cursor("V");
29
30
  const result = sequence.parse(cursor);
30
31
 
@@ -35,13 +36,13 @@ describe("And", () => {
35
36
  });
36
37
 
37
38
  test("Two Pattern Match Successful", () => {
38
- const sequence = new And("sequence", [
39
+ const sequence = new Sequence("sequence", [
39
40
  new Literal("a", "A"),
40
41
  new Literal("b", "B")
41
42
  ]);
42
43
  const cursor = new Cursor("AB");
43
44
  const result = sequence.parse(cursor);
44
- const expected = new Node("and", "sequence", 0, 1, [
45
+ const expected = new Node("sequence", "sequence", 0, 1, [
45
46
  new Node("literal", "a", 0, 0, [], "A"),
46
47
  new Node("literal", "b", 1, 1, [], "B")
47
48
  ]);
@@ -52,7 +53,7 @@ describe("And", () => {
52
53
  });
53
54
 
54
55
  test("Two Pattern Match Fails", () => {
55
- const sequence = new And("sequence", [
56
+ const sequence = new Sequence("sequence", [
56
57
  new Literal("a", "A"),
57
58
  new Literal("b", "B")
58
59
  ]);
@@ -66,39 +67,39 @@ describe("And", () => {
66
67
  });
67
68
 
68
69
  test("One Pattern Match Fails (Optional)", () => {
69
- const sequence = new And("sequence", [new Literal("a", "A")], true);
70
+ const sequence = new Optional("optional-sequence", new Sequence("sequence", [new Literal("a", "A")]));
70
71
  const cursor = new Cursor("V");
71
72
  const result = sequence.parse(cursor);
72
73
 
73
74
  expect(result).toEqual(null);
74
- expect(cursor.error).toBe(null)
75
+ expect(cursor.error).toBe(null);
75
76
  expect(cursor.index).toBe(0);
76
77
  });
77
78
 
78
79
  test("Trailing Optional Child Patterns", () => {
79
- const sequence = new And("sequence", [
80
+ const sequence = new Sequence("sequence", [
80
81
  new Literal("a", "A"),
81
- new Literal("b", "B", true)
82
+ new Optional("b", new Literal("b", "B"))
82
83
  ]);
83
84
  const cursor = new Cursor("AD");
84
85
  const result = sequence.parse(cursor);
85
- const expected = new Node("and", "sequence", 0, 0, [
86
+ const expected = new Node("sequence", "sequence", 0, 0, [
86
87
  new Node("literal", "a", 0, 0, [], "A")
87
88
  ]);
88
89
 
89
90
  expect(result).toEqual(expected);
90
- expect(cursor.error).toBe(null)
91
+ expect(cursor.error).toBe(null);
91
92
  expect(cursor.index).toBe(0);
92
93
  });
93
94
 
94
95
  test("Trailing Optional Child Patterns With No More Text", () => {
95
- const sequence = new And("sequence", [
96
+ const sequence = new Sequence("sequence", [
96
97
  new Literal("a", "A"),
97
- new Literal("b", "B", true)
98
+ new Optional("b", new Literal("b", "B"))
98
99
  ]);
99
100
  const cursor = new Cursor("A");
100
101
  const result = sequence.parse(cursor);
101
- const expected = new Node("and", "sequence", 0, 0, [
102
+ const expected = new Node("sequence", "sequence", 0, 0, [
102
103
  new Node("literal", "a", 0, 0, [], "A")
103
104
  ]);
104
105
 
@@ -108,27 +109,27 @@ describe("And", () => {
108
109
  });
109
110
 
110
111
  test("Incomplete Parse (Optional)", () => {
111
- const sequence = new And("sequence", [
112
+ const sequence = new Optional("optional-sequence", new Sequence("sequence", [
112
113
  new Literal("a", "A"),
113
114
  new Literal("b", "B")
114
- ], true);
115
+ ]));
115
116
  const cursor = new Cursor("A");
116
117
  const result = sequence.parse(cursor);
117
118
 
118
119
  expect(result).toEqual(null);
119
- expect(cursor.error).toBe(null)
120
+ expect(cursor.error).toBe(null);
120
121
  expect(cursor.index).toBe(0);
121
122
  });
122
123
 
123
124
  test("Optional Child Pattern With More Patterns", () => {
124
- const sequence = new And("sequence", [
125
- new Literal("a", "A", true),
125
+ const sequence = new Optional("optional-sequence", new Sequence("sequence", [
126
+ new Optional("a", new Literal("a", "A")),
126
127
  new Literal("b", "B"),
127
128
  new Literal("c", "C")
128
- ], true);
129
+ ]));
129
130
  const cursor = new Cursor("BC");
130
131
  const result = sequence.parse(cursor);
131
- const expected = new Node("and", "sequence", 0, 1, [
132
+ const expected = new Node("sequence", "sequence", 0, 1, [
132
133
  new Node("literal", "b", 0, 0, [], "B"),
133
134
  new Node("literal", "c", 1, 1, [], "C"),
134
135
  ]);
@@ -139,49 +140,48 @@ describe("And", () => {
139
140
  });
140
141
 
141
142
  test("Nothing Matched", () => {
142
- const sequence = new And("sequence", [
143
+ const sequence = new Optional("optional-sequence", new Sequence("sequence", [
143
144
  new Literal("a", "A"),
144
- ], true);
145
+ ]));
145
146
  const cursor = new Cursor("BC");
146
147
  const result = sequence.parse(cursor);
147
148
 
148
149
  expect(result).toEqual(null);
149
- expect(cursor.error).toBe(null)
150
+ expect(cursor.error).toBe(null);
150
151
  expect(cursor.index).toBe(0);
151
152
  });
152
153
 
153
154
  test("No Matches On Optional Child Patterns", () => {
154
- const sequence = new And("sequence", [
155
- new Literal("a", "A", true),
156
- new Literal("b", "B", true),
157
- ], true);
155
+ const sequence = new Optional("optional-sequence", new Sequence("sequence", [
156
+ new Optional("a", new Literal("a", "A")),
157
+ new Optional("b", new Literal("b", "B")),
158
+ ]));
158
159
  const cursor = new Cursor("XYZ");
159
160
  const result = sequence.parse(cursor);
160
161
 
161
162
  expect(result).toEqual(null);
162
- expect(cursor.error).toBe(null)
163
+ expect(cursor.error).toBe(null);
163
164
  expect(cursor.index).toBe(0);
164
165
  });
165
166
 
166
167
  test("Properties", () => {
167
- const a = new Literal("a", "A", true)
168
- const sequence = new And("sequence", [
168
+ const a = new Literal("a", "A");
169
+ const sequence = new Sequence("sequence", [
169
170
  a,
170
- ], true);
171
+ ]);
171
172
 
172
- expect(sequence.type).toBe("and");
173
+ expect(sequence.type).toBe("sequence");
173
174
  expect(sequence.name).toBe("sequence");
174
175
  expect(sequence.parent).toBe(null);
175
- expect(sequence.isOptional).toBe(true);
176
176
  expect(sequence.children[0].type).toBe("literal");
177
177
  expect(sequence.children[0].name).toBe("a");
178
178
  });
179
179
 
180
180
  test("Exec", () => {
181
- const sequence = new And("sequence", [new Literal("a", "A")]);
181
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
182
182
 
183
183
  const { ast: result, cursor } = sequence.exec("A");
184
- const expected = new Node("and", "sequence", 0, 0, [
184
+ const expected = new Node("sequence", "sequence", 0, 0, [
185
185
  new Node("literal", "a", 0, 0, undefined, "A")
186
186
  ]);
187
187
 
@@ -190,71 +190,71 @@ describe("And", () => {
190
190
  });
191
191
 
192
192
  test("Test With Match", () => {
193
- const sequence = new And("sequence", [new Literal("a", "A")]);
193
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
194
194
  const hasMatch = sequence.test("A");
195
195
 
196
196
  expect(hasMatch).toBeTruthy();
197
197
  });
198
198
 
199
199
  test("Test With No Match", () => {
200
- const sequence = new And("sequence", [new Literal("a", "A")]);
200
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
201
201
  const hasMatch = sequence.test("B");
202
202
 
203
203
  expect(hasMatch).toBeFalsy();
204
204
  });
205
205
 
206
206
  test("Set Parent", () => {
207
- const a = new Literal("a", "A", true)
208
- const sequence = new And("sequence", [
207
+ const a = new Optional("a", new Literal("a", "A"));
208
+ const sequence = new Sequence("sequence", [
209
209
  a,
210
- ], true);
211
- const parent = new And("parent", [sequence]);
210
+ ]);
211
+ const parent = new Sequence("parent", [sequence]);
212
212
 
213
- expect(parent.type).toBe("and");
214
- expect(parent.children[0].type).toBe("and");
213
+ expect(parent.type).toBe("sequence");
214
+ expect(parent.children[0].type).toBe("sequence");
215
215
  });
216
216
 
217
217
  test("Get Tokens", () => {
218
- const sequence = new And("sequence", [
219
- new Literal("a", "A", true),
218
+ const sequence = new Sequence("sequence", [
219
+ new Optional("a", new Literal("a", "A")),
220
220
  new Literal("b", "B"),
221
- ], true);
222
- const tokens = sequence.getTokens()
221
+ ]);
222
+ const tokens = sequence.getTokens();
223
223
  const expected = ["A", "B"];
224
224
 
225
225
  expect(tokens).toEqual(expected);
226
226
  });
227
227
 
228
228
  test("Get Tokens After", () => {
229
- const sequence = new And("sequence", [
229
+ const sequence = new Sequence("sequence", [
230
230
  new Literal("a", "A"),
231
- new Literal("b", "B", true),
231
+ new Optional("b", new Literal("b", "B")),
232
232
  new Literal("c", "C"),
233
- ], true);
233
+ ]);
234
234
 
235
- const tokens = sequence.getTokensAfter(sequence.children[0])
235
+ const tokens = sequence.getTokensAfter(sequence.children[0]);
236
236
  const expected = ["B", "C"];
237
237
 
238
238
  expect(tokens).toEqual(expected);
239
239
  });
240
240
 
241
241
  test("Get Tokens After With Invalid Pattern", () => {
242
- const sequence = new And("sequence", [
242
+ const sequence = new Sequence("sequence", [
243
243
  new Literal("a", "A"),
244
- new Literal("b", "B", true),
244
+ new Optional("b", new Literal("b", "B")),
245
245
  new Literal("c", "C"),
246
- ], true);
246
+ ]);
247
247
 
248
- const tokens = sequence.getTokensAfter(new Literal("not-child", "not-child"))
248
+ const tokens = sequence.getTokensAfter(new Literal("not-child", "not-child"));
249
249
 
250
250
  expect(tokens).toEqual([]);
251
251
  });
252
252
 
253
253
  test("Get Tokens After With Last Child", () => {
254
- const sequence = new And("sequence", [
254
+ const sequence = new Sequence("sequence", [
255
255
  new Literal("a", "A"),
256
- ], true);
257
- const parent = new And("parent", [sequence, new Literal("b", "B")]);
256
+ ]);
257
+ const parent = new Sequence("parent", [sequence, new Literal("b", "B")]);
258
258
 
259
259
 
260
260
  const tokens = parent.children[0].getTokensAfter(parent.children[0].children[0])
@@ -263,11 +263,11 @@ describe("And", () => {
263
263
  });
264
264
 
265
265
  test("Get Tokens After With Last Optional Child", () => {
266
- const sequence = new And("sequence", [
266
+ const sequence = new Sequence("sequence", [
267
267
  new Literal("a", "A"),
268
- new Literal("b", "B", true),
269
- ], true);
270
- const parent = new And("parent", [sequence, new Literal("c", "C")]);
268
+ new Optional("b", new Literal("b", "B")),
269
+ ]);
270
+ const parent = new Sequence("parent", [sequence, new Literal("c", "C")]);
271
271
 
272
272
  const tokens = parent.children[0].getTokensAfter(parent.children[0].children[0])
273
273
 
@@ -275,8 +275,8 @@ describe("And", () => {
275
275
  });
276
276
 
277
277
  test("Get Next Tokens", () => {
278
- const sequence = new And("sequence", [new Literal("a", "A")]);
279
- const parent = new And("parent", [sequence, new Literal("b", "B")]);
278
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
279
+ const parent = new Sequence("parent", [sequence, new Literal("b", "B")]);
280
280
 
281
281
  const sequenceClone = parent.find(p => p.name === "sequence");
282
282
  const tokens = sequenceClone?.getNextTokens() || [];
@@ -285,17 +285,17 @@ describe("And", () => {
285
285
  });
286
286
 
287
287
  test("Get Next Tokens With Null Parent", () => {
288
- const sequence = new And("sequence", [new Literal("a", "A")]);
288
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
289
289
  const tokens = sequence.getNextTokens();
290
290
 
291
291
  expect(tokens.length).toBe(0);
292
292
  });
293
293
 
294
294
  test("Get Patterns", () => {
295
- const sequence = new And("sequence", [
296
- new Literal("a", "A", true),
295
+ const sequence = new Sequence("sequence", [
296
+ new Optional("a", new Literal("a", "A")),
297
297
  new Literal("b", "B"),
298
- ], true);
298
+ ]);
299
299
  const tokens = sequence.getPatterns();
300
300
  const a = sequence.find(p => p.name === "a");
301
301
  const b = sequence.find(p => p.name === "b");
@@ -305,8 +305,8 @@ describe("And", () => {
305
305
  });
306
306
 
307
307
  test("Get Next Patterns", () => {
308
- const sequence = new And("sequence", [new Literal("a", "A")]);
309
- const parent = new And("parent", [sequence, new Literal("b", "B")]);
308
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
309
+ const parent = new Sequence("parent", [sequence, new Literal("b", "B")]);
310
310
 
311
311
  const sequenceClone = parent.find(p => p.name === "sequence");
312
312
  const nextPatterns = sequenceClone?.getNextPatterns() || [];
@@ -316,7 +316,7 @@ describe("And", () => {
316
316
  });
317
317
 
318
318
  test("Get Next Patterns With Null Parent", () => {
319
- const sequence = new And("sequence", [new Literal("a", "A")]);
319
+ const sequence = new Sequence("sequence", [new Literal("a", "A")]);
320
320
  const nextPatterns = sequence.getNextPatterns()
321
321
 
322
322
  expect(nextPatterns.length).toBe(0);
@@ -5,15 +5,21 @@ import { clonePatterns } from "./clonePatterns";
5
5
  import { filterOutNull } from "./filterOutNull";
6
6
  import { findPattern } from "./findPattern";
7
7
 
8
- export class And implements Pattern {
8
+ let idIndex = 0;
9
+
10
+ export class Sequence implements Pattern {
11
+ private _id: string;
9
12
  private _type: string;
10
13
  private _name: string;
11
14
  private _parent: Pattern | null;
12
15
  private _children: Pattern[];
13
- private _isOptional: boolean;
14
16
  private _nodes: (Node | null)[];
15
17
  private _firstIndex: number;
16
18
 
19
+ get id(): string {
20
+ return this._id;
21
+ }
22
+
17
23
  get type(): string {
18
24
  return this._type;
19
25
  }
@@ -34,24 +40,20 @@ export class And implements Pattern {
34
40
  return this._children;
35
41
  }
36
42
 
37
- get isOptional(): boolean {
38
- return this._isOptional;
39
- }
40
-
41
- constructor(name: string, sequence: Pattern[], isOptional = false) {
43
+ constructor(name: string, sequence: Pattern[]) {
42
44
  if (sequence.length === 0) {
43
- throw new Error("Need at least one pattern with an 'and' pattern.");
45
+ throw new Error("Need at least one pattern with a 'sequence' pattern.");
44
46
  }
45
47
 
46
48
  const children = clonePatterns(sequence);
47
- this._assignChildrenToParent(children)
49
+ this._assignChildrenToParent(children);
48
50
 
49
- this._type = "and";
51
+ this._id = `sequence-${idIndex++}`;
52
+ this._type = "sequence";
50
53
  this._name = name;
51
- this._isOptional = isOptional;
52
54
  this._parent = null;
53
55
  this._children = children;
54
- this._firstIndex = -1
56
+ this._firstIndex = -1;
55
57
  this._nodes = [];
56
58
  }
57
59
 
@@ -68,8 +70,10 @@ export class And implements Pattern {
68
70
  return ast?.value === text;
69
71
  }
70
72
 
71
- exec(text: string) {
73
+ exec(text: string, record = false) {
72
74
  const cursor = new Cursor(text);
75
+ record && cursor.startRecording();
76
+
73
77
  const ast = this.parse(cursor);
74
78
 
75
79
  return {
@@ -79,6 +83,8 @@ export class And implements Pattern {
79
83
  }
80
84
 
81
85
  parse(cursor: Cursor): Node | null {
86
+ cursor.startParseWith(this);
87
+
82
88
  this._firstIndex = cursor.index;
83
89
  this._nodes = [];
84
90
 
@@ -91,13 +97,11 @@ export class And implements Pattern {
91
97
  cursor.recordMatch(this, node);
92
98
  }
93
99
 
100
+ cursor.endParse();
94
101
  return node;
95
102
  }
96
103
 
97
- if (this._isOptional) {
98
- cursor.resolveError();
99
- }
100
-
104
+ cursor.endParse();
101
105
  return null;
102
106
  }
103
107
 
@@ -178,7 +182,7 @@ export class And implements Pattern {
178
182
 
179
183
  for (let i = startOnIndex; i < length; i++) {
180
184
  const pattern = this._children[i];
181
- if (!pattern.isOptional) {
185
+ if (pattern.type !== "optional") {
182
186
  return false;
183
187
  }
184
188
  }
@@ -191,10 +195,10 @@ export class And implements Pattern {
191
195
 
192
196
  const lastIndex = children[children.length - 1].lastIndex;
193
197
 
194
- cursor.moveTo(lastIndex)
198
+ cursor.moveTo(lastIndex);
195
199
 
196
200
  return new Node(
197
- "and",
201
+ "sequence",
198
202
  this._name,
199
203
  this._firstIndex,
200
204
  lastIndex,
@@ -208,7 +212,7 @@ export class And implements Pattern {
208
212
  for (const child of this._children) {
209
213
  tokens.push(...child.getTokens());
210
214
 
211
- if (!child.isOptional) {
215
+ if (child.type !== "optional") {
212
216
  break;
213
217
  }
214
218
  }
@@ -227,7 +231,7 @@ export class And implements Pattern {
227
231
 
228
232
  getNextTokens(): string[] {
229
233
  if (this.parent == null) {
230
- return []
234
+ return [];
231
235
  }
232
236
 
233
237
  return this.parent.getTokensAfter(this);
@@ -236,10 +240,10 @@ export class And implements Pattern {
236
240
  getPatterns(): Pattern[] {
237
241
  const patterns: Pattern[] = [];
238
242
 
239
- for (const pattern of this._children) {
240
- patterns.push(...pattern.getPatterns());
243
+ for (const child of this._children) {
244
+ patterns.push(...child.getPatterns());
241
245
 
242
- if (!pattern.isOptional) {
246
+ if (child.type !== "optional") {
243
247
  break;
244
248
  }
245
249
  }
@@ -276,7 +280,7 @@ export class And implements Pattern {
276
280
  const child = this._children[i];
277
281
  patterns.push(child);
278
282
 
279
- if (!child.isOptional) {
283
+ if (child.type !== "optional") {
280
284
  break;
281
285
  }
282
286
 
@@ -294,14 +298,21 @@ export class And implements Pattern {
294
298
  return [];
295
299
  }
296
300
 
297
- return this.parent.getPatternsAfter(this)
301
+ return this.parent.getPatternsAfter(this);
298
302
  }
299
303
 
300
304
  find(predicate: (p: Pattern) => boolean): Pattern | null {
301
305
  return findPattern(this, predicate);
302
306
  }
303
307
 
304
- clone(name = this._name, isOptional = this._isOptional): Pattern {
305
- return new And(name, this._children, isOptional)
308
+ clone(name = this._name): Pattern {
309
+ const clone = new Sequence(name, this._children);
310
+ clone._id = this._id;
311
+
312
+ return clone;
313
+ }
314
+
315
+ isEqual(pattern: Sequence): boolean {
316
+ return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
306
317
  }
307
318
  }
@@ -0,0 +1,12 @@
1
+ import { Literal } from "./Literal";
2
+ import { Pattern } from "./Pattern";
3
+
4
+ export function arePatternsEqual(a?: Pattern | null, b?: Pattern | null): boolean {
5
+ if (a === b) {
6
+ return true;
7
+ } else if (a == null || b == null) {
8
+ return false;
9
+ }
10
+
11
+ return a.isEqual(b);
12
+ }
@@ -1,5 +1,5 @@
1
1
  import { Pattern } from "./Pattern";
2
2
 
3
- export function clonePatterns(patterns: Pattern[], isOptional?: boolean): Pattern[] {
4
- return patterns.map(p => p.clone(p.name, isOptional))
3
+ export function clonePatterns(patterns: Pattern[]): Pattern[] {
4
+ return patterns.map(p => p.clone());
5
5
  }
@@ -1,8 +0,0 @@
1
- import { Repeat } from "../../patterns/Repeat"
2
- import { Regex } from "../../patterns/Regex";
3
- import { pattern } from "./pattern";
4
-
5
- const divider = new Regex("and-divider", "\\s*[&]\\s*");
6
- divider.setTokens([" & "]);
7
-
8
- export const andLiteral = new Repeat("and-literal", pattern, { divider, min: 2, trimDivider: true });
@@ -1,8 +0,0 @@
1
- import { Repeat } from "../../patterns/Repeat"
2
- import { name } from "./name"
3
- import { Regex } from "../../patterns/Regex";
4
-
5
- const divider = new Regex("or-divider", "\\s*[|]\\s*");
6
- divider.setTokens([" | "]);
7
-
8
- export const orLiteral = new Repeat("or-literal", name.clone("pattern-name"), { divider, min: 2, trimDivider: true });