clarity-pattern-parser 10.3.7 → 11.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/dist/ast/Node.d.ts +2 -2
- package/dist/ast/compact.d.ts +2 -0
- package/dist/ast/remove.d.ts +2 -0
- package/dist/index.browser.js +417 -487
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +416 -488
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +417 -487
- package/dist/index.js.map +1 -1
- package/dist/patterns/ExpressionPattern.d.ts +27 -25
- package/dist/patterns/FiniteRepeat.d.ts +1 -2
- package/dist/patterns/InfiniteRepeat.d.ts +1 -2
- package/dist/patterns/Literal.d.ts +0 -1
- package/dist/patterns/Not.d.ts +1 -2
- package/dist/patterns/Optional.d.ts +0 -1
- package/dist/patterns/Options.d.ts +1 -2
- package/dist/patterns/Pattern.d.ts +0 -1
- package/dist/patterns/PrecedenceTree.d.ts +28 -0
- package/dist/patterns/Reference.d.ts +1 -2
- package/dist/patterns/Regex.d.ts +1 -2
- package/dist/patterns/Repeat.d.ts +0 -3
- package/dist/patterns/Sequence.d.ts +3 -6
- package/dist/patterns/execPattern.d.ts +3 -0
- package/dist/patterns/testPattern.d.ts +2 -0
- package/package.json +1 -1
- package/src/ast/Node.test.ts +17 -17
- package/src/ast/Node.ts +7 -5
- package/src/ast/compact.ts +11 -0
- package/src/ast/remove.ts +11 -0
- package/src/grammar/Grammar.test.ts +0 -50
- package/src/grammar/Grammar.ts +0 -20
- package/src/grammar/patterns/statement.ts +1 -6
- package/src/index.ts +4 -0
- package/src/patterns/ExpressionPattern.test.ts +1 -1
- package/src/patterns/ExpressionPattern.ts +235 -384
- package/src/patterns/FiniteRepeat.ts +5 -22
- package/src/patterns/InfiniteRepeat.ts +6 -21
- package/src/patterns/Literal.ts +5 -19
- package/src/patterns/Not.ts +5 -16
- package/src/patterns/Optional.ts +0 -7
- package/src/patterns/Options.ts +5 -21
- package/src/patterns/Pattern.ts +0 -1
- package/src/patterns/PrecedenceTree.test.ts +162 -0
- package/src/patterns/PrecedenceTree.ts +207 -0
- package/src/patterns/Reference.ts +5 -17
- package/src/patterns/Regex.ts +5 -17
- package/src/patterns/Repeat.ts +1 -13
- package/src/patterns/Sequence.ts +7 -22
- package/src/patterns/execPattern.ts +16 -0
- package/src/patterns/testPattern.ts +11 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { Node } from "../ast/Node";
|
|
2
|
+
|
|
3
|
+
export enum Association {
|
|
4
|
+
left = 0,
|
|
5
|
+
right,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class PrecedenceTree {
|
|
9
|
+
private _prefixPlaceholder: Node;
|
|
10
|
+
private _prefixNode: Node | null;
|
|
11
|
+
private _postfixPlaceholder: Node;
|
|
12
|
+
private _postfixNode: Node | null;
|
|
13
|
+
private _binaryPlaceholder: Node;
|
|
14
|
+
private _binaryNode: Node | null;
|
|
15
|
+
private _atomNode: Node | null;
|
|
16
|
+
private _orphanedAtom: Node | null;
|
|
17
|
+
private _precedenceMap: Record<string, number>;
|
|
18
|
+
private _associationMap: Record<string, Association>;
|
|
19
|
+
|
|
20
|
+
constructor(precedenceMap: Record<string, number> = {}, associationMap: Record<string, Association> = {}) {
|
|
21
|
+
this._prefixPlaceholder = Node.createNode("placeholder", "prefix-placeholder");
|
|
22
|
+
this._prefixNode = null;
|
|
23
|
+
this._postfixPlaceholder = Node.createNode("placeholder", "postfix-placeholder");
|
|
24
|
+
this._postfixNode = null;
|
|
25
|
+
this._binaryPlaceholder = Node.createNode("placeholder", "binary-placeholder");
|
|
26
|
+
this._atomNode = null;
|
|
27
|
+
this._binaryNode = null;
|
|
28
|
+
this._orphanedAtom = null;
|
|
29
|
+
this._precedenceMap = precedenceMap;
|
|
30
|
+
this._associationMap = associationMap;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
addPrefix(name: string, ...prefix: Node[]) {
|
|
34
|
+
const lastPrefixNode = this._prefixNode;
|
|
35
|
+
|
|
36
|
+
if (lastPrefixNode == null) {
|
|
37
|
+
const node = Node.createNode("expression", name, [...prefix]);
|
|
38
|
+
this._prefixNode = node;
|
|
39
|
+
this._prefixNode.append(this._prefixPlaceholder);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const node = Node.createNode("expression", name, [...prefix]);
|
|
44
|
+
this._prefixPlaceholder.replaceWith(node);
|
|
45
|
+
node.append(this._prefixPlaceholder);
|
|
46
|
+
|
|
47
|
+
this._prefixNode = node;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
addPostfix(name: string, ...postfix: Node[]) {
|
|
51
|
+
const lastPostfixNode = this._postfixNode;
|
|
52
|
+
|
|
53
|
+
if (lastPostfixNode == null) {
|
|
54
|
+
const node = Node.createNode("expression", name, [this._postfixPlaceholder, ...postfix]);
|
|
55
|
+
this._postfixNode = node;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const node = Node.createNode("expression", name, [lastPostfixNode, ...postfix]);
|
|
60
|
+
this._postfixNode = node;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
addBinary(name: string, ...delimiterNode: Node[]) {
|
|
64
|
+
const lastBinaryNode = this._binaryNode;
|
|
65
|
+
const lastPrecendece = this._getPrecedenceFromNode(this._binaryNode);
|
|
66
|
+
const precedence = this._getPrecedence(name);
|
|
67
|
+
const association = this._associationMap[name];
|
|
68
|
+
const lastAtomNode = this._compileAtomNode();
|
|
69
|
+
|
|
70
|
+
if (lastAtomNode == null) {
|
|
71
|
+
throw new Error("Cannot add a binary without an atom node.");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this._binaryPlaceholder.remove();
|
|
75
|
+
this._orphanedAtom = lastAtomNode;
|
|
76
|
+
|
|
77
|
+
if (lastBinaryNode == null) {
|
|
78
|
+
const node = Node.createNode("expression", name, [lastAtomNode, ...delimiterNode, this._binaryPlaceholder]);
|
|
79
|
+
|
|
80
|
+
this._binaryNode = node;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (precedence === lastPrecendece && association === Association.right) {
|
|
85
|
+
const node = Node.createNode("expression", name, [lastAtomNode, ...delimiterNode, this._binaryPlaceholder]);
|
|
86
|
+
|
|
87
|
+
lastBinaryNode.appendChild(node);
|
|
88
|
+
|
|
89
|
+
this._binaryNode = node;
|
|
90
|
+
} else if (precedence === lastPrecendece) {
|
|
91
|
+
const node = Node.createNode("expression", name, []);
|
|
92
|
+
|
|
93
|
+
lastBinaryNode.replaceWith(node);
|
|
94
|
+
lastBinaryNode.appendChild(lastAtomNode);
|
|
95
|
+
|
|
96
|
+
node.append(lastBinaryNode, ...delimiterNode, this._binaryPlaceholder);
|
|
97
|
+
this._binaryNode = node;
|
|
98
|
+
} else if (precedence > lastPrecendece) {
|
|
99
|
+
let ancestor = lastBinaryNode.parent;
|
|
100
|
+
let root = lastBinaryNode;
|
|
101
|
+
|
|
102
|
+
while (ancestor != null) {
|
|
103
|
+
const nodePrecedence = this._precedenceMap[ancestor.name];
|
|
104
|
+
|
|
105
|
+
if (nodePrecedence > precedence) {
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
root = ancestor;
|
|
109
|
+
ancestor = ancestor.parent;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
lastBinaryNode.appendChild(lastAtomNode);
|
|
113
|
+
|
|
114
|
+
const node = Node.createNode("expression", name, []);
|
|
115
|
+
root.replaceWith(node);
|
|
116
|
+
node.append(root, ...delimiterNode, this._binaryPlaceholder);
|
|
117
|
+
|
|
118
|
+
this._binaryNode = node;
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
} else {
|
|
122
|
+
const node = Node.createNode("expression", name, [lastAtomNode, ...delimiterNode, this._binaryPlaceholder]);
|
|
123
|
+
lastBinaryNode.appendChild(node);
|
|
124
|
+
|
|
125
|
+
this._binaryNode = node;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private _getPrecedenceFromNode(node: Node | null) {
|
|
131
|
+
if (node == null) {
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return this._getPrecedence(node.name);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private _getPrecedence(name: string) {
|
|
139
|
+
if (this._precedenceMap[name] != null) {
|
|
140
|
+
return this._precedenceMap[name];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private _compileAtomNode() {
|
|
147
|
+
let node = this._atomNode;
|
|
148
|
+
|
|
149
|
+
if (this._prefixNode != null && this._atomNode != null) {
|
|
150
|
+
node = this._prefixNode;
|
|
151
|
+
this._prefixPlaceholder.replaceWith(this._atomNode);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (this._postfixNode != null && node != null) {
|
|
155
|
+
this._postfixPlaceholder.replaceWith(node);
|
|
156
|
+
node = this._postfixNode;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this._prefixNode = null;
|
|
160
|
+
this._atomNode = null;
|
|
161
|
+
this._postfixNode = null;
|
|
162
|
+
|
|
163
|
+
if (node == null) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return node.findRoot();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
addAtom(node: Node) {
|
|
171
|
+
this._atomNode = node;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
hasAtom(){
|
|
175
|
+
return this._atomNode != null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
commit() {
|
|
179
|
+
if (this._binaryNode == null) {
|
|
180
|
+
return this._compileAtomNode();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const atomNode = this._compileAtomNode();
|
|
184
|
+
|
|
185
|
+
if (atomNode == null) {
|
|
186
|
+
let root = this._binaryPlaceholder.findRoot();
|
|
187
|
+
this._binaryPlaceholder.parent?.replaceWith(this._orphanedAtom as Node);
|
|
188
|
+
this.reset();
|
|
189
|
+
return root;
|
|
190
|
+
} else {
|
|
191
|
+
this._binaryPlaceholder.replaceWith(atomNode);
|
|
192
|
+
const root = this._binaryNode.findRoot();
|
|
193
|
+
this.reset();
|
|
194
|
+
return root;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private reset() {
|
|
200
|
+
this._prefixNode = null;
|
|
201
|
+
this._atomNode = null;
|
|
202
|
+
this._orphanedAtom = null;
|
|
203
|
+
this._postfixNode = null;
|
|
204
|
+
this._binaryNode = null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
}
|
|
@@ -4,6 +4,8 @@ import { Pattern } from "./Pattern";
|
|
|
4
4
|
import { findPattern } from "./findPattern";
|
|
5
5
|
import { ParseResult } from "./ParseResult";
|
|
6
6
|
import { Context } from "./Context";
|
|
7
|
+
import { testPattern } from "./testPattern";
|
|
8
|
+
import { execPattern } from "./execPattern";
|
|
7
9
|
|
|
8
10
|
let idIndex = 0;
|
|
9
11
|
|
|
@@ -17,8 +19,6 @@ export class Reference implements Pattern {
|
|
|
17
19
|
private _children: Pattern[];
|
|
18
20
|
private _firstIndex: number;
|
|
19
21
|
|
|
20
|
-
shouldCompactAst = false;
|
|
21
|
-
|
|
22
22
|
get id(): string {
|
|
23
23
|
return this._id;
|
|
24
24
|
}
|
|
@@ -58,23 +58,12 @@ export class Reference implements Pattern {
|
|
|
58
58
|
this._firstIndex = 0;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
test(text: string) {
|
|
62
|
-
|
|
63
|
-
const ast = this.parse(cursor);
|
|
64
|
-
|
|
65
|
-
return ast?.value === text;
|
|
61
|
+
test(text: string, record = false): boolean {
|
|
62
|
+
return testPattern(this, text, record);
|
|
66
63
|
}
|
|
67
64
|
|
|
68
65
|
exec(text: string, record = false): ParseResult {
|
|
69
|
-
|
|
70
|
-
record && cursor.startRecording();
|
|
71
|
-
|
|
72
|
-
const ast = this.parse(cursor);
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
ast: ast?.value === text ? ast : null,
|
|
76
|
-
cursor
|
|
77
|
-
};
|
|
66
|
+
return execPattern(this, text, record);
|
|
78
67
|
}
|
|
79
68
|
|
|
80
69
|
parse(cursor: Cursor): Node | null {
|
|
@@ -205,7 +194,6 @@ export class Reference implements Pattern {
|
|
|
205
194
|
clone(name = this._name): Pattern {
|
|
206
195
|
const clone = new Reference(name);
|
|
207
196
|
clone._id = this._id;
|
|
208
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
209
197
|
|
|
210
198
|
// Optimize future clones, by caching the pattern we already found.
|
|
211
199
|
if (this._pattern != null) {
|
package/src/patterns/Regex.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { Node } from "../ast/Node";
|
|
|
2
2
|
import { Pattern } from "./Pattern";
|
|
3
3
|
import { Cursor } from "./Cursor";
|
|
4
4
|
import { ParseResult } from "./ParseResult";
|
|
5
|
+
import { testPattern } from "./testPattern";
|
|
6
|
+
import { execPattern } from "./execPattern";
|
|
5
7
|
|
|
6
8
|
let idIndex = 0;
|
|
7
9
|
|
|
@@ -18,8 +20,6 @@ export class Regex implements Pattern {
|
|
|
18
20
|
private _substring = "";
|
|
19
21
|
private _tokens: string[] = [];
|
|
20
22
|
|
|
21
|
-
shouldCompactAst = false;
|
|
22
|
-
|
|
23
23
|
get id(): string {
|
|
24
24
|
return this._id;
|
|
25
25
|
}
|
|
@@ -82,23 +82,12 @@ export class Regex implements Pattern {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
test(text: string) {
|
|
86
|
-
|
|
87
|
-
const ast = this.parse(cursor);
|
|
88
|
-
|
|
89
|
-
return ast?.value === text;
|
|
85
|
+
test(text: string, record = false): boolean {
|
|
86
|
+
return testPattern(this, text, record);
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
exec(text: string, record = false): ParseResult {
|
|
93
|
-
|
|
94
|
-
record && cursor.startRecording();
|
|
95
|
-
|
|
96
|
-
const ast = this.parse(cursor);
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
ast: ast?.value === text ? ast : null,
|
|
100
|
-
cursor
|
|
101
|
-
};
|
|
90
|
+
return execPattern(this, text, record);
|
|
102
91
|
}
|
|
103
92
|
|
|
104
93
|
parse(cursor: Cursor) {
|
|
@@ -152,7 +141,6 @@ export class Regex implements Pattern {
|
|
|
152
141
|
const clone = new Regex(name, this._originalRegexString);
|
|
153
142
|
clone._tokens = this._tokens.slice();
|
|
154
143
|
clone._id = this._id;
|
|
155
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
156
144
|
|
|
157
145
|
return clone;
|
|
158
146
|
}
|
package/src/patterns/Repeat.ts
CHANGED
|
@@ -27,16 +27,6 @@ export class Repeat implements Pattern {
|
|
|
27
27
|
private _pattern: Pattern;
|
|
28
28
|
private _options: InternalRepeatOptions;
|
|
29
29
|
private _children: Pattern[];
|
|
30
|
-
private _shouldCompactAst: boolean;
|
|
31
|
-
|
|
32
|
-
get shouldCompactAst() {
|
|
33
|
-
return this._shouldCompactAst;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
set shouldCompactAst(value: boolean) {
|
|
37
|
-
this._shouldCompactAst = value;
|
|
38
|
-
this._repeatPattern.shouldCompactAst = value;
|
|
39
|
-
}
|
|
40
30
|
|
|
41
31
|
get id() {
|
|
42
32
|
return this._id;
|
|
@@ -70,7 +60,7 @@ export class Repeat implements Pattern {
|
|
|
70
60
|
return this._options.max;
|
|
71
61
|
}
|
|
72
62
|
|
|
73
|
-
get startedOnIndex(){
|
|
63
|
+
get startedOnIndex() {
|
|
74
64
|
return this._repeatPattern.startedOnIndex;
|
|
75
65
|
}
|
|
76
66
|
|
|
@@ -78,7 +68,6 @@ export class Repeat implements Pattern {
|
|
|
78
68
|
this._id = `repeat-${idIndex++}`;
|
|
79
69
|
this._pattern = pattern;
|
|
80
70
|
this._parent = null;
|
|
81
|
-
this._shouldCompactAst = false;
|
|
82
71
|
this._options = {
|
|
83
72
|
...options,
|
|
84
73
|
min: options.min == null ? 1 : options.min,
|
|
@@ -112,7 +101,6 @@ export class Repeat implements Pattern {
|
|
|
112
101
|
const clone = new Repeat(name, this._pattern, { ...this._options, min });
|
|
113
102
|
|
|
114
103
|
clone._id = this._id;
|
|
115
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
116
104
|
return clone;
|
|
117
105
|
}
|
|
118
106
|
|
package/src/patterns/Sequence.ts
CHANGED
|
@@ -5,6 +5,9 @@ import { clonePatterns } from "./clonePatterns";
|
|
|
5
5
|
import { filterOutNull } from "./filterOutNull";
|
|
6
6
|
import { findPattern } from "./findPattern";
|
|
7
7
|
import { isRecursivePattern } from "./isRecursivePattern";
|
|
8
|
+
import { testPattern } from "./testPattern";
|
|
9
|
+
import { execPattern } from "./execPattern";
|
|
10
|
+
import { ParseResult } from "./ParseResult";
|
|
8
11
|
|
|
9
12
|
let idIndex = 0;
|
|
10
13
|
|
|
@@ -17,8 +20,6 @@ export class Sequence implements Pattern {
|
|
|
17
20
|
private _nodes: (Node | null)[];
|
|
18
21
|
private _firstIndex: number;
|
|
19
22
|
|
|
20
|
-
shouldCompactAst = false;
|
|
21
|
-
|
|
22
23
|
get id(): string {
|
|
23
24
|
return this._id;
|
|
24
25
|
}
|
|
@@ -70,23 +71,12 @@ export class Sequence implements Pattern {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
test(text: string) {
|
|
74
|
-
|
|
75
|
-
const ast = this.parse(cursor);
|
|
76
|
-
|
|
77
|
-
return ast?.value === text;
|
|
74
|
+
test(text: string, record = false): boolean {
|
|
75
|
+
return testPattern(this, text, record);
|
|
78
76
|
}
|
|
79
77
|
|
|
80
|
-
exec(text: string, record = false) {
|
|
81
|
-
|
|
82
|
-
record && cursor.startRecording();
|
|
83
|
-
|
|
84
|
-
const ast = this.parse(cursor);
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
ast: ast?.value === text ? ast : null,
|
|
88
|
-
cursor
|
|
89
|
-
};
|
|
78
|
+
exec(text: string, record = false): ParseResult {
|
|
79
|
+
return execPattern(this, text, record);
|
|
90
80
|
}
|
|
91
81
|
|
|
92
82
|
parse(cursor: Cursor): Node | null {
|
|
@@ -99,10 +89,6 @@ export class Sequence implements Pattern {
|
|
|
99
89
|
|
|
100
90
|
if (node !== null) {
|
|
101
91
|
cursor.recordMatch(this, node);
|
|
102
|
-
|
|
103
|
-
if (this.shouldCompactAst) {
|
|
104
|
-
node.compact();
|
|
105
|
-
}
|
|
106
92
|
}
|
|
107
93
|
|
|
108
94
|
return node;
|
|
@@ -344,7 +330,6 @@ export class Sequence implements Pattern {
|
|
|
344
330
|
clone(name = this._name): Pattern {
|
|
345
331
|
const clone = new Sequence(name, this._children);
|
|
346
332
|
clone._id = this._id;
|
|
347
|
-
clone.shouldCompactAst = this.shouldCompactAst;
|
|
348
333
|
|
|
349
334
|
return clone;
|
|
350
335
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Cursor } from "./Cursor";
|
|
2
|
+
import { ParseResult } from "./ParseResult";
|
|
3
|
+
import { Pattern } from "./Pattern";
|
|
4
|
+
|
|
5
|
+
export function execPattern(pattern: Pattern, text: string, record = false): ParseResult {
|
|
6
|
+
const cursor = new Cursor(text);
|
|
7
|
+
record && cursor.startRecording();
|
|
8
|
+
|
|
9
|
+
const ast = pattern.parse(cursor);
|
|
10
|
+
const isMatch = ast?.value.length === text.length;
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
ast: isMatch ? ast : null,
|
|
14
|
+
cursor
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Cursor } from "./Cursor";
|
|
2
|
+
import { Pattern } from "./Pattern";
|
|
3
|
+
|
|
4
|
+
export function testPattern (pattern: Pattern, text: string, record = false): boolean{
|
|
5
|
+
const cursor = new Cursor(text);
|
|
6
|
+
record && cursor.startRecording();
|
|
7
|
+
|
|
8
|
+
const ast = pattern.parse(cursor);
|
|
9
|
+
|
|
10
|
+
return ast?.value.length === text.length;
|
|
11
|
+
}
|