clarity-pattern-parser 11.0.6 → 11.0.7
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 +1 -5
- package/dist/ast/Node.d.ts +3 -4
- package/dist/grammar/Grammar.d.ts +1 -1
- package/dist/index.browser.js +54 -54
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.esm.js +53 -54
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +54 -54
- package/dist/index.js.map +1 -1
- package/dist/patterns/CursorHistory.d.ts +1 -1
- package/dist/patterns/Expression.d.ts +66 -0
- package/dist/patterns/Pattern.d.ts +1 -1
- package/dist/patterns/RightAssociated.d.ts +31 -0
- package/package.json +1 -1
- package/src/ast/Node.test.ts +2 -2
- package/src/ast/Node.ts +15 -20
- package/src/grammar/Grammar.ts +20 -20
- package/src/grammar/patterns/sequenceLiteral.ts +3 -3
- package/src/index.ts +4 -2
- package/src/patterns/CursorHistory.ts +3 -3
- package/src/patterns/{ExpressionPattern.test.ts → Expression.test.ts} +8 -8
- package/src/patterns/{ExpressionPattern.ts → Expression.ts} +19 -13
- package/src/patterns/FiniteRepeat.ts +10 -5
- package/src/patterns/InfiniteRepeat.ts +2 -5
- package/src/patterns/Pattern.ts +1 -1
- package/src/patterns/{RightAssociatedPattern.ts → RightAssociated.ts} +2 -2
|
@@ -31,7 +31,7 @@ export declare class CursorHistory {
|
|
|
31
31
|
get nodes(): Node[];
|
|
32
32
|
get patterns(): Pattern[];
|
|
33
33
|
recordMatch(pattern: Pattern, node: Node): void;
|
|
34
|
-
recordErrorAt(startIndex: number,
|
|
34
|
+
recordErrorAt(startIndex: number, lastIndex: number, pattern: Pattern): void;
|
|
35
35
|
startRecording(): void;
|
|
36
36
|
stopRecording(): void;
|
|
37
37
|
resolveError(): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
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 Expression implements Pattern {
|
|
6
|
+
private _id;
|
|
7
|
+
private _type;
|
|
8
|
+
private _name;
|
|
9
|
+
private _parent;
|
|
10
|
+
private _firstIndex;
|
|
11
|
+
private _originalPatterns;
|
|
12
|
+
private _patterns;
|
|
13
|
+
private _atomPatterns;
|
|
14
|
+
private _prefixPatterns;
|
|
15
|
+
private _prefixNames;
|
|
16
|
+
private _postfixPatterns;
|
|
17
|
+
private _postfixNames;
|
|
18
|
+
private _binaryPatterns;
|
|
19
|
+
private _binaryNames;
|
|
20
|
+
private _associationMap;
|
|
21
|
+
private _precedenceMap;
|
|
22
|
+
private _shouldStopParsing;
|
|
23
|
+
private _precedenceTree;
|
|
24
|
+
get id(): string;
|
|
25
|
+
get type(): string;
|
|
26
|
+
get name(): string;
|
|
27
|
+
get parent(): Pattern | null;
|
|
28
|
+
set parent(pattern: Pattern | null);
|
|
29
|
+
get children(): Pattern[];
|
|
30
|
+
get prefixPatterns(): readonly Pattern[];
|
|
31
|
+
get atomPatterns(): readonly Pattern[];
|
|
32
|
+
get postfixPatterns(): readonly Pattern[];
|
|
33
|
+
get binaryPatterns(): readonly Pattern[];
|
|
34
|
+
get startedOnIndex(): number;
|
|
35
|
+
constructor(name: string, patterns: Pattern[]);
|
|
36
|
+
private _organizePatterns;
|
|
37
|
+
private _extractName;
|
|
38
|
+
private _isPrefix;
|
|
39
|
+
private _extractPrefix;
|
|
40
|
+
private _isAtom;
|
|
41
|
+
private _isPostfix;
|
|
42
|
+
private _extractPostfix;
|
|
43
|
+
private _isBinary;
|
|
44
|
+
private _extractBinary;
|
|
45
|
+
private _unwrapAssociationIfNecessary;
|
|
46
|
+
private _referenceCount;
|
|
47
|
+
private _isRecursiveReference;
|
|
48
|
+
parse(cursor: Cursor): Node | null;
|
|
49
|
+
private _tryToParse;
|
|
50
|
+
private _tryToMatchPrefix;
|
|
51
|
+
private _tryToMatchAtom;
|
|
52
|
+
private _tryToMatchPostfix;
|
|
53
|
+
private _tryToMatchBinary;
|
|
54
|
+
private _isBeyondRecursiveAllowance;
|
|
55
|
+
test(text: string, record?: boolean): boolean;
|
|
56
|
+
exec(text: string, record?: boolean): ParseResult;
|
|
57
|
+
getTokens(): string[];
|
|
58
|
+
getTokensAfter(childReference: Pattern): string[];
|
|
59
|
+
getNextTokens(): string[];
|
|
60
|
+
getPatterns(): Pattern[];
|
|
61
|
+
getPatternsAfter(childReference: Pattern): Pattern[];
|
|
62
|
+
getNextPatterns(): Pattern[];
|
|
63
|
+
find(predicate: (p: Pattern) => boolean): Pattern | null;
|
|
64
|
+
clone(name?: string): Pattern;
|
|
65
|
+
isEqual(pattern: Expression): boolean;
|
|
66
|
+
}
|
|
@@ -5,9 +5,9 @@ export interface Pattern {
|
|
|
5
5
|
id: string;
|
|
6
6
|
type: string;
|
|
7
7
|
name: string;
|
|
8
|
-
startedOnIndex: number;
|
|
9
8
|
parent: Pattern | null;
|
|
10
9
|
children: Pattern[];
|
|
10
|
+
startedOnIndex: number;
|
|
11
11
|
parse(cursor: Cursor): Node | null;
|
|
12
12
|
exec(text: string, record?: boolean): ParseResult;
|
|
13
13
|
test(text: string, record?: boolean): boolean;
|
|
@@ -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 RightAssociated implements Pattern {
|
|
6
|
+
private _id;
|
|
7
|
+
private _type;
|
|
8
|
+
private _name;
|
|
9
|
+
private _parent;
|
|
10
|
+
private _children;
|
|
11
|
+
get id(): string;
|
|
12
|
+
get type(): string;
|
|
13
|
+
get name(): string;
|
|
14
|
+
get parent(): Pattern | null;
|
|
15
|
+
set parent(pattern: Pattern | null);
|
|
16
|
+
get children(): Pattern[];
|
|
17
|
+
get startedOnIndex(): number;
|
|
18
|
+
constructor(pattern: 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 | undefined): 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
package/src/ast/Node.test.ts
CHANGED
|
@@ -329,12 +329,12 @@ describe("Node", () => {
|
|
|
329
329
|
expect(result).toEqual(expected);
|
|
330
330
|
});
|
|
331
331
|
|
|
332
|
-
test("
|
|
332
|
+
test("Compact", () => {
|
|
333
333
|
const parent = new Node("parent", "parent", 0, 6, [
|
|
334
334
|
new Node("child", "child", 0, 6, undefined, "Content")
|
|
335
335
|
]);
|
|
336
336
|
|
|
337
|
-
parent.
|
|
337
|
+
parent.compact();
|
|
338
338
|
|
|
339
339
|
expect(parent.hasChildren).toBeFalsy();
|
|
340
340
|
expect(parent.value).toBe("Content");
|
package/src/ast/Node.ts
CHANGED
|
@@ -28,6 +28,10 @@ export class Node {
|
|
|
28
28
|
return this._name;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
get value() {
|
|
32
|
+
return this.toString();
|
|
33
|
+
}
|
|
34
|
+
|
|
31
35
|
get firstIndex() {
|
|
32
36
|
return this._firstIndex;
|
|
33
37
|
}
|
|
@@ -60,10 +64,6 @@ export class Node {
|
|
|
60
64
|
return !this.hasChildren;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
get value() {
|
|
64
|
-
return this.toString();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
67
|
constructor(
|
|
68
68
|
type: string,
|
|
69
69
|
name: string,
|
|
@@ -185,6 +185,16 @@ export class Node {
|
|
|
185
185
|
return this.findAll(predicate)[0] || null;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
findAll(predicate: (node: Node) => boolean): Node[] {
|
|
189
|
+
const matches: Node[] = [];
|
|
190
|
+
|
|
191
|
+
this.walkUp(n => {
|
|
192
|
+
if (predicate(n)) { matches.push(n); }
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return matches;
|
|
196
|
+
}
|
|
197
|
+
|
|
188
198
|
findRoot() {
|
|
189
199
|
let pattern: Node | null = this;
|
|
190
200
|
|
|
@@ -196,16 +206,6 @@ export class Node {
|
|
|
196
206
|
}
|
|
197
207
|
}
|
|
198
208
|
|
|
199
|
-
findAll(predicate: (node: Node) => boolean): Node[] {
|
|
200
|
-
const matches: Node[] = [];
|
|
201
|
-
|
|
202
|
-
this.walkUp(n => {
|
|
203
|
-
if (predicate(n)) { matches.push(n); }
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
return matches;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
209
|
findAncestor(predicate: (node: Node) => boolean) {
|
|
210
210
|
let parent = this._parent;
|
|
211
211
|
|
|
@@ -267,7 +267,7 @@ export class Node {
|
|
|
267
267
|
return nodes;
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
|
|
270
|
+
compact() {
|
|
271
271
|
const value = this.toString();
|
|
272
272
|
this.removeAllChildren();
|
|
273
273
|
this._value = value;
|
|
@@ -310,11 +310,6 @@ export class Node {
|
|
|
310
310
|
return length;
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
compact() {
|
|
314
|
-
this._value = this.toString();
|
|
315
|
-
this._children.length = 0;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
313
|
toString(): string {
|
|
319
314
|
if (this._children.length === 0) {
|
|
320
315
|
return this._value;
|
package/src/grammar/Grammar.ts
CHANGED
|
@@ -11,8 +11,8 @@ import { Repeat, RepeatOptions } from "../patterns/Repeat";
|
|
|
11
11
|
import { AutoComplete } from "../intellisense/AutoComplete";
|
|
12
12
|
import { Optional } from "../patterns/Optional";
|
|
13
13
|
import { Context } from "../patterns/Context";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { Expression } from "../patterns/Expression";
|
|
15
|
+
import { RightAssociated } from "../patterns/RightAssociated";
|
|
16
16
|
|
|
17
17
|
let anonymousIndexId = 0;
|
|
18
18
|
|
|
@@ -88,17 +88,6 @@ export class Grammar {
|
|
|
88
88
|
return this._buildPatternRecord();
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
private _buildPatternRecord() {
|
|
92
|
-
const patterns: Record<string, Pattern> = {};
|
|
93
|
-
const allPatterns = Array.from(this._parseContext.patternsByName.values());
|
|
94
|
-
|
|
95
|
-
allPatterns.forEach(p => {
|
|
96
|
-
patterns[p.name] = new Context(p.name, p, allPatterns.filter(o => o !== p));
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
return patterns;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
91
|
parseString(expression: string) {
|
|
103
92
|
this._parseContext = new ParseContext(this._params);
|
|
104
93
|
const ast = this._tryToParse(expression);
|
|
@@ -112,6 +101,17 @@ export class Grammar {
|
|
|
112
101
|
return this._buildPatternRecord();
|
|
113
102
|
}
|
|
114
103
|
|
|
104
|
+
private _buildPatternRecord() {
|
|
105
|
+
const patterns: Record<string, Pattern> = {};
|
|
106
|
+
const allPatterns = Array.from(this._parseContext.patternsByName.values());
|
|
107
|
+
|
|
108
|
+
allPatterns.forEach(p => {
|
|
109
|
+
patterns[p.name] = new Context(p.name, p, allPatterns.filter(o => o !== p));
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return patterns;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
115
|
private _tryToParse(expression: string): Node {
|
|
116
116
|
const { ast, cursor, options, isComplete } = this._autoComplete.suggestFor(expression);
|
|
117
117
|
|
|
@@ -252,23 +252,23 @@ export class Grammar {
|
|
|
252
252
|
const patterns = patternNodes.map(n => {
|
|
253
253
|
const rightAssociated = n.find(n => n.name === "right-associated");
|
|
254
254
|
if (rightAssociated != null) {
|
|
255
|
-
return new
|
|
255
|
+
return new RightAssociated(this._buildPattern(n.children[0]));
|
|
256
256
|
} else {
|
|
257
257
|
return this._buildPattern(n.children[0]);
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
});
|
|
261
|
-
|
|
261
|
+
|
|
262
262
|
const hasRecursivePattern = patterns.some(p => this._isRecursive(name, p));
|
|
263
263
|
if (hasRecursivePattern && !isGreedy) {
|
|
264
264
|
try {
|
|
265
|
-
const expression = new
|
|
265
|
+
const expression = new Expression(name, patterns);
|
|
266
266
|
return expression;
|
|
267
267
|
} catch { }
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
const
|
|
271
|
-
return
|
|
270
|
+
const options = new Options(name, patterns, isGreedy);
|
|
271
|
+
return options;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
private _isRecursive(name: string, pattern: Pattern) {
|
|
@@ -280,7 +280,7 @@ export class Grammar {
|
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
private _isRecursivePattern(name: string, pattern: Pattern) {
|
|
283
|
-
if (pattern.children.length === 0){
|
|
283
|
+
if (pattern.children.length === 0) {
|
|
284
284
|
return false;
|
|
285
285
|
}
|
|
286
286
|
|
|
@@ -333,7 +333,7 @@ export class Grammar {
|
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
private _buildSequence(name: string, node: Node) {
|
|
336
|
-
const patternNodes = node.children.filter(n => n.name !== "
|
|
336
|
+
const patternNodes = node.children.filter(n => n.name !== "sequence-divider");
|
|
337
337
|
|
|
338
338
|
const patterns = patternNodes.map(n => {
|
|
339
339
|
const patternNode = n.children[0].name === "not" ? n.children[1] : n.children[0];
|
|
@@ -10,15 +10,15 @@ import { Optional } from "../../patterns/Optional";
|
|
|
10
10
|
const optionalNot = new Optional("optional-not", new Literal("not", "!"));
|
|
11
11
|
const optionalIsOptional = new Optional("optional-is-optional", new Literal("is-optional", "?"));
|
|
12
12
|
const patternName = name.clone("pattern-name");
|
|
13
|
-
const patterns = new Options("
|
|
13
|
+
const patterns = new Options("sequence-patterns", [patternName, anonymousPattern]);
|
|
14
14
|
|
|
15
|
-
export const pattern = new Sequence("
|
|
15
|
+
export const pattern = new Sequence("sequence-child-pattern", [
|
|
16
16
|
optionalNot,
|
|
17
17
|
patterns,
|
|
18
18
|
optionalIsOptional,
|
|
19
19
|
]);
|
|
20
20
|
|
|
21
|
-
const divider = new Regex("
|
|
21
|
+
const divider = new Regex("sequence-divider", "\\s*[+]\\s*");
|
|
22
22
|
divider.setTokens([" + "]);
|
|
23
23
|
|
|
24
24
|
export const sequenceLiteral = new Repeat("sequence-literal", pattern, { divider, min: 2, trimDivider: true });
|
package/src/index.ts
CHANGED
|
@@ -21,7 +21,8 @@ import { ParseResult } from "./patterns/ParseResult";
|
|
|
21
21
|
import { grammar } from "./grammar/patterns/grammar";
|
|
22
22
|
import { patterns } from "./grammar/patterns";
|
|
23
23
|
import { Context } from "./patterns/Context";
|
|
24
|
-
import {
|
|
24
|
+
import { Expression } from "./patterns/Expression";
|
|
25
|
+
import { RightAssociated } from "./patterns/RightAssociated";
|
|
25
26
|
|
|
26
27
|
export {
|
|
27
28
|
Node,
|
|
@@ -35,7 +36,7 @@ export {
|
|
|
35
36
|
CursorHistory,
|
|
36
37
|
Match,
|
|
37
38
|
Context,
|
|
38
|
-
|
|
39
|
+
Expression,
|
|
39
40
|
Literal,
|
|
40
41
|
Not,
|
|
41
42
|
Options,
|
|
@@ -44,6 +45,7 @@ export {
|
|
|
44
45
|
ParseResult,
|
|
45
46
|
Pattern,
|
|
46
47
|
Reference,
|
|
48
|
+
RightAssociated,
|
|
47
49
|
Regex,
|
|
48
50
|
Repeat,
|
|
49
51
|
grammar,
|
|
@@ -112,11 +112,11 @@ export class CursorHistory {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
recordErrorAt(startIndex: number,
|
|
116
|
-
const error = new ParseError(startIndex,
|
|
115
|
+
recordErrorAt(startIndex: number, lastIndex: number, pattern: Pattern): void {
|
|
116
|
+
const error = new ParseError(startIndex, lastIndex, pattern);
|
|
117
117
|
this._currentError = error;
|
|
118
118
|
|
|
119
|
-
if (this._furthestError === null ||
|
|
119
|
+
if (this._furthestError === null || lastIndex > this._furthestError.lastIndex) {
|
|
120
120
|
this._furthestError = error;
|
|
121
121
|
}
|
|
122
122
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Options } from "./Options";
|
|
2
2
|
import { Literal } from './Literal';
|
|
3
|
-
import {
|
|
3
|
+
import { Expression } from './Expression';
|
|
4
4
|
import { Reference } from "./Reference";
|
|
5
5
|
import { Sequence } from './Sequence';
|
|
6
6
|
import { Regex } from './Regex';
|
|
7
7
|
import { Optional } from "./Optional";
|
|
8
8
|
import { AutoComplete } from "../intellisense/AutoComplete";
|
|
9
|
-
import {
|
|
9
|
+
import { RightAssociated } from "./RightAssociated";
|
|
10
10
|
|
|
11
11
|
function createExpressionPattern() {
|
|
12
12
|
const spaces = new Regex("spaces", "\\s+");
|
|
@@ -75,11 +75,11 @@ function createExpressionPattern() {
|
|
|
75
75
|
new Reference("expression"),
|
|
76
76
|
]);
|
|
77
77
|
|
|
78
|
-
const expression = new
|
|
79
|
-
|
|
78
|
+
const expression = new Expression("expression", [
|
|
79
|
+
multDivExpression,
|
|
80
80
|
addSubExpression,
|
|
81
81
|
boolExpression,
|
|
82
|
-
new
|
|
82
|
+
new RightAssociated(ternary),
|
|
83
83
|
group,
|
|
84
84
|
variables,
|
|
85
85
|
]);
|
|
@@ -92,8 +92,8 @@ function createOptionsExpression() {
|
|
|
92
92
|
const b = new Literal("b", "b");
|
|
93
93
|
const c = new Literal("c", "c");
|
|
94
94
|
|
|
95
|
-
const
|
|
96
|
-
return
|
|
95
|
+
const expression = new Expression("expression", [a, b, c]);
|
|
96
|
+
return expression;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
function createTailExpression() {
|
|
@@ -115,7 +115,7 @@ function createTailExpression() {
|
|
|
115
115
|
invocation
|
|
116
116
|
]);
|
|
117
117
|
|
|
118
|
-
const expression = new
|
|
118
|
+
const expression = new Expression("expression", [
|
|
119
119
|
refinementExpression,
|
|
120
120
|
invocationExpression,
|
|
121
121
|
variable
|
|
@@ -10,7 +10,7 @@ import { execPattern } from "./execPattern";
|
|
|
10
10
|
|
|
11
11
|
let indexId = 0;
|
|
12
12
|
|
|
13
|
-
export class
|
|
13
|
+
export class Expression implements Pattern {
|
|
14
14
|
private _id: string;
|
|
15
15
|
private _type: string;
|
|
16
16
|
private _name: string;
|
|
@@ -83,7 +83,7 @@ export class ExpressionPattern implements Pattern {
|
|
|
83
83
|
this._type = "expression";
|
|
84
84
|
this._name = name;
|
|
85
85
|
this._parent = null;
|
|
86
|
-
this._firstIndex =
|
|
86
|
+
this._firstIndex = 0;
|
|
87
87
|
this._atomPatterns = [];
|
|
88
88
|
this._prefixPatterns = [];
|
|
89
89
|
this._prefixNames = [];
|
|
@@ -135,11 +135,11 @@ export class ExpressionPattern implements Pattern {
|
|
|
135
135
|
finalPatterns.push(postfix);
|
|
136
136
|
} else if (this._isBinary(pattern)) {
|
|
137
137
|
const name = this._extractName(pattern);
|
|
138
|
-
const
|
|
139
|
-
|
|
138
|
+
const binary = this._extractBinary(pattern);
|
|
139
|
+
binary.parent = this;
|
|
140
140
|
|
|
141
141
|
this._precedenceMap[name] = this._binaryPatterns.length;
|
|
142
|
-
this._binaryPatterns.push(
|
|
142
|
+
this._binaryPatterns.push(binary);
|
|
143
143
|
this._binaryNames.push(name);
|
|
144
144
|
|
|
145
145
|
if (pattern.type === "right-associated") {
|
|
@@ -148,7 +148,7 @@ export class ExpressionPattern implements Pattern {
|
|
|
148
148
|
this._associationMap[name] = Association.left;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
finalPatterns.push(
|
|
151
|
+
finalPatterns.push(binary);
|
|
152
152
|
}
|
|
153
153
|
});
|
|
154
154
|
|
|
@@ -183,7 +183,7 @@ export class ExpressionPattern implements Pattern {
|
|
|
183
183
|
pattern = this._unwrapAssociationIfNecessary(pattern);
|
|
184
184
|
|
|
185
185
|
const firstChild = pattern.children[0];
|
|
186
|
-
const lastChild = pattern.children[pattern.children.length -1];
|
|
186
|
+
const lastChild = pattern.children[pattern.children.length - 1];
|
|
187
187
|
const firstChildIsReference = this._isRecursiveReference(firstChild);
|
|
188
188
|
const lastChildIsReference = this._isRecursiveReference(lastChild);
|
|
189
189
|
|
|
@@ -454,7 +454,10 @@ export class ExpressionPattern implements Pattern {
|
|
|
454
454
|
}
|
|
455
455
|
|
|
456
456
|
getTokens(): string[] {
|
|
457
|
-
|
|
457
|
+
const atomTokens = this._atomPatterns.map(p => p.getTokens()).flat();
|
|
458
|
+
const prefixTokens = this.prefixPatterns.map(p => p.getTokens()).flat();
|
|
459
|
+
|
|
460
|
+
return [...prefixTokens, ...atomTokens];
|
|
458
461
|
}
|
|
459
462
|
|
|
460
463
|
getTokensAfter(childReference: Pattern): string[] {
|
|
@@ -468,7 +471,7 @@ export class ExpressionPattern implements Pattern {
|
|
|
468
471
|
if (this._atomPatterns.includes(childReference)) {
|
|
469
472
|
const postfixTokens = this.prefixPatterns.map(p => p.getTokens()).flat();
|
|
470
473
|
|
|
471
|
-
if (postfixTokens.length === 0){
|
|
474
|
+
if (postfixTokens.length === 0) {
|
|
472
475
|
return this._binaryPatterns.map(p => p.getTokens()).flat();
|
|
473
476
|
}
|
|
474
477
|
|
|
@@ -494,7 +497,10 @@ export class ExpressionPattern implements Pattern {
|
|
|
494
497
|
}
|
|
495
498
|
|
|
496
499
|
getPatterns(): Pattern[] {
|
|
497
|
-
|
|
500
|
+
const atomPatterns = this._atomPatterns.map(p => p.getPatterns()).flat();
|
|
501
|
+
const prefixPatterns = this.prefixPatterns.map(p => p.getPatterns()).flat();
|
|
502
|
+
|
|
503
|
+
return [...prefixPatterns, ...atomPatterns];
|
|
498
504
|
}
|
|
499
505
|
|
|
500
506
|
getPatternsAfter(childReference: Pattern): Pattern[] {
|
|
@@ -508,7 +514,7 @@ export class ExpressionPattern implements Pattern {
|
|
|
508
514
|
if (this._atomPatterns.includes(childReference)) {
|
|
509
515
|
const postfixPatterns = this.prefixPatterns.map(p => p.getPatterns()).flat();
|
|
510
516
|
|
|
511
|
-
if (postfixPatterns.length === 0){
|
|
517
|
+
if (postfixPatterns.length === 0) {
|
|
512
518
|
return this._binaryPatterns.map(p => p.getPatterns()).flat();
|
|
513
519
|
}
|
|
514
520
|
|
|
@@ -538,12 +544,12 @@ export class ExpressionPattern implements Pattern {
|
|
|
538
544
|
}
|
|
539
545
|
|
|
540
546
|
clone(name = this._name): Pattern {
|
|
541
|
-
const clone = new
|
|
547
|
+
const clone = new Expression(name, this._originalPatterns);
|
|
542
548
|
clone._id = this._id;
|
|
543
549
|
return clone;
|
|
544
550
|
}
|
|
545
551
|
|
|
546
|
-
isEqual(pattern:
|
|
552
|
+
isEqual(pattern: Expression): boolean {
|
|
547
553
|
return pattern.type === this.type && this.children.every((c, index) => c.isEqual(pattern.children[index]));
|
|
548
554
|
}
|
|
549
555
|
}
|
|
@@ -93,7 +93,6 @@ export class FiniteRepeat implements Pattern {
|
|
|
93
93
|
parse(cursor: Cursor): Node | null {
|
|
94
94
|
this._firstIndex = cursor.index;
|
|
95
95
|
|
|
96
|
-
const startIndex = cursor.index;
|
|
97
96
|
const nodes: Node[] = [];
|
|
98
97
|
const modulo = this._hasDivider ? 2 : 1;
|
|
99
98
|
let matchCount = 0;
|
|
@@ -134,13 +133,13 @@ export class FiniteRepeat implements Pattern {
|
|
|
134
133
|
|
|
135
134
|
if (matchCount < this._min) {
|
|
136
135
|
const lastIndex = cursor.index;
|
|
137
|
-
cursor.moveTo(
|
|
138
|
-
cursor.recordErrorAt(
|
|
136
|
+
cursor.moveTo(this._firstIndex);
|
|
137
|
+
cursor.recordErrorAt(this._firstIndex, lastIndex, this);
|
|
139
138
|
return null;
|
|
140
139
|
}
|
|
141
140
|
|
|
142
141
|
if (nodes.length === 0 && !cursor.hasError) {
|
|
143
|
-
cursor.moveTo(
|
|
142
|
+
cursor.moveTo(this._firstIndex);
|
|
144
143
|
return null;
|
|
145
144
|
}
|
|
146
145
|
|
|
@@ -150,7 +149,13 @@ export class FiniteRepeat implements Pattern {
|
|
|
150
149
|
cursor.resolveError();
|
|
151
150
|
cursor.moveTo(lastIndex);
|
|
152
151
|
|
|
153
|
-
const node = new Node(
|
|
152
|
+
const node = new Node(
|
|
153
|
+
this._type,
|
|
154
|
+
this.name,
|
|
155
|
+
firstIndex,
|
|
156
|
+
lastIndex,
|
|
157
|
+
nodes
|
|
158
|
+
);
|
|
154
159
|
|
|
155
160
|
return node;
|
|
156
161
|
}
|
|
@@ -80,7 +80,7 @@ export class InfiniteRepeat implements Pattern {
|
|
|
80
80
|
this._children = children;
|
|
81
81
|
this._pattern = children[0];
|
|
82
82
|
this._divider = children[1];
|
|
83
|
-
this._firstIndex =
|
|
83
|
+
this._firstIndex = 0;
|
|
84
84
|
this._nodes = [];
|
|
85
85
|
this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
|
|
86
86
|
}
|
|
@@ -91,7 +91,6 @@ export class InfiniteRepeat implements Pattern {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
95
94
|
test(text: string, record = false): boolean {
|
|
96
95
|
return testPattern(this, text, record);
|
|
97
96
|
}
|
|
@@ -113,7 +112,6 @@ export class InfiniteRepeat implements Pattern {
|
|
|
113
112
|
if (node != null) {
|
|
114
113
|
cursor.moveTo(node.lastIndex);
|
|
115
114
|
cursor.recordMatch(this, node);
|
|
116
|
-
|
|
117
115
|
}
|
|
118
116
|
|
|
119
117
|
return node;
|
|
@@ -314,7 +312,7 @@ export class InfiniteRepeat implements Pattern {
|
|
|
314
312
|
}
|
|
315
313
|
|
|
316
314
|
// If there is no divider then suggest the repeating pattern and the next pattern after.
|
|
317
|
-
if (index === 0 &&
|
|
315
|
+
if (index === 0 && this._divider == null && this._parent) {
|
|
318
316
|
patterns.push(this._children[0]);
|
|
319
317
|
patterns.push(...this._parent.getPatternsAfter(this));
|
|
320
318
|
}
|
|
@@ -348,7 +346,6 @@ export class InfiniteRepeat implements Pattern {
|
|
|
348
346
|
);
|
|
349
347
|
|
|
350
348
|
clone._id = this._id;
|
|
351
|
-
|
|
352
349
|
return clone;
|
|
353
350
|
}
|
|
354
351
|
|
package/src/patterns/Pattern.ts
CHANGED
|
@@ -6,9 +6,9 @@ export interface Pattern {
|
|
|
6
6
|
id: string;
|
|
7
7
|
type: string;
|
|
8
8
|
name: string;
|
|
9
|
-
startedOnIndex: number;
|
|
10
9
|
parent: Pattern | null;
|
|
11
10
|
children: Pattern[];
|
|
11
|
+
startedOnIndex: number;
|
|
12
12
|
|
|
13
13
|
parse(cursor: Cursor): Node | null;
|
|
14
14
|
exec(text: string, record?: boolean): ParseResult;
|
|
@@ -5,7 +5,7 @@ import { Pattern } from "./Pattern";
|
|
|
5
5
|
|
|
6
6
|
let indexId = 0;
|
|
7
7
|
|
|
8
|
-
export class
|
|
8
|
+
export class RightAssociated implements Pattern {
|
|
9
9
|
private _id: string;
|
|
10
10
|
private _type: string;
|
|
11
11
|
private _name: string;
|
|
@@ -61,7 +61,7 @@ export class RightAssociatedPattern implements Pattern {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
clone(_name?: string | undefined): Pattern {
|
|
64
|
-
const clone = new
|
|
64
|
+
const clone = new RightAssociated(this.children[0]);
|
|
65
65
|
clone._id = this._id;
|
|
66
66
|
return clone;
|
|
67
67
|
}
|