clarity-pattern-parser 5.0.0 → 6.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/README.md +328 -38
- package/TODO.md +55 -1
- package/dist/ast/Node.d.ts +8 -2
- package/dist/index.browser.js +470 -205
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.esm.js +469 -206
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +470 -205
- package/dist/index.js.map +1 -1
- package/dist/intellisense/AutoComplete.d.ts +28 -0
- package/dist/intellisense/Suggestion.d.ts +11 -0
- package/dist/intellisense/SuggestionOption.d.ts +4 -0
- package/dist/patterns/And.d.ts +7 -7
- package/dist/patterns/Cursor.d.ts +6 -4
- package/dist/patterns/CursorHistory.d.ts +2 -2
- package/dist/patterns/Literal.d.ts +7 -8
- package/dist/patterns/Not.d.ts +8 -5
- package/dist/patterns/Or.d.ts +7 -5
- package/dist/patterns/Pattern.d.ts +7 -4
- package/dist/patterns/Reference.d.ts +10 -7
- package/dist/patterns/Regex.d.ts +7 -8
- package/dist/patterns/Repeat.d.ts +7 -7
- package/package.json +1 -1
- package/src/ast/Node.test.ts +110 -0
- package/src/ast/Node.ts +71 -5
- package/src/index.ts +14 -3
- package/src/intellisense/AutoComplete.test.ts +90 -12
- package/src/intellisense/AutoComplete.ts +66 -12
- package/src/intellisense/Suggestion.ts +3 -4
- package/src/intellisense/javascript/Javascript.test.ts +56 -56
- package/src/intellisense/javascript/escapedCharacter.ts +0 -1
- package/src/intellisense/javascript/exponent.ts +0 -2
- package/src/intellisense/javascript/fraction.ts +0 -2
- package/src/patterns/And.test.ts +63 -52
- package/src/patterns/And.ts +58 -36
- package/src/patterns/Cursor.ts +17 -14
- package/src/patterns/CursorHistory.ts +8 -8
- package/src/patterns/Literal.test.ts +70 -38
- package/src/patterns/Literal.ts +31 -42
- package/src/patterns/Not.test.ts +88 -8
- package/src/patterns/Not.ts +54 -14
- package/src/patterns/Or.test.ts +117 -13
- package/src/patterns/Or.ts +36 -13
- package/src/patterns/Pattern.ts +7 -4
- package/src/patterns/Reference.test.ts +117 -28
- package/src/patterns/Reference.ts +58 -32
- package/src/patterns/Regex.test.ts +67 -35
- package/src/patterns/Regex.ts +31 -43
- package/src/patterns/Repeat.test.ts +63 -41
- package/src/patterns/Repeat.ts +51 -38
- package/src/patterns/getNextPattern.test.ts +0 -39
- package/src/patterns/getNextPattern.ts +0 -18
|
@@ -1,25 +1,28 @@
|
|
|
1
|
-
import { Cursor, Repeat } from "..";
|
|
2
1
|
import { Node } from "../ast/Node";
|
|
3
2
|
import { And } from "./And";
|
|
3
|
+
import { Cursor } from "./Cursor";
|
|
4
4
|
import { findPattern } from "./findPattern";
|
|
5
5
|
import { Literal } from "./Literal";
|
|
6
6
|
import { Or } from "./Or";
|
|
7
|
+
import { Pattern } from "./Pattern";
|
|
7
8
|
import { Reference } from "./Reference";
|
|
8
9
|
import { Regex } from "./Regex";
|
|
10
|
+
import { Repeat } from "./Repeat";
|
|
9
11
|
|
|
10
12
|
function createValuePattern() {
|
|
11
13
|
const number = new Regex("number", "\\d+");
|
|
14
|
+
number.setTokens(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]);
|
|
15
|
+
|
|
12
16
|
const openBracket = new Literal("open-bracket", "[");
|
|
13
17
|
const closeBracket = new Literal("close-bracket", "]");
|
|
14
18
|
const divider = new Regex("divider", "\\s*,\\s+");
|
|
19
|
+
divider.setTokens([", "]);
|
|
20
|
+
|
|
15
21
|
const valueRef = new Reference("value");
|
|
16
22
|
const values = new Repeat("values", valueRef, divider);
|
|
17
23
|
const array = new And("array", [openBracket, values, closeBracket]);
|
|
18
24
|
const value = new Or("value", [number, array]);
|
|
19
25
|
|
|
20
|
-
number.setTokens(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]);
|
|
21
|
-
divider.setTokens([", "])
|
|
22
|
-
|
|
23
26
|
return value;
|
|
24
27
|
}
|
|
25
28
|
|
|
@@ -54,37 +57,30 @@ describe("Reference", () => {
|
|
|
54
57
|
const value = createValuePattern();
|
|
55
58
|
const ref = findPattern(value, (p) => p.type === "reference");
|
|
56
59
|
const tokens = ref?.getTokens();
|
|
57
|
-
const expected = [
|
|
60
|
+
const expected = [
|
|
61
|
+
"1",
|
|
62
|
+
"2",
|
|
63
|
+
"3",
|
|
64
|
+
"4",
|
|
65
|
+
"5",
|
|
66
|
+
"6",
|
|
67
|
+
"7",
|
|
68
|
+
"8",
|
|
69
|
+
"9",
|
|
70
|
+
"0",
|
|
71
|
+
"["
|
|
72
|
+
];
|
|
58
73
|
|
|
59
74
|
expect(tokens).toEqual(expected);
|
|
60
75
|
});
|
|
61
76
|
|
|
62
|
-
test("Get
|
|
63
|
-
const value = createValuePattern();
|
|
64
|
-
const ref = findPattern(value, (p) => p.type === "reference");
|
|
65
|
-
|
|
66
|
-
// The value passed to getNextTokens doesn't matter.
|
|
67
|
-
// I just needed it to be a pattern.
|
|
68
|
-
const tokens = ref?.getNextTokens(value);
|
|
69
|
-
const expected = ["]"];
|
|
70
|
-
|
|
71
|
-
expect(tokens).toEqual(expected);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test("Get Next Tokens With No Parent", () => {
|
|
77
|
+
test("Get Tokens After With No Parent", () => {
|
|
75
78
|
const ref = new Reference("bad-reference");
|
|
76
|
-
const tokens = ref.
|
|
79
|
+
const tokens = ref.getTokensAfter(new Literal("bogus", "bogus"))
|
|
77
80
|
|
|
78
81
|
expect(tokens).toEqual([]);
|
|
79
82
|
});
|
|
80
83
|
|
|
81
|
-
test("Get Next Pattern", () => {
|
|
82
|
-
const ref = new Reference("ref");
|
|
83
|
-
const nextPattern = ref.getNextPattern();
|
|
84
|
-
|
|
85
|
-
expect(nextPattern).toBeNull()
|
|
86
|
-
});
|
|
87
|
-
|
|
88
84
|
test("Properties", () => {
|
|
89
85
|
const ref = new Reference("ref");
|
|
90
86
|
|
|
@@ -95,10 +91,103 @@ describe("Reference", () => {
|
|
|
95
91
|
expect(ref.children).toEqual([])
|
|
96
92
|
});
|
|
97
93
|
|
|
98
|
-
test("
|
|
94
|
+
test("Exec", () => {
|
|
99
95
|
const value = createValuePattern();
|
|
100
96
|
const reference = findPattern(value, p => p.type === "reference") as Reference
|
|
101
|
-
const { ast: result } = reference.
|
|
97
|
+
const { ast: result } = reference.exec("B");
|
|
102
98
|
expect(result).toBeNull()
|
|
103
99
|
});
|
|
100
|
+
|
|
101
|
+
test("Test With Match", () => {
|
|
102
|
+
const value = createValuePattern();
|
|
103
|
+
const reference = findPattern(value, p => p.type === "reference") as Reference
|
|
104
|
+
const result = reference.test("[1]");
|
|
105
|
+
expect(result).toBeTruthy()
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("Test No Match", () => {
|
|
109
|
+
const value = createValuePattern();
|
|
110
|
+
const reference = findPattern(value, p => p.type === "reference") as Reference
|
|
111
|
+
const result = reference.test("B");
|
|
112
|
+
expect(result).toBeFalsy()
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("Find Pattern", () => {
|
|
116
|
+
const value = createValuePattern();
|
|
117
|
+
const reference = value.findPattern(p => p.type === "reference") as Pattern;
|
|
118
|
+
|
|
119
|
+
const pattern = reference?.findPattern(p => p.name === "Nada");
|
|
120
|
+
|
|
121
|
+
expect(pattern).toBe(null);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
test("Get Next Tokens", () => {
|
|
126
|
+
const value = createValuePattern();
|
|
127
|
+
const reference = value.findPattern(p => p.type === "reference") as Pattern;
|
|
128
|
+
const tokens = reference.getNextTokens();
|
|
129
|
+
|
|
130
|
+
expect(tokens).toEqual([", ", "]"]);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test("Get Next Tokens With Null Parent", () => {
|
|
134
|
+
const reference = new Reference("ref-name");
|
|
135
|
+
const tokens = reference.getNextTokens();
|
|
136
|
+
|
|
137
|
+
expect(tokens).toEqual([])
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("Get Tokens After", () => {
|
|
141
|
+
const value = createValuePattern();
|
|
142
|
+
const reference = value.findPattern(p => p.type === "reference") as Pattern;
|
|
143
|
+
const tokens = reference.getTokensAfter(new Literal("bogus", "Bogus"));
|
|
144
|
+
|
|
145
|
+
expect(tokens).toEqual([", ", "]"]);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("Get Tokens After With Null Parent", () => {
|
|
149
|
+
const reference = new Reference("ref-name");
|
|
150
|
+
const tokens = reference.getTokensAfter(new Literal("bogus", "Bogus"));
|
|
151
|
+
|
|
152
|
+
expect(tokens).toEqual([])
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("Get Patterns After", () => {
|
|
156
|
+
const value = createValuePattern();
|
|
157
|
+
const reference = value.findPattern(p => p.type === "reference") as Pattern;
|
|
158
|
+
const patterns = reference.getPatternsAfter(new Literal("bogus", "Bogus"));
|
|
159
|
+
|
|
160
|
+
expect(patterns.length).toEqual(2);
|
|
161
|
+
expect(patterns[0].type).toEqual("regex");
|
|
162
|
+
expect(patterns[0].name).toEqual("divider");
|
|
163
|
+
expect(patterns[1].type).toEqual("literal");
|
|
164
|
+
expect(patterns[1].name).toEqual("close-bracket");
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("Get Patterns After With Null Parent", () => {
|
|
168
|
+
const reference = new Reference("ref-name");
|
|
169
|
+
const patterns = reference.getPatternsAfter(new Literal("bogus", "Bogus"));
|
|
170
|
+
|
|
171
|
+
expect(patterns).toEqual([])
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("Get Next Patterns", () => {
|
|
175
|
+
const value = createValuePattern();
|
|
176
|
+
const reference = value.findPattern(p => p.type === "reference") as Pattern;
|
|
177
|
+
const patterns = reference.getNextPatterns();
|
|
178
|
+
|
|
179
|
+
expect(patterns.length).toEqual(2);
|
|
180
|
+
expect(patterns[0].type).toEqual("regex");
|
|
181
|
+
expect(patterns[0].name).toEqual("divider");
|
|
182
|
+
expect(patterns[1].type).toEqual("literal");
|
|
183
|
+
expect(patterns[1].name).toEqual("close-bracket");
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("Get Next Patterns With Null Parent", () => {
|
|
187
|
+
const reference = new Reference("ref-name");
|
|
188
|
+
const patterns = reference.getNextPatterns();
|
|
189
|
+
|
|
190
|
+
expect(patterns).toEqual([])
|
|
191
|
+
});
|
|
192
|
+
|
|
104
193
|
});
|
|
@@ -2,7 +2,6 @@ import { Node } from "../ast/Node";
|
|
|
2
2
|
import { Cursor } from "./Cursor";
|
|
3
3
|
import { Pattern } from "./Pattern";
|
|
4
4
|
import { findPattern } from "./findPattern";
|
|
5
|
-
import { getNextPattern } from "./getNextPattern";
|
|
6
5
|
|
|
7
6
|
export class Reference implements Pattern {
|
|
8
7
|
private _type: string;
|
|
@@ -20,10 +19,6 @@ export class Reference implements Pattern {
|
|
|
20
19
|
return this._name;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
get isOptional(): boolean {
|
|
24
|
-
return this._isOptional;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
22
|
get parent(): Pattern | null {
|
|
28
23
|
return this._parent;
|
|
29
24
|
}
|
|
@@ -36,6 +31,10 @@ export class Reference implements Pattern {
|
|
|
36
31
|
return this._children
|
|
37
32
|
}
|
|
38
33
|
|
|
34
|
+
get isOptional(): boolean {
|
|
35
|
+
return this._isOptional;
|
|
36
|
+
}
|
|
37
|
+
|
|
39
38
|
constructor(name: string, isOptional: boolean = false) {
|
|
40
39
|
this._type = "reference";
|
|
41
40
|
this._name = name;
|
|
@@ -45,12 +44,19 @@ export class Reference implements Pattern {
|
|
|
45
44
|
this._children = [];
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
test(text: string) {
|
|
49
48
|
const cursor = new Cursor(text);
|
|
50
|
-
const ast = this.parse(cursor)
|
|
49
|
+
const ast = this.parse(cursor);
|
|
50
|
+
|
|
51
|
+
return ast?.value === text;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exec(text: string) {
|
|
55
|
+
const cursor = new Cursor(text);
|
|
56
|
+
const ast = this.parse(cursor);
|
|
51
57
|
|
|
52
58
|
return {
|
|
53
|
-
ast,
|
|
59
|
+
ast: ast?.value === text ? ast : null,
|
|
54
60
|
cursor
|
|
55
61
|
};
|
|
56
62
|
}
|
|
@@ -59,30 +65,6 @@ export class Reference implements Pattern {
|
|
|
59
65
|
return this._getPatternSafely().parse(cursor);
|
|
60
66
|
}
|
|
61
67
|
|
|
62
|
-
clone(name = this._name, isOptional = this._isOptional): Pattern {
|
|
63
|
-
return new Reference(name, isOptional);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
getTokens(): string[] {
|
|
67
|
-
return this._getPatternSafely().getTokens();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getNextTokens(_lastMatched: Pattern): string[] {
|
|
71
|
-
if (this.parent == null) {
|
|
72
|
-
return [];
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return this.parent.getNextTokens(this);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
getNextPattern(): Pattern | null {
|
|
79
|
-
return getNextPattern(this)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
findPattern(_isMatch: (p: Pattern)=>boolean): Pattern | null{
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
68
|
private _getPatternSafely(): Pattern {
|
|
87
69
|
if (this._pattern === null) {
|
|
88
70
|
const pattern = this._findPattern();
|
|
@@ -124,4 +106,48 @@ export class Reference implements Pattern {
|
|
|
124
106
|
|
|
125
107
|
return node;
|
|
126
108
|
}
|
|
109
|
+
|
|
110
|
+
getTokens(): string[] {
|
|
111
|
+
return this._getPatternSafely().getTokens();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getTokensAfter(_lastMatched: Pattern): string[] {
|
|
115
|
+
if (this._parent == null) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return this._parent.getTokensAfter(this);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
getNextTokens(): string[] {
|
|
123
|
+
if (this.parent == null) {
|
|
124
|
+
return []
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return this.parent.getTokensAfter(this);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
getPatternsAfter(_childReference: Pattern): Pattern[] {
|
|
131
|
+
if (this._parent == null) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return this._parent.getPatternsAfter(this);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
getNextPatterns(): Pattern[] {
|
|
139
|
+
if (this.parent == null) {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return this.parent.getPatternsAfter(this)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
findPattern(_predicate: (p: Pattern) => boolean): Pattern | null {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
clone(name = this._name, isOptional = this._isOptional): Pattern {
|
|
151
|
+
return new Reference(name, isOptional);
|
|
152
|
+
}
|
|
127
153
|
}
|
|
@@ -3,6 +3,7 @@ import { Regex } from "./Regex";
|
|
|
3
3
|
import { Node } from "../ast/Node"
|
|
4
4
|
import { And } from "./And";
|
|
5
5
|
import { Literal } from "./Literal";
|
|
6
|
+
import { Pattern } from "./Pattern";
|
|
6
7
|
|
|
7
8
|
describe("Regex", () => {
|
|
8
9
|
test("Empty String", () => {
|
|
@@ -38,52 +39,24 @@ describe("Regex", () => {
|
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
test("Get Tokens", () => {
|
|
41
|
-
const
|
|
42
|
-
new Regex("a", "A"),
|
|
43
|
-
new Regex("b", "B")
|
|
44
|
-
]);
|
|
45
|
-
|
|
46
|
-
const a = parent.children[0] as Regex;
|
|
47
|
-
const b = parent.children[1] as Regex;
|
|
42
|
+
const a = new Regex("a", "A");
|
|
48
43
|
|
|
49
44
|
a.setTokens(["A"]);
|
|
50
|
-
b.setTokens(["B"]);
|
|
51
|
-
|
|
52
|
-
let tokens = a.getTokens();
|
|
53
|
-
let expectedTokens = ["A"];
|
|
54
|
-
|
|
55
|
-
expect(tokens).toEqual(expectedTokens);
|
|
56
|
-
|
|
57
|
-
a.enableContextualTokenAggregation();
|
|
58
45
|
|
|
59
|
-
tokens = a.getTokens();
|
|
60
|
-
expectedTokens = ["
|
|
61
|
-
|
|
62
|
-
expect(tokens).toEqual(expectedTokens);
|
|
63
|
-
|
|
64
|
-
a.disableContextualTokenAggregation();
|
|
65
|
-
|
|
66
|
-
tokens = a.getTokens();
|
|
67
|
-
expectedTokens = ["A"];
|
|
46
|
+
const tokens = a.getTokens();
|
|
47
|
+
const expectedTokens = ["A"];
|
|
68
48
|
|
|
69
49
|
expect(tokens).toEqual(expectedTokens);
|
|
70
50
|
});
|
|
71
51
|
|
|
72
|
-
test("Get
|
|
52
|
+
test("Get Tokens After", () => {
|
|
73
53
|
const regex = new Regex("a", "A");
|
|
74
|
-
const tokens = regex.
|
|
54
|
+
const tokens = regex.getTokensAfter(new Literal("bogus", "bogus"));
|
|
75
55
|
const expected: string[] = [];
|
|
76
56
|
|
|
77
57
|
expect(tokens).toEqual(expected)
|
|
78
58
|
});
|
|
79
59
|
|
|
80
|
-
test("Get Next Pattern", () => {
|
|
81
|
-
const regex = new Regex("a", "A");
|
|
82
|
-
const nextPattern = regex.getNextPattern();
|
|
83
|
-
|
|
84
|
-
expect(nextPattern).toBeNull()
|
|
85
|
-
});
|
|
86
|
-
|
|
87
60
|
test("Properties", () => {
|
|
88
61
|
const regex = new Regex("a", "A");
|
|
89
62
|
|
|
@@ -93,9 +66,68 @@ describe("Regex", () => {
|
|
|
93
66
|
expect(regex.children).toEqual([]);
|
|
94
67
|
});
|
|
95
68
|
|
|
96
|
-
test("
|
|
69
|
+
test("Exec", () => {
|
|
97
70
|
const regex = new Regex("a", "A");
|
|
98
|
-
const { ast: result } = regex.
|
|
71
|
+
const { ast: result } = regex.exec("B");
|
|
99
72
|
expect(result).toBeNull();
|
|
100
73
|
});
|
|
74
|
+
|
|
75
|
+
test("Test With Match", () => {
|
|
76
|
+
const regex = new Regex("a", "A");
|
|
77
|
+
const result = regex.test("A");
|
|
78
|
+
expect(result).toBeTruthy();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("Test With No Match", () => {
|
|
82
|
+
const regex = new Regex("a", "A");
|
|
83
|
+
const result = regex.test("B");
|
|
84
|
+
expect(result).toBeFalsy();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("Get Next Tokens", () => {
|
|
88
|
+
const parent = new And("parent", [new Regex("a", "A"), new Literal("b", "B")]);
|
|
89
|
+
const aClone = parent.findPattern(p => p.name === "a") as Pattern;
|
|
90
|
+
const tokens = aClone.getNextTokens();
|
|
91
|
+
|
|
92
|
+
expect(tokens).toEqual(["B"]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("Get Next Tokens With Null Parent", () => {
|
|
96
|
+
const a = new Regex("a", "A")
|
|
97
|
+
const tokens = a.getNextTokens();
|
|
98
|
+
|
|
99
|
+
expect(tokens).toEqual([]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("Get Patterns After", () => {
|
|
103
|
+
const a = new Regex("a", "A")
|
|
104
|
+
const patterns = a.getPatternsAfter(new Literal("bogus", "bogus"));
|
|
105
|
+
|
|
106
|
+
expect(patterns).toEqual([]);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("Find Pattern", () => {
|
|
110
|
+
const a = new Regex("a", "A")
|
|
111
|
+
const pattern = a.findPattern(p => p.name === "other");
|
|
112
|
+
|
|
113
|
+
expect(pattern).toBeNull();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("Get Next Patterns", () => {
|
|
117
|
+
const parent = new And("parent", [new Regex("a", "A"), new Literal("b", "B")]);
|
|
118
|
+
const aClone = parent.findPattern(p => p.name === "a") as Pattern;
|
|
119
|
+
const bClone = parent.findPattern(p => p.name === "b") as Pattern;
|
|
120
|
+
const patterns = aClone.getNextPatterns();
|
|
121
|
+
|
|
122
|
+
expect(patterns.length).toBe(1);
|
|
123
|
+
expect(patterns[0]).toBe(bClone);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("Get Next Patterns With Null Parent", () => {
|
|
127
|
+
const a = new Regex("a", "A")
|
|
128
|
+
const patterns = a.getNextPatterns();
|
|
129
|
+
|
|
130
|
+
expect(patterns).toEqual([])
|
|
131
|
+
});
|
|
132
|
+
|
|
101
133
|
});
|
package/src/patterns/Regex.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Node } from "../ast/Node";
|
|
2
2
|
import { Pattern } from "./Pattern";
|
|
3
3
|
import { Cursor } from "./Cursor";
|
|
4
|
-
import { getNextPattern } from "./getNextPattern";
|
|
5
4
|
|
|
6
5
|
export class Regex implements Pattern {
|
|
7
6
|
private _type: string;
|
|
@@ -14,8 +13,6 @@ export class Regex implements Pattern {
|
|
|
14
13
|
private _cursor: Cursor | null = null;
|
|
15
14
|
private _substring: string = "";
|
|
16
15
|
private _tokens: string[] = [];
|
|
17
|
-
private _hasContextualTokenAggregation = false;
|
|
18
|
-
private _isRetrievingContextualTokens: boolean = false;
|
|
19
16
|
|
|
20
17
|
get type(): string {
|
|
21
18
|
return this._type;
|
|
@@ -71,12 +68,19 @@ export class Regex implements Pattern {
|
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
|
|
71
|
+
test(text: string) {
|
|
75
72
|
const cursor = new Cursor(text);
|
|
76
|
-
const ast = this.parse(cursor)
|
|
73
|
+
const ast = this.parse(cursor);
|
|
74
|
+
|
|
75
|
+
return ast?.value === text;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
exec(text: string) {
|
|
79
|
+
const cursor = new Cursor(text);
|
|
80
|
+
const ast = this.parse(cursor);
|
|
77
81
|
|
|
78
82
|
return {
|
|
79
|
-
ast,
|
|
83
|
+
ast: ast?.value === text ? ast : null,
|
|
80
84
|
cursor
|
|
81
85
|
};
|
|
82
86
|
}
|
|
@@ -114,7 +118,7 @@ export class Regex implements Pattern {
|
|
|
114
118
|
this._name,
|
|
115
119
|
currentIndex,
|
|
116
120
|
newIndex,
|
|
117
|
-
|
|
121
|
+
undefined,
|
|
118
122
|
result[0]
|
|
119
123
|
);
|
|
120
124
|
|
|
@@ -133,60 +137,44 @@ export class Regex implements Pattern {
|
|
|
133
137
|
clone(name = this._name, isOptional = this._isOptional) {
|
|
134
138
|
const pattern = new Regex(name, this._originalRegexString, isOptional);
|
|
135
139
|
pattern._tokens = this._tokens.slice();
|
|
136
|
-
pattern._hasContextualTokenAggregation =
|
|
137
|
-
this._hasContextualTokenAggregation;
|
|
138
140
|
|
|
139
141
|
return pattern;
|
|
140
142
|
}
|
|
141
143
|
|
|
142
144
|
getTokens() {
|
|
143
|
-
const parent = this._parent;
|
|
144
|
-
|
|
145
|
-
if (this._hasContextualTokenAggregation &&
|
|
146
|
-
parent != null &&
|
|
147
|
-
!this._isRetrievingContextualTokens
|
|
148
|
-
) {
|
|
149
|
-
this._isRetrievingContextualTokens = true;
|
|
150
|
-
|
|
151
|
-
const tokens = this._tokens;
|
|
152
|
-
const aggregateTokens: string[] = [];
|
|
153
|
-
const nextTokens = parent.getNextTokens(this);
|
|
154
|
-
|
|
155
|
-
for (let nextToken of nextTokens) {
|
|
156
|
-
for (let token of tokens) {
|
|
157
|
-
aggregateTokens.push(token + nextToken);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
this._isRetrievingContextualTokens = false
|
|
162
|
-
return aggregateTokens;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
145
|
return this._tokens;
|
|
166
146
|
}
|
|
167
147
|
|
|
168
|
-
|
|
148
|
+
getTokensAfter(_childReference: Pattern): string[] {
|
|
169
149
|
return [];
|
|
170
150
|
}
|
|
171
151
|
|
|
172
|
-
|
|
173
|
-
|
|
152
|
+
getNextTokens(): string[] {
|
|
153
|
+
if (this.parent == null) {
|
|
154
|
+
return []
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return this.parent.getTokensAfter(this);
|
|
174
158
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return
|
|
159
|
+
|
|
160
|
+
getPatternsAfter(_childReference: Pattern): Pattern[] {
|
|
161
|
+
return [];
|
|
178
162
|
}
|
|
179
163
|
|
|
180
|
-
|
|
181
|
-
this.
|
|
164
|
+
getNextPatterns(): Pattern[] {
|
|
165
|
+
if (this.parent == null) {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return this.parent.getPatternsAfter(this)
|
|
182
170
|
}
|
|
183
171
|
|
|
184
|
-
|
|
185
|
-
|
|
172
|
+
findPattern(_predicate: (p: Pattern) => boolean): Pattern | null {
|
|
173
|
+
return null;
|
|
186
174
|
}
|
|
187
175
|
|
|
188
|
-
|
|
189
|
-
this.
|
|
176
|
+
setTokens(tokens: string[]) {
|
|
177
|
+
this._tokens = tokens;
|
|
190
178
|
}
|
|
191
179
|
|
|
192
180
|
}
|