clarity-pattern-parser 4.0.3 → 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 (133) hide show
  1. package/README.md +466 -1
  2. package/TODO.md +76 -2
  3. package/dist/ast/Node.d.ts +49 -11
  4. package/dist/ast/Visitor.d.ts +31 -31
  5. package/dist/index.browser.js +1513 -1495
  6. package/dist/index.browser.js.map +1 -1
  7. package/dist/index.d.ts +17 -17
  8. package/dist/index.esm.js +1480 -1459
  9. package/dist/index.esm.js.map +1 -1
  10. package/dist/index.js +1481 -1463
  11. package/dist/index.js.map +1 -1
  12. package/dist/intellisense/AutoComplete.d.ts +28 -0
  13. package/dist/intellisense/Suggestion.d.ts +11 -0
  14. package/dist/intellisense/SuggestionOption.d.ts +4 -0
  15. package/dist/patterns/And.d.ts +37 -24
  16. package/dist/patterns/Cursor.d.ts +37 -0
  17. package/dist/patterns/CursorHistory.d.ts +30 -0
  18. package/dist/patterns/Literal.d.ts +35 -19
  19. package/dist/patterns/Not.d.ts +29 -11
  20. package/dist/patterns/Or.d.ts +33 -22
  21. package/dist/patterns/ParseError.d.ts +6 -8
  22. package/dist/patterns/ParseResult.d.ts +6 -0
  23. package/dist/patterns/Pattern.d.ts +20 -26
  24. package/dist/patterns/Reference.d.ts +34 -12
  25. package/dist/patterns/Regex.d.ts +41 -21
  26. package/dist/patterns/Repeat.d.ts +38 -20
  27. package/dist/patterns/clonePatterns.d.ts +2 -0
  28. package/dist/patterns/filterOutNull.d.ts +2 -0
  29. package/dist/patterns/findPattern.d.ts +2 -0
  30. package/dist/patterns/getNextPattern.d.ts +2 -0
  31. package/jest.config.js +2 -1
  32. package/package.json +4 -5
  33. package/rollup.config.js +1 -1
  34. package/src/ast/Node.test.ts +364 -0
  35. package/src/ast/Node.ts +237 -23
  36. package/src/index.ts +25 -27
  37. package/src/intellisense/AutoComplete.test.ts +150 -0
  38. package/src/intellisense/AutoComplete.ts +200 -0
  39. package/src/intellisense/Suggestion.ts +12 -0
  40. package/src/intellisense/SuggestionOption.ts +4 -0
  41. package/src/{tests/cssPatterns → intellisense/css}/cssValue.ts +1 -1
  42. package/src/{tests/cssPatterns → intellisense/css}/divider.ts +2 -1
  43. package/src/intellisense/css/hex.ts +6 -0
  44. package/src/{tests/cssPatterns → intellisense/css}/method.ts +8 -9
  45. package/src/intellisense/css/name.ts +5 -0
  46. package/src/{tests/javascriptPatterns → intellisense/css}/number.ts +3 -3
  47. package/src/intellisense/css/spaces.ts +6 -0
  48. package/src/intellisense/css/unit.ts +10 -0
  49. package/src/{tests/cssPatterns → intellisense/css}/value.ts +1 -1
  50. package/src/{tests/cssPatterns → intellisense/css}/values.ts +1 -1
  51. package/src/intellisense/javascript/Javascript.test.ts +203 -0
  52. package/src/intellisense/javascript/arrayLiteral.ts +25 -0
  53. package/src/intellisense/javascript/deleteStatement.ts +14 -0
  54. package/src/intellisense/javascript/escapedCharacter.ts +49 -0
  55. package/src/intellisense/javascript/exponent.ts +24 -0
  56. package/src/intellisense/javascript/expression.ts +87 -0
  57. package/src/intellisense/javascript/expressionStatement.ts +29 -0
  58. package/src/intellisense/javascript/fraction.ts +11 -0
  59. package/src/intellisense/javascript/infixOperator.ts +36 -0
  60. package/src/intellisense/javascript/integer.ts +7 -0
  61. package/src/intellisense/javascript/invocation.ts +28 -0
  62. package/src/intellisense/javascript/literal.ts +14 -0
  63. package/src/intellisense/javascript/name.ts +3 -0
  64. package/src/intellisense/javascript/numberLiteral.ts +10 -0
  65. package/src/intellisense/javascript/objectLiteral.ts +30 -0
  66. package/src/intellisense/javascript/optionalSpaces.ts +3 -0
  67. package/src/intellisense/javascript/parameters.ts +20 -0
  68. package/src/intellisense/javascript/prefixOperator.ts +13 -0
  69. package/src/intellisense/javascript/propertyAccess.ts +23 -0
  70. package/src/intellisense/javascript/stringLiteral.ts +28 -0
  71. package/src/patterns/And.test.ts +310 -0
  72. package/src/patterns/And.ts +244 -119
  73. package/src/patterns/Cursor.test.ts +93 -0
  74. package/src/patterns/Cursor.ts +133 -0
  75. package/src/patterns/CursorHistory.test.ts +54 -0
  76. package/src/patterns/CursorHistory.ts +95 -0
  77. package/src/patterns/Literal.test.ts +166 -0
  78. package/src/patterns/Literal.ts +141 -62
  79. package/src/patterns/Not.test.ts +168 -0
  80. package/src/patterns/Not.ts +113 -32
  81. package/src/patterns/Or.test.ts +209 -0
  82. package/src/patterns/Or.ts +128 -97
  83. package/src/patterns/ParseError.ts +3 -7
  84. package/src/patterns/ParseResult.ts +7 -0
  85. package/src/patterns/Pattern.ts +21 -150
  86. package/src/patterns/Reference.test.ts +193 -0
  87. package/src/patterns/Reference.ts +114 -88
  88. package/src/patterns/Regex.test.ts +133 -0
  89. package/src/patterns/Regex.ts +117 -60
  90. package/src/patterns/Repeat.test.ts +218 -0
  91. package/src/patterns/Repeat.ts +220 -103
  92. package/src/patterns/clonePatterns.ts +5 -0
  93. package/src/patterns/filterOutNull.ts +13 -0
  94. package/src/patterns/findPattern.ts +25 -0
  95. package/src/Cursor.ts +0 -141
  96. package/src/CursorHistory.ts +0 -146
  97. package/src/TextSuggester.ts +0 -317
  98. package/src/ast/Visitor.ts +0 -271
  99. package/src/patterns/LookAhead.ts +0 -32
  100. package/src/patterns/Recursive.ts +0 -92
  101. package/src/tests/And.test.ts +0 -180
  102. package/src/tests/ComplexExamples.test.ts +0 -86
  103. package/src/tests/CssPatterns.test.ts +0 -90
  104. package/src/tests/CursorHistory.test.ts +0 -107
  105. package/src/tests/Cusor.test.ts +0 -174
  106. package/src/tests/HtmlPatterns.test.ts +0 -34
  107. package/src/tests/Literal.test.ts +0 -79
  108. package/src/tests/LookAhead.test.ts +0 -44
  109. package/src/tests/Not.test.ts +0 -51
  110. package/src/tests/Or.test.ts +0 -113
  111. package/src/tests/Pattern.test.ts +0 -290
  112. package/src/tests/Recursive.test.ts +0 -64
  113. package/src/tests/Reference.test.ts +0 -16
  114. package/src/tests/Repeat.test.ts +0 -75
  115. package/src/tests/SpeedTest.test.ts +0 -31
  116. package/src/tests/TextSuggester.test.ts +0 -297
  117. package/src/tests/Visitor.test.ts +0 -331
  118. package/src/tests/cssPatterns/hex.ts +0 -5
  119. package/src/tests/cssPatterns/name.ts +0 -5
  120. package/src/tests/cssPatterns/number.ts +0 -8
  121. package/src/tests/cssPatterns/spaces.ts +0 -5
  122. package/src/tests/cssPatterns/unit.ts +0 -8
  123. package/src/tests/htmlPatterns/element.ts +0 -49
  124. package/src/tests/javascriptPatterns/boolean.ts +0 -10
  125. package/src/tests/javascriptPatterns/json.ts +0 -67
  126. package/src/tests/javascriptPatterns/name.ts +0 -5
  127. package/src/tests/javascriptPatterns/objectLiteral.ts +0 -40
  128. package/src/tests/javascriptPatterns/string.ts +0 -84
  129. package/src/tests/javascriptPatterns/unit.ts +0 -8
  130. package/src/tests/javascriptPatterns/whitespace.ts +0 -44
  131. package/src/tests/naturalLanguage/filter.ts +0 -37
  132. package/src/tests/patterns/sentence.ts +0 -37
  133. /package/src/{tests/cssPatterns → intellisense/css}/optionalSpaces.ts +0 -0
