@traqula/core 0.0.1-alpha.148 → 0.0.1-alpha.176
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/generator-builder/builderTypes.d.ts +20 -0
- package/lib/generator-builder/builderTypes.js.map +1 -0
- package/lib/generator-builder/dynamicGenerator.d.ts +7 -0
- package/lib/generator-builder/dynamicGenerator.js +28 -0
- package/lib/generator-builder/dynamicGenerator.js.map +1 -0
- package/lib/generator-builder/generatorBuilder.d.ts +58 -0
- package/lib/generator-builder/generatorBuilder.js +101 -0
- package/lib/generator-builder/generatorBuilder.js.map +1 -0
- package/lib/generator-builder/generatorTypes.d.ts +27 -0
- package/lib/generator-builder/generatorTypes.js +2 -0
- package/lib/generator-builder/generatorTypes.js.map +1 -0
- package/lib/index.cjs +379 -320
- package/lib/index.d.ts +7 -6
- package/lib/index.js +11 -6
- package/lib/index.js.map +1 -1
- package/lib/lexer-builder/LexerBuilder.d.ts +7 -9
- package/lib/lexer-builder/LexerBuilder.js +12 -4
- package/lib/lexer-builder/LexerBuilder.js.map +1 -1
- 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 +73 -0
- package/lib/parser-builder/parserBuilder.js +161 -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
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Traqula core package
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
**WARNING:** V2 will come shortly and will have lots of breaking changes.
|
|
4
|
+
|
|
5
|
+
Traqula core contains core components of Traqula.
|
|
6
|
+
Most importantly, its [lexer builder](./lib/lexer-builder/LexerBuilder.ts), [parser builder](./lib/parser-builder/parserBuilder.ts), and [generator builder](./lib/generator-builder/generatorBuilder.ts).
|
|
7
|
+
This library heavily relies on the amazing [Chevrotain package](https://chevrotain.io/docs/).
|
|
8
|
+
Knowing the basics of that package will allow you to quickly generate your own grammars.
|
|
7
9
|
|
|
8
10
|
## Installation
|
|
9
11
|
|
|
@@ -19,12 +21,12 @@ yarn add @traqula/core
|
|
|
19
21
|
|
|
20
22
|
## Usage
|
|
21
23
|
|
|
22
|
-
Each parser contains two steps:
|
|
24
|
+
Each parser contains two steps:
|
|
23
25
|
1. a lexer
|
|
24
26
|
2. a grammar + abstract syntax tree generation step.
|
|
25
27
|
|
|
26
|
-
Sometimes grammar definitions and abstract syntax tree generation is split into separate steps.
|
|
27
|
-
In this library, we choose to keep the two together.
|
|
28
|
+
Sometimes grammar definitions and abstract syntax tree generation is split into separate steps.
|
|
29
|
+
In this library, we choose to keep the two together when building a parser.
|
|
28
30
|
|
|
29
31
|
### Lexer Builder
|
|
30
32
|
|
|
@@ -38,10 +40,10 @@ To create a token definition, you use the provided function `createToken` like:
|
|
|
38
40
|
const select = createToken({ name: 'Select', pattern: /select/i, label: 'SELECT' });
|
|
39
41
|
```
|
|
40
42
|
|
|
41
|
-
Lexer definitions are then put in a list and when a lexer is build, the lexer will match a string to the first token in the list that matches.
|
|
43
|
+
Lexer definitions are then put in a list and when a lexer is build, the lexer will match a string to the [**first token in the list**](https://chevrotain.io/docs/tutorial/step1_lexing.html#creating-the-lexer) that matches.
|
|
42
44
|
Note that the order of definitions in the list is thus essential.
|
|
43
45
|
|
|
44
|
-
We therefore use a
|
|
46
|
+
We therefore use a [lexer builder](./lib/lexer-builder/LexerBuilder.ts) which allows you to easily:
|
|
45
47
|
1. change the order of lexer rules,
|
|
46
48
|
2. and create a new lexer staring from an existing one.
|
|
47
49
|
|
|
@@ -56,11 +58,11 @@ A new lexer can be created from an existing one by calling:
|
|
|
56
58
|
const sparql11AdjustTokens = sparql11Tokens.addBefore(select, BuiltInAdjust);
|
|
57
59
|
```
|
|
58
60
|
|
|
59
|
-
###
|
|
61
|
+
### Parser Builder
|
|
60
62
|
|
|
61
63
|
The grammar builder is used to link together grammar rules such that they can be converted into a parser.
|
|
62
|
-
Grammar rule definitions come in the form of
|
|
63
|
-
Each `
|
|
64
|
+
Grammar rule definitions come in the form of [ParserRule](./lib/parser-builder/ruleDefTypes.ts) objects.
|
|
65
|
+
Each `ParserRule` object contains its name and its returnType.
|
|
64
66
|
Optionally, it can also contain arguments that should be provided to the SUBRULE calls.
|
|
65
67
|
A simple example of a grammar rule is the rule bellow that allows you to parse booleanLiterals.
|
|
66
68
|
|
|
@@ -69,7 +71,7 @@ A simple example of a grammar rule is the rule bellow that allows you to parse b
|
|
|
69
71
|
* Parses a boolean literal.
|
|
70
72
|
* [[134]](https://www.w3.org/TR/sparql11-query/#rBooleanLiteral)
|
|
71
73
|
*/
|
|
72
|
-
export const booleanLiteral:
|
|
74
|
+
export const booleanLiteral: ParserRule<'booleanLiteral', LiteralTerm> = <const> {
|
|
73
75
|
name: 'booleanLiteral',
|
|
74
76
|
impl: ({ CONSUME, OR, context }) => () => OR([
|
|
75
77
|
{ ALT: () => context.dataFactory.literal(
|
|
@@ -84,20 +86,19 @@ export const booleanLiteral: RuleDef<'booleanLiteral', LiteralTerm> = <const> {
|
|
|
84
86
|
};
|
|
85
87
|
```
|
|
86
88
|
|
|
87
|
-
The `impl` member of `
|
|
89
|
+
The `impl` member of `ParserRule` is a function that receives:
|
|
88
90
|
1. essential functions to create a grammar rule (capitalized members),
|
|
89
91
|
2. a context object that can be used by the rules,
|
|
90
|
-
3. a cache object ([WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)) that can be used to cache the creation of long lists in the parser.
|
|
92
|
+
3. a cache object ([WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)) that can be used to cache the creation of long lists in the parser, [increasing parser performance](https://chevrotain.io/docs/guide/performance.html#caching-arrays-of-alternatives).
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
Doing so will cause the unpacked entries to be captured in the closure which will cause unwanted behaviour since the context entry can be reset between runs.
|
|
94
|
+
You cannot unpack the context entry in the function definition itself because the parser uses a [recording phase](https://chevrotain.io/docs/guide/internals.html#grammar-recording) to optimize itself. During this phase, the context entry will be undefined, as such, it can only be accessed within the `ACTION` function.
|
|
94
95
|
|
|
95
96
|
The result of an `impl` call is a function called a `rule`.
|
|
96
97
|
Rules can be [parameterized](https://chevrotain.io/docs/features/parameterized_rules.html), although I have not found a scenario where that is usefully.
|
|
97
|
-
Personally I create a function that can be used to create multiple `
|
|
98
|
-
The result of a rule should match the type provided in the `
|
|
98
|
+
Personally I create a function that can be used to create multiple `ParserRule` objects.
|
|
99
|
+
The result of a rule should match the type provided in the `ParserRule` definition, and is the result of a call of `SUBRULE` with that rule.
|
|
99
100
|
|
|
100
|
-
|
|
101
|
+
#### Patching rules
|
|
101
102
|
|
|
102
103
|
When a rule definition calls to a subrule using `SUBRULE(mySub)`, the implementation itself is not necessarily called.
|
|
103
104
|
That is because the SUBRULE function will call the function with the same name as `mySub` that is present in the current grammarBuilder.
|
|
@@ -112,4 +113,25 @@ const myBuilder = Builder
|
|
|
112
113
|
```
|
|
113
114
|
|
|
114
115
|
When `selectOrDescribe` calls what it thinks to be `selectRule`,
|
|
115
|
-
it will instead call `selectRuleAlternative` since it overwrote the function `selectRule` with the same name.
|
|
116
|
+
it will instead call `selectRuleAlternative` since it overwrote the function `selectRule` with the same name.
|
|
117
|
+
|
|
118
|
+
### Generator Builder
|
|
119
|
+
|
|
120
|
+
The generator builder function in much the same as the [parser builder](#parser-builder).
|
|
121
|
+
Your builder expects objects of type [GeneratorRule](lib/generator-builder/generatorTypes.ts),
|
|
122
|
+
containing the implementation of the generator in the `gImpl` member.
|
|
123
|
+
The `gImpl` function gets essential functions to create a generator rule (capitalized members),
|
|
124
|
+
returning a function that will get the AST and context, returning a string.
|
|
125
|
+
For generator rules, you can unpack the context since no recording phase is present in this case.
|
|
126
|
+
The idea is that GeneratorRules and ParserRules can be tied together in the same object, as such, similar behaviour is grouped together.
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
/**
|
|
130
|
+
* Parses a named node, either as an IRI or as a prefixed name.
|
|
131
|
+
* [[136]](https://www.w3.org/TR/sparql11-query/#riri)
|
|
132
|
+
*/
|
|
133
|
+
export const iri: GeneratorRule<'iri', IriTerm> = <const> {
|
|
134
|
+
name: 'iri',
|
|
135
|
+
gImpl: () => ast => ast.value,
|
|
136
|
+
};
|
|
137
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { GeneratorRule } from './generatorTypes';
|
|
2
|
+
/**
|
|
3
|
+
* Get union-type of names used in list of ruledefs.
|
|
4
|
+
*/
|
|
5
|
+
export type GenNamesFromList<T extends readonly GeneratorRule[]> = T[number]['name'];
|
|
6
|
+
/**
|
|
7
|
+
* Convert a list of ruledefs to a record that maps each rule name to its definition.
|
|
8
|
+
*/
|
|
9
|
+
export type GenRuleMap<RuleNames extends string> = {
|
|
10
|
+
[Key in RuleNames]: GeneratorRule<any, Key>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Convert a list of RuleDefs to a Record with the name of the RuleDef as the key, matching the RuleDefMap type.
|
|
14
|
+
*/
|
|
15
|
+
export type GenRulesToObject<T extends readonly GeneratorRule[], Names extends string = GenNamesFromList<T>, Agg extends Record<string, GeneratorRule> = Record<never, never>> = T extends readonly [infer First, ...infer Rest] ? (First extends GeneratorRule ? (Rest extends readonly GeneratorRule[] ? (GenRulesToObject<Rest, Names, {
|
|
16
|
+
[K in keyof Agg | First['name']]: K extends First['name'] ? First : Agg[K];
|
|
17
|
+
}>) : never) : never) : GenRuleMap<Names> & Agg;
|
|
18
|
+
export type GeneratorFromRules<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> = {
|
|
19
|
+
[K in Names]: RuleDefs[K] extends GeneratorRule<Context, K, infer RET, infer ARGS> ? (input: RET, context: Context, args: ARGS) => string : never;
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builderTypes.js","sourceRoot":"","sources":["builderTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { GeneratorRule } from './generatorTypes';\n\n/**\n * Get union-type of names used in list of ruledefs.\n */\nexport type GenNamesFromList<T extends readonly GeneratorRule[]> = T[number]['name'];\n\n/**\n * Convert a list of ruledefs to a record that maps each rule name to its definition.\n */\nexport type GenRuleMap<RuleNames extends string> = {[Key in RuleNames]: GeneratorRule<any, Key> };\n\n/**\n * Convert a list of RuleDefs to a Record with the name of the RuleDef as the key, matching the RuleDefMap type.\n */\nexport type GenRulesToObject<\n T extends readonly GeneratorRule[],\n Names extends string = GenNamesFromList<T>,\n Agg extends Record<string, GeneratorRule> = Record<never, never>,\n> = T extends readonly [infer First, ...infer Rest] ? (\n First extends GeneratorRule ? (\n Rest extends readonly GeneratorRule[] ? (\n GenRulesToObject<Rest, Names, {[K in keyof Agg | First['name']]: K extends First['name'] ? First : Agg[K] }>\n ) : never\n ) : never\n) : GenRuleMap<Names> & Agg;\n\nexport type GeneratorFromRules<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> = {\n [K in Names]: RuleDefs[K] extends GeneratorRule<Context, K, infer RET, infer ARGS> ?\n (input: RET, context: Context, args: ARGS) => string : never\n};\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GenRuleMap } from './builderTypes';
|
|
2
|
+
export declare class DynamicGenerator<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> {
|
|
3
|
+
private __context;
|
|
4
|
+
setContext(context: Context): void;
|
|
5
|
+
private getSafeContext;
|
|
6
|
+
constructor(rules: RuleDefs);
|
|
7
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class DynamicGenerator {
|
|
2
|
+
setContext(context) {
|
|
3
|
+
this.__context = context;
|
|
4
|
+
}
|
|
5
|
+
getSafeContext() {
|
|
6
|
+
return this.__context;
|
|
7
|
+
}
|
|
8
|
+
constructor(rules) {
|
|
9
|
+
this.__context = undefined;
|
|
10
|
+
const selfRef = {
|
|
11
|
+
SUBRULE: (cstDef, input, arg) => {
|
|
12
|
+
const def = rules[cstDef.name];
|
|
13
|
+
if (!def) {
|
|
14
|
+
throw new Error(`Rule ${cstDef.name} not found`);
|
|
15
|
+
}
|
|
16
|
+
return def.gImpl(selfRef)(input, this.getSafeContext(), arg);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
// eslint-disable-next-line ts/no-unnecessary-type-assertion
|
|
20
|
+
for (const rule of Object.values(rules)) {
|
|
21
|
+
this[rule.name] = ((input, context, args) => {
|
|
22
|
+
this.setContext(context);
|
|
23
|
+
return rule.gImpl(selfRef)(input, this.getSafeContext(), args);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=dynamicGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamicGenerator.js","sourceRoot":"","sources":["dynamicGenerator.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,gBAAgB;IAGpB,UAAU,CAAC,OAAgB;QAChC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC;IAC3B,CAAC;IAEO,cAAc;QACpB,OAAiB,IAAI,CAAC,SAAS,CAAC;IAClC,CAAC;IAED,YAAmB,KAAe;QAV1B,cAAS,GAAwB,SAAS,CAAC;QAWjD,MAAM,OAAO,GAAe;YAC1B,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC9B,MAAM,GAAG,GAAG,KAAK,CAAQ,MAAM,CAAC,IAAI,CAAC,CAAC;gBACtC,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,MAAM,IAAI,KAAK,CAAC,QAAQ,MAAM,CAAC,IAAI,YAAY,CAAC,CAAC;gBACnD,CAAC;gBACD,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,GAAG,CAAC,CAAC;YAC/D,CAAC;SACF,CAAC;QAEF,4DAA4D;QAC5D,KAAK,MAAM,IAAI,IAAqB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,IAAI,CAAsB,IAAI,CAAC,IAAI,CAAC,GAAQ,CAAC,CAAC,KAAU,EAAE,OAAgB,EAAE,IAAS,EAAE,EAAE;gBACvF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;gBACzB,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF","sourcesContent":["import type { GenRuleMap } from './builderTypes';\nimport type { GeneratorRule, RuleDefArg } from './generatorTypes';\n\nexport class DynamicGenerator<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> {\n private __context: Context | undefined = undefined;\n\n public setContext(context: Context): void {\n this.__context = context;\n }\n\n private getSafeContext(): Context {\n return <Context> this.__context;\n }\n\n public constructor(rules: RuleDefs) {\n const selfRef: RuleDefArg = {\n SUBRULE: (cstDef, input, arg) => {\n const def = rules[<Names>cstDef.name];\n if (!def) {\n throw new Error(`Rule ${cstDef.name} not found`);\n }\n return def.gImpl(selfRef)(input, this.getSafeContext(), arg);\n },\n };\n\n // eslint-disable-next-line ts/no-unnecessary-type-assertion\n for (const rule of <GeneratorRule[]>Object.values(rules)) {\n this[<keyof (typeof this)>rule.name] = <any>((input: any, context: Context, args: any) => {\n this.setContext(context);\n return rule.gImpl(selfRef)(input, this.getSafeContext(), args);\n });\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { CheckOverlap } from '../utils';
|
|
2
|
+
import type { GeneratorFromRules, GenNamesFromList, GenRuleMap, GenRulesToObject } 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 createBuilder<Context, Names extends string, RuleDefs extends GenRuleMap<Names>>(args: GeneratorBuilder<Context, Names, RuleDefs>): GeneratorBuilder<Context, Names, RuleDefs>;
|
|
10
|
+
static createBuilder<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
|
+
typePatch<Patch extends {
|
|
14
|
+
[Key in Names]?: any;
|
|
15
|
+
}>(): GeneratorBuilder<Context, Names, {
|
|
16
|
+
[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);
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Change the implementation of an existing generator rule.
|
|
20
|
+
*/
|
|
21
|
+
patchRule<U extends Names, RET, ARGS>(patch: GeneratorRule<Context, U, RET, ARGS>): GeneratorBuilder<Context, Names, {
|
|
22
|
+
[Key in Names]: Key extends U ? GeneratorRule<Context, Key, RET, ARGS> : (RuleDefs[Key] extends GeneratorRule<Context, Key> ? RuleDefs[Key] : never);
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Add a rule to the grammar. If the rule already exists, but the implementation differs, an error will be thrown.
|
|
26
|
+
*/
|
|
27
|
+
addRuleRedundant<U extends string, RET, ARGS>(rule: GeneratorRule<Context, U, RET, ARGS>): GeneratorBuilder<Context, Names | U, {
|
|
28
|
+
[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);
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Add a rule to the grammar. Will raise a typescript error if the rule already exists in the grammar.
|
|
32
|
+
*/
|
|
33
|
+
addRule<U extends string, RET, ARGS>(rule: CheckOverlap<U, Names, GeneratorRule<Context, U, RET, ARGS>>): GeneratorBuilder<Context, Names | U, {
|
|
34
|
+
[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);
|
|
35
|
+
}>;
|
|
36
|
+
addMany<U extends readonly GeneratorRule<Context>[]>(...rules: CheckOverlap<GenNamesFromList<U>, Names, U>): GeneratorBuilder<Context, Names | GenNamesFromList<U>, {
|
|
37
|
+
[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);
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Delete a grammar rule by its name.
|
|
41
|
+
*/
|
|
42
|
+
deleteRule<U extends Names>(ruleName: U): GeneratorBuilder<Context, Exclude<Names, U>, {
|
|
43
|
+
[K in Exclude<Names, U>]: RuleDefs[K] extends GeneratorRule<Context, K> ? RuleDefs[K] : never;
|
|
44
|
+
}>;
|
|
45
|
+
/**
|
|
46
|
+
* Merge this grammar GeneratorBuilder with another.
|
|
47
|
+
* It is best to merge the bigger grammar with the smaller one.
|
|
48
|
+
* If the two builders both have a grammar rule with the same name,
|
|
49
|
+
* no error will be thrown case they map to the same ruledef object.
|
|
50
|
+
* If they map to a different object, an error will be thrown.
|
|
51
|
+
* To fix this problem, the overridingRules array should contain a rule with the same conflicting name,
|
|
52
|
+
* this rule implementation will be used.
|
|
53
|
+
*/
|
|
54
|
+
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>, {
|
|
55
|
+
[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);
|
|
56
|
+
}>;
|
|
57
|
+
build(): GeneratorFromRules<Context, Names, RuleDefs>;
|
|
58
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
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 createBuilder(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
|
+
typePatch() {
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Change the implementation of an existing generator rule.
|
|
27
|
+
*/
|
|
28
|
+
patchRule(patch) {
|
|
29
|
+
const self = this;
|
|
30
|
+
self.rules[patch.name] = patch;
|
|
31
|
+
return self;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Add a rule to the grammar. If the rule already exists, but the implementation differs, an error will be thrown.
|
|
35
|
+
*/
|
|
36
|
+
addRuleRedundant(rule) {
|
|
37
|
+
const self = this;
|
|
38
|
+
const rules = self.rules;
|
|
39
|
+
if (rules[rule.name] !== undefined && rules[rule.name] !== rule) {
|
|
40
|
+
throw new Error(`Rule ${rule.name} already exists in the GeneratorBuilder`);
|
|
41
|
+
}
|
|
42
|
+
rules[rule.name] = rule;
|
|
43
|
+
return self;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Add a rule to the grammar. Will raise a typescript error if the rule already exists in the grammar.
|
|
47
|
+
*/
|
|
48
|
+
addRule(rule) {
|
|
49
|
+
return this.addRuleRedundant(rule);
|
|
50
|
+
}
|
|
51
|
+
addMany(...rules) {
|
|
52
|
+
this.rules = { ...this.rules, ...listToRuleDefMap(rules) };
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Delete a grammar rule by its name.
|
|
57
|
+
*/
|
|
58
|
+
deleteRule(ruleName) {
|
|
59
|
+
delete this.rules[ruleName];
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Merge this grammar GeneratorBuilder with another.
|
|
64
|
+
* It is best to merge the bigger grammar with the smaller one.
|
|
65
|
+
* If the two builders both have a grammar rule with the same name,
|
|
66
|
+
* no error will be thrown case they map to the same ruledef object.
|
|
67
|
+
* If they map to a different object, an error will be thrown.
|
|
68
|
+
* To fix this problem, the overridingRules array should contain a rule with the same conflicting name,
|
|
69
|
+
* this rule implementation will be used.
|
|
70
|
+
*/
|
|
71
|
+
merge(GeneratorBuilder, overridingRules) {
|
|
72
|
+
// Assume the other grammar is bigger than yours. So start from that one and add this one
|
|
73
|
+
const otherRules = { ...GeneratorBuilder.rules };
|
|
74
|
+
const myRules = this.rules;
|
|
75
|
+
for (const rule of Object.values(myRules)) {
|
|
76
|
+
if (otherRules[rule.name] === undefined) {
|
|
77
|
+
otherRules[rule.name] = rule;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const existingRule = otherRules[rule.name];
|
|
81
|
+
// If same rule, no issue, move on. Else
|
|
82
|
+
if (existingRule !== rule) {
|
|
83
|
+
const override = overridingRules.find(x => x.name === rule.name);
|
|
84
|
+
// If override specified, take override, else, inform user that there is a conflict
|
|
85
|
+
if (override) {
|
|
86
|
+
otherRules[rule.name] = override;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
throw new Error(`Rule with name "${rule.name}" already exists in the GeneratorBuilder, specify an override to resolve conflict`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
this.rules = otherRules;
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
build() {
|
|
98
|
+
return new DynamicGenerator(this.rules);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# 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, GenNamesFromList, GenRuleMap, GenRulesToObject } 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 createBuilder<Context, Names extends string, RuleDefs extends GenRuleMap<Names>>(\n args: GeneratorBuilder<Context, Names, RuleDefs>\n ): GeneratorBuilder<Context, Names, RuleDefs>;\n public static createBuilder<\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 createBuilder<\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 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,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type used to declare generator rules.
|
|
3
|
+
*/
|
|
4
|
+
export type GeneratorRule<
|
|
5
|
+
/**
|
|
6
|
+
* Context object available in rule implementation.
|
|
7
|
+
*/
|
|
8
|
+
Context = any,
|
|
9
|
+
/**
|
|
10
|
+
* Name of grammar rule, should be a strict subtype of string like 'myGrammarRule'.
|
|
11
|
+
*/
|
|
12
|
+
NameType extends string = string,
|
|
13
|
+
/**
|
|
14
|
+
* Type that will be returned after a correct parse of this rule.
|
|
15
|
+
* This type will be the return type of calling SUBRULE with this grammar rule.
|
|
16
|
+
*/
|
|
17
|
+
ReturnType = any,
|
|
18
|
+
/**
|
|
19
|
+
* Function arguments that can be given to convey the state of the current parse operation.
|
|
20
|
+
*/
|
|
21
|
+
ParamType = any> = {
|
|
22
|
+
name: NameType;
|
|
23
|
+
gImpl: (def: RuleDefArg) => (ast: ReturnType, context: Context, params: ParamType) => string;
|
|
24
|
+
};
|
|
25
|
+
export interface RuleDefArg {
|
|
26
|
+
SUBRULE: <T, U>(cstDef: GeneratorRule<any, any, T, U>, input: T, arg: U) => string;
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generatorTypes.js","sourceRoot":"","sources":["generatorTypes.ts"],"names":[],"mappings":"","sourcesContent":["/**\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 will be returned after a correct parse of this rule.\n * This type will be the return type of calling SUBRULE with this grammar rule.\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) => string;\n};\n\nexport interface RuleDefArg {\n SUBRULE: <T, U>(cstDef: GeneratorRule<any, any, T, U>, input: T, arg: U) => string;\n}\n"]}
|