clarity-pattern-parser 8.4.10 → 8.4.11

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.
@@ -271,9 +271,9 @@ describe("Grammar", () => {
271
271
  test("Bad Grammar At Beginning", () => {
272
272
 
273
273
  expect(() => {
274
- const expression = `Just Junk`;
274
+ const expression = `//`;
275
275
  Grammar.parseString(expression);
276
- }).toThrowError("[Parse Error] Found: 'Just Junk', expected: ' ='.");
276
+ }).toThrow();
277
277
 
278
278
  });
279
279
 
@@ -339,18 +339,18 @@ describe("Grammar", () => {
339
339
  use params { custom-space }
340
340
  space = custom-space
341
341
  `
342
-
343
- const pathMap: Record<string, string> = {
344
- "space.cpat": spaceExpression,
345
- "first-name.cpat": importExpression
346
- };
347
-
348
342
  const expression = `
349
343
  import { first-name } from "first-name.cpat"
350
344
  import { space } from "space.cpat" with params { custom-space = " " }
351
345
  last-name = "Doe"
352
346
  full-name = first-name & space & last-name
353
347
  `
348
+
349
+ const pathMap: Record<string, string> = {
350
+ "space.cpat": spaceExpression,
351
+ "first-name.cpat": importExpression
352
+ };
353
+
354
354
  function resolveImport(resource: string) {
355
355
  return Promise.resolve({ expression: pathMap[resource], resource });
356
356
  }
@@ -361,9 +361,65 @@ describe("Grammar", () => {
361
361
  expect(result?.ast?.value).toBe("John Doe");
362
362
  });
363
363
 
364
- test("Use Params", () => {
364
+ test("Export Name", async () => {
365
365
  const expression = `
366
- use Params { first-name }
366
+ import { use-this } from "resource1"
367
+ import {name} from "resource2" with params {
368
+ use-this
369
+ }
370
+
371
+ name
367
372
  `
373
+
374
+ const resource1 = `
375
+ use-this = "Use This"
376
+ `;
377
+
378
+ const resource2 = `
379
+ use params {
380
+ use-this
381
+ }
382
+ name = use-this
383
+ `;
384
+
385
+ const pathMap: Record<string, string> = {
386
+ "resource1": resource1,
387
+ "resource2": resource2
388
+ };
389
+
390
+ function resolveImport(resource: string) {
391
+ return Promise.resolve({ expression: pathMap[resource], resource });
392
+ }
393
+ const patterns = await Grammar.parse(expression, { resolveImport });
394
+ const pattern = patterns.get("name") as Literal;
395
+
396
+ const result = pattern.exec("Use This");
397
+
398
+ expect(result.ast?.value).toBe("Use This");
399
+ });
400
+
401
+ test("Import Alias", async () => {
402
+ const expression = `
403
+ import { value as alias } from "resource1"
404
+ name = alias
405
+ `
406
+
407
+ const resource1 = `
408
+ value = "Value"
409
+ `;
410
+
411
+
412
+ const pathMap: Record<string, string> = {
413
+ "resource1": resource1,
414
+ };
415
+
416
+ function resolveImport(resource: string) {
417
+ return Promise.resolve({ expression: pathMap[resource], resource });
418
+ }
419
+ const patterns = await Grammar.parse(expression, { resolveImport });
420
+ const pattern = patterns.get("name") as Literal;
421
+
422
+ const result = pattern.exec("Value");
423
+ expect(result.ast?.value).toBe("Value");
368
424
  });
369
425
  });
@@ -119,9 +119,15 @@ export class Grammar {
119
119
  }
120
120
 
121
121
  private _buildPatterns(ast: Node) {
122
- ast.findAll(n => n.name === "statement").forEach((n) => {
122
+ const body = ast.find(n => n.name === "body");
123
+
124
+ if (body == null) {
125
+ return;
126
+ }
127
+
128
+ body.findAll(n => n.name === "assign-statement" || n.name === "export-name").forEach((n) => {
123
129
  const typeNode = n.find(n => n.name.includes("literal"));
124
- const type = typeNode?.name || "unknown";
130
+ const type = n.name === "export-name" ? "export-name" : typeNode?.name || "unknown";
125
131
 
126
132
  switch (type) {
127
133
  case "literal": {
@@ -148,6 +154,11 @@ export class Grammar {
148
154
  this._buildAlias(n)
149
155
  break;
150
156
  }
157
+ case "export-name": {
158
+ const pattern = this._getPattern(n.value);
159
+ this._parseContext.patternsByName.set(n.value, pattern);
160
+ break;
161
+ }
151
162
  default: {
152
163
  break;
153
164
  }
@@ -172,20 +183,42 @@ export class Grammar {
172
183
 
173
184
  try {
174
185
  const patterns = await grammar.parse(grammarFile.expression);
175
- const importNames = importStatement.findAll(n => n.name === "import-name").map(n => n.value);
176
-
177
- importNames.forEach((importName) => {
178
- if (parseContext.importedPatternsByName.has(importName)) {
179
- throw new Error(`'${importName}' was already used within another import.`);
186
+ const importStatements = importStatement.findAll(n => n.name === "import-name" || n.name === "import-alias");
187
+
188
+ importStatements.forEach((node) => {
189
+ if (node.name === "import-name") {
190
+ const importName = node.value;
191
+
192
+ if (parseContext.importedPatternsByName.has(importName)) {
193
+ throw new Error(`'${importName}' was already used within another import.`);
194
+ }
195
+
196
+ const pattern = patterns.get(importName);
197
+ if (pattern == null) {
198
+ throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
199
+ }
200
+
201
+ parseContext.importedPatternsByName.set(importName, pattern);
202
+ } else {
203
+ const importNameNode = node.find(n => n.name === "import-name") as Node;
204
+ const importName = importNameNode.value;
205
+ const aliasNode = node.find(n => n.name === "import-name-alias") as Node;
206
+ const alias = aliasNode.value;
207
+
208
+ if (parseContext.importedPatternsByName.has(alias)) {
209
+ throw new Error(`'${alias}' was already used within another import.`);
210
+ }
211
+
212
+ const pattern = patterns.get(importName);
213
+ if (pattern == null) {
214
+ throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
215
+ }
216
+
217
+ parseContext.importedPatternsByName.set(alias, pattern);
180
218
  }
219
+ });
181
220
 
182
- const pattern = patterns.get(importName);
183
- if (pattern == null) {
184
- throw new Error(`Couldn't find pattern with name: ${importName}, from import: ${resource}.`);
185
- }
186
221
 
187
- parseContext.importedPatternsByName.set(importName, pattern);
188
- })
189
222
 
