clarity-pattern-parser 5.0.0 → 6.0.2

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.
Files changed (61) hide show
  1. package/README.md +328 -38
  2. package/TODO.md +63 -7
  3. package/dist/ast/Node.d.ts +8 -2
  4. package/dist/index.browser.js +520 -205
  5. package/dist/index.browser.js.map +1 -1
  6. package/dist/index.d.ts +6 -1
  7. package/dist/index.esm.js +519 -206
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +520 -205
  10. package/dist/index.js.map +1 -1
  11. package/dist/intellisense/AutoComplete.d.ts +34 -0
  12. package/dist/intellisense/Suggestion.d.ts +10 -0
  13. package/dist/intellisense/SuggestionOption.d.ts +4 -0
  14. package/dist/patterns/And.d.ts +8 -7
  15. package/dist/patterns/Cursor.d.ts +6 -4
  16. package/dist/patterns/CursorHistory.d.ts +2 -2
  17. package/dist/patterns/Literal.d.ts +8 -8
  18. package/dist/patterns/Not.d.ts +9 -5
  19. package/dist/patterns/Or.d.ts +8 -5
  20. package/dist/patterns/Pattern.d.ts +8 -4
  21. package/dist/patterns/Reference.d.ts +11 -7
  22. package/dist/patterns/Regex.d.ts +8 -8
  23. package/dist/patterns/Repeat.d.ts +8 -7
  24. package/package.json +1 -1
  25. package/src/ast/Node.test.ts +116 -0
  26. package/src/ast/Node.ts +71 -5
  27. package/src/index.ts +14 -3
  28. package/src/intellisense/AutoComplete.test.ts +168 -23
  29. package/src/intellisense/AutoComplete.ts +102 -21
  30. package/src/intellisense/Suggestion.ts +3 -4
  31. package/src/intellisense/javascript/Javascript.test.ts +86 -62
  32. package/src/intellisense/javascript/{expressionStatement.ts → assignment.ts} +7 -8
  33. package/src/intellisense/javascript/escapedCharacter.ts +0 -1
  34. package/src/intellisense/javascript/exponent.ts +0 -2
  35. package/src/intellisense/javascript/expression.ts +44 -26
  36. package/src/intellisense/javascript/fraction.ts +0 -2
  37. package/src/intellisense/javascript/infixOperator.ts +6 -2
  38. package/src/intellisense/javascript/keywords.ts +3 -0
  39. package/src/intellisense/javascript/objectAccess.ts +9 -0
  40. package/src/intellisense/javascript/objectLiteral.ts +3 -3
  41. package/src/intellisense/javascript/propertyAccess.ts +8 -3
  42. package/src/intellisense/javascript/stringLiteral.ts +16 -8
  43. package/src/patterns/And.test.ts +74 -50
  44. package/src/patterns/And.ts +72 -36
  45. package/src/patterns/Cursor.ts +17 -14
  46. package/src/patterns/CursorHistory.ts +8 -8
  47. package/src/patterns/Literal.test.ts +79 -38
  48. package/src/patterns/Literal.ts +34 -41
  49. package/src/patterns/Not.test.ts +99 -8
  50. package/src/patterns/Not.ts +58 -14
  51. package/src/patterns/Or.test.ts +128 -13
  52. package/src/patterns/Or.ts +46 -13
  53. package/src/patterns/Pattern.ts +8 -4
  54. package/src/patterns/Reference.test.ts +127 -28
  55. package/src/patterns/Reference.ts +62 -32
  56. package/src/patterns/Regex.test.ts +76 -35
  57. package/src/patterns/Regex.ts +35 -43
  58. package/src/patterns/Repeat.test.ts +72 -41
  59. package/src/patterns/Repeat.ts +55 -38
  60. package/src/patterns/getNextPattern.test.ts +0 -39
  61. package/src/patterns/getNextPattern.ts +0 -18
