clarity-pattern-parser 10.1.0 → 10.1.2
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 +6 -6
- package/dist/grammar/Grammar.d.ts +1 -0
- package/dist/index.browser.js +97 -3
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +97 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +97 -3
- package/dist/index.js.map +1 -1
- package/dist/patterns/Context.d.ts +31 -0
- package/package.json +1 -1
- package/src/grammar/Grammar.test.ts +54 -30
- package/src/grammar/Grammar.ts +16 -2
- package/src/index.ts +2 -0
- package/src/patterns/Context.test.ts +35 -0
- package/src/patterns/Context.ts +105 -0
- package/src/patterns/Reference.ts +20 -2
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Node } from "../ast/Node";
|
|
2
|
+
import { Cursor } from "./Cursor";
|
|
3
|
+
import { ParseResult } from "./ParseResult";
|
|
4
|
+
import { Pattern } from "./Pattern";
|
|
5
|
+
export declare class Context implements Pattern {
|
|
6
|
+
private _id;
|
|
7
|
+
private _type;
|
|
8
|
+
private _name;
|
|
9
|
+
private _parent;
|
|
10
|
+
private _children;
|
|
11
|
+
private _pattern;
|
|
12
|
+
get id(): string;
|
|
13
|
+
get type(): string;
|
|
14
|
+
get name(): string;
|
|
15
|
+
get parent(): Pattern | null;
|
|
16
|
+
set parent(pattern: Pattern | null);
|
|
17
|
+
get children(): Pattern[];
|
|
18
|
+
constructor(name: string, pattern: Pattern, context?: Pattern[]);
|
|
19
|
+
parse(cursor: Cursor): Node | null;
|
|
20
|
+
exec(text: string, record?: boolean | undefined): ParseResult;
|
|
21
|
+
test(text: string, record?: boolean | undefined): boolean;
|
|
22
|
+
clone(name?: string): Pattern;
|
|
23
|
+
getTokens(): string[];
|
|
24
|
+
getTokensAfter(childReference: Pattern): string[];
|
|
25
|
+
getNextTokens(): string[];
|
|
26
|
+
getPatterns(): Pattern[];
|
|
27
|
+
getPatternsAfter(childReference: Pattern): Pattern[];
|
|
28
|
+
getNextPatterns(): Pattern[];
|
|
29
|
+
find(predicate: (pattern: Pattern) => boolean): Pattern | null;
|
|
30
|
+
isEqual(pattern: Pattern): boolean;
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -8,6 +8,7 @@ import { Regex } from "../patterns/Regex";
|
|
|
8
8
|
import { Repeat } from "../patterns/Repeat";
|
|
9
9
|
import { Grammar } from "./Grammar";
|
|
10
10
|
import { Optional } from "../patterns/Optional";
|
|
11
|
+
import { Context } from "../patterns/Context";
|
|
11
12
|
|
|
12
13
|
describe("Grammar", () => {
|
|
13
14
|
test("Literal", () => {
|
|
@@ -17,7 +18,8 @@ describe("Grammar", () => {
|
|
|
17
18
|
|
|
18
19
|
const patterns = Grammar.parseString(expression);
|
|
19
20
|
const namePattern = patterns["name"];
|
|
20
|
-
const
|
|
21
|
+
const name = new Literal("name", "John");
|
|
22
|
+
const expected = new Context("name", name);
|
|
21
23
|
|
|
22
24
|
expect(namePattern.isEqual(expected)).toBeTruthy();
|
|
23
25
|
});
|
|
@@ -28,7 +30,8 @@ describe("Grammar", () => {
|
|
|
28
30
|
`;
|
|
29
31
|
const patterns = Grammar.parseString(expression);
|
|
30
32
|
const namePattern = patterns["chars"];
|
|
31
|
-
const
|
|
33
|
+
const chars = new Literal("chars", "\n\r\t\b\f\v\0\x00\u0000\"\\");
|
|
34
|
+
const expected = new Context('chars', chars);
|
|
32
35
|
|
|
33
36
|
expect(namePattern.isEqual(expected)).toBeTruthy();
|
|
34
37
|
});
|
|
@@ -39,7 +42,8 @@ describe("Grammar", () => {
|
|
|
39
42
|
`;
|
|
40
43
|
const patterns = Grammar.parseString(expression);
|
|
41
44
|
const namePattern = patterns["content"];
|
|
42
|
-
const
|
|
45
|
+
const content = new Literal("content", "With Con\"tent");
|
|
46
|
+
const expected = new Context(`content`, content);
|
|
43
47
|
|
|
44
48
|
expect(namePattern.isEqual(expected)).toBeTruthy();
|
|
45
49
|
});
|
|
@@ -52,8 +56,9 @@ describe("Grammar", () => {
|
|
|
52
56
|
const patterns = Grammar.parseString(expression);
|
|
53
57
|
const pattern = patterns["name"];
|
|
54
58
|
const name = new Regex("name", "\\w");
|
|
59
|
+
const expected = new Context(`name`, name);
|
|
55
60
|
|
|
56
|
-
expect(pattern.isEqual(
|
|
61
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
57
62
|
});
|
|
58
63
|
|
|
59
64
|
test("Or", () => {
|
|
@@ -68,8 +73,9 @@ describe("Grammar", () => {
|
|
|
68
73
|
const john = new Literal("john", "John");
|
|
69
74
|
const jane = new Literal("jane", "Jane");
|
|
70
75
|
const names = new Options("names", [john, jane], true);
|
|
76
|
+
const expected = new Context("names", names, [john, jane]);
|
|
71
77
|
|
|
72
|
-
expect(pattern.isEqual(
|
|
78
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
73
79
|
});
|
|
74
80
|
|
|
75
81
|
test("And", () => {
|
|
@@ -86,8 +92,9 @@ describe("Grammar", () => {
|
|
|
86
92
|
const firstName = new Regex("first-name", "\\w");
|
|
87
93
|
const lastName = new Regex("last-name", "\\w");
|
|
88
94
|
const fullName = new Sequence("full-name", [firstName, space, lastName]);
|
|
95
|
+
const expected = new Context("full-name", fullName, [space, firstName, lastName]);
|
|
89
96
|
|
|
90
|
-
expect(pattern.isEqual(
|
|
97
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
91
98
|
});
|
|
92
99
|
|
|
93
100
|
test("And With Optional Pattern", () => {
|
|
@@ -106,10 +113,12 @@ describe("Grammar", () => {
|
|
|
106
113
|
const firstName = new Regex("first-name", "\\w");
|
|
107
114
|
const lastName = new Regex("last-name", "\\w");
|
|
108
115
|
const middleName = new Regex("middle-name", "\\w");
|
|
109
|
-
const middleNameWithSpace = new
|
|
110
|
-
const
|
|
116
|
+
const middleNameWithSpace = new Sequence("middle-name-with-space", [middleName, space]);
|
|
117
|
+
const optionalMiddleNameWithSpace = new Optional("optional-middle-name-with-space", middleNameWithSpace);
|
|
118
|
+
const fullName = new Sequence("full-name", [firstName, space, optionalMiddleNameWithSpace, lastName]);
|
|
119
|
+
const expected = new Context("full-name", fullName, [space, firstName, lastName, middleName, middleNameWithSpace]);
|
|
111
120
|
|
|
112
|
-
expect(pattern.isEqual(
|
|
121
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
113
122
|
});
|
|
114
123
|
|
|
115
124
|
test("And With Not Pattern", () => {
|
|
@@ -130,11 +139,12 @@ describe("Grammar", () => {
|
|
|
130
139
|
const lastName = new Regex("last-name", "\\w");
|
|
131
140
|
const middleName = new Regex("middle-name", "\\w");
|
|
132
141
|
const jack = new Literal("jack", "Jack");
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
const fullName = new Sequence("full-name", [
|
|
142
|
+
const middleNameWithSpace = new Sequence("middle-name-with-space", [middleName, space]);
|
|
143
|
+
const optionalMiddleNameWithSpace = new Optional("optional-middle-name-with-space", middleNameWithSpace);
|
|
144
|
+
const fullName = new Sequence("full-name", [new Not("not-jack", jack), firstName, space, optionalMiddleNameWithSpace, lastName]);
|
|
145
|
+
const expected = new Context("full-name", fullName, [space, firstName, lastName, middleName, jack, middleNameWithSpace]);
|
|
136
146
|
|
|
137
|
-
expect(pattern.isEqual(
|
|
147
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
138
148
|
});
|
|
139
149
|
|
|
140
150
|
test("Repeat", () => {
|
|
@@ -147,8 +157,9 @@ describe("Grammar", () => {
|
|
|
147
157
|
const pattern = patterns["digits"];
|
|
148
158
|
const digit = new Regex("digit", "\\d");
|
|
149
159
|
const digits = new Repeat("digits", digit);
|
|
160
|
+
const expected = new Context("digits", digits, [digit]);
|
|
150
161
|
|
|
151
|
-
expect(pattern.isEqual(
|
|
162
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
152
163
|
});
|
|
153
164
|
|
|
154
165
|
test("Repeat Zero Or More", () => {
|
|
@@ -162,7 +173,9 @@ describe("Grammar", () => {
|
|
|
162
173
|
const digit = new Regex("digit", "\\d");
|
|
163
174
|
const digits = new Optional("digits", new Repeat("digits", digit, { min: 0 }));
|
|
164
175
|
|
|
165
|
-
|
|
176
|
+
const expected = new Context("digits", digits, [digit]);
|
|
177
|
+
|
|
178
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
166
179
|
});
|
|
167
180
|
|
|
168
181
|
test("Repeat Lower Limit", () => {
|
|
@@ -175,8 +188,9 @@ describe("Grammar", () => {
|
|
|
175
188
|
const pattern = patterns["digits"];
|
|
176
189
|
const digit = new Regex("digit", "\\d+");
|
|
177
190
|
const digits = new Repeat("digits", digit, { min: 1 });
|
|
191
|
+
const expected = new Context("digits", digits, [digit]);
|
|
178
192
|
|
|
179
|
-
expect(pattern.isEqual(
|
|
193
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
180
194
|
});
|
|
181
195
|
|
|
182
196
|
test("Repeat Bounded", () => {
|
|
@@ -189,8 +203,9 @@ describe("Grammar", () => {
|
|
|
189
203
|
const pattern = patterns["digits"];
|
|
190
204
|
const digit = new Regex("digit", "\\d+");
|
|
191
205
|
const digits = new Repeat("digits", digit, { min: 1, max: 3 });
|
|
206
|
+
const expected = new Context("digits", digits, [digit]);
|
|
192
207
|
|
|
193
|
-
expect(pattern.isEqual(
|
|
208
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
194
209
|
});
|
|
195
210
|
|
|
196
211
|
test("Repeat Upper Limit", () => {
|
|
@@ -203,8 +218,9 @@ describe("Grammar", () => {
|
|
|
203
218
|
const pattern = patterns["digits"];
|
|
204
219
|
const digit = new Regex("digit", "\\d+");
|
|
205
220
|
const digits = new Repeat("digits", digit, { min: 0, max: 3 });
|
|
221
|
+
const expected = new Context("digits", digits, [digit]);
|
|
206
222
|
|
|
207
|
-
expect(pattern.isEqual(
|
|
223
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
208
224
|
});
|
|
209
225
|
|
|
210
226
|
test("Repeat Exact", () => {
|
|
@@ -217,8 +233,9 @@ describe("Grammar", () => {
|
|
|
217
233
|
const pattern = patterns["digits"];
|
|
218
234
|
const digit = new Regex("digit", "\\d+");
|
|
219
235
|
const digits = new Repeat("digits", digit, { min: 3, max: 3 });
|
|
236
|
+
const expected = new Context("digits", digits, [digit]);
|
|
220
237
|
|
|
221
|
-
expect(pattern.isEqual(
|
|
238
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
222
239
|
});
|
|
223
240
|
|
|
224
241
|
test("Repeat Divider", () => {
|
|
@@ -231,10 +248,11 @@ describe("Grammar", () => {
|
|
|
231
248
|
const patterns = Grammar.parseString(expression);
|
|
232
249
|
const pattern = patterns["digits"];
|
|
233
250
|
const digit = new Regex("digit", "\\d+");
|
|
234
|
-
const
|
|
235
|
-
const digits = new Repeat("digits", digit, { divider, min: 3, max: 3 });
|
|
251
|
+
const comma = new Literal("comma", ",");
|
|
252
|
+
const digits = new Repeat("digits", digit, { divider: comma, min: 3, max: 3 });
|
|
253
|
+
const expected = new Context("digits", digits, [digit, comma]);
|
|
236
254
|
|
|
237
|
-
expect(pattern.isEqual(
|
|
255
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
238
256
|
});
|
|
239
257
|
|
|
240
258
|
test("Repeat Divider With Trim Divider", () => {
|
|
@@ -247,10 +265,11 @@ describe("Grammar", () => {
|
|
|
247
265
|
const patterns = Grammar.parseString(expression);
|
|
248
266
|
const pattern = patterns["digits"];
|
|
249
267
|
const digit = new Regex("digit", "\\d+");
|
|
250
|
-
const
|
|
251
|
-
const digits = new Repeat("digits", digit, { divider, min: 1, trimDivider: true });
|
|
268
|
+
const comma = new Literal("comma", ",");
|
|
269
|
+
const digits = new Repeat("digits", digit, { divider: comma, min: 1, trimDivider: true });
|
|
270
|
+
const expected = new Context("digits", digits, [digit, comma]);
|
|
252
271
|
|
|
253
|
-
expect(pattern.isEqual(
|
|
272
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
254
273
|
});
|
|
255
274
|
|
|
256
275
|
test("Repeat Divider With Trim Divider And Bounds", () => {
|
|
@@ -265,8 +284,9 @@ describe("Grammar", () => {
|
|
|
265
284
|
const digit = new Regex("digit", "\\d+");
|
|
266
285
|
const divider = new Literal("comma", ",");
|
|
267
286
|
const digits = new Repeat("digits", digit, { divider, min: 3, max: 3, trimDivider: true });
|
|
287
|
+
const expected = new Context("digits", digits, [digit, divider]);
|
|
268
288
|
|
|
269
|
-
expect(pattern.isEqual(
|
|
289
|
+
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
270
290
|
});
|
|
271
291
|
|
|
272
292
|
test("Reference", () => {
|
|
@@ -302,10 +322,14 @@ describe("Grammar", () => {
|
|
|
302
322
|
const expectedName = new Regex("name", "regex");
|
|
303
323
|
|
|
304
324
|
const alias = patterns["alias"];
|
|
325
|
+
|
|
305
326
|
const expectedAlias = new Regex("alias", "regex");
|
|
306
327
|
|
|
307
|
-
|
|
308
|
-
|
|
328
|
+
const contextualAlias = new Context("alias", expectedAlias, [expectedName]);
|
|
329
|
+
const contextualName = new Context("name", expectedName, [expectedAlias]);
|
|
330
|
+
|
|
331
|
+
expect(name.isEqual(contextualName)).toBeTruthy();
|
|
332
|
+
expect(alias.isEqual(contextualAlias)).toBeTruthy();
|
|
309
333
|
});
|
|
310
334
|
|
|
311
335
|
test("Bad Grammar At Beginning", () => {
|
|
@@ -481,7 +505,7 @@ describe("Grammar", () => {
|
|
|
481
505
|
`;
|
|
482
506
|
|
|
483
507
|
const patterns = Grammar.parseString(expression);
|
|
484
|
-
const expected = new Sequence("complex-expression", [
|
|
508
|
+
const expected = new Context("complex-expression", new Sequence("complex-expression", [
|
|
485
509
|
new Not("not-NOT_THIS", new Literal("NOT_THIS", "NOT_THIS")),
|
|
486
510
|
new Optional("Text", new Literal("Text", "Text")),
|
|
487
511
|
new Regex("regex", "regex"),
|
|
@@ -496,7 +520,7 @@ describe("Grammar", () => {
|
|
|
496
520
|
new Reference("pattern"),
|
|
497
521
|
new Reference("pattern")
|
|
498
522
|
])
|
|
499
|
-
]);
|
|
523
|
+
]));
|
|
500
524
|
|
|
501
525
|
expect(patterns["complex-expression"].isEqual(expected)).toBeTruthy();
|
|
502
526
|
});
|
package/src/grammar/Grammar.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { Sequence } from "../patterns/Sequence";
|
|
|
10
10
|
import { Repeat, RepeatOptions } from "../patterns/Repeat";
|
|
11
11
|
import { AutoComplete } from "../intellisense/AutoComplete";
|
|
12
12
|
import { Optional } from "../patterns/Optional";
|
|
13
|
+
import { Context } from "../patterns/Context";
|
|
13
14
|
|
|
14
15
|
let anonymousIndexId = 0;
|
|
15
16
|
|
|
@@ -88,7 +89,18 @@ export class Grammar {
|
|
|
88
89
|
await this._resolveImports(ast);
|
|
89
90
|
this._buildPatterns(ast);
|
|
90
91
|
|
|
91
|
-
return
|
|
92
|
+
return this._buildPatternRecord();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private _buildPatternRecord() {
|
|
96
|
+
const patterns: Record<string, Pattern> = {};
|
|
97
|
+
const allPatterns = Array.from(this._parseContext.patternsByName.values());
|
|
98
|
+
|
|
99
|
+
allPatterns.forEach(p => {
|
|
100
|
+
patterns[p.name] = new Context(p.name, p, allPatterns.filter(o => o !== p));
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return patterns;
|
|
92
104
|
}
|
|
93
105
|
|
|
94
106
|
parseString(expression: string) {
|
|
@@ -98,8 +110,10 @@ export class Grammar {
|
|
|
98
110
|
if (this._hasImports(ast)) {
|
|
99
111
|
throw new Error("Cannot use imports on parseString, use parse instead.");
|
|
100
112
|
}
|
|
113
|
+
|
|
101
114
|
this._buildPatterns(ast);
|
|
102
|
-
|
|
115
|
+
|
|
116
|
+
return this._buildPatternRecord();
|
|
103
117
|
}
|
|
104
118
|
|
|
105
119
|
private _tryToParse(expression: string): Node {
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { CursorHistory, Match } from "./patterns/CursorHistory";
|
|
|
18
18
|
import { ParseResult } from "./patterns/ParseResult";
|
|
19
19
|
import { grammar } from "./grammar/patterns/grammar";
|
|
20
20
|
import { patterns } from "./grammar/patterns";
|
|
21
|
+
import { Context } from "./patterns/Context";
|
|
21
22
|
|
|
22
23
|
export {
|
|
23
24
|
Node,
|
|
@@ -30,6 +31,7 @@ export {
|
|
|
30
31
|
Cursor,
|
|
31
32
|
CursorHistory,
|
|
32
33
|
Match,
|
|
34
|
+
Context,
|
|
33
35
|
Literal,
|
|
34
36
|
Not,
|
|
35
37
|
Options,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { patterns } from "../grammar/patterns";
|
|
2
|
+
import { Context } from "./Context";
|
|
3
|
+
import { Literal } from "./Literal";
|
|
4
|
+
import { Reference } from "./Reference";
|
|
5
|
+
import { Sequence } from "./Sequence";
|
|
6
|
+
|
|
7
|
+
describe("Context", () => {
|
|
8
|
+
test("Basic", () => {
|
|
9
|
+
const john = new Literal("john", "John");
|
|
10
|
+
const space = new Literal("space", " ");
|
|
11
|
+
const jane = new Literal("jane", "Jane");
|
|
12
|
+
const spaceReference = new Reference("space");
|
|
13
|
+
|
|
14
|
+
const names = new Sequence("names", [john, spaceReference, jane]);
|
|
15
|
+
const context = new Context("context", names, [space, names]);
|
|
16
|
+
|
|
17
|
+
const { ast } = context.exec("John Jane");
|
|
18
|
+
|
|
19
|
+
expect(ast?.toString()).toBe("John Jane");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("With Grammar", ()=>{
|
|
23
|
+
const {names} = patterns`
|
|
24
|
+
names = john + space + jane
|
|
25
|
+
john = "John"
|
|
26
|
+
jane = "Jane"
|
|
27
|
+
space = " "
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
const { ast } = names.exec("John Jane");
|
|
31
|
+
|
|
32
|
+
expect(ast?.toString()).toBe("John Jane");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Node } from "../ast/Node";
|
|
2
|
+
import { Cursor } from "./Cursor";
|
|
3
|
+
import { ParseResult } from "./ParseResult";
|
|
4
|
+
import { Pattern } from "./Pattern";
|
|
5
|
+
|
|
6
|
+
let contextId = 0;
|
|
7
|
+
|
|
8
|
+
export class Context implements Pattern {
|
|
9
|
+
private _id: string;
|
|
10
|
+
private _type: string;
|
|
11
|
+
private _name: string;
|
|
12
|
+
private _parent: Pattern | null;
|
|
13
|
+
private _children: Pattern[];
|
|
14
|
+
private _pattern: Pattern;
|
|
15
|
+
|
|
16
|
+
get id(): string {
|
|
17
|
+
return this._id;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get type(): string {
|
|
21
|
+
return this._type;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get name(): string {
|
|
25
|
+
return this._name;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get parent(): Pattern | null {
|
|
29
|
+
return this._parent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set parent(pattern: Pattern | null) {
|
|
33
|
+
this._parent = pattern;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get children(): Pattern[] {
|
|
37
|
+
return this._children;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
constructor(name: string, pattern: Pattern, context: Pattern[] = []) {
|
|
41
|
+
this._id = `context-${contextId++}`;
|
|
42
|
+
this._type = "context";
|
|
43
|
+
this._name = name;
|
|
44
|
+
this._parent = null;
|
|
45
|
+
|
|
46
|
+
const clonedContext = context.map(p => p.clone());
|
|
47
|
+
const clonedPattern = pattern.clone();
|
|
48
|
+
|
|
49
|
+
clonedContext.forEach(p => p.parent = this);
|
|
50
|
+
clonedPattern.parent = this;
|
|
51
|
+
|
|
52
|
+
this._pattern = clonedPattern;
|
|
53
|
+
this._children = [...clonedContext, clonedPattern];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
parse(cursor: Cursor): Node | null {
|
|
57
|
+
return this._pattern.parse(cursor);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
exec(text: string, record?: boolean | undefined): ParseResult {
|
|
61
|
+
return this._pattern.exec(text, record);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
test(text: string, record?: boolean | undefined): boolean {
|
|
65
|
+
return this._pattern.test(text, record);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
clone(name = this._name): Pattern {
|
|
69
|
+
const clone = new Context(name, this._pattern, this._children.slice(0, -1));
|
|
70
|
+
return clone;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getTokens(): string[] {
|
|
74
|
+
return this._pattern.getTokens();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
getTokensAfter(childReference: Pattern): string[] {
|
|
78
|
+
return this._pattern.getTokensAfter(childReference);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
getNextTokens(): string[] {
|
|
82
|
+
return this._pattern.getNextTokens();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
getPatterns(): Pattern[] {
|
|
86
|
+
return this._pattern.getPatterns();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
getPatternsAfter(childReference: Pattern): Pattern[] {
|
|
90
|
+
return this._pattern.getPatternsAfter(childReference);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getNextPatterns(): Pattern[] {
|
|
94
|
+
return this._pattern.getNextPatterns();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
find(predicate: (pattern: Pattern) => boolean): Pattern | null {
|
|
98
|
+
return this._pattern.find(predicate);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
isEqual(pattern: Pattern): boolean {
|
|
102
|
+
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
}
|
|
@@ -97,10 +97,28 @@ export class Reference implements Pattern {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
private _findPattern(): Pattern | null {
|
|
100
|
-
|
|
100
|
+
let pattern = this._parent;
|
|
101
|
+
|
|
102
|
+
while (pattern != null) {
|
|
103
|
+
if (pattern.type !== "context") {
|
|
104
|
+
pattern = pattern.parent;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
101
107
|
|
|
108
|
+
const foundPattern = findPattern(pattern, (pattern: Pattern) => {
|
|
109
|
+
return pattern.name === this._name && pattern.type !== "reference" && pattern.type !== "context";
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (foundPattern != null) {
|
|
113
|
+
return foundPattern;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
pattern = pattern.parent;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const root = this._getRoot();
|
|
102
120
|
return findPattern(root, (pattern: Pattern) => {
|
|
103
|
-
return pattern.name === this._name && pattern.type !== "reference";
|
|
121
|
+
return pattern.name === this._name && pattern.type !== "reference" && pattern.type !== "context";
|
|
104
122
|
});
|
|
105
123
|
}
|
|
106
124
|
|