190
223
  } catch (e: any) {
191
224
  throw new Error(`Failed loading expression from: "${resource}". Error details: "${e.message}"`);
@@ -199,7 +232,7 @@ export class Grammar {
199
232
  const paramsStatement = importStatement.find(n => n.name === "with-params-statement");
200
233
 
201
234
  if (paramsStatement != null) {
202
- const statements = paramsStatement.find(n => n.name === "body");
235
+ const statements = paramsStatement.find(n => n.name === "with-params-body");
203
236
 
204
237
  if (statements != null) {
205
238
  const expression = statements.toString();
@@ -7,18 +7,22 @@ import { Or } from "../../patterns/Or";
7
7
  import { body } from "./body";
8
8
  import { allSpaces, lineSpaces } from "./spaces";
9
9
 
10
+ const optionalSpaces = allSpaces.clone("optional-spaces", true);
11
+ const optionalLineSpaces = lineSpaces.clone("options-line-spaces", true);
12
+
10
13
  const importNameDivider = new Regex("import-name-divider", "(\\s+)?,(\\s+)?");
11
14
  const importKeyword = new Literal("import", "import");
12
15
  const useParamsKeyword = new Literal("use-params", "use params");
16
+ const asKeyword = new Literal("as", "as");
13
17
  const fromKeyword = new Literal("from", "from");
14
18
  const openBracket = new Literal("open-bracket", "{");
15
19
  const closeBracket = new Literal("close-bracket", "}");
16
20
  const name = new Regex("import-name", "[^}\\s,]+");
17
- const importedNames = new Repeat("imported-names", name, { divider: importNameDivider });
21
+ const importNameAlias = name.clone("import-name-alias");
22
+ const importAlias = new And("import-alias", [name, lineSpaces, asKeyword, lineSpaces, importNameAlias]);
23
+ const importedNames = new Repeat("imported-names", new Or("import-names", [importAlias, name]), { divider: importNameDivider });
18
24
  const paramName = name.clone("param-name");
19
25
  const paramNames = new Repeat("param-names", paramName, { divider: importNameDivider });
20
- const optionalSpaces = allSpaces.clone("optional-spaces", true);
21
- const optionalLineSpaces = lineSpaces.clone("options-line-spaces", true);
22
26
  const resource = literal.clone("resource");
23
27
 
24
28
  const useParams = new And("import-params", [
@@ -37,7 +41,7 @@ const withParamsStatement = new And("with-params-statement", [
37
41
  optionalLineSpaces,
38
42
  openBracket,
39
43
  optionalSpaces,
40
- body,
44
+ body.clone("with-params-body"),
41
45
  optionalSpaces,
42
46
  closeBracket
43
47
  ], true);
@@ -21,11 +21,13 @@ const statements = new Or("statements", [
21
21
  name.clone("alias-literal"),
22
22
  ]);
23
23
 
24
- export const statement = new And("statement", [
24
+ const assignStatement = new And("assign-statement", [
25
25
  optionalSpaces,
26
26
  name,
27
27
  optionalSpaces,
28
28
  assignOperator,
29
29
  optionalSpaces,
30
30
  statements
31
- ]);
31
+ ]);
32
+
33
+ export const statement = new Or("statement", [assignStatement, name.clone("export-name")]);