clarity-pattern-parser 10.1.15 → 10.1.17
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/dist/index.browser.js +35 -33
- package/dist/index.browser.js.map +1 -1
- package/dist/index.esm.js +35 -33
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +35 -33
- package/dist/index.js.map +1 -1
- package/dist/patterns/Options.d.ts +0 -1
- package/dist/patterns/Sequence.d.ts +0 -1
- package/package.json +1 -1
- package/src/grammar/Grammar.test.ts +0 -3
- package/src/intellisense/AutoComplete.test.ts +1 -28
- package/src/intellisense/AutoComplete.ts +11 -14
- package/src/intellisense/javascript/Javascript.test.ts +3 -1
- package/src/patterns/DepthCache.ts +26 -0
- package/src/patterns/Options.ts +13 -24
- package/src/patterns/Sequence.ts +7 -20
- package/src/grammar/ComplexGrammar.test.ts +0 -16
|
@@ -22,7 +22,6 @@ export declare class Options implements Pattern {
|
|
|
22
22
|
exec(text: string, record?: boolean): ParseResult;
|
|
23
23
|
parse(cursor: Cursor): Node | null;
|
|
24
24
|
private _tryToParse;
|
|
25
|
-
private _isBeyondRecursiveDepth;
|
|
26
25
|
getTokens(): string[];
|
|
27
26
|
getTokensAfter(_childReference: Pattern): string[];
|
|
28
27
|
getNextTokens(): string[];
|
package/package.json
CHANGED
|
@@ -9,7 +9,6 @@ import { Repeat } from "../patterns/Repeat";
|
|
|
9
9
|
import { Grammar } from "./Grammar";
|
|
10
10
|
import { Optional } from "../patterns/Optional";
|
|
11
11
|
import { Context } from "../patterns/Context";
|
|
12
|
-
import { patterns } from "..";
|
|
13
12
|
|
|
14
13
|
describe("Grammar", () => {
|
|
15
14
|
test("Literal", () => {
|
|
@@ -570,6 +569,4 @@ describe("Grammar", () => {
|
|
|
570
569
|
const result = fullname.exec("John Doe");
|
|
571
570
|
expect(result?.ast?.value).toBe("John Doe");
|
|
572
571
|
});
|
|
573
|
-
|
|
574
|
-
|
|
575
572
|
});
|
|
@@ -490,31 +490,4 @@ describe("AutoComplete", () => {
|
|
|
490
490
|
expect(results.options).toEqual(expected);
|
|
491
491
|
});
|
|
492
492
|
|
|
493
|
-
|
|
494
|
-
const branchOne = new Sequence("branch-1", [
|
|
495
|
-
new Literal("space-1-1", " "),
|
|
496
|
-
new Literal("space-1-2", " "),
|
|
497
|
-
new Options('branch-1-options', [
|
|
498
|
-
new Literal("AA", "AA"),
|
|
499
|
-
new Literal("AB", "AB"),
|
|
500
|
-
])
|
|
501
|
-
]);
|
|
502
|
-
const branchTwo = new Sequence("branch-2", [
|
|
503
|
-
new Literal("space-2-1", " "),
|
|
504
|
-
new Literal("space-2-2", " "),
|
|
505
|
-
new Options('branch-2-options', [
|
|
506
|
-
new Literal("BA", "BA"),
|
|
507
|
-
new Literal("BB", "BB")
|
|
508
|
-
])
|
|
509
|
-
]);
|
|
510
|
-
const eitherBranch = new Options("either-branch", [branchOne, branchTwo]);
|
|
511
|
-
|
|
512
|
-
const autoComplete = new AutoComplete(eitherBranch);
|
|
513
|
-
const results = autoComplete.suggestFor(" B");
|
|
514
|
-
const expected = [
|
|
515
|
-
{ startIndex: 3, text: "A" },
|
|
516
|
-
{ startIndex: 3, text: "B" },
|
|
517
|
-
];
|
|
518
|
-
expect(results.options).toEqual(expected);
|
|
519
|
-
})
|
|
520
|
-
});
|
|
493
|
+
});
|
|
@@ -76,10 +76,9 @@ export class AutoComplete {
|
|
|
76
76
|
errorAtIndex = this._cursor.furthestError.endIndex;
|
|
77
77
|
error = this._cursor.furthestError;
|
|
78
78
|
|
|
79
|
-
errorAtIndex = options.reduce(
|
|
80
|
-
|
|
81
|
-
errorAtIndex
|
|
82
|
-
);
|
|
79
|
+
errorAtIndex = options.reduce((errorAtIndex, option) =>
|
|
80
|
+
Math.max(errorAtIndex, option.startIndex),
|
|
81
|
+
errorAtIndex);
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
return {
|
|
@@ -99,19 +98,17 @@ export class AutoComplete {
|
|
|
99
98
|
|
|
100
99
|
private _getAllOptions() {
|
|
101
100
|
const errorMatches = this._getOptionsFromErrors();
|
|
102
|
-
const
|
|
101
|
+
const leafMatches = this._cursor.leafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
|
|
102
|
+
const finalResults: SuggestionOption[] = [];
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
[...leafMatchSuggestions, ...errorMatches].forEach(m=>{
|
|
108
|
-
const index = uniqueResults.findIndex(f => m.text === f.text);
|
|
104
|
+
[...leafMatches, ...errorMatches].forEach(m=>{
|
|
105
|
+
const index = finalResults.findIndex(f=> m.text === f.text);
|
|
109
106
|
if (index === -1){
|
|
110
|
-
|
|
107
|
+
finalResults.push(m);
|
|
111
108
|
}
|
|
112
109
|
});
|
|
113
110
|
|
|
114
|
-
return
|
|
111
|
+
return finalResults;
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
private _getOptionsFromErrors() {
|
|
@@ -121,9 +118,9 @@ export class AutoComplete {
|
|
|
121
118
|
const tokens = this._getTokensForPattern(e.pattern);
|
|
122
119
|
const adjustedTokens = tokens.map(t => t.slice(e.endIndex - e.startIndex));
|
|
123
120
|
return this._createSuggestions(e.endIndex, adjustedTokens);
|
|
124
|
-
})
|
|
121
|
+
});
|
|
125
122
|
|
|
126
|
-
return suggestions;
|
|
123
|
+
return suggestions.flat();
|
|
127
124
|
}
|
|
128
125
|
|
|
129
126
|
private _createSuggestionsFromRoot(): SuggestionOption[] {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export class DepthCache {
|
|
2
|
+
private _depthMap: Record<string, Record<number, number>> = {};
|
|
3
|
+
|
|
4
|
+
getDepth(name: string, cursorIndex: number) {
|
|
5
|
+
if (this._depthMap[name] == null) {
|
|
6
|
+
this._depthMap[name] = {};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (this._depthMap[name][cursorIndex] == null) {
|
|
10
|
+
this._depthMap[name][cursorIndex] = 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
return this._depthMap[name][cursorIndex];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
incrementDepth(name: string, cursorIndex: number) {
|
|
18
|
+
const depth = this.getDepth(name, cursorIndex);
|
|
19
|
+
this._depthMap[name][cursorIndex] = depth + 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
decrementDepth(name: string, cursorIndex: number) {
|
|
23
|
+
const depth = this.getDepth(name, cursorIndex);
|
|
24
|
+
this._depthMap[name][cursorIndex] = depth - 1;
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/patterns/Options.ts
CHANGED
|
@@ -4,10 +4,13 @@ import { Pattern } from "./Pattern";
|
|
|
4
4
|
import { clonePatterns } from "./clonePatterns";
|
|
5
5
|
import { findPattern } from "./findPattern";
|
|
6
6
|
import { ParseResult } from "./ParseResult";
|
|
7
|
+
import { DepthCache } from './DepthCache';
|
|
7
8
|
|
|
8
9
|
/*
|
|
9
10
|
The following is created to reduce the overhead of recursion check.
|
|
10
11
|
*/
|
|
12
|
+
|
|
13
|
+
const depthCache = new DepthCache();
|
|
11
14
|
let idIndex = 0;
|
|
12
15
|
|
|
13
16
|
export class Options implements Pattern {
|
|
@@ -87,9 +90,13 @@ export class Options implements Pattern {
|
|
|
87
90
|
|
|
88
91
|
parse(cursor: Cursor): Node | null {
|
|
89
92
|
// This is a cache to help with speed
|
|
93
|
+
this._firstIndex = cursor.index;
|
|
94
|
+
depthCache.incrementDepth(this._id, this._firstIndex);
|
|
95
|
+
|
|
90
96
|
this._firstIndex = cursor.index;
|
|
91
97
|
const node = this._tryToParse(cursor);
|
|
92
98
|
|
|
99
|
+
depthCache.decrementDepth(this._id, this._firstIndex);
|
|
93
100
|
|
|
94
101
|
if (node != null) {
|
|
95
102
|
cursor.moveTo(node.lastIndex);
|
|
@@ -101,16 +108,17 @@ export class Options implements Pattern {
|
|
|
101
108
|
return null;
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
private _tryToParse(cursor: Cursor): Node | null {
|
|
105
|
-
let children = this.children;
|
|
106
111
|
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
|
|
113
|
+
private _tryToParse(cursor: Cursor): Node | null {
|
|
114
|
+
if (depthCache.getDepth(this._id, this._firstIndex) > 2) {
|
|
115
|
+
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
116
|
+
return null;
|
|
109
117
|
}
|
|
110
118
|
|
|
111
119
|
const results: (Node | null)[] = [];
|
|
112
120
|
|
|
113
|
-
for (const pattern of
|
|
121
|
+
for (const pattern of this._children) {
|
|
114
122
|
cursor.moveTo(this._firstIndex);
|
|
115
123
|
let result = null;
|
|
116
124
|
|
|
@@ -133,25 +141,6 @@ export class Options implements Pattern {
|
|
|
133
141
|
return nonNullResults[0] || null;
|
|
134
142
|
}
|
|
135
143
|
|
|
136
|
-
private _isBeyondRecursiveDepth() {
|
|
137
|
-
let depth = 0;
|
|
138
|
-
let pattern: Pattern | null = this;
|
|
139
|
-
|
|
140
|
-
while (pattern != null) {
|
|
141
|
-
if (pattern.id === this.id) {
|
|
142
|
-
depth++;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (depth >= this.children.length) {
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
pattern = pattern.parent;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
144
|
getTokens(): string[] {
|
|
156
145
|
const tokens: string[] = [];
|
|
157
146
|
|
package/src/patterns/Sequence.ts
CHANGED
|
@@ -4,7 +4,9 @@ import { Node } from "../ast/Node";
|
|
|
4
4
|
import { clonePatterns } from "./clonePatterns";
|
|
5
5
|
import { filterOutNull } from "./filterOutNull";
|
|
6
6
|
import { findPattern } from "./findPattern";
|
|
7
|
+
import { DepthCache } from "./DepthCache";
|
|
7
8
|
|
|
9
|
+
const depthCache = new DepthCache();
|
|
8
10
|
let idIndex = 0;
|
|
9
11
|
|
|
10
12
|
export class Sequence implements Pattern {
|
|
@@ -85,8 +87,12 @@ export class Sequence implements Pattern {
|
|
|
85
87
|
parse(cursor: Cursor): Node | null {
|
|
86
88
|
// This is a cache to help with speed
|
|
87
89
|
this._firstIndex = cursor.index;
|
|
90
|
+
depthCache.incrementDepth(this._id, this._firstIndex);
|
|
91
|
+
|
|
88
92
|
this._nodes = [];
|
|
93
|
+
|
|
89
94
|
const passed = this.tryToParse(cursor);
|
|
95
|
+
depthCache.decrementDepth(this._id, this._firstIndex);
|
|
90
96
|
|
|
91
97
|
if (passed) {
|
|
92
98
|
const node = this.createNode(cursor);
|
|
@@ -102,7 +108,7 @@ export class Sequence implements Pattern {
|
|
|
102
108
|
}
|
|
103
109
|
|
|
104
110
|
private tryToParse(cursor: Cursor): boolean {
|
|
105
|
-
if (this.
|
|
111
|
+
if (depthCache.getDepth(this._id, this._firstIndex) > 1) {
|
|
106
112
|
cursor.recordErrorAt(this._firstIndex, this._firstIndex, this);
|
|
107
113
|
return false;
|
|
108
114
|
}
|
|
@@ -167,25 +173,6 @@ export class Sequence implements Pattern {
|
|
|
167
173
|
return passed;
|
|
168
174
|
}
|
|
169
175
|
|
|
170
|
-
private _isBeyondRecursiveDepth() {
|
|
171
|
-
let depth = 0;
|
|
172
|
-
let pattern: Pattern | null = this;
|
|
173
|
-
|
|
174
|
-
while (pattern != null) {
|
|
175
|
-
if (pattern.id === this.id && this._firstIndex === (pattern as Sequence)._firstIndex) {
|
|
176
|
-
depth++;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (depth > 1) {
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
pattern = pattern.parent;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
176
|
private getLastValidNode(): Node | null {
|
|
190
177
|
const nodes = filterOutNull(this._nodes);
|
|
191
178
|
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { patterns } from "./patterns";
|
|
2
|
-
|
|
3
|
-
describe("Complex Grammar Tests", () => {
|
|
4
|
-
test("Nested", () => {
|
|
5
|
-
const { expression } = patterns`
|
|
6
|
-
integer = /[0-9]+/
|
|
7
|
-
variable = /[A-Za-z][A-Za-z0-9]*/
|
|
8
|
-
space = /\\s+/
|
|
9
|
-
or-expression = expression + space? + "||" + space? + expression
|
|
10
|
-
mult-expression = expression + space? + "*" + space? + expression
|
|
11
|
-
expression = or-expression | mult-expression | integer | variable
|
|
12
|
-
`;
|
|
13
|
-
const result = expression.exec("a * b || c");
|
|
14
|
-
expect(result.ast?.toString()).toBe("a * b || c");
|
|
15
|
-
});
|
|
16
|
-
});
|