clarity-pattern-parser 6.0.0 → 7.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/TODO.md +1 -76
- package/dist/ast/Node.d.ts +1 -0
- package/dist/grammar/Grammar.d.ts +17 -0
- package/dist/grammar/patterns/andLiteral.d.ts +2 -0
- package/dist/grammar/patterns/comment.d.ts +2 -0
- package/dist/grammar/patterns/grammar.d.ts +2 -0
- package/dist/grammar/patterns/literal.d.ts +2 -0
- package/dist/grammar/patterns/name.d.ts +2 -0
- package/dist/grammar/patterns/orLiteral.d.ts +2 -0
- package/dist/grammar/patterns/pattern.d.ts +2 -0
- package/dist/grammar/patterns/regexLiteral.d.ts +2 -0
- package/dist/grammar/patterns/repeatLiteral.d.ts +3 -0
- package/dist/grammar/patterns/spaces.d.ts +2 -0
- package/dist/grammar/patterns/statement.d.ts +2 -0
- package/dist/index.browser.js +1205 -550
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.esm.js +1203 -549
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1203 -548
- package/dist/index.js.map +1 -1
- package/dist/intellisense/AutoComplete.d.ts +9 -7
- package/dist/intellisense/Suggestion.d.ts +1 -2
- package/dist/patterns/And.d.ts +2 -1
- package/dist/patterns/Cursor.d.ts +1 -0
- package/dist/patterns/CursorHistory.d.ts +2 -1
- package/dist/patterns/FiniteRepeat.d.ts +39 -0
- package/dist/patterns/InfiniteRepeat.d.ts +47 -0
- package/dist/patterns/Literal.d.ts +2 -1
- package/dist/patterns/Not.d.ts +2 -1
- package/dist/patterns/Or.d.ts +2 -1
- package/dist/patterns/Pattern.d.ts +3 -2
- package/dist/patterns/Reference.d.ts +2 -1
- package/dist/patterns/Regex.d.ts +2 -1
- package/dist/patterns/Repeat.d.ts +19 -22
- package/jest.config.js +0 -1
- package/jest.coverage.config.js +13 -0
- package/package.json +3 -3
- package/src/ast/Node.test.ts +21 -0
- package/src/ast/Node.ts +12 -6
- package/src/grammar/Grammar.test.ts +288 -0
- package/src/grammar/Grammar.ts +234 -0
- package/src/grammar/patterns/andLiteral.ts +8 -0
- package/src/grammar/patterns/comment.ts +3 -0
- package/src/grammar/patterns/grammar.ts +19 -0
- package/src/grammar/patterns/literal.ts +5 -0
- package/src/grammar/patterns/name.ts +3 -0
- package/src/grammar/patterns/orLiteral.ts +8 -0
- package/src/grammar/patterns/pattern.ts +13 -0
- package/src/grammar/patterns/regexLiteral.ts +4 -0
- package/src/grammar/patterns/repeatLiteral.ts +72 -0
- package/src/grammar/patterns/spaces.ts +4 -0
- package/src/grammar/patterns/statement.ts +35 -0
- package/src/grammar/spec.md +142 -0
- package/src/index.ts +6 -3
- package/src/intellisense/AutoComplete.test.ts +125 -39
- package/src/intellisense/AutoComplete.ts +52 -36
- package/src/intellisense/Suggestion.ts +1 -2
- package/src/intellisense/css/cssValue.ts +1 -1
- package/src/intellisense/css/method.ts +1 -1
- package/src/intellisense/css/values.ts +1 -1
- package/src/intellisense/javascript/Javascript.test.ts +34 -11
- package/src/intellisense/javascript/arrayLiteral.ts +1 -1
- package/src/intellisense/javascript/{expressionStatement.ts → assignment.ts} +7 -8
- package/src/intellisense/javascript/expression.ts +45 -27
- package/src/intellisense/javascript/infixOperator.ts +6 -2
- package/src/intellisense/javascript/invocation.ts +1 -1
- package/src/intellisense/javascript/keywords.ts +3 -0
- package/src/intellisense/javascript/objectAccess.ts +9 -0
- package/src/intellisense/javascript/objectLiteral.ts +3 -3
- package/src/intellisense/javascript/parameters.ts +1 -1
- package/src/intellisense/javascript/propertyAccess.ts +8 -3
- package/src/intellisense/javascript/stringLiteral.ts +14 -8
- package/src/patterns/And.test.ts +16 -3
- package/src/patterns/And.ts +25 -17
- package/src/patterns/Cursor.ts +4 -0
- package/src/patterns/CursorHistory.ts +34 -5
- package/src/patterns/FiniteRepeat.test.ts +481 -0
- package/src/patterns/FiniteRepeat.ts +231 -0
- package/src/patterns/InfiniteRepeat.test.ts +296 -0
- package/src/patterns/InfiniteRepeat.ts +329 -0
- package/src/patterns/Literal.test.ts +13 -4
- package/src/patterns/Literal.ts +5 -1
- package/src/patterns/Not.test.ts +20 -9
- package/src/patterns/Not.ts +5 -1
- package/src/patterns/Or.test.ts +18 -7
- package/src/patterns/Or.ts +11 -1
- package/src/patterns/Pattern.ts +3 -2
- package/src/patterns/Reference.test.ts +18 -8
- package/src/patterns/Reference.ts +5 -1
- package/src/patterns/Regex.test.ts +13 -4
- package/src/patterns/Regex.ts +5 -1
- package/src/patterns/Repeat.test.ts +162 -158
- package/src/patterns/Repeat.ts +95 -226
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Cursor } from "../patterns/Cursor";
|
|
2
|
+
import { Match } from "../patterns/CursorHistory";
|
|
2
3
|
import { Pattern } from "../patterns/Pattern";
|
|
3
4
|
import { Suggestion } from "./Suggestion";
|
|
4
5
|
import { SuggestionOption } from "./SuggestionOption";
|
|
@@ -9,12 +10,12 @@ export interface AutoCompleteOptions {
|
|
|
9
10
|
* Be very careful, this can explode to infinity pretty quick. Usually useful
|
|
10
11
|
* for dividers and spaces.
|
|
11
12
|
*/
|
|
12
|
-
greedyPatternNames
|
|
13
|
+
greedyPatternNames?: string[];
|
|
13
14
|
/**
|
|
14
15
|
* Allows for custom suggestions for patterns. The key is the name of the pattern
|
|
15
16
|
* and the string array are the tokens suggested for that pattern.
|
|
16
17
|
*/
|
|
17
|
-
customTokens
|
|
18
|
+
customTokens?: Record<string, string[]>;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
const defaultOptions = { greedyPatternNames: [], customTokens: {} };
|
|
@@ -31,12 +32,12 @@ export class AutoComplete {
|
|
|
31
32
|
this._text = "";
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
suggestFor(text: string): Suggestion {
|
|
35
36
|
if (text.length === 0) {
|
|
36
37
|
return {
|
|
37
38
|
isComplete: false,
|
|
38
|
-
options: this.
|
|
39
|
-
|
|
39
|
+
options: this._createSuggestionsFromRoot(),
|
|
40
|
+
errorAtIndex: 0,
|
|
40
41
|
cursor: null,
|
|
41
42
|
ast: null
|
|
42
43
|
}
|
|
@@ -44,50 +45,54 @@ export class AutoComplete {
|
|
|
44
45
|
|
|
45
46
|
this._text = text;
|
|
46
47
|
this._cursor = new Cursor(text);
|
|
47
|
-
const ast = this._pattern.parse(this._cursor);
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
let errorAtIndex = null;
|
|
50
|
+
|
|
51
|
+
const ast = this._pattern.parse(this._cursor);
|
|
50
52
|
const isComplete = ast?.value === text;
|
|
51
|
-
const options = this.
|
|
53
|
+
const options = this._getAllOptions();
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
if (this._cursor.hasError && this._cursor.furthestError != null) {
|
|
56
|
+
errorAtIndex = this._cursor.furthestError.index;
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
errorAtIndex = options.reduce((errorAtIndex, option) =>
|
|
59
|
+
Math.max(errorAtIndex, option.startIndex),
|
|
60
|
+
errorAtIndex);
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
return {
|
|
60
64
|
isComplete: isComplete,
|
|
61
65
|
options: options,
|
|
62
|
-
|
|
66
|
+
errorAtIndex,
|
|
63
67
|
cursor: this._cursor,
|
|
64
68
|
ast,
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
71
|
|
|
68
|
-
private
|
|
72
|
+
private _getAllOptions() {
|
|
73
|
+
return this._cursor.leafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private _createSuggestionsFromRoot(): SuggestionOption[] {
|
|
69
77
|
const suggestions: SuggestionOption[] = [];
|
|
70
78
|
const tokens = this._pattern.getTokens();
|
|
71
79
|
|
|
72
80
|
for (const token of tokens) {
|
|
73
|
-
suggestions.push(this.
|
|
81
|
+
suggestions.push(this._createSuggestion("", token));
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
return suggestions;
|
|
77
85
|
}
|
|
78
86
|
|
|
79
|
-
private
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (!leafMatch.pattern) {
|
|
83
|
-
return this.createSuggestions(-1, this._getTokensForPattern(this._pattern));
|
|
87
|
+
private _createSuggestionsFromMatch(match: Match): SuggestionOption[] {
|
|
88
|
+
if (!match.pattern) {
|
|
89
|
+
return this._createSuggestions(-1, this._getTokensForPattern(this._pattern));
|
|
84
90
|
}
|
|
85
91
|
|
|
86
|
-
const leafPattern =
|
|
87
|
-
const
|
|
88
|
-
const parent = leafMatch.pattern.parent;
|
|
92
|
+
const leafPattern = match.pattern;
|
|
93
|
+
const parent = match.pattern.parent;
|
|
89
94
|
|
|
90
|
-
if (parent !== null &&
|
|
95
|
+
if (parent !== null && match.node != null) {
|
|
91
96
|
const patterns = leafPattern.getNextPatterns();
|
|
92
97
|
|
|
93
98
|
const tokens = patterns.reduce((acc: string[], pattern) => {
|
|
@@ -95,39 +100,50 @@ export class AutoComplete {
|
|
|
95
100
|
return acc;
|
|
96
101
|
}, []);
|
|
97
102
|
|
|
98
|
-
return this.
|
|
103
|
+
return this._createSuggestions(match.node.lastIndex, tokens);
|
|
99
104
|
} else {
|
|
100
105
|
return [];
|
|
101
106
|
}
|
|
102
107
|
}
|
|
103
108
|
|
|
104
109
|
private _getTokensForPattern(pattern: Pattern) {
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
const augmentedTokens = this._getAugmentedTokens(pattern)
|
|
111
|
+
|
|
112
|
+
if (this._options.greedyPatternNames != null && this._options.greedyPatternNames.includes(pattern.name)) {
|
|
107
113
|
const nextPatterns = pattern.getNextPatterns();
|
|
108
114
|
const tokens: string[] = [];
|
|
109
115
|
|
|
110
|
-
const nextPatternTokens = nextPatterns.reduce((acc: string[], pattern)=>{
|
|
116
|
+
const nextPatternTokens = nextPatterns.reduce((acc: string[], pattern) => {
|
|
111
117
|
acc.push(...this._getTokensForPattern(pattern));
|
|
112
118
|
return acc;
|
|
113
119
|
}, []);
|
|
114
120
|
|
|
115
|
-
for (let token of
|
|
116
|
-
for (let nextPatternToken of nextPatternTokens){
|
|
121
|
+
for (let token of augmentedTokens) {
|
|
122
|
+
for (let nextPatternToken of nextPatternTokens) {
|
|
117
123
|
tokens.push(token + nextPatternToken);
|
|
118
124
|
}
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
return tokens;
|
|
122
128
|
} else {
|
|
123
|
-
|
|
124
|
-
const customTokens = this._options.customTokens[pattern.name] || [];
|
|
125
|
-
tokens.push(...customTokens);
|
|
126
|
-
return tokens;
|
|
129
|
+
return augmentedTokens;
|
|
127
130
|
}
|
|
128
131
|
}
|
|
129
132
|
|
|
130
|
-
private
|
|
133
|
+
private _getAugmentedTokens(pattern: Pattern) {
|
|
134
|
+
const customTokensMap: any = this._options.customTokens || {};
|
|
135
|
+
const leafPatterns = pattern.getPatterns();
|
|
136
|
+
const tokens: string[] = customTokensMap[pattern.name] || [];
|
|
137
|
+
|
|
138
|
+
leafPatterns.forEach(p => {
|
|
139
|
+
const augmentedTokens = customTokensMap[p.name] || [];
|
|
140
|
+
tokens.push(...p.getTokens(), ...augmentedTokens);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return tokens;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private _createSuggestions(lastIndex: number, tokens: string[]): SuggestionOption[] {
|
|
131
147
|
let substring = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
|
|
132
148
|
const suggestionStrings: string[] = [];
|
|
133
149
|
const options: SuggestionOption[] = [];
|
|
@@ -140,7 +156,7 @@ export class AutoComplete {
|
|
|
140
156
|
|
|
141
157
|
if (startsWith && !alreadyExist && !isSameAsText) {
|
|
142
158
|
suggestionStrings.push(suggestion);
|
|
143
|
-
options.push(this.
|
|
159
|
+
options.push(this._createSuggestion(this._cursor.text, suggestion));
|
|
144
160
|
}
|
|
145
161
|
}
|
|
146
162
|
|
|
@@ -150,7 +166,7 @@ export class AutoComplete {
|
|
|
150
166
|
return reducedOptions;
|
|
151
167
|
}
|
|
152
168
|
|
|
153
|
-
private
|
|
169
|
+
private _createSuggestion(fullText: string, suggestion: string): SuggestionOption {
|
|
154
170
|
const furthestMatch = findMatchIndex(suggestion, fullText);
|
|
155
171
|
const text = suggestion.slice(furthestMatch);
|
|
156
172
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Node } from "../ast/Node";
|
|
2
2
|
import { Cursor } from "../patterns/Cursor";
|
|
3
|
-
import { Pattern } from "../patterns/Pattern";
|
|
4
3
|
import { SuggestionOption } from "./SuggestionOption";
|
|
5
4
|
|
|
6
5
|
export interface Suggestion {
|
|
7
6
|
isComplete: boolean;
|
|
8
7
|
options: SuggestionOption[];
|
|
9
|
-
|
|
8
|
+
errorAtIndex: number | null;
|
|
10
9
|
cursor: Cursor | null;
|
|
11
10
|
ast: Node | null;
|
|
12
11
|
}
|
|
@@ -2,6 +2,6 @@ import { Repeat } from "../../patterns/Repeat";
|
|
|
2
2
|
import divider from "./divider";
|
|
3
3
|
import values from "./values";
|
|
4
4
|
|
|
5
|
-
const cssValue = new Repeat("css-value", values, divider);
|
|
5
|
+
const cssValue = new Repeat("css-value", values, { divider });
|
|
6
6
|
|
|
7
7
|
export default cssValue;
|
|
@@ -9,7 +9,7 @@ import divider from "./divider";
|
|
|
9
9
|
const openParen = new Literal("open-paren", "(");
|
|
10
10
|
const closeParen = new Literal("close-paren", ")");
|
|
11
11
|
const values = new Reference("values");
|
|
12
|
-
const args = new Repeat("arguments", values, divider,
|
|
12
|
+
const args = new Repeat("arguments", values, { divider, min: 0 });
|
|
13
13
|
const methodName = name.clone("method-name");
|
|
14
14
|
methodName.setTokens(["rgba", "radial-gradient", "linear-gradient"]);
|
|
15
15
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { Cursor } from "../../patterns/Cursor";
|
|
1
2
|
import { escapedCharacter } from "./escapedCharacter";
|
|
2
3
|
import { exponent } from "./exponent";
|
|
3
4
|
import { expression } from "./expression";
|
|
4
|
-
import {
|
|
5
|
+
import { assignment } from "./assignment";
|
|
5
6
|
import { infixOperator } from "./infixOperator";
|
|
6
7
|
import { integer } from "./integer";
|
|
7
8
|
import { name } from "./name";
|
|
@@ -173,30 +174,52 @@ describe("Ecmascript 3", () => {
|
|
|
173
174
|
expect(result.ast?.value).toBe(`{"prop":1}`);
|
|
174
175
|
});
|
|
175
176
|
|
|
176
|
-
test("
|
|
177
|
+
test("Expression", () => {
|
|
178
|
+
|
|
177
179
|
let result = expression.exec("[]")
|
|
178
180
|
expect(result.ast?.value).toBe("[]");
|
|
179
181
|
|
|
180
182
|
result = expression.exec("[{}, 9, 0.9e-10, [1, 2]]")
|
|
181
183
|
expect(result.ast?.value).toBe("[{}, 9, 0.9e-10, [1, 2]]");
|
|
182
|
-
|
|
184
|
+
|
|
185
|
+
result = expression.exec(`"John"`);
|
|
186
|
+
expect(result.ast?.value).toBe(`"John"`)
|
|
187
|
+
|
|
188
|
+
result = expression.exec(`variableName.property`);
|
|
189
|
+
expect(result.ast?.value).toBe(`variableName.property`);
|
|
190
|
+
|
|
191
|
+
result = expression.exec(`{property: ""}`);
|
|
192
|
+
expect(result.ast?.value).toBe(`{property: ""}`);
|
|
193
|
+
|
|
194
|
+
const cursor = new Cursor(`name() == name.property === name2 ? {prop: name, blah: [ 0.9e-10 ]} : name`);
|
|
195
|
+
cursor.startRecording();
|
|
196
|
+
const ast = expression.parse(cursor);
|
|
197
|
+
})
|
|
183
198
|
|
|
184
199
|
test("Expression Statement", () => {
|
|
185
|
-
let result =
|
|
200
|
+
let result = assignment.exec(`name = "John"`);
|
|
186
201
|
expect(result.ast?.value).toBe(`name = "John"`);
|
|
187
202
|
|
|
188
|
-
result =
|
|
203
|
+
result = assignment.exec(`name = othername = "John"`)
|
|
189
204
|
expect(result.ast?.value).toBe(`name = othername = "John"`);
|
|
190
205
|
|
|
191
|
-
result =
|
|
206
|
+
result = assignment.exec(`name = othername.prop = "John"`)
|
|
192
207
|
expect(result.ast?.value).toBe(`name = othername.prop = "John"`);
|
|
193
208
|
|
|
194
|
-
result =
|
|
209
|
+
result = assignment.exec(`name = othername.prop += 2`)
|
|
195
210
|
expect(result.ast?.value).toBe(`name = othername.prop += 2`);
|
|
196
|
-
|
|
197
|
-
result =
|
|
198
|
-
expect(result.ast?.value).toBe(`name.prop().method(blah) = blah.prop()`);
|
|
199
|
-
|
|
211
|
+
|
|
212
|
+
result = assignment.exec(`name.prop().method(blah) = blah.prop() == ha ? first : second`)
|
|
213
|
+
expect(result.ast?.value).toBe(`name.prop().method(blah) = blah.prop() == ha ? first : second`);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
test("Object Access", () => {
|
|
218
|
+
let result = expression.exec("name.prop");
|
|
219
|
+
expect(result.ast?.value).toBe(`name.prop`);
|
|
220
|
+
|
|
221
|
+
result = expression.exec(`name.prop.anotherProp["Ha"][coolYo] === 1`);
|
|
222
|
+
expect(result.ast?.value).toBe(`name.prop.anotherProp["Ha"][coolYo] === 1`);
|
|
200
223
|
});
|
|
201
224
|
|
|
202
225
|
|
|
@@ -7,7 +7,7 @@ import { Repeat } from "../../patterns/Repeat";
|
|
|
7
7
|
import { optionalSpaces } from "./optionalSpaces";
|
|
8
8
|
|
|
9
9
|
const divider = new Regex("array-divider", "\\s*,\\s*");
|
|
10
|
-
const arrayItems = new Repeat("array-items", new Reference("expression"), divider,
|
|
10
|
+
const arrayItems = new Repeat("array-items", new Reference("expression"), { divider, min: 0 });
|
|
11
11
|
|
|
12
12
|
export const arrayLiteral = new Or("array-literal",
|
|
13
13
|
[new And("empty-array-literal", [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { And } from "../../patterns/And";
|
|
2
2
|
import { Literal } from "../../patterns/Literal";
|
|
3
3
|
import { Or } from "../../patterns/Or";
|
|
4
|
-
import {
|
|
4
|
+
import { Reference } from "../../patterns/Reference";
|
|
5
5
|
import { expression } from "./expression";
|
|
6
6
|
import { optionalSpaces } from "./optionalSpaces";
|
|
7
7
|
|
|
@@ -16,14 +16,13 @@ const assignment = new And("assignment", [
|
|
|
16
16
|
optionalSpaces,
|
|
17
17
|
assignmentOperators,
|
|
18
18
|
optionalSpaces,
|
|
19
|
+
new Or("assignment-right-operand", [
|
|
20
|
+
new Reference("assignment"),
|
|
21
|
+
expression
|
|
22
|
+
]),
|
|
19
23
|
]);
|
|
20
24
|
|
|
21
|
-
const expressionStatement = new And("expressionStatement", [
|
|
22
|
-
new Repeat("assignments",
|
|
23
|
-
assignment),
|
|
24
|
-
optionalSpaces,
|
|
25
|
-
expression
|
|
26
|
-
]);
|
|
27
25
|
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
|
|
28
|
+
export { assignment }
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { Regex } from "../..";
|
|
2
1
|
import { And } from "../../patterns/And";
|
|
3
2
|
import { Literal } from "../../patterns/Literal";
|
|
4
3
|
import { Or } from "../../patterns/Or";
|
|
5
4
|
import { Reference } from "../../patterns/Reference";
|
|
5
|
+
import { Regex } from "../../patterns/Regex";
|
|
6
6
|
import { Repeat } from "../../patterns/Repeat";
|
|
7
7
|
import { infixOperator } from "./infixOperator";
|
|
8
8
|
import { invocation } from "./invocation";
|
|
9
|
+
import { nullKeyword } from "./keywords";
|
|
9
10
|
import { literal } from "./literal";
|
|
10
11
|
import { name } from "./name";
|
|
12
|
+
import { objectAccess } from "./objectAccess";
|
|
11
13
|
import { optionalSpaces } from "./optionalSpaces";
|
|
12
14
|
import { prefixOperator } from "./prefixOperator";
|
|
13
15
|
import { propertyAccess } from "./propertyAccess";
|
|
@@ -41,46 +43,62 @@ const prefixExpression = new And("prefix-expression", [
|
|
|
41
43
|
new Reference("expression")
|
|
42
44
|
]);
|
|
43
45
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
optionalSpaces,
|
|
47
|
-
new Reference("expression"),
|
|
48
|
-
], true);
|
|
49
|
-
|
|
50
|
-
const optionalTernary = new And("ternary", [
|
|
51
|
-
new Literal("question-mark", "?"),
|
|
52
|
-
optionalSpaces,
|
|
53
|
-
new Reference("expression"),
|
|
54
|
-
optionalSpaces,
|
|
55
|
-
new Literal("colon", ":"),
|
|
56
|
-
optionalSpaces,
|
|
57
|
-
new Reference("expression")
|
|
58
|
-
], true);
|
|
59
|
-
|
|
60
|
-
const optionalMemberAccesses = new Repeat("object-member-accesses",
|
|
61
|
-
new Or("object-member-access", [
|
|
46
|
+
const memberAccess = new Repeat("member-access",
|
|
47
|
+
new Or("member-access", [
|
|
62
48
|
invocation,
|
|
63
49
|
propertyAccess,
|
|
64
|
-
])
|
|
65
|
-
undefined, true
|
|
50
|
+
])
|
|
66
51
|
);
|
|
67
52
|
|
|
53
|
+
|
|
68
54
|
var variableName = name.clone("variable-name");
|
|
69
55
|
|
|
70
56
|
const expressions = new Or("expressions", [
|
|
71
57
|
newExpression,
|
|
72
58
|
deleteExpression,
|
|
73
|
-
groupExpression,
|
|
74
|
-
prefixExpression,
|
|
75
59
|
literal,
|
|
60
|
+
nullKeyword,
|
|
61
|
+
objectAccess,
|
|
76
62
|
variableName,
|
|
63
|
+
groupExpression,
|
|
64
|
+
prefixExpression
|
|
77
65
|
]);
|
|
78
66
|
|
|
79
|
-
const
|
|
67
|
+
const expressionBody = new And("expression-body", [
|
|
80
68
|
expressions,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
69
|
+
memberAccess.clone(undefined, true),
|
|
70
|
+
]);
|
|
71
|
+
|
|
72
|
+
const infixExpression = new And("infix-expression", [
|
|
73
|
+
expressionBody,
|
|
74
|
+
optionalSpaces,
|
|
75
|
+
infixOperator,
|
|
76
|
+
optionalSpaces,
|
|
77
|
+
new Or("infix-right-operand", [
|
|
78
|
+
new Reference("infix-expression"),
|
|
79
|
+
expressionBody,
|
|
80
|
+
])
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
const ternaryExpression = new And("ternary", [
|
|
84
|
+
new Or("ternary-condition", [
|
|
85
|
+
infixExpression,
|
|
86
|
+
expressionBody
|
|
87
|
+
]),
|
|
88
|
+
optionalSpaces,
|
|
89
|
+
new Literal("question-mark", "?"),
|
|
90
|
+
optionalSpaces,
|
|
91
|
+
new Reference("expression"),
|
|
92
|
+
optionalSpaces,
|
|
93
|
+
new Literal("colon", ":"),
|
|
94
|
+
optionalSpaces,
|
|
95
|
+
new Reference("expression")
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
const expression = new Or("expression", [
|
|
99
|
+
ternaryExpression,
|
|
100
|
+
infixExpression,
|
|
101
|
+
expressionBody
|
|
84
102
|
]);
|
|
85
103
|
|
|
86
104
|
export { expression }
|
|
@@ -10,8 +10,10 @@ const greaterOrEqual = new Literal("greater-or-equal", ">=");
|
|
|
10
10
|
const lessOrEqual = new Literal("less-or-equal", "<=");
|
|
11
11
|
const greater = new Literal("greater", ">");
|
|
12
12
|
const less = new Literal("less", "<");
|
|
13
|
-
const equal = new Literal("equal", "
|
|
14
|
-
const notEqual = new Literal("not-equal", "
|
|
13
|
+
const equal = new Literal("equal", "==");
|
|
14
|
+
const notEqual = new Literal("not-equal", "!=");
|
|
15
|
+
const strictEqual = new Literal("strict-equal", "===");
|
|
16
|
+
const strictNotEqual = new Literal("strict-not-equal", "!==");
|
|
15
17
|
const logicalOr = new Literal("logical-or", "||");
|
|
16
18
|
const logicalAnd = new Literal("logical-and", "&&");
|
|
17
19
|
|
|
@@ -25,6 +27,8 @@ const infixOperator = new Or("infix-operator", [
|
|
|
25
27
|
lessOrEqual,
|
|
26
28
|
greater,
|
|
27
29
|
less,
|
|
30
|
+
strictEqual,
|
|
31
|
+
strictNotEqual,
|
|
28
32
|
equal,
|
|
29
33
|
notEqual,
|
|
30
34
|
logicalOr,
|
|
@@ -11,7 +11,7 @@ const divider = new Regex("invocation-divider", "\\s*,\\s*");
|
|
|
11
11
|
const invocationWithArguments = new And("invocation-with-arguments", [
|
|
12
12
|
new Literal("open-paren", "("),
|
|
13
13
|
optionalSpaces,
|
|
14
|
-
new Repeat("expressions", new Reference("expression"), divider,
|
|
14
|
+
new Repeat("expressions", new Reference("expression"), { divider, min: 0 }),
|
|
15
15
|
optionalSpaces,
|
|
16
16
|
new Literal("close-paren", ")"),
|
|
17
17
|
]);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { And } from "../../patterns/And";
|
|
2
|
+
import { Reference } from "../../patterns/Reference";
|
|
3
|
+
import { name } from "./name";
|
|
4
|
+
import { propertyAccess } from "./propertyAccess";
|
|
5
|
+
|
|
6
|
+
export const objectAccess = new And("object-access", [
|
|
7
|
+
name.clone("variable-name"),
|
|
8
|
+
propertyAccess,
|
|
9
|
+
]);
|
|
@@ -8,7 +8,7 @@ import { name } from "./name";
|
|
|
8
8
|
import { optionalSpaces } from "./optionalSpaces";
|
|
9
9
|
import { stringLiteral } from "./stringLiteral";
|
|
10
10
|
|
|
11
|
-
const propertyName = new Or("property-name", [stringLiteral, name]);
|
|
11
|
+
const propertyName = new Or("property-name", [stringLiteral.clone("object-property"), name.clone("object-property")]);
|
|
12
12
|
const property = new And("property", [
|
|
13
13
|
propertyName,
|
|
14
14
|
optionalSpaces,
|
|
@@ -17,12 +17,12 @@ const property = new And("property", [
|
|
|
17
17
|
new Reference("expression"),
|
|
18
18
|
]);
|
|
19
19
|
const divider = new Regex("property-divider", "\\s*,\\s*");
|
|
20
|
-
const
|
|
20
|
+
const optionalProperties = new Repeat("properties", property, { divider, min: 0 });
|
|
21
21
|
|
|
22
22
|
const objectLiteral = new And("object-literal", [
|
|
23
23
|
new Literal("open-curly-bracket", "{"),
|
|
24
24
|
optionalSpaces,
|
|
25
|
-
|
|
25
|
+
optionalProperties,
|
|
26
26
|
optionalSpaces,
|
|
27
27
|
new Literal("close-curly-bracket", "}"),
|
|
28
28
|
]);
|
|
@@ -12,7 +12,7 @@ const optionalSpace = new Regex("optional-space", "\\s", true)
|
|
|
12
12
|
const parameters = new And("parameters", [
|
|
13
13
|
new Literal("open-paren", "("),
|
|
14
14
|
optionalSpace,
|
|
15
|
-
new Repeat("arguments", name, divider),
|
|
15
|
+
new Repeat("arguments", name, { divider, trimDivider: true }),
|
|
16
16
|
optionalSpace,
|
|
17
17
|
new Literal("close-paren", ")"),
|
|
18
18
|
]);
|
|
@@ -6,7 +6,7 @@ import { name } from "./name";
|
|
|
6
6
|
|
|
7
7
|
const dotPropertyAccess = new And("dot-property-access", [
|
|
8
8
|
new Literal("period", "."),
|
|
9
|
-
name
|
|
9
|
+
name.clone("property-name")
|
|
10
10
|
]);
|
|
11
11
|
|
|
12
12
|
const bracketPropertyAccess = new And("bracket-property-access", [
|
|
@@ -15,9 +15,14 @@ const bracketPropertyAccess = new And("bracket-property-access", [
|
|
|
15
15
|
new Literal("close-square-bracket", "]"),
|
|
16
16
|
]);
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const propertyAccessTypes = new Or("property-access-types", [
|
|
19
19
|
dotPropertyAccess,
|
|
20
|
-
bracketPropertyAccess
|
|
20
|
+
bracketPropertyAccess
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
const propertyAccess = new And("property-access", [
|
|
24
|
+
propertyAccessTypes,
|
|
25
|
+
new Reference("property-access", true)
|
|
21
26
|
]);
|
|
22
27
|
|
|
23
28
|
export { propertyAccess }
|
|
@@ -7,19 +7,25 @@ import { escapedCharacter } from "./escapedCharacter";
|
|
|
7
7
|
|
|
8
8
|
const doubleQuoteStringLiteral = new And("double-string-literal", [
|
|
9
9
|
new Literal("double-quote", "\""),
|
|
10
|
-
new Repeat("characters",
|
|
11
|
-
new
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
new Repeat("characters",
|
|
11
|
+
new Or("characters", [
|
|
12
|
+
new Regex("normal-characters", "[^\\\"]+"),
|
|
13
|
+
escapedCharacter
|
|
14
|
+
]),
|
|
15
|
+
{ min: 0 }
|
|
16
|
+
),
|
|
14
17
|
new Literal("double-quote", "\""),
|
|
15
18
|
]);
|
|
16
19
|
|
|
17
20
|
const singleQuoteStringLiteral = new And("single-string-literal", [
|
|
18
21
|
new Literal("single-quote", "'"),
|
|
19
|
-
new Repeat("characters",
|
|
20
|
-
new
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
new Repeat("characters",
|
|
23
|
+
new Or("characters", [
|
|
24
|
+
new Regex("normal-characters", "[^\\']+"),
|
|
25
|
+
escapedCharacter
|
|
26
|
+
]),
|
|
27
|
+
{ min: 0 }
|
|
28
|
+
),
|
|
23
29
|
new Literal("single-quote", "'"),
|
|
24
30
|
]);
|
|
25
31
|
|
package/src/patterns/And.test.ts
CHANGED
|
@@ -276,7 +276,7 @@ describe("And", () => {
|
|
|
276
276
|
const sequence = new And("sequence", [new Literal("a", "A")]);
|
|
277
277
|
const parent = new And("parent", [sequence, new Literal("b", "B")]);
|
|
278
278
|
|
|
279
|
-
const sequenceClone = parent.
|
|
279
|
+
const sequenceClone = parent.find(p => p.name === "sequence");
|
|
280
280
|
const tokens = sequenceClone?.getNextTokens() || [];
|
|
281
281
|
|
|
282
282
|
expect(tokens[0]).toBe("B");
|
|
@@ -289,13 +289,26 @@ describe("And", () => {
|
|
|
289
289
|
expect(tokens.length).toBe(0);
|
|
290
290
|
});
|
|
291
291
|
|
|
292
|
+
test("Get Patterns", () => {
|
|
293
|
+
const sequence = new And("sequence", [
|
|
294
|
+
new Literal("a", "A", true),
|
|
295
|
+
new Literal("b", "B"),
|
|
296
|
+
], true);
|
|
297
|
+
const tokens = sequence.getPatterns();
|
|
298
|
+
const a = sequence.find(p=>p.name === "a");
|
|
299
|
+
const b = sequence.find(p=>p.name === "b");
|
|
300
|
+
const expected = [a, b]
|
|
301
|
+
|
|
302
|
+
expect(tokens).toEqual(expected);
|
|
303
|
+
});
|
|
304
|
+
|
|
292
305
|
test("Get Next Patterns", () => {
|
|
293
306
|
const sequence = new And("sequence", [new Literal("a", "A")]);
|
|
294
307
|
const parent = new And("parent", [sequence, new Literal("b", "B")]);
|
|
295
308
|
|
|
296
|
-
const sequenceClone = parent.
|
|
309
|
+
const sequenceClone = parent.find(p => p.name === "sequence");
|
|
297
310
|
const nextPatterns = sequenceClone?.getNextPatterns() || [];
|
|
298
|
-
const b = parent.
|
|
311
|
+
const b = parent.find(p => p.name === "b")
|
|
299
312
|
|
|
300
313
|
expect(nextPatterns[0]).toBe(b);
|
|
301
314
|
});
|