@traqula/core 0.0.1-alpha.148 → 0.0.1-alpha.9
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/README.md +44 -22
- package/lib/CoreFactory.d.ts +39 -0
- package/lib/CoreFactory.js +135 -0
- package/lib/CoreFactory.js.map +1 -0
- package/lib/RangeArithmetic.d.ts +14 -0
- package/lib/RangeArithmetic.js +71 -0
- package/lib/RangeArithmetic.js.map +1 -0
- package/lib/Transformer.d.ts +26 -0
- package/lib/Transformer.js +57 -0
- package/lib/Transformer.js.map +1 -0
- package/lib/generator-builder/builderTypes.d.ts +23 -0
- package/lib/generator-builder/builderTypes.js.map +1 -0
- package/lib/generator-builder/dynamicGenerator.d.ts +22 -0
- package/lib/generator-builder/dynamicGenerator.js +115 -0
- package/lib/generator-builder/dynamicGenerator.js.map +1 -0
- package/lib/generator-builder/generatorBuilder.d.ts +59 -0
- package/lib/generator-builder/generatorBuilder.js +104 -0
- package/lib/generator-builder/generatorBuilder.js.map +1 -0
- package/lib/generator-builder/generatorTypes.d.ts +36 -0
- package/lib/generator-builder/generatorTypes.js +2 -0
- package/lib/generator-builder/generatorTypes.js.map +1 -0
- package/lib/index.cjs +706 -297
- package/lib/index.d.ts +11 -6
- package/lib/index.js +15 -6
- package/lib/index.js.map +1 -1
- package/lib/lexer-builder/LexerBuilder.d.ts +11 -9
- package/lib/lexer-builder/LexerBuilder.js +16 -4
- package/lib/lexer-builder/LexerBuilder.js.map +1 -1
- package/lib/nodeTypings.d.ts +53 -0
- package/lib/nodeTypings.js +2 -0
- package/lib/nodeTypings.js.map +1 -0
- package/lib/parser-builder/builderTypes.d.ts +24 -0
- package/lib/parser-builder/builderTypes.js +2 -0
- package/lib/parser-builder/builderTypes.js.map +1 -0
- package/lib/parser-builder/dynamicParser.d.ts +9 -0
- package/lib/parser-builder/dynamicParser.js +113 -0
- package/lib/parser-builder/dynamicParser.js.map +1 -0
- package/lib/parser-builder/parserBuilder.d.ts +74 -0
- package/lib/parser-builder/parserBuilder.js +171 -0
- package/lib/parser-builder/parserBuilder.js.map +1 -0
- package/lib/{grammar-builder → parser-builder}/ruleDefTypes.d.ts +5 -5
- package/lib/parser-builder/ruleDefTypes.js.map +1 -0
- package/lib/utils.d.ts +17 -0
- package/lib/utils.js +8 -0
- package/lib/utils.js.map +1 -0
- package/package.json +6 -6
- package/lib/Wildcard.d.ts +0 -9
- package/lib/Wildcard.js +0 -19
- package/lib/Wildcard.js.map +0 -1
- package/lib/grammar-builder/builderTypes.d.ts +0 -28
- package/lib/grammar-builder/builderTypes.js.map +0 -1
- package/lib/grammar-builder/parserBuilder.d.ts +0 -68
- package/lib/grammar-builder/parserBuilder.js +0 -283
- package/lib/grammar-builder/parserBuilder.js.map +0 -1
- package/lib/grammar-builder/ruleDefTypes.js.map +0 -1
- package/lib/grammar-helpers/utils.d.ts +0 -16
- package/lib/grammar-helpers/utils.js +0 -53
- package/lib/grammar-helpers/utils.js.map +0 -1
- package/lib/lexer-helper/utils.d.ts +0 -6
- package/lib/lexer-helper/utils.js +0 -5
- package/lib/lexer-helper/utils.js.map +0 -1
- /package/lib/{grammar-builder → generator-builder}/builderTypes.js +0 -0
- /package/lib/{grammar-builder → parser-builder}/ruleDefTypes.js +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { CoreFactory } from '../CoreFactory';
|
|
2
|
+
export class DynamicGenerator {
|
|
3
|
+
constructor(rules) {
|
|
4
|
+
this.rules = rules;
|
|
5
|
+
this.factory = new CoreFactory();
|
|
6
|
+
this.__context = undefined;
|
|
7
|
+
this.origSource = '';
|
|
8
|
+
this.generatedUntil = 0;
|
|
9
|
+
this.stringBuilder = [];
|
|
10
|
+
this.subrule = (cstDef, ast, arg) => {
|
|
11
|
+
const def = this.rules[cstDef.name];
|
|
12
|
+
if (!def) {
|
|
13
|
+
throw new Error(`Rule ${cstDef.name} not found`);
|
|
14
|
+
}
|
|
15
|
+
const generate = () => def.gImpl({
|
|
16
|
+
SUBRULE: this.subrule,
|
|
17
|
+
PRINT: this.print,
|
|
18
|
+
PRINT_SPACE_LEFT: this.printSpaceLeft,
|
|
19
|
+
PRINT_WORD: this.printWord,
|
|
20
|
+
PRINT_WORDS: this.printWords,
|
|
21
|
+
CATCHUP: this.catchup,
|
|
22
|
+
HANDLE_LOC: this.handleLoc,
|
|
23
|
+
})(ast, this.getSafeContext(), arg);
|
|
24
|
+
if (this.factory.isLocalized(ast)) {
|
|
25
|
+
this.handleLoc(ast, generate);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
generate();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
this.handleLoc = (localized, handle) => {
|
|
32
|
+
if (this.factory.isSourceLocationNoMaterialize(localized.loc)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (this.factory.isSourceLocationStringReplace(localized.loc)) {
|
|
36
|
+
this.catchup(localized.loc.start);
|
|
37
|
+
this.print(localized.loc.newSource);
|
|
38
|
+
this.generatedUntil = localized.loc.end;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (this.factory.isSourceLocationNodeReplace(localized.loc)) {
|
|
42
|
+
this.catchup(localized.loc.start);
|
|
43
|
+
this.generatedUntil = localized.loc.end;
|
|
44
|
+
}
|
|
45
|
+
if (this.factory.isSourceLocationSource(localized.loc)) {
|
|
46
|
+
this.catchup(localized.loc.start);
|
|
47
|
+
}
|
|
48
|
+
// If autoGenerate - do nothing
|
|
49
|
+
const ret = handle();
|
|
50
|
+
if (this.factory.isSourceLocationSource(localized.loc)) {
|
|
51
|
+
this.catchup(localized.loc.end);
|
|
52
|
+
}
|
|
53
|
+
return ret;
|
|
54
|
+
};
|
|
55
|
+
this.catchup = (until) => {
|
|
56
|
+
const start = this.generatedUntil;
|
|
57
|
+
if (start < until) {
|
|
58
|
+
this.print(this.origSource.slice(start, until));
|
|
59
|
+
}
|
|
60
|
+
this.generatedUntil = Math.max(this.generatedUntil, until);
|
|
61
|
+
};
|
|
62
|
+
this.print = (...args) => {
|
|
63
|
+
const pureArgs = args.filter(x => x.length > 0);
|
|
64
|
+
if (pureArgs.length > 0) {
|
|
65
|
+
const [head, ...tail] = pureArgs;
|
|
66
|
+
if (this.expectsSpace) {
|
|
67
|
+
this.expectsSpace = false;
|
|
68
|
+
const blanks = new Set(['\n', ' ', '\t']);
|
|
69
|
+
if (this.stringBuilder.length > 0 &&
|
|
70
|
+
!(blanks.has(head[0]) || blanks.has(this.stringBuilder.at(-1).at(-1)))) {
|
|
71
|
+
this.stringBuilder.push(' ');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
this.stringBuilder.push(head);
|
|
75
|
+
this.stringBuilder.push(...tail);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
this.printWord = (...args) => {
|
|
79
|
+
this.expectsSpace = true;
|
|
80
|
+
this.print(...args);
|
|
81
|
+
this.expectsSpace = true;
|
|
82
|
+
};
|
|
83
|
+
this.printSpaceLeft = (...args) => {
|
|
84
|
+
this.expectsSpace = true;
|
|
85
|
+
this.print(...args);
|
|
86
|
+
};
|
|
87
|
+
this.printWords = (...args) => {
|
|
88
|
+
for (const arg of args) {
|
|
89
|
+
this.printWord(arg);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
// eslint-disable-next-line ts/no-unnecessary-type-assertion
|
|
93
|
+
for (const rule of Object.values(rules)) {
|
|
94
|
+
// Define function implementation
|
|
95
|
+
this[rule.name] =
|
|
96
|
+
((input, context, args) => {
|
|
97
|
+
this.expectsSpace = false;
|
|
98
|
+
this.stringBuilder.length = 0;
|
|
99
|
+
this.origSource = context.origSource;
|
|
100
|
+
this.generatedUntil = context?.offset ?? 0;
|
|
101
|
+
this.setContext(context);
|
|
102
|
+
this.subrule(rule, input, args);
|
|
103
|
+
this.catchup(this.origSource.length);
|
|
104
|
+
return this.stringBuilder.join('');
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
setContext(context) {
|
|
109
|
+
this.__context = context;
|
|
110
|
+
}
|
|
111
|
+
getSafeContext() {
|
|
112
|
+
return this.__context;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=dynamicGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamicGenerator.js","sourceRoot":"","sources":["dynamicGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["import { CoreFactory } from '../CoreFactory';\nimport type { GenRuleMap } from './builderTypes';\nimport type { GeneratorRule, RuleDefArg } from './generatorTypes';\n\nexport class DynamicGenerator<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> {\n protected readonly factory = new CoreFactory();\n protected __context: Context | undefined = undefined;\n protected origSource = '';\n protected generatedUntil = 0;\n protected expectsSpace: boolean;\n protected readonly stringBuilder: string[] = [];\n\n public constructor(protected rules: RuleDefs) {\n // eslint-disable-next-line ts/no-unnecessary-type-assertion\n for (const rule of <GeneratorRule[]> Object.values(rules)) {\n // Define function implementation\n this[<keyof (typeof this)> rule.name] =\n <any> ((input: any, context: Context & { origSource: string; offset?: number }, args: any) => {\n this.expectsSpace = false;\n this.stringBuilder.length = 0;\n this.origSource = context.origSource;\n this.generatedUntil = context?.offset ?? 0;\n this.setContext(context);\n\n this.subrule(rule, input, args);\n\n this.catchup(this.origSource.length);\n\n return this.stringBuilder.join('');\n });\n }\n }\n\n public setContext(context: Context): void {\n this.__context = context;\n }\n\n protected getSafeContext(): Context {\n return <Context> this.__context;\n }\n\n protected readonly subrule: RuleDefArg['SUBRULE'] = (cstDef, ast, arg) => {\n const def = this.rules[<Names> cstDef.name];\n if (!def) {\n throw new Error(`Rule ${cstDef.name} not found`);\n }\n\n const generate = (): void => def.gImpl({\n SUBRULE: this.subrule,\n PRINT: this.print,\n PRINT_SPACE_LEFT: this.printSpaceLeft,\n PRINT_WORD: this.printWord,\n PRINT_WORDS: this.printWords,\n CATCHUP: this.catchup,\n HANDLE_LOC: this.handleLoc,\n })(ast, this.getSafeContext(), arg);\n\n if (this.factory.isLocalized(ast)) {\n this.handleLoc(ast, generate);\n } else {\n generate();\n }\n };\n\n protected readonly handleLoc: RuleDefArg['HANDLE_LOC'] = (localized, handle) => {\n if (this.factory.isSourceLocationNoMaterialize(localized.loc)) {\n return;\n }\n if (this.factory.isSourceLocationStringReplace(localized.loc)) {\n this.catchup(localized.loc.start);\n this.print(localized.loc.newSource);\n this.generatedUntil = localized.loc.end;\n return;\n }\n if (this.factory.isSourceLocationNodeReplace(localized.loc)) {\n this.catchup(localized.loc.start);\n this.generatedUntil = localized.loc.end;\n }\n if (this.factory.isSourceLocationSource(localized.loc)) {\n this.catchup(localized.loc.start);\n }\n // If autoGenerate - do nothing\n\n const ret = handle();\n\n if (this.factory.isSourceLocationSource(localized.loc)) {\n this.catchup(localized.loc.end);\n }\n return ret;\n };\n\n protected readonly catchup: RuleDefArg['CATCHUP'] = (until) => {\n const start = this.generatedUntil;\n if (start < until) {\n this.print(this.origSource.slice(start, until));\n }\n this.generatedUntil = Math.max(this.generatedUntil, until);\n };\n\n protected readonly print: RuleDefArg['PRINT'] = (...args) => {\n const pureArgs = args.filter(x => x.length > 0);\n if (pureArgs.length > 0) {\n const [ head, ...tail ] = pureArgs;\n if (this.expectsSpace) {\n this.expectsSpace = false;\n const blanks = new Set([ '\\n', ' ', '\\t' ]);\n if (this.stringBuilder.length > 0 &&\n !(blanks.has(head[0]) || blanks.has(this.stringBuilder.at(-1)!.at(-1)!))) {\n this.stringBuilder.push(' ');\n }\n }\n this.stringBuilder.push(head);\n this.stringBuilder.push(...tail);\n }\n };\n\n private readonly printWord: RuleDefArg['PRINT_WORD'] = (...args) => {\n this.expectsSpace = true;\n this.print(...args);\n this.expectsSpace = true;\n };\n\n private readonly printSpaceLeft: RuleDefArg['PRINT_WORD'] = (...args) => {\n this.expectsSpace = true;\n this.print(...args);\n };\n\n private readonly printWords: RuleDefArg['PRINT_WORD'] = (...args) => {\n for (const arg of args) {\n this.printWord(arg);\n }\n };\n}\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { CheckOverlap } from '../utils';
|
|
2
|
+
import type { GeneratorFromRules, GenRuleMap, GenRulesToObject, GenNamesFromList } from './builderTypes';
|
|
3
|
+
import type { GeneratorRule } from './generatorTypes';
|
|
4
|
+
export declare class GeneratorBuilder<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> {
|
|
5
|
+
/**
|
|
6
|
+
* Create a GeneratorBuilder from some initial grammar rules or an existing GeneratorBuilder.
|
|
7
|
+
* If a GeneratorBuilder is provided, a new copy will be created.
|
|
8
|
+
*/
|
|
9
|
+
static create<Context, Names extends string, RuleDefs extends GenRuleMap<Names>>(args: GeneratorBuilder<Context, Names, RuleDefs>): GeneratorBuilder<Context, Names, RuleDefs>;
|
|
10
|
+
static create<Rules extends readonly GeneratorRule[] = readonly GeneratorRule[], Context = Rules[0] extends GeneratorRule<infer context> ? context : never, Names extends string = GenNamesFromList<Rules>, RuleDefs extends GenRuleMap<Names> = GenRulesToObject<Rules>>(rules: Rules): GeneratorBuilder<Context, Names, RuleDefs>;
|
|
11
|
+
private rules;
|
|
12
|
+
private constructor();
|
|
13
|
+
widenContext<NewContext extends Context>(): GeneratorBuilder<NewContext, Names, RuleDefs>;
|
|
14
|
+
typePatch<Patch extends {
|
|
15
|
+
[Key in Names]?: any;
|
|
16
|
+
}>(): GeneratorBuilder<Context, Names, {
|
|
17
|
+
[Key in Names]: Key extends keyof Patch ? (RuleDefs[Key] extends GeneratorRule<Context, Key, any, infer Args> ? GeneratorRule<Context, Key, Patch[Key], Args> : never) : (RuleDefs[Key] extends GeneratorRule<Context, Key> ? RuleDefs[Key] : never);
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Change the implementation of an existing generator rule.
|
|
21
|
+
*/
|
|
22
|
+
patchRule<U extends Names, RET, ARGS>(patch: GeneratorRule<Context, U, RET, ARGS>): GeneratorBuilder<Context, Names, {
|
|
23
|
+
[Key in Names]: Key extends U ? GeneratorRule<Context, Key, RET, ARGS> : (RuleDefs[Key] extends GeneratorRule<Context, Key> ? RuleDefs[Key] : never);
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Add a rule to the grammar. If the rule already exists, but the implementation differs, an error will be thrown.
|
|
27
|
+
*/
|
|
28
|
+
addRuleRedundant<U extends string, RET, ARGS>(rule: GeneratorRule<Context, U, RET, ARGS>): GeneratorBuilder<Context, Names | U, {
|
|
29
|
+
[K in Names | U]: K extends Names ? (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never) : (K extends U ? GeneratorRule<Context, K, RET, ARGS> : never);
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Add a rule to the grammar. Will raise a typescript error if the rule already exists in the grammar.
|
|
33
|
+
*/
|
|
34
|
+
addRule<U extends string, RET, ARGS>(rule: CheckOverlap<U, Names, GeneratorRule<Context, U, RET, ARGS>>): GeneratorBuilder<Context, Names | U, {
|
|
35
|
+
[K in Names | U]: K extends Names ? (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never) : (K extends U ? GeneratorRule<Context, K, RET, ARGS> : never);
|
|
36
|
+
}>;
|
|
37
|
+
addMany<U extends readonly GeneratorRule<Context>[]>(...rules: CheckOverlap<GenNamesFromList<U>, Names, U>): GeneratorBuilder<Context, Names | GenNamesFromList<U>, {
|
|
38
|
+
[K in Names | GenNamesFromList<U>]: K extends keyof GenRulesToObject<typeof rules> ? (GenRulesToObject<typeof rules>[K] extends GeneratorRule<Context, K> ? GenRulesToObject<typeof rules>[K] : never) : (K extends Names ? (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never) : never);
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Delete a grammar rule by its name.
|
|
42
|
+
*/
|
|
43
|
+
deleteRule<U extends Names>(ruleName: U): GeneratorBuilder<Context, Exclude<Names, U>, {
|
|
44
|
+
[K in Exclude<Names, U>]: RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Merge this grammar GeneratorBuilder with another.
|
|
48
|
+
* It is best to merge the bigger grammar with the smaller one.
|
|
49
|
+
* If the two builders both have a grammar rule with the same name,
|
|
50
|
+
* no error will be thrown case they map to the same ruledef object.
|
|
51
|
+
* If they map to a different object, an error will be thrown.
|
|
52
|
+
* To fix this problem, the overridingRules array should contain a rule with the same conflicting name,
|
|
53
|
+
* this rule implementation will be used.
|
|
54
|
+
*/
|
|
55
|
+
merge<OtherNames extends string, OtherRules extends GenRuleMap<OtherNames>, OW extends readonly GeneratorRule<Context>[]>(GeneratorBuilder: GeneratorBuilder<Context, OtherNames, OtherRules>, overridingRules: OW): GeneratorBuilder<Context, Names | OtherNames | GenNamesFromList<OW>, {
|
|
56
|
+
[K in Names | OtherNames | GenNamesFromList<OW>]: K extends keyof GenRulesToObject<OW> ? (GenRulesToObject<OW>[K] extends GeneratorRule<Context, K> ? GenRulesToObject<OW>[K] : never) : (K extends Names ? (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never) : K extends OtherNames ? (OtherRules[K] extends GeneratorRule<Context, K> ? OtherRules[K] : never) : never);
|
|
57
|
+
}>;
|
|
58
|
+
build(): GeneratorFromRules<Context, Names, RuleDefs>;
|
|
59
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { DynamicGenerator } from './dynamicGenerator';
|
|
2
|
+
/**
|
|
3
|
+
* Converts a list of ruledefs to a record mapping a name to the corresponding ruledef.
|
|
4
|
+
*/
|
|
5
|
+
function listToRuleDefMap(rules) {
|
|
6
|
+
const newRules = {};
|
|
7
|
+
for (const rule of rules) {
|
|
8
|
+
newRules[rule.name] = rule;
|
|
9
|
+
}
|
|
10
|
+
return newRules;
|
|
11
|
+
}
|
|
12
|
+
export class GeneratorBuilder {
|
|
13
|
+
static create(start) {
|
|
14
|
+
if (start instanceof GeneratorBuilder) {
|
|
15
|
+
return new GeneratorBuilder({ ...start.rules });
|
|
16
|
+
}
|
|
17
|
+
return new GeneratorBuilder(listToRuleDefMap(start));
|
|
18
|
+
}
|
|
19
|
+
constructor(startRules) {
|
|
20
|
+
this.rules = startRules;
|
|
21
|
+
}
|
|
22
|
+
widenContext() {
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
typePatch() {
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Change the implementation of an existing generator rule.
|
|
30
|
+
*/
|
|
31
|
+
patchRule(patch) {
|
|
32
|
+
const self = this;
|
|
33
|
+
self.rules[patch.name] = patch;
|
|
34
|
+
return self;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Add a rule to the grammar. If the rule already exists, but the implementation differs, an error will be thrown.
|
|
38
|
+
*/
|
|
39
|
+
addRuleRedundant(rule) {
|
|
40
|
+
const self = this;
|
|
41
|
+
const rules = self.rules;
|
|
42
|
+
if (rules[rule.name] !== undefined && rules[rule.name] !== rule) {
|
|
43
|
+
throw new Error(`Rule ${rule.name} already exists in the GeneratorBuilder`);
|
|
44
|
+
}
|
|
45
|
+
rules[rule.name] = rule;
|
|
46
|
+
return self;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Add a rule to the grammar. Will raise a typescript error if the rule already exists in the grammar.
|
|
50
|
+
*/
|
|
51
|
+
addRule(rule) {
|
|
52
|
+
return this.addRuleRedundant(rule);
|
|
53
|
+
}
|
|
54
|
+
addMany(...rules) {
|
|
55
|
+
this.rules = { ...this.rules, ...listToRuleDefMap(rules) };
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Delete a grammar rule by its name.
|
|
60
|
+
*/
|
|
61
|
+
deleteRule(ruleName) {
|
|
62
|
+
delete this.rules[ruleName];
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Merge this grammar GeneratorBuilder with another.
|
|
67
|
+
* It is best to merge the bigger grammar with the smaller one.
|
|
68
|
+
* If the two builders both have a grammar rule with the same name,
|
|
69
|
+
* no error will be thrown case they map to the same ruledef object.
|
|
70
|
+
* If they map to a different object, an error will be thrown.
|
|
71
|
+
* To fix this problem, the overridingRules array should contain a rule with the same conflicting name,
|
|
72
|
+
* this rule implementation will be used.
|
|
73
|
+
*/
|
|
74
|
+
merge(GeneratorBuilder, overridingRules) {
|
|
75
|
+
// Assume the other grammar is bigger than yours. So start from that one and add this one
|
|
76
|
+
const otherRules = { ...GeneratorBuilder.rules };
|
|
77
|
+
const myRules = this.rules;
|
|
78
|
+
for (const rule of Object.values(myRules)) {
|
|
79
|
+
if (otherRules[rule.name] === undefined) {
|
|
80
|
+
otherRules[rule.name] = rule;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
const existingRule = otherRules[rule.name];
|
|
84
|
+
// If same rule, no issue, move on. Else
|
|
85
|
+
if (existingRule !== rule) {
|
|
86
|
+
const override = overridingRules.find(x => x.name === rule.name);
|
|
87
|
+
// If override specified, take override, else, inform user that there is a conflict
|
|
88
|
+
if (override) {
|
|
89
|
+
otherRules[rule.name] = override;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
throw new Error(`Rule with name "${rule.name}" already exists in the GeneratorBuilder, specify an override to resolve conflict`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
this.rules = otherRules;
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
build() {
|
|
101
|
+
return new DynamicGenerator(this.rules);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=generatorBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generatorBuilder.js","sourceRoot":"","sources":["generatorBuilder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CheckOverlap } from '../utils';\nimport type { GeneratorFromRules, GenRuleMap, GenRulesToObject, GenNamesFromList } from './builderTypes';\nimport { DynamicGenerator } from './dynamicGenerator';\nimport type { GeneratorRule } from './generatorTypes';\n\n/**\n * Converts a list of ruledefs to a record mapping a name to the corresponding ruledef.\n */\nfunction listToRuleDefMap<T extends readonly GeneratorRule[]>(rules: T): GenRulesToObject<T> {\n const newRules: Record<string, GeneratorRule> = {};\n for (const rule of rules) {\n newRules[rule.name] = rule;\n }\n return <GenRulesToObject<T>>newRules;\n}\n\nexport class GeneratorBuilder<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> {\n /**\n * Create a GeneratorBuilder from some initial grammar rules or an existing GeneratorBuilder.\n * If a GeneratorBuilder is provided, a new copy will be created.\n */\n public static create<Context, Names extends string, RuleDefs extends GenRuleMap<Names>>(\n args: GeneratorBuilder<Context, Names, RuleDefs>\n ): GeneratorBuilder<Context, Names, RuleDefs>;\n public static create<\n Rules extends readonly GeneratorRule[] = readonly GeneratorRule[],\n Context = Rules[0] extends GeneratorRule<infer context> ? context : never,\n Names extends string = GenNamesFromList<Rules>,\n RuleDefs extends GenRuleMap<Names> = GenRulesToObject<Rules>,\n >(rules: Rules): GeneratorBuilder<Context, Names, RuleDefs>;\n public static create<\n Rules extends readonly GeneratorRule[] = readonly GeneratorRule[],\n Context = Rules[0] extends GeneratorRule<infer context> ? context : never,\n Names extends string = GenNamesFromList<Rules>,\n RuleDefs extends GenRuleMap<Names> = GenRulesToObject<Rules>,\n >(\n start: Rules | GeneratorBuilder<Context, Names, RuleDefs>,\n ): GeneratorBuilder<Context, Names, RuleDefs> {\n if (start instanceof GeneratorBuilder) {\n return new GeneratorBuilder({ ...start.rules });\n }\n return <GeneratorBuilder<Context, Names, RuleDefs>> <unknown> new GeneratorBuilder(listToRuleDefMap(start));\n }\n\n private rules: RuleDefs;\n\n private constructor(startRules: RuleDefs) {\n this.rules = startRules;\n }\n\n public widenContext<NewContext extends Context>(): GeneratorBuilder<NewContext, Names, RuleDefs> {\n return <GeneratorBuilder<NewContext, Names, RuleDefs>> <unknown> this;\n }\n\n public typePatch<Patch extends {[Key in Names]?: any }>():\n GeneratorBuilder<Context, Names, {[Key in Names]: Key extends keyof Patch ? (\n RuleDefs[Key] extends GeneratorRule<Context, Key, any, infer Args> ?\n GeneratorRule<Context, Key, Patch[Key], Args> : never\n ) : (RuleDefs[Key] extends GeneratorRule<Context, Key> ? RuleDefs[Key] : never) }> {\n return <GeneratorBuilder<Context, Names, {[Key in Names]: Key extends keyof Patch ? (\n RuleDefs[Key] extends GeneratorRule<Context, Key, any, infer Args> ?\n GeneratorRule<Context, Key, Patch[Key], Args> : never\n ) : (RuleDefs[Key] extends GeneratorRule<Context, Key> ? RuleDefs[Key] : never) }>> <unknown> this;\n }\n\n /**\n * Change the implementation of an existing generator rule.\n */\n public patchRule<U extends Names, RET, ARGS>(patch: GeneratorRule<Context, U, RET, ARGS>):\n GeneratorBuilder<Context, Names, {[Key in Names]: Key extends U ?\n GeneratorRule<Context, Key, RET, ARGS> :\n (RuleDefs[Key] extends GeneratorRule<Context, Key> ? RuleDefs[Key] : never)\n } > {\n const self = <GeneratorBuilder<Context, Names, {[Key in Names]: Key extends U ?\n GeneratorRule<Context, Key, RET, ARGS> :\n (RuleDefs[Key] extends GeneratorRule<Context, Key> ? RuleDefs[Key] : never) }>>\n <unknown> this;\n self.rules[patch.name] = <any> patch;\n return self;\n }\n\n /**\n * Add a rule to the grammar. If the rule already exists, but the implementation differs, an error will be thrown.\n */\n public addRuleRedundant<U extends string, RET, ARGS>(rule: GeneratorRule<Context, U, RET, ARGS>):\n GeneratorBuilder<Context, Names | U, {[K in Names | U]: K extends Names ?\n (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never)\n : (K extends U ? GeneratorRule<Context, K, RET, ARGS> : never)\n }> {\n const self = <GeneratorBuilder<Context, Names | U, {[K in Names | U]: K extends Names ?\n (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never)\n : (K extends U ? GeneratorRule<Context, K, RET, ARGS> : never) }>>\n <unknown> this;\n const rules = <Record<string, GeneratorRule<Context>>> self.rules;\n if (rules[rule.name] !== undefined && rules[rule.name] !== rule) {\n throw new Error(`Rule ${rule.name} already exists in the GeneratorBuilder`);\n }\n rules[rule.name] = rule;\n return self;\n }\n\n /**\n * Add a rule to the grammar. Will raise a typescript error if the rule already exists in the grammar.\n */\n public addRule<U extends string, RET, ARGS>(\n rule: CheckOverlap<U, Names, GeneratorRule<Context, U, RET, ARGS>>,\n ): GeneratorBuilder<Context, Names | U, {[K in Names | U]: K extends Names ?\n (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never)\n : (K extends U ? GeneratorRule<Context, K, RET, ARGS> : never)\n }> {\n return this.addRuleRedundant(rule);\n }\n\n public addMany<U extends readonly GeneratorRule<Context>[]>(\n ...rules: CheckOverlap<GenNamesFromList<U>, Names, U>\n ): GeneratorBuilder<\n Context,\n Names | GenNamesFromList<U>,\n {[K in Names | GenNamesFromList<U>]:\n K extends keyof GenRulesToObject<typeof rules> ? (\n GenRulesToObject<typeof rules>[K] extends GeneratorRule<Context, K> ? GenRulesToObject<typeof rules>[K] : never\n ) : (\n K extends Names ? (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never) : never\n )\n }\n > {\n this.rules = { ...this.rules, ...listToRuleDefMap(rules) };\n return <any> <unknown> this;\n }\n\n /**\n * Delete a grammar rule by its name.\n */\n public deleteRule<U extends Names>(ruleName: U):\n GeneratorBuilder<Context, Exclude<Names, U>, {[K in Exclude<Names, U>]:\n RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never }> {\n delete this.rules[ruleName];\n return <GeneratorBuilder<Context, Exclude<Names, U>, {[K in Exclude<Names, U>]:\n RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never }>>\n <unknown> this;\n }\n\n /**\n * Merge this grammar GeneratorBuilder with another.\n * It is best to merge the bigger grammar with the smaller one.\n * If the two builders both have a grammar rule with the same name,\n * no error will be thrown case they map to the same ruledef object.\n * If they map to a different object, an error will be thrown.\n * To fix this problem, the overridingRules array should contain a rule with the same conflicting name,\n * this rule implementation will be used.\n */\n public merge<\n OtherNames extends string,\n OtherRules extends GenRuleMap<OtherNames>,\n OW extends readonly GeneratorRule<Context>[],\n >(\n GeneratorBuilder: GeneratorBuilder<Context, OtherNames, OtherRules>,\n overridingRules: OW,\n ):\n GeneratorBuilder<\n Context,\n Names | OtherNames | GenNamesFromList<OW>,\n {[K in Names | OtherNames | GenNamesFromList<OW>]:\n K extends keyof GenRulesToObject<OW> ? (\n GenRulesToObject<OW>[K] extends GeneratorRule<Context, K> ? GenRulesToObject<OW>[K] : never\n )\n : (\n K extends Names ? (RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never)\n : K extends OtherNames ? (OtherRules[K] extends GeneratorRule<Context, K> ? OtherRules[K] : never)\n : never\n ) }\n > {\n // Assume the other grammar is bigger than yours. So start from that one and add this one\n const otherRules: Record<string, GeneratorRule<Context>> = { ...GeneratorBuilder.rules };\n const myRules: Record<string, GeneratorRule<Context>> = this.rules;\n\n for (const rule of Object.values(myRules)) {\n if (otherRules[rule.name] === undefined) {\n otherRules[rule.name] = rule;\n } else {\n const existingRule = otherRules[rule.name];\n // If same rule, no issue, move on. Else\n if (existingRule !== rule) {\n const override = overridingRules.find(x => x.name === rule.name);\n // If override specified, take override, else, inform user that there is a conflict\n if (override) {\n otherRules[rule.name] = override;\n } else {\n throw new Error(`Rule with name \"${rule.name}\" already exists in the GeneratorBuilder, specify an override to resolve conflict`);\n }\n }\n }\n }\n\n this.rules = <any> <unknown> otherRules;\n return <any> <unknown> this;\n }\n\n public build(): GeneratorFromRules<Context, Names, RuleDefs> {\n return <GeneratorFromRules<Context, Names, RuleDefs>> new DynamicGenerator(this.rules);\n }\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Localized } from '../nodeTypings';
|
|
2
|
+
/**
|
|
3
|
+
* Type used to declare generator rules.
|
|
4
|
+
*/
|
|
5
|
+
export type GeneratorRule<
|
|
6
|
+
/**
|
|
7
|
+
* Context object available in rule implementation.
|
|
8
|
+
*/
|
|
9
|
+
Context = any,
|
|
10
|
+
/**
|
|
11
|
+
* Name of grammar rule, should be a strict subtype of string like 'myGrammarRule'.
|
|
12
|
+
*/
|
|
13
|
+
NameType extends string = string,
|
|
14
|
+
/**
|
|
15
|
+
* Type that of the AST that we will generate the string for.
|
|
16
|
+
* This type will be the provided when calling SUBRULE with this generator rule.
|
|
17
|
+
* Generation happens on a per AST node basis.
|
|
18
|
+
* The core will implement the generation as such. If this ever changes, we will cross that bridge when we get there.
|
|
19
|
+
*/
|
|
20
|
+
ReturnType = any,
|
|
21
|
+
/**
|
|
22
|
+
* Function arguments that can be given to convey the state of the current parse operation.
|
|
23
|
+
*/
|
|
24
|
+
ParamType = any> = {
|
|
25
|
+
name: NameType;
|
|
26
|
+
gImpl: (def: RuleDefArg) => (ast: ReturnType, context: Context, params: ParamType) => void;
|
|
27
|
+
};
|
|
28
|
+
export interface RuleDefArg {
|
|
29
|
+
SUBRULE: <T, U>(cstDef: GeneratorRule<any, any, T, U>, input: T, arg: U) => void;
|
|
30
|
+
PRINT: (...args: string[]) => void;
|
|
31
|
+
PRINT_SPACE_LEFT: (...args: string[]) => void;
|
|
32
|
+
PRINT_WORD: (...args: string[]) => void;
|
|
33
|
+
PRINT_WORDS: (...args: string[]) => void;
|
|
34
|
+
HANDLE_LOC: <T>(loc: Localized, nodeHandle: () => T) => T | undefined;
|
|
35
|
+
CATCHUP: (until: number) => void;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generatorTypes.js","sourceRoot":"","sources":["generatorTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { Localized } from '../nodeTypings';\n\n/**\n * Type used to declare generator rules.\n */\nexport type GeneratorRule<\n /**\n * Context object available in rule implementation.\n */\n Context = any,\n /**\n * Name of grammar rule, should be a strict subtype of string like 'myGrammarRule'.\n */\n NameType extends string = string,\n /**\n * Type that of the AST that we will generate the string for.\n * This type will be the provided when calling SUBRULE with this generator rule.\n * Generation happens on a per AST node basis.\n * The core will implement the generation as such. If this ever changes, we will cross that bridge when we get there.\n */\n ReturnType = any,\n /**\n * Function arguments that can be given to convey the state of the current parse operation.\n */\n ParamType = any,\n> = {\n name: NameType;\n gImpl: (def: RuleDefArg) =>\n (ast: ReturnType, context: Context, params: ParamType) => void;\n};\n\nexport interface RuleDefArg {\n SUBRULE: <T, U>(cstDef: GeneratorRule<any, any, T, U>, input: T, arg: U) => void;\n PRINT: (...args: string[]) => void;\n PRINT_SPACE_LEFT: (...args: string[]) => void;\n PRINT_WORD: (...args: string[]) => void;\n PRINT_WORDS: (...args: string[]) => void;\n HANDLE_LOC: <T>(loc: Localized, nodeHandle: () => T) => T | undefined;\n CATCHUP: (until: number) => void;\n}\n"]}
|