clarity-pattern-parser 10.3.1 → 10.3.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/dist/index.browser.js +86 -43
- package/dist/index.browser.js.map +1 -1
- package/dist/index.esm.js +86 -43
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +86 -43
- package/dist/index.js.map +1 -1
- package/dist/patterns/Context.d.ts +1 -0
- package/dist/patterns/ExpressionPattern.d.ts +2 -0
- package/dist/patterns/FiniteRepeat.d.ts +2 -0
- package/dist/patterns/InfiniteRepeat.d.ts +1 -0
- package/dist/patterns/Literal.d.ts +1 -0
- package/dist/patterns/Not.d.ts +1 -0
- package/dist/patterns/Optional.d.ts +1 -0
- package/dist/patterns/Options.d.ts +2 -0
- package/dist/patterns/Pattern.d.ts +1 -0
- package/dist/patterns/Reference.d.ts +2 -0
- package/dist/patterns/Regex.d.ts +1 -0
- package/dist/patterns/Repeat.d.ts +1 -0
- package/dist/patterns/Sequence.d.ts +2 -0
- package/package.json +1 -1
- package/src/patterns/Context.ts +4 -0
- package/src/patterns/ExpressionPattern.ts +23 -9
- package/src/patterns/FiniteRepeat.ts +8 -0
- package/src/patterns/InfiniteRepeat.ts +4 -0
- package/src/patterns/Literal.ts +4 -0
- package/src/patterns/Not.ts +4 -0
- package/src/patterns/Optional.ts +4 -0
- package/src/patterns/Options.ts +23 -13
- package/src/patterns/Pattern.ts +1 -0
- package/src/patterns/Reference.ts +7 -0
- package/src/patterns/Regex.ts +6 -2
- package/src/patterns/Repeat.ts +4 -0
- package/src/patterns/RightAssociatedPattern.ts +4 -0
- package/src/patterns/Sequence.ts +23 -8
- package/src/patterns/DepthCache.ts +0 -26
|
@@ -17,6 +17,7 @@ export declare class Context implements Pattern {
|
|
|
17
17
|
get parent(): Pattern | null;
|
|
18
18
|
set parent(pattern: Pattern | null);
|
|
19
19
|
get children(): Pattern[];
|
|
20
|
+
get startedOnIndex(): number;
|
|
20
21
|
getPatternWithinContext(name: string): Pattern | null;
|
|
21
22
|
getPatternsWithinContext(): {
|
|
22
23
|
[x: string]: Pattern;
|
|
@@ -29,6 +29,7 @@ export declare class ExpressionPattern implements Pattern {
|
|
|
29
29
|
get unaryPatterns(): readonly Pattern[];
|
|
30
30
|
get binaryPatterns(): readonly Pattern[];
|
|
31
31
|
get recursivePatterns(): readonly Pattern[];
|
|
32
|
+
get startedOnIndex(): number;
|
|
32
33
|
constructor(name: string, patterns: Pattern[]);
|
|
33
34
|
private _organizePatterns;
|
|
34
35
|
private _isBinary;
|
|
@@ -42,6 +43,7 @@ export declare class ExpressionPattern implements Pattern {
|
|
|
42
43
|
parse(cursor: Cursor): Node | null;
|
|
43
44
|
private _compactResult;
|
|
44
45
|
private _tryToParse;
|
|
46
|
+
private _isBeyondRecursiveAllowance;
|
|
45
47
|
test(text: string): boolean;
|
|
46
48
|
exec(text: string, record?: boolean): ParseResult;
|
|
47
49
|
getTokens(): string[];
|
|
@@ -18,6 +18,7 @@ export declare class FiniteRepeat implements Pattern {
|
|
|
18
18
|
private _min;
|
|
19
19
|
private _max;
|
|
20
20
|
private _trimDivider;
|
|
21
|
+
private _firstIndex;
|
|
21
22
|
shouldCompactAst: boolean;
|
|
22
23
|
get id(): string;
|
|
23
24
|
get type(): string;
|
|
@@ -27,6 +28,7 @@ export declare class FiniteRepeat implements Pattern {
|
|
|
27
28
|
get children(): Pattern[];
|
|
28
29
|
get min(): number;
|
|
29
30
|
get max(): number;
|
|
31
|
+
get startedOnIndex(): number;
|
|
30
32
|
constructor(name: string, pattern: Pattern, options?: FiniteRepeatOptions);
|
|
31
33
|
parse(cursor: Cursor): Node | null;
|
|
32
34
|
test(text: string): boolean;
|
|
@@ -27,6 +27,7 @@ export declare class InfiniteRepeat implements Pattern {
|
|
|
27
27
|
set parent(pattern: Pattern | null);
|
|
28
28
|
get children(): Pattern[];
|
|
29
29
|
get min(): number;
|
|
30
|
+
get startedOnIndex(): number;
|
|
30
31
|
constructor(name: string, pattern: Pattern, options?: InfiniteRepeatOptions);
|
|
31
32
|
private _assignChildrenToParent;
|
|
32
33
|
test(text: string): boolean;
|
|
@@ -20,6 +20,7 @@ export declare class Literal implements Pattern {
|
|
|
20
20
|
get parent(): Pattern | null;
|
|
21
21
|
set parent(pattern: Pattern | null);
|
|
22
22
|
get children(): Pattern[];
|
|
23
|
+
get startedOnIndex(): number;
|
|
23
24
|
constructor(name: string, value: string);
|
|
24
25
|
test(text: string, record?: boolean): boolean;
|
|
25
26
|
exec(text: string, record?: boolean): ParseResult;
|
package/dist/patterns/Not.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class Not implements Pattern {
|
|
|
15
15
|
get parent(): Pattern | null;
|
|
16
16
|
set parent(pattern: Pattern | null);
|
|
17
17
|
get children(): Pattern[];
|
|
18
|
+
get startedOnIndex(): number;
|
|
18
19
|
constructor(name: string, pattern: Pattern);
|
|
19
20
|
test(text: string): boolean;
|
|
20
21
|
exec(text: string, record?: boolean): ParseResult;
|
|
@@ -15,6 +15,7 @@ export declare class Optional implements Pattern {
|
|
|
15
15
|
get parent(): Pattern | null;
|
|
16
16
|
set parent(pattern: Pattern | null);
|
|
17
17
|
get children(): Pattern[];
|
|
18
|
+
get startedOnIndex(): number;
|
|
18
19
|
constructor(name: string, pattern: Pattern);
|
|
19
20
|
test(text: string): boolean;
|
|
20
21
|
exec(text: string, record?: boolean): ParseResult;
|
|
@@ -17,12 +17,14 @@ export declare class Options implements Pattern {
|
|
|
17
17
|
get parent(): Pattern | null;
|
|
18
18
|
set parent(pattern: Pattern | null);
|
|
19
19
|
get children(): Pattern[];
|
|
20
|
+
get startedOnIndex(): number;
|
|
20
21
|
constructor(name: string, options: Pattern[], isGreedy?: boolean);
|
|
21
22
|
private _assignChildrenToParent;
|
|
22
23
|
test(text: string): boolean;
|
|
23
24
|
exec(text: string, record?: boolean): ParseResult;
|
|
24
25
|
parse(cursor: Cursor): Node | null;
|
|
25
26
|
private _tryToParse;
|
|
27
|
+
private _isBeyondRecursiveAllowance;
|
|
26
28
|
getTokens(): string[];
|
|
27
29
|
getTokensAfter(_childReference: Pattern): string[];
|
|
28
30
|
getNextTokens(): string[];
|
|
@@ -10,6 +10,7 @@ export declare class Reference implements Pattern {
|
|
|
10
10
|
private _cachedPattern;
|
|
11
11
|
private _pattern;
|
|
12
12
|
private _children;
|
|
13
|
+
private _firstIndex;
|
|
13
14
|
shouldCompactAst: boolean;
|
|
14
15
|
get id(): string;
|
|
15
16
|
get type(): string;
|
|
@@ -17,6 +18,7 @@ export declare class Reference implements Pattern {
|
|
|
17
18
|
get parent(): Pattern | null;
|
|
18
19
|
set parent(pattern: Pattern | null);
|
|
19
20
|
get children(): Pattern[];
|
|
21
|
+
get startedOnIndex(): number;
|
|
20
22
|
constructor(name: string);
|
|
21
23
|
test(text: string): boolean;
|
|
22
24
|
exec(text: string, record?: boolean): ParseResult;
|
package/dist/patterns/Regex.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export declare class Regex implements Pattern {
|
|
|
22
22
|
get parent(): Pattern | null;
|
|
23
23
|
set parent(pattern: Pattern | null);
|
|
24
24
|
get children(): Pattern[];
|
|
25
|
+
get startedOnIndex(): number;
|
|
25
26
|
constructor(name: string, regex: string);
|
|
26
27
|
private assertArguments;
|
|
27
28
|
test(text: string): boolean;
|
|
@@ -26,6 +26,7 @@ export declare class Repeat implements Pattern {
|
|
|
26
26
|
get children(): Pattern[];
|
|
27
27
|
get min(): number;
|
|
28
28
|
get max(): number;
|
|
29
|
+
get startedOnIndex(): number;
|
|
29
30
|
constructor(name: string, pattern: Pattern, options?: RepeatOptions);
|
|
30
31
|
parse(cursor: Cursor): Node | null;
|
|
31
32
|
exec(text: string): ParseResult;
|
|
@@ -16,6 +16,7 @@ export declare class Sequence implements Pattern {
|
|
|
16
16
|
get parent(): Pattern | null;
|
|
17
17
|
set parent(pattern: Pattern | null);
|
|
18
18
|
get children(): Pattern[];
|
|
19
|
+
get startedOnIndex(): number;
|
|
19
20
|
constructor(name: string, sequence: Pattern[]);
|
|
20
21
|
private _assignChildrenToParent;
|
|
21
22
|
test(text: string): boolean;
|
|
@@ -26,6 +27,7 @@ export declare class Sequence implements Pattern {
|
|
|
26
27
|
parse(cursor: Cursor): Node | null;
|
|
27
28
|
private tryToParse;
|
|
28
29
|
private getLastValidNode;
|
|
30
|
+
private _isBeyondRecursiveAllowance;
|
|
29
31
|
private areRemainingPatternsOptional;
|
|
30
32
|
private createNode;
|
|
31
33
|
getTokens(): string[];
|
package/package.json
CHANGED
package/src/patterns/Context.ts
CHANGED
|
@@ -40,6 +40,10 @@ export class Context implements Pattern {
|
|
|
40
40
|
return this._children;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
get startedOnIndex(){
|
|
44
|
+
return this.children[0].startedOnIndex;
|
|
45
|
+
}
|
|
46
|
+
|
|
43
47
|
getPatternWithinContext(name: string): Pattern | null {
|
|
44
48
|
return this._patterns[name] || null;
|
|
45
49
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { Node } from "../ast/Node";
|
|
2
2
|
import { Cursor } from "./Cursor";
|
|
3
|
-
import { DepthCache } from "./DepthCache";
|
|
4
3
|
import { ParseResult } from "./ParseResult";
|
|
5
4
|
import { Pattern } from "./Pattern";
|
|
6
5
|
import { findPattern } from "./findPattern";
|
|
7
6
|
import { Sequence } from "./Sequence";
|
|
8
7
|
|
|
9
8
|
let indexId = 0;
|
|
10
|
-
const depthCache = new DepthCache();
|
|
11
9
|
|
|
12
10
|
function createNode(name: string, children: Node[]) {
|
|
13
11
|
return new Node("expression", name, 0, 0, children, "");
|
|
@@ -74,6 +72,10 @@ export class ExpressionPattern implements Pattern {
|
|
|
74
72
|
return this._recursivePatterns;
|
|
75
73
|
}
|
|
76
74
|
|
|
75
|
+
get startedOnIndex() {
|
|
76
|
+
return this._firstIndex;
|
|
77
|
+
}
|
|
78
|
+
|
|
77
79
|
constructor(name: string, patterns: Pattern[]) {
|
|
78
80
|
if (patterns.length === 0) {
|
|
79
81
|
throw new Error("Need at least one pattern with an 'expression' pattern.");
|
|
@@ -211,14 +213,9 @@ export class ExpressionPattern implements Pattern {
|
|
|
211
213
|
}
|
|
212
214
|
|
|
213
215
|
parse(cursor: Cursor): Node | null {
|
|
214
|
-
this._firstIndex = cursor.index;
|
|
215
|
-
depthCache.incrementDepth(this._id, this._firstIndex);
|
|
216
|
-
|
|
217
216
|
this._firstIndex = cursor.index;
|
|
218
217
|
const node = this._tryToParse(cursor);
|
|
219
218
|
|
|
220
|
-
depthCache.decrementDepth(this._id, this._firstIndex);
|
|
221
|
-
|
|
222
219
|
if (node != null) {
|
|
223
220
|
cursor.moveTo(node.lastIndex);
|
|
224
221
|
cursor.resolveError();
|
|
@@ -253,12 +250,11 @@ export class ExpressionPattern implements Pattern {
|
|
|
253
250
|
}
|
|
254
251
|
|
|
255
252
|
private _tryToParse(cursor: Cursor): Node | null {
|
|
256
|
-
if (
|
|
253
|
+
if (this._isBeyondRecursiveAllowance()) {
|
|
257
254
|
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
258
255
|
return null;
|
|
259
256
|
}
|
|
260
257
|
|
|
261
|
-
|
|
262
258
|
let lastUnaryNode: Node | null = null;
|
|
263
259
|
let lastBinaryNode: Node | null = null;
|
|
264
260
|
let onIndex = cursor.index;
|
|
@@ -447,6 +443,24 @@ export class ExpressionPattern implements Pattern {
|
|
|
447
443
|
}
|
|
448
444
|
}
|
|
449
445
|
|
|
446
|
+
private _isBeyondRecursiveAllowance() {
|
|
447
|
+
let depth = 0;
|
|
448
|
+
let pattern: Pattern | null = this;
|
|
449
|
+
|
|
450
|
+
while (pattern != null) {
|
|
451
|
+
if (pattern.id === this.id && pattern.startedOnIndex === this.startedOnIndex) {
|
|
452
|
+
depth++;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (depth > 2) {
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
pattern = pattern.parent;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
|
|
450
464
|
test(text: string) {
|
|
451
465
|
const cursor = new Cursor(text);
|
|
452
466
|
const ast = this.parse(cursor);
|
|
@@ -23,6 +23,7 @@ export class FiniteRepeat implements Pattern {
|
|
|
23
23
|
private _min: number;
|
|
24
24
|
private _max: number;
|
|
25
25
|
private _trimDivider: boolean;
|
|
26
|
+
private _firstIndex: number;
|
|
26
27
|
|
|
27
28
|
shouldCompactAst = false;
|
|
28
29
|
|
|
@@ -58,6 +59,10 @@ export class FiniteRepeat implements Pattern {
|
|
|
58
59
|
return this._max;
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
get startedOnIndex() {
|
|
63
|
+
return this._firstIndex;
|
|
64
|
+
}
|
|
65
|
+
|
|
61
66
|
constructor(name: string, pattern: Pattern, options: FiniteRepeatOptions = {}) {
|
|
62
67
|
this._id = `finite-repeat-${idIndex++}`;
|
|
63
68
|
this._type = "finite-repeat";
|
|
@@ -68,6 +73,7 @@ export class FiniteRepeat implements Pattern {
|
|
|
68
73
|
this._min = options.min != null ? Math.max(options.min, 1) : 1;
|
|
69
74
|
this._max = Math.max(this.min, options.max || this.min);
|
|
70
75
|
this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
|
|
76
|
+
this._firstIndex = 0;
|
|
71
77
|
|
|
72
78
|
for (let i = 0; i < this._max; i++) {
|
|
73
79
|
const child = pattern.clone();
|
|
@@ -85,6 +91,8 @@ export class FiniteRepeat implements Pattern {
|
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
parse(cursor: Cursor): Node | null {
|
|
94
|
+
this._firstIndex = cursor.index;
|
|
95
|
+
|
|
88
96
|
const startIndex = cursor.index;
|
|
89
97
|
const nodes: Node[] = [];
|
|
90
98
|
const modulo = this._hasDivider ? 2 : 1;
|
|
@@ -56,6 +56,10 @@ export class InfiniteRepeat implements Pattern {
|
|
|
56
56
|
return this._min;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
get startedOnIndex(){
|
|
60
|
+
return this._firstIndex;
|
|
61
|
+
}
|
|
62
|
+
|
|
59
63
|
constructor(name: string, pattern: Pattern, options: InfiniteRepeatOptions = {}) {
|
|
60
64
|
const min = options.min != null ? Math.max(options.min, 1) : 1;
|
|
61
65
|
const divider = options.divider;
|
package/src/patterns/Literal.ts
CHANGED
package/src/patterns/Not.ts
CHANGED
package/src/patterns/Optional.ts
CHANGED
|
@@ -38,6 +38,10 @@ export class Optional implements Pattern {
|
|
|
38
38
|
return this._children;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
get startedOnIndex() {
|
|
42
|
+
return this._children[0].startedOnIndex;
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
constructor(name: string, pattern: Pattern) {
|
|
42
46
|
this._id = `optional-${idIndex++}`;
|
|
43
47
|
this._type = "optional";
|
package/src/patterns/Options.ts
CHANGED
|
@@ -4,14 +4,8 @@ import { Pattern } from "./Pattern";
|
|
|
4
4
|
import { clonePatterns } from "./clonePatterns";
|
|
5
5
|
import { findPattern } from "./findPattern";
|
|
6
6
|
import { ParseResult } from "./ParseResult";
|
|
7
|
-
import { DepthCache } from './DepthCache';
|
|
8
7
|
import { isRecursivePattern } from "./isRecursivePattern";
|
|
9
8
|
|
|
10
|
-
/*
|
|
11
|
-
The following is created to reduce the overhead of recursion check.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const depthCache = new DepthCache();
|
|
15
9
|
let idIndex = 0;
|
|
16
10
|
|
|
17
11
|
export class Options implements Pattern {
|
|
@@ -49,6 +43,10 @@ export class Options implements Pattern {
|
|
|
49
43
|
return this._children;
|
|
50
44
|
}
|
|
51
45
|
|
|
46
|
+
get startedOnIndex() {
|
|
47
|
+
return this._firstIndex;
|
|
48
|
+
}
|
|
49
|
+
|
|
52
50
|
constructor(name: string, options: Pattern[], isGreedy = false) {
|
|
53
51
|
if (options.length === 0) {
|
|
54
52
|
throw new Error("Need at least one pattern with an 'options' pattern.");
|
|
@@ -92,15 +90,9 @@ export class Options implements Pattern {
|
|
|
92
90
|
}
|
|
93
91
|
|
|
94
92
|
parse(cursor: Cursor): Node | null {
|
|
95
|
-
// This is a cache to help with speed
|
|
96
|
-
this._firstIndex = cursor.index;
|
|
97
|
-
depthCache.incrementDepth(this._id, this._firstIndex);
|
|
98
|
-
|
|
99
93
|
this._firstIndex = cursor.index;
|
|
100
94
|
const node = this._tryToParse(cursor);
|
|
101
95
|
|
|
102
|
-
depthCache.decrementDepth(this._id, this._firstIndex);
|
|
103
|
-
|
|
104
96
|
if (node != null) {
|
|
105
97
|
cursor.moveTo(node.lastIndex);
|
|
106
98
|
cursor.resolveError();
|
|
@@ -117,7 +109,7 @@ export class Options implements Pattern {
|
|
|
117
109
|
}
|
|
118
110
|
|
|
119
111
|
private _tryToParse(cursor: Cursor): Node | null {
|
|
120
|
-
if (
|
|
112
|
+
if (this._isBeyondRecursiveAllowance()) {
|
|
121
113
|
return null;
|
|
122
114
|
}
|
|
123
115
|
|
|
@@ -146,6 +138,24 @@ export class Options implements Pattern {
|
|
|
146
138
|
return nonNullResults[0] || null;
|
|
147
139
|
}
|
|
148
140
|
|
|
141
|
+
private _isBeyondRecursiveAllowance() {
|
|
142
|
+
let depth = 0;
|
|
143
|
+
let pattern: Pattern | null = this;
|
|
144
|
+
|
|
145
|
+
while (pattern != null) {
|
|
146
|
+
if (pattern.id === this.id && pattern.startedOnIndex === this.startedOnIndex) {
|
|
147
|
+
depth++;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (depth > 2) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
pattern = pattern.parent;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
|
|
149
159
|
getTokens(): string[] {
|
|
150
160
|
const tokens: string[] = [];
|
|
151
161
|
|
package/src/patterns/Pattern.ts
CHANGED
|
@@ -15,6 +15,7 @@ export class Reference implements Pattern {
|
|
|
15
15
|
private _cachedPattern: Pattern | null;
|
|
16
16
|
private _pattern: Pattern | null;
|
|
17
17
|
private _children: Pattern[];
|
|
18
|
+
private _firstIndex: number;
|
|
18
19
|
|
|
19
20
|
shouldCompactAst = false;
|
|
20
21
|
|
|
@@ -42,6 +43,10 @@ export class Reference implements Pattern {
|
|
|
42
43
|
return this._children;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
get startedOnIndex() {
|
|
47
|
+
return this._firstIndex;
|
|
48
|
+
}
|
|
49
|
+
|
|
45
50
|
constructor(name: string) {
|
|
46
51
|
this._id = `reference-${idIndex++}`;
|
|
47
52
|
this._type = "reference";
|
|
@@ -50,6 +55,7 @@ export class Reference implements Pattern {
|
|
|
50
55
|
this._pattern = null;
|
|
51
56
|
this._cachedPattern = null;
|
|
52
57
|
this._children = [];
|
|
58
|
+
this._firstIndex = 0;
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
test(text: string) {
|
|
@@ -72,6 +78,7 @@ export class Reference implements Pattern {
|
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
parse(cursor: Cursor): Node | null {
|
|
81
|
+
this._firstIndex = cursor.index;
|
|
75
82
|
return this.getReferencePatternSafely().parse(cursor);
|
|
76
83
|
}
|
|
77
84
|
|
package/src/patterns/Regex.ts
CHANGED
|
@@ -14,7 +14,7 @@ export class Regex implements Pattern {
|
|
|
14
14
|
private _regex: RegExp;
|
|
15
15
|
private _node: Node | null = null;
|
|
16
16
|
private _cursor: Cursor | null = null;
|
|
17
|
-
private _firstIndex =
|
|
17
|
+
private _firstIndex = 0;
|
|
18
18
|
private _substring = "";
|
|
19
19
|
private _tokens: string[] = [];
|
|
20
20
|
|
|
@@ -48,6 +48,10 @@ export class Regex implements Pattern {
|
|
|
48
48
|
return [];
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
get startedOnIndex() {
|
|
52
|
+
return this._firstIndex;
|
|
53
|
+
}
|
|
54
|
+
|
|
51
55
|
constructor(name: string, regex: string) {
|
|
52
56
|
this._id = `regex-${idIndex++}`;
|
|
53
57
|
this._type = "regex";
|
|
@@ -149,7 +153,7 @@ export class Regex implements Pattern {
|
|
|
149
153
|
clone._tokens = this._tokens.slice();
|
|
150
154
|
clone._id = this._id;
|
|
151
155
|
clone.shouldCompactAst = this.shouldCompactAst;
|
|
152
|
-
|
|
156
|
+
|
|
153
157
|
return clone;
|
|
154
158
|
}
|
|
155
159
|
|
package/src/patterns/Repeat.ts
CHANGED
|
@@ -70,6 +70,10 @@ export class Repeat implements Pattern {
|
|
|
70
70
|
return this._options.max;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
get startedOnIndex(){
|
|
74
|
+
return this._repeatPattern.startedOnIndex;
|
|
75
|
+
}
|
|
76
|
+
|
|
73
77
|
constructor(name: string, pattern: Pattern, options: RepeatOptions = {}) {
|
|
74
78
|
this._id = `repeat-${idIndex++}`;
|
|
75
79
|
this._pattern = pattern;
|
|
@@ -38,6 +38,10 @@ export class RightAssociatedPattern implements Pattern {
|
|
|
38
38
|
return this._children;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
get startedOnIndex() {
|
|
42
|
+
return this._children[0].startedOnIndex;
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
constructor(pattern: Pattern) {
|
|
42
46
|
this._id = `right-associated-${indexId++}`;
|
|
43
47
|
this._type = "right-associated";
|
package/src/patterns/Sequence.ts
CHANGED
|
@@ -4,10 +4,8 @@ import { Node } from "../ast/Node";
|
|
|
4
4
|
import { clonePatterns } from "./clonePatterns";
|
|
5
5
|
import { filterOutNull } from "./filterOutNull";
|
|
6
6
|
import { findPattern } from "./findPattern";
|
|
7
|
-
import { DepthCache } from "./DepthCache";
|
|
8
7
|
import { isRecursivePattern } from "./isRecursivePattern";
|
|
9
8
|
|
|
10
|
-
const depthCache = new DepthCache();
|
|
11
9
|
let idIndex = 0;
|
|
12
10
|
|
|
13
11
|
export class Sequence implements Pattern {
|
|
@@ -45,6 +43,10 @@ export class Sequence implements Pattern {
|
|
|
45
43
|
return this._children;
|
|
46
44
|
}
|
|
47
45
|
|
|
46
|
+
get startedOnIndex() {
|
|
47
|
+
return this._firstIndex;
|
|
48
|
+
}
|
|
49
|
+
|
|
48
50
|
constructor(name: string, sequence: Pattern[]) {
|
|
49
51
|
if (sequence.length === 0) {
|
|
50
52
|
throw new Error("Need at least one pattern with a 'sequence' pattern.");
|
|
@@ -88,14 +90,9 @@ export class Sequence implements Pattern {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
parse(cursor: Cursor): Node | null {
|
|
91
|
-
// This is a cache to help with speed
|
|
92
93
|
this._firstIndex = cursor.index;
|
|
93
|
-
depthCache.incrementDepth(this._id, this._firstIndex);
|
|
94
|
-
|
|
95
94
|
this._nodes = [];
|
|
96
|
-
|
|
97
95
|
const passed = this.tryToParse(cursor);
|
|
98
|
-
depthCache.decrementDepth(this._id, this._firstIndex);
|
|
99
96
|
|
|
100
97
|
if (passed) {
|
|
101
98
|
const node = this.createNode(cursor);
|
|
@@ -115,7 +112,7 @@ export class Sequence implements Pattern {
|
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
private tryToParse(cursor: Cursor): boolean {
|
|
118
|
-
if (
|
|
115
|
+
if (this._isBeyondRecursiveAllowance()) {
|
|
119
116
|
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
120
117
|
return false;
|
|
121
118
|
}
|
|
@@ -190,6 +187,24 @@ export class Sequence implements Pattern {
|
|
|
190
187
|
return nodes[nodes.length - 1];
|
|
191
188
|
}
|
|
192
189
|
|
|
190
|
+
private _isBeyondRecursiveAllowance() {
|
|
191
|
+
let depth = 0;
|
|
192
|
+
let pattern: Pattern | null = this;
|
|
193
|
+
|
|
194
|
+
while (pattern != null) {
|
|
195
|
+
if (pattern.id === this.id && pattern.startedOnIndex === this.startedOnIndex) {
|
|
196
|
+
depth++;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (depth > 1) {
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
pattern = pattern.parent;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
193
208
|
private areRemainingPatternsOptional(fromIndex: number): boolean {
|
|
194
209
|
const startOnIndex = fromIndex + 1;
|
|
195
210
|
const length = this._children.length;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export class DepthCache {
|
|
2
|
-
private _depthMap: Record<string, Record<number, number>> = {};
|
|
3
|
-
|
|
4
|
-
getDepth(name: string, cursorIndex: number) {
|
|
5
|
-
if (this._depthMap[name] == null) {
|
|
6
|
-
this._depthMap[name] = {};
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
if (this._depthMap[name][cursorIndex] == null) {
|
|
10
|
-
this._depthMap[name][cursorIndex] = 0;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return this._depthMap[name][cursorIndex];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
incrementDepth(name: string, cursorIndex: number) {
|
|
18
|
-
const depth = this.getDepth(name, cursorIndex);
|
|
19
|
-
this._depthMap[name][cursorIndex] = depth + 1;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
decrementDepth(name: string, cursorIndex: number) {
|
|
23
|
-
const depth = this.getDepth(name, cursorIndex);
|
|
24
|
-
this._depthMap[name][cursorIndex] = depth - 1;
|
|
25
|
-
}
|
|
26
|
-
}
|