@@ -70,53 +70,22 @@ describe("Literal", () => {
70
70
  });
71
71
 
72
72
  test("Get Tokens", () => {
73
- const parent = new And("parent", [
74
- new Literal("a", "A"),
75
- new Literal("b", "B")
76
- ]);
73
+ const a = new Literal("a", "A");
77
74
 
78
- const a = parent.children[0] as Literal;
79
- const b = parent.children[1];
80
-
81
- let tokens = a.getTokens();
82
- let expectedTokens = ["A"];
83
-
84
- expect(tokens).toEqual(expectedTokens);
85
-
86
- a.enableContextualTokenAggregation();
87
-
88
- tokens = a.getTokens();
89
- expectedTokens = ["AB"];
90
-
91
- expect(tokens).toEqual(expectedTokens);
92
-
93
- a.disableContextualTokenAggregation();
94
-
95
- tokens = a.getTokens();
96
- expectedTokens = ["A"];
75
+ const tokens = a.getTokens();
76
+ const expectedTokens = ["A"];
97
77
 
98
78
  expect(tokens).toEqual(expectedTokens);
99
79
  });
100
80
 
101
- test("Get Next Tokens", () => {
81
+ test("Get Tokens After", () => {
102
82
  const literal = new Literal("a", "A");
103
- const tokens = literal.getNextTokens(new Literal("bogus", "bogus"));
83
+ const tokens = literal.getTokensAfter(new Literal("bogus", "bogus"));
104
84
  const expected: string[] = [];
105
85
 
106
86
  expect(tokens).toEqual(expected)
107
87
  });
108
88
 
109
- test("Get Next Pattern", () => {
110
- const parent = new And("parent", [
111
- new Literal("a", "A"),
112
- new Literal("b", "B")
113
- ]);
114
-
115
- const nextPattern = parent.children[0].getNextPattern();
116
-
117
- expect(nextPattern?.name).toBe("b")
118
- });
119
-
120
89
  test("Properties", () => {
121
90
  const literal = new Literal("a", "A");
122
91
 
@@ -126,9 +95,81 @@ describe("Literal", () => {
126
95
  expect(literal.children).toEqual([]);
127
96
  });
128
97
 
129
- test("Parse Text", () => {
98
+ test("Exec", () => {
130
99
  const literal = new Literal("a", "A");
131
- const { ast: result } = literal.parseText("B");
100
+ const { ast: result } = literal.exec("B");
132
101
  expect(result).toBeNull()
133
102
  });
103
+
104
+ test("Test With No Match", () => {
105
+ const literal = new Literal("a", "A");
106
+ const isMatch = literal.test("B");
107
+
108
+ expect(isMatch).toBeFalsy();
109
+ });
110
+
111
+ test("Test With Match", () => {
112
+ const literal = new Literal("a", "A");
113
+ const isMatch = literal.test("A");
114
+
115
+ expect(isMatch).toBeTruthy();
116
+ });
117
+
118
+ test("Get Next Tokens", () => {
119
+ const sequence = new And("sequence", [new Literal("a", "A")]);
120
+ const parent = new And("parent", [sequence, new Literal("b", "B")]);
121
+
122
+ const a = parent.findPattern(p => p.name === "a");
123
+ const tokens = a?.getNextTokens() || [];
124
+
125
+ expect(tokens[0]).toBe("B");
126
+ });
127
+
128
+ test("Get Next Tokens With Null Parent", () => {
129
+ const a = new Literal("a", "A");
130
+ const tokens = a.getNextTokens();
131
+
132
+ expect(tokens.length).toBe(0);
133
+ });
134
+
135
+ test("Get Patterns", () => {
136
+ const a = new Literal("a", "A");
137
+
138
+ const tokens = a.getPatterns();
139
+ const expectedTokens = [a];
140
+
141
+ expect(tokens).toEqual(expectedTokens);
142
+ });
143
+
144
+ test("Get Next Patterns", () => {
145
+ const sequence = new And("sequence", [new Literal("a", "A")]);
146
+ const parent = new And("parent", [sequence, new Literal("b", "B")]);
147
+
148
+ const a = parent.findPattern(p => p.name === "a");
149
+ const nextPatterns = a?.getNextPatterns() || [];
150
+ const b = parent.findPattern(p => p.name === "b")
151
+
152
+ expect(nextPatterns[0]).toBe(b);
153
+ });
154
+
155
+ test("Get Next Patterns With Null Parent", () => {
156
+ const a = new Literal("a", "A");
157
+ const nextPatterns = a.getNextPatterns();
158
+
159
+ expect(nextPatterns.length).toBe(0);
160
+ });
161
+
162
+ test("Get Patterns After", () => {
163
+ const a = new Literal("a", "A");
164
+ const patterns = a.getPatternsAfter();
165
+
166
+ expect(patterns.length).toBe(0);
167
+ });
168
+
169
+ test("Find Pattern", () => {
170
+ const a = new Literal("a", "A");
171
+ const pattern = a.findPattern(p => p.name === "nada");
172
+
173
+ expect(pattern).toBeNull();
174
+ });
134
175
  });
@@ -1,6 +1,5 @@
1
1
  import { Node } from "../ast/Node";
2
2
  import { Cursor } from "./Cursor";
3
- import { getNextPattern } from "./getNextPattern";
4
3
  import { Pattern } from "./Pattern";
5
4
 
6
5
  export class Literal implements Pattern {
@@ -12,8 +11,6 @@ export class Literal implements Pattern {
12
11
  private _runes: string[];
13
12
  private _firstIndex: number;
14
13
  private _lastIndex: number;
15
- private _hasContextualTokenAggregation: boolean;
16
- private _isRetrievingContextualTokens: boolean;
17
14
 
18
15
  get type(): string {
19
16
  return this._type;
@@ -40,10 +37,10 @@ export class Literal implements Pattern {
40
37
  }
41
38
 
42
39
  constructor(name: string, value: string, isOptional = false) {
43
- if (value.length === 0){
40
+ if (value.length === 0) {
44
41
  throw new Error("Value Cannot be empty.");
45
42
  }
46
-
43
+
47
44
  this._type = "literal";
48
45
  this._name = name;
49
46
  this._literal = value;
@@ -52,16 +49,21 @@ export class Literal implements Pattern {
52
49
  this._parent = null;
53
50
  this._firstIndex = 0;
54
51
  this._lastIndex = 0;
55
- this._hasContextualTokenAggregation = false;
56
- this._isRetrievingContextualTokens = false;
57
52
  }
58
53
 
59
- parseText(text: string) {
54
+ test(text: string) {
55
+ const cursor = new Cursor(text);
56
+ const ast = this.parse(cursor);
57
+
58
+ return ast?.value === text;
59
+ }
60
+
61
+ exec(text: string) {
60
62
  const cursor = new Cursor(text);
61
- const ast = this.parse(cursor)
63
+ const ast = this.parse(cursor);
62
64
 
63
65
  return {
64
- ast,
66
+ ast: ast?.value === text ? ast : null,
65
67
  cursor
66
68
  };
67
69
  }
@@ -123,59 +125,50 @@ export class Literal implements Pattern {
123
125
  this._name,
124
126
  this._firstIndex,
125
127
  this._lastIndex,
126
- [],
128
+ undefined,
127
129
  this._literal
128
130
  );
129
131
  }
130
132
 
131
133
  clone(name = this._name, isOptional = this._isOptional): Pattern {
132
134
  const clone = new Literal(name, this._literal, isOptional);
133
- clone._hasContextualTokenAggregation = this._hasContextualTokenAggregation;
134
135
  return clone;
135
136
  }
136
137
 
137
138
  getTokens(): string[] {
138
- const parent = this._parent;
139
-
140
- if (
141
- this._hasContextualTokenAggregation &&
142
- parent != null &&
143
- !this._isRetrievingContextualTokens
144
- ) {
145
- this._isRetrievingContextualTokens = true;
146
-
147
- const aggregateTokens: string[] = [];
148
- const nextTokens = parent.getNextTokens(this);
139
+ return [this._literal];
140
+ }
149
141
 
150
- for (const nextToken of nextTokens) {
151
- aggregateTokens.push(this._literal + nextToken);
152
- }
142
+ getTokensAfter(_lastMatched: Pattern): string[] {
143
+ return [];
144
+ }
153
145
 
154
- this._isRetrievingContextualTokens = false;
155
- return aggregateTokens;
156
- } else {
157
- return [this._literal];
146
+ getNextTokens(): string[] {
147
+ if (this.parent == null) {
148
+ return []
158
149
  }
159
- }
160
150
 
161
- getNextTokens(_lastMatched: Pattern): string[] {
162
- return [];
151
+ return this.parent.getTokensAfter(this);
163
152
  }
164
153
 
165
- getNextPattern(): Pattern | null {
166
- return getNextPattern(this)
154
+ getPatterns(): Pattern[] {
155
+ return [this];
167
156
  }
168
157
 
169
- findPattern(_isMatch: (p: Pattern) => boolean): Pattern | null {
170
- return null;
158
+ getPatternsAfter(): Pattern[] {
159
+ return []
171
160
  }
172
161
 
173
- enableContextualTokenAggregation(): void {
174
- this._hasContextualTokenAggregation = true;
162
+ getNextPatterns(): Pattern[] {
163
+ if (this.parent == null) {
164
+ return [];
165
+ }
166
+
167
+ return this.parent.getPatternsAfter(this)
175
168
  }
176
169
 
177
- disableContextualTokenAggregation(): void {
178
- this._hasContextualTokenAggregation = false;
170
+ findPattern(_predicate: (p: Pattern) => boolean): Pattern | null {
171
+ return null;
179
172
  }
180
173
 
181
174
  }
@@ -2,6 +2,7 @@ import { And } from "./And";
2
2
  import { Cursor } from "./Cursor";
3
3
  import { Literal } from "./Literal";
4
4
  import { Not } from "./Not";
5
+ import { Pattern } from "./Pattern";
5
6
 
6
7
  describe("Not", () => {
7
8
  test("Parse Successfully", () => {
@@ -37,7 +38,7 @@ describe("Not", () => {
37
38
  const a = new Literal("a", "A");
38
39
  const notA = new Not("not-a", a);
39
40
  const tokens = notA.getTokens();
40
- const nextTokens = notA.getNextTokens(new Literal("bogus", "bogus"))
41
+ const nextTokens = notA.getTokensAfter(new Literal("bogus", "bogus"))
41
42
  const emptyArray: string[] = [];
42
43
 
43
44
  expect(tokens).toEqual(emptyArray);
@@ -67,22 +68,112 @@ describe("Not", () => {
67
68
  expect(cursor.hasError).toBeFalsy();
68
69
  });
69
70
 
70
- test("Parse Text", () => {
71
+ test("Exec", () => {
71
72
  const a = new Literal("a", "A");
72
73
  const notA = new Not("not-a", a);
73
- const { ast: result } = notA.parseText("A");
74
+ const { ast: result } = notA.exec("A");
74
75
 
75
76
  expect(result).toBeNull();
76
77
  });
77
78
 
78
- test("Get Next Pattern", () => {
79
+ test("Test", () => {
79
80
  const a = new Literal("a", "A");
80
- const b = new Literal("b", "B");
81
81
  const notA = new Not("not-a", a);
82
+ const result = notA.test("A");
82
83
 
83
- const parent = new And("parent", [notA, b]);
84
- const nextPattern = parent.children[0].getNextPattern();
84
+ expect(result).toBeFalsy();
85
+ });
86
+
87
+ test("Get Next Tokens", () => {
88
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
89
+ const sequence = new And("sequence", [notAboutUs, new Literal("about-them", "About Them")]);
90
+
91
+ const cloneNotAboutUs = sequence.findPattern(p => p.name === "not-about-us") as Pattern;
92
+ const nextTokens = cloneNotAboutUs.getNextTokens() || [];
93
+
94
+ expect(nextTokens[0]).toBe("About Them");
95
+ });
96
+
97
+ test("Get Next Tokens With No Parent", () => {
98
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
99
+ const nextTokens = notAboutUs.getNextTokens() || [];
100
+
101
+ expect(nextTokens.length).toBe(0);
102
+ });
103
+
104
+ test("Get Tokens", () => {
105
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
106
+ const sequence = new And("sequence", [notAboutUs, new Literal("about-them", "About Them")]);
107
+
108
+ const cloneNotAboutUs = sequence.findPattern(p => p.name === "not-about-us") as Pattern;
109
+ const nextTokens = cloneNotAboutUs.getTokens() || [];
110
+
111
+ expect(nextTokens[0]).toBe("About Them");
112
+ });
113
+
114
+ test("Get Tokens After", () => {
115
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
116
+ const sequence = new And("sequence", [notAboutUs, new Literal("about-them", "About Them")]);
117
+ const notAboutUsClone = sequence.findPattern(p => p.name === "not-about-us") as Pattern;
118
+ const aboutUsClone = sequence.findPattern(p => p.name === "about-us") as Pattern;
119
+ const nextTokens = notAboutUsClone.getTokensAfter(aboutUsClone) || [];
120
+
121
+ expect(nextTokens[0]).toBe("About Them");
122
+ });
123
+
124
+ test("Find Pattern", () => {
125
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
126
+ const child = notAboutUs.findPattern(p => p.name === "about-us")
127
+
128
+ expect(child).not.toBeNull();
129
+ });
130
+
131
+ test("Get Patterns", () => {
132
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
133
+ const sequence = new And("sequence", [notAboutUs, new Literal("about-them", "About Them")]);
134
+
135
+ const cloneNotAboutUs = sequence.findPattern(p => p.name === "not-about-us") as Pattern;
136
+ const nextPatterns = cloneNotAboutUs.getPatterns();
137
+ const expected = [sequence.findPattern(p=>p.name === "about-them")];
85
138
 
86
- expect(nextPattern?.name).toBe("b");
139
+ expect(nextPatterns).toEqual(expected);
87
140
  });
141
+
142
+ test("Get Next Patterns", () => {
143
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
144
+ const sequence = new And("sequence", [notAboutUs, new Literal("about-them", "About Them")]);
145
+
146
+ const cloneNotAboutUs = sequence.findPattern(p => p.name === "not-about-us") as Pattern;
147
+ const patterns = cloneNotAboutUs.getNextPatterns() || [];
148
+
149
+ expect(patterns.length).toBe(1);
150
+ expect(patterns[0].name).toBe("about-them");
151
+ });
152
+
153
+ test("Get Next Patterns With No Parent", () => {
154
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
155
+ const patterns = notAboutUs.getNextPatterns() || [];
156
+
157
+ expect(patterns.length).toBe(0);
158
+ });
159
+
160
+ test("Get Patterns After", () => {
161
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
162
+ const sequence = new And("sequence", [notAboutUs, new Literal("about-them", "About Them")]);
163
+ const notAboutUsClone = sequence.findPattern(p => p.name === "not-about-us") as Pattern;
164
+ const aboutUsClone = sequence.findPattern(p => p.name === "about-us") as Pattern;
165
+ const patterns = notAboutUsClone.getPatternsAfter(aboutUsClone) || [];
166
+
167
+ expect(patterns.length).toBe(1);
168
+ expect(patterns[0].name).toBe("about-them");
169
+ });
170
+
171
+ test("Get Patterns After With Null Parent", () => {
172
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
173
+ const aboutUsClone = notAboutUs.findPattern(p => p.name === "about-us") as Pattern;
174
+ const patterns = notAboutUs.getPatternsAfter(aboutUsClone) || [];
175
+
176
+ expect(patterns.length).toBe(0);
177
+ });
178
+
88
179
  });
@@ -1,6 +1,5 @@
1
1
  import { Node } from "../ast/Node";
2
2
  import { Cursor } from "./Cursor";
3
- import { getNextPattern } from "./getNextPattern";
4
3
  import { Pattern } from "./Pattern";
5
4
 
6
5
  export class Not implements Pattern {
@@ -17,10 +16,6 @@ export class Not implements Pattern {
17
16
  return this._name;
18
17
  }
19
18
 
20
- get isOptional(): boolean {
21
- return false;
22
- }
23
-
24
19
  get parent(): Pattern | null {
25
20
  return this._parent;
26
21
  }
@@ -33,6 +28,10 @@ export class Not implements Pattern {
33
28
  return this._children;
34
29
  }
35
30
 
31
+ get isOptional(): boolean {
32
+ return false;
33
+ }
34
+
36
35
  constructor(name: string, pattern: Pattern) {
37
36
  this._type = "not";
38
37
  this._name = name;
@@ -41,9 +40,16 @@ export class Not implements Pattern {
41
40
  this._children[0].parent = this;
42
41
  }
43
42
 
44
- parseText(text: string) {
43
+ test(text: string) {
44
+ const cursor = new Cursor(text);
45
+ this.parse(cursor);
46
+
47
+ return !cursor.hasError;
48
+ }
49
+
50
+ exec(text: string) {
45
51
  const cursor = new Cursor(text);
46
- const ast = this.parse(cursor)
52
+ const ast = this.parse(cursor);
47
53
 
48
54
  return {
49
55
  ast,
@@ -72,20 +78,58 @@ export class Not implements Pattern {
72
78
  return not;
73
79
  }
74
80
 
75
- getNextPattern(): Pattern | null {
76
- return getNextPattern(this)
77
- }
78
-
79
81
  getTokens(): string[] {
82
+ const parent = this._parent;
83
+
84
+ if (parent != null) {
85
+ return parent.getTokensAfter(this);
86
+ }
87
+
80
88
  return [];
81
89
  }
82
90
 
83
- getNextTokens(_lastMatched: Pattern): string[] {
91
+ getTokensAfter(_childReference: Pattern): string[] {
92
+ const parent = this._parent;
93
+
94
+ if (parent != null) {
95
+ return parent.getTokensAfter(this);
96
+ }
97
+
84
98
  return [];
85
99
  }
86
100
 
87
- findPattern(isMatch: (p: Pattern) => boolean): Pattern | null {
88
- return isMatch(this._children[0]) ? this._children[0] : null;
101
+ getNextTokens(): string[] {
102
+ if (this.parent == null) {
103
+ return []
104
+ }
105
+
106
+ return this.parent.getTokensAfter(this);
107
+ }
108
+
109
+ getPatterns(): Pattern[] {
110
+ return [...this.getNextPatterns().map(p => p.getPatterns()).flat()];
111
+ }
112
+
113
+ getPatternsAfter(_childReference: Pattern): Pattern[] {
114
+ const parent = this._parent;
115
+
116
+ if (parent != null) {
117
+ return parent.getPatternsAfter(this);
118
+ }
119
+
120
+ return []
121
+ }
122
+
123
+ getNextPatterns(): Pattern[] {
124
+ if (this.parent == null) {
125
+ return [];
126
+ }
127
+
128
+ return this.parent.getPatternsAfter(this)
129
+ }
130
+
131
+ findPattern(predicate: (p: Pattern) => boolean): Pattern | null {
132
+ return predicate(this._children[0]) ? this._children[0] : null;
89
133
  }
90
134
 
91
135
  }