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.
- package/TODO.md +12 -2
- package/dist/grammar/patterns/statement.d.ts +2 -2
- package/dist/index.browser.js +46 -16
- package/dist/index.browser.js.map +1 -1
- package/dist/index.esm.js +46 -16
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +46 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/grammar/Grammar.test.ts +66 -10
- package/src/grammar/Grammar.ts +47 -14
- package/src/grammar/patterns/import.ts +8 -4
- package/src/grammar/patterns/statement.ts +4 -2
|
@@ -271,9 +271,9 @@ describe("Grammar", () => {
|
|
|
271
271
|
test("Bad Grammar At Beginning", () => {
|
|
272
272
|
|
|
273
273
|
expect(() => {
|
|
274
|
-
const expression =
|
|
274
|
+
const expression = `//`;
|
|
275
275
|
Grammar.parseString(expression);
|
|
276
|
-
}).
|
|
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("
|
|
364
|
+
test("Export Name", async () => {
|
|
365
365
|
const expression = `
|
|
366
|
-
|
|
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
|
});
|
package/src/grammar/Grammar.ts
CHANGED
|
@@ -119,9 +119,15 @@ export class Grammar {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
private _buildPatterns(ast: Node) {
|
|
122
|
-
ast.
|
|
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
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
|
|
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
|
|
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
|
-
|
|
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")]);
|