clarity-pattern-parser 3.0.15 → 4.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 +0 -191
- package/dist/ast/Node.d.ts +4 -5
- package/dist/index.browser.js +476 -731
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +10 -18
- package/dist/index.esm.js +469 -716
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +476 -731
- package/dist/index.js.map +1 -1
- package/dist/patterns/And.d.ts +24 -0
- package/dist/patterns/Literal.d.ts +19 -0
- package/dist/patterns/LookAhead.d.ts +8 -0
- package/dist/patterns/Not.d.ts +11 -0
- package/dist/patterns/Or.d.ts +22 -0
- package/dist/patterns/Pattern.d.ts +6 -7
- package/dist/patterns/{RecursivePattern.d.ts → Recursive.d.ts} +4 -4
- package/dist/patterns/Reference.d.ts +14 -0
- package/dist/patterns/Regex.d.ts +21 -0
- package/dist/patterns/Repeat.d.ts +20 -0
- package/package.json +1 -1
- package/src/CursorHistory.ts +1 -1
- package/src/ast/Node.ts +20 -17
- package/src/ast/Visitor.ts +14 -18
- package/src/index.ts +17 -33
- package/src/patterns/And.ts +178 -0
- package/src/patterns/Literal.ts +91 -0
- package/src/patterns/LookAhead.ts +32 -0
- package/src/patterns/Not.ts +50 -0
- package/src/patterns/Or.ts +132 -0
- package/src/patterns/Pattern.ts +31 -47
- package/src/patterns/Recursive.ts +92 -0
- package/src/patterns/Reference.ts +127 -0
- package/src/patterns/Regex.ts +123 -0
- package/src/patterns/Repeat.ts +155 -0
- package/src/tests/{AndValue.test.ts → And.test.ts} +31 -41
- package/src/tests/CursorHistory.test.ts +6 -6
- package/src/tests/Cusor.test.ts +7 -10
- package/src/tests/Literal.test.ts +3 -5
- package/src/tests/LookAhead.test.ts +44 -0
- package/src/tests/Not.test.ts +51 -0
- package/src/tests/Or.test.ts +113 -0
- package/src/tests/Pattern.test.ts +41 -141
- package/src/tests/{RecursivePattern.test.ts → Recursive.test.ts} +10 -8
- package/src/tests/Reference.test.ts +16 -0
- package/src/tests/{RepeatValue.test.ts → Repeat.test.ts} +10 -42
- package/src/tests/TextSuggester.test.ts +20 -28
- package/src/tests/{NodeVisitor.test.ts → Visitor.test.ts} +42 -21
- package/src/tests/cssPatterns/cssValue.ts +2 -2
- package/src/tests/cssPatterns/divider.ts +2 -2
- package/src/tests/cssPatterns/hex.ts +2 -2
- package/src/tests/cssPatterns/method.ts +7 -9
- package/src/tests/cssPatterns/name.ts +2 -2
- package/src/tests/cssPatterns/number.ts +2 -2
- package/src/tests/cssPatterns/optionalSpaces.ts +1 -2
- package/src/tests/cssPatterns/spaces.ts +2 -2
- package/src/tests/cssPatterns/unit.ts +3 -3
- package/src/tests/cssPatterns/value.ts +2 -2
- package/src/tests/cssPatterns/values.ts +2 -2
- package/src/tests/htmlPatterns/element.ts +18 -33
- package/src/tests/javascriptPatterns/boolean.ts +2 -3
- package/src/tests/javascriptPatterns/json.ts +14 -24
- package/src/tests/javascriptPatterns/name.ts +3 -20
- package/src/tests/javascriptPatterns/number.ts +2 -2
- package/src/tests/javascriptPatterns/objectLiteral.ts +9 -16
- package/src/tests/javascriptPatterns/string.ts +26 -24
- package/src/tests/javascriptPatterns/unit.ts +3 -6
- package/src/tests/javascriptPatterns/whitespace.ts +8 -12
- package/src/tests/naturalLanguage/filter.ts +16 -33
- package/src/tests/patterns/sentence.ts +8 -8
- package/dist/Cursor.js +0 -105
- package/dist/Cursor.js.map +0 -1
- package/dist/CursorHistory.js +0 -104
- package/dist/CursorHistory.js.map +0 -1
- package/dist/Permutor.d.ts +0 -13
- package/dist/Permutor.js +0 -52
- package/dist/Permutor.js.map +0 -1
- package/dist/TextSuggester.js +0 -244
- package/dist/TextSuggester.js.map +0 -1
- package/dist/ast/CompositeNode.d.ts +0 -6
- package/dist/ast/CompositeNode.js +0 -17
- package/dist/ast/CompositeNode.js.map +0 -1
- package/dist/ast/Node.js +0 -16
- package/dist/ast/Node.js.map +0 -1
- package/dist/ast/NodeVisitor.d.ts +0 -31
- package/dist/ast/ValueNode.d.ts +0 -6
- package/dist/ast/ValueNode.js +0 -14
- package/dist/ast/ValueNode.js.map +0 -1
- package/dist/ast/Visitor.js +0 -209
- package/dist/ast/Visitor.js.map +0 -1
- package/dist/patterns/ParseError.js +0 -9
- package/dist/patterns/ParseError.js.map +0 -1
- package/dist/patterns/Pattern.js +0 -127
- package/dist/patterns/Pattern.js.map +0 -1
- package/dist/patterns/RecursivePattern.js +0 -65
- package/dist/patterns/RecursivePattern.js.map +0 -1
- package/dist/patterns/composite/AndComposite.d.ts +0 -22
- package/dist/patterns/composite/AndComposite.js +0 -117
- package/dist/patterns/composite/AndComposite.js.map +0 -1
- package/dist/patterns/composite/CompositePattern.d.ts +0 -4
- package/dist/patterns/composite/CompositePattern.js +0 -7
- package/dist/patterns/composite/CompositePattern.js.map +0 -1
- package/dist/patterns/composite/OptionalComposite.d.ts +0 -10
- package/dist/patterns/composite/OptionalComposite.js +0 -29
- package/dist/patterns/composite/OptionalComposite.js.map +0 -1
- package/dist/patterns/composite/OrComposite.d.ts +0 -16
- package/dist/patterns/composite/OrComposite.js +0 -69
- package/dist/patterns/composite/OrComposite.js.map +0 -1
- package/dist/patterns/composite/RepeatComposite.d.ts +0 -21
- package/dist/patterns/composite/RepeatComposite.js +0 -88
- package/dist/patterns/composite/RepeatComposite.js.map +0 -1
- package/dist/patterns/value/AndValue.d.ts +0 -21
- package/dist/patterns/value/AndValue.js +0 -118
- package/dist/patterns/value/AndValue.js.map +0 -1
- package/dist/patterns/value/AnyOfThese.d.ts +0 -18
- package/dist/patterns/value/AnyOfThese.js +0 -59
- package/dist/patterns/value/AnyOfThese.js.map +0 -1
- package/dist/patterns/value/Literal.d.ts +0 -20
- package/dist/patterns/value/Literal.js +0 -63
- package/dist/patterns/value/Literal.js.map +0 -1
- package/dist/patterns/value/NotValue.d.ts +0 -17
- package/dist/patterns/value/NotValue.js +0 -70
- package/dist/patterns/value/NotValue.js.map +0 -1
- package/dist/patterns/value/OptionalValue.d.ts +0 -9
- package/dist/patterns/value/OptionalValue.js +0 -32
- package/dist/patterns/value/OptionalValue.js.map +0 -1
- package/dist/patterns/value/OrValue.d.ts +0 -19
- package/dist/patterns/value/OrValue.js +0 -73
- package/dist/patterns/value/OrValue.js.map +0 -1
- package/dist/patterns/value/RegexValue.d.ts +0 -19
- package/dist/patterns/value/RegexValue.js +0 -69
- package/dist/patterns/value/RegexValue.js.map +0 -1
- package/dist/patterns/value/RepeatValue.d.ts +0 -19
- package/dist/patterns/value/RepeatValue.js +0 -89
- package/dist/patterns/value/RepeatValue.js.map +0 -1
- package/dist/patterns/value/ValuePattern.d.ts +0 -5
- package/dist/patterns/value/ValuePattern.js +0 -7
- package/dist/patterns/value/ValuePattern.js.map +0 -1
- package/src/Permutor.ts +0 -64
- package/src/ast/CompositeNode.ts +0 -26
- package/src/ast/ValueNode.ts +0 -28
- package/src/patterns/RecursivePattern.ts +0 -86
- package/src/patterns/composite/AndComposite.ts +0 -159
- package/src/patterns/composite/CompositePattern.ts +0 -7
- package/src/patterns/composite/OptionalComposite.ts +0 -37
- package/src/patterns/composite/OrComposite.ts +0 -96
- package/src/patterns/composite/RepeatComposite.ts +0 -130
- package/src/patterns/value/AndValue.ts +0 -153
- package/src/patterns/value/AnyOfThese.ts +0 -81
- package/src/patterns/value/Literal.ts +0 -92
- package/src/patterns/value/NotValue.ts +0 -95
- package/src/patterns/value/OptionalValue.ts +0 -39
- package/src/patterns/value/OrValue.ts +0 -103
- package/src/patterns/value/RegexValue.ts +0 -103
- package/src/patterns/value/RepeatValue.ts +0 -131
- package/src/patterns/value/ValuePattern.ts +0 -8
- package/src/tests/AndComposite.test.ts +0 -102
- package/src/tests/AnyOfThese.test.ts +0 -74
- package/src/tests/CompositeNode.test.ts +0 -33
- package/src/tests/NotValue.test.ts +0 -69
- package/src/tests/OptionalValue.test.ts +0 -50
- package/src/tests/OrComposite.test.ts +0 -75
- package/src/tests/OrValue.test.ts +0 -171
- package/src/tests/Permutor.test.ts +0 -30
- package/src/tests/RegexValue.test.ts +0 -22
- package/src/tests/RepeatComposite.test.ts +0 -58
- package/src/tests/ValueNode.test.ts +0 -24
- package/src/tests/javascriptPatterns/varStatement.ts +0 -0
- package/src/tests/readmeDemo.test.ts +0 -124
|
@@ -5,9 +5,9 @@ export default abstract class Pattern {
|
|
|
5
5
|
protected _name: string;
|
|
6
6
|
protected _children: Pattern[];
|
|
7
7
|
protected _parent: Pattern | null;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
protected _isOptional: boolean;
|
|
9
|
+
get isOptional(): boolean;
|
|
10
|
+
constructor(type: string, name: string, children?: Pattern[], isOptional?: boolean);
|
|
11
11
|
abstract parse(cursor: Cursor): Node | null;
|
|
12
12
|
exec(text: string): Node | null;
|
|
13
13
|
test(text: string): boolean;
|
|
@@ -17,11 +17,10 @@ export default abstract class Pattern {
|
|
|
17
17
|
set parent(value: Pattern | null);
|
|
18
18
|
get children(): Pattern[];
|
|
19
19
|
set children(value: Pattern[]);
|
|
20
|
-
protected _assertChildren(): void;
|
|
21
|
-
private _cloneChildren;
|
|
22
|
-
private _assignAsParent;
|
|
23
20
|
abstract clone(name?: string): Pattern;
|
|
24
21
|
abstract getTokens(): string[];
|
|
25
|
-
getNextTokens(): string[];
|
|
26
22
|
getTokenValue(): string | null;
|
|
23
|
+
getNextTokens(): string[];
|
|
24
|
+
private cloneChildren;
|
|
25
|
+
private assignAsParent;
|
|
27
26
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import Pattern from "./Pattern";
|
|
2
2
|
import Cursor from "../Cursor";
|
|
3
|
-
export default class
|
|
3
|
+
export default class Recursive extends Pattern {
|
|
4
4
|
isRecursing: boolean;
|
|
5
5
|
pattern: Pattern | null;
|
|
6
|
-
constructor(name: string);
|
|
6
|
+
constructor(name: string, isOptional?: boolean);
|
|
7
7
|
getPattern(): Pattern | null;
|
|
8
|
-
|
|
8
|
+
private climb;
|
|
9
9
|
parse(cursor: Cursor): import("..").Node | null;
|
|
10
|
-
clone(name?: string):
|
|
10
|
+
clone(name?: string, isOptional?: boolean): Recursive;
|
|
11
11
|
getTokenValue(): string | null;
|
|
12
12
|
getTokens(): string[];
|
|
13
13
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Pattern from "./Pattern";
|
|
2
|
+
import Cursor from "../Cursor";
|
|
3
|
+
export default class Reference extends Pattern {
|
|
4
|
+
private isRecursing;
|
|
5
|
+
constructor(name: string, isOptional?: boolean);
|
|
6
|
+
private getRoot;
|
|
7
|
+
private findPattern;
|
|
8
|
+
private walkTheTree;
|
|
9
|
+
parse(cursor: Cursor): import("..").Node | null;
|
|
10
|
+
clone(name?: string, isOptional?: boolean): Reference;
|
|
11
|
+
getTokenValue(): string | null;
|
|
12
|
+
private safelyGetPattern;
|
|
13
|
+
getTokens(): string[];
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Node from "../ast/Node";
|
|
2
|
+
import Pattern from "./Pattern";
|
|
3
|
+
import Cursor from "../Cursor";
|
|
4
|
+
export default class Regex extends Pattern {
|
|
5
|
+
private regexString;
|
|
6
|
+
private regex;
|
|
7
|
+
private node;
|
|
8
|
+
private cursor;
|
|
9
|
+
private substring;
|
|
10
|
+
constructor(name: string, regex: string, isOptional?: boolean);
|
|
11
|
+
private assertArguments;
|
|
12
|
+
parse(cursor: Cursor): Node | null;
|
|
13
|
+
private resetState;
|
|
14
|
+
private tryToParse;
|
|
15
|
+
private processResult;
|
|
16
|
+
private processError;
|
|
17
|
+
private safelyGetCursor;
|
|
18
|
+
clone(name?: string, isOptional?: boolean): Regex;
|
|
19
|
+
getTokenValue(): string;
|
|
20
|
+
getTokens(): string[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import Pattern from "./Pattern";
|
|
2
|
+
import Node from "../ast/Node";
|
|
3
|
+
import Cursor from "../Cursor";
|
|
4
|
+
export default class Repeat extends Pattern {
|
|
5
|
+
_pattern: Pattern;
|
|
6
|
+
_divider: Pattern;
|
|
7
|
+
nodes: Node[];
|
|
8
|
+
cursor: Cursor;
|
|
9
|
+
mark: number;
|
|
10
|
+
node: Node | null;
|
|
11
|
+
constructor(name: string, pattern: Pattern, divider?: Pattern, isOptional?: boolean);
|
|
12
|
+
private assertArguments;
|
|
13
|
+
private _reset;
|
|
14
|
+
parse(cursor: Cursor): Node | null;
|
|
15
|
+
private tryToParse;
|
|
16
|
+
private processResult;
|
|
17
|
+
private safelyGetCursor;
|
|
18
|
+
clone(name?: string, isOptional?: boolean): Repeat;
|
|
19
|
+
getTokens(): string[];
|
|
20
|
+
}
|
package/package.json
CHANGED
package/src/CursorHistory.ts
CHANGED
package/src/ast/Node.ts
CHANGED
|
@@ -1,36 +1,39 @@
|
|
|
1
|
-
export default
|
|
1
|
+
export default class Node {
|
|
2
2
|
public type: string;
|
|
3
3
|
public name: string;
|
|
4
4
|
public startIndex: number;
|
|
5
5
|
public endIndex: number;
|
|
6
|
-
public
|
|
7
|
-
public
|
|
8
|
-
public value: string = "";
|
|
6
|
+
public children: Node[];
|
|
7
|
+
public value: string;
|
|
9
8
|
|
|
10
9
|
constructor(
|
|
11
10
|
type: string,
|
|
12
11
|
name: string,
|
|
13
12
|
startIndex: number,
|
|
14
13
|
endIndex: number,
|
|
15
|
-
|
|
14
|
+
children: Node[] = [],
|
|
15
|
+
value: string = ""
|
|
16
16
|
) {
|
|
17
17
|
this.type = type;
|
|
18
18
|
this.name = name;
|
|
19
19
|
this.startIndex = startIndex;
|
|
20
20
|
this.endIndex = endIndex;
|
|
21
|
-
this.
|
|
22
|
-
|
|
23
|
-
if (
|
|
24
|
-
typeof this.startIndex !== "number" ||
|
|
25
|
-
typeof this.endIndex !== "number"
|
|
26
|
-
) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
"Invalid Arguments: startIndex and endIndex need to be number."
|
|
29
|
-
);
|
|
30
|
-
}
|
|
21
|
+
this.children = children;
|
|
22
|
+
this.value = value;
|
|
31
23
|
}
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
clone(): Node {
|
|
26
|
+
return new Node(
|
|
27
|
+
this.type,
|
|
28
|
+
this.name,
|
|
29
|
+
this.startIndex,
|
|
30
|
+
this.endIndex,
|
|
31
|
+
this.children.map((c) => c.clone()),
|
|
32
|
+
this.value
|
|
33
|
+
);
|
|
34
|
+
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
toString() {
|
|
37
|
+
return this.value;
|
|
38
|
+
}
|
|
36
39
|
}
|
package/src/ast/Visitor.ts
CHANGED
|
@@ -11,11 +11,11 @@ export default class Visitor {
|
|
|
11
11
|
|
|
12
12
|
flatten() {
|
|
13
13
|
this.selectedNodes.forEach((node) => {
|
|
14
|
-
if (node.
|
|
14
|
+
if (node.children.length > 0) {
|
|
15
15
|
const children: Node[] = [];
|
|
16
16
|
|
|
17
17
|
Visitor.walkUp(node, (descendant: Node) => {
|
|
18
|
-
if (
|
|
18
|
+
if (descendant.children.length === 0) {
|
|
19
19
|
children.push(descendant);
|
|
20
20
|
}
|
|
21
21
|
});
|
|
@@ -38,14 +38,12 @@ export default class Visitor {
|
|
|
38
38
|
|
|
39
39
|
private recursiveRemove(node: Node) {
|
|
40
40
|
const nodesToRemove = this.selectedNodes;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.recursiveRemove(node.children[x]);
|
|
48
|
-
}
|
|
41
|
+
for (let x = 0; x < node.children.length; x++) {
|
|
42
|
+
if (nodesToRemove.indexOf(node.children[x]) > -1) {
|
|
43
|
+
node.children.splice(x, 1);
|
|
44
|
+
x--;
|
|
45
|
+
} else {
|
|
46
|
+
this.recursiveRemove(node.children[x]);
|
|
49
47
|
}
|
|
50
48
|
}
|
|
51
49
|
}
|
|
@@ -136,12 +134,10 @@ export default class Visitor {
|
|
|
136
134
|
}
|
|
137
135
|
|
|
138
136
|
private recursiveTransform(node: Node, callback: (node: Node) => Node) {
|
|
139
|
-
|
|
140
|
-
const length = node.children.length;
|
|
137
|
+
const length = node.children.length;
|
|
141
138
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
139
|
+
for (let x = 0; x < length; x++) {
|
|
140
|
+
node.children[x] = this.recursiveTransform(node.children[x], callback);
|
|
145
141
|
}
|
|
146
142
|
|
|
147
143
|
return callback(node);
|
|
@@ -168,7 +164,7 @@ export default class Visitor {
|
|
|
168
164
|
const node = this.root;
|
|
169
165
|
const selectedNodes: Node[] = [];
|
|
170
166
|
|
|
171
|
-
if (node.
|
|
167
|
+
if (node.children.length > 0) {
|
|
172
168
|
Visitor.walkDown(node, (descendant: Node) => {
|
|
173
169
|
if (callback(descendant)) {
|
|
174
170
|
selectedNodes.push(descendant);
|
|
@@ -245,7 +241,7 @@ export default class Visitor {
|
|
|
245
241
|
) {
|
|
246
242
|
ancestors.push(node);
|
|
247
243
|
|
|
248
|
-
if (node.
|
|
244
|
+
if (node.children.length > 0) {
|
|
249
245
|
const children = node.children.slice();
|
|
250
246
|
children.forEach((c) => this.walkUp(c, callback, ancestors));
|
|
251
247
|
}
|
|
@@ -264,7 +260,7 @@ export default class Visitor {
|
|
|
264
260
|
callback(node, ancestors);
|
|
265
261
|
ancestors.push(node);
|
|
266
262
|
|
|
267
|
-
if (node.
|
|
263
|
+
if (node.children.length > 0) {
|
|
268
264
|
const children = node.children.slice();
|
|
269
265
|
children.forEach((c) => this.walkDown(c, callback, ancestors));
|
|
270
266
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,49 +1,33 @@
|
|
|
1
1
|
import Node from "./ast/Node";
|
|
2
|
-
import CompositeNode from "./ast/CompositeNode";
|
|
3
|
-
import ValueNode from "./ast/ValueNode";
|
|
4
2
|
import Cursor from "./Cursor";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import RepeatValue from "./patterns/value/RepeatValue";
|
|
13
|
-
import ValuePattern from "./patterns/value/ValuePattern";
|
|
14
|
-
import AndComposite from "./patterns/composite/AndComposite";
|
|
15
|
-
import CompositePattern from "./patterns/composite/CompositePattern";
|
|
16
|
-
import OptionalComposite from "./patterns/composite/OptionalComposite";
|
|
17
|
-
import OrComposite from "./patterns/composite/OrComposite";
|
|
18
|
-
import RepeatComposite from "./patterns/composite/RepeatComposite";
|
|
3
|
+
import Regex from "./patterns/Regex";
|
|
4
|
+
import And from "./patterns/And";
|
|
5
|
+
import Literal from "./patterns/Literal";
|
|
6
|
+
import LookAhead from "./patterns/LookAhead";
|
|
7
|
+
import Not from "./patterns/Not";
|
|
8
|
+
import Or from "./patterns/Or";
|
|
9
|
+
import Repeat from "./patterns/Repeat";
|
|
19
10
|
import ParseError from "./patterns/ParseError";
|
|
20
11
|
import Pattern from "./patterns/Pattern";
|
|
21
|
-
import
|
|
12
|
+
import Recursive from "./patterns/Recursive";
|
|
13
|
+
import Reference from "./patterns/Reference";
|
|
22
14
|
import TextSuggester from "./TextSuggester";
|
|
23
15
|
import Visitor from "./ast/Visitor";
|
|
24
16
|
|
|
25
17
|
export {
|
|
26
18
|
Node,
|
|
27
|
-
CompositeNode,
|
|
28
|
-
ValueNode,
|
|
29
19
|
Cursor,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
AnyOfThese,
|
|
20
|
+
Regex,
|
|
21
|
+
And,
|
|
33
22
|
Literal,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
RepeatValue,
|
|
38
|
-
ValuePattern,
|
|
39
|
-
AndComposite,
|
|
40
|
-
CompositePattern,
|
|
41
|
-
OptionalComposite,
|
|
42
|
-
OrComposite,
|
|
43
|
-
RepeatComposite,
|
|
23
|
+
Not,
|
|
24
|
+
Or,
|
|
25
|
+
Repeat,
|
|
44
26
|
ParseError,
|
|
45
27
|
Pattern,
|
|
46
|
-
|
|
28
|
+
Recursive,
|
|
29
|
+
Reference,
|
|
47
30
|
TextSuggester,
|
|
48
31
|
Visitor,
|
|
32
|
+
LookAhead,
|
|
49
33
|
};
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import ParseError from "../patterns/ParseError";
|
|
2
|
+
import Cursor from "../Cursor";
|
|
3
|
+
import Pattern from "./Pattern";
|
|
4
|
+
import Node from "../ast/Node";
|
|
5
|
+
|
|
6
|
+
export default class And extends Pattern {
|
|
7
|
+
public onPatternIndex: number = 0;
|
|
8
|
+
public nodes: (Node | null)[] = [];
|
|
9
|
+
public node: Node | null = null;
|
|
10
|
+
public cursor: Cursor | null = null;
|
|
11
|
+
public mark: number = 0;
|
|
12
|
+
|
|
13
|
+
constructor(name: string, patterns: Pattern[], isOptional = false) {
|
|
14
|
+
super("and", name, patterns, isOptional);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
parse(cursor: Cursor) {
|
|
18
|
+
this.resetState(cursor);
|
|
19
|
+
this.tryToParse();
|
|
20
|
+
|
|
21
|
+
return this.node;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
clone(name?: string, isOptional?: boolean) {
|
|
25
|
+
if (name == null) {
|
|
26
|
+
name = this.name;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (isOptional == null){
|
|
30
|
+
isOptional = this._isOptional;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return new And(name, this._children, isOptional);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getTokens() {
|
|
37
|
+
let tokens: string[] = [];
|
|
38
|
+
|
|
39
|
+
for (let x = 0; x < this._children.length; x++) {
|
|
40
|
+
const child = this._children[x];
|
|
41
|
+
|
|
42
|
+
if (child.isOptional) {
|
|
43
|
+
tokens = tokens.concat(child.getTokens());
|
|
44
|
+
} else {
|
|
45
|
+
tokens = tokens.concat(child.getTokens());
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return tokens;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private resetState(cursor: Cursor) {
|
|
54
|
+
this.onPatternIndex = 0;
|
|
55
|
+
this.nodes = [];
|
|
56
|
+
this.node = null;
|
|
57
|
+
this.cursor = cursor;
|
|
58
|
+
this.mark = this.cursor.mark();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private tryToParse() {
|
|
62
|
+
const cursor = this.safelyGetCursor();
|
|
63
|
+
|
|
64
|
+
while (true) {
|
|
65
|
+
const pattern = this._children[this.onPatternIndex];
|
|
66
|
+
const node = pattern.parse(cursor);
|
|
67
|
+
|
|
68
|
+
if (cursor.hasUnresolvedError()) {
|
|
69
|
+
this.processError();
|
|
70
|
+
break;
|
|
71
|
+
} else {
|
|
72
|
+
this.nodes.push(node);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!this.shouldProceed()) {
|
|
76
|
+
this.processResult();
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private safelyGetCursor() {
|
|
83
|
+
const cursor = this.cursor;
|
|
84
|
+
|
|
85
|
+
if (cursor == null) {
|
|
86
|
+
throw new Error("Couldn't find cursor.");
|
|
87
|
+
}
|
|
88
|
+
return cursor;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private processResult() {
|
|
92
|
+
const cursor = this.safelyGetCursor();
|
|
93
|
+
|
|
94
|
+
if (cursor.hasUnresolvedError()) {
|
|
95
|
+
this.processError();
|
|
96
|
+
} else {
|
|
97
|
+
this.processSuccess();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private processError() {
|
|
102
|
+
const cursor = this.safelyGetCursor();
|
|
103
|
+
|
|
104
|
+
if (this.isOptional) {
|
|
105
|
+
cursor.moveToMark(this.mark);
|
|
106
|
+
cursor.resolveError();
|
|
107
|
+
}
|
|
108
|
+
this.node = null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private shouldProceed() {
|
|
112
|
+
const cursor = this.safelyGetCursor();
|
|
113
|
+
|
|
114
|
+
if (this.hasMorePatterns()) {
|
|
115
|
+
const lastNode = this.nodes[this.nodes.length - 1];
|
|
116
|
+
const wasOptional = lastNode == null;
|
|
117
|
+
|
|
118
|
+
if (cursor.hasNext()) {
|
|
119
|
+
if (!wasOptional) {
|
|
120
|
+
cursor.next();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.onPatternIndex++;
|
|
124
|
+
return true;
|
|
125
|
+
} else if (wasOptional) {
|
|
126
|
+
this.onPatternIndex++;
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.assertRestOfPatternsAreOptional();
|
|
131
|
+
return false;
|
|
132
|
+
} else {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private hasMorePatterns() {
|
|
138
|
+
return this.onPatternIndex + 1 < this._children.length;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private assertRestOfPatternsAreOptional() {
|
|
142
|
+
const cursor = this.safelyGetCursor();
|
|
143
|
+
const areTheRestOptional = this.areTheRemainingPatternsOptional();
|
|
144
|
+
|
|
145
|
+
if (!areTheRestOptional) {
|
|
146
|
+
const parseError = new ParseError(
|
|
147
|
+
`Could not match ${this.name} before string ran out.`,
|
|
148
|
+
this.onPatternIndex,
|
|
149
|
+
this
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
cursor.throwError(parseError);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private areTheRemainingPatternsOptional() {
|
|
157
|
+
return this.children
|
|
158
|
+
.slice(this.onPatternIndex + 1)
|
|
159
|
+
.map((p) => p.isOptional)
|
|
160
|
+
.every((r) => r);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private processSuccess() {
|
|
164
|
+
const cursor = this.safelyGetCursor();
|
|
165
|
+
const nodes = this.nodes.filter((node) => node != null) as Node[];
|
|
166
|
+
this.nodes = nodes;
|
|
167
|
+
|
|
168
|
+
const lastNode = nodes[this.nodes.length - 1];
|
|
169
|
+
const startIndex = this.mark;
|
|
170
|
+
const endIndex = lastNode.endIndex;
|
|
171
|
+
const value = nodes.map((node) => node.value).join("");
|
|
172
|
+
|
|
173
|
+
this.node = new Node("and", this.name, startIndex, endIndex, nodes, value);
|
|
174
|
+
|
|
175
|
+
cursor.index = this.node.endIndex;
|
|
176
|
+
cursor.addMatch(this, this.node);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import ParseError from "./ParseError";
|
|
2
|
+
import Node from "../ast/Node";
|
|
3
|
+
import Pattern from "./Pattern";
|
|
4
|
+
import Cursor from "../Cursor";
|
|
5
|
+
|
|
6
|
+
export default class Literal extends Pattern {
|
|
7
|
+
public literal: string;
|
|
8
|
+
public node: Node | null = null;
|
|
9
|
+
public cursor!: Cursor;
|
|
10
|
+
public mark: number = 0;
|
|
11
|
+
public substring: string = "";
|
|
12
|
+
|
|
13
|
+
constructor(name: string, literal: string, isOptional = false) {
|
|
14
|
+
super("literal", name, [], isOptional);
|
|
15
|
+
this.literal = literal;
|
|
16
|
+
this.assertArguments();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
parse(cursor: Cursor) {
|
|
20
|
+
this.resetState(cursor);
|
|
21
|
+
this.tryToParse();
|
|
22
|
+
|
|
23
|
+
return this.node;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
clone(name?: string, isOptional?: boolean) {
|
|
27
|
+
if (name == null) {
|
|
28
|
+
name = this.name;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isOptional == null) {
|
|
32
|
+
isOptional = this._isOptional;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return new Literal(name, this.literal, isOptional);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getTokens() {
|
|
39
|
+
return [this.literal];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private assertArguments() {
|
|
43
|
+
if (this.literal.length < 1) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
"Invalid Arguments: The `literal` argument needs to be at least one character long."
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private resetState(cursor: Cursor) {
|
|
51
|
+
this.cursor = cursor;
|
|
52
|
+
this.mark = this.cursor.mark();
|
|
53
|
+
this.substring = this.cursor.text.substring(
|
|
54
|
+
this.mark,
|
|
55
|
+
this.mark + this.literal.length
|
|
56
|
+
);
|
|
57
|
+
this.node = null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private tryToParse() {
|
|
61
|
+
if (this.substring === this.literal) {
|
|
62
|
+
this.processResult();
|
|
63
|
+
} else {
|
|
64
|
+
this.processError();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private processError() {
|
|
69
|
+
this.node = null;
|
|
70
|
+
|
|
71
|
+
if (!this._isOptional) {
|
|
72
|
+
const message = `ParseError: Expected '${this.literal}' but found '${this.substring}'.`;
|
|
73
|
+
const parseError = new ParseError(message, this.cursor.getIndex(), this);
|
|
74
|
+
this.cursor.throwError(parseError);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private processResult() {
|
|
79
|
+
this.node = new Node(
|
|
80
|
+
"literal",
|
|
81
|
+
this.name,
|
|
82
|
+
this.mark,
|
|
83
|
+
this.mark + this.literal.length - 1,
|
|
84
|
+
[],
|
|
85
|
+
this.substring
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
this.cursor.index = this.node.endIndex;
|
|
89
|
+
this.cursor.addMatch(this, this.node);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import Cursor from "../Cursor";
|
|
2
|
+
import ParseError from "./ParseError";
|
|
3
|
+
import Pattern from "./Pattern";
|
|
4
|
+
|
|
5
|
+
export default class LookAhead extends Pattern {
|
|
6
|
+
constructor(pattern: Pattern) {
|
|
7
|
+
super("look-ahead", "look-ahead", [pattern]);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
parse(cursor: Cursor) {
|
|
11
|
+
const mark = cursor.mark();
|
|
12
|
+
const node = this.children[0].parse(cursor);
|
|
13
|
+
|
|
14
|
+
if (cursor.hasUnresolvedError() || node == null) {
|
|
15
|
+
cursor.resolveError();
|
|
16
|
+
cursor.throwError(
|
|
17
|
+
new ParseError("Couldn't find look ahead pattern.", mark, this.children[0])
|
|
18
|
+
);
|
|
19
|
+
cursor.moveToMark(mark);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
clone() {
|
|
26
|
+
return new LookAhead(this.children[0].clone());
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getTokens() {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import Pattern from "./Pattern";
|
|
2
|
+
import ParseError from "./ParseError";
|
|
3
|
+
import Cursor from "../Cursor";
|
|
4
|
+
|
|
5
|
+
export default class Not extends Pattern {
|
|
6
|
+
public cursor!: Cursor;
|
|
7
|
+
public mark: number = 0;
|
|
8
|
+
|
|
9
|
+
constructor(pattern: Pattern) {
|
|
10
|
+
super("not", `not-${pattern.name}`, [pattern]);
|
|
11
|
+
this._isOptional = true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
parse(cursor: Cursor) {
|
|
15
|
+
this.cursor = cursor;
|
|
16
|
+
this.mark = cursor.mark();
|
|
17
|
+
this.tryToParse();
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private tryToParse() {
|
|
22
|
+
const mark = this.cursor.mark();
|
|
23
|
+
this.children[0].parse(this.cursor);
|
|
24
|
+
|
|
25
|
+
if (this.cursor.hasUnresolvedError()) {
|
|
26
|
+
this.cursor.resolveError();
|
|
27
|
+
this.cursor.moveToMark(mark);
|
|
28
|
+
} else {
|
|
29
|
+
this.cursor.moveToMark(mark);
|
|
30
|
+
const parseError = new ParseError(
|
|
31
|
+
`Match invalid pattern: ${this.children[0].name}.`,
|
|
32
|
+
this.mark,
|
|
33
|
+
this
|
|
34
|
+
);
|
|
35
|
+
this.cursor.throwError(parseError);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
clone(name?: string) {
|
|
40
|
+
if (name == null) {
|
|
41
|
+
name = this.name;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return new Not(this.children[0]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getTokens() {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|