@traqula/core 0.0.19 → 0.0.21

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.
Files changed (36) hide show
  1. package/lib/AstCoreFactory.js +1 -1
  2. package/lib/AstCoreFactory.js.map +1 -1
  3. package/lib/TransformerObject.d.ts +65 -0
  4. package/lib/TransformerObject.js +207 -0
  5. package/lib/TransformerObject.js.map +1 -0
  6. package/lib/TransformerSubTyped.d.ts +95 -0
  7. package/lib/TransformerSubTyped.js +119 -0
  8. package/lib/TransformerSubTyped.js.map +1 -0
  9. package/lib/TransformerTyped.d.ts +63 -0
  10. package/lib/TransformerTyped.js +98 -0
  11. package/lib/TransformerTyped.js.map +1 -0
  12. package/lib/generator-builder/dynamicGenerator.d.ts +13 -3
  13. package/lib/generator-builder/dynamicGenerator.js +90 -60
  14. package/lib/generator-builder/dynamicGenerator.js.map +1 -1
  15. package/lib/generator-builder/generatorBuilder.d.ts +5 -2
  16. package/lib/generator-builder/generatorBuilder.js +3 -0
  17. package/lib/generator-builder/generatorBuilder.js.map +1 -1
  18. package/lib/generator-builder/generatorTypes.d.ts +35 -21
  19. package/lib/generator-builder/generatorTypes.js.map +1 -1
  20. package/lib/index.cjs +346 -129
  21. package/lib/index.d.ts +3 -1
  22. package/lib/index.js +3 -1
  23. package/lib/index.js.map +1 -1
  24. package/lib/indirection-builder/IndirBuilder.d.ts +4 -1
  25. package/lib/indirection-builder/IndirBuilder.js +3 -0
  26. package/lib/indirection-builder/IndirBuilder.js.map +1 -1
  27. package/lib/parser-builder/parserBuilder.d.ts +12 -8
  28. package/lib/parser-builder/parserBuilder.js +3 -0
  29. package/lib/parser-builder/parserBuilder.js.map +1 -1
  30. package/lib/utils.d.ts +4 -0
  31. package/lib/utils.js +4 -0
  32. package/lib/utils.js.map +1 -1
  33. package/package.json +2 -2
  34. package/lib/Transformers.d.ts +0 -129
  35. package/lib/Transformers.js +0 -226
  36. package/lib/Transformers.js.map +0 -1
