@traqula/core 0.0.1-alpha.145 → 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 +388 -643
- 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 +45 -29
- 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 +8 -10
- 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 -19
- package/lib/grammar-builder/builderTypes.js.map +0 -1
- package/lib/grammar-builder/parserBuilder.d.ts +0 -50
- package/lib/grammar-builder/parserBuilder.js +0 -276
- 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/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './grammar-helpers/utils';
|
|
1
|
+
export * from './generator-builder/builderTypes';
|
|
2
|
+
export * from './generator-builder/generatorBuilder';
|
|
3
|
+
export * from './generator-builder/generatorTypes';
|
|
5
4
|
export * from './lexer-builder/LexerBuilder';
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
5
|
+
export * from './parser-builder/builderTypes';
|
|
6
|
+
export * from './parser-builder/parserBuilder';
|
|
7
|
+
export * from './parser-builder/ruleDefTypes';
|
|
8
|
+
export * from './utils';
|
package/lib/index.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
1
|
+
// Export generator builder
|
|
2
|
+
export * from './generator-builder/builderTypes';
|
|
3
|
+
export * from './generator-builder/generatorBuilder';
|
|
4
|
+
export * from './generator-builder/generatorTypes';
|
|
5
|
+
// Export lexer builder
|
|
5
6
|
export * from './lexer-builder/LexerBuilder';
|
|
6
|
-
|
|
7
|
-
export * from './
|
|
7
|
+
// Export parser builder
|
|
8
|
+
export * from './parser-builder/builderTypes';
|
|
9
|
+
export * from './parser-builder/parserBuilder';
|
|
10
|
+
export * from './parser-builder/ruleDefTypes';
|
|
11
|
+
// Export general types
|
|
12
|
+
export * from './utils';
|
|
8
13
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,cAAc,kCAAkC,CAAC;AACjD,cAAc,sCAAsC,CAAC;AACrD,cAAc,oCAAoC,CAAC;AACnD,uBAAuB;AACvB,cAAc,8BAA8B,CAAC;AAC7C,wBAAwB;AACxB,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,uBAAuB;AACvB,cAAc,SAAS,CAAC","sourcesContent":["// Export generator builder\nexport * from './generator-builder/builderTypes';\nexport * from './generator-builder/generatorBuilder';\nexport * from './generator-builder/generatorTypes';\n// Export lexer builder\nexport * from './lexer-builder/LexerBuilder';\n// Export parser builder\nexport * from './parser-builder/builderTypes';\nexport * from './parser-builder/parserBuilder';\nexport * from './parser-builder/ruleDefTypes';\n// Export general types\nexport * from './utils';\n"]}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
+
import type { ILexerConfig } from '@chevrotain/types';
|
|
1
2
|
import type { TokenType } from 'chevrotain';
|
|
2
|
-
import
|
|
3
|
-
type
|
|
4
|
-
name: Name;
|
|
5
|
-
};
|
|
3
|
+
import { Lexer } from 'chevrotain';
|
|
4
|
+
import type { CheckOverlap, NamedToken } from '../utils';
|
|
6
5
|
export declare class LexerBuilder<NAMES extends string = string> {
|
|
7
6
|
private readonly tokens;
|
|
8
|
-
static create<U extends LexerBuilder<T>, T extends string =
|
|
9
|
-
constructor(
|
|
10
|
-
get(index: number): TokenType;
|
|
7
|
+
static create<U extends LexerBuilder<T>, T extends string = never>(starter?: U): U;
|
|
8
|
+
private constructor();
|
|
11
9
|
merge<OtherNames extends string, OW extends string>(merge: LexerBuilder<OtherNames>, overwrite?: NamedToken<OW>[]): LexerBuilder<NAMES | OtherNames>;
|
|
12
10
|
add<Name extends string>(...token: CheckOverlap<Name, NAMES, NamedToken<Name>[]>): LexerBuilder<Name | NAMES>;
|
|
13
11
|
addBefore<Name extends string>(before: NamedToken<NAMES>, ...token: CheckOverlap<Name, NAMES, NamedToken<Name>[]>): LexerBuilder<NAMES | Name>;
|
|
@@ -16,6 +14,6 @@ export declare class LexerBuilder<NAMES extends string = string> {
|
|
|
16
14
|
moveAfter<Name extends string>(after: NamedToken<NAMES>, ...tokens: CheckOverlap<Name, NAMES, never, NamedToken<Name>[]>): LexerBuilder<NAMES>;
|
|
17
15
|
addAfter<Name extends string>(after: NamedToken<NAMES>, ...token: CheckOverlap<Name, NAMES, never, NamedToken<Name>[]>): LexerBuilder<NAMES | Name>;
|
|
18
16
|
delete<Name extends NAMES>(...token: NamedToken<Name>[]): LexerBuilder<Exclude<NAMES, Name>>;
|
|
19
|
-
build():
|
|
17
|
+
build(lexerConfig?: ILexerConfig): Lexer;
|
|
18
|
+
get tokenVocabulary(): readonly TokenType[];
|
|
20
19
|
}
|
|
21
|
-
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Lexer } from 'chevrotain';
|
|
1
2
|
export class LexerBuilder {
|
|
2
3
|
static create(starter) {
|
|
3
4
|
return new LexerBuilder(starter);
|
|
@@ -5,9 +6,6 @@ export class LexerBuilder {
|
|
|
5
6
|
constructor(starter) {
|
|
6
7
|
this.tokens = starter?.tokens ? [...starter.tokens] : [];
|
|
7
8
|
}
|
|
8
|
-
get(index) {
|
|
9
|
-
return this.tokens[index];
|
|
10
|
-
}
|
|
11
9
|
merge(merge, overwrite = []) {
|
|
12
10
|
const extraTokens = merge.tokens.filter((token) => {
|
|
13
11
|
const overwriteToken = overwrite.find(t => t.name === token.name);
|
|
@@ -77,7 +75,17 @@ export class LexerBuilder {
|
|
|
77
75
|
}
|
|
78
76
|
return this;
|
|
79
77
|
}
|
|
80
|
-
build() {
|
|
78
|
+
build(lexerConfig) {
|
|
79
|
+
return new Lexer(this.tokens, {
|
|
80
|
+
positionTracking: 'onlyStart',
|
|
81
|
+
recoveryEnabled: false,
|
|
82
|
+
// SafeMode: true,
|
|
83
|
+
// SkipValidations: true,
|
|
84
|
+
ensureOptimizations: true,
|
|
85
|
+
...lexerConfig,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
get tokenVocabulary() {
|
|
81
89
|
return this.tokens;
|
|
82
90
|
}
|
|
83
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LexerBuilder.js","sourceRoot":"","sources":["LexerBuilder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LexerBuilder.js","sourceRoot":"","sources":["LexerBuilder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ILexerConfig } from '@chevrotain/types';\nimport type { TokenType } from 'chevrotain';\nimport { Lexer } from 'chevrotain';\nimport type { CheckOverlap, NamedToken } from '../utils';\n\nexport class LexerBuilder<NAMES extends string = string> {\n private readonly tokens: TokenType[];\n\n public static create<U extends LexerBuilder<T>, T extends string = never>(starter?: U): U {\n return <U> new LexerBuilder(starter);\n }\n\n private constructor(starter?: LexerBuilder<NAMES>) {\n this.tokens = starter?.tokens ? [ ...starter.tokens ] : [];\n }\n\n public merge<OtherNames extends string, OW extends string>(\n merge: LexerBuilder<OtherNames>,\n overwrite: NamedToken<OW>[] = [],\n ):\n LexerBuilder<NAMES | OtherNames> {\n const extraTokens = merge.tokens.filter((token) => {\n const overwriteToken = overwrite.find(t => t.name === token.name);\n if (overwriteToken) {\n return false;\n }\n const match = this.tokens.find(t => t.name === token.name);\n if (match) {\n if (match !== token) {\n throw new Error(`Token with name ${token.name} already exists. Implementation is different and no overwrite was provided.`);\n }\n return false;\n }\n return true;\n });\n this.tokens.push(...extraTokens);\n return this;\n }\n\n public add<Name extends string>(...token: CheckOverlap<Name, NAMES, NamedToken<Name>[]>):\n LexerBuilder<Name | NAMES> {\n this.tokens.push(...token);\n return this;\n }\n\n public addBefore<Name extends string>(\n before: NamedToken<NAMES>,\n ...token: CheckOverlap<Name, NAMES, NamedToken<Name>[]>\n ): LexerBuilder<NAMES | Name> {\n const index = this.tokens.indexOf(before);\n if (index === -1) {\n throw new Error('Token not found');\n }\n this.tokens.splice(index, 0, ...token);\n return this;\n }\n\n private moveBeforeOrAfter<Name extends string>(\n beforeOrAfter: 'before' | 'after',\n before: NamedToken<NAMES>,\n ...tokens: CheckOverlap<Name, NAMES, never, NamedToken<Name>[]>\n ): LexerBuilder<NAMES> {\n const beforeIndex = this.tokens.indexOf(before) + (beforeOrAfter === 'before' ? 0 : 1);\n if (beforeIndex === -1) {\n throw new Error('BeforeToken not found');\n }\n for (const token of tokens) {\n const tokenIndex = this.tokens.indexOf(token);\n if (tokenIndex === -1) {\n throw new Error('Token not found');\n }\n this.tokens.splice(tokenIndex, 1);\n this.tokens.splice(beforeIndex, 0, token);\n }\n return this;\n }\n\n public moveBefore<Name extends string>(\n before: NamedToken<NAMES>,\n ...tokens: CheckOverlap<Name, NAMES, never, NamedToken<Name>[]>\n ): LexerBuilder<NAMES> {\n return this.moveBeforeOrAfter('before', before, ...tokens);\n }\n\n public moveAfter<Name extends string>(\n after: NamedToken<NAMES>,\n ...tokens: CheckOverlap<Name, NAMES, never, NamedToken<Name>[]>\n ): LexerBuilder<NAMES> {\n return this.moveBeforeOrAfter('after', after, ...tokens);\n }\n\n public addAfter<Name extends string>(\n after: NamedToken<NAMES>,\n ...token: CheckOverlap<Name, NAMES, never, NamedToken<Name>[]>\n ): LexerBuilder<NAMES | Name> {\n const index = this.tokens.indexOf(after);\n if (index === -1) {\n throw new Error('Token not found');\n }\n this.tokens.splice(index + 1, 0, ...token);\n return this;\n }\n\n public delete<Name extends NAMES>(...token: NamedToken<Name>[]): LexerBuilder<Exclude<NAMES, Name>> {\n for (const t of token) {\n const index = this.tokens.indexOf(t);\n if (index === -1) {\n throw new Error('Token not found');\n }\n this.tokens.splice(index, 1);\n }\n return this;\n }\n\n public build(lexerConfig?: ILexerConfig): Lexer {\n return new Lexer(this.tokens, {\n positionTracking: 'onlyStart',\n recoveryEnabled: false,\n // SafeMode: true,\n // SkipValidations: true,\n ensureOptimizations: true,\n ...lexerConfig,\n });\n }\n\n public get tokenVocabulary(): readonly TokenType[] {\n return this.tokens;\n }\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ParserMethod } from 'chevrotain';
|
|
2
|
+
import type { ParserRule } from './ruleDefTypes';
|
|
3
|
+
/**
|
|
4
|
+
* Get union-type of names used in list of ruledefs.
|
|
5
|
+
*/
|
|
6
|
+
export type ParseNamesFromList<T extends readonly ParserRule[]> = T[number]['name'];
|
|
7
|
+
/**
|
|
8
|
+
* Convert a list of ruledefs to a record that maps each rule name to its definition.
|
|
9
|
+
*/
|
|
10
|
+
export type ParseRuleMap<RuleNames extends string> = {
|
|
11
|
+
[Key in RuleNames]: ParserRule<any, Key>;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Convert a list of RuleDefs to a Record with the name of the RuleDef as the key, matching the RuleDefMap type.
|
|
15
|
+
*/
|
|
16
|
+
export type ParseRulesToObject<T extends readonly ParserRule[], Names extends string = ParseNamesFromList<T>, Agg extends Record<string, ParserRule> = Record<never, never>> = T extends readonly [infer First, ...infer Rest] ? (First extends ParserRule ? (Rest extends readonly ParserRule[] ? (ParseRulesToObject<Rest, Names, {
|
|
17
|
+
[K in keyof Agg | First['name']]: K extends First['name'] ? First : Agg[K];
|
|
18
|
+
}>) : never) : never) : ParseRuleMap<Names> & Agg;
|
|
19
|
+
export type ParserFromRules<Context, Names extends string, RuleDefs extends ParseRuleMap<Names>> = {
|
|
20
|
+
[K in Names]: RuleDefs[K] extends ParserRule<Context, K, infer RET, infer ARGS> ? (input: string, context: Context, args: ARGS) => RET : never;
|
|
21
|
+
};
|
|
22
|
+
export type ParseMethodsFromRules<Context, Names extends string, RuleDefs extends ParseRuleMap<Names>> = {
|
|
23
|
+
[K in Names]: RuleDefs[K] extends ParserRule<Context, K, infer RET, infer ARGS> ? ParserMethod<[Context, ARGS], RET> : never;
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builderTypes.js","sourceRoot":"","sources":["builderTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { ParserMethod } from 'chevrotain';\nimport type { ParserRule } from './ruleDefTypes';\n\n/**\n * Get union-type of names used in list of ruledefs.\n */\nexport type ParseNamesFromList<T extends readonly ParserRule[]> = 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 ParseRuleMap<RuleNames extends string> = {[Key in RuleNames]: ParserRule<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 ParseRulesToObject<\n T extends readonly ParserRule[],\n Names extends string = ParseNamesFromList<T>,\n Agg extends Record<string, ParserRule> = Record<never, never>,\n> = T extends readonly [infer First, ...infer Rest] ? (\n First extends ParserRule ? (\n Rest extends readonly ParserRule[] ? (\n ParseRulesToObject<Rest, Names, {[K in keyof Agg | First['name']]: K extends First['name'] ? First : Agg[K] }>\n ) : never\n ) : never\n) : ParseRuleMap<Names> & Agg;\n\nexport type ParserFromRules<Context, Names extends string, RuleDefs extends ParseRuleMap<Names>> = {\n [K in Names]: RuleDefs[K] extends ParserRule<Context, K, infer RET, infer ARGS> ?\n (input: string, context: Context, args: ARGS) => RET : never\n};\n\nexport type ParseMethodsFromRules<Context, Names extends string, RuleDefs extends ParseRuleMap<Names>> = {\n [K in Names]: RuleDefs[K] extends ParserRule<Context, K, infer RET, infer ARGS> ?\n ParserMethod<[Context, ARGS], RET> : never\n};\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IParserConfig } from '@chevrotain/types';
|
|
2
|
+
import { EmbeddedActionsParser, type TokenVocabulary } from 'chevrotain';
|
|
3
|
+
import type { ParseRuleMap } from './builderTypes';
|
|
4
|
+
export declare class DynamicParser<Context, Names extends string, RuleDefs extends ParseRuleMap<Names>> extends EmbeddedActionsParser {
|
|
5
|
+
private context;
|
|
6
|
+
setContext(context: Context): void;
|
|
7
|
+
constructor(rules: RuleDefs, tokenVocabulary: TokenVocabulary, config?: IParserConfig);
|
|
8
|
+
private constructSelfRef;
|
|
9
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { EmbeddedActionsParser } from 'chevrotain';
|
|
2
|
+
export class DynamicParser extends EmbeddedActionsParser {
|
|
3
|
+
setContext(context) {
|
|
4
|
+
this.context = context;
|
|
5
|
+
}
|
|
6
|
+
constructor(rules, tokenVocabulary, config = {}) {
|
|
7
|
+
super(tokenVocabulary, {
|
|
8
|
+
// RecoveryEnabled: true,
|
|
9
|
+
maxLookahead: 2,
|
|
10
|
+
// SkipValidations: true,
|
|
11
|
+
...config,
|
|
12
|
+
});
|
|
13
|
+
this.context = undefined;
|
|
14
|
+
const selfRef = this.constructSelfRef();
|
|
15
|
+
const implArgs = {
|
|
16
|
+
...selfRef,
|
|
17
|
+
cache: new WeakMap(),
|
|
18
|
+
};
|
|
19
|
+
for (const rule of Object.values(rules)) {
|
|
20
|
+
// Function implementation itself - this function is called AFTER lexing
|
|
21
|
+
this[rule.name] = this.RULE(rule.name, rule.impl(implArgs));
|
|
22
|
+
}
|
|
23
|
+
this.performSelfAnalysis();
|
|
24
|
+
}
|
|
25
|
+
constructSelfRef() {
|
|
26
|
+
const subRuleImpl = (chevrotainSubrule) => ((cstDef, arg) => chevrotainSubrule(this[cstDef.name], { ARGS: [this.context, arg] }));
|
|
27
|
+
return {
|
|
28
|
+
CONSUME: (tokenType, option) => this.CONSUME(tokenType, option),
|
|
29
|
+
CONSUME1: (tokenType, option) => this.CONSUME1(tokenType, option),
|
|
30
|
+
CONSUME2: (tokenType, option) => this.CONSUME2(tokenType, option),
|
|
31
|
+
CONSUME3: (tokenType, option) => this.CONSUME3(tokenType, option),
|
|
32
|
+
CONSUME4: (tokenType, option) => this.CONSUME4(tokenType, option),
|
|
33
|
+
CONSUME5: (tokenType, option) => this.CONSUME5(tokenType, option),
|
|
34
|
+
CONSUME6: (tokenType, option) => this.CONSUME6(tokenType, option),
|
|
35
|
+
CONSUME7: (tokenType, option) => this.CONSUME7(tokenType, option),
|
|
36
|
+
CONSUME8: (tokenType, option) => this.CONSUME8(tokenType, option),
|
|
37
|
+
CONSUME9: (tokenType, option) => this.CONSUME9(tokenType, option),
|
|
38
|
+
OPTION: actionORMethodDef => this.OPTION(actionORMethodDef),
|
|
39
|
+
OPTION1: actionORMethodDef => this.OPTION1(actionORMethodDef),
|
|
40
|
+
OPTION2: actionORMethodDef => this.OPTION2(actionORMethodDef),
|
|
41
|
+
OPTION3: actionORMethodDef => this.OPTION3(actionORMethodDef),
|
|
42
|
+
OPTION4: actionORMethodDef => this.OPTION4(actionORMethodDef),
|
|
43
|
+
OPTION5: actionORMethodDef => this.OPTION5(actionORMethodDef),
|
|
44
|
+
OPTION6: actionORMethodDef => this.OPTION6(actionORMethodDef),
|
|
45
|
+
OPTION7: actionORMethodDef => this.OPTION7(actionORMethodDef),
|
|
46
|
+
OPTION8: actionORMethodDef => this.OPTION8(actionORMethodDef),
|
|
47
|
+
OPTION9: actionORMethodDef => this.OPTION9(actionORMethodDef),
|
|
48
|
+
OR: altsOrOpts => this.OR(altsOrOpts),
|
|
49
|
+
OR1: altsOrOpts => this.OR1(altsOrOpts),
|
|
50
|
+
OR2: altsOrOpts => this.OR2(altsOrOpts),
|
|
51
|
+
OR3: altsOrOpts => this.OR3(altsOrOpts),
|
|
52
|
+
OR4: altsOrOpts => this.OR4(altsOrOpts),
|
|
53
|
+
OR5: altsOrOpts => this.OR5(altsOrOpts),
|
|
54
|
+
OR6: altsOrOpts => this.OR6(altsOrOpts),
|
|
55
|
+
OR7: altsOrOpts => this.OR7(altsOrOpts),
|
|
56
|
+
OR8: altsOrOpts => this.OR8(altsOrOpts),
|
|
57
|
+
OR9: altsOrOpts => this.OR9(altsOrOpts),
|
|
58
|
+
MANY: actionORMethodDef => this.MANY(actionORMethodDef),
|
|
59
|
+
MANY1: actionORMethodDef => this.MANY1(actionORMethodDef),
|
|
60
|
+
MANY2: actionORMethodDef => this.MANY2(actionORMethodDef),
|
|
61
|
+
MANY3: actionORMethodDef => this.MANY3(actionORMethodDef),
|
|
62
|
+
MANY4: actionORMethodDef => this.MANY4(actionORMethodDef),
|
|
63
|
+
MANY5: actionORMethodDef => this.MANY5(actionORMethodDef),
|
|
64
|
+
MANY6: actionORMethodDef => this.MANY6(actionORMethodDef),
|
|
65
|
+
MANY7: actionORMethodDef => this.MANY7(actionORMethodDef),
|
|
66
|
+
MANY8: actionORMethodDef => this.MANY8(actionORMethodDef),
|
|
67
|
+
MANY9: actionORMethodDef => this.MANY9(actionORMethodDef),
|
|
68
|
+
MANY_SEP: options => this.MANY_SEP(options),
|
|
69
|
+
MANY_SEP1: options => this.MANY_SEP1(options),
|
|
70
|
+
MANY_SEP2: options => this.MANY_SEP2(options),
|
|
71
|
+
MANY_SEP3: options => this.MANY_SEP3(options),
|
|
72
|
+
MANY_SEP4: options => this.MANY_SEP4(options),
|
|
73
|
+
MANY_SEP5: options => this.MANY_SEP5(options),
|
|
74
|
+
MANY_SEP6: options => this.MANY_SEP6(options),
|
|
75
|
+
MANY_SEP7: options => this.MANY_SEP7(options),
|
|
76
|
+
MANY_SEP8: options => this.MANY_SEP8(options),
|
|
77
|
+
MANY_SEP9: options => this.MANY_SEP9(options),
|
|
78
|
+
AT_LEAST_ONE: actionORMethodDef => this.AT_LEAST_ONE(actionORMethodDef),
|
|
79
|
+
AT_LEAST_ONE1: actionORMethodDef => this.AT_LEAST_ONE1(actionORMethodDef),
|
|
80
|
+
AT_LEAST_ONE2: actionORMethodDef => this.AT_LEAST_ONE2(actionORMethodDef),
|
|
81
|
+
AT_LEAST_ONE3: actionORMethodDef => this.AT_LEAST_ONE3(actionORMethodDef),
|
|
82
|
+
AT_LEAST_ONE4: actionORMethodDef => this.AT_LEAST_ONE4(actionORMethodDef),
|
|
83
|
+
AT_LEAST_ONE5: actionORMethodDef => this.AT_LEAST_ONE5(actionORMethodDef),
|
|
84
|
+
AT_LEAST_ONE6: actionORMethodDef => this.AT_LEAST_ONE6(actionORMethodDef),
|
|
85
|
+
AT_LEAST_ONE7: actionORMethodDef => this.AT_LEAST_ONE7(actionORMethodDef),
|
|
86
|
+
AT_LEAST_ONE8: actionORMethodDef => this.AT_LEAST_ONE8(actionORMethodDef),
|
|
87
|
+
AT_LEAST_ONE9: actionORMethodDef => this.AT_LEAST_ONE9(actionORMethodDef),
|
|
88
|
+
AT_LEAST_ONE_SEP: options => this.AT_LEAST_ONE_SEP(options),
|
|
89
|
+
AT_LEAST_ONE_SEP1: options => this.AT_LEAST_ONE_SEP1(options),
|
|
90
|
+
AT_LEAST_ONE_SEP2: options => this.AT_LEAST_ONE_SEP2(options),
|
|
91
|
+
AT_LEAST_ONE_SEP3: options => this.AT_LEAST_ONE_SEP3(options),
|
|
92
|
+
AT_LEAST_ONE_SEP4: options => this.AT_LEAST_ONE_SEP4(options),
|
|
93
|
+
AT_LEAST_ONE_SEP5: options => this.AT_LEAST_ONE_SEP5(options),
|
|
94
|
+
AT_LEAST_ONE_SEP6: options => this.AT_LEAST_ONE_SEP6(options),
|
|
95
|
+
AT_LEAST_ONE_SEP7: options => this.AT_LEAST_ONE_SEP7(options),
|
|
96
|
+
AT_LEAST_ONE_SEP8: options => this.AT_LEAST_ONE_SEP8(options),
|
|
97
|
+
AT_LEAST_ONE_SEP9: options => this.AT_LEAST_ONE_SEP9(options),
|
|
98
|
+
ACTION: func => this.ACTION(func),
|
|
99
|
+
BACKTRACK: (cstDef, ...args) => this.BACKTRACK(this[cstDef.name], { ARGS: args }),
|
|
100
|
+
SUBRULE: subRuleImpl((rule, args) => this.SUBRULE(rule, args)),
|
|
101
|
+
SUBRULE1: subRuleImpl((rule, args) => this.SUBRULE1(rule, args)),
|
|
102
|
+
SUBRULE2: subRuleImpl((rule, args) => this.SUBRULE2(rule, args)),
|
|
103
|
+
SUBRULE3: subRuleImpl((rule, args) => this.SUBRULE3(rule, args)),
|
|
104
|
+
SUBRULE4: subRuleImpl((rule, args) => this.SUBRULE4(rule, args)),
|
|
105
|
+
SUBRULE5: subRuleImpl((rule, args) => this.SUBRULE5(rule, args)),
|
|
106
|
+
SUBRULE6: subRuleImpl((rule, args) => this.SUBRULE6(rule, args)),
|
|
107
|
+
SUBRULE7: subRuleImpl((rule, args) => this.SUBRULE7(rule, args)),
|
|
108
|
+
SUBRULE8: subRuleImpl((rule, args) => this.SUBRULE8(rule, args)),
|
|
109
|
+
SUBRULE9: subRuleImpl((rule, args) => this.SUBRULE9(rule, args)),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=dynamicParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamicParser.js","sourceRoot":"","sources":["dynamicParser.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IParserConfig } from '@chevrotain/types';\nimport { EmbeddedActionsParser, type TokenVocabulary } from 'chevrotain';\nimport type { ParseRuleMap } from './builderTypes';\nimport type { CstDef, ImplArgs, ParserRule } from './ruleDefTypes';\n\nexport class DynamicParser<Context, Names extends string, RuleDefs extends ParseRuleMap<Names>>\n extends EmbeddedActionsParser {\n private context: Context | undefined;\n\n public setContext(context: Context): void {\n this.context = context;\n }\n\n public constructor(rules: RuleDefs, tokenVocabulary: TokenVocabulary, config: IParserConfig = {}) {\n super(tokenVocabulary, {\n // RecoveryEnabled: true,\n maxLookahead: 2,\n // SkipValidations: true,\n ...config,\n });\n this.context = undefined;\n const selfRef = this.constructSelfRef();\n const implArgs: ImplArgs = {\n ...selfRef,\n cache: new WeakMap(),\n };\n\n for (const rule of Object.values(<Record<string, ParserRule<Context>>>rules)) {\n // Function implementation itself - this function is called AFTER lexing\n this[<keyof (typeof this)>rule.name] = <any> this.RULE(rule.name, rule.impl(implArgs));\n }\n this.performSelfAnalysis();\n }\n\n private constructSelfRef(): CstDef {\n const subRuleImpl = (chevrotainSubrule: typeof this.SUBRULE): CstDef['SUBRULE'] =>\n ((cstDef, arg) =>\n chevrotainSubrule(<any> this[<keyof (typeof this)>cstDef.name], <any>{ ARGS: [ this.context, arg ]})\n ) satisfies CstDef['SUBRULE'];\n return {\n CONSUME: (tokenType, option) => this.CONSUME(tokenType, option),\n CONSUME1: (tokenType, option) => this.CONSUME1(tokenType, option),\n CONSUME2: (tokenType, option) => this.CONSUME2(tokenType, option),\n CONSUME3: (tokenType, option) => this.CONSUME3(tokenType, option),\n CONSUME4: (tokenType, option) => this.CONSUME4(tokenType, option),\n CONSUME5: (tokenType, option) => this.CONSUME5(tokenType, option),\n CONSUME6: (tokenType, option) => this.CONSUME6(tokenType, option),\n CONSUME7: (tokenType, option) => this.CONSUME7(tokenType, option),\n CONSUME8: (tokenType, option) => this.CONSUME8(tokenType, option),\n CONSUME9: (tokenType, option) => this.CONSUME9(tokenType, option),\n OPTION: actionORMethodDef => this.OPTION(actionORMethodDef),\n OPTION1: actionORMethodDef => this.OPTION1(actionORMethodDef),\n OPTION2: actionORMethodDef => this.OPTION2(actionORMethodDef),\n OPTION3: actionORMethodDef => this.OPTION3(actionORMethodDef),\n OPTION4: actionORMethodDef => this.OPTION4(actionORMethodDef),\n OPTION5: actionORMethodDef => this.OPTION5(actionORMethodDef),\n OPTION6: actionORMethodDef => this.OPTION6(actionORMethodDef),\n OPTION7: actionORMethodDef => this.OPTION7(actionORMethodDef),\n OPTION8: actionORMethodDef => this.OPTION8(actionORMethodDef),\n OPTION9: actionORMethodDef => this.OPTION9(actionORMethodDef),\n OR: altsOrOpts => this.OR(altsOrOpts),\n OR1: altsOrOpts => this.OR1(altsOrOpts),\n OR2: altsOrOpts => this.OR2(altsOrOpts),\n OR3: altsOrOpts => this.OR3(altsOrOpts),\n OR4: altsOrOpts => this.OR4(altsOrOpts),\n OR5: altsOrOpts => this.OR5(altsOrOpts),\n OR6: altsOrOpts => this.OR6(altsOrOpts),\n OR7: altsOrOpts => this.OR7(altsOrOpts),\n OR8: altsOrOpts => this.OR8(altsOrOpts),\n OR9: altsOrOpts => this.OR9(altsOrOpts),\n MANY: actionORMethodDef => this.MANY(actionORMethodDef),\n MANY1: actionORMethodDef => this.MANY1(actionORMethodDef),\n MANY2: actionORMethodDef => this.MANY2(actionORMethodDef),\n MANY3: actionORMethodDef => this.MANY3(actionORMethodDef),\n MANY4: actionORMethodDef => this.MANY4(actionORMethodDef),\n MANY5: actionORMethodDef => this.MANY5(actionORMethodDef),\n MANY6: actionORMethodDef => this.MANY6(actionORMethodDef),\n MANY7: actionORMethodDef => this.MANY7(actionORMethodDef),\n MANY8: actionORMethodDef => this.MANY8(actionORMethodDef),\n MANY9: actionORMethodDef => this.MANY9(actionORMethodDef),\n MANY_SEP: options => this.MANY_SEP(options),\n MANY_SEP1: options => this.MANY_SEP1(options),\n MANY_SEP2: options => this.MANY_SEP2(options),\n MANY_SEP3: options => this.MANY_SEP3(options),\n MANY_SEP4: options => this.MANY_SEP4(options),\n MANY_SEP5: options => this.MANY_SEP5(options),\n MANY_SEP6: options => this.MANY_SEP6(options),\n MANY_SEP7: options => this.MANY_SEP7(options),\n MANY_SEP8: options => this.MANY_SEP8(options),\n MANY_SEP9: options => this.MANY_SEP9(options),\n AT_LEAST_ONE: actionORMethodDef => this.AT_LEAST_ONE(actionORMethodDef),\n AT_LEAST_ONE1: actionORMethodDef => this.AT_LEAST_ONE1(actionORMethodDef),\n AT_LEAST_ONE2: actionORMethodDef => this.AT_LEAST_ONE2(actionORMethodDef),\n AT_LEAST_ONE3: actionORMethodDef => this.AT_LEAST_ONE3(actionORMethodDef),\n AT_LEAST_ONE4: actionORMethodDef => this.AT_LEAST_ONE4(actionORMethodDef),\n AT_LEAST_ONE5: actionORMethodDef => this.AT_LEAST_ONE5(actionORMethodDef),\n AT_LEAST_ONE6: actionORMethodDef => this.AT_LEAST_ONE6(actionORMethodDef),\n AT_LEAST_ONE7: actionORMethodDef => this.AT_LEAST_ONE7(actionORMethodDef),\n AT_LEAST_ONE8: actionORMethodDef => this.AT_LEAST_ONE8(actionORMethodDef),\n AT_LEAST_ONE9: actionORMethodDef => this.AT_LEAST_ONE9(actionORMethodDef),\n AT_LEAST_ONE_SEP: options => this.AT_LEAST_ONE_SEP(options),\n AT_LEAST_ONE_SEP1: options => this.AT_LEAST_ONE_SEP1(options),\n AT_LEAST_ONE_SEP2: options => this.AT_LEAST_ONE_SEP2(options),\n AT_LEAST_ONE_SEP3: options => this.AT_LEAST_ONE_SEP3(options),\n AT_LEAST_ONE_SEP4: options => this.AT_LEAST_ONE_SEP4(options),\n AT_LEAST_ONE_SEP5: options => this.AT_LEAST_ONE_SEP5(options),\n AT_LEAST_ONE_SEP6: options => this.AT_LEAST_ONE_SEP6(options),\n AT_LEAST_ONE_SEP7: options => this.AT_LEAST_ONE_SEP7(options),\n AT_LEAST_ONE_SEP8: options => this.AT_LEAST_ONE_SEP8(options),\n AT_LEAST_ONE_SEP9: options => this.AT_LEAST_ONE_SEP9(options),\n ACTION: func => this.ACTION(func),\n BACKTRACK: (cstDef, ...args) =>\n this.BACKTRACK(<any> this[<keyof (typeof this)>cstDef.name], <any>{ ARGS: args }),\n SUBRULE: subRuleImpl((rule, args) => this.SUBRULE(rule, args)),\n SUBRULE1: subRuleImpl((rule, args) => this.SUBRULE1(rule, args)),\n SUBRULE2: subRuleImpl((rule, args) => this.SUBRULE2(rule, args)),\n SUBRULE3: subRuleImpl((rule, args) => this.SUBRULE3(rule, args)),\n SUBRULE4: subRuleImpl((rule, args) => this.SUBRULE4(rule, args)),\n SUBRULE5: subRuleImpl((rule, args) => this.SUBRULE5(rule, args)),\n SUBRULE6: subRuleImpl((rule, args) => this.SUBRULE6(rule, args)),\n SUBRULE7: subRuleImpl((rule, args) => this.SUBRULE7(rule, args)),\n SUBRULE8: subRuleImpl((rule, args) => this.SUBRULE8(rule, args)),\n SUBRULE9: subRuleImpl((rule, args) => this.SUBRULE9(rule, args)),\n };\n }\n}\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ILexerConfig, IParserConfig, IRecognitionException } from '@chevrotain/types';
|
|
2
|
+
import type { TokenType } from 'chevrotain';
|
|
3
|
+
import type { CheckOverlap } from '../utils';
|
|
4
|
+
import type { ParseNamesFromList, ParserFromRules, ParseRuleMap, ParseRulesToObject } from './builderTypes';
|
|
5
|
+
import type { ParserRule } from './ruleDefTypes';
|
|
6
|
+
/**
|
|
7
|
+
* The grammar builder. This is the core of traqula (besides using the amazing chevrotain framework).
|
|
8
|
+
* Using the builder you can create a grammar + AST creator.
|
|
9
|
+
* At any point in time, a parser can be constructed from the added rules.
|
|
10
|
+
* Constructing a parser will cause a validation which will validate the correctness of the grammar.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ParserBuilder<Context, Names extends string, RuleDefs extends ParseRuleMap<Names>> {
|
|
13
|
+
/**
|
|
14
|
+
* Create a builder from some initial grammar rules or an existing builder.
|
|
15
|
+
* If a builder is provided, a new copy will be created.
|
|
16
|
+
*/
|
|
17
|
+
static createBuilder<Rules extends readonly ParserRule[] = readonly ParserRule[], Context = Rules[0] extends ParserRule<infer context> ? context : never, Names extends string = ParseNamesFromList<Rules>, RuleDefs extends ParseRuleMap<Names> = ParseRulesToObject<Rules>>(start: Rules | ParserBuilder<Context, Names, RuleDefs>): ParserBuilder<Context, Names, RuleDefs>;
|
|
18
|
+
private rules;
|
|
19
|
+
private constructor();
|
|
20
|
+
typePatch<Patch extends {
|
|
21
|
+
[Key in Names]?: any;
|
|
22
|
+
}>(): ParserBuilder<Context, Names, {
|
|
23
|
+
[Key in Names]: Key extends keyof Patch ? (RuleDefs[Key] extends ParserRule<Context, Key, any, infer Par> ? ParserRule<Context, Key, Patch[Key], Par> : never) : (RuleDefs[Key] extends ParserRule<Context, Key> ? RuleDefs[Key] : never);
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Change the implementation of an existing grammar rule.
|
|
27
|
+
*/
|
|
28
|
+
patchRule<U extends Names, RET, ARGS>(patch: ParserRule<Context, U, RET, ARGS>): ParserBuilder<Context, Names, {
|
|
29
|
+
[Key in Names]: Key extends U ? ParserRule<Context, Key, RET, ARGS> : (RuleDefs[Key] extends ParserRule<Context, Key> ? RuleDefs[Key] : never);
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Add a rule to the grammar. If the rule already exists, but the implementation differs, an error will be thrown.
|
|
33
|
+
*/
|
|
34
|
+
addRuleRedundant<U extends string, RET, ARGS>(rule: ParserRule<Context, U, RET, ARGS>): ParserBuilder<Context, Names | U, {
|
|
35
|
+
[K in Names | U]: K extends U ? ParserRule<Context, K, RET, ARGS> : (K extends Names ? (RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never) : never);
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Add a rule to the grammar. Will raise a typescript error if the rule already exists in the grammar.
|
|
39
|
+
*/
|
|
40
|
+
addRule<U extends string, RET, ARGS>(rule: CheckOverlap<U, Names, ParserRule<Context, U, RET, ARGS>>): ParserBuilder<Context, Names | U, {
|
|
41
|
+
[K in Names | U]: K extends U ? ParserRule<Context, K, RET, ARGS> : (K extends Names ? (RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never) : never);
|
|
42
|
+
}>;
|
|
43
|
+
addMany<U extends readonly ParserRule<Context>[]>(...rules: CheckOverlap<ParseNamesFromList<U>, Names, U>): ParserBuilder<Context, Names | ParseNamesFromList<U>, {
|
|
44
|
+
[K in Names | ParseNamesFromList<U>]: K extends keyof ParseRulesToObject<typeof rules> ? (ParseRulesToObject<typeof rules>[K] extends ParserRule<Context, K> ? ParseRulesToObject<typeof rules>[K] : never) : (K extends Names ? (RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never) : never);
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Delete a grammar rule by its name.
|
|
48
|
+
*/
|
|
49
|
+
deleteRule<U extends Names>(ruleName: U): ParserBuilder<Context, Exclude<Names, U>, {
|
|
50
|
+
[K in Exclude<Names, U>]: RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* Merge this grammar builder with another.
|
|
54
|
+
* It is best to merge the bigger grammar with the smaller one.
|
|
55
|
+
* If the two builders both have a grammar rule with the same name,
|
|
56
|
+
* no error will be thrown case they map to the same ruledef object.
|
|
57
|
+
* If they map to a different object, an error will be thrown.
|
|
58
|
+
* To fix this problem, the overridingRules array should contain a rule with the same conflicting name,
|
|
59
|
+
* this rule implementation will be used.
|
|
60
|
+
*/
|
|
61
|
+
merge<OtherNames extends string, OtherRules extends ParseRuleMap<OtherNames>, OW extends readonly ParserRule<Context>[]>(builder: ParserBuilder<Context, OtherNames, OtherRules>, overridingRules: OW): ParserBuilder<Context, Names | OtherNames | ParseNamesFromList<OW>, {
|
|
62
|
+
[K in Names | OtherNames | ParseNamesFromList<OW>]: K extends keyof ParseRulesToObject<OW> ? (ParseRulesToObject<OW>[K] extends ParserRule<Context, K> ? ParseRulesToObject<OW>[K] : never) : (K extends Names ? (RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never) : K extends OtherNames ? (OtherRules[K] extends ParserRule<Context, K> ? OtherRules[K] : never) : never);
|
|
63
|
+
}>;
|
|
64
|
+
private defaultErrorHandler;
|
|
65
|
+
build({ tokenVocabulary, parserConfig, lexerConfig, queryPreProcessor, errorHandler, }: {
|
|
66
|
+
tokenVocabulary: readonly TokenType[];
|
|
67
|
+
parserConfig?: IParserConfig;
|
|
68
|
+
lexerConfig?: ILexerConfig;
|
|
69
|
+
queryPreProcessor?: (input: string) => string;
|
|
70
|
+
errorHandler?: (errors: IRecognitionException[]) => void;
|
|
71
|
+
}): ParserFromRules<Context, Names, RuleDefs>;
|
|
72
|
+
private consume;
|
|
73
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { LexerBuilder } from '../lexer-builder/LexerBuilder';
|
|
2
|
+
import { DynamicParser } from './dynamicParser';
|
|
3
|
+
/**
|
|
4
|
+
* Converts a list of ruledefs to a record mapping a name to the corresponding ruledef.
|
|
5
|
+
*/
|
|
6
|
+
function listToRuleDefMap(rules) {
|
|
7
|
+
const newRules = {};
|
|
8
|
+
for (const rule of rules) {
|
|
9
|
+
newRules[rule.name] = rule;
|
|
10
|
+
}
|
|
11
|
+
return newRules;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The grammar builder. This is the core of traqula (besides using the amazing chevrotain framework).
|
|
15
|
+
* Using the builder you can create a grammar + AST creator.
|
|
16
|
+
* At any point in time, a parser can be constructed from the added rules.
|
|
17
|
+
* Constructing a parser will cause a validation which will validate the correctness of the grammar.
|
|
18
|
+
*/
|
|
19
|
+
// This code is wild so other code can be simple.
|
|
20
|
+
export class ParserBuilder {
|
|
21
|
+
/**
|
|
22
|
+
* Create a builder from some initial grammar rules or an existing builder.
|
|
23
|
+
* If a builder is provided, a new copy will be created.
|
|
24
|
+
*/
|
|
25
|
+
static createBuilder(start) {
|
|
26
|
+
if (start instanceof ParserBuilder) {
|
|
27
|
+
return new ParserBuilder({ ...start.rules });
|
|
28
|
+
}
|
|
29
|
+
return new ParserBuilder(listToRuleDefMap(start));
|
|
30
|
+
}
|
|
31
|
+
constructor(startRules) {
|
|
32
|
+
this.rules = startRules;
|
|
33
|
+
}
|
|
34
|
+
typePatch() {
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Change the implementation of an existing grammar rule.
|
|
39
|
+
*/
|
|
40
|
+
patchRule(patch) {
|
|
41
|
+
const self = this;
|
|
42
|
+
self.rules[patch.name] = patch;
|
|
43
|
+
return self;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Add a rule to the grammar. If the rule already exists, but the implementation differs, an error will be thrown.
|
|
47
|
+
*/
|
|
48
|
+
addRuleRedundant(rule) {
|
|
49
|
+
const self = this;
|
|
50
|
+
const rules = self.rules;
|
|
51
|
+
if (rules[rule.name] !== undefined && rules[rule.name] !== rule) {
|
|
52
|
+
throw new Error(`Rule ${rule.name} already exists in the builder`);
|
|
53
|
+
}
|
|
54
|
+
rules[rule.name] = rule;
|
|
55
|
+
return self;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Add a rule to the grammar. Will raise a typescript error if the rule already exists in the grammar.
|
|
59
|
+
*/
|
|
60
|
+
addRule(rule) {
|
|
61
|
+
return this.addRuleRedundant(rule);
|
|
62
|
+
}
|
|
63
|
+
addMany(...rules) {
|
|
64
|
+
this.rules = { ...this.rules, ...listToRuleDefMap(rules) };
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Delete a grammar rule by its name.
|
|
69
|
+
*/
|
|
70
|
+
deleteRule(ruleName) {
|
|
71
|
+
delete this.rules[ruleName];
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Merge this grammar builder with another.
|
|
76
|
+
* It is best to merge the bigger grammar with the smaller one.
|
|
77
|
+
* If the two builders both have a grammar rule with the same name,
|
|
78
|
+
* no error will be thrown case they map to the same ruledef object.
|
|
79
|
+
* If they map to a different object, an error will be thrown.
|
|
80
|
+
* To fix this problem, the overridingRules array should contain a rule with the same conflicting name,
|
|
81
|
+
* this rule implementation will be used.
|
|
82
|
+
*/
|
|
83
|
+
merge(builder, overridingRules) {
|
|
84
|
+
// Assume the other grammar is bigger than yours. So start from that one and add this one
|
|
85
|
+
const otherRules = { ...builder.rules };
|
|
86
|
+
const myRules = this.rules;
|
|
87
|
+
for (const rule of Object.values(myRules)) {
|
|
88
|
+
if (otherRules[rule.name] === undefined) {
|
|
89
|
+
otherRules[rule.name] = rule;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
const existingRule = otherRules[rule.name];
|
|
93
|
+
// If same rule, no issue, move on. Else
|
|
94
|
+
if (existingRule !== rule) {
|
|
95
|
+
const override = overridingRules.find(x => x.name === rule.name);
|
|
96
|
+
// If override specified, take override, else, inform user that there is a conflict
|
|
97
|
+
if (override) {
|
|
98
|
+
otherRules[rule.name] = override;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
throw new Error(`Rule with name "${rule.name}" already exists in the builder, specify an override to resolve conflict`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this.rules = otherRules;
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
defaultErrorHandler(input, errors) {
|
|
110
|
+
const firstError = errors[0];
|
|
111
|
+
const messageBuilder = ['Parse error'];
|
|
112
|
+
const lineIdx = firstError.token.startLine;
|
|
113
|
+
if (lineIdx !== undefined) {
|
|
114
|
+
const errorLine = input.split('\n')[lineIdx - 1];
|
|
115
|
+
messageBuilder.push(` on line ${lineIdx}
|
|
116
|
+
${errorLine}`);
|
|
117
|
+
const columnIdx = firstError.token.startColumn;
|
|
118
|
+
if (columnIdx !== undefined) {
|
|
119
|
+
messageBuilder.push(`\n${'-'.repeat(columnIdx - 1)}^`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
messageBuilder.push(`\n${firstError.message}`);
|
|
123
|
+
throw new Error(messageBuilder.join(''));
|
|
124
|
+
}
|
|
125
|
+
build({ tokenVocabulary, parserConfig = {}, lexerConfig = {}, queryPreProcessor = s => s, errorHandler, }) {
|
|
126
|
+
const lexer = LexerBuilder.create().add(...tokenVocabulary).build(lexerConfig);
|
|
127
|
+
// Get the chevrotain parser
|
|
128
|
+
const parser = this.consume({
|
|
129
|
+
tokenVocabulary: tokenVocabulary,
|
|
130
|
+
config: parserConfig,
|
|
131
|
+
});
|
|
132
|
+
// Start building a parser accepts a string instead of tokenized input
|
|
133
|
+
const selfSufficientParser = {};
|
|
134
|
+
// To do that, we need to create a wrapper for each parser rule.
|
|
135
|
+
// eslint-disable-next-line ts/no-unnecessary-type-assertion
|
|
136
|
+
for (const rule of Object.values(this.rules)) {
|
|
137
|
+
selfSufficientParser[rule.name] = ((input, context, arg) => {
|
|
138
|
+
const processedInput = queryPreProcessor(input);
|
|
139
|
+
const lexResult = lexer.tokenize(processedInput);
|
|
140
|
+
// This also resets the parser
|
|
141
|
+
parser.input = lexResult.tokens;
|
|
142
|
+
parser.setContext(context);
|
|
143
|
+
const result = parser[rule.name](context, arg);
|
|
144
|
+
if (parser.errors.length > 0) {
|
|
145
|
+
if (errorHandler) {
|
|
146
|
+
errorHandler(parser.errors);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
this.defaultErrorHandler(processedInput, parser.errors);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return selfSufficientParser;
|
|
156
|
+
}
|
|
157
|
+
consume({ tokenVocabulary, config = {} }) {
|
|
158
|
+
return new DynamicParser(this.rules, tokenVocabulary, config);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=parserBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parserBuilder.js","sourceRoot":"","sources":["parserBuilder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAS7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD;;GAEG;AACH,SAAS,gBAAgB,CAAkC,KAAQ;IACjE,MAAM,QAAQ,GAA+B,EAAE,CAAC;IAChD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7B,CAAC;IACD,OAA8B,QAAQ,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,iDAAiD;AACjD,MAAM,OAAO,aAAa;IACxB;;;OAGG;IACI,MAAM,CAAC,aAAa,CAMzB,KAAsD;QAEtD,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;YACnC,OAAO,IAAI,aAAa,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,OAA2D,IAAI,aAAa,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;IACxG,CAAC;IAID,YAAoB,UAAoB;QACtC,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;IAC1B,CAAC;IAEM,SAAS;QAId,OAE2F,IAAI,CAAC;IAClG,CAAC;IAED;;OAEG;IACI,SAAS,CAA6B,KAAwC;QAKnF,MAAM,IAAI,GAEE,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAS,KAAK,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,gBAAgB,CAA8B,IAAuC;QAK1F,MAAM,IAAI,GAGE,IAAI,CAAC;QACjB,MAAM,KAAK,GAAyC,IAAI,CAAC,KAAK,CAAC;QAC/D,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,gCAAgC,CAAC,CAAC;QACrE,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,OAAO,CACZ,IAA+D;QAI/D,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAEM,OAAO,CACZ,GAAG,KAAoD;QAYvD,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,OAAuB,IAAI,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,UAAU,CAAkB,QAAW;QAG5C,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC5B,OAEY,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAKV,OAAuD,EACvD,eAAmB;QAcnB,yFAAyF;QACzF,MAAM,UAAU,GAAwC,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7E,MAAM,OAAO,GAAwC,IAAI,CAAC,KAAK,CAAC;QAEhE,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBACxC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC3C,wCAAwC;gBACxC,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;oBAC1B,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;oBACjE,mFAAmF;oBACnF,IAAI,QAAQ,EAAE,CAAC;wBACb,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;oBACnC,CAAC;yBAAM,CAAC;wBACN,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,CAAC,IAAI,0EAA0E,CAAC,CAAC;oBAC1H,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,KAAK,GAAmB,UAAU,CAAC;QACxC,OAAuB,IAAI,CAAC;IAC9B,CAAC;IAEO,mBAAmB,CAAC,KAAa,EAAE,MAA+B;QACxE,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,cAAc,GAAa,CAAE,aAAa,CAAE,CAAC;QACnD,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;QAC3C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YACjD,cAAc,CAAC,IAAI,CAAC,YAAY,OAAO;EAC3C,SAAS,EAAE,CAAC,CAAC;YACT,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC;YAC/C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,cAAc,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QACD,cAAc,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC;IAEM,KAAK,CAAC,EACX,eAAe,EACf,YAAY,GAAG,EAAE,EACjB,WAAW,GAAG,EAAE,EAChB,iBAAiB,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1B,YAAY,GAOb;QACC,MAAM,KAAK,GAAU,YAAY,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEtF,4BAA4B;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;YAC1B,eAAe,EAAgB,eAAe;YAC9C,MAAM,EAAE,YAAY;SACrB,CAAC,CAAC;QAEH,sEAAsE;QACtE,MAAM,oBAAoB,GAAuD,EAAE,CAAC;QAEpF,gEAAgE;QAChE,4DAA4D;QAC5D,KAAK,MAAM,IAAI,IAAmC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5E,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAS,CAAC,CAAC,KAAa,EAAE,OAAgB,EAAE,GAAY,EAAE,EAAE;gBACzF,MAAM,cAAc,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;gBAChD,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;gBAEjD,8BAA8B;gBAC9B,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC;gBAChC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;gBAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBAC/C,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,IAAI,YAAY,EAAE,CAAC;wBACjB,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBAC9B,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,mBAAmB,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;oBAC1D,CAAC;gBACH,CAAC;gBACD,OAAO,MAAM,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAmD,oBAAoB,CAAC;IAC1E,CAAC;IAEO,OAAO,CAAC,EAAE,eAAe,EAAE,MAAM,GAAG,EAAE,EAG7C;QAEC,OACuD,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;IAChH,CAAC;CACF","sourcesContent":["import type { ILexerConfig, IParserConfig, IRecognitionException } from '@chevrotain/types';\nimport type { Lexer, TokenType, TokenVocabulary, EmbeddedActionsParser } from 'chevrotain';\nimport { LexerBuilder } from '../lexer-builder/LexerBuilder';\nimport type { CheckOverlap } from '../utils';\nimport type {\n ParseMethodsFromRules,\n ParseNamesFromList,\n ParserFromRules,\n ParseRuleMap,\n ParseRulesToObject,\n} from './builderTypes';\nimport { DynamicParser } from './dynamicParser';\nimport type { ParserRule } from './ruleDefTypes';\n\n/**\n * Converts a list of ruledefs to a record mapping a name to the corresponding ruledef.\n */\nfunction listToRuleDefMap<T extends readonly ParserRule[]>(rules: T): ParseRulesToObject<T> {\n const newRules: Record<string, ParserRule> = {};\n for (const rule of rules) {\n newRules[rule.name] = rule;\n }\n return <ParseRulesToObject<T>>newRules;\n}\n\n/**\n * The grammar builder. This is the core of traqula (besides using the amazing chevrotain framework).\n * Using the builder you can create a grammar + AST creator.\n * At any point in time, a parser can be constructed from the added rules.\n * Constructing a parser will cause a validation which will validate the correctness of the grammar.\n */\n// This code is wild so other code can be simple.\nexport class ParserBuilder<Context, Names extends string, RuleDefs extends ParseRuleMap<Names>> {\n /**\n * Create a builder from some initial grammar rules or an existing builder.\n * If a builder is provided, a new copy will be created.\n */\n public static createBuilder<\n Rules extends readonly ParserRule[] = readonly ParserRule[],\n Context = Rules[0] extends ParserRule<infer context> ? context : never,\n Names extends string = ParseNamesFromList<Rules>,\n RuleDefs extends ParseRuleMap<Names> = ParseRulesToObject<Rules>,\n >(\n start: Rules | ParserBuilder<Context, Names, RuleDefs>,\n ): ParserBuilder<Context, Names, RuleDefs> {\n if (start instanceof ParserBuilder) {\n return new ParserBuilder({ ...start.rules });\n }\n return <ParserBuilder<Context, Names, RuleDefs>> <unknown> new ParserBuilder(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 ParserBuilder<Context, Names, {[Key in Names]: Key extends keyof Patch ? (\n RuleDefs[Key] extends ParserRule<Context, Key, any, infer Par> ? ParserRule<Context, Key, Patch[Key], Par> : never\n ) : (RuleDefs[Key] extends ParserRule<Context, Key> ? RuleDefs[Key] : never) }> {\n return <ParserBuilder<Context, Names, {[Key in Names]: Key extends keyof Patch ? (\n RuleDefs[Key] extends ParserRule<Context, Key, any, infer Par> ? ParserRule<Context, Key, Patch[Key], Par> : never\n ) : (RuleDefs[Key] extends ParserRule<Context, Key> ? RuleDefs[Key] : never) }>> <unknown> this;\n }\n\n /**\n * Change the implementation of an existing grammar rule.\n */\n public patchRule<U extends Names, RET, ARGS>(patch: ParserRule<Context, U, RET, ARGS>):\n ParserBuilder<Context, Names, {[Key in Names]: Key extends U ?\n ParserRule<Context, Key, RET, ARGS> :\n (RuleDefs[Key] extends ParserRule<Context, Key> ? RuleDefs[Key] : never)\n } > {\n const self = <ParserBuilder<Context, Names, {[Key in Names]: Key extends U ?\n ParserRule<Context, Key, RET, ARGS> : (RuleDefs[Key] extends ParserRule<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: ParserRule<Context, U, RET, ARGS>):\n ParserBuilder<Context, Names | U, {[K in Names | U]: K extends U ?\n ParserRule<Context, K, RET, ARGS> :\n (K extends Names ? (RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never) : never)\n }> {\n const self = <ParserBuilder<Context, Names | U, {[K in Names | U]: K extends U ?\n ParserRule<Context, K, RET, ARGS> :\n (K extends Names ? (RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never) : never) }>>\n <unknown> this;\n const rules = <Record<string, ParserRule<Context>>> self.rules;\n if (rules[rule.name] !== undefined && rules[rule.name] !== rule) {\n throw new Error(`Rule ${rule.name} already exists in the builder`);\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, ParserRule<Context, U, RET, ARGS>>,\n ): ParserBuilder<Context, Names | U, {[K in Names | U]: K extends U ?\n ParserRule<Context, K, RET, ARGS> :\n (K extends Names ? (RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never) : never) }> {\n return this.addRuleRedundant(rule);\n }\n\n public addMany<U extends readonly ParserRule<Context>[]>(\n ...rules: CheckOverlap<ParseNamesFromList<U>, Names, U>\n ): ParserBuilder<\n Context,\n Names | ParseNamesFromList<U>,\n {[K in Names | ParseNamesFromList<U>]:\n K extends keyof ParseRulesToObject<typeof rules> ? (\n ParseRulesToObject<typeof rules>[K] extends ParserRule<Context, K> ? ParseRulesToObject<typeof rules>[K] : never\n ) : (\n K extends Names ? (RuleDefs[K] extends ParserRule<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 ParserBuilder<Context, Exclude<Names, U>, {[K in Exclude<Names, U>]:\n RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never }> {\n delete this.rules[ruleName];\n return <ParserBuilder<Context, Exclude<Names, U>, {[K in Exclude<Names, U>]:\n RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never }>>\n <unknown> this;\n }\n\n /**\n * Merge this grammar builder 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 ParseRuleMap<OtherNames>,\n OW extends readonly ParserRule<Context>[],\n >(\n builder: ParserBuilder<Context, OtherNames, OtherRules>,\n overridingRules: OW,\n ):\n ParserBuilder<\n Context,\n Names | OtherNames | ParseNamesFromList<OW>,\n {[K in Names | OtherNames | ParseNamesFromList<OW>]:\n K extends keyof ParseRulesToObject<OW> ? (\n ParseRulesToObject<OW>[K] extends ParserRule<Context, K> ? ParseRulesToObject<OW>[K] : never\n )\n : (\n K extends Names ? (RuleDefs[K] extends ParserRule<Context, K> ? RuleDefs[K] : never)\n : K extends OtherNames ? (OtherRules[K] extends ParserRule<Context, K> ? OtherRules[K] : never) : 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, ParserRule<Context>> = { ...builder.rules };\n const myRules: Record<string, ParserRule<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 builder, 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 private defaultErrorHandler(input: string, errors: IRecognitionException[]): void {\n const firstError = errors[0];\n const messageBuilder: string[] = [ 'Parse error' ];\n const lineIdx = firstError.token.startLine;\n if (lineIdx !== undefined) {\n const errorLine = input.split('\\n')[lineIdx - 1];\n messageBuilder.push(` on line ${lineIdx}\n${errorLine}`);\n const columnIdx = firstError.token.startColumn;\n if (columnIdx !== undefined) {\n messageBuilder.push(`\\n${'-'.repeat(columnIdx - 1)}^`);\n }\n }\n messageBuilder.push(`\\n${firstError.message}`);\n throw new Error(messageBuilder.join(''));\n }\n\n public build({\n tokenVocabulary,\n parserConfig = {},\n lexerConfig = {},\n queryPreProcessor = s => s,\n errorHandler,\n }: {\n tokenVocabulary: readonly TokenType[];\n parserConfig?: IParserConfig;\n lexerConfig?: ILexerConfig;\n queryPreProcessor?: (input: string) => string;\n errorHandler?: (errors: IRecognitionException[]) => void;\n }): ParserFromRules<Context, Names, RuleDefs> {\n const lexer: Lexer = LexerBuilder.create().add(...tokenVocabulary).build(lexerConfig);\n\n // Get the chevrotain parser\n const parser = this.consume({\n tokenVocabulary: <TokenType[]> tokenVocabulary,\n config: parserConfig,\n });\n\n // Start building a parser accepts a string instead of tokenized input\n const selfSufficientParser: Partial<ParserFromRules<Context, Names, RuleDefs>> = {};\n\n // To do that, we need to create a wrapper for each parser rule.\n // eslint-disable-next-line ts/no-unnecessary-type-assertion\n for (const rule of <ParserRule<Context, Names>[]> Object.values(this.rules)) {\n selfSufficientParser[rule.name] = <any> ((input: string, context: Context, arg: unknown) => {\n const processedInput = queryPreProcessor(input);\n const lexResult = lexer.tokenize(processedInput);\n\n // This also resets the parser\n parser.input = lexResult.tokens;\n parser.setContext(context);\n const result = parser[rule.name](context, arg);\n if (parser.errors.length > 0) {\n if (errorHandler) {\n errorHandler(parser.errors);\n } else {\n this.defaultErrorHandler(processedInput, parser.errors);\n }\n }\n return result;\n });\n }\n return <ParserFromRules<Context, Names, RuleDefs>> selfSufficientParser;\n }\n\n private consume({ tokenVocabulary, config = {}}: {\n tokenVocabulary: TokenVocabulary;\n config?: IParserConfig;\n }): EmbeddedActionsParser & ParseMethodsFromRules<Context, Names, RuleDefs> &\n { setContext: (context: Context) => void } {\n return <EmbeddedActionsParser & ParseMethodsFromRules<Context, Names, RuleDefs> &\n { setContext: (context: Context) => void }><unknown> new DynamicParser(this.rules, tokenVocabulary, config);\n }\n}\n"]}
|