clarity-pattern-parser 5.0.0 → 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.
Files changed (53) hide show
  1. package/README.md +328 -38
  2. package/TODO.md +55 -1
  3. package/dist/ast/Node.d.ts +8 -2
  4. package/dist/index.browser.js +470 -205
  5. package/dist/index.browser.js.map +1 -1
  6. package/dist/index.d.ts +6 -1
  7. package/dist/index.esm.js +469 -206
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +470 -205
  10. package/dist/index.js.map +1 -1
  11. package/dist/intellisense/AutoComplete.d.ts +28 -0
  12. package/dist/intellisense/Suggestion.d.ts +11 -0
  13. package/dist/intellisense/SuggestionOption.d.ts +4 -0
  14. package/dist/patterns/And.d.ts +7 -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 +7 -8
  18. package/dist/patterns/Not.d.ts +8 -5
  19. package/dist/patterns/Or.d.ts +7 -5
  20. package/dist/patterns/Pattern.d.ts +7 -4
  21. package/dist/patterns/Reference.d.ts +10 -7
  22. package/dist/patterns/Regex.d.ts +7 -8
  23. package/dist/patterns/Repeat.d.ts +7 -7
  24. package/package.json +1 -1
  25. package/src/ast/Node.test.ts +110 -0
  26. package/src/ast/Node.ts +71 -5
  27. package/src/index.ts +14 -3
  28. package/src/intellisense/AutoComplete.test.ts +90 -12
  29. package/src/intellisense/AutoComplete.ts +66 -12
  30. package/src/intellisense/Suggestion.ts +3 -4
  31. package/src/intellisense/javascript/Javascript.test.ts +56 -56
  32. package/src/intellisense/javascript/escapedCharacter.ts +0 -1
  33. package/src/intellisense/javascript/exponent.ts +0 -2
  34. package/src/intellisense/javascript/fraction.ts +0 -2
  35. package/src/patterns/And.test.ts +63 -52
  36. package/src/patterns/And.ts +58 -36
  37. package/src/patterns/Cursor.ts +17 -14
  38. package/src/patterns/CursorHistory.ts +8 -8
  39. package/src/patterns/Literal.test.ts +70 -38
  40. package/src/patterns/Literal.ts +31 -42
  41. package/src/patterns/Not.test.ts +88 -8
  42. package/src/patterns/Not.ts +54 -14
  43. package/src/patterns/Or.test.ts +117 -13
  44. package/src/patterns/Or.ts +36 -13
  45. package/src/patterns/Pattern.ts +7 -4
  46. package/src/patterns/Reference.test.ts +117 -28
  47. package/src/patterns/Reference.ts +58 -32
  48. package/src/patterns/Regex.test.ts +67 -35
  49. package/src/patterns/Regex.ts +31 -43
  50. package/src/patterns/Repeat.test.ts +63 -41
  51. package/src/patterns/Repeat.ts +51 -38
  52. package/src/patterns/getNextPattern.test.ts +0 -39
  53. package/src/patterns/getNextPattern.ts +0 -18
@@ -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,101 @@ 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
+ });
85
123
 
86
- expect(nextPattern?.name).toBe("b");
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 Next 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 patterns = cloneNotAboutUs.getNextPatterns() || [];
137
+
138
+ expect(patterns.length).toBe(1);
139
+ expect(patterns[0].name).toBe("about-them");
140
+ });
141
+
142
+ test("Get Next Patterns With No Parent", () => {
143
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
144
+ const patterns = notAboutUs.getNextPatterns() || [];
145
+
146
+ expect(patterns.length).toBe(0);
87
147
  });
148
+
149
+ test("Get Patterns After", () => {
150
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
151
+ const sequence = new And("sequence", [notAboutUs, new Literal("about-them", "About Them")]);
152
+ const notAboutUsClone = sequence.findPattern(p => p.name === "not-about-us") as Pattern;
153
+ const aboutUsClone = sequence.findPattern(p => p.name === "about-us") as Pattern;
154
+ const patterns = notAboutUsClone.getPatternsAfter(aboutUsClone) || [];
155
+
156
+ expect(patterns.length).toBe(1);
157
+ expect(patterns[0].name).toBe("about-them");
158
+ });
159
+
160
+ test("Get Patterns After With Null Parent", () => {
161
+ const notAboutUs = new Not("not-about-us", new Literal("about-us", "About Us"));
162
+ const aboutUsClone = notAboutUs.findPattern(p => p.name === "about-us") as Pattern;
163
+ const patterns = notAboutUs.getPatternsAfter(aboutUsClone) || [];
164
+
165
+ expect(patterns.length).toBe(0);
166
+ });
167
+
88
168
  });
