clarity-pattern-parser 6.0.2 → 7.0.1

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 (88) hide show
  1. package/TODO.md +1 -78
  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 +1161 -556
  16. package/dist/index.browser.js.map +1 -1
  17. package/dist/index.d.ts +5 -4
  18. package/dist/index.esm.js +1159 -555
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +1159 -554
  21. package/dist/index.js.map +1 -1
  22. package/dist/intellisense/AutoComplete.d.ts +2 -6
  23. package/dist/patterns/And.d.ts +1 -1
  24. package/dist/patterns/Cursor.d.ts +1 -0
  25. package/dist/patterns/CursorHistory.d.ts +2 -1
  26. package/dist/patterns/FiniteRepeat.d.ts +39 -0
  27. package/dist/patterns/InfiniteRepeat.d.ts +47 -0
  28. package/dist/patterns/Literal.d.ts +1 -1
  29. package/dist/patterns/Not.d.ts +1 -1
  30. package/dist/patterns/Or.d.ts +1 -1
  31. package/dist/patterns/Pattern.d.ts +1 -1
  32. package/dist/patterns/Reference.d.ts +1 -1
  33. package/dist/patterns/Regex.d.ts +1 -1
  34. package/dist/patterns/Repeat.d.ts +18 -22
  35. package/jest.config.js +0 -1
  36. package/jest.coverage.config.js +13 -0
  37. package/package.json +3 -3
  38. package/src/ast/Node.test.ts +15 -0
  39. package/src/ast/Node.ts +12 -6
  40. package/src/grammar/Grammar.test.ts +306 -0
  41. package/src/grammar/Grammar.ts +249 -0
  42. package/src/grammar/patterns/andLiteral.ts +8 -0
  43. package/src/grammar/patterns/comment.ts +3 -0
  44. package/src/grammar/patterns/grammar.ts +19 -0
  45. package/src/grammar/patterns/literal.ts +5 -0
  46. package/src/grammar/patterns/name.ts +3 -0
  47. package/src/grammar/patterns/orLiteral.ts +8 -0
  48. package/src/grammar/patterns/pattern.ts +13 -0
  49. package/src/grammar/patterns/regexLiteral.ts +4 -0
  50. package/src/grammar/patterns/repeatLiteral.ts +72 -0
  51. package/src/grammar/patterns/spaces.ts +4 -0
  52. package/src/grammar/patterns/statement.ts +36 -0
  53. package/src/grammar/spec.md +142 -0
  54. package/src/index.ts +6 -3
  55. package/src/intellisense/AutoComplete.test.ts +21 -2
  56. package/src/intellisense/AutoComplete.ts +14 -25
  57. package/src/intellisense/Suggestion.ts +0 -1
  58. package/src/intellisense/css/cssValue.ts +1 -1
  59. package/src/intellisense/css/method.ts +1 -1
  60. package/src/intellisense/css/values.ts +1 -1
  61. package/src/intellisense/javascript/Javascript.test.ts +0 -1
  62. package/src/intellisense/javascript/arrayLiteral.ts +1 -1
  63. package/src/intellisense/javascript/expression.ts +1 -1
  64. package/src/intellisense/javascript/invocation.ts +1 -1
  65. package/src/intellisense/javascript/objectLiteral.ts +1 -1
  66. package/src/intellisense/javascript/parameters.ts +1 -1
  67. package/src/intellisense/javascript/stringLiteral.ts +2 -4
  68. package/src/patterns/And.test.ts +5 -5
  69. package/src/patterns/And.ts +11 -17
  70. package/src/patterns/Cursor.ts +4 -0
  71. package/src/patterns/CursorHistory.ts +34 -5
  72. package/src/patterns/FiniteRepeat.test.ts +481 -0
  73. package/src/patterns/FiniteRepeat.ts +231 -0
  74. package/src/patterns/InfiniteRepeat.test.ts +296 -0
  75. package/src/patterns/InfiniteRepeat.ts +329 -0
  76. package/src/patterns/Literal.test.ts +4 -4
  77. package/src/patterns/Literal.ts +1 -1
  78. package/src/patterns/Not.test.ts +11 -11
  79. package/src/patterns/Not.ts +1 -1
  80. package/src/patterns/Or.test.ts +9 -9
  81. package/src/patterns/Or.ts +1 -1
  82. package/src/patterns/Pattern.ts +1 -1
  83. package/src/patterns/Reference.test.ts +8 -8
  84. package/src/patterns/Reference.ts +1 -1
  85. package/src/patterns/Regex.test.ts +4 -4
  86. package/src/patterns/Regex.ts +1 -1
  87. package/src/patterns/Repeat.test.ts +160 -165
  88. package/src/patterns/Repeat.ts +95 -230
@@ -1,276 +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
93
 
156
- return passed;
157
- }
158
-
159
- private createNode(cursor: Cursor): Node | null {
160
- let children: Node[] = [];
161
-
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
- getPatterns(): Pattern[] {
220
- return this._pattern.getPatterns();
221
- }
222
-
223
- getPatternsAfter(childReference: Pattern): Pattern[] {
224
- let index = -1;
225
- const patterns: Pattern[] = [];
109
+ getNextTokens(): string[] {
110
+ if (this._parent == null) {
111
+ return []
112
+ }
226
113
 
227
- for (let i = 0; i < this._children.length; i++) {
228
- if (this._children[i] === childReference) {
229
- index = i;
230
- }
114
+ return this._parent.getTokensAfter(this);
231
115
  }
232
116
 
233
- // If the last match isn't a child of this pattern.
234
- if (index === -1) {
235
- return [];
117
+ getPatterns(): Pattern[] {
118
+ return this._repeatPattern.getPatterns();
236
119
  }
237
120
 
238
- // If the last match was the repeated patterns, then suggest the divider.
239
- if (index === 0 && this._divider) {
240
- patterns.push(this._children[1]);
121
+ getPatternsAfter(_childReference: Pattern): Pattern[] {
122
+ if (this._parent == null) {
123
+ return []
124
+ }
241
125
 
242
- if (this._parent) {
243
- patterns.push(...this._parent.getPatternsAfter(this));
244
- }
126
+ return this._parent.getPatternsAfter(this);
245
127
  }
246
128
 
247
- // Suggest the pattern because the divider was the last match.
248
- if (index === 1) {
249
- patterns.push(this._children[0]);
250
- }
129
+ getNextPatterns(): Pattern[] {
130
+ if (this._parent == null) {
131
+ return []
132
+ }
251
133
 
252
- if (index === 0 && !this._divider && this._parent) {
253
- patterns.push(this._children[0]);
254
- patterns.push(...this._parent.getPatternsAfter(this));
134
+ return this._parent.getPatternsAfter(this);
255
135
  }
256
136
 
257
- return patterns;
258
- }
259
-
260
- getNextPatterns(): Pattern[] {
261
- if (this.parent == null) {
262
- return [];
137
+ find(predicate: (p: Pattern) => boolean): Pattern | null {
138
+ return this._repeatPattern.find(predicate);
263
139
  }
264
140
 
265
- return this.parent.getPatternsAfter(this)
266
- }
267
-
268
- findPattern(predicate: (p: Pattern) => boolean): Pattern | null {
269
- return findPattern(this, predicate);
270
- }
271
-
272
- clone(name = this._name, isOptional = this._isOptional): Pattern {
273
- return new Repeat(name, this._pattern, this._divider, isOptional);
274
- }
275
- }
276
-
141
+ }