clarity-pattern-parser 6.0.2 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/TODO.md +1 -78
  2. package/dist/ast/Node.d.ts +1 -0
  3. package/dist/grammar/Grammar.d.ts +17 -0
  4. package/dist/grammar/patterns/andLiteral.d.ts +2 -0
  5. package/dist/grammar/patterns/comment.d.ts +2 -0
  6. package/dist/grammar/patterns/grammar.d.ts +2 -0
  7. package/dist/grammar/patterns/literal.d.ts +2 -0
  8. package/dist/grammar/patterns/name.d.ts +2 -0
  9. package/dist/grammar/patterns/orLiteral.d.ts +2 -0
  10. package/dist/grammar/patterns/pattern.d.ts +2 -0
  11. package/dist/grammar/patterns/regexLiteral.d.ts +2 -0
  12. package/dist/grammar/patterns/repeatLiteral.d.ts +3 -0
  13. package/dist/grammar/patterns/spaces.d.ts +2 -0
  14. package/dist/grammar/patterns/statement.d.ts +2 -0
  15. package/dist/index.browser.js +1161 -556
  16. package/dist/index.browser.js.map +1 -1
  17. package/dist/index.d.ts +5 -4
  18. package/dist/index.esm.js +1159 -555
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1159 -554
  21. package/dist/index.js.map +1 -1
  22. package/dist/intellisense/AutoComplete.d.ts +2 -6
  23. package/dist/patterns/And.d.ts +1 -1
  24. package/dist/patterns/Cursor.d.ts +1 -0
  25. package/dist/patterns/CursorHistory.d.ts +2 -1
  26. package/dist/patterns/FiniteRepeat.d.ts +39 -0
  27. package/dist/patterns/InfiniteRepeat.d.ts +47 -0
  28. package/dist/patterns/Literal.d.ts +1 -1
  29. package/dist/patterns/Not.d.ts +1 -1
  30. package/dist/patterns/Or.d.ts +1 -1
  31. package/dist/patterns/Pattern.d.ts +1 -1
  32. package/dist/patterns/Reference.d.ts +1 -1
  33. package/dist/patterns/Regex.d.ts +1 -1
  34. package/dist/patterns/Repeat.d.ts +18 -22
  35. package/jest.config.js +0 -1
  36. package/jest.coverage.config.js +13 -0
  37. package/package.json +3 -3
  38. package/src/ast/Node.test.ts +15 -0
  39. package/src/ast/Node.ts +12 -6
  40. package/src/grammar/Grammar.test.ts +306 -0
  41. package/src/grammar/Grammar.ts +249 -0
  42. package/src/grammar/patterns/andLiteral.ts +8 -0
  43. package/src/grammar/patterns/comment.ts +3 -0
  44. package/src/grammar/patterns/grammar.ts +19 -0
  45. package/src/grammar/patterns/literal.ts +5 -0
  46. package/src/grammar/patterns/name.ts +3 -0
  47. package/src/grammar/patterns/orLiteral.ts +8 -0
  48. package/src/grammar/patterns/pattern.ts +13 -0
  49. package/src/grammar/patterns/regexLiteral.ts +4 -0
  50. package/src/grammar/patterns/repeatLiteral.ts +72 -0
  51. package/src/grammar/patterns/spaces.ts +4 -0
  52. package/src/grammar/patterns/statement.ts +36 -0
  53. package/src/grammar/spec.md +142 -0
  54. package/src/index.ts +6 -3
  55. package/src/intellisense/AutoComplete.test.ts +21 -2
  56. package/src/intellisense/AutoComplete.ts +14 -25
  57. package/src/intellisense/Suggestion.ts +0 -1
  58. package/src/intellisense/css/cssValue.ts +1 -1
  59. package/src/intellisense/css/method.ts +1 -1
  60. package/src/intellisense/css/values.ts +1 -1
  61. package/src/intellisense/javascript/Javascript.test.ts +0 -1
  62. package/src/intellisense/javascript/arrayLiteral.ts +1 -1
  63. package/src/intellisense/javascript/expression.ts +1 -1
  64. package/src/intellisense/javascript/invocation.ts +1 -1
  65. package/src/intellisense/javascript/objectLiteral.ts +1 -1
  66. package/src/intellisense/javascript/parameters.ts +1 -1
  67. package/src/intellisense/javascript/stringLiteral.ts +2 -4
  68. package/src/patterns/And.test.ts +5 -5
  69. package/src/patterns/And.ts +11 -17
  70. package/src/patterns/Cursor.ts +4 -0
  71. package/src/patterns/CursorHistory.ts +34 -5
  72. package/src/patterns/FiniteRepeat.test.ts +481 -0
  73. package/src/patterns/FiniteRepeat.ts +231 -0
  74. package/src/patterns/InfiniteRepeat.test.ts +296 -0
  75. package/src/patterns/InfiniteRepeat.ts +329 -0
  76. package/src/patterns/Literal.test.ts +4 -4
  77. package/src/patterns/Literal.ts +1 -1
  78. package/src/patterns/Not.test.ts +11 -11
  79. package/src/patterns/Not.ts +1 -1
  80. package/src/patterns/Or.test.ts +9 -9
  81. package/src/patterns/Or.ts +1 -1
  82. package/src/patterns/Pattern.ts +1 -1
  83. package/src/patterns/Reference.test.ts +8 -8
  84. package/src/patterns/Reference.ts +1 -1
  85. package/src/patterns/Regex.test.ts +4 -4
  86. package/src/patterns/Regex.ts +1 -1
  87. package/src/patterns/Repeat.test.ts +160 -165
  88. package/src/patterns/Repeat.ts +95 -230
