@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 +100 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -1
- package/dist/index.d.ts +117 -1
- package/dist/index.js +96 -31
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a model variable or subscript/dimension name into a valid C identifier (with
|
|
3
|
+
* special characters converted to underscore).
|
|
4
|
+
*
|
|
5
|
+
* Note that this should only be called with an individual variable base name (e.g.,
|
|
6
|
+
* 'Variable name') or a subscript/dimension name (e.g., 'DimA'). In the case where
|
|
7
|
+
* you have a full variable name that includes subscripts/dimensions (e.g.,
|
|
8
|
+
* 'Variable name[DimA,B2]'), use `canonicalVarId` to convert the base variable name
|
|
9
|
+
* and subscript/dimension parts to canonical form indepdendently.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} name The name of the variable in the source model, e.g., "Variable name".
|
|
12
|
+
* @returns {string} The C identifier for the given name, e.g., "_variable_name".
|
|
13
|
+
*/
|
|
14
|
+
declare function canonicalId(name: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Format a (subscripted or non-subscripted) model variable name into a canonical identifier,
|
|
17
|
+
* (with special characters converted to underscore, and subscript/dimension parts separated
|
|
18
|
+
* by commas).
|
|
19
|
+
*
|
|
20
|
+
* @param {string} name The name of the variable in the source model, e.g., "Variable name[DimA, B2]".
|
|
21
|
+
* @returns {string} The canonical identifier for the given name, e.g., "_variable_name[_dima,_b2]".
|
|
22
|
+
*/
|
|
23
|
+
declare function canonicalVarId(name: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Format a model function name into a valid C identifier (with special characters
|
|
26
|
+
* converted to underscore, and the ID converted to uppercase).
|
|
27
|
+
*
|
|
28
|
+
* @param {string} name The name of the variable in the source model, e.g., "FUNCTION name".
|
|
29
|
+
* @returns {string} The C identifier for the given name, e.g., "_FUNCTION_NAME".
|
|
30
|
+
*/
|
|
31
|
+
declare function canonicalFunctionId(name: string): string;
|
|
32
|
+
|
|
1
33
|
/** The original name of a dimension, as it appears in the model. */
|
|
2
34
|
type DimName = string;
|
|
3
35
|
/** The canonical identifier of a dimension, as it appears in generated code. */
|
|
@@ -442,4 +474,88 @@ declare function parseVensimEquation(input: string): Equation;
|
|
|
442
474
|
*/
|
|
443
475
|
declare function parseVensimModel(input: string, context?: VensimParseContext, sort?: boolean): Model;
|
|
444
476
|
|
|
445
|
-
|
|
477
|
+
/**
|
|
478
|
+
* A single Vensim definition (either a subscript range definition or an
|
|
479
|
+
* equation definition). This contains the definition's text and metadata
|
|
480
|
+
* that was extracted during preprocessing.
|
|
481
|
+
*/
|
|
482
|
+
interface VensimDef {
|
|
483
|
+
/**
|
|
484
|
+
* A simplified key for the LHS of the definition, used for sorting
|
|
485
|
+
* and/or flattening.
|
|
486
|
+
*/
|
|
487
|
+
key: string;
|
|
488
|
+
/**
|
|
489
|
+
* The preprocessed equation or subscript range definition (with
|
|
490
|
+
* units and comment replaced with `~~|`).
|
|
491
|
+
*/
|
|
492
|
+
def: string;
|
|
493
|
+
/**
|
|
494
|
+
* The kind of definition; either 'eqn' for an equation containing an equals
|
|
495
|
+
* sign, 'dim' for a dimension (subscript range) definition, or 'decl' for
|
|
496
|
+
* all other declarations (e.g., a lookup or data variable definition).
|
|
497
|
+
*/
|
|
498
|
+
kind: 'eqn' | 'dim' | 'decl';
|
|
499
|
+
/**
|
|
500
|
+
* The (1-based) line number where the definition begins.
|
|
501
|
+
*/
|
|
502
|
+
line: number;
|
|
503
|
+
/**
|
|
504
|
+
* The units text.
|
|
505
|
+
*/
|
|
506
|
+
units: string;
|
|
507
|
+
/**
|
|
508
|
+
* The comment text.
|
|
509
|
+
*/
|
|
510
|
+
comment: string;
|
|
511
|
+
/**
|
|
512
|
+
* The optional group name, if the definition is contained within a group.
|
|
513
|
+
*/
|
|
514
|
+
group?: string;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Result type for the `preprocessVensimModel` function.
|
|
518
|
+
*/
|
|
519
|
+
interface PreprocessedVensimModel {
|
|
520
|
+
/**
|
|
521
|
+
* The preprocessed definitions that were preserved.
|
|
522
|
+
*/
|
|
523
|
+
defs: VensimDef[];
|
|
524
|
+
/**
|
|
525
|
+
* The macros that were removed by the preprocessor.
|
|
526
|
+
*/
|
|
527
|
+
removedMacros: string[];
|
|
528
|
+
/**
|
|
529
|
+
* The text blocks that were removed by the preprocessor. These include
|
|
530
|
+
* unsupported functions (such as `TABBED ARRAY`) and other definitions
|
|
531
|
+
* that were requested for removal.
|
|
532
|
+
*/
|
|
533
|
+
removedBlocks: string[];
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Process the given Vensim model content so that it can be parsed
|
|
537
|
+
* by `antlr4-vensim`. This will:
|
|
538
|
+
* - strip out group markers
|
|
539
|
+
* - remove macro definitions, which are currently unsupported
|
|
540
|
+
* - remove equations that reference certain unsupported functions
|
|
541
|
+
* (e.g., `TABBED ARRAY`)
|
|
542
|
+
* - remove everything in the private Vensim sketch section
|
|
543
|
+
* - join lines that are separated by a continuation (backslash)
|
|
544
|
+
* - split the input into distinct definitions (equations and
|
|
545
|
+
* subscript ranges)
|
|
546
|
+
*
|
|
547
|
+
* The definitions are further processed to preserve the units and
|
|
548
|
+
* comment text in separate properties, but strips them from the
|
|
549
|
+
* equation string (replaced with `~~`) to make it easier for
|
|
550
|
+
* `antlr4-vensim` to process.
|
|
551
|
+
*
|
|
552
|
+
* @param input The original Vensim mdl file content.
|
|
553
|
+
* @param options The options that control preprocessing.
|
|
554
|
+
* @return A `PreprocessedVensimModel` instance containing the preprocessed
|
|
555
|
+
* Vensim definitions.
|
|
556
|
+
*/
|
|
557
|
+
declare function preprocessVensimModel(input: string, options?: {
|
|
558
|
+
removalKeys?: string[];
|
|
559
|
+
}): PreprocessedVensimModel;
|
|
560
|
+
|
|
561
|
+
export { type BinaryOp, type BinaryOpExpr, type DimId, type DimName, type DimOrSubId, type DimOrSubName, type DimensionDef, type Equation, type EquationLhs, type EquationRhs, type EquationRhsConstList, type EquationRhsData, type EquationRhsExpr, type EquationRhsLookup, type Expr, type FormatVariableRefFunc, type FunctionCall, type FunctionId, type FunctionName, type Keyword, type LookupCall, type LookupDef, type LookupPoint, type LookupRange, type Model, type NumberLiteral, type ParensExpr, type PreprocessedVensimModel, type PrettyOpts, type ReduceExprOptions, type StringLiteral, type SubId, type SubName, type SubscriptMapping, type SubscriptRef, type UnaryOp, type UnaryOpExpr, type VariableDef, type VariableId, type VariableName, type VariableRef, type VensimDef, type VensimParseContext, canonicalFunctionId, canonicalId, canonicalVarId, debugPrintExpr, parseVensimEquation, parseVensimExpr, parseVensimModel, parseVensimSubscriptRange, preprocessVensimModel, prettyPrintExpr, printExprStats, reduceConditionals, reduceExpr, toPrettyString };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a model variable or subscript/dimension name into a valid C identifier (with
|
|
3
|
+
* special characters converted to underscore).
|
|
4
|
+
*
|
|
5
|
+
* Note that this should only be called with an individual variable base name (e.g.,
|
|
6
|
+
* 'Variable name') or a subscript/dimension name (e.g., 'DimA'). In the case where
|
|
7
|
+
* you have a full variable name that includes subscripts/dimensions (e.g.,
|
|
8
|
+
* 'Variable name[DimA,B2]'), use `canonicalVarId` to convert the base variable name
|
|
9
|
+
* and subscript/dimension parts to canonical form indepdendently.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} name The name of the variable in the source model, e.g., "Variable name".
|
|
12
|
+
* @returns {string} The C identifier for the given name, e.g., "_variable_name".
|
|
13
|
+
*/
|
|
14
|
+
declare function canonicalId(name: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Format a (subscripted or non-subscripted) model variable name into a canonical identifier,
|
|
17
|
+
* (with special characters converted to underscore, and subscript/dimension parts separated
|
|
18
|
+
* by commas).
|
|
19
|
+
*
|
|
20
|
+
* @param {string} name The name of the variable in the source model, e.g., "Variable name[DimA, B2]".
|
|
21
|
+
* @returns {string} The canonical identifier for the given name, e.g., "_variable_name[_dima,_b2]".
|
|
22
|
+
*/
|
|
23
|
+
declare function canonicalVarId(name: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Format a model function name into a valid C identifier (with special characters
|
|
26
|
+
* converted to underscore, and the ID converted to uppercase).
|
|
27
|
+
*
|
|
28
|
+
* @param {string} name The name of the variable in the source model, e.g., "FUNCTION name".
|
|
29
|
+
* @returns {string} The C identifier for the given name, e.g., "_FUNCTION_NAME".
|
|
30
|
+
*/
|
|
31
|
+
declare function canonicalFunctionId(name: string): string;
|
|
32
|
+
|
|
1
33
|
/** The original name of a dimension, as it appears in the model. */
|
|
2
34
|
type DimName = string;
|
|
3
35
|
/** The canonical identifier of a dimension, as it appears in generated code. */
|
|
@@ -442,4 +474,88 @@ declare function parseVensimEquation(input: string): Equation;
|
|
|
442
474
|
*/
|
|
443
475
|
declare function parseVensimModel(input: string, context?: VensimParseContext, sort?: boolean): Model;
|
|
444
476
|
|
|
445
|
-
|
|
477
|
+
/**
|
|
478
|
+
* A single Vensim definition (either a subscript range definition or an
|
|
479
|
+
* equation definition). This contains the definition's text and metadata
|
|
480
|
+
* that was extracted during preprocessing.
|
|
481
|
+
*/
|
|
482
|
+
interface VensimDef {
|
|
483
|
+
/**
|
|
484
|
+
* A simplified key for the LHS of the definition, used for sorting
|
|
485
|
+
* and/or flattening.
|
|
486
|
+
*/
|
|
487
|
+
key: string;
|
|
488
|
+
/**
|
|
489
|
+
* The preprocessed equation or subscript range definition (with
|
|
490
|
+
* units and comment replaced with `~~|`).
|
|
491
|
+
*/
|
|
492
|
+
def: string;
|
|
493
|
+
/**
|
|
494
|
+
* The kind of definition; either 'eqn' for an equation containing an equals
|
|
495
|
+
* sign, 'dim' for a dimension (subscript range) definition, or 'decl' for
|
|
496
|
+
* all other declarations (e.g., a lookup or data variable definition).
|
|
497
|
+
*/
|
|
498
|
+
kind: 'eqn' | 'dim' | 'decl';
|
|
499
|
+
/**
|
|
500
|
+
* The (1-based) line number where the definition begins.
|
|
501
|
+
*/
|
|
502
|
+
line: number;
|
|
503
|
+
/**
|
|
504
|
+
* The units text.
|
|
505
|
+
*/
|
|
506
|
+
units: string;
|
|
507
|
+
/**
|
|
508
|
+
* The comment text.
|
|
509
|
+
*/
|
|
510
|
+
comment: string;
|
|
511
|
+
/**
|
|
512
|
+
* The optional group name, if the definition is contained within a group.
|
|
513
|
+
*/
|
|
514
|
+
group?: string;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Result type for the `preprocessVensimModel` function.
|
|
518
|
+
*/
|
|
519
|
+
interface PreprocessedVensimModel {
|
|
520
|
+
/**
|
|
521
|
+
* The preprocessed definitions that were preserved.
|
|
522
|
+
*/
|
|
523
|
+
defs: VensimDef[];
|
|
524
|
+
/**
|
|
525
|
+
* The macros that were removed by the preprocessor.
|
|
526
|
+
*/
|
|
527
|
+
removedMacros: string[];
|
|
528
|
+
/**
|
|
529
|
+
* The text blocks that were removed by the preprocessor. These include
|
|
530
|
+
* unsupported functions (such as `TABBED ARRAY`) and other definitions
|
|
531
|
+
* that were requested for removal.
|
|
532
|
+
*/
|
|
533
|
+
removedBlocks: string[];
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Process the given Vensim model content so that it can be parsed
|
|
537
|
+
* by `antlr4-vensim`. This will:
|
|
538
|
+
* - strip out group markers
|
|
539
|
+
* - remove macro definitions, which are currently unsupported
|
|
540
|
+
* - remove equations that reference certain unsupported functions
|
|
541
|
+
* (e.g., `TABBED ARRAY`)
|
|
542
|
+
* - remove everything in the private Vensim sketch section
|
|
543
|
+
* - join lines that are separated by a continuation (backslash)
|
|
544
|
+
* - split the input into distinct definitions (equations and
|
|
545
|
+
* subscript ranges)
|
|
546
|
+
*
|
|
547
|
+
* The definitions are further processed to preserve the units and
|
|
548
|
+
* comment text in separate properties, but strips them from the
|
|
549
|
+
* equation string (replaced with `~~`) to make it easier for
|
|
550
|
+
* `antlr4-vensim` to process.
|
|
551
|
+
*
|
|
552
|
+
* @param input The original Vensim mdl file content.
|
|
553
|
+
* @param options The options that control preprocessing.
|
|
554
|
+
* @return A `PreprocessedVensimModel` instance containing the preprocessed
|
|
555
|
+
* Vensim definitions.
|
|
556
|
+
*/
|
|
557
|
+
declare function preprocessVensimModel(input: string, options?: {
|
|
558
|
+
removalKeys?: string[];
|
|
559
|
+
}): PreprocessedVensimModel;
|
|
560
|
+
|
|
561
|
+
export { type BinaryOp, type BinaryOpExpr, type DimId, type DimName, type DimOrSubId, type DimOrSubName, type DimensionDef, type Equation, type EquationLhs, type EquationRhs, type EquationRhsConstList, type EquationRhsData, type EquationRhsExpr, type EquationRhsLookup, type Expr, type FormatVariableRefFunc, type FunctionCall, type FunctionId, type FunctionName, type Keyword, type LookupCall, type LookupDef, type LookupPoint, type LookupRange, type Model, type NumberLiteral, type ParensExpr, type PreprocessedVensimModel, type PrettyOpts, type ReduceExprOptions, type StringLiteral, type SubId, type SubName, type SubscriptMapping, type SubscriptRef, type UnaryOp, type UnaryOpExpr, type VariableDef, type VariableId, type VariableName, type VariableRef, type VensimDef, type VensimParseContext, canonicalFunctionId, canonicalId, canonicalVarId, debugPrintExpr, parseVensimEquation, parseVensimExpr, parseVensimModel, parseVensimSubscriptRange, preprocessVensimModel, prettyPrintExpr, printExprStats, reduceConditionals, reduceExpr, toPrettyString };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
// src/_shared/canonical-id.js
|
|
2
|
+
var reTrailingMark = new RegExp("\\s+!$", "g");
|
|
3
|
+
var reWhitespace = new RegExp("(\\s|_)+", "g");
|
|
4
|
+
var reSpecialChars = new RegExp(`['"\\.,\\-\\$&%\\/\\|()]`, "g");
|
|
5
|
+
function canonicalId(name) {
|
|
6
|
+
return "_" + name.trim().replace(reTrailingMark, "!").replace(reWhitespace, "_").replace(reSpecialChars, "_").toLowerCase();
|
|
7
|
+
}
|
|
8
|
+
function canonicalVarId(name) {
|
|
9
|
+
const m = name.match(/([^[]+)(?:\[([^\]]+)\])?/);
|
|
10
|
+
if (!m) {
|
|
11
|
+
throw new Error(`Invalid variable name: ${name}`);
|
|
12
|
+
}
|
|
13
|
+
let id = canonicalId(m[1]);
|
|
14
|
+
if (m[2]) {
|
|
15
|
+
const subscripts = m[2].split(",").map((x) => canonicalId(x));
|
|
16
|
+
id += `[${subscripts.join(",")}]`;
|
|
17
|
+
}
|
|
18
|
+
return id;
|
|
19
|
+
}
|
|
20
|
+
function canonicalFunctionId(name) {
|
|
21
|
+
return canonicalId(name).toUpperCase();
|
|
22
|
+
}
|
|
23
|
+
|
|
1
24
|
// src/ast/print-expr.ts
|
|
2
25
|
import { assertNever } from "assert-never";
|
|
3
26
|
function debugPrintExpr(expr, indent = 0) {
|
|
@@ -246,14 +269,6 @@ function fullIdForVarRef(varRef) {
|
|
|
246
269
|
// src/ast/reduce-expr.ts
|
|
247
270
|
import { assertNever as assertNever2 } from "assert-never";
|
|
248
271
|
|
|
249
|
-
// src/_shared/names.js
|
|
250
|
-
function canonicalName(name) {
|
|
251
|
-
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();
|
|
252
|
-
}
|
|
253
|
-
function cFunctionName(name) {
|
|
254
|
-
return canonicalName(name).toUpperCase();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
272
|
// src/ast/ast-builders.ts
|
|
258
273
|
function num(value, text) {
|
|
259
274
|
return {
|
|
@@ -629,7 +644,7 @@ var SubscriptRangeReader = class extends ModelVisitor {
|
|
|
629
644
|
const ids = ctx.Id();
|
|
630
645
|
if (ids.length === 1) {
|
|
631
646
|
const dimName = ids[0].getText();
|
|
632
|
-
const dimId =
|
|
647
|
+
const dimId = canonicalId(dimName);
|
|
633
648
|
super.visitSubscriptRange(ctx);
|
|
634
649
|
return {
|
|
635
650
|
dimName,
|
|
@@ -639,7 +654,7 @@ var SubscriptRangeReader = class extends ModelVisitor {
|
|
|
639
654
|
subscriptRefs: this.subscriptNames.map((subName) => {
|
|
640
655
|
return {
|
|
641
656
|
subName,
|
|
642
|
-
subId:
|
|
657
|
+
subId: canonicalId(subName)
|
|
643
658
|
};
|
|
644
659
|
}),
|
|
645
660
|
subscriptMappings: this.subscriptMappings,
|
|
@@ -647,9 +662,9 @@ var SubscriptRangeReader = class extends ModelVisitor {
|
|
|
647
662
|
};
|
|
648
663
|
} else if (ids.length === 2) {
|
|
649
664
|
const dimName = ids[0].getText();
|
|
650
|
-
const dimId =
|
|
665
|
+
const dimId = canonicalId(dimName);
|
|
651
666
|
const familyName = ids[1].getText();
|
|
652
|
-
const familyId =
|
|
667
|
+
const familyId = canonicalId(familyName);
|
|
653
668
|
return {
|
|
654
669
|
dimName,
|
|
655
670
|
dimId,
|
|
@@ -689,11 +704,11 @@ var SubscriptRangeReader = class extends ModelVisitor {
|
|
|
689
704
|
super.visitSubscriptMapping(ctx);
|
|
690
705
|
this.subscriptMappings.push({
|
|
691
706
|
toDimName,
|
|
692
|
-
toDimId:
|
|
707
|
+
toDimId: canonicalId(toDimName),
|
|
693
708
|
subscriptRefs: this.mappedSubscriptNames.map((subName) => {
|
|
694
709
|
return {
|
|
695
710
|
subName,
|
|
696
|
-
subId:
|
|
711
|
+
subId: canonicalId(subName)
|
|
697
712
|
};
|
|
698
713
|
})
|
|
699
714
|
});
|
|
@@ -703,7 +718,7 @@ var SubscriptRangeReader = class extends ModelVisitor {
|
|
|
703
718
|
}
|
|
704
719
|
visitCall(ctx) {
|
|
705
720
|
const fnName = ctx.Id().getText();
|
|
706
|
-
const fnId =
|
|
721
|
+
const fnId = canonicalFunctionId(fnName);
|
|
707
722
|
if (fnId === "_GET_DIRECT_SUBSCRIPT") {
|
|
708
723
|
super.visitCall(ctx);
|
|
709
724
|
} else {
|
|
@@ -799,7 +814,7 @@ var ExprReader = class extends ModelVisitor2 {
|
|
|
799
814
|
//
|
|
800
815
|
visitCall(ctx) {
|
|
801
816
|
const vensimFnName = ctx.Id().getText();
|
|
802
|
-
const fnId =
|
|
817
|
+
const fnId = canonicalFunctionId(vensimFnName);
|
|
803
818
|
this.callStack.push({ fn: fnId, args: [] });
|
|
804
819
|
super.visitCall(ctx);
|
|
805
820
|
const callInfo = this.callStack.pop();
|
|
@@ -822,14 +837,14 @@ var ExprReader = class extends ModelVisitor2 {
|
|
|
822
837
|
}
|
|
823
838
|
visitVar(ctx) {
|
|
824
839
|
const vensimVarName = ctx.Id().getText().trim();
|
|
825
|
-
const varId =
|
|
840
|
+
const varId = canonicalId(vensimVarName);
|
|
826
841
|
this.subscripts = void 0;
|
|
827
842
|
super.visitVar(ctx);
|
|
828
843
|
const subscriptNames = this.subscripts;
|
|
829
844
|
const subscriptRefs = subscriptNames?.map((name) => {
|
|
830
845
|
return {
|
|
831
846
|
subName: name,
|
|
832
|
-
subId:
|
|
847
|
+
subId: canonicalId(name)
|
|
833
848
|
};
|
|
834
849
|
});
|
|
835
850
|
this.subscripts = void 0;
|
|
@@ -879,7 +894,7 @@ var ExprReader = class extends ModelVisitor2 {
|
|
|
879
894
|
}
|
|
880
895
|
visitLookupCall(ctx) {
|
|
881
896
|
const lookupVarName = ctx.Id().getText();
|
|
882
|
-
const lookupVarId =
|
|
897
|
+
const lookupVarId = canonicalId(lookupVarName);
|
|
883
898
|
if (ctx.subscriptList()) {
|
|
884
899
|
ctx.subscriptList().accept(this);
|
|
885
900
|
}
|
|
@@ -887,7 +902,7 @@ var ExprReader = class extends ModelVisitor2 {
|
|
|
887
902
|
const subscriptRefs = subscriptNames?.map((name) => {
|
|
888
903
|
return {
|
|
889
904
|
subName: name,
|
|
890
|
-
subId:
|
|
905
|
+
subId: canonicalId(name)
|
|
891
906
|
};
|
|
892
907
|
});
|
|
893
908
|
this.subscripts = void 0;
|
|
@@ -1084,13 +1099,13 @@ var EquationReader = class extends ModelVisitor3 {
|
|
|
1084
1099
|
}
|
|
1085
1100
|
visitLhs(ctx) {
|
|
1086
1101
|
const lhsVarName = ctx.Id().getText();
|
|
1087
|
-
const lhsVarId =
|
|
1102
|
+
const lhsVarId = canonicalId(lhsVarName);
|
|
1088
1103
|
super.visitLhs(ctx);
|
|
1089
1104
|
const subscriptNames = this.subscripts;
|
|
1090
1105
|
const subscriptRefs = subscriptNames?.map((name) => {
|
|
1091
1106
|
return {
|
|
1092
1107
|
subName: name,
|
|
1093
|
-
subId:
|
|
1108
|
+
subId: canonicalId(name)
|
|
1094
1109
|
};
|
|
1095
1110
|
});
|
|
1096
1111
|
const exceptSubscriptSets = this.exceptSubscriptSets;
|
|
@@ -1098,7 +1113,7 @@ var EquationReader = class extends ModelVisitor3 {
|
|
|
1098
1113
|
return subscriptSet.map((name) => {
|
|
1099
1114
|
return {
|
|
1100
1115
|
subName: name,
|
|
1101
|
-
subId:
|
|
1116
|
+
subId: canonicalId(name)
|
|
1102
1117
|
};
|
|
1103
1118
|
});
|
|
1104
1119
|
});
|
|
@@ -1178,16 +1193,41 @@ function parseVensimEquation(input) {
|
|
|
1178
1193
|
|
|
1179
1194
|
// src/vensim/preprocess-vensim.ts
|
|
1180
1195
|
import split from "split-string";
|
|
1181
|
-
function preprocessVensimModel(input) {
|
|
1196
|
+
function preprocessVensimModel(input, options) {
|
|
1197
|
+
const removalKeys = options?.removalKeys;
|
|
1198
|
+
function shouldRemove(text) {
|
|
1199
|
+
if (text.includes("TABBED ARRAY")) {
|
|
1200
|
+
return true;
|
|
1201
|
+
}
|
|
1202
|
+
if (removalKeys) {
|
|
1203
|
+
for (const key of removalKeys) {
|
|
1204
|
+
if (text.includes(key)) {
|
|
1205
|
+
return true;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1211
|
+
const macrosResult = removeMacros(input);
|
|
1212
|
+
input = macrosResult.processed;
|
|
1182
1213
|
const rawDefs = splitDefs(input);
|
|
1183
1214
|
const vensimDefs = [];
|
|
1215
|
+
const removedBlocks = [];
|
|
1184
1216
|
for (const rawDef of rawDefs) {
|
|
1217
|
+
if (shouldRemove(rawDef.text)) {
|
|
1218
|
+
removedBlocks.push(rawDef.text.trim() + "|");
|
|
1219
|
+
continue;
|
|
1220
|
+
}
|
|
1185
1221
|
const vensimDef = processDef(rawDef);
|
|
1186
1222
|
if (vensimDef) {
|
|
1187
1223
|
vensimDefs.push(vensimDef);
|
|
1188
1224
|
}
|
|
1189
1225
|
}
|
|
1190
|
-
return
|
|
1226
|
+
return {
|
|
1227
|
+
defs: vensimDefs,
|
|
1228
|
+
removedMacros: macrosResult.removed,
|
|
1229
|
+
removedBlocks
|
|
1230
|
+
};
|
|
1191
1231
|
}
|
|
1192
1232
|
function splitDefs(input) {
|
|
1193
1233
|
const defTexts = split(input, { separator: "|", quotes: ['"'], keep: () => true });
|
|
@@ -1229,6 +1269,9 @@ function splitDefs(input) {
|
|
|
1229
1269
|
function splitLines(input) {
|
|
1230
1270
|
return input.split(/\r\n|\n|\r/);
|
|
1231
1271
|
}
|
|
1272
|
+
function splitExceptInQuoted(input, sep) {
|
|
1273
|
+
return split(input, { separator: sep, quotes: ['"'] });
|
|
1274
|
+
}
|
|
1232
1275
|
function processBackslashes(input) {
|
|
1233
1276
|
const inputLines = splitLines(input);
|
|
1234
1277
|
let output = "";
|
|
@@ -1274,22 +1317,27 @@ function replaceDelimitedStrings(str, open, close, newStr) {
|
|
|
1274
1317
|
function reduceWhitespace(input) {
|
|
1275
1318
|
return input.replace(/\s\s+/g, " ").trim();
|
|
1276
1319
|
}
|
|
1320
|
+
var reWhitespace2 = new RegExp("(\\s|_)+", "g");
|
|
1277
1321
|
function keyForDef(def) {
|
|
1278
1322
|
let key = def;
|
|
1279
1323
|
key = key.replace(/:INTERPOLATE:/g, "");
|
|
1324
|
+
let kind;
|
|
1280
1325
|
if (key.includes("=")) {
|
|
1326
|
+
kind = "eqn";
|
|
1281
1327
|
key = key.split("=")[0].trim();
|
|
1282
1328
|
} else if (key.includes(":")) {
|
|
1329
|
+
kind = "dim";
|
|
1283
1330
|
key = key.split(":")[0].trim();
|
|
1284
1331
|
} else {
|
|
1332
|
+
kind = "decl";
|
|
1285
1333
|
}
|
|
1334
|
+
key = splitExceptInQuoted(key, "(")[0];
|
|
1286
1335
|
key = key.replace(/"/g, "");
|
|
1287
|
-
key = key.split("(")[0];
|
|
1288
1336
|
key = key.trim();
|
|
1289
|
-
key = key.replace(/\
|
|
1290
|
-
key = key.replace(
|
|
1337
|
+
key = key.replace(/(?<=\[).*?(?=\])/g, (match) => match.replace(/\s/g, ""));
|
|
1338
|
+
key = key.replace(reWhitespace2, "_");
|
|
1291
1339
|
key = key.toLowerCase();
|
|
1292
|
-
return key;
|
|
1340
|
+
return { key, kind };
|
|
1293
1341
|
}
|
|
1294
1342
|
function processDef(rawDef) {
|
|
1295
1343
|
let input = rawDef.text;
|
|
@@ -1307,7 +1355,7 @@ function processDef(rawDef) {
|
|
|
1307
1355
|
${input}`);
|
|
1308
1356
|
}
|
|
1309
1357
|
const rawDefText = reduceWhitespace(parts[0]);
|
|
1310
|
-
const key = keyForDef(rawDefText);
|
|
1358
|
+
const { key, kind } = keyForDef(rawDefText);
|
|
1311
1359
|
const def = `${rawDefText} ~~|`;
|
|
1312
1360
|
const units = reduceWhitespace(parts[1]);
|
|
1313
1361
|
const comment = reduceWhitespace(parts[2]);
|
|
@@ -1315,12 +1363,25 @@ ${input}`);
|
|
|
1315
1363
|
return {
|
|
1316
1364
|
key,
|
|
1317
1365
|
def,
|
|
1366
|
+
kind,
|
|
1318
1367
|
line: rawDef.line,
|
|
1319
1368
|
units,
|
|
1320
1369
|
comment,
|
|
1321
1370
|
...group ? { group } : {}
|
|
1322
1371
|
};
|
|
1323
1372
|
}
|
|
1373
|
+
function removeMacros(input) {
|
|
1374
|
+
const removed = [];
|
|
1375
|
+
const processed = input.replace(/:MACRO:.*:END OF MACRO:/gms, (match) => {
|
|
1376
|
+
removed.push(match);
|
|
1377
|
+
const numBreaks = match.split(/\r\n|\n|\r/gms).length - 1;
|
|
1378
|
+
return numBreaks > 0 ? "\n".repeat(numBreaks) : "";
|
|
1379
|
+
});
|
|
1380
|
+
return {
|
|
1381
|
+
processed,
|
|
1382
|
+
removed
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1324
1385
|
|
|
1325
1386
|
// src/vensim/impl/model-reader.js
|
|
1326
1387
|
import { ModelVisitor as ModelVisitor4 } from "antlr4-vensim";
|
|
@@ -1379,7 +1440,7 @@ var ModelReader = class extends ModelVisitor4 {
|
|
|
1379
1440
|
function parseVensimModel(input, context, sort = false) {
|
|
1380
1441
|
const dimensions = [];
|
|
1381
1442
|
const equations = [];
|
|
1382
|
-
const defs = preprocessVensimModel(input);
|
|
1443
|
+
const { defs } = preprocessVensimModel(input);
|
|
1383
1444
|
if (sort) {
|
|
1384
1445
|
defs.sort((a, b) => {
|
|
1385
1446
|
return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
|
|
@@ -1431,11 +1492,15 @@ Detail:
|
|
|
1431
1492
|
};
|
|
1432
1493
|
}
|
|
1433
1494
|
export {
|
|
1495
|
+
canonicalFunctionId,
|
|
1496
|
+
canonicalId,
|
|
1497
|
+
canonicalVarId,
|
|
1434
1498
|
debugPrintExpr,
|
|
1435
1499
|
parseVensimEquation,
|
|
1436
1500
|
parseVensimExpr,
|
|
1437
1501
|
parseVensimModel,
|
|
1438
1502
|
parseVensimSubscriptRange,
|
|
1503
|
+
preprocessVensimModel,
|
|
1439
1504
|
prettyPrintExpr,
|
|
1440
1505
|
printExprStats,
|
|
1441
1506
|
reduceConditionals,
|