@traqula/core 0.0.15 → 0.0.17

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.
@@ -1,7 +1,8 @@
1
- import { CoreFactory } from '../CoreFactory.js';
1
+ import { AstCoreFactory } from '../AstCoreFactory.js';
2
+ import { traqulaIndentation } from '../utils.js';
2
3
  export class DynamicGenerator {
3
4
  rules;
4
- factory = new CoreFactory();
5
+ factory = new AstCoreFactory();
5
6
  __context = undefined;
6
7
  origSource = '';
7
8
  generatedUntil = 0;
@@ -42,6 +43,7 @@ export class DynamicGenerator {
42
43
  PRINT_SPACE_LEFT: this.printSpaceLeft,
43
44
  PRINT_WORD: this.printWord,
44
45
  PRINT_WORDS: this.printWords,
46
+ PRINT_ON_EMPTY: this.printOnEmpty,
45
47
  CATCHUP: this.catchup,
46
48
  HANDLE_LOC: this.handleLoc,
47
49
  })(ast, this.getSafeContext(), ...arg);
@@ -86,7 +88,7 @@ export class DynamicGenerator {
86
88
  print = (...args) => {
87
89
  const pureArgs = args.filter(x => x.length > 0);
88
90
  if (pureArgs.length > 0) {
89
- const [head, ...tail] = pureArgs;
91
+ const head = pureArgs[0];
90
92
  if (this.expectsSpace) {
91
93
  this.expectsSpace = false;
92
94
  const blanks = new Set(['\n', ' ', '\t']);
@@ -95,8 +97,23 @@ export class DynamicGenerator {
95
97
  this.stringBuilder.push(' ');
96
98
  }
97
99
  }
98
- this.stringBuilder.push(head);
99
- this.stringBuilder.push(...tail);
100
+ const context = this.getSafeContext();
101
+ if (context[traqulaIndentation] && typeof context[traqulaIndentation] === 'number') {
102
+ const indent = context[traqulaIndentation];
103
+ for (const str of pureArgs) {
104
+ const [noNl, ...postNl] = str.split('\n');
105
+ this.stringBuilder.push(noNl);
106
+ for (const subStr of postNl.map(line => line.trimStart())) {
107
+ this.stringBuilder.push('\n', ' '.repeat(indent));
108
+ if (subStr.length > 0) {
109
+ this.stringBuilder.push(subStr);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ else {
115
+ this.stringBuilder.push(...pureArgs);
116
+ }
100
117
  }
101
118
  };
102
119
  printWord = (...args) => {
@@ -113,5 +130,33 @@ export class DynamicGenerator {
113
130
  this.printWord(arg);
114
131
  }
115
132
  };
133
+ printOnEmpty = (...args) => {
134
+ // Check if pointer already on empty line
135
+ let counter = this.stringBuilder.length - 1;
136
+ let onEmpty = true;
137
+ const isEmptyTest = /^[ \t\n]*$/u;
138
+ while (counter >= 0 && onEmpty) {
139
+ const cur = this.stringBuilder[counter];
140
+ const indexOfNl = cur.lastIndexOf('\n');
141
+ if (indexOfNl >= 0) {
142
+ // This is the last newline that is printed
143
+ onEmpty = isEmptyTest.test(cur.slice(indexOfNl));
144
+ if (onEmpty) {
145
+ // We still want to have the current indent printed
146
+ const newVal = cur.slice(0, indexOfNl);
147
+ if (newVal) {
148
+ this.stringBuilder[counter] = cur.slice(0, indexOfNl);
149
+ }
150
+ else {
151
+ this.stringBuilder.splice(counter, 1);
152
+ }
153
+ }
154
+ break;
155
+ }
156
+ onEmpty = isEmptyTest.test(cur);
157
+ counter--;
158
+ }
159
+ this.print('\n', ...args);
160
+ };
116
161
  }
117
162
  //# sourceMappingURL=dynamicGenerator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamicGenerator.js","sourceRoot":"","sources":["dynamicGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["import { CoreFactory } from '../CoreFactory.js';\nimport type { GenRuleMap } from './builderTypes.js';\nimport type { GeneratorRule, RuleDefArg } from './generatorTypes.js';\n\nexport class DynamicGenerator<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> {\n protected readonly factory = new CoreFactory();\n protected __context: Context | undefined = undefined;\n protected origSource = '';\n protected generatedUntil = 0;\n protected expectsSpace: boolean;\n protected readonly stringBuilder: string[] = [];\n\n public constructor(protected rules: RuleDefs) {\n // eslint-disable-next-line ts/no-unnecessary-type-assertion\n for (const rule of <GeneratorRule[]> Object.values(rules)) {\n // Define function implementation\n this[<keyof (typeof this)> rule.name] =\n <any> ((input: any, context: Context & { origSource: string; offset?: number }, args: any) => {\n this.expectsSpace = false;\n this.stringBuilder.length = 0;\n this.origSource = context.origSource;\n this.generatedUntil = context?.offset ?? 0;\n this.setContext(context);\n\n this.subrule(rule, input, args);\n\n this.catchup(this.origSource.length);\n\n return this.stringBuilder.join('');\n });\n }\n }\n\n public setContext(context: Context): void {\n this.__context = context;\n }\n\n protected getSafeContext(): Context {\n return <Context> this.__context;\n }\n\n protected readonly subrule: RuleDefArg['SUBRULE'] = (cstDef, ast, ...arg) => {\n const def = this.rules[<Names> cstDef.name];\n if (!def) {\n throw new Error(`Rule ${cstDef.name} not found`);\n }\n\n const generate = (): void => def.gImpl({\n SUBRULE: this.subrule,\n PRINT: this.print,\n PRINT_SPACE_LEFT: this.printSpaceLeft,\n PRINT_WORD: this.printWord,\n PRINT_WORDS: this.printWords,\n CATCHUP: this.catchup,\n HANDLE_LOC: this.handleLoc,\n })(ast, this.getSafeContext(), ...arg);\n\n if (this.factory.isLocalized(ast)) {\n this.handleLoc(ast, generate);\n } else {\n generate();\n }\n };\n\n protected readonly handleLoc: RuleDefArg['HANDLE_LOC'] = (localized, handle) => {\n if (this.factory.isSourceLocationNoMaterialize(localized.loc)) {\n return;\n }\n if (this.factory.isSourceLocationStringReplace(localized.loc)) {\n this.catchup(localized.loc.start);\n this.print(localized.loc.newSource);\n this.generatedUntil = localized.loc.end;\n return;\n }\n if (this.factory.isSourceLocationNodeReplace(localized.loc)) {\n this.catchup(localized.loc.start);\n this.generatedUntil = localized.loc.end;\n }\n if (this.factory.isSourceLocationSource(localized.loc)) {\n this.catchup(localized.loc.start);\n }\n // If autoGenerate - do nothing\n\n const ret = handle();\n\n if (this.factory.isSourceLocationSource(localized.loc)) {\n this.catchup(localized.loc.end);\n }\n return ret;\n };\n\n protected readonly catchup: RuleDefArg['CATCHUP'] = (until) => {\n const start = this.generatedUntil;\n if (start < until) {\n this.print(this.origSource.slice(start, until));\n }\n this.generatedUntil = Math.max(this.generatedUntil, until);\n };\n\n protected readonly print: RuleDefArg['PRINT'] = (...args) => {\n const pureArgs = args.filter(x => x.length > 0);\n if (pureArgs.length > 0) {\n const [ head, ...tail ] = pureArgs;\n if (this.expectsSpace) {\n this.expectsSpace = false;\n const blanks = new Set([ '\\n', ' ', '\\t' ]);\n if (this.stringBuilder.length > 0 &&\n !(blanks.has(head[0]) || blanks.has(this.stringBuilder.at(-1)!.at(-1)!))) {\n this.stringBuilder.push(' ');\n }\n }\n this.stringBuilder.push(head);\n this.stringBuilder.push(...tail);\n }\n };\n\n private readonly printWord: RuleDefArg['PRINT_WORD'] = (...args) => {\n this.expectsSpace = true;\n this.print(...args);\n this.expectsSpace = true;\n };\n\n private readonly printSpaceLeft: RuleDefArg['PRINT_WORD'] = (...args) => {\n this.expectsSpace = true;\n this.print(...args);\n };\n\n private readonly printWords: RuleDefArg['PRINT_WORD'] = (...args) => {\n for (const arg of args) {\n this.printWord(arg);\n }\n };\n}\n"]}
1
+ {"version":3,"file":"dynamicGenerator.js","sourceRoot":"","sources":["dynamicGenerator.ts"],"names":[],"mappings":"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","sourcesContent":["import { AstCoreFactory } from '../AstCoreFactory.js';\nimport { traqulaIndentation } from '../utils.js';\nimport type { GenRuleMap } from './builderTypes.js';\nimport type { GeneratorRule, RuleDefArg } from './generatorTypes.js';\n\nexport class DynamicGenerator<Context, Names extends string, RuleDefs extends GenRuleMap<Names>> {\n protected readonly factory = new AstCoreFactory();\n protected __context: Context | undefined = undefined;\n protected origSource = '';\n protected generatedUntil = 0;\n protected expectsSpace: boolean;\n protected readonly stringBuilder: string[] = [];\n\n public constructor(protected rules: RuleDefs) {\n // eslint-disable-next-line ts/no-unnecessary-type-assertion\n for (const rule of <GeneratorRule[]> Object.values(rules)) {\n // Define function implementation\n this[<keyof (typeof this)> rule.name] =\n <any> ((input: any, context: Context & { origSource: string; offset?: number }, args: any) => {\n this.expectsSpace = false;\n this.stringBuilder.length = 0;\n this.origSource = context.origSource;\n this.generatedUntil = context?.offset ?? 0;\n this.setContext(context);\n\n this.subrule(rule, input, args);\n\n this.catchup(this.origSource.length);\n\n return this.stringBuilder.join('');\n });\n }\n }\n\n public setContext(context: Context): void {\n this.__context = context;\n }\n\n protected getSafeContext(): Context & { [traqulaIndentation]?: unknown } {\n return <Context & { [traqulaIndentation]?: unknown }> this.__context;\n }\n\n protected readonly subrule: RuleDefArg['SUBRULE'] = (cstDef, ast, ...arg) => {\n const def = this.rules[<Names> cstDef.name];\n if (!def) {\n throw new Error(`Rule ${cstDef.name} not found`);\n }\n\n const generate = (): void => def.gImpl({\n SUBRULE: this.subrule,\n PRINT: this.print,\n PRINT_SPACE_LEFT: this.printSpaceLeft,\n PRINT_WORD: this.printWord,\n PRINT_WORDS: this.printWords,\n PRINT_ON_EMPTY: this.printOnEmpty,\n CATCHUP: this.catchup,\n HANDLE_LOC: this.handleLoc,\n })(ast, this.getSafeContext(), ...arg);\n\n if (this.factory.isLocalized(ast)) {\n this.handleLoc(ast, generate);\n } else {\n generate();\n }\n };\n\n protected readonly handleLoc: RuleDefArg['HANDLE_LOC'] = (localized, handle) => {\n if (this.factory.isSourceLocationNoMaterialize(localized.loc)) {\n return;\n }\n if (this.factory.isSourceLocationStringReplace(localized.loc)) {\n this.catchup(localized.loc.start);\n this.print(localized.loc.newSource);\n this.generatedUntil = localized.loc.end;\n return;\n }\n if (this.factory.isSourceLocationNodeReplace(localized.loc)) {\n this.catchup(localized.loc.start);\n this.generatedUntil = localized.loc.end;\n }\n if (this.factory.isSourceLocationSource(localized.loc)) {\n this.catchup(localized.loc.start);\n }\n // If autoGenerate - do nothing\n\n const ret = handle();\n\n if (this.factory.isSourceLocationSource(localized.loc)) {\n this.catchup(localized.loc.end);\n }\n return ret;\n };\n\n protected readonly catchup: RuleDefArg['CATCHUP'] = (until) => {\n const start = this.generatedUntil;\n if (start < until) {\n this.print(this.origSource.slice(start, until));\n }\n this.generatedUntil = Math.max(this.generatedUntil, until);\n };\n\n protected readonly print: RuleDefArg['PRINT'] = (...args) => {\n const pureArgs = args.filter(x => x.length > 0);\n if (pureArgs.length > 0) {\n const head = pureArgs[0];\n if (this.expectsSpace) {\n this.expectsSpace = false;\n const blanks = new Set([ '\\n', ' ', '\\t' ]);\n if (this.stringBuilder.length > 0 &&\n !(blanks.has(head[0]) || blanks.has(this.stringBuilder.at(-1)!.at(-1)!))) {\n this.stringBuilder.push(' ');\n }\n }\n const context = this.getSafeContext();\n if (context[traqulaIndentation] && typeof context[traqulaIndentation] === 'number') {\n const indent = context[traqulaIndentation];\n for (const str of pureArgs) {\n const [ noNl, ...postNl ] = str.split('\\n');\n this.stringBuilder.push(noNl);\n for (const subStr of postNl.map(line => line.trimStart())) {\n this.stringBuilder.push('\\n', ' '.repeat(indent));\n if (subStr.length > 0) {\n this.stringBuilder.push(subStr);\n }\n }\n }\n } else {\n this.stringBuilder.push(...pureArgs);\n }\n }\n };\n\n private readonly printWord: RuleDefArg['PRINT_WORD'] = (...args) => {\n this.expectsSpace = true;\n this.print(...args);\n this.expectsSpace = true;\n };\n\n private readonly printSpaceLeft: RuleDefArg['PRINT_WORD'] = (...args) => {\n this.expectsSpace = true;\n this.print(...args);\n };\n\n private readonly printWords: RuleDefArg['PRINT_WORD'] = (...args) => {\n for (const arg of args) {\n this.printWord(arg);\n }\n };\n\n private readonly printOnEmpty: RuleDefArg['PRINT_ON_EMPTY'] = (...args) => {\n // Check if pointer already on empty line\n let counter = this.stringBuilder.length - 1;\n let onEmpty = true;\n const isEmptyTest = /^[ \\t\\n]*$/u;\n while (counter >= 0 && onEmpty) {\n const cur = this.stringBuilder[counter];\n const indexOfNl = cur.lastIndexOf('\\n');\n if (indexOfNl >= 0) {\n // This is the last newline that is printed\n onEmpty = isEmptyTest.test(cur.slice(indexOfNl));\n if (onEmpty) {\n // We still want to have the current indent printed\n const newVal = cur.slice(0, indexOfNl);\n if (newVal) {\n this.stringBuilder[counter] = cur.slice(0, indexOfNl);\n } else {\n this.stringBuilder.splice(counter, 1);\n }\n }\n break;\n }\n onEmpty = isEmptyTest.test(cur);\n counter--;\n }\n this.print('\\n', ...args);\n };\n}\n"]}
@@ -31,6 +31,7 @@ export interface RuleDefArg {
31
31
  PRINT_SPACE_LEFT: (...args: string[]) => void;
32
32
  PRINT_WORD: (...args: string[]) => void;
33
33
  PRINT_WORDS: (...args: string[]) => void;
34
+ PRINT_ON_EMPTY: (...args: string[]) => void;
34
35
  HANDLE_LOC: <T>(loc: Localized, nodeHandle: () => T) => T | undefined;
35
36
  CATCHUP: (until: number) => void;
36
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generatorTypes.js","sourceRoot":"","sources":["generatorTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { Localized } from '../nodeTypings.js';\n\n/**\n * Type used to declare generator rules.\n */\nexport type GeneratorRule<\n /**\n * Context object available in rule implementation.\n */\n Context = any,\n /**\n * Name of grammar rule, should be a strict subtype of string like 'myGrammarRule'.\n */\n NameType extends string = string,\n /**\n * Type that of the AST that we will generate the string for.\n * This type will be the provided when calling SUBRULE with this generator rule.\n * Generation happens on a per AST node basis.\n * The core will implement the generation as such. If this ever changes, we will cross that bridge when we get there.\n */\n AstType = any,\n /**\n * Function arguments that can be given to convey the state of the current parse operation.\n */\n ParamType extends any[] = any[],\n> = {\n name: NameType;\n gImpl: (def: RuleDefArg) =>\n (ast: AstType, context: Context, ...params: ParamType) => void;\n};\n\nexport interface RuleDefArg {\n SUBRULE: <T, U extends any[]>(cstDef: GeneratorRule<any, any, T, U>, input: T, ...arg: U) => void;\n PRINT: (...args: string[]) => void;\n PRINT_SPACE_LEFT: (...args: string[]) => void;\n PRINT_WORD: (...args: string[]) => void;\n PRINT_WORDS: (...args: string[]) => void;\n HANDLE_LOC: <T>(loc: Localized, nodeHandle: () => T) => T | undefined;\n CATCHUP: (until: number) => void;\n}\n"]}
1
+ {"version":3,"file":"generatorTypes.js","sourceRoot":"","sources":["generatorTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { Localized } from '../nodeTypings.js';\n\n/**\n * Type used to declare generator rules.\n */\nexport type GeneratorRule<\n /**\n * Context object available in rule implementation.\n */\n Context = any,\n /**\n * Name of grammar rule, should be a strict subtype of string like 'myGrammarRule'.\n */\n NameType extends string = string,\n /**\n * Type that of the AST that we will generate the string for.\n * This type will be the provided when calling SUBRULE with this generator rule.\n * Generation happens on a per AST node basis.\n * The core will implement the generation as such. If this ever changes, we will cross that bridge when we get there.\n */\n AstType = any,\n /**\n * Function arguments that can be given to convey the state of the current parse operation.\n */\n ParamType extends any[] = any[],\n> = {\n name: NameType;\n gImpl: (def: RuleDefArg) =>\n (ast: AstType, context: Context, ...params: ParamType) => void;\n};\n\nexport interface RuleDefArg {\n SUBRULE: <T, U extends any[]>(cstDef: GeneratorRule<any, any, T, U>, input: T, ...arg: U) => void;\n PRINT: (...args: string[]) => void;\n PRINT_SPACE_LEFT: (...args: string[]) => void;\n PRINT_WORD: (...args: string[]) => void;\n PRINT_WORDS: (...args: string[]) => void;\n PRINT_ON_EMPTY: (...args: string[]) => void;\n HANDLE_LOC: <T>(loc: Localized, nodeHandle: () => T) => T | undefined;\n CATCHUP: (until: number) => void;\n}\n"]}