@@ -0,0 +1,231 @@
1
+ import { Node } from "../ast/Node";
2
+ import { Cursor } from "./Cursor";
3
+ import { findPattern } from "./findPattern";
4
+ import { ParseResult } from "./ParseResult";
5
+ import { Pattern } from "./Pattern";
6
+
7
+ export interface FiniteRepeatOptions {
8
+ divider?: Pattern;
9
+ min?: number;
10
+ trimDivider?: boolean;
11
+ }
12
+
13
+ export class FiniteRepeat implements Pattern {
14
+ private _type: string;
15
+ private _name: string;
16
+ private _parent: Pattern | null;
17
+ private _children: Pattern[];
18
+ private _hasDivider: boolean;
19
+ private _min: number;
20
+ private _max: number;
21
+ private _trimDivider: boolean;
22
+
23
+ get type() {
24
+ return this._type;
25
+ }
26
+
27
+ get name() {
28
+ return this._name;
29
+ }
30
+
31
+ get parent() {
32
+ return this._parent;
33
+ }
34
+
35
+ set parent(value: Pattern | null) {
36
+ this._parent = value;
37
+ }
38
+
39
+ get children() {
40
+ return this._children;
41
+ }
42
+
43
+ get isOptional() {
44
+ return this._min === 0;
45
+ }
46
+
47
+ get min() {
48
+ return this._min;
49
+ }
50
+
51
+ get max() {
52
+ return this._max;
53
+ }
54
+
55
+ constructor(name: string, pattern: Pattern, repeatAmount: number, options: FiniteRepeatOptions = {}) {
56
+ this._type = "finite-repeat";
57
+ this._name = name;
58
+ this._parent = null;
59
+ this._children = [];
60
+ this._hasDivider = options.divider != null;
61
+ this._min = options.min != null ? options.min : 1;
62
+ this._max = repeatAmount;
63
+ this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
64
+
65
+ for (let i = 0; i < repeatAmount; i++) {
66
+ this._children.push(pattern.clone(pattern.name));
67
+
68
+ if (options.divider != null && (i < repeatAmount - 1 || !this._trimDivider)) {
69
+ this._children.push(options.divider.clone(options.divider.name, false));
70
+ }
71
+ }
72
+ }
73
+
74
+ parse(cursor: Cursor): Node | null {
75
+ const startIndex = cursor.index;
76
+ const nodes: Node[] = [];
77
+ const modulo = this._hasDivider ? 2 : 1;
78
+ let matchCount = 0;
79
+
80
+
81
+ for (let i = 0; i < this._children.length; i++) {
82
+ const childPattern = this._children[i];
83
+ const node = childPattern.parse(cursor);
84
+
85
+ if (i % modulo === 0 && !cursor.hasError) {
86
+ matchCount++
87
+ }
88
+
89
+ if (cursor.hasError) {
90
+ cursor.resolveError();
91
+ break;
92
+ }
93
+
94
+ if (node != null) {
95
+ nodes.push(node);
96
+
97
+ if (cursor.hasNext()) {
98
+ cursor.next();
99
+ } else {
100
+ break;
101
+ }
102
+ }
103
+
104
+ }
105
+
106
+ if (this._trimDivider && this._hasDivider) {
107
+ if (cursor.leafMatch.pattern === this.children[1]) {
108
+ const node = nodes.pop() as Node;
109
+ cursor.moveTo(node.firstIndex)
110
+ }
111
+ }
112
+
113
+ if (matchCount < this._min) {
114
+ cursor.moveTo(startIndex);
115
+ cursor.recordErrorAt(startIndex, this);
116
+ return null;
117
+ } else if (nodes.length === 0) {
118
+ cursor.resolveError();
119
+ cursor.moveTo(startIndex)
120
+ return null;
121
+ }
122
+
123
+ const firstIndex = nodes[0].firstIndex;
124
+ const lastIndex = nodes[nodes.length - 1].lastIndex;
125
+
126
+ cursor.moveTo(lastIndex);
127
+
128
+ return new Node(this._type, this.name, firstIndex, lastIndex, nodes);
129
+ }
130
+
131
+ test(text: string): boolean {
132
+ const cursor = new Cursor(text);
133
+ const ast = this.parse(cursor);
134
+
135
+ return ast?.value === text;
136
+ }
137
+
138
+ exec(text: string): ParseResult {
139
+ const cursor = new Cursor(text);
140
+ const ast = this.parse(cursor);
141
+
142
+ return {
143
+ ast: ast?.value === text ? ast : null,
144
+ cursor
145
+ };
146
+ }
147
+
148
+ clone(name = this._name, isOptional?: boolean): Pattern {
149
+ let min = this._min;
150
+
151
+ if (isOptional != null) {
152
+ if (isOptional) {
153
+ min = 0
154
+ } else {
155
+ min = Math.max(this._min, 1);
156
+ }
157
+ }
158
+
159
+ return new FiniteRepeat(
160
+ name,
161
+ this._children[0],
162
+ this._max,
163
+ {
164
+ divider: this._hasDivider ? this._children[1] : undefined,
165
+ min,
166
+ trimDivider: this._trimDivider
167
+ }
168
+ );
169
+ }
170
+
171
+ getTokens(): string[] {
172
+ return this._children[0].getTokens();
173
+ }
174
+
175
+ getTokensAfter(childReference: Pattern): string[] {
176
+ const patterns = this.getPatternsAfter(childReference);
177
+ const tokens: string[] = [];
178
+
179
+ patterns.forEach(p => tokens.push(...p.getTokens()));
180
+
181
+ return tokens;
182
+ }
183
+
184
+ getNextTokens(): string[] {
185
+ if (this._parent == null) {
186
+ return []
187
+ }
188
+
189
+ return this._parent.getTokensAfter(this);
190
+ }
191
+
192
+ getPatterns(): Pattern[] {
193
+ return this._children[0].getPatterns();
194
+ }
195
+
196
+ getPatternsAfter(childReference: Pattern): Pattern[] {
197
+ const childIndex = this._children.indexOf(childReference);
198
+
199
+ // If Reference Pattern isn't a child.
200
+ if (childIndex == -1) {
201
+ return [];
202
+ }
203
+
204
+ // If Reference Pattern is the last pattern. Ask for the parents next patterns
205
+ if (childIndex === this._children.length - 1) {
206
+ if (this._parent == null) {
207
+ return [];
208
+ } else {
209
+ return this._parent.getPatternsAfter(this);
210
+ }
211
+ }
212
+
213
+ // Get the next childs patterns.
214
+ const nextChild = this._children[childIndex + 1];
215
+
216
+ return nextChild.getPatterns()
217
+ }
218
+
219
+ getNextPatterns(): Pattern[] {
220
+ if (this._parent == null) {
221
+ return [];
222
+ }
223
+
224
+ return this._parent.getPatternsAfter(this);
225
+ }
226
+
227
+ find(predicate: (p: Pattern) => boolean): Pattern | null {
228
+ return findPattern(this, predicate);
229
+ }
230
+
231
+ }
@@ -0,0 +1,296 @@
1
+ import { Node } from "../ast/Node";
2
+ import { And } from "./And";
3
+ import { Cursor } from "./Cursor";
4
+ import { findPattern } from "./findPattern";
5
+ import { Literal } from "./Literal";
6
+ import { Pattern } from "./Pattern";
7
+ import { Regex } from "./Regex";
8
+ import { InfiniteRepeat } from "./InfiniteRepeat";
9
+
10
+ describe("InfiniteRepeat", () => {
11
+ test("Successful Parse", () => {
12
+ const digit = new Regex("digit", "\\d");
13
+ const integer = new InfiniteRepeat("number", digit);
14
+ const cursor = new Cursor("337");
15
+ const result = integer.parse(cursor);
16
+ const expected = new Node("infinite-repeat", "number", 0, 2, [
17
+ new Node("regex", "digit", 0, 0, [], "3"),
18
+ new Node("regex", "digit", 1, 1, [], "3"),
19
+ new Node("regex", "digit", 2, 2, [], "7"),
20
+ ]);
21
+
22
+ expect(result).toEqual(expected)
23
+ expect(cursor.hasError).toBeFalsy()
24
+ });
25
+
26
+ test("Bounds", () => {
27
+ const digit = new Regex("digit", "\\d");
28
+ const integer = new InfiniteRepeat("number", digit, { min: 2 });
29
+
30
+ let cursor = new Cursor("3");
31
+ let result = integer.parse(cursor);
32
+ let expected: Node | null = null;
33
+
34
+ expect(result).toEqual(expected);
35
+ expect(cursor.hasError).toBeTruthy();
36
+
37
+ cursor = new Cursor("33");
38
+ result = integer.parse(cursor);
39
+ expected = new Node("infinite-repeat", "number", 0, 1, [
40
+ new Node("regex", "digit", 0, 0, [], "3"),
41
+ new Node("regex", "digit", 1, 1, [], "3")
42
+ ]);
43
+
44
+ expect(result).toEqual(expected);
45
+ expect(cursor.hasError).toBeFalsy();
46
+ });
47
+
48
+ test("Failed Parse", () => {
49
+ const digit = new Regex("digit", "\\d");
50
+ const integer = new InfiniteRepeat("number", digit);
51
+ const cursor = new Cursor("John");
52
+ const result = integer.parse(cursor);
53
+
54
+ expect(result).toBeNull()
55
+ expect(cursor.hasError).toBeTruthy()
56
+ });
57
+
58
+ test("Successful Parse With Divider", () => {
59
+ const digit = new Regex("digit", "\\d");
60
+ const divider = new Literal("divider", ",");
61
+ const integer = new InfiniteRepeat("number", digit, { divider });
62
+ const cursor = new Cursor("3,3,7");
63
+ const result = integer.parse(cursor);
64
+ const expected = new Node("infinite-repeat", "number", 0, 4, [
65
+ new Node("regex", "digit", 0, 0, [], "3"),
66
+ new Node("literal", "divider", 1, 1, [], ","),
67
+ new Node("regex", "digit", 2, 2, [], "3"),
68
+ new Node("literal", "divider", 3, 3, [], ","),
69
+ new Node("regex", "digit", 4, 4, [], "7"),
70
+ ]);
71
+
72
+ expect(result).toEqual(expected)
73
+ expect(cursor.hasError).toBeFalsy()
74
+ });
75
+
76
+ test("Successful Parse Text Ends With Divider", () => {
77
+ const digit = new Regex("digit", "\\d");
78
+ const divider = new Literal("divider", ",");
79
+ const integer = new InfiniteRepeat("number", digit, { divider, trimDivider: true });
80
+ const cursor = new Cursor("3,3,7,");
81
+ const result = integer.parse(cursor);
82
+ const expected = new Node("infinite-repeat", "number", 0, 4, [
83
+ new Node("regex", "digit", 0, 0, [], "3"),
84
+ new Node("literal", "divider", 1, 1, [], ","),
85
+ new Node("regex", "digit", 2, 2, [], "3"),
86
+ new Node("literal", "divider", 3, 3, [], ","),
87
+ new Node("regex", "digit", 4, 4, [], "7"),
88
+ ]);
89
+
90
+ expect(result).toEqual(expected)
91
+ expect(cursor.hasError).toBeFalsy()
92
+ });
93
+
94
+ test("Successful Parse Trailing Comma", () => {
95
+ const digit = new Regex("digit", "\\d");
96
+ const divider = new Literal("divider", ",");
97
+ const integer = new InfiniteRepeat("number", digit, { divider, trimDivider: true });
98
+ const cursor = new Cursor("3,3,7,t");
99
+ const result = integer.parse(cursor);
100
+ const expected = new Node("infinite-repeat", "number", 0, 4, [
101
+ new Node("regex", "digit", 0, 0, [], "3"),
102
+ new Node("literal", "divider", 1, 1, [], ","),
103
+ new Node("regex", "digit", 2, 2, [], "3"),
104
+ new Node("literal", "divider", 3, 3, [], ","),
105
+ new Node("regex", "digit", 4, 4, [], "7"),
106
+ ]);
107
+
108
+ expect(result).toEqual(expected)
109
+ expect(cursor.hasError).toBeFalsy()
110
+ });
111
+
112
+ test("Optional Repeating Pattern", () => {
113
+ const digit = new Regex("digit", "\\d+", true);
114
+ const divider = new Regex("divider", "\\s");
115
+ const integer = new InfiniteRepeat("number", digit, { divider });
116
+ const cursor = new Cursor(
117
+ "\n" +
118
+ "3\n" +
119
+ "\n" +
120
+ "\n"
121
+ );
122
+ const result = integer.parse(cursor);
123
+ const expected = new Node("infinite-repeat", "number", 0, 4, [
124
+ new Node("regex", "divider", 0, 0, [], "\n"),
125
+ new Node("regex", "digit", 1, 1, [], "3"),
126
+ new Node("regex", "divider", 2, 2, [], "\n"),
127
+ new Node("regex", "divider", 3, 3, [], "\n"),
128
+ new Node("regex", "divider", 4, 4, [], "\n"),
129
+ ]);
130
+
131
+ expect(result).toEqual(expected)
132
+ expect(cursor.hasError).toBeFalsy()
133
+ });
134
+
135
+ test("Failed (Optional)", () => {
136
+ const digit = new Regex("digit", "\\d");
137
+ const integer = new InfiniteRepeat("number", digit, { min: 0 });
138
+ const cursor = new Cursor("John");
139
+ const result = integer.parse(cursor);
140
+
141
+ expect(result).toBeNull()
142
+ expect(cursor.hasError).toBeFalsy()
143
+ });
144
+
145
+ test("Get Tokens", () => {
146
+ const a = new Literal("a", "A");
147
+ const manyA = new InfiniteRepeat("number", a);
148
+ const tokens = manyA.getTokens();
149
+ const expected = ["A"];
150
+
151
+ expect(tokens).toEqual(expected)
152
+ });
153
+
154
+ test("Get Tokens After With Bogus Pattern", () => {
155
+ const a = new Literal("a", "A");
156
+ const manyA = new InfiniteRepeat("many-a", a);
157
+ const tokens = manyA.getTokensAfter(new Literal("bogus", "bogus"));
158
+ const expected: string[] = [];
159
+
160
+ expect(tokens).toEqual(expected)
161
+ });
162
+
163
+ test("Get Tokens After With Divider", () => {
164
+ const a = new Literal("a", "A");
165
+ const b = new Literal("b", "B");
166
+ const divider = new Literal("divider", ",");
167
+ const manyA = new InfiniteRepeat("many-a", a, { divider });
168
+ const parent = new And("parent", [manyA, b]);
169
+
170
+ const clonedManyA = findPattern(parent, p => p.name == "many-a");
171
+ let tokens = clonedManyA?.getTokensAfter(clonedManyA.children[0]);
172
+ let expected = [",", "B"];
173
+
174
+ expect(tokens).toEqual(expected)
175
+
176
+ tokens = clonedManyA?.getTokensAfter(clonedManyA.children[1]);
177
+ expected = ["A"];
178
+
179
+ expect(tokens).toEqual(expected)
180
+ });
181
+
182
+ test("Get Tokens After Without Divider", () => {
183
+ const a = new Literal("a", "A");
184
+ const b = new Literal("b", "B");
185
+ const manyA = new InfiniteRepeat("many-a", a);
186
+ const parent = new And("parent", [manyA, b]);
187
+
188
+ const clonedManyA = findPattern(parent, p => p.name == "many-a");
189
+ const tokens = clonedManyA?.getTokensAfter(clonedManyA.children[0]);
190
+ const expected = ["A", "B"];
191
+
192
+ expect(tokens).toEqual(expected)
193
+ });
194
+
195
+ test("Properties", () => {
196
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
197
+
198
+ expect(integer.type).toBe("infinite-repeat");
199
+ expect(integer.name).toBe("integer");
200
+ expect(integer.min).toBe(1);
201
+ expect(integer.isOptional).toBeFalsy()
202
+ expect(integer.parent).toBeNull();
203
+ expect(integer.children[0].name).toBe("digit");
204
+ });
205
+
206
+ test("Exec", () => {
207
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
208
+ const { ast: result } = integer.exec("B");
209
+ expect(result).toBeNull()
210
+ });
211
+
212
+ test("Test With Match", () => {
213
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
214
+ const result = integer.test("1");
215
+ expect(result).toBeTruthy()
216
+ });
217
+
218
+ test("Test With No Match", () => {
219
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
220
+ const result = integer.test("b");
221
+ expect(result).toBeFalsy()
222
+ });
223
+
224
+ test("Get Next Tokens", () => {
225
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
226
+ const parent = new And("parent", [integer, new Literal("pow", "!")]);
227
+ const integerClone = parent.find(p => p.name === "integer") as Pattern;
228
+ const tokens = integerClone.getNextTokens();
229
+
230
+ expect(tokens).toEqual(["!"])
231
+ });
232
+
233
+ test("Get Next Tokens With Null Parents", () => {
234
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
235
+ const tokens = integer.getNextTokens();
236
+
237
+ expect(tokens.length).toBe(0);
238
+ });
239
+
240
+ test("Find Pattern", () => {
241
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
242
+ const digitClone = integer.find(p => p.name === "digit") as Pattern;
243
+
244
+ expect(digitClone).not.toBeNull();
245
+ });
246
+
247
+ test("Get Patterns", () => {
248
+ const a = new Literal("a", "A");
249
+ const manyA = new InfiniteRepeat("number", a);
250
+ const patterns = manyA.getPatterns();
251
+ const expected = [manyA.find(p => p.name === "a")];
252
+
253
+ expect(patterns).toEqual(expected)
254
+ });
255
+
256
+ test("Get Next Patterns", () => {
257
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
258
+ const parent = new And("parent", [integer, new Literal("pow", "!")]);
259
+ const integerClone = parent.find(p => p.name === "integer") as Pattern;
260
+ const powClone = parent.find(p => p.name === "pow") as Pattern;
261
+ const patterns = integerClone.getNextPatterns();
262
+
263
+ expect(patterns.length).toBe(1);
264
+ expect(patterns[0]).toBe(powClone);
265
+ });
266
+
267
+ test("Get Next Patterns With Null Parents", () => {
268
+ const integer = new InfiniteRepeat("integer", new Regex("digit", "\\d"));
269
+ const patterns = integer.getNextPatterns();
270
+
271
+ expect(patterns.length).toBe(0);
272
+ });
273
+
274
+ test("Clone With Custom Overrides", () => {
275
+ const numbers = new InfiniteRepeat("numbers", new Regex("number", "\\d"), { min: 0 });
276
+ let clone = numbers.clone();
277
+ let expected = new InfiniteRepeat("numbers", new Regex("number", "\\d"), { min: 0 });
278
+
279
+ expect(clone).toEqual(expected);
280
+
281
+ clone = numbers.clone("cloned-numbers");
282
+ expected = new InfiniteRepeat("cloned-numbers", new Regex("number", "\\d"), { min: 0 });
283
+
284
+ expect(clone).toEqual(expected);
285
+
286
+ clone = numbers.clone("cloned-numbers", true);
287
+ expected = new InfiniteRepeat("cloned-numbers", new Regex("number", "\\d"), { min: 0 });
288
+
289
+ expect(clone).toEqual(expected);
290
+
291
+ clone = numbers.clone("cloned-numbers", false);
292
+ expected = new InfiniteRepeat("cloned-numbers", new Regex("number", "\\d"), { min: 1 });
293
+
294
+ expect(clone).toEqual(expected);
295
+ });
296
+ });