@sdeverywhere/parse 0.1.0 → 0.1.2

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/dist/index.cjs CHANGED
@@ -29,11 +29,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/index.ts
30
30
  var src_exports = {};
31
31
  __export(src_exports, {
32
+ canonicalFunctionId: () => canonicalFunctionId,
33
+ canonicalId: () => canonicalId,
34
+ canonicalVarId: () => canonicalVarId,
32
35
  debugPrintExpr: () => debugPrintExpr,
33
36
  parseVensimEquation: () => parseVensimEquation,
34
37
  parseVensimExpr: () => parseVensimExpr,
35
38
  parseVensimModel: () => parseVensimModel,
36
39
  parseVensimSubscriptRange: () => parseVensimSubscriptRange,
40
+ preprocessVensimModel: () => preprocessVensimModel,
37
41
  prettyPrintExpr: () => prettyPrintExpr,
38
42
  printExprStats: () => printExprStats,
39
43
  reduceConditionals: () => reduceConditionals,
@@ -42,6 +46,29 @@ __export(src_exports, {
42
46
  });
43
47
  module.exports = __toCommonJS(src_exports);
44
48
 
49
+ // src/_shared/canonical-id.js
50
+ var reTrailingMark = new RegExp("\\s+!$", "g");
51
+ var reWhitespace = new RegExp("(\\s|_)+", "g");
52
+ var reSpecialChars = new RegExp(`['"\\.,\\-\\$&%\\/\\|()]`, "g");
53
+ function canonicalId(name) {
54
+ return "_" + name.trim().replace(reTrailingMark, "!").replace(reWhitespace, "_").replace(reSpecialChars, "_").toLowerCase();
55
+ }
56
+ function canonicalVarId(name) {
57
+ const m = name.match(/([^[]+)(?:\[([^\]]+)\])?/);
58
+ if (!m) {
59
+ throw new Error(`Invalid variable name: ${name}`);
60
+ }
61
+ let id = canonicalId(m[1]);
62
+ if (m[2]) {
63
+ const subscripts = m[2].split(",").map((x) => canonicalId(x));
64
+ id += `[${subscripts.join(",")}]`;
65
+ }
66
+ return id;
67
+ }
68
+ function canonicalFunctionId(name) {
69
+ return canonicalId(name).toUpperCase();
70
+ }
71
+
45
72
  // src/ast/print-expr.ts
46
73
  var import_assert_never = require("assert-never");
47
74
  function debugPrintExpr(expr, indent = 0) {
@@ -290,14 +317,6 @@ function fullIdForVarRef(varRef) {
290
317
  // src/ast/reduce-expr.ts
291
318
  var import_assert_never2 = require("assert-never");
292
319
 
293
- // src/_shared/names.js
294
- function canonicalName(name) {
295
- return "_" + name.trim().replace(/"/g, "_").replace(/\s+!$/g, "!").replace(/\s/g, "_").replace(/,/g, "_").replace(/-/g, "_").replace(/\./g, "_").replace(/\$/g, "_").replace(/'/g, "_").replace(/&/g, "_").replace(/%/g, "_").replace(/\//g, "_").replace(/\|/g, "_").toLowerCase();
296
- }
297
- function cFunctionName(name) {
298
- return canonicalName(name).toUpperCase();
299
- }
300
-
301
320
  // src/ast/ast-builders.ts
302
321
  function num(value, text) {
303
322
  return {
@@ -673,7 +692,7 @@ var SubscriptRangeReader = class extends import_antlr4_vensim2.ModelVisitor {
673
692
  const ids = ctx.Id();
674
693
  if (ids.length === 1) {
675
694
  const dimName = ids[0].getText();
676
- const dimId = canonicalName(dimName);
695
+ const dimId = canonicalId(dimName);
677
696
  super.visitSubscriptRange(ctx);
678
697
  return {
679
698
  dimName,
@@ -683,7 +702,7 @@ var SubscriptRangeReader = class extends import_antlr4_vensim2.ModelVisitor {
683
702
  subscriptRefs: this.subscriptNames.map((subName) => {
684
703
  return {
685
704
  subName,
686
- subId: canonicalName(subName)
705
+ subId: canonicalId(subName)
687
706
  };
688
707
  }),
689
708
  subscriptMappings: this.subscriptMappings,
@@ -691,9 +710,9 @@ var SubscriptRangeReader = class extends import_antlr4_vensim2.ModelVisitor {
691
710
  };
692
711
  } else if (ids.length === 2) {
693
712
  const dimName = ids[0].getText();
694
- const dimId = canonicalName(dimName);
713
+ const dimId = canonicalId(dimName);
695
714
  const familyName = ids[1].getText();
696
- const familyId = canonicalName(familyName);
715
+ const familyId = canonicalId(familyName);
697
716
  return {
698
717
  dimName,
699
718
  dimId,
@@ -733,11 +752,11 @@ var SubscriptRangeReader = class extends import_antlr4_vensim2.ModelVisitor {
733
752
  super.visitSubscriptMapping(ctx);
734
753
  this.subscriptMappings.push({
735
754
  toDimName,
736
- toDimId: canonicalName(toDimName),
755
+ toDimId: canonicalId(toDimName),
737
756
  subscriptRefs: this.mappedSubscriptNames.map((subName) => {
738
757
  return {
739
758
  subName,
740
- subId: canonicalName(subName)
759
+ subId: canonicalId(subName)
741
760
  };
742
761
  })
743
762
  });
@@ -747,7 +766,7 @@ var SubscriptRangeReader = class extends import_antlr4_vensim2.ModelVisitor {
747
766
  }
748
767
  visitCall(ctx) {
749
768
  const fnName = ctx.Id().getText();
750
- const fnId = cFunctionName(fnName);
769
+ const fnId = canonicalFunctionId(fnName);
751
770
  if (fnId === "_GET_DIRECT_SUBSCRIPT") {
752
771
  super.visitCall(ctx);
753
772
  } else {
@@ -843,7 +862,7 @@ var ExprReader = class extends import_antlr4_vensim3.ModelVisitor {
843
862
  //
844
863
  visitCall(ctx) {
845
864
  const vensimFnName = ctx.Id().getText();
846
- const fnId = cFunctionName(vensimFnName);
865
+ const fnId = canonicalFunctionId(vensimFnName);
847
866
  this.callStack.push({ fn: fnId, args: [] });
848
867
  super.visitCall(ctx);
849
868
  const callInfo = this.callStack.pop();
@@ -866,14 +885,14 @@ var ExprReader = class extends import_antlr4_vensim3.ModelVisitor {
866
885
  }
867
886
  visitVar(ctx) {
868
887
  const vensimVarName = ctx.Id().getText().trim();
869
- const varId = canonicalName(vensimVarName);
888
+ const varId = canonicalId(vensimVarName);
870
889
  this.subscripts = void 0;
871
890
  super.visitVar(ctx);
872
891
  const subscriptNames = this.subscripts;
873
892
  const subscriptRefs = subscriptNames?.map((name) => {
874
893
  return {
875
894
  subName: name,
876
- subId: canonicalName(name)
895
+ subId: canonicalId(name)
877
896
  };
878
897
  });
879
898
  this.subscripts = void 0;
@@ -923,7 +942,7 @@ var ExprReader = class extends import_antlr4_vensim3.ModelVisitor {
923
942
  }
924
943
  visitLookupCall(ctx) {
925
944
  const lookupVarName = ctx.Id().getText();
926
- const lookupVarId = canonicalName(lookupVarName);
945
+ const lookupVarId = canonicalId(lookupVarName);
927
946
  if (ctx.subscriptList()) {
928
947
  ctx.subscriptList().accept(this);
929
948
  }
@@ -931,7 +950,7 @@ var ExprReader = class extends import_antlr4_vensim3.ModelVisitor {
931
950
  const subscriptRefs = subscriptNames?.map((name) => {
932
951
  return {
933
952
  subName: name,
934
- subId: canonicalName(name)
953
+ subId: canonicalId(name)
935
954
  };
936
955
  });
937
956
  this.subscripts = void 0;
@@ -1128,13 +1147,13 @@ var EquationReader = class extends import_antlr4_vensim4.ModelVisitor {
1128
1147
  }
1129
1148
  visitLhs(ctx) {
1130
1149
  const lhsVarName = ctx.Id().getText();
1131
- const lhsVarId = canonicalName(lhsVarName);
1150
+ const lhsVarId = canonicalId(lhsVarName);
1132
1151
  super.visitLhs(ctx);
1133
1152
  const subscriptNames = this.subscripts;
1134
1153
  const subscriptRefs = subscriptNames?.map((name) => {
1135
1154
  return {
1136
1155
  subName: name,
1137
- subId: canonicalName(name)
1156
+ subId: canonicalId(name)
1138
1157
  };
1139
1158
  });
1140
1159
  const exceptSubscriptSets = this.exceptSubscriptSets;
@@ -1142,7 +1161,7 @@ var EquationReader = class extends import_antlr4_vensim4.ModelVisitor {
1142
1161
  return subscriptSet.map((name) => {
1143
1162
  return {
1144
1163
  subName: name,
1145
- subId: canonicalName(name)
1164
+ subId: canonicalId(name)
1146
1165
  };
1147
1166
  });
1148
1167
  });
@@ -1222,16 +1241,41 @@ function parseVensimEquation(input) {
1222
1241
 
1223
1242
  // src/vensim/preprocess-vensim.ts
1224
1243
  var import_split_string = __toESM(require("split-string"), 1);
1225
- function preprocessVensimModel(input) {
1244
+ function preprocessVensimModel(input, options) {
1245
+ const removalKeys = options?.removalKeys;
1246
+ function shouldRemove(text) {
1247
+ if (text.includes("TABBED ARRAY")) {
1248
+ return true;
1249
+ }
1250
+ if (removalKeys) {
1251
+ for (const key of removalKeys) {
1252
+ if (text.includes(key)) {
1253
+ return true;
1254
+ }
1255
+ }
1256
+ }
1257
+ return false;
1258
+ }
1259
+ const macrosResult = removeMacros(input);
1260
+ input = macrosResult.processed;
1226
1261
  const rawDefs = splitDefs(input);
1227
1262
  const vensimDefs = [];
1263
+ const removedBlocks = [];
1228
1264
  for (const rawDef of rawDefs) {
1265
+ if (shouldRemove(rawDef.text)) {
1266
+ removedBlocks.push(rawDef.text.trim() + "|");
1267
+ continue;
1268
+ }
1229
1269
  const vensimDef = processDef(rawDef);
1230
1270
  if (vensimDef) {
1231
1271
  vensimDefs.push(vensimDef);
1232
1272
  }
1233
1273
  }
1234
- return vensimDefs;
1274
+ return {
1275
+ defs: vensimDefs,
1276
+ removedMacros: macrosResult.removed,
1277
+ removedBlocks
1278
+ };
1235
1279
  }
1236
1280
  function splitDefs(input) {
1237
1281
  const defTexts = (0, import_split_string.default)(input, { separator: "|", quotes: ['"'], keep: () => true });
@@ -1273,6 +1317,9 @@ function splitDefs(input) {
1273
1317
  function splitLines(input) {
1274
1318
  return input.split(/\r\n|\n|\r/);
1275
1319
  }
1320
+ function splitExceptInQuoted(input, sep) {
1321
+ return (0, import_split_string.default)(input, { separator: sep, quotes: ['"'] });
1322
+ }
1276
1323
  function processBackslashes(input) {
1277
1324
  const inputLines = splitLines(input);
1278
1325
  let output = "";
@@ -1318,22 +1365,27 @@ function replaceDelimitedStrings(str, open, close, newStr) {
1318
1365
  function reduceWhitespace(input) {
1319
1366
  return input.replace(/\s\s+/g, " ").trim();
1320
1367
  }
1368
+ var reWhitespace2 = new RegExp("(\\s|_)+", "g");
1321
1369
  function keyForDef(def) {
1322
1370
  let key = def;
1323
1371
  key = key.replace(/:INTERPOLATE:/g, "");
1372
+ let kind;
1324
1373
  if (key.includes("=")) {
1374
+ kind = "eqn";
1325
1375
  key = key.split("=")[0].trim();
1326
1376
  } else if (key.includes(":")) {
1377
+ kind = "dim";
1327
1378
  key = key.split(":")[0].trim();
1328
1379
  } else {
1380
+ kind = "decl";
1329
1381
  }
1382
+ key = splitExceptInQuoted(key, "(")[0];
1330
1383
  key = key.replace(/"/g, "");
1331
- key = key.split("(")[0];
1332
1384
  key = key.trim();
1333
- key = key.replace(/\[\s*/g, "[");
1334
- key = key.replace(/\s*\]/g, "]");
1385
+ key = key.replace(/(?<=\[).*?(?=\])/g, (match) => match.replace(/\s/g, ""));
1386
+ key = key.replace(reWhitespace2, "_");
1335
1387
  key = key.toLowerCase();
1336
- return key;
1388
+ return { key, kind };
1337
1389
  }
1338
1390
  function processDef(rawDef) {
1339
1391
  let input = rawDef.text;
@@ -1351,7 +1403,7 @@ function processDef(rawDef) {
1351
1403
  ${input}`);
1352
1404
  }
1353
1405
  const rawDefText = reduceWhitespace(parts[0]);
1354
- const key = keyForDef(rawDefText);
1406
+ const { key, kind } = keyForDef(rawDefText);
1355
1407
  const def = `${rawDefText} ~~|`;
1356
1408
  const units = reduceWhitespace(parts[1]);
1357
1409
  const comment = reduceWhitespace(parts[2]);
@@ -1359,12 +1411,25 @@ ${input}`);
1359
1411
  return {
1360
1412
  key,
1361
1413
  def,
1414
+ kind,
1362
1415
  line: rawDef.line,
1363
1416
  units,
1364
1417
  comment,
1365
1418
  ...group ? { group } : {}
1366
1419
  };
1367
1420
  }
1421
+ function removeMacros(input) {
1422
+ const removed = [];
1423
+ const processed = input.replace(/:MACRO:.*:END OF MACRO:/gms, (match) => {
1424
+ removed.push(match);
1425
+ const numBreaks = match.split(/\r\n|\n|\r/gms).length - 1;
1426
+ return numBreaks > 0 ? "\n".repeat(numBreaks) : "";
1427
+ });
1428
+ return {
1429
+ processed,
1430
+ removed
1431
+ };
1432
+ }
1368
1433
 
1369
1434
  // src/vensim/impl/model-reader.js
1370
1435
  var import_antlr4_vensim5 = require("antlr4-vensim");
@@ -1423,7 +1488,7 @@ var ModelReader = class extends import_antlr4_vensim5.ModelVisitor {
1423
1488
  function parseVensimModel(input, context, sort = false) {
1424
1489
  const dimensions = [];
1425
1490
  const equations = [];
1426
- const defs = preprocessVensimModel(input);
1491
+ const { defs } = preprocessVensimModel(input);
1427
1492
  if (sort) {
1428
1493
  defs.sort((a, b) => {
1429
1494
  return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
@@ -1476,11 +1541,15 @@ Detail:
1476
1541
  }
1477
1542
  // Annotate the CommonJS export names for ESM import in node:
1478
1543
  0 && (module.exports = {
1544
+ canonicalFunctionId,
1545
+ canonicalId,
1546
+ canonicalVarId,
1479
1547
  debugPrintExpr,
1480
1548
  parseVensimEquation,
1481
1549
  parseVensimExpr,
1482
1550
  parseVensimModel,
1483
1551
  parseVensimSubscriptRange,
1552
+ preprocessVensimModel,
1484
1553
  prettyPrintExpr,
1485
1554
  printExprStats,
1486
1555
  reduceConditionals,