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,21 +1,21 @@
|
|
|
1
1
|
import { Cursor } from "./Cursor";
|
|
2
2
|
import { Regex } from "./Regex";
|
|
3
3
|
import { Node } from "../ast/Node"
|
|
4
|
-
import {
|
|
4
|
+
import { Sequence } from "./Sequence";
|
|
5
5
|
import { Literal } from "./Literal";
|
|
6
6
|
import { Pattern } from "./Pattern";
|
|
7
7
|
|
|
8
8
|
describe("Regex", () => {
|
|
9
9
|
test("Empty String", () => {
|
|
10
|
-
expect(() => new Regex("empty", "")).toThrowError()
|
|
10
|
+
expect(() => new Regex("empty", "")).toThrowError();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
test("Starts With ^", () => {
|
|
14
|
-
expect(() => new Regex("carrot", "^")).toThrowError()
|
|
14
|
+
expect(() => new Regex("carrot", "^")).toThrowError();
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
test("Ends With $", () => {
|
|
18
|
-
expect(() => new Regex("money", ".$")).toThrowError()
|
|
18
|
+
expect(() => new Regex("money", ".$")).toThrowError();
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
test("Successful Parse", () => {
|
|
@@ -25,8 +25,8 @@ describe("Regex", () => {
|
|
|
25
25
|
const expected = new Node("regex", "number", 0, 0, [], "1");
|
|
26
26
|
|
|
27
27
|
expect(result).toEqual(expected);
|
|
28
|
-
expect(cursor.hasError).toBeFalsy()
|
|
29
|
-
})
|
|
28
|
+
expect(cursor.hasError).toBeFalsy();
|
|
29
|
+
});
|
|
30
30
|
|
|
31
31
|
test("Failed Parse", () => {
|
|
32
32
|
const number = new Regex("number", "\\d");
|
|
@@ -34,7 +34,7 @@ describe("Regex", () => {
|
|
|
34
34
|
const result = number.parse(cursor);
|
|
35
35
|
|
|
36
36
|
expect(result).toBeNull();
|
|
37
|
-
expect(cursor.hasError).toBeTruthy()
|
|
37
|
+
expect(cursor.hasError).toBeTruthy();
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
|
|
@@ -54,7 +54,7 @@ describe("Regex", () => {
|
|
|
54
54
|
const tokens = regex.getTokensAfter(new Literal("bogus", "bogus"));
|
|
55
55
|
const expected: string[] = [];
|
|
56
56
|
|
|
57
|
-
expect(tokens).toEqual(expected)
|
|
57
|
+
expect(tokens).toEqual(expected);
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
test("Properties", () => {
|
|
@@ -85,7 +85,7 @@ describe("Regex", () => {
|
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
test("Get Next Tokens", () => {
|
|
88
|
-
const parent = new
|
|
88
|
+
const parent = new Sequence("parent", [new Regex("a", "A"), new Literal("b", "B")]);
|
|
89
89
|
const aClone = parent.find(p => p.name === "a") as Pattern;
|
|
90
90
|
const tokens = aClone.getNextTokens();
|
|
91
91
|
|
|
@@ -93,7 +93,7 @@ describe("Regex", () => {
|
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
test("Get Next Tokens With Null Parent", () => {
|
|
96
|
-
const a = new Regex("a", "A")
|
|
96
|
+
const a = new Regex("a", "A");
|
|
97
97
|
const tokens = a.getNextTokens();
|
|
98
98
|
|
|
99
99
|
expect(tokens).toEqual([]);
|
|
@@ -109,21 +109,21 @@ describe("Regex", () => {
|
|
|
109
109
|
});
|
|
110
110
|
|
|
111
111
|
test("Get Patterns After", () => {
|
|
112
|
-
const a = new Regex("a", "A")
|
|
112
|
+
const a = new Regex("a", "A");
|
|
113
113
|
const patterns = a.getPatternsAfter(new Literal("bogus", "bogus"));
|
|
114
114
|
|
|
115
115
|
expect(patterns).toEqual([]);
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
test("Find Pattern", () => {
|
|
119
|
-
const a = new Regex("a", "A")
|
|
119
|
+
const a = new Regex("a", "A");
|
|
120
120
|
const pattern = a.find(p => p.name === "other");
|
|
121
121
|
|
|
122
122
|
expect(pattern).toBeNull();
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
test("Get Next Patterns", () => {
|
|
126
|
-
const parent = new
|
|
126
|
+
const parent = new Sequence("parent", [new Regex("a", "A"), new Literal("b", "B")]);
|
|
127
127
|
const aClone = parent.find(p => p.name === "a") as Pattern;
|
|
128
128
|
const bClone = parent.find(p => p.name === "b") as Pattern;
|
|
129
129
|
const patterns = aClone.getNextPatterns();
|
|
@@ -133,10 +133,10 @@ describe("Regex", () => {
|
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
test("Get Next Patterns With Null Parent", () => {
|
|
136
|
-
const a = new Regex("a", "A")
|
|
136
|
+
const a = new Regex("a", "A");
|
|
137
137
|
const patterns = a.getNextPatterns();
|
|
138
138
|
|
|
139
|
-
expect(patterns).toEqual([])
|
|
139
|
+
expect(patterns).toEqual([]);
|
|
140
140
|
});
|
|
141
141
|
|
|
142
142
|
});
|
package/src/patterns/Regex.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { Node } from "../ast/Node";
|
|
2
2
|
import { Pattern } from "./Pattern";
|
|
3
3
|
import { Cursor } from "./Cursor";
|
|
4
|
+
import { ParseResult } from "./ParseResult";
|
|
5
|
+
|
|
6
|
+
let idIndex = 0;
|
|
4
7
|
|
|
5
8
|
export class Regex implements Pattern {
|
|
9
|
+
private _id: string;
|
|
6
10
|
private _type: string;
|
|
7
11
|
private _name: string;
|
|
8
|
-
private _isOptional: boolean;
|
|
9
12
|
private _parent: Pattern | null;
|
|
10
13
|
private _originalRegexString: string;
|
|
11
14
|
private _regex: RegExp;
|
|
@@ -15,6 +18,10 @@ export class Regex implements Pattern {
|
|
|
15
18
|
private _substring = "";
|
|
16
19
|
private _tokens: string[] = [];
|
|
17
20
|
|
|
21
|
+
get id(): string {
|
|
22
|
+
return this._id;
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
get type(): string {
|
|
19
26
|
return this._type;
|
|
20
27
|
}
|
|
@@ -35,14 +42,10 @@ export class Regex implements Pattern {
|
|
|
35
42
|
return [];
|
|
36
43
|
}
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
constructor(name: string, regex: string, isOptional = false) {
|
|
43
|
-
this._type = "regex"
|
|
45
|
+
constructor(name: string, regex: string) {
|
|
46
|
+
this._id = `regex-${idIndex++}`;
|
|
47
|
+
this._type = "regex";
|
|
44
48
|
this._name = name;
|
|
45
|
-
this._isOptional = isOptional;
|
|
46
49
|
this._parent = null;
|
|
47
50
|
this._originalRegexString = regex;
|
|
48
51
|
this._regex = new RegExp(`^${regex}`, "g");
|
|
@@ -76,8 +79,10 @@ export class Regex implements Pattern {
|
|
|
76
79
|
return ast?.value === text;
|
|
77
80
|
}
|
|
78
81
|
|
|
79
|
-
exec(text: string) {
|
|
82
|
+
exec(text: string, record = false): ParseResult {
|
|
80
83
|
const cursor = new Cursor(text);
|
|
84
|
+
record && cursor.startRecording();
|
|
85
|
+
|
|
81
86
|
const ast = this.parse(cursor);
|
|
82
87
|
|
|
83
88
|
return {
|
|
@@ -87,10 +92,13 @@ export class Regex implements Pattern {
|
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
parse(cursor: Cursor) {
|
|
95
|
+
cursor.startParseWith(this);
|
|
96
|
+
|
|
90
97
|
this._firstIndex = cursor.index;
|
|
91
98
|
this.resetState(cursor);
|
|
92
99
|
this.tryToParse(cursor);
|
|
93
100
|
|
|
101
|
+
cursor.endParse();
|
|
94
102
|
return this._node;
|
|
95
103
|
}
|
|
96
104
|
|
|
@@ -129,18 +137,16 @@ export class Regex implements Pattern {
|
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
private processError(cursor: Cursor) {
|
|
132
|
-
|
|
133
|
-
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
134
|
-
}
|
|
135
|
-
|
|
140
|
+
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
136
141
|
this._node = null;
|
|
137
142
|
}
|
|
138
143
|
|
|
139
|
-
clone(name = this._name
|
|
140
|
-
const
|
|
141
|
-
|
|
144
|
+
clone(name = this._name) {
|
|
145
|
+
const clone = new Regex(name, this._originalRegexString);
|
|
146
|
+
clone._tokens = this._tokens.slice();
|
|
142
147
|
|
|
143
|
-
|
|
148
|
+
clone._id = this._id;
|
|
149
|
+
return clone;
|
|
144
150
|
}
|
|
145
151
|
|
|
146
152
|
getTokens() {
|
|
@@ -153,7 +159,7 @@ export class Regex implements Pattern {
|
|
|
153
159
|
|
|
154
160
|
getNextTokens(): string[] {
|
|
155
161
|
if (this.parent == null) {
|
|
156
|
-
return []
|
|
162
|
+
return [];
|
|
157
163
|
}
|
|
158
164
|
|
|
159
165
|
return this.parent.getTokensAfter(this);
|
|
@@ -172,7 +178,7 @@ export class Regex implements Pattern {
|
|
|
172
178
|
return [];
|
|
173
179
|
}
|
|
174
180
|
|
|
175
|
-
return this.parent.getPatternsAfter(this)
|
|
181
|
+
return this.parent.getPatternsAfter(this);
|
|
176
182
|
}
|
|
177
183
|
|
|
178
184
|
find(_predicate: (p: Pattern) => boolean): Pattern | null {
|
|
@@ -183,4 +189,8 @@ export class Regex implements Pattern {
|
|
|
183
189
|
this._tokens = tokens;
|
|
184
190
|
}
|
|
185
191
|
|
|
192
|
+
isEqual(pattern: Regex): boolean {
|
|
193
|
+
return pattern.type === this.type && pattern._originalRegexString === this._originalRegexString;
|
|
194
|
+
}
|
|
195
|
+
|
|
186
196
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Node } from "../ast/Node";
|
|
2
|
-
import {
|
|
2
|
+
import { Sequence } from "./Sequence";
|
|
3
|
+
import { arePatternsEqual } from "./arePatternsEqual";
|
|
3
4
|
import { Cursor } from "./Cursor";
|
|
4
5
|
import { InfiniteRepeat } from "./InfiniteRepeat";
|
|
5
6
|
import { Literal } from "./Literal";
|
|
@@ -26,7 +27,7 @@ describe("Repeat", () => {
|
|
|
26
27
|
new Node("regex", "number", 0, 0, [], "1")
|
|
27
28
|
]);
|
|
28
29
|
|
|
29
|
-
expect(result).toEqual(expected);
|
|
30
|
+
expect(result?.toJson()).toEqual(expected.toJson());
|
|
30
31
|
expect(cursor.hasError).toBeFalsy();
|
|
31
32
|
|
|
32
33
|
cursor = new Cursor("12");
|
|
@@ -36,7 +37,7 @@ describe("Repeat", () => {
|
|
|
36
37
|
new Node("regex", "number", 1, 1, [], "2")
|
|
37
38
|
]);
|
|
38
39
|
|
|
39
|
-
expect(result).toEqual(expected);
|
|
40
|
+
expect(result?.toJson()).toEqual(expected.toJson());
|
|
40
41
|
expect(cursor.hasError).toBeFalsy();
|
|
41
42
|
|
|
42
43
|
cursor = new Cursor("123");
|
|
@@ -46,7 +47,7 @@ describe("Repeat", () => {
|
|
|
46
47
|
new Node("regex", "number", 1, 1, [], "2")
|
|
47
48
|
]);
|
|
48
49
|
|
|
49
|
-
expect(result).toEqual(expected);
|
|
50
|
+
expect(result?.toJson()).toEqual(expected.toJson());
|
|
50
51
|
expect(cursor.hasError).toBeFalsy();
|
|
51
52
|
expect(cursor.index).toBe(1);
|
|
52
53
|
});
|
|
@@ -76,7 +77,7 @@ describe("Repeat", () => {
|
|
|
76
77
|
new Node("regex", "number", 1, 1, [], "2")
|
|
77
78
|
]);
|
|
78
79
|
|
|
79
|
-
expect(result).toEqual(expected);
|
|
80
|
+
expect(result?.toJson()).toEqual(expected.toJson());
|
|
80
81
|
expect(cursor.hasError).toBeFalsy();
|
|
81
82
|
|
|
82
83
|
cursor = new Cursor("123");
|
|
@@ -86,7 +87,7 @@ describe("Repeat", () => {
|
|
|
86
87
|
new Node("regex", "number", 1, 1, [], "2")
|
|
87
88
|
]);
|
|
88
89
|
|
|
89
|
-
expect(result).toEqual(expected);
|
|
90
|
+
expect(result?.toJson()).toEqual(expected.toJson());
|
|
90
91
|
expect(cursor.hasError).toBeFalsy();
|
|
91
92
|
expect(cursor.index).toBe(1);
|
|
92
93
|
});
|
|
@@ -115,7 +116,7 @@ describe("Repeat", () => {
|
|
|
115
116
|
test("Get Tokens After", () => {
|
|
116
117
|
const number = new Literal("number", "1");
|
|
117
118
|
const repeat = new Repeat("numbers", number);
|
|
118
|
-
const parent = new
|
|
119
|
+
const parent = new Sequence("parent", [repeat, new Literal("b", "B")]);
|
|
119
120
|
const numberClone = parent.find(p => p.name === "number") as Pattern;
|
|
120
121
|
const repeatClone = parent.children[0];
|
|
121
122
|
|
|
@@ -128,7 +129,7 @@ describe("Repeat", () => {
|
|
|
128
129
|
test("Get Next Tokens", () => {
|
|
129
130
|
const number = new Literal("number", "1");
|
|
130
131
|
const repeat = new Repeat("numbers", number);
|
|
131
|
-
const parent = new
|
|
132
|
+
const parent = new Sequence("parent", [repeat, new Literal("b", "B")]);
|
|
132
133
|
const repeatClone = parent.children[0];
|
|
133
134
|
|
|
134
135
|
let tokens = repeatClone.getNextTokens();
|
|
@@ -140,7 +141,7 @@ describe("Repeat", () => {
|
|
|
140
141
|
test("Get Next Patterns", () => {
|
|
141
142
|
const number = new Literal("number", "1");
|
|
142
143
|
const repeat = new Repeat("numbers", number);
|
|
143
|
-
const parent = new
|
|
144
|
+
const parent = new Sequence("parent", [repeat, new Literal("b", "B")]);
|
|
144
145
|
const repeatClone = parent.children[0];
|
|
145
146
|
const bClone = parent.find(p => p.name === "b") as Pattern;
|
|
146
147
|
|
|
@@ -178,7 +179,6 @@ describe("Repeat", () => {
|
|
|
178
179
|
expect(repeat.type).toBe("infinite-repeat");
|
|
179
180
|
expect(repeat.name).toBe("numbers");
|
|
180
181
|
expect(repeat.parent).toBeNull();
|
|
181
|
-
expect(repeat.isOptional).toBeFalsy();
|
|
182
182
|
});
|
|
183
183
|
|
|
184
184
|
test("test", () => {
|
|
@@ -202,21 +202,11 @@ describe("Repeat", () => {
|
|
|
202
202
|
let repeatClone = repeat.clone();
|
|
203
203
|
let expected = new Repeat("numbers", number);
|
|
204
204
|
|
|
205
|
-
expect(repeatClone).
|
|
205
|
+
expect(arePatternsEqual(repeatClone, expected)).toBeTruthy();
|
|
206
206
|
|
|
207
207
|
repeatClone = repeat.clone("new-name");
|
|
208
208
|
expected = new Repeat("new-name", number);
|
|
209
209
|
|
|
210
|
-
expect(repeatClone).
|
|
211
|
-
|
|
212
|
-
repeatClone = repeat.clone("new-name", false);
|
|
213
|
-
expected = new Repeat("new-name", number);
|
|
214
|
-
|
|
215
|
-
expect(repeatClone).toEqual(expected);
|
|
216
|
-
|
|
217
|
-
repeatClone = repeat.clone("new-name", true);
|
|
218
|
-
expected = new Repeat("new-name", number, { min: 0 });
|
|
219
|
-
|
|
220
|
-
expect(repeatClone).toEqual(expected);
|
|
210
|
+
expect(arePatternsEqual(repeatClone, expected)).toBeTruthy();
|
|
221
211
|
});
|
|
222
212
|
});
|
package/src/patterns/Repeat.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { InfiniteRepeat } from "./InfiniteRepeat";
|
|
|
5
5
|
import { ParseResult } from "./ParseResult";
|
|
6
6
|
import { Pattern } from "./Pattern";
|
|
7
7
|
|
|
8
|
+
let idIndex = 0;
|
|
9
|
+
|
|
8
10
|
export interface RepeatOptions {
|
|
9
11
|
min?: number;
|
|
10
12
|
max?: number;
|
|
@@ -19,12 +21,17 @@ interface InternalRepeatOptions {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
export class Repeat implements Pattern {
|
|
24
|
+
private _id: string;
|
|
22
25
|
private _repeatPattern: InfiniteRepeat | FiniteRepeat;
|
|
23
26
|
private _parent: Pattern | null;
|
|
24
27
|
private _pattern: Pattern;
|
|
25
28
|
private _options: InternalRepeatOptions;
|
|
26
29
|
private _children: Pattern[];
|
|
27
30
|
|
|
31
|
+
get id() {
|
|
32
|
+
return this._id;
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
get type() {
|
|
29
36
|
return this._repeatPattern.type;
|
|
30
37
|
}
|
|
@@ -45,11 +52,8 @@ export class Repeat implements Pattern {
|
|
|
45
52
|
return this._children;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
|
-
get isOptional() {
|
|
49
|
-
return this._repeatPattern.isOptional;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
55
|
constructor(name: string, pattern: Pattern, options: RepeatOptions = {}) {
|
|
56
|
+
this._id = `repeat-${idIndex++}`;
|
|
53
57
|
this._pattern = pattern;
|
|
54
58
|
this._parent = null;
|
|
55
59
|
this._options = {
|
|
@@ -59,12 +63,12 @@ export class Repeat implements Pattern {
|
|
|
59
63
|
};
|
|
60
64
|
|
|
61
65
|
if (this._options.max !== Infinity) {
|
|
62
|
-
this._repeatPattern = new FiniteRepeat(name, pattern, this._options
|
|
66
|
+
this._repeatPattern = new FiniteRepeat(name, pattern, this._options);
|
|
63
67
|
} else {
|
|
64
|
-
this._repeatPattern = new InfiniteRepeat(name, pattern, this._options)
|
|
68
|
+
this._repeatPattern = new InfiniteRepeat(name, pattern, this._options);
|
|
65
69
|
}
|
|
66
70
|
|
|
67
|
-
this._children = [this._repeatPattern]
|
|
71
|
+
this._children = [this._repeatPattern];
|
|
68
72
|
this._repeatPattern.parent = this;
|
|
69
73
|
}
|
|
70
74
|
|
|
@@ -80,18 +84,12 @@ export class Repeat implements Pattern {
|
|
|
80
84
|
return this._repeatPattern.test(text);
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
clone(name = this.name
|
|
87
|
+
clone(name = this.name) {
|
|
84
88
|
let min = this._options.min;
|
|
89
|
+
const clone = new Repeat(name, this._pattern, { ...this._options, min });
|
|
85
90
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
min = 0
|
|
89
|
-
} else {
|
|
90
|
-
min = Math.max(this._options.min, 1);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return new Repeat(name, this._pattern, { ...this._options, min });
|
|
91
|
+
clone._id = this._id;
|
|
92
|
+
return clone;
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
getTokens(): string[] {
|
|
@@ -100,7 +98,7 @@ export class Repeat implements Pattern {
|
|
|
100
98
|
|
|
101
99
|
getTokensAfter(_childReference: Pattern): string[] {
|
|
102
100
|
if (this._parent == null) {
|
|
103
|
-
return []
|
|
101
|
+
return [];
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
return this._parent.getTokensAfter(this);
|
|
@@ -108,7 +106,7 @@ export class Repeat implements Pattern {
|
|
|
108
106
|
|
|
109
107
|
getNextTokens(): string[] {
|
|
110
108
|
if (this._parent == null) {
|
|
111
|
-
return []
|
|
109
|
+
return [];
|
|
112
110
|
}
|
|
113
111
|
|
|
114
112
|
return this._parent.getTokensAfter(this);
|
|
@@ -120,7 +118,7 @@ export class Repeat implements Pattern {
|
|
|
120
118
|
|
|
121
119
|
getPatternsAfter(_childReference: Pattern): Pattern[] {
|
|
122
120
|
if (this._parent == null) {
|
|
123
|
-
return []
|
|
121
|
+
return [];
|
|
124
122
|
}
|
|
125
123
|
|
|
126
124
|
return this._parent.getPatternsAfter(this);
|
|
@@ -128,7 +126,7 @@ export class Repeat implements Pattern {
|
|
|
128
126
|
|
|
129
127
|
getNextPatterns(): Pattern[] {
|
|
130
128
|
if (this._parent == null) {
|
|
131
|
-
return []
|
|
129
|
+
return [];
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
return this._parent.getPatternsAfter(this);
|
|
@@ -138,4 +136,7 @@ export class Repeat implements Pattern {
|
|
|
138
136
|
return this._repeatPattern.find(predicate);
|
|
139
137
|
}
|
|
140
138
|
|
|
139
|
+
isEqual(pattern: Repeat): boolean {
|
|
140
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
141
|
+
}
|
|
141
142
|
}
|