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.
Files changed (94) hide show
  1. package/TODO.md +1 -76
  2. package/dist/ast/Node.d.ts +1 -0
  3. package/dist/grammar/Grammar.d.ts +17 -0
  4. package/dist/grammar/patterns/andLiteral.d.ts +2 -0
  5. package/dist/grammar/patterns/comment.d.ts +2 -0
  6. package/dist/grammar/patterns/grammar.d.ts +2 -0
  7. package/dist/grammar/patterns/literal.d.ts +2 -0
  8. package/dist/grammar/patterns/name.d.ts +2 -0
  9. package/dist/grammar/patterns/orLiteral.d.ts +2 -0
  10. package/dist/grammar/patterns/pattern.d.ts +2 -0
  11. package/dist/grammar/patterns/regexLiteral.d.ts +2 -0
  12. package/dist/grammar/patterns/repeatLiteral.d.ts +3 -0
  13. package/dist/grammar/patterns/spaces.d.ts +2 -0
  14. package/dist/grammar/patterns/statement.d.ts +2 -0
  15. package/dist/index.browser.js +1205 -550
  16. package/dist/index.browser.js.map +1 -1
  17. package/dist/index.d.ts +5 -4
  18. package/dist/index.esm.js +1203 -549
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1203 -548
  21. package/dist/index.js.map +1 -1
  22. package/dist/intellisense/AutoComplete.d.ts +9 -7
  23. package/dist/intellisense/Suggestion.d.ts +1 -2
  24. package/dist/patterns/And.d.ts +2 -1
  25. package/dist/patterns/Cursor.d.ts +1 -0
  26. package/dist/patterns/CursorHistory.d.ts +2 -1
  27. package/dist/patterns/FiniteRepeat.d.ts +39 -0
  28. package/dist/patterns/InfiniteRepeat.d.ts +47 -0
  29. package/dist/patterns/Literal.d.ts +2 -1
  30. package/dist/patterns/Not.d.ts +2 -1
  31. package/dist/patterns/Or.d.ts +2 -1
  32. package/dist/patterns/Pattern.d.ts +3 -2
  33. package/dist/patterns/Reference.d.ts +2 -1
  34. package/dist/patterns/Regex.d.ts +2 -1
  35. package/dist/patterns/Repeat.d.ts +19 -22
  36. package/jest.config.js +0 -1
  37. package/jest.coverage.config.js +13 -0
  38. package/package.json +3 -3
  39. package/src/ast/Node.test.ts +21 -0
  40. package/src/ast/Node.ts +12 -6
  41. package/src/grammar/Grammar.test.ts +288 -0
  42. package/src/grammar/Grammar.ts +234 -0
  43. package/src/grammar/patterns/andLiteral.ts +8 -0
  44. package/src/grammar/patterns/comment.ts +3 -0
  45. package/src/grammar/patterns/grammar.ts +19 -0
  46. package/src/grammar/patterns/literal.ts +5 -0
  47. package/src/grammar/patterns/name.ts +3 -0
  48. package/src/grammar/patterns/orLiteral.ts +8 -0
  49. package/src/grammar/patterns/pattern.ts +13 -0
  50. package/src/grammar/patterns/regexLiteral.ts +4 -0
  51. package/src/grammar/patterns/repeatLiteral.ts +72 -0
  52. package/src/grammar/patterns/spaces.ts +4 -0
  53. package/src/grammar/patterns/statement.ts +35 -0
  54. package/src/grammar/spec.md +142 -0
  55. package/src/index.ts +6 -3
  56. package/src/intellisense/AutoComplete.test.ts +125 -39
  57. package/src/intellisense/AutoComplete.ts +52 -36
  58. package/src/intellisense/Suggestion.ts +1 -2
  59. package/src/intellisense/css/cssValue.ts +1 -1
  60. package/src/intellisense/css/method.ts +1 -1
  61. package/src/intellisense/css/values.ts +1 -1
  62. package/src/intellisense/javascript/Javascript.test.ts +34 -11
  63. package/src/intellisense/javascript/arrayLiteral.ts +1 -1
  64. package/src/intellisense/javascript/{expressionStatement.ts → assignment.ts} +7 -8
  65. package/src/intellisense/javascript/expression.ts +45 -27
  66. package/src/intellisense/javascript/infixOperator.ts +6 -2
  67. package/src/intellisense/javascript/invocation.ts +1 -1
  68. package/src/intellisense/javascript/keywords.ts +3 -0
  69. package/src/intellisense/javascript/objectAccess.ts +9 -0
  70. package/src/intellisense/javascript/objectLiteral.ts +3 -3
  71. package/src/intellisense/javascript/parameters.ts +1 -1
  72. package/src/intellisense/javascript/propertyAccess.ts +8 -3
  73. package/src/intellisense/javascript/stringLiteral.ts +14 -8
  74. package/src/patterns/And.test.ts +16 -3
  75. package/src/patterns/And.ts +25 -17
  76. package/src/patterns/Cursor.ts +4 -0
  77. package/src/patterns/CursorHistory.ts +34 -5
  78. package/src/patterns/FiniteRepeat.test.ts +481 -0
  79. package/src/patterns/FiniteRepeat.ts +231 -0
  80. package/src/patterns/InfiniteRepeat.test.ts +296 -0
  81. package/src/patterns/InfiniteRepeat.ts +329 -0
  82. package/src/patterns/Literal.test.ts +13 -4
  83. package/src/patterns/Literal.ts +5 -1
  84. package/src/patterns/Not.test.ts +20 -9
  85. package/src/patterns/Not.ts +5 -1
  86. package/src/patterns/Or.test.ts +18 -7
  87. package/src/patterns/Or.ts +11 -1
  88. package/src/patterns/Pattern.ts +3 -2
  89. package/src/patterns/Reference.test.ts +18 -8
  90. package/src/patterns/Reference.ts +5 -1
  91. package/src/patterns/Regex.test.ts +13 -4
  92. package/src/patterns/Regex.ts +5 -1
  93. package/src/patterns/Repeat.test.ts +162 -158
  94. package/src/patterns/Repeat.ts +95 -226