@@ -1,271 +0,0 @@
1
- import Node from "./Node";
2
-
3
- export default class Visitor {
4
- public root: Node | null;
5
- public selectedNodes: Node[];
6
-
7
- constructor(root: Node | null = null, selectedNodes: Node[] = []) {
8
- this.root = root;
9
- this.selectedNodes = selectedNodes;
10
- }
11
-
12
- flatten() {
13
- this.selectedNodes.forEach((node) => {
14
- if (node.children.length > 0) {
15
- const children: Node[] = [];
16
-
17
- Visitor.walkUp(node, (descendant: Node) => {
18
- if (descendant.children.length === 0) {
19
- children.push(descendant);
20
- }
21
- });
22
-
23
- node.children = children;
24
- }
25
- });
26
-
27
- return this;
28
- }
29
-
30
- remove() {
31
- if (this.root == null) {
32
- return this;
33
- }
34
-
35
- this.recursiveRemove(this.root);
36
- return this;
37
- }
38
-
39
- private recursiveRemove(node: Node) {
40
- const nodesToRemove = this.selectedNodes;
41
- for (let x = 0; x < node.children.length; x++) {
42
- if (nodesToRemove.indexOf(node.children[x]) > -1) {
43
- node.children.splice(x, 1);
44
- x--;
45
- } else {
46
- this.recursiveRemove(node.children[x]);
47
- }
48
- }
49
- }
50
-
51
- wrap(callback: (node: Node) => Node) {
52
- const visitor = new Visitor(this.root);
53
-
54
- visitor.selectRoot().transform((node) => {
55
- if (this.selectedNodes.includes(node)) {
56
- return callback(node);
57
- }
58
- return node;
59
- });
60
-
61
- return this;
62
- }
63
-
64
- unwrap() {
65
- if (this.root == null) {
66
- return this;
67
- }
68
-
69
- Visitor.walkDown(this.root, (node, stack) => {
70
- if (this.selectedNodes.includes(node)) {
71
- const parent = stack[stack.length - 1];
72
- const grandParent = stack[stack.length - 2];
73
-
74
- if (parent != null && grandParent != null) {
75
- const index = grandParent.children.indexOf(parent);
76
- if (index > -1) {
77
- grandParent.children.splice(index, 1, ...parent.children);
78
- }
79
- }
80
- }
81
- });
82
-
83
- return this;
84
- }
85
-
86
- prepend(callback: (node: Node) => Node) {
87
- if (this.root == null) {
88
- return this;
89
- }
90
-
91
- Visitor.walkUp(this.root, (node, stack) => {
92
- if (this.selectedNodes.includes(node)) {
93
- const parent = stack[stack.length - 1];
94
-
95
- if (parent != null) {
96
- const index = parent.children.indexOf(node);
97
- if (index > -1) {
98
- parent.children.splice(index, 0, callback(node));
99
- }
100
- }
101
- }
102
- });
103
-
104
- return this;
105
- }
106
-
107
- append(callback: (node: Node) => Node) {
108
- if (this.root == null) {
109
- return this;
110
- }
111
-
112
- Visitor.walkDown(this.root, (node, stack) => {
113
- if (this.selectedNodes.includes(node)) {
114
- const parent = stack[stack.length - 1];
115
-
116
- if (parent != null) {
117
- const index = parent.children.indexOf(node);
118
- if (index > -1) {
119
- parent.children.splice(index + 1, 0, callback(node));
120
- }
121
- }
122
- }
123
- });
124
-
125
- return this;
126
- }
127
-
128
- transform(callback: (node: Node) => Node) {
129
- this.selectedNodes.forEach((node) => {
130
- return this.recursiveTransform(node, callback);
131
- });
132
-
133
- return this;
134
- }
135
-
136
- private recursiveTransform(node: Node, callback: (node: Node) => Node) {
137
- const length = node.children.length;
138
-
139
- for (let x = 0; x < length; x++) {
140
- node.children[x] = this.recursiveTransform(node.children[x], callback);
141
- }
142
-
143
- return callback(node);
144
- }
145
-
146
- selectAll() {
147
- return this.select((n) => true);
148
- }
149
-
150
- selectNode(node: Node) {
151
- return new Visitor(this.root, [...this.selectedNodes, node]);
152
- }
153
-
154
- deselectNode(node: Node) {
155
- const visitor = new Visitor(this.root, this.selectedNodes.slice());
156
- return visitor.filter((n) => n !== node);
157
- }
158
-
159
- select(callback: (node: Node) => boolean) {
160
- if (this.root == null) {
161
- return this;
162
- }
163
-
164
- const node = this.root;
165
- const selectedNodes: Node[] = [];
166
-
167
- if (node.children.length > 0) {
168
- Visitor.walkDown(node, (descendant: Node) => {
169
- if (callback(descendant)) {
170
- selectedNodes.push(descendant);
171
- }
172
- });
173
- }
174
-
175
- return new Visitor(this.root, selectedNodes);
176
- }
177
-
178
- forEach(callback: (node: Node) => void) {
179
- this.selectedNodes.forEach(callback);
180
- return this;
181
- }
182
-
183
- filter(callback: (node: Node) => boolean) {
184
- return new Visitor(this.root, this.selectedNodes.filter(callback));
185
- }
186
-
187
- map(callback: (node: Node) => Node) {
188
- return new Visitor(this.root, this.selectedNodes.map(callback));
189
- }
190
-
191
- selectRoot() {
192
- if (this.root == null) {
193
- return this;
194
- }
195
-
196
- return new Visitor(this.root, [this.root]);
197
- }
198
-
199
- first() {
200
- return this.get(0);
201
- }
202
-
203
- last() {
204
- return this.get(this.selectedNodes.length - 1);
205
- }
206
-
207
- get(index: number) {
208
- const node = this.selectedNodes[index];
209
-
210
- if (node == null) {
211
- throw new Error(
212
- `Couldn't find node at index: ${index}, out of ${this.selectedNodes.length}.`
213
- );
214
- }
215
-
216
- return new Visitor(node, []);
217
- }
218
-
219
- clear() {
220
- this.selectedNodes = [];
221
- return this;
222
- }
223
-
224
- setRoot(root: Node | null) {
225
- this.root = root;
226
- return this;
227
- }
228
-
229
- static select(root: Node, callback?: (node: Node) => boolean) {
230
- if (callback != null) {
231
- return new Visitor(root).select(callback);
232
- } else {
233
- return new Visitor(root);
234
- }
235
- }
236
-
237
- static walkUp(
238
- node: Node,
239
- callback: (node: Node, ancestors: Node[]) => void,
240
- ancestors: Node[] = []
241
- ) {
242
- ancestors.push(node);
243
-
244
- if (node.children.length > 0) {
245
- const children = node.children.slice();
246
- children.forEach((c) => this.walkUp(c, callback, ancestors));
247
- }
248
-
249
- ancestors.pop();
250
- callback(node, ancestors);
251
-
252
- return this;
253
- }
254
-
255
- static walkDown(
256
- node: Node,
257
- callback: (node: Node, ancestors: Node[]) => void,
258
- ancestors: Node[] = []
259
- ) {
260
- callback(node, ancestors);
261
- ancestors.push(node);
262
-
263
- if (node.children.length > 0) {
264
- const children = node.children.slice();
265
- children.forEach((c) => this.walkDown(c, callback, ancestors));
266
- }
267
-
268
- ancestors.pop();
269
- return this;
270
- }
271
- }
@@ -1,32 +0,0 @@
1
- import Cursor from "../Cursor";
2
- import ParseError from "./ParseError";
3
- import Pattern from "./Pattern";
4
-
5
- export default class LookAhead extends Pattern {
6
- constructor(pattern: Pattern) {
7
- super("look-ahead", "look-ahead", [pattern]);
8
- }
9
-
10
- parse(cursor: Cursor) {
11
- const mark = cursor.mark();
12
- const node = this.children[0].parse(cursor);
13
-
14
- if (cursor.hasUnresolvedError() || node == null) {
15
- cursor.resolveError();
16
- cursor.throwError(
17
- new ParseError("Couldn't find look ahead pattern.", mark, this.children[0])
18
- );
19
- cursor.moveToMark(mark);
20
- }
21
-
22
- return null;
23
- }
24
-
25
- clone() {
26
- return new LookAhead(this.children[0].clone());
27
- }
28
-
29
- getTokens() {
30
- return [];
31
- }
32
- }
@@ -1,92 +0,0 @@
1
- import Pattern from "./Pattern";
2
- import ParserError from "./ParseError";
3
- import Cursor from "../Cursor";
4
-
5
- export default class Recursive extends Pattern {
6
- public isRecursing: boolean;
7
- public pattern: Pattern | null = null;
8
-
9
- constructor(name: string, isOptional = false) {
10
- super("recursive", name, [], isOptional);
11
- this.isRecursing = false;
12
- }
13
-
14
- getPattern() {
15
- return this.climb(this.parent, (pattern: Pattern | null) => {
16
- if (pattern == null) {
17
- return false;
18
- }
19
- return (
20
- pattern.type !== "recursive" &&
21
- pattern.name === this.name
22
- );
23
- });
24
- }
25
-
26
- private climb(
27
- pattern: Pattern | null,
28
- isMatch: (pattern: Pattern | null) => boolean
29
- ): Pattern | null {
30
- if (isMatch(pattern)) {
31
- return pattern;
32
- } else {
33
- if (pattern && pattern.parent != null) {
34
- return this.climb(pattern.parent, isMatch);
35
- }
36
- return null;
37
- }
38
- }
39
-
40
- parse(cursor: Cursor) {
41
- if (this.pattern == null) {
42
- const pattern = this.getPattern();
43
-
44
- if (pattern == null) {
45
- if (!this._isOptional) {
46
- cursor.throwError(
47
- new ParserError(
48
- `Couldn't find parent pattern to recursively parse, with the name ${this.name}.`,
49
- cursor.index,
50
- this
51
- )
52
- );
53
- }
54
-
55
- return null;
56
- }
57
-
58
- this.pattern = pattern.clone();
59
- this.pattern.parent = this;
60
- }
61
-
62
- const mark = cursor.mark();
63
- const node = this.pattern.parse(cursor);
64
-
65
- if (!cursor.hasUnresolvedError() && node != null) {
66
- cursor.addMatch(this, node);
67
- }
68
-
69
- if (cursor.hasUnresolvedError() && this._isOptional) {
70
- cursor.resolveError();
71
- cursor.moveToMark(mark);
72
- }
73
-
74
- return node;
75
- }
76
-
77
- clone(name?: string, isOptional?: boolean) {
78
- if (name == null) {
79
- name = this.name;
80
- }
81
-
82
- if (isOptional == null) {
83
- isOptional = this._isOptional;
84
- }
85
-
86
- return new Recursive(name, isOptional);
87
- }
88
-
89
- getTokens() {
90
- return this.getPattern()?.getTokens() || [];
91
- }
92
- }
@@ -1,180 +0,0 @@
1
- /** @jest-environment node */
2
- import And from "../patterns/And";
3
- import Literal from "../patterns/Literal";
4
- import Cursor from "../Cursor";
5
-
6
- describe("And", () => {
7
- test("Success", () => {
8
- const firstName = new Literal("first-name", "John");
9
- const lastName = new Literal("last-name", "Doe");
10
- const fullName = new And("full-name", [firstName, lastName]);
11
- const cursor = new Cursor("JohnDoe");
12
- const node = fullName.parse(cursor);
13
-
14
- expect(node?.name).toBe("full-name");
15
- expect(node?.value).toBe("JohnDoe");
16
- expect(node?.startIndex).toBe(0);
17
- expect(node?.endIndex).toBe(6);
18
- });
19
-
20
- test("First Part Match with optional Second part.", () => {
21
- const firstName = new Literal("first-name", "John");
22
- const lastName = new Literal("last-name", "Doe", true);
23
- const fullName = new And("full-name", [firstName, lastName]);
24
- const cursor = new Cursor("John");
25
- const node = fullName.parse(cursor);
26
-
27
- expect(node?.name).toBe("full-name");
28
- expect(node?.value).toBe("John");
29
- expect(node?.startIndex).toBe(0);
30
- expect(node?.endIndex).toBe(3);
31
- });
32
-
33
- test("First Part Match, but run out for second part.", () => {
34
- const firstName = new Literal("first-name", "John");
35
- const lastName = new Literal("last-name", "Doe");
36
- const fullName = new And("full-name", [firstName, lastName]);
37
- const cursor = new Cursor("John");
38
- const node = fullName.parse(cursor);
39
-
40
- expect(node).toBe(null);
41
- });
42
-
43
- test("No Match", () => {
44
- const firstName = new Literal("first-name", "John");
45
- const lastName = new Literal("last-name", "Doe");
46
- const fullName = new And("full-name", [firstName, lastName]);
47
- const cursor = new Cursor("JaneDoe");
48
- const node = fullName.parse(cursor);
49
-
50
- expect(node).toBe(null);
51
- });
52
-
53
- test("Partial Match without optional siblings.", () => {
54
- const firstName = new Literal("first-name", "John");
55
- const lastName = new Literal("last-name", "Doe");
56
- const fullName = new And("full-name", [firstName, lastName]);
57
- const cursor = new Cursor("JohnSmith");
58
- const node = fullName.parse(cursor);
59
-
60
- expect(node).toBe(null);
61
- });
62
-
63
- test("Success with more to parse", () => {
64
- const firstName = new Literal("first-name", "John");
65
- const lastName = new Literal("last-name", "Doe");
66
- const fullName = new And("full-name", [firstName, lastName]);
67
- const cursor = new Cursor("JohnDoe JaneDoe");
68
- const node = fullName.parse(cursor);
69
-
70
- expect(node?.name).toBe("full-name");
71
- expect(node?.value).toBe("JohnDoe");
72
- expect(node?.startIndex).toBe(0);
73
- expect(node?.endIndex).toBe(6);
74
- });
75
-
76
- test("Clone.", () => {
77
- const firstName = new Literal("first-name", "John");
78
- const lastName = new Literal("last-name", "Doe");
79
- const fullName = new And("full-name", [firstName, lastName]);
80
- const clone = fullName.clone();
81
-
82
- const fullNamePatterns = fullName.children;
83
- const _cloneChildren = clone.children;
84
-
85
- expect(fullNamePatterns[0]).not.toBe(_cloneChildren[0]);
86
- expect(fullNamePatterns[1]).not.toBe(_cloneChildren[1]);
87
- expect(fullName.name).toBe(clone.name);
88
- });
89
-
90
- test("Clone with custom name.", () => {
91
- const firstName = new Literal("first-name", "John");
92
- const lastName = new Literal("last-name", "Doe");
93
- const fullName = new And("full-name", [firstName, lastName]);
94
- const clone = fullName.clone("full-name-2");
95
-
96
- const fullNamePatterns = fullName.children;
97
- const _cloneChildren = clone.children;
98
-
99
- expect(fullNamePatterns[0]).not.toBe(_cloneChildren[0]);
100
- expect(fullNamePatterns[1]).not.toBe(_cloneChildren[1]);
101
- expect(clone.name).toBe("full-name-2");
102
- });
103
-
104
- test("Partial Match.", () => {
105
- const firstName = new Literal("first-name", "John");
106
- const lastName = new Literal("last-name", "Doe", true);
107
- const fullName = new And("full-name", [
108
- firstName,
109
- lastName,
110
- ]);
111
- const result = fullName.parse(new Cursor("JohnBo"));
112
-
113
- expect(result?.type).toBe("and");
114
- expect(result?.name).toBe("full-name");
115
- expect(result?.value).toBe("John");
116
- });
117
-
118
- test("Partial Match with string running out, and optional last name.", () => {
119
- const firstName = new Literal("first-name", "John");
120
- const lastName = new Literal("last-name", "Doe", true);
121
- const fullName = new And("full-name", [
122
- firstName,
123
- lastName,
124
- ]);
125
- const result = fullName.parse(new Cursor("JohnDo"));
126
-
127
- expect(result?.type).toBe("and");
128
- expect(result?.name).toBe("full-name");
129
- expect(result?.value).toBe("John");
130
- });
131
-
132
- test("Three parts first optional.", () => {
133
- const firstName = new Literal("first-name", "John", true);
134
- const middle = new Literal("middle", "Smith");
135
- const lastName = new Literal("last-name", "Doe");
136
-
137
- const fullName = new And("full-name", [
138
- firstName,
139
- middle,
140
- lastName,
141
- ]);
142
- const result = fullName.parse(new Cursor("SmithDoe"));
143
-
144
- expect(result?.value).toBe("SmithDoe");
145
- expect(result?.type).toBe("and");
146
- expect(result?.name).toBe("full-name");
147
- });
148
-
149
- test("Three parts middle optional.", () => {
150
- const firstName = new Literal("first-name", "John");
151
- const middle = new Literal("middle", "Smith", true);
152
- const lastName = new Literal("last-name", "Doe");
153
-
154
- const fullName = new And("full-name", [
155
- firstName,
156
- middle,
157
- lastName,
158
- ]);
159
- const result = fullName.parse(new Cursor("JohnDo"));
160
-
161
- expect(result).toBe(null);
162
- });
163
-
164
- test("Three parts third optional.", () => {
165
- const firstName = new Literal("first-name", "John");
166
- const middle = new Literal("middle", "Smith");
167
- const lastName = new Literal("last-name", "Doe", true);
168
-
169
- const fullName = new And("full-name", [
170
- firstName,
171
- middle,
172
- lastName,
173
- ]);
174
- const result = fullName.parse(new Cursor("JohnSmith"));
175
-
176
- expect(result?.value).toBe("JohnSmith");
177
- expect(result?.type).toBe("and");
178
- expect(result?.name).toBe("full-name");
179
- });
180
- });
@@ -1,86 +0,0 @@
1
- /** @jest-environment node */
2
- import whitespace from "./javascriptPatterns/whitespace";
3
- import name from "./javascriptPatterns/name";
4
- import number from "./javascriptPatterns/number";
5
- import Cursor from "../Cursor";
6
- import filter from "./naturalLanguage/filter";
7
- import string from "./javascriptPatterns/string";
8
- import cssValue from "./cssPatterns/cssValue";
9
-
10
- describe("Complex Examples", () => {
11
- test("Complex Examples: A Comment", () => {
12
- const cursor = new Cursor(`/*
13
- This is the comment!
14
- */`);
15
-
16
- const node = whitespace.parse(cursor);
17
- });
18
-
19
- test("Complex Examples: name", () => {
20
- const validName = new Cursor("firstName1_2");
21
- const invalidName = new Cursor("1_firstName");
22
- const validNode = name.parse(validName);
23
-
24
- expect(validNode?.name).toBe("name");
25
- expect(validNode?.value).toBe("firstName1_2");
26
-
27
- name.parse(invalidName);
28
- expect(invalidName.hasUnresolvedError()).toBe(true);
29
- });
30
-
31
- test("Complex Examples: number", () => {
32
- const validNumber = new Cursor("1234");
33
- const invalidNumber = new Cursor("01234");
34
- const validFraction = new Cursor("0.1");
35
- const validExponent = new Cursor("1.23e+5");
36
- const singleNumber = new Cursor("1");
37
-
38
- const validNumberNode = number.parse(validNumber);
39
- const validFractionNode = number.parse(validFraction);
40
- const validExponentNode = number.parse(validExponent);
41
- const singleNumberNode = number.parse(singleNumber);
42
-
43
- expect(validNumberNode?.name).toBe("number");
44
- expect(validNumberNode?.value).toBe("1234");
45
-
46
- expect(validFractionNode?.name).toBe("number");
47
- expect(validFractionNode?.value).toBe("0.1");
48
-
49
- expect(validExponentNode?.name).toBe("number");
50
- expect(validExponentNode?.value).toBe("1.23e+5");
51
- expect(validExponent.didSuccessfullyParse()).toBe(true);
52
-
53
- expect(singleNumberNode?.name).toBe("number");
54
- expect(singleNumberNode?.value).toBe("1");
55
-
56
- name.parse(invalidNumber);
57
- expect(invalidNumber.hasUnresolvedError()).toBe(true);
58
- });
59
-
60
- test("Complex Examples: string", () => {
61
- const testString = `"This is a string!."`;
62
- const validString = new Cursor(testString);
63
- const validStringNode = string.parse(validString);
64
-
65
- expect(validStringNode?.name).toBe("string");
66
- expect(validStringNode?.value).toBe(testString);
67
- });
68
-
69
- test("Complex Examples: Natural Language.", () => {
70
- const validCursor = new Cursor(
71
- "Match records where firstName is 'John' and lastName is 'Barnes'."
72
- );
73
- const invalidCursor = new Cursor("Match records where firstName ");
74
- const node = filter.parse(validCursor);
75
-
76
- try {
77
- filter.parse(invalidCursor);
78
- } catch (error) {}
79
- });
80
-
81
- test("Complex Examples: cssMethod", () => {
82
- const result = cssValue.exec(
83
- "linear-gradient(to left, #333, #333 50%, #eee 75%, #333 75%)"
84
- );
85
- });
86
- });