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.
- package/TODO.md +1 -78
- package/dist/ast/Node.d.ts +1 -0
- package/dist/grammar/Grammar.d.ts +17 -0
- package/dist/grammar/patterns/andLiteral.d.ts +2 -0
- package/dist/grammar/patterns/comment.d.ts +2 -0
- package/dist/grammar/patterns/grammar.d.ts +2 -0
- package/dist/grammar/patterns/literal.d.ts +2 -0
- package/dist/grammar/patterns/name.d.ts +2 -0
- package/dist/grammar/patterns/orLiteral.d.ts +2 -0
- package/dist/grammar/patterns/pattern.d.ts +2 -0
- package/dist/grammar/patterns/regexLiteral.d.ts +2 -0
- package/dist/grammar/patterns/repeatLiteral.d.ts +3 -0
- package/dist/grammar/patterns/spaces.d.ts +2 -0
- package/dist/grammar/patterns/statement.d.ts +2 -0
- package/dist/index.browser.js +1161 -556
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.esm.js +1159 -555
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1159 -554
- package/dist/index.js.map +1 -1
- package/dist/intellisense/AutoComplete.d.ts +2 -6
- package/dist/patterns/And.d.ts +1 -1
- package/dist/patterns/Cursor.d.ts +1 -0
- package/dist/patterns/CursorHistory.d.ts +2 -1
- package/dist/patterns/FiniteRepeat.d.ts +39 -0
- package/dist/patterns/InfiniteRepeat.d.ts +47 -0
- package/dist/patterns/Literal.d.ts +1 -1
- package/dist/patterns/Not.d.ts +1 -1
- package/dist/patterns/Or.d.ts +1 -1
- package/dist/patterns/Pattern.d.ts +1 -1
- package/dist/patterns/Reference.d.ts +1 -1
- package/dist/patterns/Regex.d.ts +1 -1
- package/dist/patterns/Repeat.d.ts +18 -22
- package/jest.config.js +0 -1
- package/jest.coverage.config.js +13 -0
- package/package.json +3 -3
- package/src/ast/Node.test.ts +15 -0
- package/src/ast/Node.ts +12 -6
- package/src/grammar/Grammar.test.ts +306 -0
- package/src/grammar/Grammar.ts +249 -0
- package/src/grammar/patterns/andLiteral.ts +8 -0
- package/src/grammar/patterns/comment.ts +3 -0
- package/src/grammar/patterns/grammar.ts +19 -0
- package/src/grammar/patterns/literal.ts +5 -0
- package/src/grammar/patterns/name.ts +3 -0
- package/src/grammar/patterns/orLiteral.ts +8 -0
- package/src/grammar/patterns/pattern.ts +13 -0
- package/src/grammar/patterns/regexLiteral.ts +4 -0
- package/src/grammar/patterns/repeatLiteral.ts +72 -0
- package/src/grammar/patterns/spaces.ts +4 -0
- package/src/grammar/patterns/statement.ts +36 -0
- package/src/grammar/spec.md +142 -0
- package/src/index.ts +6 -3
- package/src/intellisense/AutoComplete.test.ts +21 -2
- package/src/intellisense/AutoComplete.ts +14 -25
- package/src/intellisense/Suggestion.ts +0 -1
- package/src/intellisense/css/cssValue.ts +1 -1
- package/src/intellisense/css/method.ts +1 -1
- package/src/intellisense/css/values.ts +1 -1
- package/src/intellisense/javascript/Javascript.test.ts +0 -1
- package/src/intellisense/javascript/arrayLiteral.ts +1 -1
- package/src/intellisense/javascript/expression.ts +1 -1
- package/src/intellisense/javascript/invocation.ts +1 -1
- package/src/intellisense/javascript/objectLiteral.ts +1 -1
- package/src/intellisense/javascript/parameters.ts +1 -1
- package/src/intellisense/javascript/stringLiteral.ts +2 -4
- package/src/patterns/And.test.ts +5 -5
- package/src/patterns/And.ts +11 -17
- package/src/patterns/Cursor.ts +4 -0
- package/src/patterns/CursorHistory.ts +34 -5
- package/src/patterns/FiniteRepeat.test.ts +481 -0
- package/src/patterns/FiniteRepeat.ts +231 -0
- package/src/patterns/InfiniteRepeat.test.ts +296 -0
- package/src/patterns/InfiniteRepeat.ts +329 -0
- package/src/patterns/Literal.test.ts +4 -4
- package/src/patterns/Literal.ts +1 -1
- package/src/patterns/Not.test.ts +11 -11
- package/src/patterns/Not.ts +1 -1
- package/src/patterns/Or.test.ts +9 -9
- package/src/patterns/Or.ts +1 -1
- package/src/patterns/Pattern.ts +1 -1
- package/src/patterns/Reference.test.ts +8 -8
- package/src/patterns/Reference.ts +1 -1
- package/src/patterns/Regex.test.ts +4 -4
- package/src/patterns/Regex.ts +1 -1
- package/src/patterns/Repeat.test.ts +160 -165
- 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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
66
|
-
this.
|
|
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
|
+
});
|