clarity-pattern-parser 4.0.3 → 5.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 +176 -1
- package/TODO.md +22 -2
- package/dist/ast/Node.d.ts +43 -11
- package/dist/ast/Visitor.d.ts +31 -31
- package/dist/index.browser.js +1248 -1495
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +12 -17
- package/dist/index.esm.js +1218 -1460
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1217 -1464
- package/dist/index.js.map +1 -1
- package/dist/patterns/And.d.ts +37 -24
- package/dist/patterns/Cursor.d.ts +35 -0
- package/dist/patterns/CursorHistory.d.ts +30 -0
- package/dist/patterns/Literal.d.ts +36 -19
- package/dist/patterns/Not.d.ts +26 -11
- package/dist/patterns/Or.d.ts +31 -22
- package/dist/patterns/ParseError.d.ts +6 -8
- package/dist/patterns/ParseResult.d.ts +6 -0
- package/dist/patterns/Pattern.d.ts +17 -26
- package/dist/patterns/Reference.d.ts +31 -12
- package/dist/patterns/Regex.d.ts +42 -21
- package/dist/patterns/Repeat.d.ts +38 -20
- package/dist/patterns/clonePatterns.d.ts +2 -0
- package/dist/patterns/filterOutNull.d.ts +2 -0
- package/dist/patterns/findPattern.d.ts +2 -0
- package/dist/patterns/getNextPattern.d.ts +2 -0
- package/jest.config.js +2 -1
- package/package.json +4 -5
- package/rollup.config.js +1 -1
- package/src/ast/Node.test.ts +254 -0
- package/src/ast/Node.ts +171 -23
- package/src/index.ts +11 -24
- package/src/intellisense/AutoComplete.test.ts +72 -0
- package/src/intellisense/AutoComplete.ts +146 -0
- package/src/intellisense/Suggestion.ts +13 -0
- package/src/intellisense/SuggestionOption.ts +4 -0
- package/src/{tests/cssPatterns → intellisense/css}/cssValue.ts +1 -1
- package/src/{tests/cssPatterns → intellisense/css}/divider.ts +2 -1
- package/src/intellisense/css/hex.ts +6 -0
- package/src/{tests/cssPatterns → intellisense/css}/method.ts +8 -9
- package/src/intellisense/css/name.ts +5 -0
- package/src/{tests/javascriptPatterns → intellisense/css}/number.ts +3 -3
- package/src/intellisense/css/spaces.ts +6 -0
- package/src/intellisense/css/unit.ts +10 -0
- package/src/{tests/cssPatterns → intellisense/css}/value.ts +1 -1
- package/src/{tests/cssPatterns → intellisense/css}/values.ts +1 -1
- package/src/intellisense/javascript/Javascript.test.ts +203 -0
- package/src/intellisense/javascript/arrayLiteral.ts +25 -0
- package/src/intellisense/javascript/deleteStatement.ts +14 -0
- package/src/intellisense/javascript/escapedCharacter.ts +50 -0
- package/src/intellisense/javascript/exponent.ts +26 -0
- package/src/intellisense/javascript/expression.ts +87 -0
- package/src/intellisense/javascript/expressionStatement.ts +29 -0
- package/src/intellisense/javascript/fraction.ts +13 -0
- package/src/intellisense/javascript/infixOperator.ts +36 -0
- package/src/intellisense/javascript/integer.ts +7 -0
- package/src/intellisense/javascript/invocation.ts +28 -0
- package/src/intellisense/javascript/literal.ts +14 -0
- package/src/intellisense/javascript/name.ts +3 -0
- package/src/intellisense/javascript/numberLiteral.ts +10 -0
- package/src/intellisense/javascript/objectLiteral.ts +30 -0
- package/src/intellisense/javascript/optionalSpaces.ts +3 -0
- package/src/intellisense/javascript/parameters.ts +20 -0
- package/src/intellisense/javascript/prefixOperator.ts +13 -0
- package/src/intellisense/javascript/propertyAccess.ts +23 -0
- package/src/intellisense/javascript/stringLiteral.ts +28 -0
- package/src/patterns/And.test.ts +299 -0
- package/src/patterns/And.ts +222 -119
- package/src/patterns/Cursor.test.ts +93 -0
- package/src/patterns/Cursor.ts +130 -0
- package/src/patterns/CursorHistory.test.ts +54 -0
- package/src/patterns/CursorHistory.ts +95 -0
- package/src/patterns/Literal.test.ts +134 -0
- package/src/patterns/Literal.ts +151 -61
- package/src/patterns/Not.test.ts +88 -0
- package/src/patterns/Not.ts +74 -33
- package/src/patterns/Or.test.ts +105 -0
- package/src/patterns/Or.ts +106 -98
- package/src/patterns/ParseError.ts +3 -7
- package/src/patterns/ParseResult.ts +7 -0
- package/src/patterns/Pattern.ts +18 -150
- package/src/patterns/Reference.test.ts +104 -0
- package/src/patterns/Reference.ts +94 -94
- package/src/patterns/Regex.test.ts +101 -0
- package/src/patterns/Regex.ts +129 -60
- package/src/patterns/Repeat.test.ts +196 -0
- package/src/patterns/Repeat.ts +208 -104
- package/src/patterns/clonePatterns.ts +5 -0
- package/src/patterns/filterOutNull.ts +13 -0
- package/src/patterns/findPattern.ts +25 -0
- package/src/patterns/getNextPattern.test.ts +39 -0
- package/src/patterns/getNextPattern.ts +18 -0
- package/src/Cursor.ts +0 -141
- package/src/CursorHistory.ts +0 -146
- package/src/TextSuggester.ts +0 -317
- package/src/ast/Visitor.ts +0 -271
- package/src/patterns/LookAhead.ts +0 -32
- package/src/patterns/Recursive.ts +0 -92
- package/src/tests/And.test.ts +0 -180
- package/src/tests/ComplexExamples.test.ts +0 -86
- package/src/tests/CssPatterns.test.ts +0 -90
- package/src/tests/CursorHistory.test.ts +0 -107
- package/src/tests/Cusor.test.ts +0 -174
- package/src/tests/HtmlPatterns.test.ts +0 -34
- package/src/tests/Literal.test.ts +0 -79
- package/src/tests/LookAhead.test.ts +0 -44
- package/src/tests/Not.test.ts +0 -51
- package/src/tests/Or.test.ts +0 -113
- package/src/tests/Pattern.test.ts +0 -290
- package/src/tests/Recursive.test.ts +0 -64
- package/src/tests/Reference.test.ts +0 -16
- package/src/tests/Repeat.test.ts +0 -75
- package/src/tests/SpeedTest.test.ts +0 -31
- package/src/tests/TextSuggester.test.ts +0 -297
- package/src/tests/Visitor.test.ts +0 -331
- package/src/tests/cssPatterns/hex.ts +0 -5
- package/src/tests/cssPatterns/name.ts +0 -5
- package/src/tests/cssPatterns/number.ts +0 -8
- package/src/tests/cssPatterns/spaces.ts +0 -5
- package/src/tests/cssPatterns/unit.ts +0 -8
- package/src/tests/htmlPatterns/element.ts +0 -49
- package/src/tests/javascriptPatterns/boolean.ts +0 -10
- package/src/tests/javascriptPatterns/json.ts +0 -67
- package/src/tests/javascriptPatterns/name.ts +0 -5
- package/src/tests/javascriptPatterns/objectLiteral.ts +0 -40
- package/src/tests/javascriptPatterns/string.ts +0 -84
- package/src/tests/javascriptPatterns/unit.ts +0 -8
- package/src/tests/javascriptPatterns/whitespace.ts +0 -44
- package/src/tests/naturalLanguage/filter.ts +0 -37
- package/src/tests/patterns/sentence.ts +0 -37
- /package/src/{tests/cssPatterns → intellisense/css}/optionalSpaces.ts +0 -0
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { Node } from "../ast/Node";
|
|
2
|
+
import { Cursor } from "./Cursor";
|
|
3
|
+
import { Pattern } from "./Pattern";
|
|
4
|
+
import { findPattern } from "./findPattern";
|
|
5
|
+
import { getNextPattern } from "./getNextPattern";
|
|
6
|
+
|
|
7
|
+
export class Reference implements Pattern {
|
|
8
|
+
private _type: string;
|
|
9
|
+
private _name: string;
|
|
10
|
+
private _parent: Pattern | null;
|
|
11
|
+
private _isOptional: boolean;
|
|
12
|
+
private _pattern: Pattern | null;
|
|
13
|
+
private _children: Pattern[];
|
|
14
|
+
|
|
15
|
+
get type(): string {
|
|
16
|
+
return this._type;
|
|
17
|
+
}
|
|
4
18
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
super("reference", name, [], isOptional);
|
|
19
|
+
get name(): string {
|
|
20
|
+
return this._name;
|
|
8
21
|
}
|
|
9
22
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
while (node != null) {
|
|
13
|
-
if (node.parent == null) {
|
|
14
|
-
return node;
|
|
15
|
-
}
|
|
16
|
-
node = node.parent;
|
|
17
|
-
}
|
|
18
|
-
return node;
|
|
23
|
+
get isOptional(): boolean {
|
|
24
|
+
return this._isOptional;
|
|
19
25
|
}
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
27
|
+
get parent(): Pattern | null {
|
|
28
|
+
return this._parent;
|
|
29
|
+
}
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
set parent(pattern: Pattern | null) {
|
|
32
|
+
this._parent = pattern;
|
|
33
|
+
}
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
pattern != this &&
|
|
33
|
-
pattern.type != "reference"
|
|
34
|
-
) {
|
|
35
|
-
result = pattern;
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
return true;
|
|
39
|
-
});
|
|
35
|
+
get children(): Pattern[] {
|
|
36
|
+
return this._children
|
|
37
|
+
}
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
constructor(name: string, isOptional: boolean = false) {
|
|
40
|
+
this._type = "reference";
|
|
41
|
+
this._name = name;
|
|
42
|
+
this._parent = null;
|
|
43
|
+
this._isOptional = isOptional;
|
|
44
|
+
this._pattern = null;
|
|
45
|
+
this._children = [];
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
) {
|
|
48
|
-
for (let x = 0; x < pattern.children.length; x++) {
|
|
49
|
-
const p = pattern.children[x];
|
|
50
|
-
const continueWalking = this.walkTheTree(p, callback);
|
|
48
|
+
parseText(text: string) {
|
|
49
|
+
const cursor = new Cursor(text);
|
|
50
|
+
const ast = this.parse(cursor)
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
return {
|
|
53
|
+
ast,
|
|
54
|
+
cursor
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
parse(cursor: Cursor): Node | null {
|
|
59
|
+
return this._getPatternSafely().parse(cursor);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
clone(name = this._name, isOptional = this._isOptional): Pattern {
|
|
63
|
+
return new Reference(name, isOptional);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getTokens(): string[] {
|
|
67
|
+
return this._getPatternSafely().getTokens();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getNextTokens(_lastMatched: Pattern): string[] {
|
|
71
|
+
if (this.parent == null) {
|
|
72
|
+
return [];
|
|
55
73
|
}
|
|
56
74
|
|
|
57
|
-
return
|
|
75
|
+
return this.parent.getNextTokens(this);
|
|
58
76
|
}
|
|
59
77
|
|
|
60
|
-
|
|
61
|
-
|
|
78
|
+
getNextPattern(): Pattern | null {
|
|
79
|
+
return getNextPattern(this)
|
|
80
|
+
}
|
|
62
81
|
|
|
63
|
-
|
|
64
|
-
|
|
82
|
+
findPattern(_isMatch: (p: Pattern)=>boolean): Pattern | null{
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
65
85
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
86
|
+
private _getPatternSafely(): Pattern {
|
|
87
|
+
if (this._pattern === null) {
|
|
88
|
+
const pattern = this._findPattern();
|
|
69
89
|
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
cursor.moveToMark(mark);
|
|
90
|
+
if (pattern === null) {
|
|
91
|
+
throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
|
|
73
92
|
}
|
|
74
93
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (this._isOptional) {
|
|
78
|
-
cursor.moveToMark(mark);
|
|
79
|
-
} else {
|
|
80
|
-
cursor.throwError(
|
|
81
|
-
new ParserError(
|
|
82
|
-
`Couldn't find reference pattern to parse, with the name ${this.name}.`,
|
|
83
|
-
cursor.index,
|
|
84
|
-
this as Pattern
|
|
85
|
-
)
|
|
86
|
-
);
|
|
87
|
-
}
|
|
94
|
+
const clonedPattern = pattern.clone(this._name, this._isOptional);
|
|
95
|
+
clonedPattern.parent = this;
|
|
88
96
|
|
|
89
|
-
|
|
97
|
+
this._pattern = clonedPattern;
|
|
98
|
+
this._children = [this._pattern];
|
|
90
99
|
}
|
|
91
|
-
}
|
|
92
100
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
name = this.name;
|
|
96
|
-
}
|
|
101
|
+
return this._pattern;
|
|
102
|
+
}
|
|
97
103
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
104
|
+
private _findPattern(): Pattern | null {
|
|
105
|
+
const root = this._getRoot();
|
|
101
106
|
|
|
102
|
-
return
|
|
107
|
+
return findPattern(root, (pattern: Pattern) => {
|
|
108
|
+
return pattern.name === this._name && pattern.type !== "reference";
|
|
109
|
+
});
|
|
103
110
|
}
|
|
104
111
|
|
|
105
|
-
private
|
|
106
|
-
let
|
|
107
|
-
const hasNoPattern = pattern == null;
|
|
112
|
+
private _getRoot(): Pattern {
|
|
113
|
+
let node: Pattern = this;
|
|
108
114
|
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
if (reference == null) {
|
|
112
|
-
throw new Error(
|
|
113
|
-
`Couldn't find reference pattern, with the name ${this.name}.`
|
|
114
|
-
);
|
|
115
|
-
}
|
|
115
|
+
while (true) {
|
|
116
|
+
const parent = node.parent;
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
if (parent == null) {
|
|
119
|
+
break;
|
|
120
|
+
} else {
|
|
121
|
+
node = parent
|
|
122
|
+
}
|
|
119
123
|
}
|
|
120
124
|
|
|
121
|
-
return
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
getTokens() {
|
|
125
|
-
return this.safelyGetPattern().getTokens();
|
|
125
|
+
return node;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Cursor } from "./Cursor";
|
|
2
|
+
import { Regex } from "./Regex";
|
|
3
|
+
import { Node } from "../ast/Node"
|
|
4
|
+
import { And } from "./And";
|
|
5
|
+
import { Literal } from "./Literal";
|
|
6
|
+
|
|
7
|
+
describe("Regex", () => {
|
|
8
|
+
test("Empty String", () => {
|
|
9
|
+
expect(() => new Regex("empty", "")).toThrowError()
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("Starts With ^", () => {
|
|
13
|
+
expect(() => new Regex("carrot", "^")).toThrowError()
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("Ends With $", () => {
|
|
17
|
+
expect(() => new Regex("money", ".$")).toThrowError()
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("Successful Parse", () => {
|
|
21
|
+
const number = new Regex("number", "\\d");
|
|
22
|
+
const cursor = new Cursor("1");
|
|
23
|
+
const result = number.parse(cursor);
|
|
24
|
+
const expected = new Node("regex", "number", 0, 0, [], "1");
|
|
25
|
+
|
|
26
|
+
expect(result).toEqual(expected);
|
|
27
|
+
expect(cursor.hasError).toBeFalsy()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test("Failed Parse", () => {
|
|
31
|
+
const number = new Regex("number", "\\d");
|
|
32
|
+
const cursor = new Cursor("F");
|
|
33
|
+
const result = number.parse(cursor);
|
|
34
|
+
|
|
35
|
+
expect(result).toBeNull();
|
|
36
|
+
expect(cursor.hasError).toBeTruthy()
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
test("Get Tokens", () => {
|
|
41
|
+
const parent = new And("parent", [
|
|
42
|
+
new Regex("a", "A"),
|
|
43
|
+
new Regex("b", "B")
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
const a = parent.children[0] as Regex;
|
|
47
|
+
const b = parent.children[1] as Regex;
|
|
48
|
+
|
|
49
|
+
a.setTokens(["A"]);
|
|
50
|
+
b.setTokens(["B"]);
|
|
51
|
+
|
|
52
|
+
let tokens = a.getTokens();
|
|
53
|
+
let expectedTokens = ["A"];
|
|
54
|
+
|
|
55
|
+
expect(tokens).toEqual(expectedTokens);
|
|
56
|
+
|
|
57
|
+
a.enableContextualTokenAggregation();
|
|
58
|
+
|
|
59
|
+
tokens = a.getTokens();
|
|
60
|
+
expectedTokens = ["AB"];
|
|
61
|
+
|
|
62
|
+
expect(tokens).toEqual(expectedTokens);
|
|
63
|
+
|
|
64
|
+
a.disableContextualTokenAggregation();
|
|
65
|
+
|
|
66
|
+
tokens = a.getTokens();
|
|
67
|
+
expectedTokens = ["A"];
|
|
68
|
+
|
|
69
|
+
expect(tokens).toEqual(expectedTokens);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("Get Next Tokens", () => {
|
|
73
|
+
const regex = new Regex("a", "A");
|
|
74
|
+
const tokens = regex.getNextTokens(new Literal("bogus", "bogus"));
|
|
75
|
+
const expected: string[] = [];
|
|
76
|
+
|
|
77
|
+
expect(tokens).toEqual(expected)
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("Get Next Pattern", () => {
|
|
81
|
+
const regex = new Regex("a", "A");
|
|
82
|
+
const nextPattern = regex.getNextPattern();
|
|
83
|
+
|
|
84
|
+
expect(nextPattern).toBeNull()
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("Properties", () => {
|
|
88
|
+
const regex = new Regex("a", "A");
|
|
89
|
+
|
|
90
|
+
expect(regex.type).toBe("regex");
|
|
91
|
+
expect(regex.name).toBe("a");
|
|
92
|
+
expect(regex.parent).toBeNull();
|
|
93
|
+
expect(regex.children).toEqual([]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("Parse Text", () => {
|
|
97
|
+
const regex = new Regex("a", "A");
|
|
98
|
+
const { ast: result } = regex.parseText("B");
|
|
99
|
+
expect(result).toBeNull();
|
|
100
|
+
});
|
|
101
|
+
});
|
package/src/patterns/Regex.ts
CHANGED
|
@@ -1,123 +1,192 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
private
|
|
8
|
-
private
|
|
9
|
-
private
|
|
10
|
-
private
|
|
11
|
-
private
|
|
1
|
+
import { Node } from "../ast/Node";
|
|
2
|
+
import { Pattern } from "./Pattern";
|
|
3
|
+
import { Cursor } from "./Cursor";
|
|
4
|
+
import { getNextPattern } from "./getNextPattern";
|
|
5
|
+
|
|
6
|
+
export class Regex implements Pattern {
|
|
7
|
+
private _type: string;
|
|
8
|
+
private _name: string;
|
|
9
|
+
private _isOptional: boolean;
|
|
10
|
+
private _parent: Pattern | null;
|
|
11
|
+
private _originalRegexString: string;
|
|
12
|
+
private _regex: RegExp;
|
|
13
|
+
private _node: Node | null = null;
|
|
14
|
+
private _cursor: Cursor | null = null;
|
|
15
|
+
private _substring: string = "";
|
|
16
|
+
private _tokens: string[] = [];
|
|
17
|
+
private _hasContextualTokenAggregation = false;
|
|
18
|
+
private _isRetrievingContextualTokens: boolean = false;
|
|
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 [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get isOptional(): boolean {
|
|
41
|
+
return this._isOptional;
|
|
42
|
+
}
|
|
12
43
|
|
|
13
44
|
constructor(name: string, regex: string, isOptional = false) {
|
|
14
|
-
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
45
|
+
this._type = "regex"
|
|
46
|
+
this._name = name;
|
|
47
|
+
this._isOptional = isOptional;
|
|
48
|
+
this._parent = null;
|
|
49
|
+
this._originalRegexString = regex;
|
|
50
|
+
this._regex = new RegExp(`^${regex}`, "g");
|
|
17
51
|
this.assertArguments();
|
|
18
52
|
}
|
|
19
53
|
|
|
20
54
|
private assertArguments() {
|
|
21
|
-
if (this.
|
|
55
|
+
if (this._originalRegexString.length < 1) {
|
|
22
56
|
throw new Error(
|
|
23
57
|
"Invalid Arguments: The regex string argument needs to be at least one character long."
|
|
24
58
|
);
|
|
25
59
|
}
|
|
26
60
|
|
|
27
|
-
if (this.
|
|
61
|
+
if (this._originalRegexString.charAt(0) === "^") {
|
|
28
62
|
throw new Error(
|
|
29
63
|
"Invalid Arguments: The regex string cannot start with a '^' because it is expected to be in the middle of a string."
|
|
30
64
|
);
|
|
31
65
|
}
|
|
32
66
|
|
|
33
|
-
if (this.
|
|
67
|
+
if (this._originalRegexString.charAt(this._originalRegexString.length - 1) === "$") {
|
|
34
68
|
throw new Error(
|
|
35
69
|
"Invalid Arguments: The regex string cannot end with a '$' because it is expected to be in the middle of a string."
|
|
36
70
|
);
|
|
37
71
|
}
|
|
38
72
|
}
|
|
39
73
|
|
|
74
|
+
parseText(text: string) {
|
|
75
|
+
const cursor = new Cursor(text);
|
|
76
|
+
const ast = this.parse(cursor)
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
ast,
|
|
80
|
+
cursor
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
40
84
|
parse(cursor: Cursor) {
|
|
41
85
|
this.resetState(cursor);
|
|
42
|
-
this.tryToParse();
|
|
86
|
+
this.tryToParse(cursor);
|
|
43
87
|
|
|
44
|
-
return this.
|
|
88
|
+
return this._node;
|
|
45
89
|
}
|
|
46
90
|
|
|
47
91
|
private resetState(cursor: Cursor) {
|
|
48
|
-
this.
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
92
|
+
this._cursor = cursor;
|
|
93
|
+
this._regex.lastIndex = 0;
|
|
94
|
+
this._substring = this._cursor.text.substr(this._cursor.index);
|
|
95
|
+
this._node = null;
|
|
52
96
|
}
|
|
53
97
|
|
|
54
|
-
private tryToParse() {
|
|
55
|
-
const result = this.
|
|
98
|
+
private tryToParse(cursor: Cursor) {
|
|
99
|
+
const result = this._regex.exec(this._substring);
|
|
56
100
|
|
|
57
101
|
if (result != null && result.index === 0) {
|
|
58
|
-
this.processResult(result);
|
|
102
|
+
this.processResult(cursor, result);
|
|
59
103
|
} else {
|
|
60
|
-
this.processError();
|
|
104
|
+
this.processError(cursor);
|
|
61
105
|
}
|
|
62
106
|
}
|
|
63
107
|
|
|
64
|
-
private processResult(result: RegExpExecArray) {
|
|
65
|
-
const
|
|
66
|
-
const currentIndex = cursor.getIndex();
|
|
108
|
+
private processResult(cursor: Cursor, result: RegExpExecArray) {
|
|
109
|
+
const currentIndex = cursor.index;
|
|
67
110
|
const newIndex = currentIndex + result[0].length - 1;
|
|
68
111
|
|
|
69
|
-
this.
|
|
112
|
+
this._node = new Node(
|
|
70
113
|
"regex",
|
|
71
|
-
this.
|
|
114
|
+
this._name,
|
|
72
115
|
currentIndex,
|
|
73
116
|
newIndex,
|
|
74
117
|
[],
|
|
75
118
|
result[0]
|
|
76
119
|
);
|
|
77
120
|
|
|
78
|
-
cursor.
|
|
79
|
-
cursor.
|
|
121
|
+
cursor.moveTo(newIndex);
|
|
122
|
+
cursor.recordMatch(this, this._node);
|
|
80
123
|
}
|
|
81
124
|
|
|
82
|
-
private processError() {
|
|
83
|
-
const cursor = this.safelyGetCursor();
|
|
84
|
-
|
|
125
|
+
private processError(cursor: Cursor) {
|
|
85
126
|
if (!this._isOptional) {
|
|
86
|
-
|
|
87
|
-
const parseError = new ParseError(message, cursor.getIndex(), this);
|
|
88
|
-
|
|
89
|
-
cursor.throwError(parseError);
|
|
127
|
+
cursor.recordErrorAt(cursor.index, this);
|
|
90
128
|
}
|
|
91
129
|
|
|
92
|
-
this.
|
|
130
|
+
this._node = null;
|
|
93
131
|
}
|
|
94
132
|
|
|
95
|
-
|
|
96
|
-
const
|
|
133
|
+
clone(name = this._name, isOptional = this._isOptional) {
|
|
134
|
+
const pattern = new Regex(name, this._originalRegexString, isOptional);
|
|
135
|
+
pattern._tokens = this._tokens.slice();
|
|
136
|
+
pattern._hasContextualTokenAggregation =
|
|
137
|
+
this._hasContextualTokenAggregation;
|
|
97
138
|
|
|
98
|
-
|
|
99
|
-
throw new Error("Couldn't find cursor.");
|
|
100
|
-
}
|
|
101
|
-
return cursor;
|
|
139
|
+
return pattern;
|
|
102
140
|
}
|
|
103
141
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
142
|
+
getTokens() {
|
|
143
|
+
const parent = this._parent;
|
|
144
|
+
|
|
145
|
+
if (this._hasContextualTokenAggregation &&
|
|
146
|
+
parent != null &&
|
|
147
|
+
!this._isRetrievingContextualTokens
|
|
148
|
+
) {
|
|
149
|
+
this._isRetrievingContextualTokens = true;
|
|
150
|
+
|
|
151
|
+
const tokens = this._tokens;
|
|
152
|
+
const aggregateTokens: string[] = [];
|
|
153
|
+
const nextTokens = parent.getNextTokens(this);
|
|
154
|
+
|
|
155
|
+
for (let nextToken of nextTokens) {
|
|
156
|
+
for (let token of tokens) {
|
|
157
|
+
aggregateTokens.push(token + nextToken);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this._isRetrievingContextualTokens = false
|
|
162
|
+
return aggregateTokens;
|
|
107
163
|
}
|
|
108
164
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
165
|
+
return this._tokens;
|
|
166
|
+
}
|
|
112
167
|
|
|
113
|
-
|
|
168
|
+
getNextTokens(_reference: Pattern): string[] {
|
|
169
|
+
return [];
|
|
114
170
|
}
|
|
115
171
|
|
|
116
|
-
|
|
117
|
-
return this
|
|
172
|
+
getNextPattern(): Pattern | null {
|
|
173
|
+
return getNextPattern(this)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
findPattern(_isMatch: (p: Pattern)=>boolean): Pattern | null{
|
|
177
|
+
return null;
|
|
118
178
|
}
|
|
119
179
|
|
|
120
|
-
|
|
121
|
-
|
|
180
|
+
setTokens(tokens: string[]) {
|
|
181
|
+
this._tokens = tokens;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
enableContextualTokenAggregation() {
|
|
185
|
+
this._hasContextualTokenAggregation = true;
|
|
122
186
|
}
|
|
123
|
-
|
|
187
|
+
|
|
188
|
+
disableContextualTokenAggregation() {
|
|
189
|
+
this._hasContextualTokenAggregation = false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
}
|