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.
- package/TODO.md +4 -1
- package/dist/grammar/Grammar.d.ts +18 -10
- package/dist/grammar/patterns/andLiteral.d.ts +2 -0
- package/dist/grammar/patterns/anonymousPattern.d.ts +2 -0
- package/dist/grammar/patterns/inlinePattern.d.ts +1 -0
- package/dist/grammar/patterns/literals.d.ts +3 -0
- package/dist/grammar/patterns/pattern.d.ts +2 -2
- package/dist/grammar/patterns.d.ts +2 -0
- package/dist/index.browser.js +472 -185
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +471 -186
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +472 -185
- package/dist/index.js.map +1 -1
- package/dist/patterns/And.d.ts +4 -1
- package/dist/patterns/Cursor.d.ts +5 -0
- package/dist/patterns/CursorHistory.d.ts +7 -0
- package/dist/patterns/FiniteRepeat.d.ts +4 -1
- package/dist/patterns/InfiniteRepeat.d.ts +5 -4
- package/dist/patterns/Literal.d.ts +6 -5
- package/dist/patterns/Not.d.ts +5 -4
- package/dist/patterns/Or.d.ts +5 -4
- package/dist/patterns/Pattern.d.ts +4 -2
- package/dist/patterns/Reference.d.ts +5 -4
- package/dist/patterns/Regex.d.ts +5 -4
- package/dist/patterns/Repeat.d.ts +3 -0
- package/dist/patterns/arePatternsEqual.d.ts +2 -0
- package/package.json +1 -1
- package/src/grammar/Grammar.test.ts +126 -72
- package/src/grammar/Grammar.ts +241 -158
- package/src/grammar/patterns/anonymousPattern.ts +23 -0
- package/src/grammar/patterns/body.ts +9 -6
- package/src/grammar/patterns/comment.ts +3 -2
- package/src/grammar/patterns/grammar.ts +15 -12
- package/src/grammar/patterns/import.ts +18 -12
- package/src/grammar/patterns/literal.ts +2 -3
- package/src/grammar/patterns/literals.ts +20 -0
- package/src/grammar/patterns/optionsLiteral.ts +19 -0
- package/src/grammar/patterns/pattern.ts +23 -9
- package/src/grammar/patterns/regexLiteral.ts +1 -0
- package/src/grammar/patterns/repeatLiteral.ts +30 -25
- package/src/grammar/patterns/sequenceLiteral.ts +24 -0
- package/src/grammar/patterns/spaces.ts +8 -6
- package/src/grammar/patterns/statement.ts +8 -20
- package/src/grammar/patterns.test.ts +38 -0
- package/src/grammar/patterns.ts +24 -0
- package/src/grammar/spec.md +4 -12
- package/src/index.ts +11 -5
- package/src/intellisense/AutoComplete.test.ts +41 -40
- package/src/intellisense/css/method.ts +2 -2
- package/src/intellisense/css/unit.ts +2 -2
- package/src/intellisense/css/value.ts +1 -1
- package/src/intellisense/javascript/Javascript.test.ts +31 -32
- package/src/intellisense/javascript/arrayLiteral.ts +7 -6
- package/src/intellisense/javascript/assignment.ts +6 -6
- package/src/intellisense/javascript/deleteStatement.ts +2 -2
- package/src/intellisense/javascript/escapedCharacter.ts +6 -6
- package/src/intellisense/javascript/exponent.ts +6 -6
- package/src/intellisense/javascript/expression.ts +18 -17
- package/src/intellisense/javascript/fraction.ts +3 -3
- package/src/intellisense/javascript/infixOperator.ts +10 -10
- package/src/intellisense/javascript/integer.ts +1 -1
- package/src/intellisense/javascript/invocation.ts +8 -7
- package/src/intellisense/javascript/literal.ts +3 -3
- package/src/intellisense/javascript/numberLiteral.ts +5 -4
- package/src/intellisense/javascript/objectAccess.ts +2 -3
- package/src/intellisense/javascript/objectLiteral.ts +8 -7
- package/src/intellisense/javascript/optionalSpaces.ts +2 -1
- package/src/intellisense/javascript/parameters.ts +5 -5
- package/src/intellisense/javascript/prefixOperator.ts +3 -4
- package/src/intellisense/javascript/propertyAccess.ts +9 -8
- package/src/intellisense/javascript/stringLiteral.ts +14 -15
- package/src/patterns/Cursor.ts +42 -4
- package/src/patterns/CursorHistory.ts +20 -4
- package/src/patterns/FiniteRepeat.test.ts +52 -51
- package/src/patterns/FiniteRepeat.ts +60 -38
- package/src/patterns/InfiniteRepeat.test.ts +36 -49
- package/src/patterns/InfiniteRepeat.ts +70 -37
- package/src/patterns/Literal.test.ts +16 -27
- package/src/patterns/Literal.ts +34 -27
- package/src/patterns/Not.test.ts +7 -7
- package/src/patterns/Not.ts +24 -6
- package/src/patterns/Optional.test.ts +164 -0
- package/src/patterns/Optional.ts +143 -0
- package/src/patterns/{Or.test.ts → Options.test.ts} +51 -49
- package/src/patterns/{Or.ts → Options.ts} +32 -23
- package/src/patterns/Pattern.ts +6 -5
- package/src/patterns/Reference.test.ts +21 -22
- package/src/patterns/Reference.ts +26 -15
- package/src/patterns/Regex.test.ts +15 -15
- package/src/patterns/Regex.ts +29 -19
- package/src/patterns/Repeat.test.ts +12 -22
- package/src/patterns/Repeat.ts +22 -21
- package/src/patterns/{And.test.ts → Sequence.test.ts} +78 -78
- package/src/patterns/{And.ts → Sequence.ts} +40 -29
- package/src/patterns/arePatternsEqual.ts +12 -0
- package/src/patterns/clonePatterns.ts +2 -2
- package/src/grammar/patterns/andLiteral.ts +0 -8
- package/src/grammar/patterns/orLiteral.ts +0 -8
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { Cursor } from "./Cursor";
|
|
2
|
-
import {
|
|
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("
|
|
7
|
+
describe("Sequence", () => {
|
|
7
8
|
test("No Patterns", () => {
|
|
8
9
|
expect(() => {
|
|
9
|
-
new
|
|
10
|
-
}).toThrowError()
|
|
10
|
+
new Sequence("empty", []);
|
|
11
|
+
}).toThrowError();
|
|
11
12
|
});
|
|
12
13
|
|
|
13
14
|
test("One Pattern Match Successful", () => {
|
|
14
|
-
const sequence = new
|
|
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("
|
|
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
|
|
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
|
|
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("
|
|
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
|
|
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
|
|
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
|
|
80
|
+
const sequence = new Sequence("sequence", [
|
|
80
81
|
new Literal("a", "A"),
|
|
81
|
-
new Literal("b", "B"
|
|
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("
|
|
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
|
|
96
|
+
const sequence = new Sequence("sequence", [
|
|
96
97
|
new Literal("a", "A"),
|
|
97
|
-
new Literal("b", "B"
|
|
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("
|
|
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
|
|
112
|
+
const sequence = new Optional("optional-sequence", new Sequence("sequence", [
|
|
112
113
|
new Literal("a", "A"),
|
|
113
114
|
new Literal("b", "B")
|
|
114
|
-
]
|
|
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
|
|
125
|
-
new Literal("a", "A"
|
|
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
|
-
]
|
|
129
|
+
]));
|
|
129
130
|
const cursor = new Cursor("BC");
|
|
130
131
|
const result = sequence.parse(cursor);
|
|
131
|
-
const expected = new Node("
|
|
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
|
|
143
|
+
const sequence = new Optional("optional-sequence", new Sequence("sequence", [
|
|
143
144
|
new Literal("a", "A"),
|
|
144
|
-
]
|
|
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
|
|
155
|
-
new Literal("a", "A"
|
|
156
|
-
new Literal("b", "B"
|
|
157
|
-
]
|
|
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"
|
|
168
|
-
const sequence = new
|
|
168
|
+
const a = new Literal("a", "A");
|
|
169
|
+
const sequence = new Sequence("sequence", [
|
|
169
170
|
a,
|
|
170
|
-
]
|
|
171
|
+
]);
|
|
171
172
|
|
|
172
|
-
expect(sequence.type).toBe("
|
|
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
|
|
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("
|
|
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
|
|
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
|
|
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"
|
|
208
|
-
const sequence = new
|
|
207
|
+
const a = new Optional("a", new Literal("a", "A"));
|
|
208
|
+
const sequence = new Sequence("sequence", [
|
|
209
209
|
a,
|
|
210
|
-
]
|
|
211
|
-
const parent = new
|
|
210
|
+
]);
|
|
211
|
+
const parent = new Sequence("parent", [sequence]);
|
|
212
212
|
|
|
213
|
-
expect(parent.type).toBe("
|
|
214
|
-
expect(parent.children[0].type).toBe("
|
|
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
|
|
219
|
-
new Literal("a", "A"
|
|
218
|
+
const sequence = new Sequence("sequence", [
|
|
219
|
+
new Optional("a", new Literal("a", "A")),
|
|
220
220
|
new Literal("b", "B"),
|
|
221
|
-
]
|
|
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
|
|
229
|
+
const sequence = new Sequence("sequence", [
|
|
230
230
|
new Literal("a", "A"),
|
|
231
|
-
new Literal("b", "B"
|
|
231
|
+
new Optional("b", new Literal("b", "B")),
|
|
232
232
|
new Literal("c", "C"),
|
|
233
|
-
]
|
|
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
|
|
242
|
+
const sequence = new Sequence("sequence", [
|
|
243
243
|
new Literal("a", "A"),
|
|
244
|
-
new Literal("b", "B"
|
|
244
|
+
new Optional("b", new Literal("b", "B")),
|
|
245
245
|
new Literal("c", "C"),
|
|
246
|
-
]
|
|
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
|
|
254
|
+
const sequence = new Sequence("sequence", [
|
|
255
255
|
new Literal("a", "A"),
|
|
256
|
-
]
|
|
257
|
-
const parent = new
|
|
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
|
|
266
|
+
const sequence = new Sequence("sequence", [
|
|
267
267
|
new Literal("a", "A"),
|
|
268
|
-
new Literal("b", "B"
|
|
269
|
-
]
|
|
270
|
-
const parent = new
|
|
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
|
|
279
|
-
const parent = new
|
|
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
|
|
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
|
|
296
|
-
new Literal("a", "A"
|
|
295
|
+
const sequence = new Sequence("sequence", [
|
|
296
|
+
new Optional("a", new Literal("a", "A")),
|
|
297
297
|
new Literal("b", "B"),
|
|
298
|
-
]
|
|
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
|
|
309
|
-
const parent = new
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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 (
|
|
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
|
-
"
|
|
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 (
|
|
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
|
|
240
|
-
patterns.push(...
|
|
243
|
+
for (const child of this._children) {
|
|
244
|
+
patterns.push(...child.getPatterns());
|
|
241
245
|
|
|
242
|
-
if (
|
|
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 (
|
|
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
|
|
305
|
-
|
|
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[]
|
|
4
|
-
return patterns.map(p => p.clone(
|
|
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 });
|