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.
@@ -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[];
@@ -24,7 +24,6 @@ export declare class Sequence implements Pattern {
24
24
  };
25
25
  parse(cursor: Cursor): Node | null;
26
26
  private tryToParse;
27
- private _isBeyondRecursiveDepth;
28
27
  private getLastValidNode;
29
28
  private areRemainingPatternsOptional;
30
29
  private createNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clarity-pattern-parser",
3
- "version": "10.1.15",
3
+ "version": "10.1.17",
4
4
  "description": "Parsing Library for Typescript and Javascript.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",
@@ -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
- test("Furthest Error", () => {
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
- (errorAtIndex, option) => Math.max(errorAtIndex, option.startIndex),
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 validLeafMatches = this._cursor.leafMatches.filter(v => v.node?.lastIndex === this._cursor.getLastIndex())
101
+ const leafMatches = this._cursor.leafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
102
+ const finalResults: SuggestionOption[] = [];
103
103
 
104
- const leafMatchSuggestions = validLeafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
105
- const uniqueResults: SuggestionOption[] = [];
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
- uniqueResults.push(m);
107
+ finalResults.push(m);
111
108
  }
112
109
  });
113
110
 
114
- return uniqueResults;
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
- }).flat();
121
+ });
125
122
 
126
- return suggestions;
123
+ return suggestions.flat();
127
124
  }
128
125
 
129
126
  private _createSuggestionsFromRoot(): SuggestionOption[] {
@@ -220,4 +220,6 @@ describe("Ecmascript 3", () => {
220
220
  result = expression.exec(`name.prop.anotherProp["Ha"][coolYo] === 1`);
221
221
  expect(result.ast?.value).toBe(`name.prop.anotherProp["Ha"][coolYo] === 1`);
222
222
  });
223
- });
223
+
224
+
225
+ });
@@ -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
+ }
@@ -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
- if (this._isBeyondRecursiveDepth()) {
108
- children = children.slice().reverse();
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 children) {
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
 
@@ -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._isBeyondRecursiveDepth()) {
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
- });