clarity-pattern-parser 4.0.3 → 6.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 +466 -1
- package/TODO.md +76 -2
- package/dist/ast/Node.d.ts +49 -11
- package/dist/ast/Visitor.d.ts +31 -31
- package/dist/index.browser.js +1513 -1495
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +17 -17
- package/dist/index.esm.js +1480 -1459
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1481 -1463
- package/dist/index.js.map +1 -1
- package/dist/intellisense/AutoComplete.d.ts +28 -0
- package/dist/intellisense/Suggestion.d.ts +11 -0
- package/dist/intellisense/SuggestionOption.d.ts +4 -0
- package/dist/patterns/And.d.ts +37 -24
- package/dist/patterns/Cursor.d.ts +37 -0
- package/dist/patterns/CursorHistory.d.ts +30 -0
- package/dist/patterns/Literal.d.ts +35 -19
- package/dist/patterns/Not.d.ts +29 -11
- package/dist/patterns/Or.d.ts +33 -22
- package/dist/patterns/ParseError.d.ts +6 -8
- package/dist/patterns/ParseResult.d.ts +6 -0
- package/dist/patterns/Pattern.d.ts +20 -26
- package/dist/patterns/Reference.d.ts +34 -12
- package/dist/patterns/Regex.d.ts +41 -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 +364 -0
- package/src/ast/Node.ts +237 -23
- package/src/index.ts +25 -27
- package/src/intellisense/AutoComplete.test.ts +150 -0
- package/src/intellisense/AutoComplete.ts +200 -0
- package/src/intellisense/Suggestion.ts +12 -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 +49 -0
- package/src/intellisense/javascript/exponent.ts +24 -0
- package/src/intellisense/javascript/expression.ts +87 -0
- package/src/intellisense/javascript/expressionStatement.ts +29 -0
- package/src/intellisense/javascript/fraction.ts +11 -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 +310 -0
- package/src/patterns/And.ts +244 -119
- package/src/patterns/Cursor.test.ts +93 -0
- package/src/patterns/Cursor.ts +133 -0
- package/src/patterns/CursorHistory.test.ts +54 -0
- package/src/patterns/CursorHistory.ts +95 -0
- package/src/patterns/Literal.test.ts +166 -0
- package/src/patterns/Literal.ts +141 -62
- package/src/patterns/Not.test.ts +168 -0
- package/src/patterns/Not.ts +113 -32
- package/src/patterns/Or.test.ts +209 -0
- package/src/patterns/Or.ts +128 -97
- package/src/patterns/ParseError.ts +3 -7
- package/src/patterns/ParseResult.ts +7 -0
- package/src/patterns/Pattern.ts +21 -150
- package/src/patterns/Reference.test.ts +193 -0
- package/src/patterns/Reference.ts +114 -88
- package/src/patterns/Regex.test.ts +133 -0
- package/src/patterns/Regex.ts +117 -60
- package/src/patterns/Repeat.test.ts +218 -0
- package/src/patterns/Repeat.ts +220 -103
- package/src/patterns/clonePatterns.ts +5 -0
- package/src/patterns/filterOutNull.ts +13 -0
- package/src/patterns/findPattern.ts +25 -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
package/src/Cursor.ts
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import Pattern from "./patterns/Pattern";
|
|
2
|
-
import Node from "./ast/Node";
|
|
3
|
-
import CursorHistory from "./CursorHistory";
|
|
4
|
-
import ParseError from "./patterns/ParseError";
|
|
5
|
-
|
|
6
|
-
export default class Cursor {
|
|
7
|
-
public text: string;
|
|
8
|
-
public index: number;
|
|
9
|
-
public length: number;
|
|
10
|
-
public history: CursorHistory;
|
|
11
|
-
public isInErrorState: boolean;
|
|
12
|
-
|
|
13
|
-
constructor(text: string) {
|
|
14
|
-
this.text = text;
|
|
15
|
-
this.assertValidity();
|
|
16
|
-
|
|
17
|
-
this.index = 0;
|
|
18
|
-
this.length = text.length;
|
|
19
|
-
this.history = new CursorHistory();
|
|
20
|
-
this.isInErrorState = false;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
assertValidity() {
|
|
24
|
-
if (this.isNullOrEmpty(this.text)) {
|
|
25
|
-
throw new Error(
|
|
26
|
-
"Illegal Argument: Cursor needs to have a string that has a length greater than 0."
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
startRecording() {
|
|
32
|
-
this.history.startRecording();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
stopRecording() {
|
|
36
|
-
this.history.stopRecording();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
get parseError() {
|
|
40
|
-
return this.history.getFurthestError();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
get lastMatch() {
|
|
44
|
-
return this.history.getFurthestMatch();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
throwError(parseError: ParseError) {
|
|
48
|
-
this.isInErrorState = true;
|
|
49
|
-
this.history.addError(parseError);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
addMatch(pattern: Pattern, astNode: Node) {
|
|
53
|
-
this.history.addMatch(pattern, astNode);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
resolveError() {
|
|
57
|
-
this.isInErrorState = false;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
hasUnresolvedError() {
|
|
61
|
-
return this.isInErrorState;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
isNullOrEmpty(value: string | null) {
|
|
65
|
-
return value == null || (typeof value === "string" && value.length === 0);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
hasNext() {
|
|
69
|
-
return this.index + 1 < this.text.length;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
hasPrevious() {
|
|
73
|
-
return this.index - 1 >= 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
next() {
|
|
77
|
-
if (this.hasNext()) {
|
|
78
|
-
this.index++;
|
|
79
|
-
} else {
|
|
80
|
-
throw new Error("Cursor: Out of Bounds Exception.");
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
previous() {
|
|
85
|
-
if (this.hasPrevious()) {
|
|
86
|
-
this.index--;
|
|
87
|
-
} else {
|
|
88
|
-
throw new Error("Cursor: Out of Bounds Exception.");
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
mark() {
|
|
93
|
-
return this.index;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
moveToMark(mark: number) {
|
|
97
|
-
this.index = mark;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
moveToBeginning() {
|
|
101
|
-
this.index = 0;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
moveToEnd() {
|
|
105
|
-
this.index = this.text.length - 1;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
getChar() {
|
|
109
|
-
return this.text.charAt(this.index);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
getIndex() {
|
|
113
|
-
return this.index;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
setIndex(index: number) {
|
|
117
|
-
if (typeof index === "number") {
|
|
118
|
-
if (index < 0 || index > this.lastIndex()) {
|
|
119
|
-
throw new Error("Cursor: Out of Bounds Exception.");
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
this.index = index;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
isAtBeginning() {
|
|
127
|
-
return this.index === 0;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
isAtEnd() {
|
|
131
|
-
return this.index === this.text.length - 1;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
lastIndex() {
|
|
135
|
-
return this.length - 1;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
didSuccessfullyParse() {
|
|
139
|
-
return !this.hasUnresolvedError() && this.isAtEnd();
|
|
140
|
-
}
|
|
141
|
-
}
|
package/src/CursorHistory.ts
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import Pattern from "./patterns/Pattern";
|
|
2
|
-
import Node from "./ast/Node";
|
|
3
|
-
import ParseError from "./patterns/ParseError";
|
|
4
|
-
|
|
5
|
-
export interface Match {
|
|
6
|
-
pattern: Pattern | null;
|
|
7
|
-
astNode: Node | null;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default class CursorHistory {
|
|
11
|
-
public isRecording: boolean;
|
|
12
|
-
public furthestMatch: Match;
|
|
13
|
-
public furthestError: ParseError | null;
|
|
14
|
-
public patterns: Pattern[];
|
|
15
|
-
public astNodes: Node[];
|
|
16
|
-
public errors: ParseError[];
|
|
17
|
-
|
|
18
|
-
constructor() {
|
|
19
|
-
this.isRecording = false;
|
|
20
|
-
|
|
21
|
-
this.furthestMatch = {
|
|
22
|
-
pattern: null,
|
|
23
|
-
astNode: null,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
this.furthestError = null;
|
|
27
|
-
|
|
28
|
-
this.patterns = [];
|
|
29
|
-
this.astNodes = [];
|
|
30
|
-
this.errors = [];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
addMatch(pattern: Pattern, astNode: Node) {
|
|
34
|
-
if (this.isRecording) {
|
|
35
|
-
this.patterns.push(pattern);
|
|
36
|
-
this.astNodes.push(astNode);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
this.furthestMatch.astNode == null ||
|
|
41
|
-
astNode.endIndex >= this.furthestMatch.astNode.endIndex
|
|
42
|
-
) {
|
|
43
|
-
this.furthestMatch.pattern = pattern;
|
|
44
|
-
this.furthestMatch.astNode = astNode;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
addError(error: ParseError) {
|
|
49
|
-
if (this.isRecording) {
|
|
50
|
-
this.errors.push(error);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (this.furthestError == null || error.index >= this.furthestError.index) {
|
|
54
|
-
this.furthestError = error;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
startRecording() {
|
|
59
|
-
this.isRecording = true;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
stopRecording() {
|
|
63
|
-
this.isRecording = false;
|
|
64
|
-
this.clear();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
clear() {
|
|
68
|
-
this.patterns.length = 0;
|
|
69
|
-
this.astNodes.length = 0;
|
|
70
|
-
this.errors.length = 0;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getFurthestError() {
|
|
74
|
-
return this.furthestError;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
getFurthestMatch() {
|
|
78
|
-
return this.furthestMatch;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
getLastMatch() {
|
|
82
|
-
if (this.isRecording) {
|
|
83
|
-
return {
|
|
84
|
-
pattern: this.patterns[this.patterns.length - 1] || null,
|
|
85
|
-
astNode: this.astNodes[this.astNodes.length - 1] || null,
|
|
86
|
-
} as Match;
|
|
87
|
-
} else {
|
|
88
|
-
return this.furthestMatch as Match;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
getLastError() {
|
|
93
|
-
return this.errors[this.errors.length - 1] || null;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
getAllParseStacks() {
|
|
97
|
-
const stacks = this.astNodes.reduce((acc: Node[][], node) => {
|
|
98
|
-
let container: Node[] = acc[acc.length - 1];
|
|
99
|
-
|
|
100
|
-
if (node.startIndex === 0) {
|
|
101
|
-
container = [];
|
|
102
|
-
acc.push(container);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
container.push(node);
|
|
106
|
-
|
|
107
|
-
return acc;
|
|
108
|
-
}, []);
|
|
109
|
-
|
|
110
|
-
// There are times when the matching will fail and hit again on the same node.
|
|
111
|
-
// This filters them out.
|
|
112
|
-
// We simply check to see if there is any overlap with the previous one,
|
|
113
|
-
// and if there is we don't add it. This is why we move backwards.
|
|
114
|
-
const cleanedStack = stacks.map((stack: Node[]) => {
|
|
115
|
-
const cleanedStack = [];
|
|
116
|
-
|
|
117
|
-
for (let x = stack.length - 1; x >= 0; x--) {
|
|
118
|
-
const currentNode = stack[x];
|
|
119
|
-
const previousNode = stack[x + 1];
|
|
120
|
-
|
|
121
|
-
if (previousNode == null) {
|
|
122
|
-
cleanedStack.unshift(currentNode);
|
|
123
|
-
} else {
|
|
124
|
-
const left = Math.max(
|
|
125
|
-
currentNode.startIndex,
|
|
126
|
-
previousNode.startIndex
|
|
127
|
-
);
|
|
128
|
-
const right = Math.min(currentNode.endIndex, previousNode.endIndex);
|
|
129
|
-
const isOverlapping = left <= right;
|
|
130
|
-
|
|
131
|
-
if (!isOverlapping) {
|
|
132
|
-
cleanedStack.unshift(currentNode);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return cleanedStack;
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
return cleanedStack;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
getLastParseStack(): Node[] {
|
|
143
|
-
const stacks = this.getAllParseStacks();
|
|
144
|
-
return stacks[stacks.length - 1] || [];
|
|
145
|
-
}
|
|
146
|
-
}
|
package/src/TextSuggester.ts
DELETED
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import Node from "./ast/Node";
|
|
2
|
-
import Cursor from "./Cursor";
|
|
3
|
-
import { Match } from "./CursorHistory";
|
|
4
|
-
import Pattern from "./patterns/Pattern";
|
|
5
|
-
|
|
6
|
-
export interface Token {
|
|
7
|
-
startIndex: number;
|
|
8
|
-
values: string[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface SuggestionError {
|
|
12
|
-
startIndex: number;
|
|
13
|
-
endIndex: number;
|
|
14
|
-
text: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface SuggestionMatch {
|
|
18
|
-
startIndex: number;
|
|
19
|
-
endIndex: number;
|
|
20
|
-
text: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface SuggestionResult {
|
|
24
|
-
pattern: Pattern | null;
|
|
25
|
-
astNode: Node | null;
|
|
26
|
-
match: SuggestionMatch | null;
|
|
27
|
-
error: SuggestionError | null;
|
|
28
|
-
options: Token;
|
|
29
|
-
isComplete: boolean;
|
|
30
|
-
parseStack: Node[];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export default class TextSuggester {
|
|
34
|
-
private cursor: Cursor | null = null;
|
|
35
|
-
private result: Node | null = null;
|
|
36
|
-
private text: string = "";
|
|
37
|
-
private match: SuggestionMatch | null = null;
|
|
38
|
-
private error: SuggestionError | null = null;
|
|
39
|
-
private patternMatch: Match | null = null;
|
|
40
|
-
private matchedText: string = "";
|
|
41
|
-
private rootPattern: Pattern | null = null;
|
|
42
|
-
private tokens: Token | null = {
|
|
43
|
-
startIndex: 0,
|
|
44
|
-
values: [],
|
|
45
|
-
};
|
|
46
|
-
private options: string[] = [];
|
|
47
|
-
private parseStack: Node[] = [];
|
|
48
|
-
|
|
49
|
-
suggest(text: string, pattern: Pattern) {
|
|
50
|
-
this.reset();
|
|
51
|
-
|
|
52
|
-
this.text = text;
|
|
53
|
-
this.rootPattern = pattern;
|
|
54
|
-
|
|
55
|
-
// If no text all options are available.
|
|
56
|
-
if (text.length === 0) {
|
|
57
|
-
return {
|
|
58
|
-
pattern: null,
|
|
59
|
-
astNode: null,
|
|
60
|
-
match: null,
|
|
61
|
-
error: null,
|
|
62
|
-
options: {
|
|
63
|
-
startIndex: 0,
|
|
64
|
-
values: pattern.getTokens(),
|
|
65
|
-
},
|
|
66
|
-
isComplete: false,
|
|
67
|
-
parseStack: [],
|
|
68
|
-
} as SuggestionResult;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
this.parse();
|
|
72
|
-
this.saveParseStack();
|
|
73
|
-
this.saveMatchedText();
|
|
74
|
-
this.saveMatch();
|
|
75
|
-
this.saveError();
|
|
76
|
-
this.saveOptions();
|
|
77
|
-
this.saveNextToken();
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
pattern: this.patternMatch?.pattern || null,
|
|
81
|
-
astNode: this.patternMatch?.astNode || null,
|
|
82
|
-
match: this.match,
|
|
83
|
-
error: this.error,
|
|
84
|
-
options: this.tokens,
|
|
85
|
-
isComplete: this.cursor?.didSuccessfullyParse() || false,
|
|
86
|
-
parseStack: this.parseStack,
|
|
87
|
-
} as SuggestionResult;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
private reset() {
|
|
91
|
-
this.cursor = null;
|
|
92
|
-
this.result = null;
|
|
93
|
-
this.text = "";
|
|
94
|
-
this.match = null;
|
|
95
|
-
this.error = null;
|
|
96
|
-
this.patternMatch = null;
|
|
97
|
-
this.matchedText = "";
|
|
98
|
-
this.rootPattern = null;
|
|
99
|
-
this.tokens = {
|
|
100
|
-
startIndex: 0,
|
|
101
|
-
values: [],
|
|
102
|
-
};
|
|
103
|
-
this.options = [];
|
|
104
|
-
this.parseStack = [];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
private parse() {
|
|
108
|
-
this.rootPattern = this.rootPattern;
|
|
109
|
-
this.cursor = new Cursor(this.text || "");
|
|
110
|
-
this.cursor.startRecording();
|
|
111
|
-
this.result = this.rootPattern?.parse(this.cursor) || null;
|
|
112
|
-
this.patternMatch = this.cursor.lastMatch;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
private saveParseStack() {
|
|
116
|
-
this.parseStack = this.cursor?.history.getLastParseStack() || [];
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
private saveMatchedText() {
|
|
120
|
-
if (this.patternMatch?.astNode != null) {
|
|
121
|
-
this.matchedText =
|
|
122
|
-
this.text?.substring(0, this.patternMatch.astNode.endIndex + 1) || "";
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private saveMatch() {
|
|
127
|
-
const node = this.patternMatch?.astNode;
|
|
128
|
-
|
|
129
|
-
if (node == null) {
|
|
130
|
-
this.match = null;
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
let endIndex = this.matchedText.length - 1;
|
|
135
|
-
|
|
136
|
-
this.match = {
|
|
137
|
-
text: this.matchedText,
|
|
138
|
-
startIndex: 0,
|
|
139
|
-
endIndex: endIndex,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private saveError() {
|
|
144
|
-
if (this.patternMatch?.astNode == null) {
|
|
145
|
-
this.error = {
|
|
146
|
-
startIndex: 0,
|
|
147
|
-
endIndex: this.text.length - 1,
|
|
148
|
-
text: this.text,
|
|
149
|
-
};
|
|
150
|
-
return this;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
this.patternMatch != null &&
|
|
155
|
-
this.text.length > this.matchedText.length
|
|
156
|
-
) {
|
|
157
|
-
const difference = this.text.length - this.matchedText.length;
|
|
158
|
-
const startIndex = this.patternMatch.astNode.endIndex + 1;
|
|
159
|
-
const endIndex = startIndex + difference - 1;
|
|
160
|
-
|
|
161
|
-
this.error = {
|
|
162
|
-
startIndex: startIndex,
|
|
163
|
-
endIndex: endIndex,
|
|
164
|
-
text: this.text.substring(startIndex, endIndex + 1),
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
return;
|
|
168
|
-
} else {
|
|
169
|
-
this.error = null;
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
private saveNextToken() {
|
|
175
|
-
const isCompleteMatch =
|
|
176
|
-
this.patternMatch?.pattern === this.rootPattern &&
|
|
177
|
-
this.cursor?.didSuccessfullyParse();
|
|
178
|
-
const noMatch = this.patternMatch?.astNode == null;
|
|
179
|
-
const noOptions = this.options.length === 0;
|
|
180
|
-
|
|
181
|
-
if (isCompleteMatch && noOptions) {
|
|
182
|
-
this.tokens = null;
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (noMatch) {
|
|
187
|
-
let options = this.rootPattern?.getTokens();
|
|
188
|
-
|
|
189
|
-
options = options?.filter((option: any) => {
|
|
190
|
-
return option.indexOf(this.text) === 0;
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
if (options?.length === 0) {
|
|
194
|
-
this.tokens = null;
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const values = options?.map((option) => {
|
|
199
|
-
const parts = option.split(this.text);
|
|
200
|
-
return parts[1];
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
this.tokens = {
|
|
204
|
-
startIndex: 0,
|
|
205
|
-
values: values || [],
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
this.matchedText = this.text;
|
|
209
|
-
this.match = {
|
|
210
|
-
text: this.text,
|
|
211
|
-
startIndex: 0,
|
|
212
|
-
endIndex: this.text.length - 1,
|
|
213
|
-
};
|
|
214
|
-
this.error = null;
|
|
215
|
-
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const options = this.options;
|
|
220
|
-
let startIndex = this.matchedText.length;
|
|
221
|
-
|
|
222
|
-
if (this.matchedText.length < this.text.length) {
|
|
223
|
-
const leftOver = this.text.substring(this.matchedText.length);
|
|
224
|
-
const partialMatchOptions = options
|
|
225
|
-
.filter((option: any) => {
|
|
226
|
-
return option.indexOf(leftOver) === 0;
|
|
227
|
-
})
|
|
228
|
-
.map((option: any) => {
|
|
229
|
-
return option.substring(leftOver.length);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
if (partialMatchOptions.length === 0) {
|
|
233
|
-
this.tokens = null;
|
|
234
|
-
return;
|
|
235
|
-
} else {
|
|
236
|
-
if (this.match == null) {
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
this.match = {
|
|
241
|
-
text: this.match.text + leftOver,
|
|
242
|
-
startIndex: this.match.startIndex,
|
|
243
|
-
endIndex: this.match.endIndex + leftOver.length,
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
this.error = null;
|
|
247
|
-
|
|
248
|
-
this.tokens = {
|
|
249
|
-
startIndex: this.match.endIndex + 1,
|
|
250
|
-
values: partialMatchOptions,
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
this.tokens = {
|
|
258
|
-
startIndex,
|
|
259
|
-
values: options,
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
private saveOptions() {
|
|
264
|
-
const parents = new Map<Pattern, Pattern>();
|
|
265
|
-
const cursor = this.cursor;
|
|
266
|
-
|
|
267
|
-
if (cursor == null) {
|
|
268
|
-
this.options = [];
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const furthestMatches = cursor.history.astNodes.reduce(
|
|
273
|
-
(acc: any, node: any, index: any) => {
|
|
274
|
-
const pattern = cursor.history.patterns[index];
|
|
275
|
-
const parent = pattern.parent;
|
|
276
|
-
|
|
277
|
-
if (parent != null) {
|
|
278
|
-
parents.set(parent, parent);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (parents.has(pattern)){
|
|
282
|
-
return acc;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (node.endIndex === acc.furthestTextIndex) {
|
|
286
|
-
acc.nodeIndexes.push(index);
|
|
287
|
-
} else if (node.endIndex > acc.furthestTextIndex) {
|
|
288
|
-
acc.furthestTextIndex = node.endIndex;
|
|
289
|
-
acc.nodeIndexes = [index];
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
return acc;
|
|
293
|
-
},
|
|
294
|
-
{ furthestTextIndex: -1, nodeIndexes: [] }
|
|
295
|
-
);
|
|
296
|
-
|
|
297
|
-
const matches = furthestMatches.nodeIndexes.reduce(
|
|
298
|
-
(acc: any, index: any) => {
|
|
299
|
-
const pattern = this.cursor?.history.patterns[index];
|
|
300
|
-
const tokens = pattern?.getNextTokens();
|
|
301
|
-
|
|
302
|
-
tokens?.forEach((token: any) => {
|
|
303
|
-
acc[token] = true;
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
return acc;
|
|
307
|
-
},
|
|
308
|
-
{}
|
|
309
|
-
);
|
|
310
|
-
|
|
311
|
-
this.options = Object.keys(matches);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
static suggest(text: string, pattern: Pattern) {
|
|
315
|
-
return new TextSuggester().suggest(text, pattern);
|
|
316
|
-
}
|
|
317
|
-
}
|