@@ -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) {
45
44
  const cursor = new Cursor(text);
46
- const ast = this.parse(cursor)
45
+ this.parse(cursor);
46
+
47
+ return !cursor.hasError;
48
+ }
49
+
50
+ exec(text: string) {
51
+ const cursor = new Cursor(text);
52
+ const ast = this.parse(cursor);
47
53
 
48
54
  return {
49
55
  ast,
@@ -72,20 +78,54 @@ 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
+ getPatternsAfter(_childReference: Pattern): Pattern[] {
110
+ const parent = this._parent;
111
+
112
+ if (parent != null) {
113
+ return parent.getPatternsAfter(this);
114
+ }
115
+
116
+ return []
117
+ }
118
+
119
+ getNextPatterns(): Pattern[] {
120
+ if (this.parent == null) {
121
+ return [];
122
+ }
123
+
124
+ return this.parent.getPatternsAfter(this)
125
+ }
126
+
127
+ findPattern(predicate: (p: Pattern) => boolean): Pattern | null {
128
+ return predicate(this._children[0]) ? this._children[0] : null;
89
129
  }
90
130
 
91
131
  }
@@ -3,6 +3,7 @@ import { Node } from "../ast/Node";
3
3
  import { Literal } from "./Literal";
4
4
  import { Or } from "./Or";
5
5
  import { And } from "./And";
6
+ import { Pattern } from "./Pattern";
6
7
 
7
8
  describe("Or", () => {
8
9
  test("Empty Options", () => {
@@ -63,30 +64,23 @@ describe("Or", () => {
63
64
  expect(tokens).toEqual(expected);
64
65
  });
65
66
 
66
- test("Get Next Tokens", () => {
67
+ test("Get Tokens After", () => {
67
68
  const a = new Or("a", [new Literal("a", "A")]);
68
69
  const parent = new And("parent", [a, new Literal("b", "B")]);
69
- const tokens = parent.children[0].getNextTokens(parent.children[0].children[0]);
70
+ const tokens = parent.children[0].getTokensAfter(parent.children[0].children[0]);
70
71
  const expected = ["B"];
71
72
 
72
73
  expect(tokens).toEqual(expected);
73
74
  });
74
75
 
75
- test("Get Next Tokens Without A Parent", () => {
76
+ test("Get Tokens After Without A Parent", () => {
76
77
  const a = new Or("a", [new Literal("a", "A")]);
77
- const tokens = a.getNextTokens(a.children[0]);
78
+ const tokens = a.getTokensAfter(a.children[0]);
78
79
  const expected: string[] = [];
79
80
 
80
81
  expect(tokens).toEqual(expected);
81
82
  });
82
83
 
83
- test("Get Next Pattern", () => {
84
- const a = new Or("a", [new Literal("a", "A")]);
85
- const nextToken = a.getNextPattern();
86
-
87
- expect(nextToken).toBeNull();
88
- });
89
-
90
84
  test("Properties", () => {
91
85
  const a = new Or("a", [new Literal("a", "A")]);
92
86
 
@@ -97,9 +91,119 @@ describe("Or", () => {
97
91
  expect(a.children[0].name).toBe("a");
98
92
  });
99
93
 
100
- test("Parse Text", () => {
94
+ test("Exec", () => {
101
95
  const a = new Or("a", [new Literal("a", "A")]);
102
- const { ast: result } = a.parseText("B");
96
+ const { ast: result } = a.exec("B");
103
97
  expect(result).toBeNull();
104
98
  });
99
+
100
+ test("Test No Match", () => {
101
+ const a = new Or("a", [new Literal("a", "A")]);
102
+ const result = a.test("B");
103
+ expect(result).toBeFalsy();
104
+ });
105
+
106
+ test("Test With Match", () => {
107
+ const a = new Or("a", [new Literal("a", "A")]);
108
+ const result = a.test("A");
109
+ expect(result).toBeTruthy();
110
+ });
111
+
112
+ test("Get Next Tokens", () => {
113
+ const sequence = new And("sequence", [
114
+ new Or("a-or-b", [
115
+ new Literal("a", "A"),
116
+ new Literal("b", "B")
117
+ ]),
118
+ new Literal("c", "C")
119
+ ]);
120
+
121
+ const orClone = sequence.findPattern(p => p.name === "a-or-b") as Pattern;
122
+ const tokens = orClone.getNextTokens();
123
+
124
+ expect(tokens.length).toBe(1);
125
+ expect(tokens[0]).toBe("C");
126
+ });
127
+
128
+ test("Get Next Tokens With Null Parent", () => {
129
+ const or = new Or("a-or-b", [
130
+ new Literal("a", "A"),
131
+ new Literal("b", "B")
132
+ ])
133
+
134
+ const tokens = or.getNextTokens();
135
+ expect(tokens.length).toBe(0);
136
+ });
137
+
138
+
139
+ test("Get Tokens After", () => {
140
+ const sequence = new And("sequence", [
141
+ new Or("a-or-b", [
142
+ new Literal("a", "A"),
143
+ new Literal("b", "B")
144
+ ]),
145
+ new Literal("c", "C")
146
+ ]);
147
+
148
+ const aClone = sequence.findPattern(p => p.name === "a") as Pattern;
149
+ const orClone = sequence.findPattern(p => p.name === "a-or-b") as Pattern;
150
+ const tokens = orClone.getTokensAfter(aClone);
151
+
152
+ expect(tokens.length).toBe(1);
153
+ expect(tokens[0]).toBe("C");
154
+ });
155
+
156
+ test("Get Patterns After", () => {
157
+ const sequence = new And("sequence", [
158
+ new Or("a-or-b", [
159
+ new Literal("a", "A"),
160
+ new Literal("b", "B")
161
+ ]),
162
+ new Literal("c", "C")
163
+ ]);
164
+
165
+ const aClone = sequence.findPattern(p => p.name === "a") as Pattern;
166
+ const orClone = sequence.findPattern(p => p.name === "a-or-b") as Pattern;
167
+ const patterns = orClone.getPatternsAfter(aClone);
168
+
169
+ expect(patterns.length).toBe(1);
170
+ expect(patterns[0].name).toBe("c");
171
+ });
172
+
173
+ test("Get Patterns After With Null Parent", () => {
174
+ const or = new Or("a-or-b", [
175
+ new Literal("a", "A"),
176
+ new Literal("b", "B")
177
+ ])
178
+ const aClone = or.findPattern(p => p.name === "a") as Pattern;
179
+ const patterns = or.getPatternsAfter(aClone);
180
+
181
+ expect(patterns.length).toBe(0);
182
+ });
183
+
184
+ test("Get Next Patterns", () => {
185
+ const sequence = new And("sequence", [
186
+ new Or("a-or-b", [
187
+ new Literal("a", "A"),
188
+ new Literal("b", "B")
189
+ ]),
190
+ new Literal("c", "C")
191
+ ]);
192
+
193
+ const orClone = sequence.findPattern(p => p.name === "a-or-b") as Pattern;
194
+ const patterns = orClone.getNextPatterns();
195
+
196
+ expect(patterns.length).toBe(1);
197
+ expect(patterns[0].name).toBe("c");
198
+ });
199
+
200
+ test("Get Next Patterns With Null Parent", () => {
201
+ const or = new Or("a-or-b", [
202
+ new Literal("a", "A"),
203
+ new Literal("b", "B")
204
+ ])
205
+ const patterns = or.getNextPatterns();
206
+
207
+ expect(patterns.length).toBe(0);
208
+ });
105
209
  });
@@ -2,7 +2,6 @@ import { Node } from "../ast/Node";
2
2
  import { Cursor } from "./Cursor";
3
3
  import { Pattern } from "./Pattern";
4
4
  import { clonePatterns } from "./clonePatterns";
5
- import { getNextPattern } from "./getNextPattern";
6
5
  import { findPattern } from "./findPattern";
7
6
 
8
7
  export class Or implements Pattern {
@@ -11,7 +10,6 @@ export class Or implements Pattern {
11
10
  private _parent: Pattern | null;
12
11
  private _children: Pattern[];
13
12
  private _isOptional: boolean;
14
- private _node: Node | null;
15
13
  private _firstIndex: number;
16
14
 
17
15
  get type(): string {
@@ -51,7 +49,6 @@ export class Or implements Pattern {
51
49
  this._parent = null;
52
50
  this._children = children;
53
51
  this._isOptional = isOptional;
54
- this._node = null;
55
52
  this._firstIndex = 0;
56
53
  }
57
54
 
@@ -61,19 +58,25 @@ export class Or implements Pattern {
61
58
  }
62
59
  }
63
60
 
64
- parseText(text: string) {
61
+ test(text: string) {
65
62
  const cursor = new Cursor(text);
66
- const ast = this.parse(cursor)
63
+ const ast = this.parse(cursor);
64
+
65
+ return ast?.value === text;
66
+ }
67
+
68
+ exec(text: string) {
69
+ const cursor = new Cursor(text);
70
+ const ast = this.parse(cursor);
67
71
 
68
72
  return {
69
- ast,
73
+ ast: ast?.value === text ? ast : null,
70
74
  cursor
71
75
  };
72
76
  }
73
77
 
74
78
  parse(cursor: Cursor): Node | null {
75
79
  this._firstIndex = cursor.index;
76
- this._node = null;
77
80
 
78
81
  const node = this._tryToParse(cursor);
79
82
 
@@ -117,20 +120,40 @@ export class Or implements Pattern {
117
120
  return tokens;
118
121
  }
119
122
 
120
- getNextTokens(_lastMatched: Pattern): string[] {
123
+ getTokensAfter(_childReference: Pattern): string[] {
121
124
  if (this._parent === null) {
122
125
  return [];
123
126
  }
124
127
 
125
- return this._parent.getNextTokens(this);
128
+ return this._parent.getTokensAfter(this);
126
129
  }
127
130
 
128
- getNextPattern(): Pattern | null {
129
- return getNextPattern(this)
131
+ getNextTokens(): string[] {
132
+ if (this._parent == null) {
133
+ return []
134
+ }
135
+
136
+ return this._parent.getTokensAfter(this);
137
+ }
138
+
139
+ getPatternsAfter(_childReference: Pattern): Pattern[] {
140
+ if (this._parent === null) {
141
+ return [];
142
+ }
143
+
144
+ return this._parent.getPatternsAfter(this)
145
+ }
146
+
147
+ getNextPatterns(): Pattern[] {
148
+ if (this.parent == null) {
149
+ return [];
150
+ }
151
+
152
+ return this.parent.getPatternsAfter(this)
130
153
  }
131
154
 
132
- findPattern(isMatch: (p: Pattern)=>boolean): Pattern | null{
133
- return findPattern(this, isMatch);
155
+ findPattern(predicate: (p: Pattern) => boolean): Pattern | null {
156
+ return findPattern(this, predicate);
134
157
  }
135
158
 
136
159
  clone(name = this._name, isOptional = this._isOptional): Pattern {
@@ -10,10 +10,13 @@ export interface Pattern {
10
10
  isOptional: boolean;
11
11
 
12
12
  parse(cursor: Cursor): Node | null;
13
- parseText(text: string): ParseResult;
13
+ exec(text: string): ParseResult;
14
+ test(text: string): boolean;
14
15
  clone(name?: string, isOptional?: boolean): Pattern;
15
16
  getTokens(): string[];
16
- getNextTokens(lastMatched: Pattern): string[];
17
- getNextPattern(): Pattern | null;
18
- findPattern(isMatch:(p: Pattern)=>boolean): Pattern | null;
17
+ getTokensAfter(childReference: Pattern): string[];
18
+ getPatternsAfter(childReference: Pattern): Pattern[];
19
+ getNextPatterns(): Pattern[];
20
+ getNextTokens(): string[];
21
+ findPattern(predicate: (p: Pattern) => boolean): Pattern | null;
19
22
  }