@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
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,39 @@
|
|
|
1
|
+
import type { IToken } from 'chevrotain';
|
|
2
|
+
import type { SourceLocation, SourceLocationNodeAutoGenerate, SourceLocationNodeReplace, SourceLocationNoMaterialize, SourceLocationSource, SourceLocationStringReplace, Node, Localized, Wrap } from './nodeTypings';
|
|
3
|
+
export type Typed<Type extends PropertyKey> = {
|
|
4
|
+
type: Type;
|
|
5
|
+
};
|
|
6
|
+
export type SubTyped<Type extends PropertyKey, Subtype extends PropertyKey> = {
|
|
7
|
+
type: Type;
|
|
8
|
+
subType: Subtype;
|
|
9
|
+
};
|
|
10
|
+
export declare class CoreFactory {
|
|
11
|
+
wrap<T>(val: T, loc: SourceLocation): Wrap<T>;
|
|
12
|
+
isLocalized(obj: unknown): obj is Localized;
|
|
13
|
+
sourceLocation(...elements: (undefined | IToken | Localized)[]): SourceLocation;
|
|
14
|
+
sourceLocationNoMaterialize(): SourceLocationNoMaterialize;
|
|
15
|
+
/**
|
|
16
|
+
* Returns a copy of the argument that is not materialized
|
|
17
|
+
*/
|
|
18
|
+
dematerialized<T extends Node>(arg: T): T & {
|
|
19
|
+
loc: SourceLocationNoMaterialize;
|
|
20
|
+
};
|
|
21
|
+
safeObjectTransform(value: unknown, mapper: (some: object) => any): any;
|
|
22
|
+
forcedAutoGenTree<T extends object>(obj: T): T;
|
|
23
|
+
forceMaterialized<T extends Node>(arg: T): T;
|
|
24
|
+
isSourceLocation(loc: object): loc is SourceLocation;
|
|
25
|
+
sourceLocationSource(start: number, end: number): SourceLocationSource;
|
|
26
|
+
gen(): SourceLocationNodeAutoGenerate;
|
|
27
|
+
isSourceLocationSource(loc: object): loc is SourceLocationSource;
|
|
28
|
+
isSourceLocationStringReplace(loc: object): loc is SourceLocationStringReplace;
|
|
29
|
+
sourceLocationNodeReplaceUnsafe(loc: SourceLocation): SourceLocationNodeReplace;
|
|
30
|
+
sourceLocationNodeReplace(location: SourceLocationSource): SourceLocationNodeReplace;
|
|
31
|
+
sourceLocationNodeReplace(start: number, end: number): SourceLocationNodeReplace;
|
|
32
|
+
isSourceLocationNodeReplace(loc: object): loc is SourceLocationNodeReplace;
|
|
33
|
+
isSourceLocationNodeAutoGenerate(loc: object): loc is SourceLocationNodeAutoGenerate;
|
|
34
|
+
nodeShouldPrint(node: Localized): boolean;
|
|
35
|
+
printFilter(node: Localized, callback: () => void): void;
|
|
36
|
+
isSourceLocationNoMaterialize(loc: object): loc is SourceLocationNoMaterialize;
|
|
37
|
+
isOfType<Type extends string>(obj: object, type: Type): obj is Typed<Type>;
|
|
38
|
+
isOfSubType<Type extends string, SubType extends string>(obj: object, type: Type, subType: SubType): obj is SubTyped<Type, SubType>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
export class CoreFactory {
|
|
2
|
+
wrap(val, loc) {
|
|
3
|
+
return { val, loc };
|
|
4
|
+
}
|
|
5
|
+
isLocalized(obj) {
|
|
6
|
+
return typeof obj === 'object' && obj !== null && 'loc' in obj &&
|
|
7
|
+
typeof obj.loc === 'object' && obj.loc !== null && 'sourceLocationType' in obj.loc;
|
|
8
|
+
}
|
|
9
|
+
sourceLocation(...elements) {
|
|
10
|
+
const pureElements = elements.filter(x => x !== undefined);
|
|
11
|
+
if (pureElements.length === 0) {
|
|
12
|
+
return this.sourceLocationNoMaterialize();
|
|
13
|
+
}
|
|
14
|
+
const filtered = pureElements.filter(element => !this.isLocalized(element) || this.isSourceLocationSource(element.loc) ||
|
|
15
|
+
this.isSourceLocationStringReplace(element.loc) || this.isSourceLocationNodeReplace(element.loc));
|
|
16
|
+
if (filtered.length === 0) {
|
|
17
|
+
return this.gen();
|
|
18
|
+
}
|
|
19
|
+
const first = filtered[0];
|
|
20
|
+
const last = filtered.at(-1);
|
|
21
|
+
return {
|
|
22
|
+
sourceLocationType: 'source',
|
|
23
|
+
start: this.isLocalized(first) ?
|
|
24
|
+
first.loc.start :
|
|
25
|
+
first.startOffset,
|
|
26
|
+
end: this.isLocalized(last) ?
|
|
27
|
+
last.loc.end :
|
|
28
|
+
(last.endOffset + 1),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
sourceLocationNoMaterialize() {
|
|
32
|
+
return { sourceLocationType: 'noMaterialize' };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns a copy of the argument that is not materialized
|
|
36
|
+
*/
|
|
37
|
+
dematerialized(arg) {
|
|
38
|
+
return { ...arg, loc: this.sourceLocationNoMaterialize() };
|
|
39
|
+
}
|
|
40
|
+
safeObjectTransform(value, mapper) {
|
|
41
|
+
if (value && typeof value === 'object') {
|
|
42
|
+
// If you wonder why this is all so hard, this is the reason. We cannot lose the methods of our Array objects
|
|
43
|
+
if (Array.isArray(value)) {
|
|
44
|
+
return value.map(x => this.safeObjectTransform(x, mapper));
|
|
45
|
+
}
|
|
46
|
+
return mapper(value);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
forcedAutoGenTree(obj) {
|
|
51
|
+
const copy = { ...obj };
|
|
52
|
+
for (const [key, value] of Object.entries(copy)) {
|
|
53
|
+
copy[key] = this.safeObjectTransform(value, obj => this.forcedAutoGenTree(obj));
|
|
54
|
+
}
|
|
55
|
+
if (this.isLocalized(copy)) {
|
|
56
|
+
copy.loc = this.gen();
|
|
57
|
+
}
|
|
58
|
+
return copy;
|
|
59
|
+
}
|
|
60
|
+
forceMaterialized(arg) {
|
|
61
|
+
if (this.isSourceLocationNoMaterialize(arg.loc)) {
|
|
62
|
+
return this.forcedAutoGenTree(arg);
|
|
63
|
+
}
|
|
64
|
+
return { ...arg };
|
|
65
|
+
}
|
|
66
|
+
isSourceLocation(loc) {
|
|
67
|
+
return 'sourceLocationType' in loc;
|
|
68
|
+
}
|
|
69
|
+
sourceLocationSource(start, end) {
|
|
70
|
+
return {
|
|
71
|
+
sourceLocationType: 'source',
|
|
72
|
+
start,
|
|
73
|
+
end,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
gen() {
|
|
77
|
+
return { sourceLocationType: 'autoGenerate' };
|
|
78
|
+
}
|
|
79
|
+
isSourceLocationSource(loc) {
|
|
80
|
+
return this.isSourceLocation(loc) && loc.sourceLocationType === 'source';
|
|
81
|
+
}
|
|
82
|
+
isSourceLocationStringReplace(loc) {
|
|
83
|
+
return this.isSourceLocation(loc) && loc.sourceLocationType === 'stringReplace';
|
|
84
|
+
}
|
|
85
|
+
sourceLocationNodeReplaceUnsafe(loc) {
|
|
86
|
+
if (this.isSourceLocationSource(loc)) {
|
|
87
|
+
return this.sourceLocationNodeReplace(loc);
|
|
88
|
+
}
|
|
89
|
+
throw new Error('not possible');
|
|
90
|
+
}
|
|
91
|
+
sourceLocationNodeReplace(startOrLoc, end) {
|
|
92
|
+
let starting;
|
|
93
|
+
let ending;
|
|
94
|
+
if (typeof startOrLoc === 'number') {
|
|
95
|
+
starting = startOrLoc;
|
|
96
|
+
ending = end;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
starting = startOrLoc.start;
|
|
100
|
+
ending = startOrLoc.end;
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
sourceLocationType: 'nodeReplace',
|
|
104
|
+
start: starting,
|
|
105
|
+
end: ending,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
isSourceLocationNodeReplace(loc) {
|
|
109
|
+
return this.isSourceLocation(loc) && loc.sourceLocationType === 'nodeReplace';
|
|
110
|
+
}
|
|
111
|
+
isSourceLocationNodeAutoGenerate(loc) {
|
|
112
|
+
return this.isSourceLocation(loc) && loc.sourceLocationType === 'autoGenerate';
|
|
113
|
+
}
|
|
114
|
+
nodeShouldPrint(node) {
|
|
115
|
+
return this.isSourceLocationNodeReplace(node.loc) ||
|
|
116
|
+
this.isSourceLocationNodeAutoGenerate(node.loc);
|
|
117
|
+
}
|
|
118
|
+
printFilter(node, callback) {
|
|
119
|
+
if (this.nodeShouldPrint(node)) {
|
|
120
|
+
callback();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
isSourceLocationNoMaterialize(loc) {
|
|
124
|
+
return this.isSourceLocation(loc) && loc.sourceLocationType === 'noMaterialize';
|
|
125
|
+
}
|
|
126
|
+
isOfType(obj, type) {
|
|
127
|
+
const casted = obj;
|
|
128
|
+
return casted.type === type;
|
|
129
|
+
}
|
|
130
|
+
isOfSubType(obj, type, subType) {
|
|
131
|
+
const temp = obj;
|
|
132
|
+
return temp.type === type && temp.subType === subType;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=CoreFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CoreFactory.js","sourceRoot":"","sources":["CoreFactory.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IToken } from 'chevrotain';\n\nimport type {\n SourceLocation,\n SourceLocationNodeAutoGenerate,\n SourceLocationNodeReplace,\n SourceLocationNoMaterialize,\n SourceLocationSource,\n SourceLocationStringReplace,\n Node,\n Localized,\n Wrap,\n} from './nodeTypings';\n\nexport type Typed<Type extends PropertyKey> = { type: Type };\nexport type SubTyped<Type extends PropertyKey, Subtype extends PropertyKey> = { type: Type; subType: Subtype };\n\nexport class CoreFactory {\n public wrap<T>(val: T, loc: SourceLocation): Wrap<T> {\n return { val, loc };\n }\n\n public isLocalized(obj: unknown): obj is Localized {\n return typeof obj === 'object' && obj !== null && 'loc' in obj &&\n typeof obj.loc === 'object' && obj.loc !== null && 'sourceLocationType' in obj.loc;\n }\n\n public sourceLocation(...elements: (undefined | IToken | Localized)[]): SourceLocation {\n const pureElements = elements.filter(x => x !== undefined);\n if (pureElements.length === 0) {\n return this.sourceLocationNoMaterialize();\n }\n const filtered = pureElements.filter(element =>\n !this.isLocalized(element) || this.isSourceLocationSource(element.loc) ||\n this.isSourceLocationStringReplace(element.loc) || this.isSourceLocationNodeReplace(element.loc));\n if (filtered.length === 0) {\n return this.gen();\n }\n const first = filtered[0];\n const last = filtered.at(-1)!;\n return {\n sourceLocationType: 'source',\n start: this.isLocalized(first) ?\n (<SourceLocationSource | SourceLocationStringReplace> first.loc).start :\n first.startOffset,\n end: this.isLocalized(last) ?\n (<SourceLocationSource | SourceLocationStringReplace> last.loc).end :\n (last.endOffset! + 1),\n };\n }\n\n public sourceLocationNoMaterialize(): SourceLocationNoMaterialize {\n return { sourceLocationType: 'noMaterialize' };\n }\n\n /**\n * Returns a copy of the argument that is not materialized\n */\n public dematerialized<T extends Node>(arg: T): T & { loc: SourceLocationNoMaterialize } {\n return { ...arg, loc: this.sourceLocationNoMaterialize() };\n }\n\n public safeObjectTransform(value: unknown, mapper: (some: object) => any): any {\n if (value && typeof value === 'object') {\n // If you wonder why this is all so hard, this is the reason. We cannot lose the methods of our Array objects\n if (Array.isArray(value)) {\n return value.map(x => this.safeObjectTransform(x, mapper));\n }\n return mapper(value);\n }\n return value;\n }\n\n public forcedAutoGenTree<T extends object>(obj: T): T {\n const copy = { ...obj };\n for (const [ key, value ] of Object.entries(copy)) {\n (<Record<string, object>> copy)[key] = this.safeObjectTransform(value, obj => this.forcedAutoGenTree(obj));\n }\n if (this.isLocalized(copy)) {\n copy.loc = this.gen();\n }\n return copy;\n }\n\n public forceMaterialized<T extends Node>(arg: T): T {\n if (this.isSourceLocationNoMaterialize(arg.loc)) {\n return this.forcedAutoGenTree(arg);\n }\n return { ...arg };\n }\n\n public isSourceLocation(loc: object): loc is SourceLocation {\n return 'sourceLocationType' in loc;\n }\n\n public sourceLocationSource(start: number, end: number): SourceLocationSource {\n return {\n sourceLocationType: 'source',\n start,\n end,\n };\n }\n\n public gen(): SourceLocationNodeAutoGenerate {\n return { sourceLocationType: 'autoGenerate' };\n }\n\n public isSourceLocationSource(loc: object): loc is SourceLocationSource {\n return this.isSourceLocation(loc) && loc.sourceLocationType === 'source';\n }\n\n public isSourceLocationStringReplace(loc: object): loc is SourceLocationStringReplace {\n return this.isSourceLocation(loc) && loc.sourceLocationType === 'stringReplace';\n }\n\n public sourceLocationNodeReplaceUnsafe(loc: SourceLocation): SourceLocationNodeReplace {\n if (this.isSourceLocationSource(loc)) {\n return this.sourceLocationNodeReplace(loc);\n }\n throw new Error('not possible');\n }\n\n public sourceLocationNodeReplace(location: SourceLocationSource): SourceLocationNodeReplace;\n public sourceLocationNodeReplace(start: number, end: number): SourceLocationNodeReplace;\n public sourceLocationNodeReplace(startOrLoc: number | SourceLocationSource, end?: number): SourceLocationNodeReplace {\n let starting;\n let ending;\n if (typeof startOrLoc === 'number') {\n starting = startOrLoc;\n ending = end!;\n } else {\n starting = startOrLoc.start;\n ending = startOrLoc.end;\n }\n return {\n sourceLocationType: 'nodeReplace',\n start: starting,\n end: ending,\n };\n }\n\n public isSourceLocationNodeReplace(loc: object): loc is SourceLocationNodeReplace {\n return this.isSourceLocation(loc) && loc.sourceLocationType === 'nodeReplace';\n }\n\n public isSourceLocationNodeAutoGenerate(loc: object): loc is SourceLocationNodeAutoGenerate {\n return this.isSourceLocation(loc) && loc.sourceLocationType === 'autoGenerate';\n }\n\n public nodeShouldPrint(node: Localized): boolean {\n return this.isSourceLocationNodeReplace(node.loc) ||\n this.isSourceLocationNodeAutoGenerate(node.loc);\n }\n\n public printFilter(node: Localized, callback: () => void): void {\n if (this.nodeShouldPrint(node)) {\n callback();\n }\n }\n\n public isSourceLocationNoMaterialize(loc: object): loc is SourceLocationNoMaterialize {\n return this.isSourceLocation(loc) && loc.sourceLocationType === 'noMaterialize';\n }\n\n public isOfType<Type extends string>(obj: object, type: Type): obj is Typed<Type> {\n const casted: { type?: any } = obj;\n return casted.type === type;\n }\n\n public isOfSubType<Type extends string, SubType extends string>(obj: object, type: Type, subType: SubType):\n obj is SubTyped<Type, SubType> {\n const temp: { type?: unknown; subType?: unknown } = obj;\n return temp.type === type && temp.subType === subType;\n }\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starting inclusive, ending exclusive
|
|
3
|
+
*/
|
|
4
|
+
export type Range<A extends number = number, B extends number = number> = [A, B];
|
|
5
|
+
export declare class RangeArithmetic {
|
|
6
|
+
ranges: Range[];
|
|
7
|
+
private readonly initRange;
|
|
8
|
+
constructor(start: number, end: number);
|
|
9
|
+
private static validate;
|
|
10
|
+
private static substractRange;
|
|
11
|
+
subtract(...range: Range): this;
|
|
12
|
+
negate(): this;
|
|
13
|
+
projection(...range: Range): Range[];
|
|
14
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export class RangeArithmetic {
|
|
2
|
+
constructor(start, end) {
|
|
3
|
+
this.ranges = [];
|
|
4
|
+
this.initRange = RangeArithmetic.validate(start, end);
|
|
5
|
+
this.ranges.push(this.initRange);
|
|
6
|
+
}
|
|
7
|
+
static validate(...range) {
|
|
8
|
+
const [start, end] = range;
|
|
9
|
+
if (start >= end) {
|
|
10
|
+
throw new Error('Invalid range');
|
|
11
|
+
}
|
|
12
|
+
return range;
|
|
13
|
+
}
|
|
14
|
+
static substractRange(included, ...range) {
|
|
15
|
+
const [sMinus, eMinus] = RangeArithmetic.validate(...range);
|
|
16
|
+
return included.flatMap(([sCur, eCur]) => {
|
|
17
|
+
// Split in half
|
|
18
|
+
if (sCur < sMinus && eMinus < eCur) {
|
|
19
|
+
return [[sCur, sMinus], [eMinus, eCur]];
|
|
20
|
+
}
|
|
21
|
+
if (sMinus <= sCur && sCur < eMinus && eMinus < eCur) {
|
|
22
|
+
return [[eMinus, eCur]];
|
|
23
|
+
}
|
|
24
|
+
if (sCur < sMinus && sMinus < eCur && eCur <= eMinus) {
|
|
25
|
+
return [[sCur, sMinus]];
|
|
26
|
+
}
|
|
27
|
+
if (sMinus <= sCur && eCur <= eMinus) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return [[sCur, eCur]];
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
subtract(...range) {
|
|
34
|
+
this.ranges = RangeArithmetic.substractRange(this.ranges, ...range);
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
negate() {
|
|
38
|
+
// Can be optimized
|
|
39
|
+
let iter = [this.initRange];
|
|
40
|
+
for (const range of this.ranges) {
|
|
41
|
+
iter = RangeArithmetic.substractRange(iter, ...range);
|
|
42
|
+
}
|
|
43
|
+
this.ranges = iter;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
projection(...range) {
|
|
47
|
+
const [sProj, eProj] = range;
|
|
48
|
+
if (sProj >= eProj) {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
return this.ranges.flatMap(([sCur, eCur]) => {
|
|
52
|
+
// If projection is inside the range
|
|
53
|
+
if (sCur < sProj && eProj < eCur) {
|
|
54
|
+
return [[sProj, eProj]];
|
|
55
|
+
}
|
|
56
|
+
// Projection wraps around
|
|
57
|
+
if (sProj <= sCur && eCur <= eProj) {
|
|
58
|
+
return [[sCur, eCur]];
|
|
59
|
+
}
|
|
60
|
+
// Matches left side
|
|
61
|
+
if (sProj <= sCur && sCur < eProj && eProj < eCur) {
|
|
62
|
+
return [[sCur, eProj]];
|
|
63
|
+
}
|
|
64
|
+
if (sCur < sProj && sProj < eCur && eCur < eProj) {
|
|
65
|
+
return [[sProj, eCur]];
|
|
66
|
+
}
|
|
67
|
+
return [];
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=RangeArithmetic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RangeArithmetic.js","sourceRoot":"","sources":["RangeArithmetic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Starting inclusive, ending exclusive\n */\nexport type Range<A extends number = number, B extends number = number> = [A, B];\n\nexport class RangeArithmetic {\n public ranges: Range[] = [];\n private readonly initRange: Range;\n public constructor(start: number, end: number) {\n this.initRange = RangeArithmetic.validate(start, end);\n this.ranges.push(this.initRange);\n }\n\n private static validate(...range: Range): Range {\n const [ start, end ] = range;\n if (start >= end) {\n throw new Error('Invalid range');\n }\n return range;\n }\n\n private static substractRange(included: Range[], ...range: Range): Range[] {\n const [ sMinus, eMinus ] = RangeArithmetic.validate(...range);\n\n return included.flatMap(([ sCur, eCur ]) => {\n // Split in half\n if (sCur < sMinus && eMinus < eCur) {\n return [[ sCur, sMinus ], [ eMinus, eCur ]];\n }\n if (sMinus <= sCur && sCur < eMinus && eMinus < eCur) {\n return [[ eMinus, eCur ]];\n }\n if (sCur < sMinus && sMinus < eCur && eCur <= eMinus) {\n return [[ sCur, sMinus ]];\n }\n if (sMinus <= sCur && eCur <= eMinus) {\n return [];\n }\n return [[ sCur, eCur ]];\n });\n }\n\n public subtract(...range: Range): this {\n this.ranges = RangeArithmetic.substractRange(this.ranges, ...range);\n return this;\n }\n\n public negate(): this {\n // Can be optimized\n let iter = [ this.initRange ];\n for (const range of this.ranges) {\n iter = RangeArithmetic.substractRange(iter, ...range);\n }\n this.ranges = iter;\n return this;\n }\n\n public projection(...range: Range): Range[] {\n const [ sProj, eProj ] = range;\n if (sProj >= eProj) {\n return [];\n }\n return this.ranges.flatMap(([ sCur, eCur ]) => {\n // If projection is inside the range\n if (sCur < sProj && eProj < eCur) {\n return [[ sProj, eProj ]];\n }\n // Projection wraps around\n if (sProj <= sCur && eCur <= eProj) {\n return [[ sCur, eCur ]];\n }\n // Matches left side\n if (sProj <= sCur && sCur < eProj && eProj < eCur) {\n return [[ sCur, eProj ]];\n }\n if (sCur < sProj && sProj < eCur && eCur < eProj) {\n return [[ sProj, eCur ]];\n }\n return [];\n });\n }\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SubTyped } from './CoreFactory';
|
|
2
|
+
import type { Node } from './nodeTypings';
|
|
3
|
+
type MapNodeTypeToImpls<Nodes extends Node> = {
|
|
4
|
+
[Node in Nodes as Node['type']]: Node;
|
|
5
|
+
};
|
|
6
|
+
type MapNodeSubTypeToImpls<Nodes extends Node & {
|
|
7
|
+
subType: string;
|
|
8
|
+
}> = {
|
|
9
|
+
[Node in Nodes as Node['subType']]: Node;
|
|
10
|
+
};
|
|
11
|
+
export type AlterNodeOutput<RecursiveObject extends object, Input, Out> = {
|
|
12
|
+
[Key in keyof RecursiveObject]: RecursiveObject[Key] extends object ? (AlterNodeOutput<RecursiveObject[Key], Input, Out> extends Input ? Out : AlterNodeOutput<RecursiveObject[Key], Input, Out>) : RecursiveObject[Key];
|
|
13
|
+
};
|
|
14
|
+
export declare class Transformer<Nodes extends Node, NodeMapping extends MapNodeTypeToImpls<Nodes> & Record<string, unknown> = MapNodeTypeToImpls<Nodes>> {
|
|
15
|
+
transformNode<Input extends object, TypeFilter extends keyof NodeMapping, Out>(curObject: Input, searchType: TypeFilter, patch: (current: NodeMapping[TypeFilter]) => Out): AlterNodeOutput<Input, NodeMapping[TypeFilter], Out>;
|
|
16
|
+
transformNodeSpecific<Input extends object, TypeFilter extends keyof NodeMapping, SpecificType extends keyof SpecificNodes, Out, SpecificNodes = NodeMapping[TypeFilter] extends Node & {
|
|
17
|
+
subType: string;
|
|
18
|
+
} ? MapNodeSubTypeToImpls<NodeMapping[TypeFilter]> : never>(curObject: Input, searchType: TypeFilter, searchSubType: SpecificType, patch: (current: SpecificNodes[SpecificType]) => Out): AlterNodeOutput<Input, SubTyped<TypeFilter, SpecificType>, Out>;
|
|
19
|
+
visitObjects(curObject: object, visitor: (current: object) => void): void;
|
|
20
|
+
visitNode<Input extends object, TypeFilter extends keyof NodeMapping>(curObject: Input, searchType: TypeFilter, visitor: (current: Readonly<NodeMapping[TypeFilter]>) => void): void;
|
|
21
|
+
visitNodeSpecific<Input extends object, TypeFilter extends keyof NodeMapping, SpecificType extends keyof SpecificNodes, SpecificNodes = NodeMapping[TypeFilter] extends Node & {
|
|
22
|
+
subType: string;
|
|
23
|
+
} ? MapNodeSubTypeToImpls<NodeMapping[TypeFilter]> : never>(curObject: Input, searchType: TypeFilter, searchSubType: SpecificType, visitor: (current: Readonly<SpecificNodes[SpecificType]>) => void): void;
|
|
24
|
+
private safeObjectVisit;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export class Transformer {
|
|
2
|
+
transformNode(curObject, searchType, patch) {
|
|
3
|
+
const copy = { ...curObject };
|
|
4
|
+
for (const [key, value] of Object.entries(copy)) {
|
|
5
|
+
copy[key] =
|
|
6
|
+
this.safeObjectVisit(value, obj => this.transformNode(obj, searchType, patch));
|
|
7
|
+
}
|
|
8
|
+
if (copy.type === searchType) {
|
|
9
|
+
return patch(copy);
|
|
10
|
+
}
|
|
11
|
+
return copy;
|
|
12
|
+
}
|
|
13
|
+
transformNodeSpecific(curObject, searchType, searchSubType, patch) {
|
|
14
|
+
const copy = { ...curObject };
|
|
15
|
+
for (const [key, value] of Object.entries(copy)) {
|
|
16
|
+
copy[key] =
|
|
17
|
+
this.safeObjectVisit(value, obj => this.transformNodeSpecific(obj, searchType, searchSubType, patch));
|
|
18
|
+
}
|
|
19
|
+
if (copy.type === searchType && copy.subType === searchSubType) {
|
|
20
|
+
return patch(copy);
|
|
21
|
+
}
|
|
22
|
+
return copy;
|
|
23
|
+
}
|
|
24
|
+
visitObjects(curObject, visitor) {
|
|
25
|
+
for (const value of Object.values(curObject)) {
|
|
26
|
+
this.safeObjectVisit(value, obj => this.visitObjects(obj, visitor));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
visitNode(curObject, searchType, visitor) {
|
|
30
|
+
for (const value of Object.values(curObject)) {
|
|
31
|
+
this.safeObjectVisit(value, obj => this.visitNode(obj, searchType, visitor));
|
|
32
|
+
}
|
|
33
|
+
if (curObject.type === searchType) {
|
|
34
|
+
visitor(curObject);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
visitNodeSpecific(curObject, searchType, searchSubType, visitor) {
|
|
38
|
+
for (const value of Object.values(curObject)) {
|
|
39
|
+
this.safeObjectVisit(value, obj => this.visitNodeSpecific(obj, searchType, searchSubType, visitor));
|
|
40
|
+
}
|
|
41
|
+
const cast = curObject;
|
|
42
|
+
if (cast.type === searchType && cast.subType === searchSubType) {
|
|
43
|
+
visitor(curObject);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
safeObjectVisit(value, mapper) {
|
|
47
|
+
if (value && typeof value === 'object') {
|
|
48
|
+
// If you wonder why this is all so hard, this is the reason. We cannot lose the methods of our Array objects
|
|
49
|
+
if (Array.isArray(value)) {
|
|
50
|
+
return value.map(x => this.safeObjectVisit(x, mapper));
|
|
51
|
+
}
|
|
52
|
+
return mapper(value);
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=Transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Transformer.js","sourceRoot":"","sources":["Transformer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SubTyped } from './CoreFactory';\nimport type { Node } from './nodeTypings';\n\ntype MapNodeTypeToImpls<Nodes extends Node> = {[Node in Nodes as Node['type']]: Node };\ntype MapNodeSubTypeToImpls<Nodes extends Node & { subType: string }> = {[Node in Nodes as Node['subType']]: Node };\n\nexport type AlterNodeOutput<RecursiveObject extends object, Input, Out>\n = {\n [Key in keyof RecursiveObject]: RecursiveObject[Key] extends object ?\n (AlterNodeOutput<RecursiveObject[Key], Input, Out> extends Input ?\n Out : AlterNodeOutput<RecursiveObject[Key], Input, Out>) :\n RecursiveObject[Key]\n };\n\nexport class Transformer<\n Nodes extends Node,\nNodeMapping extends MapNodeTypeToImpls<Nodes> & Record<string, unknown> = MapNodeTypeToImpls<Nodes>,\n> {\n public transformNode<Input extends object, TypeFilter extends keyof NodeMapping, Out>(\n curObject: Input,\n searchType: TypeFilter,\n patch: (current: NodeMapping[TypeFilter]) => Out,\n ): AlterNodeOutput<Input, NodeMapping[TypeFilter], Out> {\n const copy: { type?: unknown } = { ...curObject };\n for (const [ key, value ] of Object.entries(copy)) {\n (<Record<string, unknown>> copy)[key] =\n this.safeObjectVisit(value, obj => this.transformNode(obj, searchType, patch));\n }\n if (copy.type === searchType) {\n return <any> patch(<NodeMapping[TypeFilter]> copy);\n }\n return <any> copy;\n }\n\n public transformNodeSpecific<\n Input extends object,\nTypeFilter extends keyof NodeMapping,\nSpecificType extends keyof SpecificNodes,\nOut,\nSpecificNodes = NodeMapping[TypeFilter] extends Node & { subType: string } ?\n MapNodeSubTypeToImpls<NodeMapping[TypeFilter]> : never,\n>(\n curObject: Input,\n searchType: TypeFilter,\n searchSubType: SpecificType,\n patch: (current: SpecificNodes[SpecificType]) => Out,\n ): AlterNodeOutput<Input, SubTyped<TypeFilter, SpecificType>, Out> {\n const copy: { type?: unknown; subType?: unknown } = { ...curObject };\n for (const [ key, value ] of Object.entries(copy)) {\n (<Record<string, unknown>> copy)[key] =\n this.safeObjectVisit(value, obj => this.transformNodeSpecific(obj, searchType, searchSubType, patch));\n }\n if (copy.type === searchType && copy.subType === searchSubType) {\n return <any> patch(<SpecificNodes[SpecificType]> copy);\n }\n return <any> copy;\n }\n\n public visitObjects(curObject: object, visitor: (current: object) => void): void {\n for (const value of Object.values(curObject)) {\n this.safeObjectVisit(value, obj => this.visitObjects(obj, visitor));\n }\n }\n\n public visitNode<Input extends object, TypeFilter extends keyof NodeMapping>(\n curObject: Input,\n searchType: TypeFilter,\n visitor: (current: Readonly<NodeMapping[TypeFilter]>) => void,\n ): void {\n for (const value of Object.values(curObject)) {\n this.safeObjectVisit(value, obj => this.visitNode(obj, searchType, visitor));\n }\n if ((<{ type?: unknown }>curObject).type === searchType) {\n visitor(<NodeMapping[TypeFilter]> curObject);\n }\n }\n\n public visitNodeSpecific<\n Input extends object,\nTypeFilter extends keyof NodeMapping,\nSpecificType extends keyof SpecificNodes,\nSpecificNodes = NodeMapping[TypeFilter] extends Node & { subType: string } ?\n MapNodeSubTypeToImpls<NodeMapping[TypeFilter]> : never,\n >(\n curObject: Input,\n searchType: TypeFilter,\n searchSubType: SpecificType,\n visitor: (current: Readonly<SpecificNodes[SpecificType]>) => void,\n ): void {\n for (const value of Object.values(curObject)) {\n this.safeObjectVisit(value, obj => this.visitNodeSpecific(obj, searchType, searchSubType, visitor));\n }\n const cast = <{ type?: unknown; subType?: unknown }>curObject;\n if (cast.type === searchType && cast.subType === searchSubType) {\n visitor(<SpecificNodes[SpecificType]> curObject);\n }\n }\n\n private safeObjectVisit(value: unknown, mapper: (some: object) => any): any {\n if (value && typeof value === 'object') {\n // If you wonder why this is all so hard, this is the reason. We cannot lose the methods of our Array objects\n if (Array.isArray(value)) {\n return value.map(x => this.safeObjectVisit(x, mapper));\n }\n return mapper(value);\n }\n return value;\n }\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
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 & {
|
|
20
|
+
origSource: string;
|
|
21
|
+
offset?: number;
|
|
22
|
+
}, args: ARGS) => string : never;
|
|
23
|
+
};
|
|
@@ -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 & { origSource: string; offset?: number }, args: ARGS) => string : never\n};\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CoreFactory } from '../CoreFactory';
|
|
2
|
+
import type { GenRuleMap } from './builderTypes';
|
|
3
|
+
import type { RuleDefArg } from './generatorTypes';
|
|
4
|
+
export declare class DynamicGenerator<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> {
|
|
5
|
+
protected rules: RuleDefs;
|
|
6
|
+
protected readonly factory: CoreFactory;
|
|
7
|
+
protected __context: Context | undefined;
|
|
8
|
+
protected origSource: string;
|
|
9
|
+
protected generatedUntil: number;
|
|
10
|
+
protected expectsSpace: boolean;
|
|
11
|
+
protected readonly stringBuilder: string[];
|
|
12
|
+
constructor(rules: RuleDefs);
|
|
13
|
+
setContext(context: Context): void;
|
|
14
|
+
protected getSafeContext(): Context;
|
|
15
|
+
protected readonly subrule: RuleDefArg['SUBRULE'];
|
|
16
|
+
protected readonly handleLoc: RuleDefArg['HANDLE_LOC'];
|
|
17
|
+
protected readonly catchup: RuleDefArg['CATCHUP'];
|
|
18
|
+
protected readonly print: RuleDefArg['PRINT'];
|
|
19
|
+
private readonly printWord;
|
|
20
|
+
private readonly printSpaceLeft;
|
|
21
|
+
private readonly printWords;
|
|
22
|
+
}
|