package/lib/index.cjs CHANGED
@@ -25,8 +25,9 @@ __export(index_exports, {
25
25
  IndirBuilder: () => IndirBuilder,
26
26
  LexerBuilder: () => LexerBuilder,
27
27
  ParserBuilder: () => ParserBuilder,
28
- TransformerSubType: () => TransformerSubType,
29
- TransformerType: () => TransformerType,
28
+ TransformerObject: () => TransformerObject,
29
+ TransformerSubTyped: () => TransformerSubTyped,
30
+ TransformerTyped: () => TransformerTyped,
30
31
  createToken: () => createToken2,
31
32
  listToIndirectionMap: () => listToIndirectionMap,
32
33
  traqulaIndentation: () => traqulaIndentation,
@@ -51,7 +52,7 @@ var AstCoreFactory = class {
51
52
  if (filtered.length === 0) {
52
53
  return this.gen();
53
54
  }
54
- const first2 = filtered[0];
55
+ const first2 = filtered.at(0);
55
56
  const last2 = filtered.at(-1);
56
57
  return {
57
58
  sourceLocationType: "source",
@@ -1526,8 +1527,8 @@ var Promise2 = getNative_default(root_default, "Promise");
1526
1527
  var Promise_default = Promise2;
1527
1528
 
1528
1529
  // ../../node_modules/lodash-es/_Set.js
1529
- var Set2 = getNative_default(root_default, "Set");
1530
- var Set_default = Set2;
1530
+ var Set = getNative_default(root_default, "Set");
1531
+ var Set_default = Set;
1531
1532
 
1532
1533
  // ../../node_modules/lodash-es/_getTag.js
1533
1534
  var mapTag2 = "[object Map]";
@@ -9395,13 +9396,16 @@ var DynamicGenerator = class {
9395
9396
  __context = void 0;
9396
9397
  origSource = "";
9397
9398
  generatedUntil = 0;
9398
- expectsSpace;
9399
+ toEnsure = [];
9400
+ /**
9401
+ * Should not contain empty strings
9402
+ * @protected
9403
+ */
9399
9404
  stringBuilder = [];
9400
9405
  constructor(rules) {
9401
9406
  this.rules = rules;
9402
9407
  for (const rule of Object.values(rules)) {
9403
9408
  this[rule.name] = ((input, context, args) => {
9404
- this.expectsSpace = false;
9405
9409
  this.stringBuilder.length = 0;
9406
9410
  this.origSource = context.origSource;
9407
9411
  this.generatedUntil = context?.offset ?? 0;
@@ -9426,12 +9430,15 @@ var DynamicGenerator = class {
9426
9430
  const generate = () => def.gImpl({
9427
9431
  SUBRULE: this.subrule,
9428
9432
  PRINT: this.print,
9429
- PRINT_SPACE_LEFT: this.printSpaceLeft,
9433
+ ENSURE: this.ensure,
9434
+ ENSURE_EITHER: this.ensureEither,
9435
+ NEW_LINE: this.newLine,
9436
+ HANDLE_LOC: this.handleLoc,
9437
+ CATCHUP: this.catchup,
9430
9438
  PRINT_WORD: this.printWord,
9431
9439
  PRINT_WORDS: this.printWords,
9432
9440
  PRINT_ON_EMPTY: this.printOnEmpty,
9433
- CATCHUP: this.catchup,
9434
- HANDLE_LOC: this.handleLoc
9441
+ PRINT_ON_OWN_LINE: this.printOnOwnLine
9435
9442
  })(ast, this.getSafeContext(), ...arg);
9436
9443
  if (this.factory.isLocalized(ast)) {
9437
9444
  this.handleLoc(ast, generate);
@@ -9469,43 +9476,82 @@ var DynamicGenerator = class {
9469
9476
  }
9470
9477
  this.generatedUntil = Math.max(this.generatedUntil, until);
9471
9478
  };
9479
+ handeEnsured(toPrint) {
9480
+ for (const callBack of this.toEnsure) {
9481
+ callBack(toPrint);
9482
+ }
9483
+ this.toEnsure.length = 0;
9484
+ }
9472
9485
  print = (...args) => {
9473
- const pureArgs = args.filter((x) => x.length > 0);
9474
- if (pureArgs.length > 0) {
9475
- const head2 = pureArgs[0];
9476
- if (this.expectsSpace) {
9477
- this.expectsSpace = false;
9478
- const blanks = /* @__PURE__ */ new Set(["\n", " ", " "]);
9479
- if (this.stringBuilder.length > 0 && !(blanks.has(head2[0]) || blanks.has(this.stringBuilder.at(-1).at(-1)))) {
9480
- this.stringBuilder.push(" ");
9486
+ const joined = args.join("");
9487
+ this.handeEnsured(joined);
9488
+ this.stringBuilder.push(joined);
9489
+ };
9490
+ doesEndWith(subsStr) {
9491
+ const len = subsStr.length;
9492
+ let temp = "";
9493
+ while (temp.length < len && this.stringBuilder.length > 0) {
9494
+ temp = this.stringBuilder.pop() + temp;
9495
+ }
9496
+ this.stringBuilder.push(temp);
9497
+ return temp.endsWith(subsStr);
9498
+ }
9499
+ ensure = (...args) => {
9500
+ const toEnsure = args.join("");
9501
+ if (!this.doesEndWith(toEnsure)) {
9502
+ this.toEnsure.push((willPrint) => {
9503
+ if (!willPrint.startsWith(toEnsure) && !this.doesEndWith(toEnsure)) {
9504
+ this.stringBuilder.push(toEnsure);
9481
9505
  }
9482
- }
9483
- const context = this.getSafeContext();
9484
- if (context[traqulaIndentation] && typeof context[traqulaIndentation] === "number") {
9485
- const indent = context[traqulaIndentation];
9486
- for (const str of pureArgs) {
9487
- const [noNl, ...postNl] = str.split("\n");
9488
- this.stringBuilder.push(noNl);
9489
- for (const subStr of postNl.map((line) => line.trimStart())) {
9490
- this.stringBuilder.push("\n", " ".repeat(indent));
9491
- if (subStr.length > 0) {
9492
- this.stringBuilder.push(subStr);
9493
- }
9494
- }
9506
+ });
9507
+ }
9508
+ };
9509
+ ensureEither = (...args) => {
9510
+ if (args.length === 1) {
9511
+ this.ensure(...args);
9512
+ } else if (args.length > 1 && // Not already matched?
9513
+ !args.some((subStr) => this.doesEndWith(subStr))) {
9514
+ this.toEnsure.push((willPrint) => {
9515
+ if (!args.some((subStr) => willPrint.startsWith(subStr)) && !args.some((subStr) => this.doesEndWith(subStr))) {
9516
+ this.stringBuilder.push(args[0]);
9495
9517
  }
9518
+ });
9519
+ }
9520
+ };
9521
+ pruneEndingBlanks() {
9522
+ let temp = "";
9523
+ while (/^[ \t]*$/u.test(temp) && this.stringBuilder.length > 0) {
9524
+ temp = this.stringBuilder.pop() + temp;
9525
+ }
9526
+ this.print(temp.trimEnd());
9527
+ }
9528
+ newLine = (arg) => {
9529
+ const indentation = this.getSafeContext()[traqulaIndentation] ?? 0;
9530
+ if (indentation === -1) {
9531
+ return;
9532
+ }
9533
+ const force = arg?.force ?? false;
9534
+ this.pruneEndingBlanks();
9535
+ if (force) {
9536
+ this.print("\n", " ".repeat(indentation));
9537
+ } else {
9538
+ let temp = "";
9539
+ while (!temp.includes("\n") && this.stringBuilder.length > 0) {
9540
+ temp = this.stringBuilder.pop() + temp;
9541
+ }
9542
+ if (/\n[ \t]*$/u.test(temp)) {
9543
+ temp = temp.replace(/\n[ \t]*$/u, `
9544
+ ${" ".repeat(indentation)}`);
9545
+ this.print(temp);
9496
9546
  } else {
9497
- this.stringBuilder.push(...pureArgs);
9547
+ this.print(temp, "\n", " ".repeat(indentation));
9498
9548
  }
9499
9549
  }
9500
9550
  };
9501
9551
  printWord = (...args) => {
9502
- this.expectsSpace = true;
9503
- this.print(...args);
9504
- this.expectsSpace = true;
9505
- };
9506
- printSpaceLeft = (...args) => {
9507
- this.expectsSpace = true;
9552
+ this.ensureEither(" ", "\n");
9508
9553
  this.print(...args);
9554
+ this.ensureEither(" ", "\n");
9509
9555
  };
9510
9556
  printWords = (...args) => {
9511
9557
  for (const arg of args) {
@@ -9513,28 +9559,13 @@ var DynamicGenerator = class {
9513
9559
  }
9514
9560
  };
9515
9561
  printOnEmpty = (...args) => {
9516
- let counter = this.stringBuilder.length - 1;
9517
- let onEmpty = true;
9518
- const isEmptyTest = /^[ \t\n]*$/u;
9519
- while (counter >= 0 && onEmpty) {
9520
- const cur = this.stringBuilder[counter];
9521
- const indexOfNl = cur.lastIndexOf("\n");
9522
- if (indexOfNl >= 0) {
9523
- onEmpty = isEmptyTest.test(cur.slice(indexOfNl));
9524
- if (onEmpty) {
9525
- const newVal = cur.slice(0, indexOfNl);
9526
- if (newVal) {
9527
- this.stringBuilder[counter] = cur.slice(0, indexOfNl);
9528
- } else {
9529
- this.stringBuilder.splice(counter, 1);
9530
- }
9531
- }
9532
- break;
9533
- }
9534
- onEmpty = isEmptyTest.test(cur);
9535
- counter--;
9536
- }
9537
- this.print("\n", ...args);
9562
+ this.newLine();
9563
+ this.print(...args);
9564
+ };
9565
+ printOnOwnLine = (...args) => {
9566
+ this.newLine();
9567
+ this.print(...args);
9568
+ this.newLine();
9538
9569
  };
9539
9570
  };
9540
9571
 
@@ -9600,6 +9631,9 @@ var GeneratorBuilder = class _GeneratorBuilder {
9600
9631
  delete this.rules[ruleName];
9601
9632
  return this;
9602
9633
  }
9634
+ getRule(ruleName) {
9635
+ return this.rules[ruleName];
9636
+ }
9603
9637
  /**
9604
9638
  * Merge this grammar GeneratorBuilder with another.
9605
9639
  * It is best to merge the bigger grammar with the smaller one.
@@ -9729,6 +9763,9 @@ var IndirBuilder = class _IndirBuilder {
9729
9763
  delete this.rules[ruleName];
9730
9764
  return this;
9731
9765
  }
9766
+ getRule(ruleName) {
9767
+ return this.rules[ruleName];
9768
+ }
9732
9769
  build() {
9733
9770
  return new DynamicIndirect(this.rules);
9734
9771
  }
@@ -10010,6 +10047,9 @@ var ParserBuilder = class _ParserBuilder {
10010
10047
  delete this.rules[ruleName];
10011
10048
  return this;
10012
10049
  }
10050
+ getRule(ruleName) {
10051
+ return this.rules[ruleName];
10052
+ }
10013
10053
  /**
10014
10054
  * Merge this grammar builder with another.
10015
10055
  * It is best to merge the bigger grammar with the smaller one.
@@ -10096,21 +10136,34 @@ ${firstError.message}`);
10096
10136
  }
10097
10137
  };
10098
10138
 
10099
- // lib/Transformers.js
10100
- var TransformerType = class {
10101
- clone(obj) {
10102
- const newObj = Object.create(Object.getPrototypeOf(obj));
10103
- Object.defineProperties(newObj, Object.getOwnPropertyDescriptors(obj));
10104
- return newObj;
10139
+ // lib/TransformerObject.js
10140
+ var TransformerObject = class _TransformerObject {
10141
+ defaultContext;
10142
+ maxStackSize = 1e6;
10143
+ /**
10144
+ * Creates stateless transformer.
10145
+ * @param defaultContext
10146
+ */
10147
+ constructor(defaultContext = {}) {
10148
+ this.defaultContext = defaultContext;
10105
10149
  }
10106
- safeObjectVisit(value, mapper) {
10107
- if (value && typeof value === "object") {
10108
- if (Array.isArray(value)) {
10109
- return value.map((x) => this.safeObjectVisit(x, mapper));
10110
- }
10111
- return mapper(value);
10150
+ clone(newDefaultContext = {}) {
10151
+ return new _TransformerObject({ ...this.defaultContext, ...newDefaultContext });
10152
+ }
10153
+ /**
10154
+ * Function to shallow clone any type.
10155
+ * @param obj
10156
+ * @protected
10157
+ */
10158
+ cloneObj(obj) {
10159
+ if (obj === null || typeof obj !== "object") {
10160
+ return obj;
10112
10161
  }
10113
- return value;
10162
+ const proto = Object.getPrototypeOf(obj);
10163
+ if (proto === Object.prototype || proto === null) {
10164
+ return { ...obj };
10165
+ }
10166
+ return Object.assign(Object.create(proto), obj);
10114
10167
  }
10115
10168
  /**
10116
10169
  * Recursively transforms all objects that are not arrays. Mapper is called on deeper objects first.
@@ -10122,90 +10175,231 @@ var TransformerType = class {
10122
10175
  * - Default false
10123
10176
  */
10124
10177
  transformObject(startObject, mapper, preVisitor = () => ({})) {
10178
+ const defaults2 = this.defaultContext;
10179
+ const defaultCopyFlag = defaults2.copy ?? true;
10180
+ const defaultContinues = defaults2.continue ?? true;
10181
+ const defaultIgnoreKeys = defaults2.ignoreKeys;
10182
+ const defaultShallowKeys = defaults2.shallowKeys;
10183
+ const defaultDidShortCut = defaults2.shortcut ?? false;
10125
10184
  let didShortCut = false;
10126
- const recurse = (curObject) => {
10127
- const copy = this.clone(curObject);
10128
- const context = preVisitor(copy);
10129
- didShortCut = context.shortcut ?? false;
10130
- const continues = context.continue ?? true;
10131
- if (continues && !didShortCut) {
10132
- for (const [key, value] of Object.entries(copy)) {
10133
- if (didShortCut) {
10134
- return copy;
10185
+ const resultWrap = { res: startObject };
10186
+ const stack = [startObject];
10187
+ const stackParent = [resultWrap];
10188
+ const stackParentKey = ["res"];
10189
+ const handleMapperOnLen = [];
10190
+ const mapperCopyStack = [];
10191
+ const mapperOrigStack = [];
10192
+ const mapperParent = [];
10193
+ const mapperParentKey = [];
10194
+ function handleMapper() {
10195
+ while (stack.length === handleMapperOnLen.at(-1)) {
10196
+ handleMapperOnLen.pop();
10197
+ const copyToMap = mapperCopyStack.pop();
10198
+ const origToMap = mapperOrigStack.pop();
10199
+ const parent = mapperParent.pop();
10200
+ const parentKey = mapperParentKey.pop();
10201
+ parent[parentKey] = mapper(copyToMap, origToMap);
10202
+ }
10203
+ }
10204
+ while (stack.length > 0 && stack.length < this.maxStackSize) {
10205
+ const curObject = stack.pop();
10206
+ const curParent = stackParent.pop();
10207
+ const curKey = stackParentKey.pop();
10208
+ if (!didShortCut) {
10209
+ if (Array.isArray(curObject)) {
10210
+ const newArr = [...curObject];
10211
+ handleMapperOnLen.push(stack.length);
10212
+ mapperCopyStack.push(newArr);
10213
+ mapperOrigStack.push(curObject);
10214
+ mapperParent.push(curParent);
10215
+ mapperParentKey.push(curKey);
10216
+ for (let index = curObject.length - 1; index >= 0; index--) {
10217
+ const val = curObject[index];
10218
+ if (val !== null && typeof val === "object") {
10219
+ stack.push(val);
10220
+ stackParent.push(newArr);
10221
+ stackParentKey.push(index.toString());
10222
+ }
10223
+ }
10224
+ handleMapper();
10225
+ continue;
10226
+ }
10227
+ const context = preVisitor(curObject);
10228
+ const copyFlag = context.copy ?? defaultCopyFlag;
10229
+ const continues = context.continue ?? defaultContinues;
10230
+ const ignoreKeys = context.ignoreKeys ?? defaultIgnoreKeys;
10231
+ const shallowKeys = context.shallowKeys ?? defaultShallowKeys;
10232
+ didShortCut = context.shortcut ?? defaultDidShortCut;
10233
+ const copy = copyFlag ? this.cloneObj(curObject) : curObject;
10234
+ handleMapperOnLen.push(stack.length);
10235
+ mapperCopyStack.push(copy);
10236
+ mapperOrigStack.push(curObject);
10237
+ mapperParent.push(curParent);
10238
+ mapperParentKey.push(curKey);
10239
+ if (continues && !didShortCut) {
10240
+ for (const key in copy) {
10241
+ if (!Object.hasOwn(copy, key)) {
10242
+ continue;
10243
+ }
10244
+ const val = copy[key];
10245
+ const onlyShallow = shallowKeys && shallowKeys?.has(key);
10246
+ if (onlyShallow) {
10247
+ copy[key] = this.cloneObj(val);
10248
+ }
10249
+ if (ignoreKeys && ignoreKeys.has(key)) {
10250
+ continue;
10251
+ }
10252
+ if (!onlyShallow && val !== null && typeof val === "object") {
10253
+ stack.push(val);
10254
+ stackParentKey.push(key);
10255
+ stackParent.push(copy);
10256
+ }
10135
10257
  }
10136
- copy[key] = this.safeObjectVisit(value, (obj) => recurse(obj));
10137
10258
  }
10138
10259
  }
10139
- return mapper(copy);
10140
- };
10141
- return recurse(startObject);
10260
+ handleMapper();
10261
+ }
10262
+ if (stack.length >= this.maxStackSize) {
10263
+ throw new Error("Transform object stack overflowed");
10264
+ }
10265
+ handleMapper();
10266
+ return resultWrap.res;
10142
10267
  }
10143
10268
  /**
10144
10269
  * Visitor that visits all objects. Visits deeper objects first.
10145
10270
  */
10146
10271
  visitObject(startObject, visitor, preVisitor = () => ({})) {
10272
+ const defaults2 = this.defaultContext;
10273
+ const defaultContinues = defaults2.continue ?? true;
10274
+ const defaultIgnoreKeys = defaults2.ignoreKeys;
10275
+ const defaultShortcut = defaults2.shortcut ?? false;
10147
10276
  let didShortCut = false;
10148
- const recurse = (curObject) => {
10149
- const context = preVisitor(curObject);
10150
- didShortCut = context.shortcut ?? false;
10151
- const continues = context.continue ?? true;
10152
- if (continues && !didShortCut) {
10153
- for (const value of Object.values(curObject)) {
10154
- if (didShortCut) {
10155
- return;
10277
+ const stack = [startObject];
10278
+ const handleVisitorOnLen = [];
10279
+ const visitorStack = [];
10280
+ function handleVisitor() {
10281
+ while (stack.length === handleVisitorOnLen.at(-1)) {
10282
+ handleVisitorOnLen.pop();
10283
+ const toVisit = visitorStack.pop();
10284
+ visitor(toVisit);
10285
+ }
10286
+ }
10287
+ while (stack.length > 0 && stack.length < this.maxStackSize) {
10288
+ const curObject = stack.pop();
10289
+ if (!didShortCut) {
10290
+ if (Array.isArray(curObject)) {
10291
+ for (let i = curObject.length - 1; i >= 0; i--) {
10292
+ stack.push(curObject[i]);
10293
+ }
10294
+ handleVisitor();
10295
+ continue;
10296
+ }
10297
+ const context = preVisitor(curObject);
10298
+ didShortCut = context.shortcut ?? defaultShortcut;
10299
+ const continues = context.continue ?? defaultContinues;
10300
+ const ignoreKeys = context.ignoreKeys ?? defaultIgnoreKeys;
10301
+ handleVisitorOnLen.push(stack.length);
10302
+ visitorStack.push(curObject);
10303
+ if (continues && !didShortCut) {
10304
+ for (const key in curObject) {
10305
+ if (!Object.hasOwn(curObject, key)) {
10306
+ continue;
10307
+ }
10308
+ if (ignoreKeys && ignoreKeys.has(key)) {
10309
+ continue;
10310
+ }
10311
+ const val = curObject[key];
10312
+ if (val && typeof val === "object") {
10313
+ stack.push(val);
10314
+ }
10156
10315
  }
10157
- this.safeObjectVisit(value, (obj) => recurse(obj));
10158
10316
  }
10159
10317
  }
10160
- visitor(curObject);
10161
- };
10162
- recurse(startObject);
10318
+ handleVisitor();
10319
+ }
10320
+ if (stack.length >= this.maxStackSize) {
10321
+ throw new Error("Transform object stack overflowed");
10322
+ }
10323
+ handleVisitor();
10324
+ }
10325
+ };
10326
+
10327
+ // lib/TransformerTyped.js
10328
+ var TransformerTyped = class _TransformerTyped extends TransformerObject {
10329
+ defaultNodePreVisitor;
10330
+ constructor(defaultContext = {}, defaultNodePreVisitor = {}) {
10331
+ super(defaultContext);
10332
+ this.defaultNodePreVisitor = defaultNodePreVisitor;
10333
+ }
10334
+ clone(newDefaultContext = {}, newDefaultNodePreVisitor = {}) {
10335
+ return new _TransformerTyped({ ...this.defaultContext, ...newDefaultContext }, { ...this.defaultNodePreVisitor, ...newDefaultNodePreVisitor });
10163
10336
  }
10337
+ /**
10338
+ * Transform a single node.
10339
+ * The transformation calls the preVisitor from starting from the startObject.
10340
+ * The preVisitor can dictate whether transformation should be stopped.
10341
+ * Note that stopping the transformation also prevets further copying.
10342
+ * The transformer itself transforms object starting with the deepest one that can be visited.
10343
+ * The transformer callback is performed on a copy of the original.
10344
+ * @param startObject
10345
+ * @param nodeCallBacks
10346
+ */
10164
10347
  transformNode(startObject, nodeCallBacks) {
10165
- const transformWrapper = (curObject) => {
10166
- const casted = curObject;
10348
+ const transformWrapper = (copy, orig) => {
10349
+ let ogTransform;
10350
+ const casted = copy;
10167
10351
  if (casted.type) {
10168
- const ogFunc = nodeCallBacks[casted.type]?.transform;
10169
- if (ogFunc) {
10170
- return ogFunc(casted);
10171
- }
10352
+ ogTransform = nodeCallBacks[casted.type]?.transform;
10172
10353
  }
10173
- return curObject;
10354
+ return ogTransform ? ogTransform(casted, orig) : copy;
10174
10355
  };
10175
- const preTransformWrapper = (curObject) => {
10356
+ const nodeDefaults = this.defaultNodePreVisitor;
10357
+ const preVisitWrapper = (curObject) => {
10358
+ let ogPreVisit;
10359
+ let nodeContext = {};
10176
10360
  const casted = curObject;
10177
10361
  if (casted.type) {
10178
- const ogFunc = nodeCallBacks[casted.type]?.preVisitor;
10179
- if (ogFunc) {
10180
- return ogFunc(casted);
10181
- }
10362
+ ogPreVisit = nodeCallBacks[casted.type]?.preVisitor;
10363
+ nodeContext = nodeDefaults[casted.type] ?? nodeContext;
10182
10364
  }
10183
- return {};
10365
+ return ogPreVisit ? { ...nodeContext, ...ogPreVisit(casted) } : nodeContext;
10184
10366
  };
10185
- return this.transformObject(startObject, transformWrapper, preTransformWrapper);
10367
+ return this.transformObject(startObject, transformWrapper, preVisitWrapper);
10186
10368
  }
10369
+ /**
10370
+ * Similar to {@link this.transformNode}, but without copying the startObject.
10371
+ * The pre-visitor visits starting from the root, going deeper, while the actual visitor goes in reverse.
10372
+ * @param startObject
10373
+ * @param nodeCallBacks
10374
+ */
10187
10375
  visitNode(startObject, nodeCallBacks) {
10188
- const visitWrapper = (curObject) => {
10376
+ const visitorWrapper = (curObject) => {
10189
10377
  const casted = curObject;
10190
10378
  if (casted.type) {
10191
- const ogFunc = nodeCallBacks[casted.type]?.visitor;
10192
- if (ogFunc) {
10193
- ogFunc(casted);
10379
+ const ogTransform = nodeCallBacks[casted.type]?.visitor;
10380
+ if (ogTransform) {
10381
+ ogTransform(casted);
10194
10382
  }
10195
10383
  }
10196
10384
  };
10385
+ const nodeDefaults = this.defaultNodePreVisitor;
10197
10386
  const preVisitWrapper = (curObject) => {
10387
+ let ogPreVisit;
10388
+ let nodeContext = {};
10198
10389
  const casted = curObject;
10199
10390
  if (casted.type) {
10200
- const ogFunc = nodeCallBacks[casted.type]?.preVisitor;
10201
- if (ogFunc) {
10202
- return ogFunc(casted);
10203
- }
10391
+ ogPreVisit = nodeCallBacks[casted.type]?.preVisitor;
10392
+ nodeContext = nodeDefaults[casted.type] ?? nodeContext;
10204
10393
  }
10205
- return {};
10394
+ return ogPreVisit ? { ...nodeContext, ...ogPreVisit(casted) } : nodeContext;
10206
10395
  };
10207
- this.visitObject(startObject, visitWrapper, preVisitWrapper);
10396
+ return this.visitObject(startObject, visitorWrapper, preVisitWrapper);
10208
10397
  }
10398
+ /**
10399
+ * Traverses only selected nodes as returned by the function.
10400
+ * @param currentNode
10401
+ * @param traverse
10402
+ */
10209
10403
  traverseNodes(currentNode, traverse) {
10210
10404
  let didShortCut = false;
10211
10405
  const recurse = (curNode) => {
@@ -10226,11 +10420,27 @@ var TransformerType = class {
10226
10420
  recurse(currentNode);
10227
10421
  }
10228
10422
  };
10229
- var TransformerSubType = class extends TransformerType {
10423
+
10424
+ // lib/TransformerSubTyped.js
10425
+ var TransformerSubTyped = class _TransformerSubTyped extends TransformerTyped {
10426
+ constructor(defaultContext = {}, defaultNodePreVisitor = {}) {
10427
+ super(defaultContext, defaultNodePreVisitor);
10428
+ }
10429
+ clone(newDefaultContext = {}, newDefaultNodePreVisitor = {}) {
10430
+ return new _TransformerSubTyped({ ...this.defaultContext, ...newDefaultContext }, { ...this.defaultNodePreVisitor, ...newDefaultNodePreVisitor });
10431
+ }
10432
+ /**
10433
+ * Shares the functionality and first two arguments with {@link this.transformNode}.
10434
+ * The third argument allows you to also transform based on the subType of objects.
10435
+ * Note that when a callback for the subtype is provided, the callback for the general type is **NOT** executed.
10436
+ * @param startObject
10437
+ * @param nodeCallBacks
10438
+ * @param nodeSpecificCallBacks
10439
+ */
10230
10440
  transformNodeSpecific(startObject, nodeCallBacks, nodeSpecificCallBacks) {
10231
- const transformWrapper = (curObject) => {
10441
+ const transformWrapper = (copy, orig) => {
10232
10442
  let ogTransform;
10233
- const casted = curObject;
10443
+ const casted = copy;
10234
10444
  if (casted.type && casted.subType) {
10235
10445
  const specific = nodeSpecificCallBacks[casted.type];
10236
10446
  if (specific) {
@@ -10240,7 +10450,7 @@ var TransformerSubType = class extends TransformerType {
10240
10450
  ogTransform = nodeCallBacks[casted.type]?.transform;
10241
10451
  }
10242
10452
  }
10243
- return ogTransform ? ogTransform(casted) : curObject;
10453
+ return ogTransform ? ogTransform(casted, orig) : copy;
10244
10454
  };
10245
10455
  const preVisitWrapper = (curObject) => {
10246
10456
  let ogPreVisit;
@@ -10254,12 +10464,13 @@ var TransformerSubType = class extends TransformerType {
10254
10464
  ogPreVisit = nodeCallBacks[casted.type]?.preVisitor;
10255
10465
  }
10256
10466
  }
10257
- return ogPreVisit ? ogPreVisit(casted) : curObject;
10467
+ return ogPreVisit ? ogPreVisit(casted) : {};
10258
10468
  };
10259
10469
  return this.transformObject(startObject, transformWrapper, preVisitWrapper);
10260
10470
  }
10261
10471
  /**
10262
- * When both nodeCallBack and NodeSpecific callBack are matched, will only look at nodeSpecifCallback
10472
+ * Similar to {@link this.visitNode} but also allows you to match based on the subtype of objects.
10473
+ * When both nodeCallBack and NodeSpecific callBack are matched, will only visit nodeSpecifCallback
10263
10474
  */
10264
10475
  visitNodeSpecific(startObject, nodeCallBacks, nodeSpecificCallBacks) {
10265
10476
  const visitWrapper = (curObject) => {
@@ -10290,10 +10501,16 @@ var TransformerSubType = class extends TransformerType {
10290
10501
  ogPreVisit = nodeCallBacks[casted.type]?.preVisitor;
10291
10502
  }
10292
10503
  }
10293
- return ogPreVisit ? ogPreVisit(casted) : curObject;
10504
+ return ogPreVisit ? ogPreVisit(casted) : {};
10294
10505
  };
10295
10506
  this.visitObject(startObject, visitWrapper, preVisitWrapper);
10296
10507
  }
10508
+ /**
10509
+ * Similar to {@link this.traverseNodes} but also allows you to match based on the subtype of objects.
10510
+ * @param currentNode
10511
+ * @param traverseNode
10512
+ * @param traverseSubNode
10513
+ */
10297
10514
  traverseSubNodes(currentNode, traverseNode, traverseSubNode) {
10298
10515
  let didShortCut = false;
10299
10516
  const recurse = (curNode) => {
package/lib/index.d.ts CHANGED
@@ -10,4 +10,6 @@ export * from './parser-builder/ruleDefTypes.js';
10
10
  export * from './utils.js';
11
11
  export * from './AstCoreFactory.js';
12
12
  export * from './nodeTypings.js';
13
- export * from './Transformers.js';
13
+ export { VisitContext, TransformContext, TransformerObject, SelectiveTraversalContext } from './TransformerObject.js';
14
+ export { TransformerTyped, Safeness, SafeWrap } from './TransformerTyped.js';
15
+ export { TransformerSubTyped } from './TransformerSubTyped.js';
package/lib/index.js CHANGED
@@ -15,5 +15,7 @@ export * from './parser-builder/ruleDefTypes.js';
15
15
  export * from './utils.js';
16
16
  export * from './AstCoreFactory.js';
17
17
  export * from './nodeTypings.js';
18
- export * from './Transformers.js';
18
+ export { TransformerObject } from './TransformerObject.js';
19
+ export { TransformerTyped } from './TransformerTyped.js';
20
+ export { TransformerSubTyped } from './TransformerSubTyped.js';
19
21
  //# 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,2BAA2B;AAC3B,cAAc,qCAAqC,CAAC;AACpD,cAAc,yCAAyC,CAAC;AACxD,cAAc,uCAAuC,CAAC;AACtD,6BAA6B;AAC7B,cAAc,kCAAkC,CAAC;AACjD,cAAc,uCAAuC,CAAC;AACtD,uBAAuB;AACvB,cAAc,iCAAiC,CAAC;AAChD,wBAAwB;AACxB,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,uBAAuB;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC","sourcesContent":["// Export generator builder\nexport * from './generator-builder/builderTypes.js';\nexport * from './generator-builder/generatorBuilder.js';\nexport * from './generator-builder/generatorTypes.js';\n// Export Indirection Builder\nexport * from './indirection-builder/helpers.js';\nexport * from './indirection-builder/IndirBuilder.js';\n// Export lexer builder\nexport * from './lexer-builder/LexerBuilder.js';\n// Export parser builder\nexport * from './parser-builder/builderTypes.js';\nexport * from './parser-builder/parserBuilder.js';\nexport * from './parser-builder/ruleDefTypes.js';\n// Export general types\nexport * from './utils.js';\nexport * from './AstCoreFactory.js';\nexport * from './nodeTypings.js';\nexport * from './Transformers.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,cAAc,qCAAqC,CAAC;AACpD,cAAc,yCAAyC,CAAC;AACxD,cAAc,uCAAuC,CAAC;AACtD,6BAA6B;AAC7B,cAAc,kCAAkC,CAAC;AACjD,cAAc,uCAAuC,CAAC;AACtD,uBAAuB;AACvB,cAAc,iCAAiC,CAAC;AAChD,wBAAwB;AACxB,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,uBAAuB;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAkC,iBAAiB,EAA6B,MAAM,wBAAwB,CAAC;AACtH,OAAO,EAAE,gBAAgB,EAAsB,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC","sourcesContent":["// Export generator builder\nexport * from './generator-builder/builderTypes.js';\nexport * from './generator-builder/generatorBuilder.js';\nexport * from './generator-builder/generatorTypes.js';\n// Export Indirection Builder\nexport * from './indirection-builder/helpers.js';\nexport * from './indirection-builder/IndirBuilder.js';\n// Export lexer builder\nexport * from './lexer-builder/LexerBuilder.js';\n// Export parser builder\nexport * from './parser-builder/builderTypes.js';\nexport * from './parser-builder/parserBuilder.js';\nexport * from './parser-builder/ruleDefTypes.js';\n// Export general types\nexport * from './utils.js';\nexport * from './AstCoreFactory.js';\nexport * from './nodeTypings.js';\nexport { VisitContext, TransformContext, TransformerObject, SelectiveTraversalContext } from './TransformerObject.js';\nexport { TransformerTyped, Safeness, SafeWrap } from './TransformerTyped.js';\nexport { TransformerSubTyped } from './TransformerSubTyped.js';\n"]}