clarity-pattern-parser 11.0.30 → 11.1.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.
- package/dist/grammar/Grammar.d.ts +3 -0
- package/dist/grammar/decorators/tokens.d.ts +2 -0
- package/dist/grammar/patterns/decoratorStatement.d.ts +2 -0
- package/dist/grammar/patterns.d.ts +2 -0
- package/dist/index.browser.js +161 -25
- package/dist/index.browser.js.map +1 -1
- package/dist/index.esm.js +161 -25
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +161 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/grammar/Grammar.test.ts +88 -2
- package/src/grammar/Grammar.ts +86 -11
- package/src/grammar/decorators/tokens.ts +18 -0
- package/src/grammar/patterns/decoratorStatement.ts +85 -0
- package/src/grammar/patterns/statement.ts +2 -1
- package/src/grammar/patterns.ts +19 -1
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ import { Repeat } from "../patterns/Repeat";
|
|
|
9
9
|
import { Grammar } from "./Grammar";
|
|
10
10
|
import { Optional } from "../patterns/Optional";
|
|
11
11
|
import { Context } from "../patterns/Context";
|
|
12
|
-
import { patterns } from "./patterns";
|
|
12
|
+
import { createPatternsTemplate, patterns } from "./patterns";
|
|
13
13
|
import { Expression } from "../patterns/Expression";
|
|
14
14
|
|
|
15
15
|
describe("Grammar", () => {
|
|
@@ -176,7 +176,7 @@ describe("Grammar", () => {
|
|
|
176
176
|
const digits = new Optional("optional-digits", new Repeat("digits", digit, { min: 0 }));
|
|
177
177
|
|
|
178
178
|
const expected = new Context("optional-digits", digits, [digit]);
|
|
179
|
-
debugger;
|
|
179
|
+
debugger;
|
|
180
180
|
expect(pattern.isEqual(expected)).toBeTruthy();
|
|
181
181
|
});
|
|
182
182
|
|
|
@@ -596,4 +596,90 @@ debugger;
|
|
|
596
596
|
expect(result).toBe(result);
|
|
597
597
|
});
|
|
598
598
|
|
|
599
|
+
test("Decorators", () => {
|
|
600
|
+
const { spaces } = patterns`
|
|
601
|
+
@tokens([" "])
|
|
602
|
+
spaces = /\\s+/
|
|
603
|
+
`;
|
|
604
|
+
|
|
605
|
+
expect(spaces.getTokens()).toEqual([" "]);
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
test("Decorators No Args", () => {
|
|
609
|
+
const { spaces } = patterns`
|
|
610
|
+
@tokens()
|
|
611
|
+
spaces = /\\s+/
|
|
612
|
+
`;
|
|
613
|
+
|
|
614
|
+
expect(spaces.getTokens()).toEqual([]);
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
test("Decorators Bad Args", () => {
|
|
618
|
+
const { spaces } = patterns`
|
|
619
|
+
@tokens("Bad")
|
|
620
|
+
spaces = /\\s+/
|
|
621
|
+
`;
|
|
622
|
+
|
|
623
|
+
expect(spaces.getTokens()).toEqual([]);
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
test("Decorators Bad Decorator", () => {
|
|
627
|
+
const { spaces } = patterns`
|
|
628
|
+
@bad-decorator()
|
|
629
|
+
spaces = /\\s+/
|
|
630
|
+
`;
|
|
631
|
+
|
|
632
|
+
expect(spaces.getTokens()).toEqual([]);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
test("Decorators On Multiple Patterns", () => {
|
|
636
|
+
const { spaces, digits } = patterns`
|
|
637
|
+
@tokens([" "])
|
|
638
|
+
spaces = /\\s+/
|
|
639
|
+
|
|
640
|
+
@tokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])
|
|
641
|
+
digits = /\\d+/
|
|
642
|
+
`;
|
|
643
|
+
|
|
644
|
+
expect(spaces.getTokens()).toEqual([" "]);
|
|
645
|
+
expect(digits.getTokens()).toEqual(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
test("Decorators On Multiple Patterns And Comments", () => {
|
|
649
|
+
const { spaces, digits } = patterns`
|
|
650
|
+
#Comment
|
|
651
|
+
@tokens([" "])
|
|
652
|
+
spaces = /\\s+/
|
|
653
|
+
|
|
654
|
+
#Comment
|
|
655
|
+
@tokens(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])
|
|
656
|
+
#Comment
|
|
657
|
+
digits = /\\d+/
|
|
658
|
+
`;
|
|
659
|
+
|
|
660
|
+
expect(spaces.getTokens()).toEqual([" "]);
|
|
661
|
+
expect(digits.getTokens()).toEqual(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
test("Custom Named Decorator", () => {
|
|
665
|
+
const allRecordedPatterns: string[] = [];
|
|
666
|
+
const patterns = createPatternsTemplate({
|
|
667
|
+
decorators: {
|
|
668
|
+
record: (pattern) => {
|
|
669
|
+
allRecordedPatterns.push(pattern.name);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
patterns`
|
|
675
|
+
@record
|
|
676
|
+
spaces = /\\s+/
|
|
677
|
+
|
|
678
|
+
@record
|
|
679
|
+
digits = /\\d+/
|
|
680
|
+
`;
|
|
681
|
+
|
|
682
|
+
expect(allRecordedPatterns).toEqual(["spaces", "digits"]);
|
|
683
|
+
});
|
|
684
|
+
|
|
599
685
|
});
|
package/src/grammar/Grammar.ts
CHANGED
|
@@ -13,9 +13,16 @@ import { Context } from "../patterns/Context";
|
|
|
13
13
|
import { Expression } from "../patterns/Expression";
|
|
14
14
|
import { RightAssociated } from "../patterns/RightAssociated";
|
|
15
15
|
import { generateErrorMessage } from "../patterns/generate_error_message";
|
|
16
|
+
import { tokens } from "./decorators/tokens";
|
|
16
17
|
|
|
17
18
|
let anonymousIndexId = 0;
|
|
18
19
|
|
|
20
|
+
export type Decorator = (pattern: Pattern, arg?: string | boolean | number | null | Record<string, any> | any[]) => void;
|
|
21
|
+
|
|
22
|
+
const defaultDecorators = {
|
|
23
|
+
tokens: tokens
|
|
24
|
+
};
|
|
25
|
+
|
|
19
26
|
const patternNodes: Record<string, boolean> = {
|
|
20
27
|
"literal": true,
|
|
21
28
|
"regex-literal": true,
|
|
@@ -27,12 +34,14 @@ const patternNodes: Record<string, boolean> = {
|
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
class ParseContext {
|
|
30
|
-
constructor(params: Pattern[]) {
|
|
31
|
-
params.forEach(p => this.paramsByName.set(p.name, p));
|
|
32
|
-
}
|
|
33
37
|
patternsByName = new Map<string, Pattern>();
|
|
34
38
|
importedPatternsByName = new Map<string, Pattern>();
|
|
35
39
|
paramsByName = new Map<string, Pattern>();
|
|
40
|
+
decorators: Record<string, Decorator>;
|
|
41
|
+
constructor(params: Pattern[], decorators: Record<string, Decorator> = {}) {
|
|
42
|
+
params.forEach(p => this.paramsByName.set(p.name, p));
|
|
43
|
+
this.decorators = { ...decorators, ...defaultDecorators };
|
|
44
|
+
}
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
function defaultImportResolver(_path: string, _basePath: string | null): Promise<GrammarFile> {
|
|
@@ -48,6 +57,7 @@ export interface GrammarOptions {
|
|
|
48
57
|
resolveImport?: (resource: string, originResource: string | null) => Promise<GrammarFile>;
|
|
49
58
|
originResource?: string | null;
|
|
50
59
|
params?: Pattern[];
|
|
60
|
+
decorators?: Record<string, Decorator>;
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
export class Grammar {
|
|
@@ -60,7 +70,7 @@ export class Grammar {
|
|
|
60
70
|
this._params = options?.params == null ? [] : options.params;
|
|
61
71
|
this._originResource = options?.originResource == null ? null : options.originResource;
|
|
62
72
|
this._resolveImport = options.resolveImport == null ? defaultImportResolver : options.resolveImport;
|
|
63
|
-
this._parseContext = new ParseContext(this._params);
|
|
73
|
+
this._parseContext = new ParseContext(this._params, options.decorators || {});
|
|
64
74
|
}
|
|
65
75
|
|
|
66
76
|
async import(path: string) {
|
|
@@ -68,14 +78,15 @@ export class Grammar {
|
|
|
68
78
|
const grammar = new Grammar({
|
|
69
79
|
resolveImport: this._resolveImport,
|
|
70
80
|
originResource: grammarFile.resource,
|
|
71
|
-
params: this._params
|
|
81
|
+
params: this._params,
|
|
82
|
+
decorators: this._parseContext.decorators
|
|
72
83
|
});
|
|
73
84
|
|
|
74
85
|
return grammar.parse(grammarFile.expression);
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
async parse(expression: string) {
|
|
78
|
-
this._parseContext = new ParseContext(this._params);
|
|
89
|
+
this._parseContext = new ParseContext(this._params, this._parseContext.decorators);
|
|
79
90
|
const ast = this._tryToParse(expression);
|
|
80
91
|
|
|
81
92
|
await this._resolveImports(ast);
|
|
@@ -85,7 +96,7 @@ export class Grammar {
|
|
|
85
96
|
}
|
|
86
97
|
|
|
87
98
|
parseString(expression: string) {
|
|
88
|
-
this._parseContext = new ParseContext(this._params);
|
|
99
|
+
this._parseContext = new ParseContext(this._params, this._parseContext.decorators);
|
|
89
100
|
const ast = this._tryToParse(expression);
|
|
90
101
|
|
|
91
102
|
if (this._hasImports(ast)) {
|
|
@@ -191,6 +202,7 @@ export class Grammar {
|
|
|
191
202
|
const name = nameNode.value;
|
|
192
203
|
const literal = this._buildLiteral(name, literalNode);
|
|
193
204
|
|
|
205
|
+
this._applyDecorators(statementNode, literal);
|
|
194
206
|
this._parseContext.patternsByName.set(name, literal);
|
|
195
207
|
}
|
|
196
208
|
|
|
@@ -217,6 +229,7 @@ export class Grammar {
|
|
|
217
229
|
const name = nameNode.value;
|
|
218
230
|
const regex = this._buildRegex(name, regexNode);
|
|
219
231
|
|
|
232
|
+
this._applyDecorators(statementNode, regex);
|
|
220
233
|
this._parseContext.patternsByName.set(name, regex);
|
|
221
234
|
}
|
|
222
235
|
|
|
@@ -231,6 +244,7 @@ export class Grammar {
|
|
|
231
244
|
const optionsNode = statementNode.find(n => n.name === "options-literal") as Node;
|
|
232
245
|
const options = this._buildOptions(name, optionsNode);
|
|
233
246
|
|
|
247
|
+
this._applyDecorators(statementNode, options);
|
|
234
248
|
this._parseContext.patternsByName.set(name, options);
|
|
235
249
|
}
|
|
236
250
|
|
|
@@ -322,6 +336,7 @@ export class Grammar {
|
|
|
322
336
|
const sequenceNode = statementNode.find(n => n.name === "sequence-literal") as Node;
|
|
323
337
|
const sequence = this._buildSequence(name, sequenceNode);
|
|
324
338
|
|
|
339
|
+
this._applyDecorators(statementNode, sequence);
|
|
325
340
|
this._parseContext.patternsByName.set(name, sequence);
|
|
326
341
|
}
|
|
327
342
|
|
|
@@ -351,6 +366,7 @@ export class Grammar {
|
|
|
351
366
|
const repeatNode = statementNode.find(n => n.name === "repeat-literal") as Node;
|
|
352
367
|
const repeat = this._buildRepeat(name, repeatNode);
|
|
353
368
|
|
|
369
|
+
this._applyDecorators(statementNode, repeat);
|
|
354
370
|
this._parseContext.patternsByName.set(name, repeat);
|
|
355
371
|
}
|
|
356
372
|
|
|
@@ -413,6 +429,8 @@ export class Grammar {
|
|
|
413
429
|
const isOptional = node.children[1] != null;
|
|
414
430
|
|
|
415
431
|
const anonymous = isOptional ? new Optional(name, this._buildPattern(anonymousNode.children[0])) : this._buildPattern(anonymousNode.children[0]);
|
|
432
|
+
|
|
433
|
+
this._applyDecorators(node, anonymous);
|
|
416
434
|
this._parseContext.patternsByName.set(name, anonymous);
|
|
417
435
|
}
|
|
418
436
|
|
|
@@ -433,7 +451,8 @@ export class Grammar {
|
|
|
433
451
|
const grammar = new Grammar({
|
|
434
452
|
resolveImport: this._resolveImport,
|
|
435
453
|
originResource: grammarFile.resource,
|
|
436
|
-
params
|
|
454
|
+
params,
|
|
455
|
+
decorators: this._parseContext.decorators
|
|
437
456
|
});
|
|
438
457
|
|
|
439
458
|
try {
|
|
@@ -486,6 +505,59 @@ export class Grammar {
|
|
|
486
505
|
}
|
|
487
506
|
}
|
|
488
507
|
|
|
508
|
+
private _applyDecorators(statementNode: Node, pattern: Pattern) {
|
|
509
|
+
const decorators = this._parseContext.decorators;
|
|
510
|
+
const bodyLine = statementNode.parent;
|
|
511
|
+
|
|
512
|
+
if (bodyLine == null) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
let prevSibling = bodyLine.previousSibling();
|
|
517
|
+
let decoratorNodes: Node[] = [];
|
|
518
|
+
|
|
519
|
+
while (prevSibling != null) {
|
|
520
|
+
if (prevSibling.find(n => n.name === "assign-statement")) {
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
decoratorNodes.push(prevSibling);
|
|
524
|
+
prevSibling = prevSibling.previousSibling();
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
decoratorNodes = decoratorNodes.filter(n => n.find(n => n.name.includes("decorator")) != null);
|
|
528
|
+
|
|
529
|
+
decoratorNodes.forEach((d) => {
|
|
530
|
+
const nameNode = d.find(n => n.name === "decorator-name");
|
|
531
|
+
|
|
532
|
+
if (nameNode == null || decorators[nameNode.value] == null) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const nameDocorator = d.find(n => n.name === "name-decorator");
|
|
537
|
+
|
|
538
|
+
if (nameDocorator != null) {
|
|
539
|
+
decorators[nameNode.value](pattern);
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
const methodDecorator = d.find(n => n.name === "method-decorator");
|
|
544
|
+
|
|
545
|
+
if (methodDecorator == null) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
methodDecorator.findAll(n => n.name.includes("space")).forEach(n => n.remove());
|
|
550
|
+
const argsNode = methodDecorator.children[3];
|
|
551
|
+
|
|
552
|
+
if (argsNode == null || argsNode.name === "close-paren") {
|
|
553
|
+
decorators[nameNode.value](pattern);
|
|
554
|
+
} else {
|
|
555
|
+
decorators[nameNode.value](pattern, JSON.parse(argsNode.value));
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
}
|
|
560
|
+
|
|
489
561
|
private _getParams(importStatement: Node) {
|
|
490
562
|
let params: Pattern[] = [];
|
|
491
563
|
const paramsStatement = importStatement.find(n => n.name === "with-params-statement");
|
|
@@ -504,7 +576,8 @@ export class Grammar {
|
|
|
504
576
|
const grammar = new Grammar({
|
|
505
577
|
params: [...importedValues, ...this._parseContext.paramsByName.values()],
|
|
506
578
|
originResource: this._originResource,
|
|
507
|
-
resolveImport: this._resolveImport
|
|
579
|
+
resolveImport: this._resolveImport,
|
|
580
|
+
decorators: this._parseContext.decorators
|
|
508
581
|
});
|
|
509
582
|
|
|
510
583
|
const patterns = grammar.parseString(expression);
|
|
@@ -539,13 +612,15 @@ export class Grammar {
|
|
|
539
612
|
const aliasName = aliasNode.value;
|
|
540
613
|
const name = nameNode.value;
|
|
541
614
|
const aliasPattern = this._getPattern(aliasName);
|
|
542
|
-
|
|
615
|
+
|
|
543
616
|
// This solves the problem for an alias pointing to a reference.
|
|
544
|
-
if (aliasPattern.type === "reference"){
|
|
617
|
+
if (aliasPattern.type === "reference") {
|
|
545
618
|
const reference = new Reference(name, aliasName);
|
|
619
|
+
this._applyDecorators(statementNode, reference);
|
|
546
620
|
this._parseContext.patternsByName.set(name, reference);
|
|
547
621
|
} else {
|
|
548
622
|
const alias = aliasPattern.clone(name);
|
|
623
|
+
this._applyDecorators(statementNode, alias);
|
|
549
624
|
this._parseContext.patternsByName.set(name, alias);
|
|
550
625
|
}
|
|
551
626
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Pattern } from "../../patterns/Pattern";
|
|
2
|
+
import { Regex } from "../../patterns/Regex";
|
|
3
|
+
import { Decorator } from "../Grammar";
|
|
4
|
+
|
|
5
|
+
export const tokens: Decorator = (pattern: Pattern, arg: any) => {
|
|
6
|
+
if (pattern.type === "regex" && Array.isArray(arg)) {
|
|
7
|
+
const regex = pattern as Regex;
|
|
8
|
+
const tokens: string[] = [];
|
|
9
|
+
|
|
10
|
+
arg.forEach(token => {
|
|
11
|
+
if (typeof token === "string") {
|
|
12
|
+
tokens.push(token);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
regex.setTokens(tokens);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Literal } from "../../patterns/Literal";
|
|
2
|
+
import { Optional } from "../../patterns/Optional";
|
|
3
|
+
import { Options } from "../../patterns/Options";
|
|
4
|
+
import { Reference } from "../../patterns/Reference";
|
|
5
|
+
import { Regex } from "../../patterns/Regex";
|
|
6
|
+
import { Repeat } from "../../patterns/Repeat";
|
|
7
|
+
import { Sequence } from "../../patterns/Sequence";
|
|
8
|
+
import { name } from "./name";
|
|
9
|
+
import { allSpaces } from "./spaces";
|
|
10
|
+
|
|
11
|
+
const colon = new Literal("colon", ":");
|
|
12
|
+
const comma = new Regex("comma", "\\s*,\\s*");
|
|
13
|
+
const openBracket = new Literal("open-bracket", "{");
|
|
14
|
+
const closeBracket = new Literal("close-bracket", "}");
|
|
15
|
+
const openSquareBracket = new Literal("open-square-bracket", "[");
|
|
16
|
+
const closeSquareBracket = new Literal("close-square-bracket", "]");
|
|
17
|
+
const optionalAllSpaces = new Optional("optional-all-spaces", allSpaces);
|
|
18
|
+
|
|
19
|
+
const stringLiteral = new Regex("string-literal", '"(?:\\\\.|[^"\\\\])*"');
|
|
20
|
+
const numberLiteral = new Regex("number-literal", '[+-]?\\d+(\\\\.\\d+)?([eE][+-]?\\d+)?');
|
|
21
|
+
const nullLiteral = new Literal("null-literal", "null");
|
|
22
|
+
const trueLiteral = new Literal("true-literal", "true");
|
|
23
|
+
const falseLiteral = new Literal("false-literal", "false");
|
|
24
|
+
const booleanLiteral = new Options("", [trueLiteral, falseLiteral]);
|
|
25
|
+
|
|
26
|
+
const objectKey = name.clone("object-key");
|
|
27
|
+
const objectProperty = new Sequence("object-property", [
|
|
28
|
+
objectKey,
|
|
29
|
+
optionalAllSpaces,
|
|
30
|
+
colon,
|
|
31
|
+
optionalAllSpaces,
|
|
32
|
+
new Reference("literal"),
|
|
33
|
+
]);
|
|
34
|
+
const objectProperies = new Repeat("object-properties", objectProperty, { divider: comma });
|
|
35
|
+
const objectLiteral = new Sequence("object-literal", [
|
|
36
|
+
openBracket,
|
|
37
|
+
optionalAllSpaces,
|
|
38
|
+
new Optional("optional-object-properties", objectProperies),
|
|
39
|
+
optionalAllSpaces,
|
|
40
|
+
closeBracket
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
const arrayItems = new Repeat("array-items", new Reference("literal"), { divider: comma });
|
|
44
|
+
const arrayLiteral = new Sequence("array-literal", [
|
|
45
|
+
openSquareBracket,
|
|
46
|
+
optionalAllSpaces,
|
|
47
|
+
arrayItems,
|
|
48
|
+
optionalAllSpaces,
|
|
49
|
+
closeSquareBracket,
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
const literal = new Options("literal", [
|
|
53
|
+
objectLiteral,
|
|
54
|
+
arrayLiteral,
|
|
55
|
+
stringLiteral,
|
|
56
|
+
booleanLiteral,
|
|
57
|
+
nullLiteral,
|
|
58
|
+
numberLiteral,
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
const decoratorPrefix = new Literal("decorator-prefix", "@");
|
|
62
|
+
const decoratorName = name.clone("decorator-name");
|
|
63
|
+
const openParen = new Literal("open-paren", "(");
|
|
64
|
+
const closeParen = new Literal("close-paren", ")");
|
|
65
|
+
|
|
66
|
+
const methodDecoration = new Sequence("method-decorator", [
|
|
67
|
+
decoratorPrefix,
|
|
68
|
+
decoratorName,
|
|
69
|
+
optionalAllSpaces,
|
|
70
|
+
openParen,
|
|
71
|
+
optionalAllSpaces,
|
|
72
|
+
new Optional("optional-args", literal),
|
|
73
|
+
optionalAllSpaces,
|
|
74
|
+
closeParen
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
const nameDecoration = new Sequence("name-decorator", [
|
|
78
|
+
decoratorPrefix,
|
|
79
|
+
decoratorName,
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
export const decoratorStatement = new Options("decorator-statement", [
|
|
83
|
+
methodDecoration,
|
|
84
|
+
nameDecoration,
|
|
85
|
+
]);
|
|
@@ -5,6 +5,7 @@ import { name } from "./name";
|
|
|
5
5
|
import { spaces } from "./spaces";
|
|
6
6
|
import { pattern } from "./pattern";
|
|
7
7
|
import { Optional } from "../../patterns/Optional";
|
|
8
|
+
import {decoratorStatement} from './decoratorStatement';
|
|
8
9
|
|
|
9
10
|
const optionalSpaces = new Optional("optional-spaces", spaces);
|
|
10
11
|
const assignOperator = new Literal("assign-operator", "=");
|
|
@@ -18,4 +19,4 @@ const assignStatement = new Sequence("assign-statement", [
|
|
|
18
19
|
pattern,
|
|
19
20
|
]);
|
|
20
21
|
|
|
21
|
-
export const statement = new Options("statement", [assignStatement, name.clone("export-name")]);
|
|
22
|
+
export const statement = new Options("statement", [decoratorStatement, assignStatement, name.clone("export-name")]);
|
package/src/grammar/patterns.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Pattern } from "../patterns/Pattern";
|
|
2
|
-
import { Grammar } from "./Grammar";
|
|
2
|
+
import { Grammar, GrammarOptions } from "./Grammar";
|
|
3
3
|
|
|
4
4
|
const kebabRegex = /-([a-z])/g; // Define the regex once
|
|
5
5
|
|
|
@@ -21,4 +21,22 @@ export function patterns(strings: TemplateStringsArray, ...values: any) {
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createPatternsTemplate(options: GrammarOptions){
|
|
27
|
+
return function patterns(strings: TemplateStringsArray, ...values: any) {
|
|
28
|
+
const combinedString = strings.reduce(
|
|
29
|
+
(result, str, i) => result + str + (values[i] || ''),
|
|
30
|
+
''
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const result: Record<string, Pattern> = {};
|
|
34
|
+
const patterns = Grammar.parseString(combinedString, options);
|
|
35
|
+
|
|
36
|
+
Object.keys(patterns).forEach(k => {
|
|
37
|
+
result[kebabToCamelCase(k)] = patterns[k];
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
24
42
|
}
|