@@ -1,272 +1,141 @@
1
1
  import { Node } from "../ast/Node";
2
2
  import { Cursor } from "./Cursor";
3
+ import { FiniteRepeat } from "./FiniteRepeat";
4
+ import { InfiniteRepeat } from "./InfiniteRepeat";
5
+ import { ParseResult } from "./ParseResult";
3
6
  import { Pattern } from "./Pattern";
4
- import { clonePatterns } from "./clonePatterns";
5
- import { findPattern } from "./findPattern";
6
7
 
7
- export class Repeat implements Pattern {
8
- private _type: string;
9
- private _name: string;
10
- private _parent: Pattern | null;
11
- private _children: Pattern[];
12
- private _pattern: Pattern;
13
- private _divider: Pattern;
14
- private _isOptional: boolean;
15
- private _nodes: Node[];
16
- private _firstIndex: number;
17
-
18
- get type(): string {
19
- return this._type;
20
- }
21
-
22
- get name(): string {
23
- return this._name;
24
- }
25
-
26
- get parent(): Pattern | null {
27
- return this._parent;
28
- }
29
-
30
- set parent(pattern: Pattern | null) {
31
- this._parent = pattern;
32
- }
33
-
34
- get children(): Pattern[] {
35
- return this._children;
36
- }
37
-
38
- get isOptional(): boolean {
39
- return this._isOptional;
40
- }
41
-
42
- constructor(name: string, pattern: Pattern, divider?: Pattern, isOptional = false) {
43
- const patterns = divider != null ? [pattern, divider] : [pattern];
44
- const children: Pattern[] = clonePatterns(patterns, false);
45
- this._assignChildrenToParent(children);
8
+ export interface RepeatOptions {
9
+ min?: number;
10
+ max?: number;
11
+ divider?: Pattern;
12
+ trimDivider?: boolean;
13
+ }
46
14
 
47
- this._type = "repeat";
48
- this._name = name;
49
- this._isOptional = isOptional;
50
- this._parent = null;
51
- this._children = children;
52
- this._pattern = children[0];
53
- this._divider = children[1];
54
- this._firstIndex = -1
55
- this._nodes = [];
56
- }
15
+ interface InternalRepeatOptions {
16
+ min: number;
17
+ max: number;
18
+ divider?: Pattern;
19
+ }
57
20
 
58
- private _assignChildrenToParent(children: Pattern[]): void {
59
- for (const child of children) {
60
- child.parent = this;
21
+ export class Repeat implements Pattern {
22
+ private _repeatPattern: InfiniteRepeat | FiniteRepeat;
23
+ private _parent: Pattern | null;
24
+ private _pattern: Pattern;
25
+ private _options: InternalRepeatOptions;
26
+ private _children: Pattern[];
27
+
28
+ get type() {
29
+ return this._repeatPattern.type;
61
30
  }
62
- }
63
-
64
- test(text: string) {
65
- const cursor = new Cursor(text);
66
- const ast = this.parse(cursor);
67
-
68
- return ast?.value === text;
69
- }
70
31
 
71
- exec(text: string) {
72
- const cursor = new Cursor(text);
73
- const ast = this.parse(cursor);
74
-
75
- return {
76
- ast: ast?.value === text ? ast : null,
77
- cursor
78
- };
79
- }
80
-
81
- parse(cursor: Cursor): Node | null {
82
- this._firstIndex = cursor.index;
83
- this._nodes = [];
84
-
85
- const passed = this.tryToParse(cursor);
86
-
87
- if (passed) {
88
- cursor.resolveError();
89
- const node = this.createNode(cursor);
90
-
91
- if (node != null) {
92
- cursor.recordMatch(this, node);
93
- }
94
-
95
- return node;
32
+ get name() {
33
+ return this._repeatPattern.name;
96
34
  }
97
35
 
98
- if (!this._isOptional) {
99
- return null;
36
+ get parent() {
37
+ return this._parent;
100
38
  }
101
39
 
102
- cursor.resolveError();
103
- cursor.moveTo(this._firstIndex);
104
- return null;
105
- }
106
-
107
- private tryToParse(cursor: Cursor): boolean {
108
- let passed = false;
40
+ set parent(value: Pattern | null) {
41
+ this._parent = value;
42
+ }
109
43
 
110
- while (true) {
111
- const runningCursorIndex = cursor.index;
112
- const repeatedNode = this._pattern.parse(cursor);
44
+ get children() {
45
+ return this._children;
46
+ }
113
47
 
114
- if (cursor.hasError) {
115
- const lastValidNode = this.getLastValidNode();
48
+ get isOptional() {
49
+ return this._repeatPattern.isOptional;
50
+ }
116
51
 
117
- if (lastValidNode != null) {
118
- passed = true;
52
+ constructor(name: string, pattern: Pattern, options: RepeatOptions = {}) {
53
+ this._pattern = pattern;
54
+ this._parent = null;
55
+ this._options = {
56
+ ...options,
57
+ min: options.min == null ? 1 : options.min,
58
+ max: options.max == null ? Infinity : options.max
59
+ };
60
+
61
+ if (this._options.max != Infinity) {
62
+ this._repeatPattern = new FiniteRepeat(name, pattern, this._options.max, this._options);
119
63
  } else {
120
- cursor.moveTo(runningCursorIndex);
121
- cursor.recordErrorAt(runningCursorIndex, this._pattern);
122
- passed = false;
64
+ this._repeatPattern = new InfiniteRepeat(name, pattern, this._options)
123
65
  }
124
66
 
125
- break;
126
- } else if (repeatedNode) {
127
- this._nodes.push(repeatedNode);
67
+ this._children = [this._repeatPattern]
68
+ this._repeatPattern.parent = this;
69
+ }
128
70
 
129
- if (!cursor.hasNext()) {
130
- passed = true;
131
- break;
132
- }
71
+ parse(cursor: Cursor): Node | null {
72
+ return this._repeatPattern.parse(cursor);
73
+ }
133
74
 
134
- cursor.next();
75
+ exec(text: string): ParseResult {
76
+ return this._repeatPattern.exec(text);
77
+ }
135
78
 
136
- if (this._divider != null) {
137
- const dividerNode = this._divider.parse(cursor);
79
+ test(text: string): boolean {
80
+ return this._repeatPattern.test(text);
81
+ }
138
82
 
139
- if (cursor.hasError) {
140
- passed = true;
141
- break;
142
- } else if (dividerNode != null) {
143
- this._nodes.push(dividerNode);
83
+ clone(name = this.name, isOptional?: boolean) {
84
+ let min = this._options.min;
144
85
 
145
- if (!cursor.hasNext()) {
146
- passed = true;
147
- break;
86
+ if (isOptional != null) {
87
+ if (isOptional) {
88
+ min = 0
89
+ } else {
90
+ min = Math.max(this._options.min, 1);
148
91
  }
149
-
150
- cursor.next();
151
- }
152
92
  }
153
- }
154
- }
155
-
156
- return passed;
157
- }
158
-
159
- private createNode(cursor: Cursor): Node | null {
160
- let children: Node[] = [];
161
93
 
162
- if (!this._divider) {
163
- children = this._nodes;
164
- } else {
165
- if (this._nodes.length % 2 !== 1) {
166
- const dividerNode = this._nodes[this._nodes.length - 1];
167
- cursor.moveTo(dividerNode.firstIndex);
168
- children = this._nodes.slice(0, this._nodes.length - 1);
169
- } else {
170
- children = this._nodes;
171
- }
94
+ return new Repeat(name, this._pattern, { ...this._options, min });
172
95
  }
173
96
 
174
- const lastIndex = children[children.length - 1].lastIndex;
175
- const value = cursor.getChars(this._firstIndex, lastIndex);
176
- cursor.moveTo(lastIndex);
177
-
178
- return new Node(
179
- "repeat",
180
- this._name,
181
- this._firstIndex,
182
- lastIndex,
183
- children,
184
- undefined
185
- );
186
- }
187
-
188
- private getLastValidNode(): Node | null {
189
- const nodes = this._nodes.filter((node) => node !== null);
190
-
191
- if (nodes.length === 0) {
192
- return null;
97
+ getTokens(): string[] {
98
+ return this._repeatPattern.getTokens();
193
99
  }
194
100
 
195
- return nodes[nodes.length - 1];
196
- }
197
-
198
- getTokens(): string[] {
199
- return this._pattern.getTokens();
200
- }
201
-
202
- getTokensAfter(childReference: Pattern): string[] {
203
- const patterns = this.getPatternsAfter(childReference);
204
- const tokens: string[] = [];
205
-
206
- patterns.forEach(p => tokens.push(...p.getTokens()));
207
-
208
- return tokens;
209
- }
101
+ getTokensAfter(_childReference: Pattern): string[] {
102
+ if (this._parent == null) {
103
+ return []
104
+ }
210
105
 
211
- getNextTokens(): string[] {
212
- if (this.parent == null) {
213
- return []
106
+ return this._parent.getTokensAfter(this);
214
107
  }
215
108
 
216
- return this.parent.getTokensAfter(this);
217
- }
218
-
219
- getPatternsAfter(childReference: Pattern): Pattern[] {
220
- let index = -1;
221
- const patterns: Pattern[] = [];
109
+ getNextTokens(): string[] {
110
+ if (this._parent == null) {
111
+ return []
112
+ }
222
113
 
223
- for (let i = 0; i < this._children.length; i++) {
224
- if (this._children[i] === childReference) {
225
- index = i;
226
- }
114
+ return this._parent.getTokensAfter(this);
227
115
  }
228
116
 
229
- // If the last match isn't a child of this pattern.
230
- if (index === -1) {
231
- return [];
117
+ getPatterns(): Pattern[] {
118
+ return this._repeatPattern.getPatterns();
232
119
  }
233
120
 
234
- // If the last match was the repeated patterns, then suggest the divider.
235
- if (index === 0 && this._divider) {
236
- patterns.push(this._children[1]);
121
+ getPatternsAfter(_childReference: Pattern): Pattern[] {
122
+ if (this._parent == null) {
123
+ return []
124
+ }
237
125
 
238
- if (this._parent) {
239
- patterns.push(...this._parent.getPatternsAfter(this));
240
- }
126
+ return this._parent.getPatternsAfter(this);
241
127
  }
242
128
 
243
- // Suggest the pattern because the divider was the last match.
244
- if (index === 1) {
245
- patterns.push(this._children[0]);
246
- }
129
+ getNextPatterns(): Pattern[] {
130
+ if (this._parent == null) {
131
+ return []
132
+ }
247
133
 
248
- if (index === 0 && !this._divider && this._parent) {
249
- patterns.push(this._children[0]);
250
- patterns.push(...this._parent.getPatternsAfter(this));
134
+ return this._parent.getPatternsAfter(this);
251
135
  }
252
136
 
253
- return patterns;
254
- }
255
-
256
- getNextPatterns(): Pattern[] {
257
- if (this.parent == null) {
258
- return [];
137
+ find(predicate: (p: Pattern) => boolean): Pattern | null {
138
+ return this._repeatPattern.find(predicate);
259
139
  }
260
140
 
261
- return this.parent.getPatternsAfter(this)
262
- }
263
-
264
- findPattern(predicate: (p: Pattern) => boolean): Pattern | null {
265
- return findPattern(this, predicate);
266
- }
267
-
268
- clone(name = this._name, isOptional = this._isOptional): Pattern {
269
- return new Repeat(name, this._pattern, this._divider, isOptional);
270
- }
271
- }
272
-
141
+ }