@sdeverywhere/parse 0.1.2 → 0.1.3
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 +614 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +608 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/_shared/canonical-id.js","../src/ast/print-expr.ts","../src/ast/reduce-expr.ts","../src/ast/ast-builders.ts","../src/vensim/impl/subscript-range-reader.js","../src/vensim/impl/antlr-parser.js","../src/vensim/parse-vensim-subscript-range.ts","../src/vensim/impl/expr-reader.js","../src/vensim/parse-vensim-expr.ts","../src/vensim/impl/equation-reader.js","../src/vensim/parse-vensim-equation.ts","../src/vensim/preprocess-vensim.ts","../src/vensim/impl/model-reader.js","../src/vensim/parse-vensim-model.ts"],"sourcesContent":["// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\n// Detect '!' at the end of a marked dimension when preceded by whitespace\nconst reTrailingMark = new RegExp('\\\\s+!$', 'g')\n\n// Detect one or more consecutive whitespace or underscore characters\nconst reWhitespace = new RegExp('(\\\\s|_)+', 'g')\n\n// Detect special punctuation characters\n// TODO: We do not currently include '!' characters in this set; we should only replace these\n// when they don't appear at the end of a (marked) dimension\nconst reSpecialChars = new RegExp(`['\"\\\\.,\\\\-\\\\$&%\\\\/\\\\|()]`, 'g')\n\n/**\n * Format a model variable or subscript/dimension name into a valid C identifier (with\n * special characters converted to underscore).\n *\n * Note that this should only be called with an individual variable base name (e.g.,\n * 'Variable name') or a subscript/dimension name (e.g., 'DimA'). In the case where\n * you have a full variable name that includes subscripts/dimensions (e.g.,\n * 'Variable name[DimA,B2]'), use `canonicalVarId` to convert the base variable name\n * and subscript/dimension parts to canonical form indepdendently.\n *\n * @param {string} name The name of the variable in the source model, e.g., \"Variable name\".\n * @returns {string} The C identifier for the given name, e.g., \"_variable_name\".\n */\nexport function canonicalId(name) {\n return (\n '_' +\n name\n // Ignore any leading or trailing whitespace\n .trim()\n // When a '!' character appears at the end of a marked dimension, preserve the mark\n // but remove any preceding whitespace\n .replace(reTrailingMark, '!')\n // Replace one or more consecutive whitespace or underscore characters with a single\n // underscore character; this matches the behavior of Vensim documented here:\n // https://www.vensim.com/documentation/ref_variable_names.html\n .replace(reWhitespace, '_')\n // Replace each special punctuation character with an underscore\n .replace(reSpecialChars, '_')\n // Convert to lower case\n .toLowerCase()\n )\n}\n\n/**\n * Format a (subscripted or non-subscripted) model variable name into a canonical identifier,\n * (with special characters converted to underscore, and subscript/dimension parts separated\n * by commas).\n *\n * @param {string} name The name of the variable in the source model, e.g., \"Variable name[DimA, B2]\".\n * @returns {string} The canonical identifier for the given name, e.g., \"_variable_name[_dima,_b2]\".\n */\nexport function canonicalVarId(name) {\n const m = name.match(/([^[]+)(?:\\[([^\\]]+)\\])?/)\n if (!m) {\n throw new Error(`Invalid variable name: ${name}`)\n }\n\n let id = canonicalId(m[1])\n if (m[2]) {\n const subscripts = m[2].split(',').map(x => canonicalId(x))\n id += `[${subscripts.join(',')}]`\n }\n\n return id\n}\n\n/**\n * Format a model function name into a valid C identifier (with special characters\n * converted to underscore, and the ID converted to uppercase).\n *\n * @param {string} name The name of the variable in the source model, e.g., \"FUNCTION name\".\n * @returns {string} The C identifier for the given name, e.g., \"_FUNCTION_NAME\".\n */\nexport function canonicalFunctionId(name) {\n return canonicalId(name).toUpperCase()\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { assertNever } from 'assert-never'\n\nimport type { Expr, VariableRef } from '../ast/ast-types'\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function debugPrintExpr(expr: Expr, indent = 0): void {\n const spaces = ' '.repeat(indent * 2)\n const log = (s: string) => {\n console.log(`${spaces}${s}`)\n }\n\n switch (expr.kind) {\n case 'number':\n log(`const: ${expr.text}`)\n break\n\n case 'string':\n log(`string: ${expr.text}`)\n break\n\n case 'keyword':\n log(`keyword: ${expr.text}`)\n break\n\n case 'variable-ref':\n log(`ref: ${fullIdForVarRef(expr)}`)\n break\n\n case 'unary-op':\n log(`unary-op: ${expr.op}`)\n debugPrintExpr(expr.expr, indent + 1)\n break\n\n case 'binary-op':\n log(`binary-op: ${expr.op}`)\n debugPrintExpr(expr.lhs, indent + 1)\n debugPrintExpr(expr.rhs, indent + 1)\n break\n\n case 'parens':\n log('parens')\n debugPrintExpr(expr.expr, indent + 1)\n break\n\n case 'lookup-def':\n // TODO: Include range and points?\n log(`lookup-def`)\n break\n\n case 'lookup-call':\n log(`lookup-call: ${debugPrintExpr(expr.varRef)}`)\n debugPrintExpr(expr.arg, indent + 1)\n break\n\n case 'function-call':\n log(`function-call: ${expr.fnId}`)\n expr.args.forEach(arg => debugPrintExpr(arg, indent + 1))\n break\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport type FormatVariableRefFunc = (varRef: VariableRef) => string\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport interface PrettyOpts {\n /**\n * Whether to use a compact representation without additional spaces. (The compact form mimics\n * the behavior of the legacy parser.\n */\n compact?: boolean\n html?: boolean\n formatVariableRef?: FormatVariableRefFunc\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function toPrettyString(expr: Expr, opts?: PrettyOpts): string {\n let lparen: string, rparen: string, spaceSep: string, commaSep: string\n if (opts?.compact === true) {\n lparen = '('\n rparen = ')'\n spaceSep = ''\n commaSep = ','\n } else {\n lparen = '( '\n rparen = ' )'\n spaceSep = ' '\n commaSep = ', '\n }\n\n switch (expr.kind) {\n case 'number':\n return expr.text\n\n case 'string':\n return `'${expr.text}'`\n\n case 'keyword':\n return expr.text\n\n case 'variable-ref':\n if (opts?.formatVariableRef) {\n return opts.formatVariableRef(expr)\n } else {\n if (expr.subscriptRefs?.length > 0) {\n return `${expr.varName}[${expr.subscriptRefs.map(ref => ref.subName).join(commaSep)}]`\n } else {\n return expr.varName\n }\n }\n\n case 'unary-op':\n if (expr.op === ':NOT:') {\n return `${expr.op} ${toPrettyString(expr.expr, opts)}`\n } else {\n return `${expr.op}${toPrettyString(expr.expr, opts)}`\n }\n\n case 'binary-op': {\n let op: string\n if (opts?.html === true) {\n switch (expr.op) {\n case '<':\n op = '<'\n break\n case '<=':\n op = '<='\n break\n case '>':\n op = '>'\n break\n case '>=':\n op = '>='\n break\n default:\n op = expr.op\n break\n }\n } else {\n op = expr.op\n }\n const lhs = toPrettyString(expr.lhs, opts)\n const rhs = toPrettyString(expr.rhs, opts)\n return `${lhs}${spaceSep}${op}${spaceSep}${rhs}`\n }\n\n case 'parens':\n return `${lparen}${toPrettyString(expr.expr, opts)}${rparen}`\n\n case 'lookup-def': {\n const pointString = (p: [number, number]) => {\n return `(${p[0]},${p[1]})`\n }\n const points = expr.points.map(pointString).join(commaSep)\n if (expr.range) {\n const min = pointString(expr.range.min)\n const max = pointString(expr.range.max)\n return `${lparen}[${min}-${max}]${commaSep}${points}${rparen}`\n } else {\n return `${lparen}${points}${rparen}`\n }\n }\n\n case 'lookup-call': {\n const varRef = toPrettyString(expr.varRef, opts)\n const arg = toPrettyString(expr.arg, opts)\n return `${varRef}${lparen}${arg}${rparen}`\n }\n\n case 'function-call': {\n const args = expr.args.map(arg => toPrettyString(arg, opts))\n return `${expr.fnName}${lparen}${args.join(commaSep)}${rparen}`\n }\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function prettyPrintExpr(expr: Expr, indent = 0): void {\n const spaces = ' '.repeat(indent * 2)\n const log = (s: string) => {\n console.log(`${spaces}${s}`)\n }\n log(toPrettyString(expr))\n}\n\ntype CountMap = Map<string, number>\n\nclass Stats {\n constCount = 0\n varRefCount = 0\n readonly unaryOpCounts: CountMap = new Map()\n readonly binaryOpCounts: CountMap = new Map()\n readonly fnCallCounts: CountMap = new Map()\n readonly luCallCounts: CountMap = new Map()\n}\n\nfunction increment(map: CountMap, key: string): void {\n const count = map.get(key) || 0\n map.set(key, count + 1)\n}\n\nfunction getExprStats(expr: Expr, stats: Stats) {\n switch (expr.kind) {\n case 'number':\n stats.constCount++\n break\n\n case 'string':\n // TODO\n break\n\n case 'keyword':\n // TODO: Count this as a constant? (Currently only used for :NA: values.)\n break\n\n case 'variable-ref':\n stats.varRefCount++\n break\n\n case 'unary-op':\n getExprStats(expr.expr, stats)\n increment(stats.unaryOpCounts, expr.op)\n break\n\n case 'binary-op':\n getExprStats(expr.lhs, stats)\n getExprStats(expr.rhs, stats)\n increment(stats.binaryOpCounts, expr.op)\n break\n\n case 'parens':\n getExprStats(expr.expr, stats)\n break\n\n case 'lookup-def':\n // TODO\n break\n\n case 'lookup-call':\n increment(stats.luCallCounts, fullIdForVarRef(expr.varRef))\n getExprStats(expr.arg, stats)\n break\n\n case 'function-call':\n increment(stats.fnCallCounts, expr.fnId)\n expr.args.forEach(arg => getExprStats(arg, stats))\n break\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function printExprStats(exprs: Expr[]): void {\n const stats = new Stats()\n for (const expr of exprs) {\n getExprStats(expr, stats)\n }\n\n function printCount(count: number, label: string) {\n console.log(`${count.toString().padStart(6)} ${label}`)\n }\n\n function printCounts(map: CountMap): number {\n const entries = [...map.entries()].sort((a, b) => a[0].localeCompare(b[0]))\n let total = 0\n for (const entry of entries) {\n printCount(entry[1], entry[0])\n total += entry[1]\n }\n printCount(total, 'total')\n return total\n }\n\n let nodeCount = 0\n\n printCount(stats.constCount, 'consts')\n nodeCount += stats.constCount\n\n printCount(stats.varRefCount, 'var refs')\n nodeCount += stats.varRefCount\n\n console.log()\n console.log('UNARY OPS')\n nodeCount += printCounts(stats.unaryOpCounts)\n\n console.log()\n console.log('BINARY OPS')\n nodeCount += printCounts(stats.binaryOpCounts)\n\n console.log()\n console.log('FUNCTION CALLS')\n nodeCount += printCounts(stats.fnCallCounts)\n\n console.log()\n console.log('LOOKUP CALLS')\n nodeCount += printCounts(stats.luCallCounts)\n\n console.log()\n console.log('TOTAL')\n printCount(nodeCount, 'nodes')\n}\n\n// TODO: Move to names.ts?\nfunction fullIdForVarRef(varRef: VariableRef): string {\n if (varRef.subscriptRefs?.length > 0) {\n return `${varRef.varId}[${varRef.subscriptRefs.map(ref => ref.subId).join(',')}]`\n } else {\n return varRef.varId\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { assertNever } from 'assert-never'\n\nimport { binaryOp, lookupCall, num, parens, unaryOp } from './ast-builders'\nimport type { Expr, NumberLiteral, VariableRef } from './ast-types'\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport interface ReduceExprOptions {\n /** A callback that returns the possibly reduced expression for the referenced variable. */\n resolveVarRef?: (varRef: VariableRef) => Expr | undefined\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function reduceExpr(expr: Expr, opts?: ReduceExprOptions): Expr {\n switch (expr.kind) {\n case 'number':\n case 'string':\n case 'keyword':\n return expr\n\n case 'variable-ref':\n if (opts?.resolveVarRef !== undefined) {\n // Note that we assume the resolved expression has already been reduced by\n // the callback, and don't attempt to reduce further\n const resolvedExpr = opts.resolveVarRef(expr)\n if (resolvedExpr) {\n return resolvedExpr\n }\n }\n return expr\n\n case 'unary-op': {\n // Reduce the child expression\n const child = reduceExpr(expr.expr, opts)\n switch (expr.op) {\n case '+':\n // When there is an explicit plus sign, we can take the child expression as is\n return child\n case '-':\n if (child.kind === 'number') {\n // Negate the number\n return num(-child.value)\n } else {\n // Cannot simplify further\n return unaryOp('-', child)\n }\n case ':NOT:':\n if (child.kind === 'number') {\n // Use the same behavior as C and negate the numeric value. (\"The result of the\n // logical negation operator ! is 0 if the value of its operand compares unequal\n // to 0, 1 if the value of its operand compares equal to 0.\")\n return num(child.value === 0 ? 1 : 0)\n } else {\n // Cannot simplify further\n return unaryOp(':NOT:', child)\n }\n default:\n assertNever(expr)\n }\n break\n }\n\n case 'binary-op': {\n // Reduce the lhs and rhs expressions\n // TODO: Don't visit rhs if expression can be reduced by looking at lhs alone\n const lhs = reduceExpr(expr.lhs, opts)\n const rhs = reduceExpr(expr.rhs, opts)\n if (lhs.kind === 'number' && rhs.kind === 'number') {\n // Perform basic arithmetic to reduce to a constant number\n switch (expr.op) {\n case '+':\n return num(lhs.value + rhs.value)\n case '-':\n return num(lhs.value - rhs.value)\n case '*':\n return num(lhs.value * rhs.value)\n case '/':\n // TODO: Catch divide-by-zero errors at compile time\n return num(lhs.value / rhs.value)\n case '^':\n return num(Math.pow(lhs.value, rhs.value))\n case '=':\n return num(lhs.value === rhs.value ? 1 : 0)\n case '<>':\n return num(lhs.value !== rhs.value ? 1 : 0)\n case '<':\n return num(lhs.value < rhs.value ? 1 : 0)\n case '>':\n return num(lhs.value > rhs.value ? 1 : 0)\n case '<=':\n return num(lhs.value <= rhs.value ? 1 : 0)\n case '>=':\n return num(lhs.value >= rhs.value ? 1 : 0)\n case ':AND:':\n // For AND expressions, if both sides are non-zero, then resolve to 1\n return num(lhs.value !== 0 && rhs.value !== 0 ? 1 : 0)\n case ':OR:':\n // For OR expressions, if either side is non-zero, then resolve to 1\n return num(lhs.value !== 0 || rhs.value !== 0 ? 1 : 0)\n default:\n assertNever(expr)\n }\n } else if (lhs.kind === 'number' || rhs.kind === 'number') {\n // Try to reduce identity expressions to a single value (x*1 == x, and so on)\n const lhsNum: number = lhs.kind === 'number' ? lhs.value : undefined\n const rhsNum: number = rhs.kind === 'number' ? rhs.value : undefined\n const numValue = lhsNum !== undefined ? lhsNum : rhsNum\n const otherSide = lhsNum !== undefined ? rhs : lhs\n switch (expr.op) {\n case '+': {\n if (numValue === 0) {\n // x+0 == x\n // 0+x == x\n return otherSide\n } else if (\n otherSide.kind === 'binary-op' &&\n otherSide.op === '+' &&\n (otherSide.lhs.kind === 'number' || otherSide.rhs.kind === 'number')\n ) {\n // In this case, one side is const and and the child is a '+' with a const, so we\n // can add the two consts and fold into a single add op\n const otherSideLhsNum: number = otherSide.lhs.kind === 'number' ? otherSide.lhs.value : undefined\n const otherSideRhsNum: number = otherSide.rhs.kind === 'number' ? otherSide.rhs.value : undefined\n const otherSideConstValue = otherSideLhsNum !== undefined ? otherSideLhsNum : otherSideRhsNum\n const otherSideOtherPart = otherSideLhsNum !== undefined ? otherSide.rhs : otherSide.lhs\n return binaryOp(num(numValue + otherSideConstValue), '+', otherSideOtherPart)\n }\n break\n }\n\n case '-': {\n if (rhsNum === 0) {\n // x-0 == x\n return lhs\n } else if (lhsNum === 0) {\n // 0-x == -x\n // TODO: This probably isn't too helpful\n return unaryOp('-', rhs)\n }\n break\n }\n\n case '*': {\n if (numValue === 0) {\n // x*0 == 0\n // 0*x == 0\n return num(0)\n } else if (numValue === 1) {\n // x*1 == x\n // 1*x == x\n return otherSide\n } else if (\n otherSide.kind === 'binary-op' &&\n otherSide.op === '*' &&\n (otherSide.lhs.kind === 'number' || otherSide.rhs.kind === 'number')\n ) {\n // In this case, one side is const and and the child is a '*' with a const, so we\n // can multiply the two consts and fold into a single multiply op\n const otherSideLhsNum: number = otherSide.lhs.kind === 'number' ? otherSide.lhs.value : undefined\n const otherSideRhsNum: number = otherSide.rhs.kind === 'number' ? otherSide.rhs.value : undefined\n const otherSideConstValue = otherSideLhsNum !== undefined ? otherSideLhsNum : otherSideRhsNum\n const otherSideOtherPart = otherSideLhsNum !== undefined ? otherSide.rhs : otherSide.lhs\n return binaryOp(num(numValue * otherSideConstValue), '*', otherSideOtherPart)\n }\n break\n }\n\n case '/': {\n if (rhsNum === 1) {\n // x/1 == x\n return lhs\n }\n break\n }\n\n case '^': {\n if (rhsNum === 0) {\n // x^0 == 1\n return num(1)\n } else if (rhsNum === 1) {\n // x^1 == x\n return lhs\n }\n break\n }\n\n case ':AND:':\n // For AND expressions:\n // - if the constant side is zero, then resolve to zero (false)\n // x && 0 == 0\n // 0 && x == 0\n // - if the constant side is non-zero, then resolve to the other side\n // x && 1 == x\n // 1 && x == x\n return numValue === 0 ? num(0) : otherSide\n\n case ':OR:':\n // For OR expressions:\n // - if the constant side is non-zero, then resolve to one (true)\n // x || 1 == 1\n // 1 || x == 1\n // - if the constant side is zero, resolve to the other side\n // x || 0 == x\n // 0 || x == x\n return numValue !== 0 ? num(1) : otherSide\n\n default:\n break\n }\n }\n\n // Cannot simplify further; return a new expression with the reduced child expressions\n return {\n kind: 'binary-op',\n lhs,\n op: expr.op,\n rhs\n }\n }\n\n case 'parens': {\n const child = reduceExpr(expr.expr, opts)\n return applyParens(child)\n }\n\n case 'lookup-def':\n // TODO: Reduce lookup def?\n return expr\n\n case 'lookup-call':\n // TODO: Reduce lookup call arg?\n return expr\n\n case 'function-call': {\n // Reduce each argument expression\n if (expr.fnId === '_IF_THEN_ELSE') {\n // If condition is a constant, we can eliminate the unused branch\n const conditionExpr = reduceExpr(expr.args[0], opts)\n if (conditionExpr.kind === 'number') {\n // The condition resolved to a simple numeric constant. If it is non-zero,\n // replace the `IF THEN ELSE` call with the \"true\" branch, otherwise replace\n // it with the \"false\" branch.\n const branchExpr = conditionExpr.value !== 0 ? reduceExpr(expr.args[1], opts) : reduceExpr(expr.args[2], opts)\n\n // Wrap the branch expression in parentheses if needed to ensure that the intent\n // of the original expression remains the same. For example:\n // a = IF THEN ELSE(1, b + c, d - e) * 10\n // In this case, the parentheses are important, and need to be preserved:\n // a = (b + c) * 10\n // If the parentheses are not needed (like when the branch resolve to a simple\n // constant or variable reference), the parentheses will be dropped.\n return applyParens(branchExpr)\n }\n }\n\n // If all args are constant, apply the function at compile time (for certain functions)\n const reducedArgs = expr.args.map(arg => reduceExpr(arg, opts))\n const allConst = reducedArgs.every(arg => arg.kind === 'number')\n if (allConst) {\n const constArg = (index: number) => {\n const num = reducedArgs[index] as NumberLiteral\n return num.value\n }\n switch (expr.fnId) {\n case '_ABS':\n return num(Math.abs(constArg(0)))\n case '_COS':\n return num(Math.cos(constArg(0)))\n case '_EXP':\n return num(Math.exp(constArg(0)))\n case '_INITIAL':\n return reducedArgs[0]\n case '_INTEGER':\n return num(Math.trunc(constArg(0)))\n case '_LN':\n return num(Math.log(constArg(0)))\n case '_MAX':\n return num(Math.max(constArg(0), constArg(1)))\n case '_MIN':\n return num(Math.min(constArg(0), constArg(1)))\n case '_MODULO':\n return num(constArg(0) % constArg(1))\n case '_POWER':\n return num(Math.pow(constArg(0), constArg(1)))\n case '_SIN':\n return num(Math.sin(constArg(0)))\n case '_SQRT':\n return num(Math.sqrt(constArg(0)))\n default:\n break\n }\n }\n\n return {\n kind: 'function-call',\n fnName: expr.fnName,\n fnId: expr.fnId,\n args: reducedArgs\n }\n }\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * A variant of `reduceExpr` that does not aggressively reduce the expression, but only\n * tries to eliminate the unused branch if a conditional (`IF THEN ELSE`) has a condition\n * that resolves to a constant.\n *\n * @hidden This is not yet part of the public API.\n *\n * @param expr The expression to reduce.\n * @param opts The reduce options.\n * @returns A possibly reduced expression.\n */\nexport function reduceConditionals(expr: Expr, opts?: ReduceExprOptions): Expr {\n switch (expr.kind) {\n case 'number':\n case 'string':\n case 'keyword':\n return expr\n\n case 'variable-ref':\n // If we get here, it means that we are processing an expression that is not\n // inside the condition expression for an `IF THEN ELSE`, so we do not attempt\n // to resolve the variable reference or reduce it further\n return expr\n\n case 'unary-op': {\n const child = reduceConditionals(expr.expr, opts)\n return unaryOp(expr.op, child)\n }\n\n case 'binary-op': {\n const lhs = reduceConditionals(expr.lhs, opts)\n const rhs = reduceConditionals(expr.rhs, opts)\n return binaryOp(lhs, expr.op, rhs)\n }\n\n case 'parens': {\n const child = reduceConditionals(expr.expr, opts)\n return applyParens(child)\n }\n\n case 'lookup-def':\n return expr\n\n case 'lookup-call': {\n const arg = reduceConditionals(expr.arg, opts)\n return lookupCall(expr.varRef, arg)\n }\n\n case 'function-call': {\n if (expr.fnId === '_IF_THEN_ELSE') {\n // Note that (unlike all other places in this function) we use `reduceExpr` here\n // to aggressively reduce the condition expression (the first argument for the\n // `IF THEN ELSE` call)\n const conditionExpr = reduceExpr(expr.args[0], opts)\n if (conditionExpr.kind === 'number') {\n // The condition resolved to a simple numeric constant. If it is non-zero,\n // replace the `IF THEN ELSE` call with the \"true\" branch, otherwise replace\n // it with the \"false\" branch.\n const branchExpr =\n conditionExpr.value !== 0 ? reduceConditionals(expr.args[1], opts) : reduceConditionals(expr.args[2], opts)\n\n // Wrap the branch expression in parentheses if needed to ensure that the intent\n // of the original expression remains the same. For example:\n // a = IF THEN ELSE(1, b + c, d - e) * 10\n // In this case, the parentheses are important, and need to be preserved:\n // a = (b + c) * 10\n // If the parentheses are not needed (like when the branch resolve to a simple\n // constant or variable reference), the parentheses will be dropped.\n return applyParens(branchExpr)\n }\n }\n\n // For all other kinds of function calls, call `reduceConditionals` on the args\n const reducedArgs = expr.args.map(arg => reduceConditionals(arg, opts))\n return {\n kind: 'function-call',\n fnName: expr.fnName,\n fnId: expr.fnId,\n args: reducedArgs\n }\n }\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * Reduce the given expression that may need to be wrapped in parentheses. If the parentheses\n * are not needed, the given `child` expression will be returned as is, otherwise it will be\n * wrapped in a \"parens\" node.\n *\n * @param child The child of a parens expression to reduce.\n * @returns A possibly reduced expression.\n */\nfunction applyParens(child: Expr): Expr {\n switch (child.kind) {\n case 'number':\n case 'string':\n case 'keyword':\n case 'variable-ref':\n // When the child expression resolves to something simple, drop the parens\n // TODO: Are there other cases where we should drop the parens?\n return child\n default:\n // Otherwise, preserve the parens\n return parens(child)\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { canonicalFunctionId, canonicalId } from '../_shared/canonical-id'\n\nimport type {\n BinaryOp,\n BinaryOpExpr,\n DimensionDef,\n DimName,\n DimOrSubName,\n Equation,\n Expr,\n FunctionCall,\n FunctionName,\n Keyword,\n LookupCall,\n LookupDef,\n LookupPoint,\n LookupRange,\n Model,\n NumberLiteral,\n ParensExpr,\n StringLiteral,\n SubName,\n SubscriptMapping,\n SubscriptRef,\n UnaryOp,\n UnaryOpExpr,\n VariableDef,\n VariableName,\n VariableRef\n} from './ast-types'\n\n//\n// NOTE: This file contains functions that allow for tersely defining AST nodes.\n// It is intended for internal use only (primarily in tests), so it is not exported\n// as part of the public API at this time.\n//\n\n//\n// DIMENSIONS + SUBSCRIPTS\n//\n\nexport function subRef(dimOrSubName: DimOrSubName): SubscriptRef {\n return {\n subName: dimOrSubName,\n subId: canonicalId(dimOrSubName)\n }\n}\n\nexport function subMapping(toDimName: DimName, dimOrSubNames: DimOrSubName[] = []): SubscriptMapping {\n return {\n toDimName,\n toDimId: canonicalId(toDimName),\n subscriptRefs: dimOrSubNames.map(subRef)\n }\n}\n\nexport function dimDef(\n dimName: DimName,\n familyName: DimName,\n dimOrSubNames: SubName[],\n subscriptMappings: SubscriptMapping[] = [],\n comment = '',\n group?: string\n): DimensionDef {\n return {\n dimName,\n dimId: canonicalId(dimName),\n familyName,\n familyId: canonicalId(familyName),\n subscriptRefs: dimOrSubNames.map(subRef),\n subscriptMappings,\n comment,\n ...(group ? { group } : {})\n }\n}\n\n//\n// EXPRESSIONS\n//\n\nexport function num(value: number, text?: string): NumberLiteral {\n return {\n kind: 'number',\n value,\n text: text || value.toString()\n }\n}\n\nexport function stringLiteral(text: string): StringLiteral {\n return {\n kind: 'string',\n text\n }\n}\n\nexport function keyword(text: string): Keyword {\n return {\n kind: 'keyword',\n text\n }\n}\n\nexport function varRef(varName: VariableName, subscriptNames?: DimOrSubName[]): VariableRef {\n return {\n kind: 'variable-ref',\n varName,\n varId: canonicalId(varName),\n subscriptRefs: subscriptNames?.map(subRef)\n }\n}\n\nexport function unaryOp(op: UnaryOp, expr: Expr): UnaryOpExpr {\n return {\n kind: 'unary-op',\n op,\n expr\n }\n}\n\nexport function binaryOp(lhs: Expr, op: BinaryOp, rhs: Expr): BinaryOpExpr {\n return {\n kind: 'binary-op',\n lhs,\n op,\n rhs\n }\n}\n\nexport function parens(expr: Expr): ParensExpr {\n return {\n kind: 'parens',\n expr\n }\n}\n\nexport function lookupDef(points: LookupPoint[], range?: LookupRange): LookupDef {\n return {\n kind: 'lookup-def',\n range,\n points\n }\n}\n\nexport function lookupCall(varRef: VariableRef, arg: Expr): LookupCall {\n return {\n kind: 'lookup-call',\n varRef,\n arg\n }\n}\n\nexport function call(fnName: FunctionName, ...args: Expr[]): FunctionCall {\n return {\n kind: 'function-call',\n fnName,\n fnId: canonicalFunctionId(fnName),\n args\n }\n}\n\n//\n// EQUATIONS\n//\n\nexport function varDef(\n varName: VariableName,\n subscriptNames?: DimOrSubName[],\n exceptSubscriptNames?: DimOrSubName[][]\n): VariableDef {\n return {\n kind: 'variable-def',\n varName,\n varId: canonicalId(varName),\n subscriptRefs: subscriptNames?.map(subRef),\n exceptSubscriptRefSets: exceptSubscriptNames?.map(namesForSet => namesForSet.map(subRef))\n }\n}\n\nexport function exprEqn(varDef: VariableDef, expr: Expr, units = '', comment = '', group?: string): Equation {\n return {\n lhs: {\n varDef\n },\n rhs: {\n kind: 'expr',\n expr\n },\n units,\n comment,\n ...(group ? { group } : {})\n }\n}\n\nexport function constListEqn(varDef: VariableDef, constants: NumberLiteral[][], units = '', comment = ''): Equation {\n // For now, assume that the original text had a trailing semicolon if there are multiple groups\n let text = constants.map(arr => arr.map(constant => constant.text).join(',')).join(';')\n if (constants.length > 1) {\n text += ';'\n }\n return {\n lhs: {\n varDef\n },\n rhs: {\n kind: 'const-list',\n constants: constants.flat(),\n text\n },\n units,\n comment\n }\n}\n\nexport function dataVarEqn(varDef: VariableDef, units = '', comment = ''): Equation {\n return {\n lhs: {\n varDef\n },\n rhs: {\n kind: 'data'\n },\n units,\n comment\n }\n}\n\nexport function lookupVarEqn(varDef: VariableDef, lookupDef: LookupDef, units = '', comment = ''): Equation {\n return {\n lhs: {\n varDef\n },\n rhs: {\n kind: 'lookup',\n lookupDef\n },\n units,\n comment\n }\n}\n\n//\n// MODEL\n//\n\nexport function model(dimensions: DimensionDef[], equations: Equation[]): Model {\n return {\n dimensions,\n equations\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { ModelParser, ModelVisitor } from 'antlr4-vensim'\n\nimport { canonicalFunctionId, canonicalId } from '../../_shared/canonical-id'\n\nimport { createAntlrParser } from './antlr-parser'\n\nexport class SubscriptRangeReader extends ModelVisitor {\n /**\n * @public\n * @param {import('../vensim-parse-context').VensimParseContext} parseContext An object\n * that provides access to file system resources (such as external data files) that are\n * referenced during the parse phase.\n */\n constructor(parseContext /*: VensimParseContext*/) {\n super()\n this.parseContext = parseContext\n }\n\n /**\n * Parse the given Vensim subscript range definition and return a `DimensionDef` AST node.\n *\n * @public\n * @param {string} subscriptRangeText A string containing the Vensim subscript range definition.\n * @returns {import('../../ast/ast-types').DimensionDef} A `DimensionDef` AST node.\n */\n /*public*/ parse(subscriptRangeText /*: string*/) /*: DimensionDef*/ {\n const parser = createAntlrParser(subscriptRangeText)\n const subscriptRangeCtx = parser.subscriptRange()\n return this.visitSubscriptRange(subscriptRangeCtx)\n }\n\n /**\n * Process the given ANTLR `SubscriptRangeContext` from an already parsed Vensim\n * subscript range definition.\n *\n * @public\n * @param {import('antlr4-vensim').SubscriptRangeContext} ctx The ANTLR `SubscriptRangeContext`.\n * @returns {import('../../ast/ast-types').Expr} A `SubscriptRange` AST node.\n */\n /*public*/ visitSubscriptRange(ctx /*: SubscriptRangeContext*/) /*: DimensionDef*/ {\n this.subscriptNames = []\n this.subscriptMappings = []\n\n // TODO: For now, fill in an empty string for the comment; this is mainly\n // for compatibility with unit tests that expect empty string instead of\n // undefined, but this should be revisited\n const comment = ''\n\n // A subscript alias has two identifiers, while a regular subscript range definition\n // has just one\n const ids = ctx.Id()\n if (ids.length === 1) {\n // This is a regular subscript range definition, which begins with the dimension name\n const dimName = ids[0].getText()\n const dimId = canonicalId(dimName)\n\n // Visit children to fill in the subscript range definition\n super.visitSubscriptRange(ctx)\n\n // Create a new subscript range definition (`DimensionDef`) from Vensim-format names.\n // - The family is provisionally set to the dimension name.\n // - It will be updated to the maximal dimension if this is a subdimension.\n // - The mapping value contains dimensions and indices in the toDim.\n // - It will be expanded and inverted to fromDim indices later.\n return {\n dimName,\n dimId,\n familyName: dimName,\n familyId: dimId,\n subscriptRefs: this.subscriptNames.map(subName => {\n return {\n subName,\n subId: canonicalId(subName)\n }\n }),\n subscriptMappings: this.subscriptMappings,\n comment\n }\n } else if (ids.length === 2) {\n // This is a dimension alias (`DimA <-> DimB`)\n const dimName = ids[0].getText()\n const dimId = canonicalId(dimName)\n const familyName = ids[1].getText()\n const familyId = canonicalId(familyName)\n return {\n dimName,\n dimId,\n familyName,\n familyId,\n subscriptRefs: [],\n subscriptMappings: [],\n comment\n }\n }\n }\n\n visitSubscriptDefList(ctx) {\n // A subscript def is either an `Id` (a single subscript name, like \"A1\") or a numeric range\n // like \"(A1-A3)\". Either form can appear in the list, for example, \"A1, (A5-A7), A9\".\n for (const subscriptDef of ctx.children) {\n if (subscriptDef.symbol?.type === ModelParser.Id) {\n this.subscriptNames.push(subscriptDef.getText())\n } else if (subscriptDef.ruleIndex === ModelParser.RULE_subscriptSequence) {\n this.visitSubscriptSequence(subscriptDef)\n }\n }\n }\n\n visitSubscriptSequence(ctx) {\n // This is a subscript sequence (aka numeric range), like \"(A1-A3)\".\n // Construct index names from the sequence start and end indices.\n // This assumes the indices begin with the same string and end with numbers.\n const re = /^(.*?)(\\d+)$/\n const ids = ctx.Id().map(id => id.getText())\n const matches = ids.map(id => re.exec(id))\n if (matches[0][1] === matches[1][1]) {\n const prefix = matches[0][1]\n const start = parseInt(matches[0][2])\n const end = parseInt(matches[1][2])\n for (let i = start; i <= end; i++) {\n this.subscriptNames.push(prefix + i)\n }\n }\n }\n\n visitSubscriptMapping(ctx) {\n // Get the name of the \"to\" part of the mapping\n const toDimName = ctx.Id().getText()\n\n // If a subscript list is part of the mapping, the names will be set by `visitSubscriptList`\n this.mappedSubscriptNames = []\n\n // Visit the rest of the mapping, which includes the subscript list portion\n super.visitSubscriptMapping(ctx)\n\n // Add the mappings\n this.subscriptMappings.push({\n toDimName,\n toDimId: canonicalId(toDimName),\n subscriptRefs: this.mappedSubscriptNames.map(subName => {\n return {\n subName,\n subId: canonicalId(subName)\n }\n })\n })\n }\n\n visitSubscriptList(ctx) {\n // When parsing subscript range definitions, a subscript list is only used in the context\n // of a subscript mapping. It contains a list of subscript index names.\n this.mappedSubscriptNames = ctx.Id().map(id => id.getText())\n }\n\n visitCall(ctx) {\n // A subscript range can have a `GET DIRECT SUBSCRIPT` call on the RHS\n const fnName = ctx.Id().getText()\n const fnId = canonicalFunctionId(fnName)\n if (fnId === '_GET_DIRECT_SUBSCRIPT') {\n super.visitCall(ctx)\n } else {\n throw new Error(\n `Only 'GET DIRECT SUBSCRIPT' calls are supported in subscript range definitions, but saw '${fnName}'`\n )\n }\n }\n\n visitExprList(ctx) {\n // The only call that ends up here is `GET DIRECT SUBSCRIPT`. The arguments\n // are all strings that are delimited with single quotes, so strip those before\n // passing the arguments to the `getDirectSubscripts` function.\n const args = ctx.expr().map(expr => {\n const exprText = expr.getText()\n return exprText.replaceAll(\"'\", '')\n })\n\n // Delegate to the context\n const fileName = args[0]\n const tabOrDelimiter = args[1]\n const firstCell = args[2]\n const lastCell = args[3]\n const prefix = args[4]\n this.subscriptNames =\n this.parseContext?.getDirectSubscripts(fileName, tabOrDelimiter, firstCell, lastCell, prefix) || []\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport antlr4 from 'antlr4'\nimport { ModelLexer, ModelParser } from 'antlr4-vensim'\n\n/**\n * Create a `ModelParser` for the given model text, which can be the\n * contents of an entire `mdl` file, or a portion of one (e.g., an\n * expression or definition).\n *\n * @param {string} input The string containing the model text.\n * @return {ModelParser} A `ModelParser` from which a parse tree can be obtained.\n */\nexport function createAntlrParser(input) {\n // Create a custom error handler that will override the defafult one, which\n // only logs errors to stderr. The custom handler will rethrow the error (for\n // fail-fast behavior).\n const errorListener = new CustomErrorListener(input)\n\n // Create a lexer for the input (with custom error handler)\n let chars = new antlr4.InputStream(input)\n let lexer = new ModelLexer(chars)\n lexer.removeErrorListeners()\n lexer.addErrorListener(errorListener)\n\n // Create a parser around the result of the lexer (with custom error handler)\n // error listener.\n let tokens = new antlr4.CommonTokenStream(lexer)\n let parser = new ModelParser(tokens)\n parser.buildParseTrees = true\n parser.removeErrorListeners()\n parser.addErrorListener(errorListener)\n\n return parser\n}\n\nclass CustomErrorListener extends antlr4.error.ErrorListener {\n constructor(input) {\n super()\n this.input = input\n }\n\n syntaxError(_recognizer, _offendingSymbol, line, column, msg /*, err*/) {\n throw new Error(msg, {\n cause: {\n code: 'VensimParseError',\n line,\n column\n }\n })\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { DimensionDef } from '../ast/ast-types'\nimport type { VensimParseContext } from './vensim-parse-context'\nimport { SubscriptRangeReader } from './impl/subscript-range-reader'\n\n/**\n * Parse the given Vensim subscript range definition and return a `DimensionDef` AST node.\n *\n * @param input A string containing the Vensim subscript range definition.\n * @param context An object that provides access to file system resources (such as\n * external data files) that are referenced during the parse phase.\n * @returns A `DimensionDef` AST node.\n */\nexport function parseVensimSubscriptRange(input: string, context?: VensimParseContext): DimensionDef {\n // TODO: Reuse reader instance?\n const subscriptReader = new SubscriptRangeReader(context)\n return subscriptReader.parse(input)\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { ModelLexer, ModelVisitor } from 'antlr4-vensim'\n\nimport { canonicalFunctionId, canonicalId } from '../../_shared/canonical-id'\n\nimport { createAntlrParser } from './antlr-parser'\n\nexport class ExprReader extends ModelVisitor {\n constructor() {\n super()\n\n // Stack of function names and argument indices encountered on the RHS\n this.callStack = []\n }\n\n /**\n * Parse the given Vensim expression definition and return an `Expr` AST node.\n *\n * @public\n * @param {string} exprText A string containing the Vensim expression.\n * @returns {import('../../ast/ast-types').Expr} An `Expr` AST node.\n */\n /*public*/ parse(exprText /*: string*/) /*: Expr*/ {\n const parser = createAntlrParser(exprText)\n const exprCtx = parser.expr()\n return this.visitExpr(exprCtx)\n }\n\n /**\n * Process the given ANTLR `ExprContext` from an already parsed Vensim\n * expression definition.\n *\n * @public\n * @param {import('antlr4-vensim').ExprContext} ctx The ANTLR `ExprContext`.\n * @returns {import('../../ast/ast-types').Expr} An `Expr` AST node.\n */\n /*public*/ visitExpr(ctx /*: ExprContext*/) /*: Expr*/ {\n ctx.accept(this)\n return this.expr\n }\n\n //\n // Constants\n //\n\n visitConst(ctx) {\n const text = ctx.Const().getText()\n if (text.startsWith(\"'\") && text.endsWith(\"'\")) {\n // Treat it as a string\n this.expr = {\n kind: 'string',\n text: text.substr(1, text.length - 2)\n }\n } else {\n // Treat it as a number\n const value = parseFloat(text)\n this.expr = {\n kind: 'number',\n value,\n text\n }\n }\n }\n\n //\n // Keywords\n //\n\n visitKeyword(ctx) {\n const text = ctx.Keyword().getText()\n this.expr = {\n kind: 'keyword',\n text\n }\n }\n\n //\n // Function calls and variables\n //\n\n visitCall(ctx) {\n // Convert the function name from Vensim to C format\n const vensimFnName = ctx.Id().getText()\n const fnId = canonicalFunctionId(vensimFnName)\n this.callStack.push({ fn: fnId, args: [] })\n super.visitCall(ctx)\n const callInfo = this.callStack.pop()\n this.expr = {\n kind: 'function-call',\n fnName: vensimFnName,\n fnId: fnId,\n args: callInfo.args\n }\n }\n\n visitExprList(ctx) {\n const exprs = ctx.expr()\n for (let i = 0; i < exprs.length; i++) {\n // this.setArgIndex(i)\n exprs[i].accept(this)\n const n = this.callStack.length\n if (n > 0) {\n this.callStack[n - 1].args.push(this.expr)\n }\n }\n }\n\n visitVar(ctx) {\n // Convert the variable name from Vensim to C format\n const vensimVarName = ctx.Id().getText().trim()\n const varId = canonicalId(vensimVarName)\n\n // Process the subscripts (if any) that follow the variable name\n this.subscripts = undefined\n super.visitVar(ctx)\n const subscriptNames = this.subscripts\n const subscriptRefs = subscriptNames?.map(name => {\n return {\n subName: name,\n subId: canonicalId(name)\n }\n })\n this.subscripts = undefined\n\n this.expr = {\n kind: 'variable-ref',\n varName: vensimVarName,\n varId: varId,\n subscriptRefs\n }\n }\n\n visitSubscriptList(ctx) {\n // Get the subscripts found in the var name\n this.subscripts = ctx.Id().map(id => id.getText())\n }\n\n //\n // Lookups\n //\n\n getPoint(lookupPoint) {\n const exprs = lookupPoint.expr()\n if (exprs.length >= 2) {\n return [parseFloat(exprs[0].getText()), parseFloat(exprs[1].getText())]\n }\n }\n\n visitLookupRange(ctx) {\n this.lookupRange = ctx.lookupPoint().map(p => this.getPoint(p))\n super.visitLookupRange(ctx)\n }\n\n visitLookupPointList(ctx) {\n this.lookupPoints = ctx.lookupPoint().map(p => this.getPoint(p))\n super.visitLookupPointList(ctx)\n }\n\n visitLookupArg(ctx) {\n super.visitLookupArg(ctx)\n let range\n if (this.lookupRange && this.lookupRange.length === 2) {\n range = {\n min: this.lookupRange[0],\n max: this.lookupRange[1]\n }\n }\n this.expr = {\n kind: 'lookup-def',\n range,\n points: this.lookupPoints\n }\n this.lookupRange = undefined\n this.lookupPoints = undefined\n }\n\n visitLookupCall(ctx) {\n // Process the lookup variable name\n const lookupVarName = ctx.Id().getText()\n const lookupVarId = canonicalId(lookupVarName)\n\n // Process any subscripts that follow the variable name\n if (ctx.subscriptList()) {\n ctx.subscriptList().accept(this)\n }\n const subscriptNames = this.subscripts\n const subscriptRefs = subscriptNames?.map(name => {\n return {\n subName: name,\n subId: canonicalId(name)\n }\n })\n this.subscripts = undefined\n\n const lookupVarRef = {\n kind: 'variable-ref',\n varName: lookupVarName,\n varId: lookupVarId,\n subscriptRefs\n }\n\n // Process the single lookup argument\n ctx.expr().accept(this)\n const lookupArg = this.expr\n\n this.expr = {\n kind: 'lookup-call',\n varRef: lookupVarRef,\n arg: lookupArg\n }\n }\n\n //\n // Unary operators\n //\n\n completeUnary(op /*: UnaryOp*/) {\n const child = this.expr\n this.expr = {\n kind: 'unary-op',\n op,\n expr: child\n }\n }\n\n visitNegative(ctx) {\n super.visitNegative(ctx)\n this.completeUnary('-')\n }\n\n visitPositive(ctx) {\n super.visitPositive(ctx)\n this.completeUnary('+')\n }\n\n visitNot(ctx) {\n super.visitNot(ctx)\n this.completeUnary(':NOT:')\n }\n\n //\n // Binary operators\n //\n\n visitBinaryArgs(ctx, op /*: BinaryOp*/) {\n ctx.expr(0).accept(this)\n const lhs = this.expr\n ctx.expr(1).accept(this)\n const rhs = this.expr\n this.expr = {\n kind: 'binary-op',\n lhs,\n op,\n rhs\n }\n }\n\n visitPower(ctx) {\n this.visitBinaryArgs(ctx, '^')\n }\n\n visitMulDiv(ctx) {\n this.visitBinaryArgs(ctx, ctx.op.type === ModelLexer.Star ? '*' : '/')\n }\n\n visitAddSub(ctx) {\n this.visitBinaryArgs(ctx, ctx.op.type === ModelLexer.Plus ? '+' : '-')\n }\n\n visitRelational(ctx) {\n let op\n switch (ctx.op.type) {\n case ModelLexer.Less:\n op = '<'\n break\n case ModelLexer.Greater:\n op = '>'\n break\n case ModelLexer.LessEqual:\n op = '<='\n break\n case ModelLexer.GreaterEqual:\n op = '>='\n break\n default:\n throw new Error(`Unexpected relational operator '${op}'`)\n }\n this.visitBinaryArgs(ctx, op)\n }\n\n visitEquality(ctx) {\n this.visitBinaryArgs(ctx, ctx.op.type === ModelLexer.Equal ? '=' : '<>')\n }\n\n visitAnd(ctx) {\n this.visitBinaryArgs(ctx, ':AND:')\n }\n\n visitOr(ctx) {\n this.visitBinaryArgs(ctx, ':OR:')\n }\n\n //\n // Tokens\n //\n\n visitParens(ctx) {\n super.visitParens(ctx)\n\n const child = this.expr\n this.expr = {\n kind: 'parens',\n expr: child\n }\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { Expr } from '../ast/ast-types'\nimport { ExprReader } from './impl/expr-reader'\n\n/**\n * Parse the given Vensim expression definition and return an `Expr` AST node.\n *\n * @param input A string containing the Vensim expression.\n * @returns An `Expr` AST node.\n */\nexport function parseVensimExpr(input: string): Expr {\n // TODO: Reuse reader instance?\n const exprReader = new ExprReader()\n return exprReader.parse(input)\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { ModelVisitor } from 'antlr4-vensim'\n\nimport { canonicalId } from '../../_shared/canonical-id'\n\nimport { createAntlrParser } from './antlr-parser'\nimport { ExprReader } from './expr-reader'\n\nexport class EquationReader extends ModelVisitor {\n constructor() {\n super()\n }\n\n /**\n * Parse the given Vensim equation definition and return an `Equation` AST node.\n *\n * @public\n * @param {string} equationText A string containing the Vensim equation definition.\n * @return {import('../../ast/ast-types').Equation} An `Equation` AST node.\n */\n /*public*/ parse(equationText /*: string*/) /*: Equation*/ {\n const parser = createAntlrParser(equationText)\n const equationCtx = parser.equation()\n return this.visitEquation(equationCtx)\n }\n\n /**\n * Process the given ANTLR `EquationContext` from an already parsed Vensim\n * equation definition.\n *\n * @public\n * @param {import('antlr4-vensim').EquationContext} ctx The ANTLR `EquationContext`.\n * @returns {import('../../ast/ast-types').Equation} An `Equation` AST node.\n */\n /*public*/ visitEquation(ctx /*: EquationContext*/) /*: Equation*/ {\n this.equationLhs = undefined\n this.lookupDef = undefined\n\n ctx.lhs().accept(this)\n\n let equationRhs\n const exprCtx = ctx.expr()\n if (exprCtx) {\n const exprReader = new ExprReader()\n const expr = exprReader.visitExpr(exprCtx)\n equationRhs = {\n kind: 'expr',\n expr\n }\n } else if (ctx.constList()) {\n ctx.constList().accept(this)\n equationRhs = {\n kind: 'const-list',\n constants: this.constants,\n text: this.constListText\n }\n } else if (ctx.lookup()) {\n ctx.lookup().accept(this)\n equationRhs = {\n kind: 'lookup',\n lookupDef: this.lookupDef\n }\n } else {\n equationRhs = {\n kind: 'data'\n }\n }\n\n if (this.equationLhs) {\n this.equation = {\n lhs: this.equationLhs,\n rhs: equationRhs,\n // TODO: For now, fill in an empty string for these two; this is mainly\n // for compatibility with unit tests that expect empty string instead of\n // undefined, but this should be revisited\n units: '',\n comment: ''\n }\n }\n\n return this.equation\n }\n\n visitSubscriptList(ctx) {\n // Get the subscripts found in the var name\n if (this.subscripts === undefined) {\n // These are the primary subscripts\n this.subscripts = ctx.Id().map(id => id.getText())\n } else {\n // These are subscripts that follow the :EXCEPT: keyword. Note that there\n // can be more than one set of subscripts following :EXCEPT:, so we need\n // to keep an array\n if (this.exceptSubscriptSets === undefined) {\n this.exceptSubscriptSets = []\n }\n this.exceptSubscriptSets.push(ctx.Id().map(id => id.getText()))\n }\n }\n\n visitLhs(ctx) {\n // Process the variable name\n const lhsVarName = ctx.Id().getText()\n const lhsVarId = canonicalId(lhsVarName)\n\n // Process any subscripts that follow the variable name\n super.visitLhs(ctx)\n const subscriptNames = this.subscripts\n const subscriptRefs = subscriptNames?.map(name => {\n return {\n subName: name,\n subId: canonicalId(name)\n }\n })\n\n // Process additional sets of subscripts that follow the :EXCEPT: keyword\n const exceptSubscriptSets = this.exceptSubscriptSets\n const exceptSubscriptRefSets = exceptSubscriptSets?.map(subscriptSet => {\n return subscriptSet.map(name => {\n return {\n subName: name,\n subId: canonicalId(name)\n }\n })\n })\n this.subscripts = undefined\n this.exceptSubscripts = undefined\n\n this.equationLhs = {\n varDef: {\n kind: 'variable-def',\n varName: lhsVarName,\n varId: lhsVarId,\n subscriptRefs,\n exceptSubscriptRefSets\n }\n }\n }\n\n //\n // CONST LISTS\n //\n\n visitConstList(ctx) {\n // TODO: It would be better if resolved to a `NumberLiteral[][]` (one array per dimension) to\n // better match how it appears in a model, but the antlr4-vensim grammar currently flattens\n // them into a single list (it doesn't make use of the semicolon separator), so we have to\n // do the same for now\n this.constants = ctx.expr().map(expr => {\n const text = expr.getText()\n const value = parseFloat(text)\n return {\n kind: 'number',\n value,\n text\n }\n })\n this.constListText = ctx.getText()\n }\n\n //\n // LOOKUPS\n //\n\n getPoint(lookupPoint) {\n const exprs = lookupPoint.expr()\n if (exprs.length >= 2) {\n return [parseFloat(exprs[0].getText()), parseFloat(exprs[1].getText())]\n }\n }\n\n visitLookup(ctx) {\n this.lookupRange = undefined\n this.lookupPoints = undefined\n\n if (ctx.lookupRange()) {\n ctx.lookupRange().accept(this)\n }\n if (ctx.lookupPointList()) {\n ctx.lookupPointList().accept(this)\n }\n\n let range\n if (this.lookupRange && this.lookupRange.length === 2) {\n range = {\n min: this.lookupRange[0],\n max: this.lookupRange[1]\n }\n }\n this.lookupDef = {\n kind: 'lookup-def',\n range,\n points: this.lookupPoints\n }\n }\n\n visitLookupRange(ctx) {\n this.lookupRange = ctx.lookupPoint().map(p => this.getPoint(p))\n super.visitLookupRange(ctx)\n }\n\n visitLookupPointList(ctx) {\n this.lookupPoints = ctx.lookupPoint().map(p => this.getPoint(p))\n super.visitLookupPointList(ctx)\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { Equation } from '../ast/ast-types'\nimport { EquationReader } from './impl/equation-reader'\n\n/**\n * Parse the given Vensim equation definition and return an `Equation` AST node.\n *\n * @param input A string containing the Vensim equation definition.\n * @returns An `Equation` AST node.\n */\nexport function parseVensimEquation(input: string): Equation {\n // TODO: Reuse reader instance?\n const equationReader = new EquationReader()\n return equationReader.parse(input)\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport split from 'split-string'\n\n/**\n * A single Vensim definition (either a subscript range definition or an\n * equation definition). This contains the definition's text and metadata\n * that was extracted during preprocessing.\n */\nexport interface VensimDef {\n /**\n * A simplified key for the LHS of the definition, used for sorting\n * and/or flattening.\n */\n key: string\n /**\n * The preprocessed equation or subscript range definition (with\n * units and comment replaced with `~~|`).\n */\n def: string\n /**\n * The kind of definition; either 'eqn' for an equation containing an equals\n * sign, 'dim' for a dimension (subscript range) definition, or 'decl' for\n * all other declarations (e.g., a lookup or data variable definition).\n */\n kind: 'eqn' | 'dim' | 'decl'\n /**\n * The (1-based) line number where the definition begins.\n */\n line: number\n /**\n * The units text.\n */\n units: string\n /**\n * The comment text.\n */\n comment: string\n /**\n * The optional group name, if the definition is contained within a group.\n */\n group?: string\n}\n\n/**\n * Result type for the `preprocessVensimModel` function.\n */\nexport interface PreprocessedVensimModel {\n /**\n * The preprocessed definitions that were preserved.\n */\n defs: VensimDef[]\n /**\n * The macros that were removed by the preprocessor.\n */\n removedMacros: string[]\n /**\n * The text blocks that were removed by the preprocessor. These include\n * unsupported functions (such as `TABBED ARRAY`) and other definitions\n * that were requested for removal.\n */\n removedBlocks: string[]\n}\n\n/**\n * A raw definition extracted during preprocessing. This may or may not\n * contain an actual definition (for example, it might contain a section\n * comment).\n */\ninterface RawDef {\n /**\n * The text of the raw definition.\n */\n text: string\n /**\n * The (1-based) line number where the definition begins.\n */\n line: number\n /**\n * The group in which the definition is contained (can be undefined if\n * the definition is not inside a group).\n */\n group?: string\n}\n\n/**\n * Process the given Vensim model content so that it can be parsed\n * by `antlr4-vensim`. This will:\n * - strip out group markers\n * - remove macro definitions, which are currently unsupported\n * - remove equations that reference certain unsupported functions\n * (e.g., `TABBED ARRAY`)\n * - remove everything in the private Vensim sketch section\n * - join lines that are separated by a continuation (backslash)\n * - split the input into distinct definitions (equations and\n * subscript ranges)\n *\n * The definitions are further processed to preserve the units and\n * comment text in separate properties, but strips them from the\n * equation string (replaced with `~~`) to make it easier for\n * `antlr4-vensim` to process.\n *\n * @param input The original Vensim mdl file content.\n * @param options The options that control preprocessing.\n * @return A `PreprocessedVensimModel` instance containing the preprocessed\n * Vensim definitions.\n */\nexport function preprocessVensimModel(input: string, options?: { removalKeys?: string[] }): PreprocessedVensimModel {\n // Helper function that returns true if the given def should be removed\n const removalKeys = options?.removalKeys\n function shouldRemove(text: string): boolean {\n // Remove definitions that include `TABBED ARRAY`\n if (text.includes('TABBED ARRAY')) {\n return true\n }\n\n // Remove definitions that include one of the provided removal keys\n if (removalKeys) {\n for (const key of removalKeys) {\n if (text.includes(key)) {\n return true\n }\n }\n }\n\n // Otherwise, don't remove\n return false\n }\n\n // Remove macro definitions since they are not currently supported. We replace\n // the text in the input string with blank lines where the macro definition\n // appeared so that line numbers for definitions that follow are unaffected.\n const macrosResult = removeMacros(input)\n input = macrosResult.processed\n\n // Split the model into an array of definitions (includes equations,\n // subscript ranges, and groups)\n const rawDefs = splitDefs(input)\n\n // Keep only equations and subscript range defintions\n const vensimDefs: VensimDef[] = []\n const removedBlocks: string[] = []\n for (const rawDef of rawDefs) {\n // Remove definitions that include `TABBED ARRAY` or one of the requested\n // removal keys\n if (shouldRemove(rawDef.text)) {\n removedBlocks.push(rawDef.text.trim() + '|')\n continue\n }\n\n // Process the definition\n const vensimDef = processDef(rawDef)\n if (vensimDef) {\n vensimDefs.push(vensimDef)\n }\n }\n\n return {\n defs: vensimDefs,\n removedMacros: macrosResult.removed,\n removedBlocks: removedBlocks\n }\n}\n\n/**\n * Split a Vensim model string into an array of definitions (including\n * equations, subscript ranges, and groups), without the \"|\" terminator.\n * This will allow \"|\" to occur in quoted variable names across line breaks.\n * Backslash characters will be retained.\n */\nfunction splitDefs(input: string): RawDef[] {\n // Split the full input string into definitions delineated by the \"|\" separator.\n // Note that we use the `quotes` option so that the `split` function will not\n // split on \"|\" characters that appear inside a quoted variable name, for example:\n // \"quoted variable name with | pipe\" = 5 ~~|\n const defTexts = split(input, { separator: '|', quotes: ['\"'], keep: () => true })\n\n // Calculate starting line number for each definition by accounting for the\n // number of line breaks in that definition\n const rawDefs = []\n let lineNum = 1\n let currentGroup: string\n for (let defText of defTexts) {\n if (lineNum === 1) {\n // Strip the encoding (included in first def)\n defText = defText.replace('{UTF-8}', '')\n }\n\n if (defText.includes('\\\\---/// Sketch')) {\n // Skip everything starting with the first sketch section\n break\n }\n\n // Split on the first non-whitespace character\n const parts = defText.match(/(\\s*)(.*)/ms)\n\n // Take leading line breaks into account so that we find the line where the\n // actual definition begins\n const leadingLineBreaks = parts[1]?.match(/\\r\\n|\\n|\\r/gm)\n lineNum += leadingLineBreaks?.length || 0\n\n // See if this is a group header\n if (defText.includes('********************************************************')) {\n // This is a group; save the group name\n const groupLines = splitLines(defText).filter(s => s.trim().length > 0)\n currentGroup = undefined\n if (groupLines.length > 1) {\n const groupNameLine = groupLines[1]\n const groupNameParts = groupNameLine.match(/^\\s*\\.(.*)$/)\n if (groupNameParts) {\n currentGroup = groupNameParts[1]\n }\n }\n } else {\n // This is a regular definition; add it\n rawDefs.push({\n text: defText,\n line: lineNum,\n group: currentGroup\n })\n }\n\n // Increment by the number of line breaks that appear in the definition content\n const contentLineBreaks = parts[2]?.match(/\\r\\n|\\n|\\r/gm)\n lineNum += contentLineBreaks?.length || 0\n }\n\n return rawDefs\n}\n\n/**\n * Split a string into separate lines.\n */\nfunction splitLines(input: string): string[] {\n // Windows, Unix, or old Mac line endings\n return input.split(/\\r\\n|\\n|\\r/)\n}\n\n/**\n * Split a string on the given separator character. This will not split\n * if the character appears inside a quoted variable name. For example,\n * this will not split on '(' when it appears in the variable name, but\n * will split the '(' in the lookup expression\n * \"quoted variable (name)\" ((0,0),(1,1)) ~~|\n */\nfunction splitExceptInQuoted(input: string, sep: string): string[] {\n return split(input, { separator: sep, quotes: ['\"'] })\n}\n\n/**\n * Join lines that are separated by a continuation (backslash) character.\n */\nfunction processBackslashes(input: string): string {\n const inputLines = splitLines(input)\n\n let output = ''\n let prevLine = ''\n for (let line of inputLines) {\n // Join a previous line with a backslash ending to the current line\n if (prevLine !== '') {\n line = prevLine + line.trim()\n prevLine = ''\n }\n const continuation = line.match(/\\\\\\s*$/)\n if (continuation) {\n // If there is a backslash ending on this line, save it without the backslash\n prevLine = line.substr(0, continuation.index).replace(/\\s+$/, ' ')\n } else {\n // There is no continuation on this line, include in output\n output += line + '\\n'\n }\n }\n\n return output\n}\n\n/**\n * Match delimiters recursively. Replace delimited strings globally.\n *\n * @param str The string to operate on.\n * @param open The opening delimiter characters.\n * @param close The closing delimiter characters.\n * @param newStr The string to replace delimited substrings with.\n */\nfunction replaceDelimitedStrings(str: string, open: string, close: string, newStr: string): string {\n let result = ''\n let start = 0\n let depth = 0\n const n = str.length\n for (let i = 0; i < n; i++) {\n if (str.charAt(i) === open) {\n if (depth === 0) {\n result += str.substring(start, i)\n }\n depth++\n } else if (str.charAt(i) === close && depth > 0) {\n depth--\n if (depth === 0) {\n result += newStr\n start = i + 1\n }\n }\n }\n if (start < n) {\n result += str.substring(start)\n }\n return result\n}\n\n/**\n * Replace all newlines and redundant whitespace into single spaces so\n * that everything is on a single line.\n */\nfunction reduceWhitespace(input: string): string {\n return input.replace(/\\s\\s+/g, ' ').trim()\n}\n\n// Detect one or more consecutive whitespace or underscore characters\nconst reWhitespace = new RegExp('(\\\\s|_)+', 'g')\n\n/**\n * Create a key from the given definition's LHS that can be used during\n * flattening and/or sorting, and include the kind.\n */\nfunction keyForDef(def: string): { key: string; kind: 'eqn' | 'dim' | 'decl' } {\n // Note: The steps in this function were lifted directly from the legacy\n // preprocessor, mainly so that we would retain compatibility when writing\n // tests that compare the legacy parser to the new one.\n\n let key = def\n\n // Strip the \":INTERPOLATE:\"; it should not be included in the key\n key = key.replace(/:INTERPOLATE:/g, '')\n\n let kind: 'eqn' | 'dim' | 'decl'\n if (key.includes('=')) {\n // The line contains an '='; treat this as an equation\n kind = 'eqn'\n key = key.split('=')[0].trim()\n } else if (key.includes(':')) {\n // The line contains a ':'; treat this as a subscript range (dimension)\n kind = 'dim'\n key = key.split(':')[0].trim()\n } else {\n // Treat this as a general declaration\n kind = 'decl'\n }\n\n // Ignore the lookup data if it starts on the first line\n key = splitExceptInQuoted(key, '(')[0]\n\n // Ignore double quotes\n key = key.replace(/\"/g, '')\n\n // Ignore any leading or trailing whitespace that remains\n key = key.trim()\n\n // Remove whitespace on the inside of the brackets\n key = key.replace(/(?<=\\[).*?(?=\\])/g, match => match.replace(/\\s/g, ''))\n\n // Replace one or more consecutive whitespace or underscore characters with a single\n // underscore character; this matches the behavior of Vensim documented here:\n // https://www.vensim.com/documentation/ref_variable_names.html\n key = key.replace(reWhitespace, '_')\n\n // Ignore case\n key = key.toLowerCase()\n\n return { key, kind }\n}\n\n/**\n * Strip out unnecessary parts of the given raw definition string and\n * return a `VensimDef` containing the processed definition along with\n * the units and comment strings.\n */\nfunction processDef(rawDef: RawDef): VensimDef | undefined {\n let input = rawDef.text\n\n // Remove \":RAW:\" flag; it is not needed by SDE and causes problems if left in\n input = input.replace(/:RAW:/g, '')\n\n // Remove inline comments\n input = replaceDelimitedStrings(input, '{', '}', '')\n\n // Remove whitespace\n input = input.trim()\n\n // Skip empty definitions\n if (input.length === 0) {\n return undefined\n }\n\n // Join lines that are separated by a continuation (backslash) character\n input = processBackslashes(input)\n\n // Split on the comment delimiters\n const parts = input.split('~')\n\n // If the definition is malformed, throw an error\n if (parts.length < 3) {\n throw new Error(`Found invalid model definition during preprocessing (missing comment delimiters?):\\n\\n${input}`)\n }\n\n // Get the raw def as a single line\n const rawDefText = reduceWhitespace(parts[0])\n\n // Create the key\n const { key, kind } = keyForDef(rawDefText)\n\n // Rebuild the def with a simple `~~|` ending\n const def = `${rawDefText} ~~|`\n\n // Extract the units text\n const units = reduceWhitespace(parts[1])\n\n // Extract the comment text\n // TODO: Preserve newlines in comments?\n const comment = reduceWhitespace(parts[2])\n\n // TODO: Extract the `:SUPPLEMENTARY:` flags?\n\n // Preserve the group name, if defined\n const group = rawDef.group\n\n return {\n key,\n def,\n kind,\n line: rawDef.line,\n units,\n comment,\n ...(group ? { group } : {})\n }\n}\n\n/**\n * Remove macro definitions from the input string. We replace the text in the input\n * string with blank lines where the macro definition appeared so that line numbers\n * for definitions that follow are unaffected.\n *\n * @param input The original Vensim mdl file content.\n * @return The processed string and the text blocks that were removed.\n */\nfunction removeMacros(input: string): { processed: string; removed: string[] } {\n // Keep an array of removed strings\n const removed: string[] = []\n\n // Find all macro definitions\n const processed = input.replace(/:MACRO:.*:END OF MACRO:/gms, match => {\n // Add the removed macro to the array\n removed.push(match)\n\n // Replace each macro definition with blank lines so that line numbers for\n // definitions that follow are unaffected\n const numBreaks = match.split(/\\r\\n|\\n|\\r/gms).length - 1\n return numBreaks > 0 ? '\\n'.repeat(numBreaks) : ''\n })\n\n return {\n processed,\n removed\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { ModelVisitor } from 'antlr4-vensim'\n\nimport { createAntlrParser } from './antlr-parser'\nimport { EquationReader } from './equation-reader'\nimport { SubscriptRangeReader } from './subscript-range-reader'\n\nexport class ModelReader extends ModelVisitor {\n /**\n * @public\n * @param {import('../vensim-parse-context').VensimParseContext} parseContext An object\n * that provides access to file system resources (such as external data files) that are\n * referenced during the parse phase.\n */\n constructor(parseContext /*: VensimParseContext*/) {\n super()\n this.parseContext = parseContext\n this.dimensions = []\n this.equations = []\n }\n\n /**\n * Parse the given Vensim model definition and return a `Model` AST node.\n *\n * @public\n * @param {string} modelText A string containing the Vensim model.\n * @returns {import('../../ast/ast-types').Model} A `Model` AST node.\n */\n /*public*/ parse(modelText /*: string*/) /*: Model*/ {\n const parser = createAntlrParser(modelText)\n const modelCtx = parser.model()\n modelCtx.accept(this)\n return this.model\n }\n\n visitModel(ctx) {\n const subscriptRangesCtx = ctx.subscriptRange()\n if (subscriptRangesCtx) {\n // TODO: Can we reuse reader instances?\n const subscriptReader = new SubscriptRangeReader(this.parseContext)\n for (const subscriptRangeCtx of subscriptRangesCtx) {\n const dimensionDef = subscriptReader.visitSubscriptRange(subscriptRangeCtx)\n this.dimensions.push(dimensionDef)\n }\n }\n\n const equationsCtx = ctx.equation()\n if (equationsCtx) {\n // TODO: Can we reuse reader instances?\n const equationReader = new EquationReader()\n for (const equationCtx of equationsCtx) {\n const equation = equationReader.visitEquation(equationCtx)\n this.equations.push(equation)\n }\n }\n\n this.model = {\n dimensions: this.dimensions,\n equations: this.equations\n }\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { DimensionDef, Equation, Model } from '../ast/ast-types'\nimport { preprocessVensimModel } from './preprocess-vensim'\nimport type { VensimParseContext } from './vensim-parse-context'\nimport { ModelReader } from './impl/model-reader'\n\n/**\n * Parse the given Vensim model definition and return a `Model` AST node.\n *\n * @param input A string containing the Vensim model.\n * @param context An object that provides access to file system resources (such as\n * external data files) that are referenced during the parse phase.\n * @param sort Whether to sort definitions alphabetically during the preprocessing phase.\n * @returns A `Model` AST node.\n */\nexport function parseVensimModel(input: string, context?: VensimParseContext, sort = false): Model {\n const dimensions: DimensionDef[] = []\n const equations: Equation[] = []\n\n // Run the preprocessor on the input (to separate out units, comments, unsupported\n // sections, etc) so that it can be parsed more easily by `antlr4-vensim`.\n const { defs } = preprocessVensimModel(input)\n if (sort) {\n // Sort the definitions alphabetically by key. This mainly exists for compatibility\n // with the legacy preprocessor; it is not an essential step so is left disabled\n // by default.\n defs.sort((a, b) => {\n return a.key < b.key ? -1 : a.key > b.key ? 1 : 0\n })\n }\n\n // Parse each subscript range or equation definition\n for (const def of defs) {\n // TODO: Reuse reader instance?\n let parsedModel: Model\n try {\n const modelReader = new ModelReader(context)\n parsedModel = modelReader.parse(def.def)\n } catch (e) {\n // Include context such as line/column numbers in the error message if available\n let linePart = ''\n if (e.cause?.code === 'VensimParseError') {\n if (e.cause.line) {\n // The line number reported by ANTLR is relative to the beginning of the\n // preprocessed definition (since we parse each definition individually),\n // so we need to add it to the line of the definition in the original source\n linePart += ` at line ${e.cause.line - 1 + def.line}`\n if (e.cause.column) {\n linePart += `, col ${e.cause.column}`\n }\n }\n }\n const msg = `Failed to parse Vensim model definition${linePart}:\\n${def.def}\\n\\nDetail:\\n ${e.message}`\n throw new Error(msg)\n }\n\n for (const dimensionDef of parsedModel.dimensions) {\n // Fold in the other strings that were extracted during preprocessing\n const group = def.group\n dimensions.push({\n ...dimensionDef,\n comment: def.comment,\n ...(group ? { group } : {})\n })\n }\n\n for (const equation of parsedModel.equations) {\n // Fold in the other strings that were extracted during preprocessing\n const group = def.group\n equations.push({\n ...equation,\n units: def.units,\n comment: def.comment,\n ...(group ? { group } : {})\n })\n }\n }\n\n return {\n dimensions,\n equations\n }\n}\n"],"mappings":"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","names":["assertNever","assertNever","num","ModelParser","ModelParser","ModelLexer","ModelVisitor","ModelVisitor","ModelLexer","ModelVisitor","ModelVisitor","reWhitespace","ModelVisitor","ModelVisitor"]}
|
|
1
|
+
{"version":3,"sources":["../src/_shared/canonical-id.js","../src/ast/print-expr.ts","../src/ast/reduce-expr.ts","../src/ast/ast-builders.ts","../src/vensim/impl/subscript-range-reader.js","../src/vensim/impl/antlr-parser.js","../src/vensim/parse-vensim-subscript-range.ts","../src/vensim/impl/expr-reader.js","../src/vensim/parse-vensim-expr.ts","../src/vensim/impl/equation-reader.js","../src/vensim/parse-vensim-equation.ts","../src/vensim/preprocess-vensim.ts","../src/vensim/impl/model-reader.js","../src/vensim/parse-vensim-model.ts","../src/xmile/xml.ts","../src/xmile/parse-xmile-dimension-def.ts","../src/xmile/parse-xmile-model.ts","../src/xmile/parse-xmile-variable-def.ts"],"sourcesContent":["// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\n// Detect '!' at the end of a marked dimension when preceded by whitespace\nconst reTrailingMark = new RegExp('\\\\s+!$', 'g')\n\n// Detect one or more consecutive whitespace or underscore characters\nconst reWhitespace = new RegExp('(\\\\s|_)+', 'g')\n\n// Detect special punctuation characters\n// TODO: We do not currently include '!' characters in this set; we should only replace these\n// when they don't appear at the end of a (marked) dimension\nconst reSpecialChars = new RegExp(`['\"\\\\.,\\\\-\\\\$&%\\\\/\\\\|()]`, 'g')\n\n/**\n * Format a model variable or subscript/dimension name into a valid C identifier (with\n * special characters converted to underscore).\n *\n * Note that this should only be called with an individual variable base name (e.g.,\n * 'Variable name') or a subscript/dimension name (e.g., 'DimA'). In the case where\n * you have a full variable name that includes subscripts/dimensions (e.g.,\n * 'Variable name[DimA,B2]'), use `canonicalVarId` to convert the base variable name\n * and subscript/dimension parts to canonical form indepdendently.\n *\n * @param {string} name The name of the variable in the source model, e.g., \"Variable name\".\n * @returns {string} The C identifier for the given name, e.g., \"_variable_name\".\n */\nexport function canonicalId(name) {\n return (\n '_' +\n name\n // Ignore any leading or trailing whitespace\n .trim()\n // When a '!' character appears at the end of a marked dimension, preserve the mark\n // but remove any preceding whitespace\n .replace(reTrailingMark, '!')\n // Replace one or more consecutive whitespace or underscore characters with a single\n // underscore character; this matches the behavior of Vensim documented here:\n // https://www.vensim.com/documentation/ref_variable_names.html\n .replace(reWhitespace, '_')\n // Replace each special punctuation character with an underscore\n .replace(reSpecialChars, '_')\n // Convert to lower case\n .toLowerCase()\n )\n}\n\n/**\n * Format a (subscripted or non-subscripted) model variable name into a canonical identifier,\n * (with special characters converted to underscore, and subscript/dimension parts separated\n * by commas).\n *\n * @param {string} name The name of the variable in the source model, e.g., \"Variable name[DimA, B2]\".\n * @returns {string} The canonical identifier for the given name, e.g., \"_variable_name[_dima,_b2]\".\n */\nexport function canonicalVarId(name) {\n const m = name.match(/([^[]+)(?:\\[([^\\]]+)\\])?/)\n if (!m) {\n throw new Error(`Invalid variable name: ${name}`)\n }\n\n let id = canonicalId(m[1])\n if (m[2]) {\n const subscripts = m[2].split(',').map(x => canonicalId(x))\n id += `[${subscripts.join(',')}]`\n }\n\n return id\n}\n\n/**\n * Format a model function name into a valid C identifier (with special characters\n * converted to underscore, and the ID converted to uppercase).\n *\n * @param {string} name The name of the variable in the source model, e.g., \"FUNCTION name\".\n * @returns {string} The C identifier for the given name, e.g., \"_FUNCTION_NAME\".\n */\nexport function canonicalFunctionId(name) {\n return canonicalId(name).toUpperCase()\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { assertNever } from 'assert-never'\n\nimport type { Expr, VariableRef } from '../ast/ast-types'\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function debugPrintExpr(expr: Expr, indent = 0): void {\n const spaces = ' '.repeat(indent * 2)\n const log = (s: string) => {\n console.log(`${spaces}${s}`)\n }\n\n switch (expr.kind) {\n case 'number':\n log(`const: ${expr.text}`)\n break\n\n case 'string':\n log(`string: ${expr.text}`)\n break\n\n case 'keyword':\n log(`keyword: ${expr.text}`)\n break\n\n case 'variable-ref':\n log(`ref: ${fullIdForVarRef(expr)}`)\n break\n\n case 'unary-op':\n log(`unary-op: ${expr.op}`)\n debugPrintExpr(expr.expr, indent + 1)\n break\n\n case 'binary-op':\n log(`binary-op: ${expr.op}`)\n debugPrintExpr(expr.lhs, indent + 1)\n debugPrintExpr(expr.rhs, indent + 1)\n break\n\n case 'parens':\n log('parens')\n debugPrintExpr(expr.expr, indent + 1)\n break\n\n case 'lookup-def':\n // TODO: Include range and points?\n log(`lookup-def`)\n break\n\n case 'lookup-call':\n log(`lookup-call: ${debugPrintExpr(expr.varRef)}`)\n debugPrintExpr(expr.arg, indent + 1)\n break\n\n case 'function-call':\n log(`function-call: ${expr.fnId}`)\n expr.args.forEach(arg => debugPrintExpr(arg, indent + 1))\n break\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport type FormatVariableRefFunc = (varRef: VariableRef) => string\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport interface PrettyOpts {\n /**\n * Whether to use a compact representation without additional spaces. (The compact form mimics\n * the behavior of the legacy parser.\n */\n compact?: boolean\n html?: boolean\n formatVariableRef?: FormatVariableRefFunc\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function toPrettyString(expr: Expr, opts?: PrettyOpts): string {\n let lparen: string, rparen: string, spaceSep: string, commaSep: string\n if (opts?.compact === true) {\n lparen = '('\n rparen = ')'\n spaceSep = ''\n commaSep = ','\n } else {\n lparen = '( '\n rparen = ' )'\n spaceSep = ' '\n commaSep = ', '\n }\n\n switch (expr.kind) {\n case 'number':\n return expr.text\n\n case 'string':\n return `'${expr.text}'`\n\n case 'keyword':\n return expr.text\n\n case 'variable-ref':\n if (opts?.formatVariableRef) {\n return opts.formatVariableRef(expr)\n } else {\n if (expr.subscriptRefs?.length > 0) {\n return `${expr.varName}[${expr.subscriptRefs.map(ref => ref.subName).join(commaSep)}]`\n } else {\n return expr.varName\n }\n }\n\n case 'unary-op':\n if (expr.op === ':NOT:') {\n return `${expr.op} ${toPrettyString(expr.expr, opts)}`\n } else {\n return `${expr.op}${toPrettyString(expr.expr, opts)}`\n }\n\n case 'binary-op': {\n let op: string\n if (opts?.html === true) {\n switch (expr.op) {\n case '<':\n op = '<'\n break\n case '<=':\n op = '<='\n break\n case '>':\n op = '>'\n break\n case '>=':\n op = '>='\n break\n default:\n op = expr.op\n break\n }\n } else {\n op = expr.op\n }\n const lhs = toPrettyString(expr.lhs, opts)\n const rhs = toPrettyString(expr.rhs, opts)\n return `${lhs}${spaceSep}${op}${spaceSep}${rhs}`\n }\n\n case 'parens':\n return `${lparen}${toPrettyString(expr.expr, opts)}${rparen}`\n\n case 'lookup-def': {\n const pointString = (p: [number, number]) => {\n return `(${p[0]},${p[1]})`\n }\n const points = expr.points.map(pointString).join(commaSep)\n if (expr.range) {\n const min = pointString(expr.range.min)\n const max = pointString(expr.range.max)\n return `${lparen}[${min}-${max}]${commaSep}${points}${rparen}`\n } else {\n return `${lparen}${points}${rparen}`\n }\n }\n\n case 'lookup-call': {\n const varRef = toPrettyString(expr.varRef, opts)\n const arg = toPrettyString(expr.arg, opts)\n return `${varRef}${lparen}${arg}${rparen}`\n }\n\n case 'function-call': {\n const args = expr.args.map(arg => toPrettyString(arg, opts))\n return `${expr.fnName}${lparen}${args.join(commaSep)}${rparen}`\n }\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function prettyPrintExpr(expr: Expr, indent = 0): void {\n const spaces = ' '.repeat(indent * 2)\n const log = (s: string) => {\n console.log(`${spaces}${s}`)\n }\n log(toPrettyString(expr))\n}\n\ntype CountMap = Map<string, number>\n\nclass Stats {\n constCount = 0\n varRefCount = 0\n readonly unaryOpCounts: CountMap = new Map()\n readonly binaryOpCounts: CountMap = new Map()\n readonly fnCallCounts: CountMap = new Map()\n readonly luCallCounts: CountMap = new Map()\n}\n\nfunction increment(map: CountMap, key: string): void {\n const count = map.get(key) || 0\n map.set(key, count + 1)\n}\n\nfunction getExprStats(expr: Expr, stats: Stats) {\n switch (expr.kind) {\n case 'number':\n stats.constCount++\n break\n\n case 'string':\n // TODO\n break\n\n case 'keyword':\n // TODO: Count this as a constant? (Currently only used for :NA: values.)\n break\n\n case 'variable-ref':\n stats.varRefCount++\n break\n\n case 'unary-op':\n getExprStats(expr.expr, stats)\n increment(stats.unaryOpCounts, expr.op)\n break\n\n case 'binary-op':\n getExprStats(expr.lhs, stats)\n getExprStats(expr.rhs, stats)\n increment(stats.binaryOpCounts, expr.op)\n break\n\n case 'parens':\n getExprStats(expr.expr, stats)\n break\n\n case 'lookup-def':\n // TODO\n break\n\n case 'lookup-call':\n increment(stats.luCallCounts, fullIdForVarRef(expr.varRef))\n getExprStats(expr.arg, stats)\n break\n\n case 'function-call':\n increment(stats.fnCallCounts, expr.fnId)\n expr.args.forEach(arg => getExprStats(arg, stats))\n break\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function printExprStats(exprs: Expr[]): void {\n const stats = new Stats()\n for (const expr of exprs) {\n getExprStats(expr, stats)\n }\n\n function printCount(count: number, label: string) {\n console.log(`${count.toString().padStart(6)} ${label}`)\n }\n\n function printCounts(map: CountMap): number {\n const entries = [...map.entries()].sort((a, b) => a[0].localeCompare(b[0]))\n let total = 0\n for (const entry of entries) {\n printCount(entry[1], entry[0])\n total += entry[1]\n }\n printCount(total, 'total')\n return total\n }\n\n let nodeCount = 0\n\n printCount(stats.constCount, 'consts')\n nodeCount += stats.constCount\n\n printCount(stats.varRefCount, 'var refs')\n nodeCount += stats.varRefCount\n\n console.log()\n console.log('UNARY OPS')\n nodeCount += printCounts(stats.unaryOpCounts)\n\n console.log()\n console.log('BINARY OPS')\n nodeCount += printCounts(stats.binaryOpCounts)\n\n console.log()\n console.log('FUNCTION CALLS')\n nodeCount += printCounts(stats.fnCallCounts)\n\n console.log()\n console.log('LOOKUP CALLS')\n nodeCount += printCounts(stats.luCallCounts)\n\n console.log()\n console.log('TOTAL')\n printCount(nodeCount, 'nodes')\n}\n\n// TODO: Move to names.ts?\nfunction fullIdForVarRef(varRef: VariableRef): string {\n if (varRef.subscriptRefs?.length > 0) {\n return `${varRef.varId}[${varRef.subscriptRefs.map(ref => ref.subId).join(',')}]`\n } else {\n return varRef.varId\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { assertNever } from 'assert-never'\n\nimport { binaryOp, lookupCall, num, parens, unaryOp } from './ast-builders'\nimport type { Expr, NumberLiteral, VariableRef } from './ast-types'\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport interface ReduceExprOptions {\n /** A callback that returns the possibly reduced expression for the referenced variable. */\n resolveVarRef?: (varRef: VariableRef) => Expr | undefined\n}\n\n/**\n * @hidden This is not yet part of the public API.\n */\nexport function reduceExpr(expr: Expr, opts?: ReduceExprOptions): Expr {\n switch (expr.kind) {\n case 'number':\n case 'string':\n case 'keyword':\n return expr\n\n case 'variable-ref':\n if (opts?.resolveVarRef !== undefined) {\n // Note that we assume the resolved expression has already been reduced by\n // the callback, and don't attempt to reduce further\n const resolvedExpr = opts.resolveVarRef(expr)\n if (resolvedExpr) {\n return resolvedExpr\n }\n }\n return expr\n\n case 'unary-op': {\n // Reduce the child expression\n const child = reduceExpr(expr.expr, opts)\n switch (expr.op) {\n case '+':\n // When there is an explicit plus sign, we can take the child expression as is\n return child\n case '-':\n if (child.kind === 'number') {\n // Negate the number\n return num(-child.value)\n } else {\n // Cannot simplify further\n return unaryOp('-', child)\n }\n case ':NOT:':\n if (child.kind === 'number') {\n // Use the same behavior as C and negate the numeric value. (\"The result of the\n // logical negation operator ! is 0 if the value of its operand compares unequal\n // to 0, 1 if the value of its operand compares equal to 0.\")\n return num(child.value === 0 ? 1 : 0)\n } else {\n // Cannot simplify further\n return unaryOp(':NOT:', child)\n }\n default:\n assertNever(expr)\n }\n break\n }\n\n case 'binary-op': {\n // Reduce the lhs and rhs expressions\n // TODO: Don't visit rhs if expression can be reduced by looking at lhs alone\n const lhs = reduceExpr(expr.lhs, opts)\n const rhs = reduceExpr(expr.rhs, opts)\n if (lhs.kind === 'number' && rhs.kind === 'number') {\n // Perform basic arithmetic to reduce to a constant number\n switch (expr.op) {\n case '+':\n return num(lhs.value + rhs.value)\n case '-':\n return num(lhs.value - rhs.value)\n case '*':\n return num(lhs.value * rhs.value)\n case '/':\n // TODO: Catch divide-by-zero errors at compile time\n return num(lhs.value / rhs.value)\n case '^':\n return num(Math.pow(lhs.value, rhs.value))\n case '=':\n return num(lhs.value === rhs.value ? 1 : 0)\n case '<>':\n return num(lhs.value !== rhs.value ? 1 : 0)\n case '<':\n return num(lhs.value < rhs.value ? 1 : 0)\n case '>':\n return num(lhs.value > rhs.value ? 1 : 0)\n case '<=':\n return num(lhs.value <= rhs.value ? 1 : 0)\n case '>=':\n return num(lhs.value >= rhs.value ? 1 : 0)\n case ':AND:':\n // For AND expressions, if both sides are non-zero, then resolve to 1\n return num(lhs.value !== 0 && rhs.value !== 0 ? 1 : 0)\n case ':OR:':\n // For OR expressions, if either side is non-zero, then resolve to 1\n return num(lhs.value !== 0 || rhs.value !== 0 ? 1 : 0)\n default:\n assertNever(expr)\n }\n } else if (lhs.kind === 'number' || rhs.kind === 'number') {\n // Try to reduce identity expressions to a single value (x*1 == x, and so on)\n const lhsNum: number = lhs.kind === 'number' ? lhs.value : undefined\n const rhsNum: number = rhs.kind === 'number' ? rhs.value : undefined\n const numValue = lhsNum !== undefined ? lhsNum : rhsNum\n const otherSide = lhsNum !== undefined ? rhs : lhs\n switch (expr.op) {\n case '+': {\n if (numValue === 0) {\n // x+0 == x\n // 0+x == x\n return otherSide\n } else if (\n otherSide.kind === 'binary-op' &&\n otherSide.op === '+' &&\n (otherSide.lhs.kind === 'number' || otherSide.rhs.kind === 'number')\n ) {\n // In this case, one side is const and and the child is a '+' with a const, so we\n // can add the two consts and fold into a single add op\n const otherSideLhsNum: number = otherSide.lhs.kind === 'number' ? otherSide.lhs.value : undefined\n const otherSideRhsNum: number = otherSide.rhs.kind === 'number' ? otherSide.rhs.value : undefined\n const otherSideConstValue = otherSideLhsNum !== undefined ? otherSideLhsNum : otherSideRhsNum\n const otherSideOtherPart = otherSideLhsNum !== undefined ? otherSide.rhs : otherSide.lhs\n return binaryOp(num(numValue + otherSideConstValue), '+', otherSideOtherPart)\n }\n break\n }\n\n case '-': {\n if (rhsNum === 0) {\n // x-0 == x\n return lhs\n } else if (lhsNum === 0) {\n // 0-x == -x\n // TODO: This probably isn't too helpful\n return unaryOp('-', rhs)\n }\n break\n }\n\n case '*': {\n if (numValue === 0) {\n // x*0 == 0\n // 0*x == 0\n return num(0)\n } else if (numValue === 1) {\n // x*1 == x\n // 1*x == x\n return otherSide\n } else if (\n otherSide.kind === 'binary-op' &&\n otherSide.op === '*' &&\n (otherSide.lhs.kind === 'number' || otherSide.rhs.kind === 'number')\n ) {\n // In this case, one side is const and and the child is a '*' with a const, so we\n // can multiply the two consts and fold into a single multiply op\n const otherSideLhsNum: number = otherSide.lhs.kind === 'number' ? otherSide.lhs.value : undefined\n const otherSideRhsNum: number = otherSide.rhs.kind === 'number' ? otherSide.rhs.value : undefined\n const otherSideConstValue = otherSideLhsNum !== undefined ? otherSideLhsNum : otherSideRhsNum\n const otherSideOtherPart = otherSideLhsNum !== undefined ? otherSide.rhs : otherSide.lhs\n return binaryOp(num(numValue * otherSideConstValue), '*', otherSideOtherPart)\n }\n break\n }\n\n case '/': {\n if (rhsNum === 1) {\n // x/1 == x\n return lhs\n }\n break\n }\n\n case '^': {\n if (rhsNum === 0) {\n // x^0 == 1\n return num(1)\n } else if (rhsNum === 1) {\n // x^1 == x\n return lhs\n }\n break\n }\n\n case ':AND:':\n // For AND expressions:\n // - if the constant side is zero, then resolve to zero (false)\n // x && 0 == 0\n // 0 && x == 0\n // - if the constant side is non-zero, then resolve to the other side\n // x && 1 == x\n // 1 && x == x\n return numValue === 0 ? num(0) : otherSide\n\n case ':OR:':\n // For OR expressions:\n // - if the constant side is non-zero, then resolve to one (true)\n // x || 1 == 1\n // 1 || x == 1\n // - if the constant side is zero, resolve to the other side\n // x || 0 == x\n // 0 || x == x\n return numValue !== 0 ? num(1) : otherSide\n\n default:\n break\n }\n }\n\n // Cannot simplify further; return a new expression with the reduced child expressions\n return {\n kind: 'binary-op',\n lhs,\n op: expr.op,\n rhs\n }\n }\n\n case 'parens': {\n const child = reduceExpr(expr.expr, opts)\n return applyParens(child)\n }\n\n case 'lookup-def':\n // TODO: Reduce lookup def?\n return expr\n\n case 'lookup-call':\n // TODO: Reduce lookup call arg?\n return expr\n\n case 'function-call': {\n // Reduce each argument expression\n if (expr.fnId === '_IF_THEN_ELSE') {\n // If condition is a constant, we can eliminate the unused branch\n const conditionExpr = reduceExpr(expr.args[0], opts)\n if (conditionExpr.kind === 'number') {\n // The condition resolved to a simple numeric constant. If it is non-zero,\n // replace the `IF THEN ELSE` call with the \"true\" branch, otherwise replace\n // it with the \"false\" branch.\n const branchExpr = conditionExpr.value !== 0 ? reduceExpr(expr.args[1], opts) : reduceExpr(expr.args[2], opts)\n\n // Wrap the branch expression in parentheses if needed to ensure that the intent\n // of the original expression remains the same. For example:\n // a = IF THEN ELSE(1, b + c, d - e) * 10\n // In this case, the parentheses are important, and need to be preserved:\n // a = (b + c) * 10\n // If the parentheses are not needed (like when the branch resolve to a simple\n // constant or variable reference), the parentheses will be dropped.\n return applyParens(branchExpr)\n }\n }\n\n // If all args are constant, apply the function at compile time (for certain functions)\n const reducedArgs = expr.args.map(arg => reduceExpr(arg, opts))\n const allConst = reducedArgs.every(arg => arg.kind === 'number')\n if (allConst) {\n const constArg = (index: number) => {\n const num = reducedArgs[index] as NumberLiteral\n return num.value\n }\n switch (expr.fnId) {\n case '_ABS':\n return num(Math.abs(constArg(0)))\n case '_COS':\n return num(Math.cos(constArg(0)))\n case '_EXP':\n return num(Math.exp(constArg(0)))\n case '_INITIAL':\n return reducedArgs[0]\n case '_INTEGER':\n return num(Math.trunc(constArg(0)))\n case '_LN':\n return num(Math.log(constArg(0)))\n case '_MAX':\n return num(Math.max(constArg(0), constArg(1)))\n case '_MIN':\n return num(Math.min(constArg(0), constArg(1)))\n case '_MODULO':\n return num(constArg(0) % constArg(1))\n case '_POWER':\n return num(Math.pow(constArg(0), constArg(1)))\n case '_SIN':\n return num(Math.sin(constArg(0)))\n case '_SQRT':\n return num(Math.sqrt(constArg(0)))\n default:\n break\n }\n }\n\n return {\n kind: 'function-call',\n fnName: expr.fnName,\n fnId: expr.fnId,\n args: reducedArgs\n }\n }\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * A variant of `reduceExpr` that does not aggressively reduce the expression, but only\n * tries to eliminate the unused branch if a conditional (`IF THEN ELSE`) has a condition\n * that resolves to a constant.\n *\n * @hidden This is not yet part of the public API.\n *\n * @param expr The expression to reduce.\n * @param opts The reduce options.\n * @returns A possibly reduced expression.\n */\nexport function reduceConditionals(expr: Expr, opts?: ReduceExprOptions): Expr {\n switch (expr.kind) {\n case 'number':\n case 'string':\n case 'keyword':\n return expr\n\n case 'variable-ref':\n // If we get here, it means that we are processing an expression that is not\n // inside the condition expression for an `IF THEN ELSE`, so we do not attempt\n // to resolve the variable reference or reduce it further\n return expr\n\n case 'unary-op': {\n const child = reduceConditionals(expr.expr, opts)\n return unaryOp(expr.op, child)\n }\n\n case 'binary-op': {\n const lhs = reduceConditionals(expr.lhs, opts)\n const rhs = reduceConditionals(expr.rhs, opts)\n return binaryOp(lhs, expr.op, rhs)\n }\n\n case 'parens': {\n const child = reduceConditionals(expr.expr, opts)\n return applyParens(child)\n }\n\n case 'lookup-def':\n return expr\n\n case 'lookup-call': {\n const arg = reduceConditionals(expr.arg, opts)\n return lookupCall(expr.varRef, arg)\n }\n\n case 'function-call': {\n if (expr.fnId === '_IF_THEN_ELSE') {\n // Note that (unlike all other places in this function) we use `reduceExpr` here\n // to aggressively reduce the condition expression (the first argument for the\n // `IF THEN ELSE` call)\n const conditionExpr = reduceExpr(expr.args[0], opts)\n if (conditionExpr.kind === 'number') {\n // The condition resolved to a simple numeric constant. If it is non-zero,\n // replace the `IF THEN ELSE` call with the \"true\" branch, otherwise replace\n // it with the \"false\" branch.\n const branchExpr =\n conditionExpr.value !== 0 ? reduceConditionals(expr.args[1], opts) : reduceConditionals(expr.args[2], opts)\n\n // Wrap the branch expression in parentheses if needed to ensure that the intent\n // of the original expression remains the same. For example:\n // a = IF THEN ELSE(1, b + c, d - e) * 10\n // In this case, the parentheses are important, and need to be preserved:\n // a = (b + c) * 10\n // If the parentheses are not needed (like when the branch resolve to a simple\n // constant or variable reference), the parentheses will be dropped.\n return applyParens(branchExpr)\n }\n }\n\n // For all other kinds of function calls, call `reduceConditionals` on the args\n const reducedArgs = expr.args.map(arg => reduceConditionals(arg, opts))\n return {\n kind: 'function-call',\n fnName: expr.fnName,\n fnId: expr.fnId,\n args: reducedArgs\n }\n }\n\n default:\n assertNever(expr)\n }\n}\n\n/**\n * Reduce the given expression that may need to be wrapped in parentheses. If the parentheses\n * are not needed, the given `child` expression will be returned as is, otherwise it will be\n * wrapped in a \"parens\" node.\n *\n * @param child The child of a parens expression to reduce.\n * @returns A possibly reduced expression.\n */\nfunction applyParens(child: Expr): Expr {\n switch (child.kind) {\n case 'number':\n case 'string':\n case 'keyword':\n case 'variable-ref':\n // When the child expression resolves to something simple, drop the parens\n // TODO: Are there other cases where we should drop the parens?\n return child\n default:\n // Otherwise, preserve the parens\n return parens(child)\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { canonicalFunctionId, canonicalId } from '../_shared/canonical-id'\n\nimport type {\n BinaryOp,\n BinaryOpExpr,\n DimensionDef,\n DimName,\n DimOrSubName,\n Equation,\n Expr,\n FunctionCall,\n FunctionName,\n Keyword,\n LookupCall,\n LookupDef,\n LookupPoint,\n LookupRange,\n Model,\n NumberLiteral,\n ParensExpr,\n SimulationSpec,\n StringLiteral,\n SubName,\n SubscriptMapping,\n SubscriptRef,\n UnaryOp,\n UnaryOpExpr,\n VariableDef,\n VariableName,\n VariableRef\n} from './ast-types'\n\n//\n// NOTE: This file contains functions that allow for tersely defining AST nodes.\n// It is intended for internal use only (primarily in tests), so it is not exported\n// as part of the public API at this time.\n//\n\n//\n// DIMENSIONS + SUBSCRIPTS\n//\n\nexport function subRef(dimOrSubName: DimOrSubName): SubscriptRef {\n return {\n subName: dimOrSubName,\n subId: canonicalId(dimOrSubName)\n }\n}\n\nexport function subMapping(toDimName: DimName, dimOrSubNames: DimOrSubName[] = []): SubscriptMapping {\n return {\n toDimName,\n toDimId: canonicalId(toDimName),\n subscriptRefs: dimOrSubNames.map(subRef)\n }\n}\n\nexport function dimDef(\n dimName: DimName,\n familyName: DimName,\n dimOrSubNames: SubName[],\n subscriptMappings: SubscriptMapping[] = [],\n comment = '',\n group?: string\n): DimensionDef {\n return {\n dimName,\n dimId: canonicalId(dimName),\n familyName,\n familyId: canonicalId(familyName),\n subscriptRefs: dimOrSubNames.map(subRef),\n subscriptMappings,\n comment,\n ...(group ? { group } : {})\n }\n}\n\n//\n// EXPRESSIONS\n//\n\nexport function num(value: number, text?: string): NumberLiteral {\n return {\n kind: 'number',\n value,\n text: text || value.toString()\n }\n}\n\nexport function stringLiteral(text: string): StringLiteral {\n return {\n kind: 'string',\n text\n }\n}\n\nexport function keyword(text: string): Keyword {\n return {\n kind: 'keyword',\n text\n }\n}\n\nexport function varRef(varName: VariableName, subscriptNames?: DimOrSubName[]): VariableRef {\n return {\n kind: 'variable-ref',\n varName,\n varId: canonicalId(varName),\n subscriptRefs: subscriptNames?.map(subRef)\n }\n}\n\nexport function unaryOp(op: UnaryOp, expr: Expr): UnaryOpExpr {\n return {\n kind: 'unary-op',\n op,\n expr\n }\n}\n\nexport function binaryOp(lhs: Expr, op: BinaryOp, rhs: Expr): BinaryOpExpr {\n return {\n kind: 'binary-op',\n lhs,\n op,\n rhs\n }\n}\n\nexport function parens(expr: Expr): ParensExpr {\n return {\n kind: 'parens',\n expr\n }\n}\n\nexport function lookupDef(points: LookupPoint[], range?: LookupRange): LookupDef {\n return {\n kind: 'lookup-def',\n range,\n points\n }\n}\n\nexport function lookupCall(varRef: VariableRef, arg: Expr): LookupCall {\n return {\n kind: 'lookup-call',\n varRef,\n arg\n }\n}\n\nexport function call(fnName: FunctionName, ...args: Expr[]): FunctionCall {\n return {\n kind: 'function-call',\n fnName,\n fnId: canonicalFunctionId(fnName),\n args\n }\n}\n\n//\n// EQUATIONS\n//\n\nexport function varDef(\n varName: VariableName,\n subscriptNames?: DimOrSubName[],\n exceptSubscriptNames?: DimOrSubName[][]\n): VariableDef {\n return {\n kind: 'variable-def',\n varName,\n varId: canonicalId(varName),\n subscriptRefs: subscriptNames?.map(subRef),\n exceptSubscriptRefSets: exceptSubscriptNames?.map(namesForSet => namesForSet.map(subRef))\n }\n}\n\nexport function exprEqn(varDef: VariableDef, expr: Expr, units = '', comment = '', group?: string): Equation {\n return {\n lhs: {\n varDef\n },\n rhs: {\n kind: 'expr',\n expr\n },\n units,\n comment,\n ...(group ? { group } : {})\n }\n}\n\nexport function constListEqn(varDef: VariableDef, constants: NumberLiteral[][], units = '', comment = ''): Equation {\n // For now, assume that the original text had a trailing semicolon if there are multiple groups\n let text = constants.map(arr => arr.map(constant => constant.text).join(',')).join(';')\n if (constants.length > 1) {\n text += ';'\n }\n return {\n lhs: {\n varDef\n },\n rhs: {\n kind: 'const-list',\n constants: constants.flat(),\n text\n },\n units,\n comment\n }\n}\n\nexport function dataVarEqn(varDef: VariableDef, units = '', comment = ''): Equation {\n return {\n lhs: {\n varDef\n },\n rhs: {\n kind: 'data'\n },\n units,\n comment\n }\n}\n\nexport function lookupVarEqn(varDef: VariableDef, lookupDef: LookupDef, units = '', comment = ''): Equation {\n return {\n lhs: {\n varDef\n },\n rhs: {\n kind: 'lookup',\n lookupDef\n },\n units,\n comment\n }\n}\n\n//\n// MODEL\n//\n\nexport function model(dimensions: DimensionDef[], equations: Equation[], simulationSpec?: SimulationSpec): Model {\n return {\n simulationSpec,\n dimensions,\n equations\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { ModelParser, ModelVisitor } from 'antlr4-vensim'\n\nimport { canonicalFunctionId, canonicalId } from '../../_shared/canonical-id'\n\nimport { createAntlrParser } from './antlr-parser'\n\nexport class SubscriptRangeReader extends ModelVisitor {\n /**\n * @public\n * @param {import('../vensim-parse-context').VensimParseContext} parseContext An object\n * that provides access to file system resources (such as external data files) that are\n * referenced during the parse phase.\n */\n constructor(parseContext /*: VensimParseContext*/) {\n super()\n this.parseContext = parseContext\n }\n\n /**\n * Parse the given Vensim subscript range definition and return a `DimensionDef` AST node.\n *\n * @public\n * @param {string} subscriptRangeText A string containing the Vensim subscript range definition.\n * @returns {import('../../ast/ast-types').DimensionDef} A `DimensionDef` AST node.\n */\n /*public*/ parse(subscriptRangeText /*: string*/) /*: DimensionDef*/ {\n const parser = createAntlrParser(subscriptRangeText)\n const subscriptRangeCtx = parser.subscriptRange()\n return this.visitSubscriptRange(subscriptRangeCtx)\n }\n\n /**\n * Process the given ANTLR `SubscriptRangeContext` from an already parsed Vensim\n * subscript range definition.\n *\n * @public\n * @param {import('antlr4-vensim').SubscriptRangeContext} ctx The ANTLR `SubscriptRangeContext`.\n * @returns {import('../../ast/ast-types').Expr} A `SubscriptRange` AST node.\n */\n /*public*/ visitSubscriptRange(ctx /*: SubscriptRangeContext*/) /*: DimensionDef*/ {\n this.subscriptNames = []\n this.subscriptMappings = []\n\n // TODO: For now, fill in an empty string for the comment; this is mainly\n // for compatibility with unit tests that expect empty string instead of\n // undefined, but this should be revisited\n const comment = ''\n\n // A subscript alias has two identifiers, while a regular subscript range definition\n // has just one\n const ids = ctx.Id()\n if (ids.length === 1) {\n // This is a regular subscript range definition, which begins with the dimension name\n const dimName = ids[0].getText()\n const dimId = canonicalId(dimName)\n\n // Visit children to fill in the subscript range definition\n super.visitSubscriptRange(ctx)\n\n // Create a new subscript range definition (`DimensionDef`) from Vensim-format names.\n // - The family is provisionally set to the dimension name.\n // - It will be updated to the maximal dimension if this is a subdimension.\n // - The mapping value contains dimensions and indices in the toDim.\n // - It will be expanded and inverted to fromDim indices later.\n return {\n dimName,\n dimId,\n familyName: dimName,\n familyId: dimId,\n subscriptRefs: this.subscriptNames.map(subName => {\n return {\n subName,\n subId: canonicalId(subName)\n }\n }),\n subscriptMappings: this.subscriptMappings,\n comment\n }\n } else if (ids.length === 2) {\n // This is a dimension alias (`DimA <-> DimB`)\n const dimName = ids[0].getText()\n const dimId = canonicalId(dimName)\n const familyName = ids[1].getText()\n const familyId = canonicalId(familyName)\n return {\n dimName,\n dimId,\n familyName,\n familyId,\n subscriptRefs: [],\n subscriptMappings: [],\n comment\n }\n }\n }\n\n visitSubscriptDefList(ctx) {\n // A subscript def is either an `Id` (a single subscript name, like \"A1\") or a numeric range\n // like \"(A1-A3)\". Either form can appear in the list, for example, \"A1, (A5-A7), A9\".\n for (const subscriptDef of ctx.children) {\n if (subscriptDef.symbol?.type === ModelParser.Id) {\n this.subscriptNames.push(subscriptDef.getText())\n } else if (subscriptDef.ruleIndex === ModelParser.RULE_subscriptSequence) {\n this.visitSubscriptSequence(subscriptDef)\n }\n }\n }\n\n visitSubscriptSequence(ctx) {\n // This is a subscript sequence (aka numeric range), like \"(A1-A3)\".\n // Construct index names from the sequence start and end indices.\n // This assumes the indices begin with the same string and end with numbers.\n const re = /^(.*?)(\\d+)$/\n const ids = ctx.Id().map(id => id.getText())\n const matches = ids.map(id => re.exec(id))\n if (matches[0][1] === matches[1][1]) {\n const prefix = matches[0][1]\n const start = parseInt(matches[0][2])\n const end = parseInt(matches[1][2])\n for (let i = start; i <= end; i++) {\n this.subscriptNames.push(prefix + i)\n }\n }\n }\n\n visitSubscriptMapping(ctx) {\n // Get the name of the \"to\" part of the mapping\n const toDimName = ctx.Id().getText()\n\n // If a subscript list is part of the mapping, the names will be set by `visitSubscriptList`\n this.mappedSubscriptNames = []\n\n // Visit the rest of the mapping, which includes the subscript list portion\n super.visitSubscriptMapping(ctx)\n\n // Add the mappings\n this.subscriptMappings.push({\n toDimName,\n toDimId: canonicalId(toDimName),\n subscriptRefs: this.mappedSubscriptNames.map(subName => {\n return {\n subName,\n subId: canonicalId(subName)\n }\n })\n })\n }\n\n visitSubscriptList(ctx) {\n // When parsing subscript range definitions, a subscript list is only used in the context\n // of a subscript mapping. It contains a list of subscript index names.\n this.mappedSubscriptNames = ctx.Id().map(id => id.getText())\n }\n\n visitCall(ctx) {\n // A subscript range can have a `GET DIRECT SUBSCRIPT` call on the RHS\n const fnName = ctx.Id().getText()\n const fnId = canonicalFunctionId(fnName)\n if (fnId === '_GET_DIRECT_SUBSCRIPT') {\n super.visitCall(ctx)\n } else {\n throw new Error(\n `Only 'GET DIRECT SUBSCRIPT' calls are supported in subscript range definitions, but saw '${fnName}'`\n )\n }\n }\n\n visitExprList(ctx) {\n // The only call that ends up here is `GET DIRECT SUBSCRIPT`. The arguments\n // are all strings that are delimited with single quotes, so strip those before\n // passing the arguments to the `getDirectSubscripts` function.\n const args = ctx.expr().map(expr => {\n const exprText = expr.getText()\n return exprText.replaceAll(\"'\", '')\n })\n\n // Delegate to the context\n const fileName = args[0]\n const tabOrDelimiter = args[1]\n const firstCell = args[2]\n const lastCell = args[3]\n const prefix = args[4]\n this.subscriptNames =\n this.parseContext?.getDirectSubscripts(fileName, tabOrDelimiter, firstCell, lastCell, prefix) || []\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport antlr4 from 'antlr4'\nimport { ModelLexer, ModelParser } from 'antlr4-vensim'\n\n/**\n * Create a `ModelParser` for the given model text, which can be the\n * contents of an entire `mdl` file, or a portion of one (e.g., an\n * expression or definition).\n *\n * @param {string} input The string containing the model text.\n * @return {ModelParser} A `ModelParser` from which a parse tree can be obtained.\n */\nexport function createAntlrParser(input) {\n // Create a custom error handler that will override the defafult one, which\n // only logs errors to stderr. The custom handler will rethrow the error (for\n // fail-fast behavior).\n const errorListener = new CustomErrorListener(input)\n\n // Create a lexer for the input (with custom error handler)\n let chars = new antlr4.InputStream(input)\n let lexer = new ModelLexer(chars)\n lexer.removeErrorListeners()\n lexer.addErrorListener(errorListener)\n\n // Create a parser around the result of the lexer (with custom error handler)\n // error listener.\n let tokens = new antlr4.CommonTokenStream(lexer)\n let parser = new ModelParser(tokens)\n parser.buildParseTrees = true\n parser.removeErrorListeners()\n parser.addErrorListener(errorListener)\n\n return parser\n}\n\nclass CustomErrorListener extends antlr4.error.ErrorListener {\n constructor(input) {\n super()\n this.input = input\n }\n\n syntaxError(_recognizer, _offendingSymbol, line, column, msg /*, err*/) {\n throw new Error(msg, {\n cause: {\n code: 'VensimParseError',\n line,\n column\n }\n })\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { DimensionDef } from '../ast/ast-types'\nimport type { VensimParseContext } from './vensim-parse-context'\nimport { SubscriptRangeReader } from './impl/subscript-range-reader'\n\n/**\n * Parse the given Vensim subscript range definition and return a `DimensionDef` AST node.\n *\n * @param input A string containing the Vensim subscript range definition.\n * @param context An object that provides access to file system resources (such as\n * external data files) that are referenced during the parse phase.\n * @returns A `DimensionDef` AST node.\n */\nexport function parseVensimSubscriptRange(input: string, context?: VensimParseContext): DimensionDef {\n // TODO: Reuse reader instance?\n const subscriptReader = new SubscriptRangeReader(context)\n return subscriptReader.parse(input)\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { ModelLexer, ModelVisitor } from 'antlr4-vensim'\n\nimport { canonicalFunctionId, canonicalId } from '../../_shared/canonical-id'\n\nimport { createAntlrParser } from './antlr-parser'\n\nexport class ExprReader extends ModelVisitor {\n constructor() {\n super()\n\n // Stack of function names and argument indices encountered on the RHS\n this.callStack = []\n }\n\n /**\n * Parse the given Vensim expression definition and return an `Expr` AST node.\n *\n * @public\n * @param {string} exprText A string containing the Vensim expression.\n * @returns {import('../../ast/ast-types').Expr} An `Expr` AST node.\n */\n /*public*/ parse(exprText /*: string*/) /*: Expr*/ {\n const parser = createAntlrParser(exprText)\n const exprCtx = parser.expr()\n return this.visitExpr(exprCtx)\n }\n\n /**\n * Process the given ANTLR `ExprContext` from an already parsed Vensim\n * expression definition.\n *\n * @public\n * @param {import('antlr4-vensim').ExprContext} ctx The ANTLR `ExprContext`.\n * @returns {import('../../ast/ast-types').Expr} An `Expr` AST node.\n */\n /*public*/ visitExpr(ctx /*: ExprContext*/) /*: Expr*/ {\n ctx.accept(this)\n return this.expr\n }\n\n //\n // Constants\n //\n\n visitConst(ctx) {\n const text = ctx.Const().getText()\n if (text.startsWith(\"'\") && text.endsWith(\"'\")) {\n // Treat it as a string\n this.expr = {\n kind: 'string',\n text: text.substr(1, text.length - 2)\n }\n } else {\n // Treat it as a number\n const value = parseFloat(text)\n this.expr = {\n kind: 'number',\n value,\n text\n }\n }\n }\n\n //\n // Keywords\n //\n\n visitKeyword(ctx) {\n const text = ctx.Keyword().getText()\n this.expr = {\n kind: 'keyword',\n text\n }\n }\n\n //\n // Function calls and variables\n //\n\n visitCall(ctx) {\n // Convert the function name from Vensim to C format\n const vensimFnName = ctx.Id().getText()\n const fnId = canonicalFunctionId(vensimFnName)\n this.callStack.push({ fn: fnId, args: [] })\n super.visitCall(ctx)\n const callInfo = this.callStack.pop()\n this.expr = {\n kind: 'function-call',\n fnName: vensimFnName,\n fnId: fnId,\n args: callInfo.args\n }\n }\n\n visitExprList(ctx) {\n const exprs = ctx.expr()\n for (let i = 0; i < exprs.length; i++) {\n // this.setArgIndex(i)\n exprs[i].accept(this)\n const n = this.callStack.length\n if (n > 0) {\n this.callStack[n - 1].args.push(this.expr)\n }\n }\n }\n\n visitVar(ctx) {\n // Convert the variable name from Vensim to C format\n const vensimVarName = ctx.Id().getText().trim()\n const varId = canonicalId(vensimVarName)\n\n // Process the subscripts (if any) that follow the variable name\n this.subscripts = undefined\n super.visitVar(ctx)\n const subscriptNames = this.subscripts\n const subscriptRefs = subscriptNames?.map(name => {\n return {\n subName: name,\n subId: canonicalId(name)\n }\n })\n this.subscripts = undefined\n\n this.expr = {\n kind: 'variable-ref',\n varName: vensimVarName,\n varId: varId,\n subscriptRefs\n }\n }\n\n visitSubscriptList(ctx) {\n // Get the subscripts found in the var name\n this.subscripts = ctx.Id().map(id => id.getText())\n }\n\n //\n // Lookups\n //\n\n getPoint(lookupPoint) {\n const exprs = lookupPoint.expr()\n if (exprs.length >= 2) {\n return [parseFloat(exprs[0].getText()), parseFloat(exprs[1].getText())]\n }\n }\n\n visitLookupRange(ctx) {\n this.lookupRange = ctx.lookupPoint().map(p => this.getPoint(p))\n super.visitLookupRange(ctx)\n }\n\n visitLookupPointList(ctx) {\n this.lookupPoints = ctx.lookupPoint().map(p => this.getPoint(p))\n super.visitLookupPointList(ctx)\n }\n\n visitLookupArg(ctx) {\n super.visitLookupArg(ctx)\n let range\n if (this.lookupRange && this.lookupRange.length === 2) {\n range = {\n min: this.lookupRange[0],\n max: this.lookupRange[1]\n }\n }\n this.expr = {\n kind: 'lookup-def',\n range,\n points: this.lookupPoints\n }\n this.lookupRange = undefined\n this.lookupPoints = undefined\n }\n\n visitLookupCall(ctx) {\n // Process the lookup variable name\n const lookupVarName = ctx.Id().getText()\n const lookupVarId = canonicalId(lookupVarName)\n\n // Process any subscripts that follow the variable name\n if (ctx.subscriptList()) {\n ctx.subscriptList().accept(this)\n }\n const subscriptNames = this.subscripts\n const subscriptRefs = subscriptNames?.map(name => {\n return {\n subName: name,\n subId: canonicalId(name)\n }\n })\n this.subscripts = undefined\n\n const lookupVarRef = {\n kind: 'variable-ref',\n varName: lookupVarName,\n varId: lookupVarId,\n subscriptRefs\n }\n\n // Process the single lookup argument\n ctx.expr().accept(this)\n const lookupArg = this.expr\n\n this.expr = {\n kind: 'lookup-call',\n varRef: lookupVarRef,\n arg: lookupArg\n }\n }\n\n //\n // Unary operators\n //\n\n completeUnary(op /*: UnaryOp*/) {\n const child = this.expr\n this.expr = {\n kind: 'unary-op',\n op,\n expr: child\n }\n }\n\n visitNegative(ctx) {\n super.visitNegative(ctx)\n this.completeUnary('-')\n }\n\n visitPositive(ctx) {\n super.visitPositive(ctx)\n this.completeUnary('+')\n }\n\n visitNot(ctx) {\n super.visitNot(ctx)\n this.completeUnary(':NOT:')\n }\n\n //\n // Binary operators\n //\n\n visitBinaryArgs(ctx, op /*: BinaryOp*/) {\n ctx.expr(0).accept(this)\n const lhs = this.expr\n ctx.expr(1).accept(this)\n const rhs = this.expr\n this.expr = {\n kind: 'binary-op',\n lhs,\n op,\n rhs\n }\n }\n\n visitPower(ctx) {\n this.visitBinaryArgs(ctx, '^')\n }\n\n visitMulDiv(ctx) {\n this.visitBinaryArgs(ctx, ctx.op.type === ModelLexer.Star ? '*' : '/')\n }\n\n visitAddSub(ctx) {\n this.visitBinaryArgs(ctx, ctx.op.type === ModelLexer.Plus ? '+' : '-')\n }\n\n visitRelational(ctx) {\n let op\n switch (ctx.op.type) {\n case ModelLexer.Less:\n op = '<'\n break\n case ModelLexer.Greater:\n op = '>'\n break\n case ModelLexer.LessEqual:\n op = '<='\n break\n case ModelLexer.GreaterEqual:\n op = '>='\n break\n default:\n throw new Error(`Unexpected relational operator '${op}'`)\n }\n this.visitBinaryArgs(ctx, op)\n }\n\n visitEquality(ctx) {\n this.visitBinaryArgs(ctx, ctx.op.type === ModelLexer.Equal ? '=' : '<>')\n }\n\n visitAnd(ctx) {\n this.visitBinaryArgs(ctx, ':AND:')\n }\n\n visitOr(ctx) {\n this.visitBinaryArgs(ctx, ':OR:')\n }\n\n //\n // Tokens\n //\n\n visitParens(ctx) {\n super.visitParens(ctx)\n\n const child = this.expr\n this.expr = {\n kind: 'parens',\n expr: child\n }\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { Expr } from '../ast/ast-types'\nimport { ExprReader } from './impl/expr-reader'\n\n/**\n * Parse the given Vensim expression definition and return an `Expr` AST node.\n *\n * @param input A string containing the Vensim expression.\n * @returns An `Expr` AST node.\n */\nexport function parseVensimExpr(input: string): Expr {\n // TODO: Reuse reader instance?\n const exprReader = new ExprReader()\n return exprReader.parse(input)\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { ModelVisitor } from 'antlr4-vensim'\n\nimport { canonicalId } from '../../_shared/canonical-id'\n\nimport { createAntlrParser } from './antlr-parser'\nimport { ExprReader } from './expr-reader'\n\nexport class EquationReader extends ModelVisitor {\n constructor() {\n super()\n }\n\n /**\n * Parse the given Vensim equation definition and return an `Equation` AST node.\n *\n * @public\n * @param {string} equationText A string containing the Vensim equation definition.\n * @return {import('../../ast/ast-types').Equation} An `Equation` AST node.\n */\n /*public*/ parse(equationText /*: string*/) /*: Equation*/ {\n const parser = createAntlrParser(equationText)\n const equationCtx = parser.equation()\n return this.visitEquation(equationCtx)\n }\n\n /**\n * Process the given ANTLR `EquationContext` from an already parsed Vensim\n * equation definition.\n *\n * @public\n * @param {import('antlr4-vensim').EquationContext} ctx The ANTLR `EquationContext`.\n * @returns {import('../../ast/ast-types').Equation} An `Equation` AST node.\n */\n /*public*/ visitEquation(ctx /*: EquationContext*/) /*: Equation*/ {\n this.equationLhs = undefined\n this.lookupDef = undefined\n\n ctx.lhs().accept(this)\n\n let equationRhs\n const exprCtx = ctx.expr()\n if (exprCtx) {\n const exprReader = new ExprReader()\n const expr = exprReader.visitExpr(exprCtx)\n equationRhs = {\n kind: 'expr',\n expr\n }\n } else if (ctx.constList()) {\n ctx.constList().accept(this)\n equationRhs = {\n kind: 'const-list',\n constants: this.constants,\n text: this.constListText\n }\n } else if (ctx.lookup()) {\n ctx.lookup().accept(this)\n equationRhs = {\n kind: 'lookup',\n lookupDef: this.lookupDef\n }\n } else {\n equationRhs = {\n kind: 'data'\n }\n }\n\n if (this.equationLhs) {\n this.equation = {\n lhs: this.equationLhs,\n rhs: equationRhs,\n // TODO: For now, fill in an empty string for these two; this is mainly\n // for compatibility with unit tests that expect empty string instead of\n // undefined, but this should be revisited\n units: '',\n comment: ''\n }\n }\n\n return this.equation\n }\n\n visitSubscriptList(ctx) {\n // Get the subscripts found in the var name\n if (this.subscripts === undefined) {\n // These are the primary subscripts\n this.subscripts = ctx.Id().map(id => id.getText())\n } else {\n // These are subscripts that follow the :EXCEPT: keyword. Note that there\n // can be more than one set of subscripts following :EXCEPT:, so we need\n // to keep an array\n if (this.exceptSubscriptSets === undefined) {\n this.exceptSubscriptSets = []\n }\n this.exceptSubscriptSets.push(ctx.Id().map(id => id.getText()))\n }\n }\n\n visitLhs(ctx) {\n // Process the variable name\n const lhsVarName = ctx.Id().getText()\n const lhsVarId = canonicalId(lhsVarName)\n\n // Process any subscripts that follow the variable name\n super.visitLhs(ctx)\n const subscriptNames = this.subscripts\n const subscriptRefs = subscriptNames?.map(name => {\n return {\n subName: name,\n subId: canonicalId(name)\n }\n })\n\n // Process additional sets of subscripts that follow the :EXCEPT: keyword\n const exceptSubscriptSets = this.exceptSubscriptSets\n const exceptSubscriptRefSets = exceptSubscriptSets?.map(subscriptSet => {\n return subscriptSet.map(name => {\n return {\n subName: name,\n subId: canonicalId(name)\n }\n })\n })\n this.subscripts = undefined\n this.exceptSubscripts = undefined\n\n this.equationLhs = {\n varDef: {\n kind: 'variable-def',\n varName: lhsVarName,\n varId: lhsVarId,\n subscriptRefs,\n exceptSubscriptRefSets\n }\n }\n }\n\n //\n // CONST LISTS\n //\n\n visitConstList(ctx) {\n // TODO: It would be better if resolved to a `NumberLiteral[][]` (one array per dimension) to\n // better match how it appears in a model, but the antlr4-vensim grammar currently flattens\n // them into a single list (it doesn't make use of the semicolon separator), so we have to\n // do the same for now\n this.constants = ctx.expr().map(expr => {\n const text = expr.getText()\n const value = parseFloat(text)\n return {\n kind: 'number',\n value,\n text\n }\n })\n this.constListText = ctx.getText()\n }\n\n //\n // LOOKUPS\n //\n\n getPoint(lookupPoint) {\n const exprs = lookupPoint.expr()\n if (exprs.length >= 2) {\n return [parseFloat(exprs[0].getText()), parseFloat(exprs[1].getText())]\n }\n }\n\n visitLookup(ctx) {\n this.lookupRange = undefined\n this.lookupPoints = undefined\n\n if (ctx.lookupRange()) {\n ctx.lookupRange().accept(this)\n }\n if (ctx.lookupPointList()) {\n ctx.lookupPointList().accept(this)\n }\n\n let range\n if (this.lookupRange && this.lookupRange.length === 2) {\n range = {\n min: this.lookupRange[0],\n max: this.lookupRange[1]\n }\n }\n this.lookupDef = {\n kind: 'lookup-def',\n range,\n points: this.lookupPoints\n }\n }\n\n visitLookupRange(ctx) {\n this.lookupRange = ctx.lookupPoint().map(p => this.getPoint(p))\n super.visitLookupRange(ctx)\n }\n\n visitLookupPointList(ctx) {\n this.lookupPoints = ctx.lookupPoint().map(p => this.getPoint(p))\n super.visitLookupPointList(ctx)\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { Equation } from '../ast/ast-types'\nimport { EquationReader } from './impl/equation-reader'\n\n/**\n * Parse the given Vensim equation definition and return an `Equation` AST node.\n *\n * @param input A string containing the Vensim equation definition.\n * @returns An `Equation` AST node.\n */\nexport function parseVensimEquation(input: string): Equation {\n // TODO: Reuse reader instance?\n const equationReader = new EquationReader()\n return equationReader.parse(input)\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport split from 'split-string'\n\n/**\n * A single Vensim definition (either a subscript range definition or an\n * equation definition). This contains the definition's text and metadata\n * that was extracted during preprocessing.\n */\nexport interface VensimDef {\n /**\n * A simplified key for the LHS of the definition, used for sorting\n * and/or flattening.\n */\n key: string\n /**\n * The preprocessed equation or subscript range definition (with\n * units and comment replaced with `~~|`).\n */\n def: string\n /**\n * The kind of definition; either 'eqn' for an equation containing an equals\n * sign, 'dim' for a dimension (subscript range) definition, or 'decl' for\n * all other declarations (e.g., a lookup or data variable definition).\n */\n kind: 'eqn' | 'dim' | 'decl'\n /**\n * The (1-based) line number where the definition begins.\n */\n line: number\n /**\n * The units text.\n */\n units: string\n /**\n * The comment text.\n */\n comment: string\n /**\n * The optional group name, if the definition is contained within a group.\n */\n group?: string\n}\n\n/**\n * Result type for the `preprocessVensimModel` function.\n */\nexport interface PreprocessedVensimModel {\n /**\n * The preprocessed definitions that were preserved.\n */\n defs: VensimDef[]\n /**\n * The macros that were removed by the preprocessor.\n */\n removedMacros: string[]\n /**\n * The text blocks that were removed by the preprocessor. These include\n * unsupported functions (such as `TABBED ARRAY`) and other definitions\n * that were requested for removal.\n */\n removedBlocks: string[]\n}\n\n/**\n * A raw definition extracted during preprocessing. This may or may not\n * contain an actual definition (for example, it might contain a section\n * comment).\n */\ninterface RawDef {\n /**\n * The text of the raw definition.\n */\n text: string\n /**\n * The (1-based) line number where the definition begins.\n */\n line: number\n /**\n * The group in which the definition is contained (can be undefined if\n * the definition is not inside a group).\n */\n group?: string\n}\n\n/**\n * Process the given Vensim model content so that it can be parsed\n * by `antlr4-vensim`. This will:\n * - strip out group markers\n * - remove macro definitions, which are currently unsupported\n * - remove equations that reference certain unsupported functions\n * (e.g., `TABBED ARRAY`)\n * - remove everything in the private Vensim sketch section\n * - join lines that are separated by a continuation (backslash)\n * - split the input into distinct definitions (equations and\n * subscript ranges)\n *\n * The definitions are further processed to preserve the units and\n * comment text in separate properties, but strips them from the\n * equation string (replaced with `~~`) to make it easier for\n * `antlr4-vensim` to process.\n *\n * @param input The original Vensim mdl file content.\n * @param options The options that control preprocessing.\n * @return A `PreprocessedVensimModel` instance containing the preprocessed\n * Vensim definitions.\n */\nexport function preprocessVensimModel(input: string, options?: { removalKeys?: string[] }): PreprocessedVensimModel {\n // Helper function that returns true if the given def should be removed\n const removalKeys = options?.removalKeys\n function shouldRemove(text: string): boolean {\n // Remove definitions that include `TABBED ARRAY`\n if (text.includes('TABBED ARRAY')) {\n return true\n }\n\n // Remove definitions that include one of the provided removal keys\n if (removalKeys) {\n for (const key of removalKeys) {\n if (text.includes(key)) {\n return true\n }\n }\n }\n\n // Otherwise, don't remove\n return false\n }\n\n // Remove macro definitions since they are not currently supported. We replace\n // the text in the input string with blank lines where the macro definition\n // appeared so that line numbers for definitions that follow are unaffected.\n const macrosResult = removeMacros(input)\n input = macrosResult.processed\n\n // Split the model into an array of definitions (includes equations,\n // subscript ranges, and groups)\n const rawDefs = splitDefs(input)\n\n // Keep only equations and subscript range defintions\n const vensimDefs: VensimDef[] = []\n const removedBlocks: string[] = []\n for (const rawDef of rawDefs) {\n // Remove definitions that include `TABBED ARRAY` or one of the requested\n // removal keys\n if (shouldRemove(rawDef.text)) {\n removedBlocks.push(rawDef.text.trim() + '|')\n continue\n }\n\n // Process the definition\n const vensimDef = processDef(rawDef)\n if (vensimDef) {\n vensimDefs.push(vensimDef)\n }\n }\n\n return {\n defs: vensimDefs,\n removedMacros: macrosResult.removed,\n removedBlocks: removedBlocks\n }\n}\n\n/**\n * Split a Vensim model string into an array of definitions (including\n * equations, subscript ranges, and groups), without the \"|\" terminator.\n * This will allow \"|\" to occur in quoted variable names across line breaks.\n * Backslash characters will be retained.\n */\nfunction splitDefs(input: string): RawDef[] {\n // Split the full input string into definitions delineated by the \"|\" separator.\n // Note that we use the `quotes` option so that the `split` function will not\n // split on \"|\" characters that appear inside a quoted variable name, for example:\n // \"quoted variable name with | pipe\" = 5 ~~|\n const defTexts = split(input, { separator: '|', quotes: ['\"'], keep: () => true })\n\n // Calculate starting line number for each definition by accounting for the\n // number of line breaks in that definition\n const rawDefs = []\n let lineNum = 1\n let currentGroup: string\n for (let defText of defTexts) {\n if (lineNum === 1) {\n // Strip the encoding (included in first def)\n defText = defText.replace('{UTF-8}', '')\n }\n\n if (defText.includes('\\\\---/// Sketch')) {\n // Skip everything starting with the first sketch section\n break\n }\n\n // Split on the first non-whitespace character\n const parts = defText.match(/(\\s*)(.*)/ms)\n\n // Take leading line breaks into account so that we find the line where the\n // actual definition begins\n const leadingLineBreaks = parts[1]?.match(/\\r\\n|\\n|\\r/gm)\n lineNum += leadingLineBreaks?.length || 0\n\n // See if this is a group header\n if (defText.includes('********************************************************')) {\n // This is a group; save the group name\n const groupLines = splitLines(defText).filter(s => s.trim().length > 0)\n currentGroup = undefined\n if (groupLines.length > 1) {\n const groupNameLine = groupLines[1]\n const groupNameParts = groupNameLine.match(/^\\s*\\.(.*)$/)\n if (groupNameParts) {\n currentGroup = groupNameParts[1]\n }\n }\n } else {\n // This is a regular definition; add it\n rawDefs.push({\n text: defText,\n line: lineNum,\n group: currentGroup\n })\n }\n\n // Increment by the number of line breaks that appear in the definition content\n const contentLineBreaks = parts[2]?.match(/\\r\\n|\\n|\\r/gm)\n lineNum += contentLineBreaks?.length || 0\n }\n\n return rawDefs\n}\n\n/**\n * Split a string into separate lines.\n */\nfunction splitLines(input: string): string[] {\n // Windows, Unix, or old Mac line endings\n return input.split(/\\r\\n|\\n|\\r/)\n}\n\n/**\n * Split a string on the given separator character. This will not split\n * if the character appears inside a quoted variable name. For example,\n * this will not split on '(' when it appears in the variable name, but\n * will split the '(' in the lookup expression\n * \"quoted variable (name)\" ((0,0),(1,1)) ~~|\n */\nfunction splitExceptInQuoted(input: string, sep: string): string[] {\n return split(input, { separator: sep, quotes: ['\"'] })\n}\n\n/**\n * Join lines that are separated by a continuation (backslash) character.\n */\nfunction processBackslashes(input: string): string {\n const inputLines = splitLines(input)\n\n let output = ''\n let prevLine = ''\n for (let line of inputLines) {\n // Join a previous line with a backslash ending to the current line\n if (prevLine !== '') {\n line = prevLine + line.trim()\n prevLine = ''\n }\n const continuation = line.match(/\\\\\\s*$/)\n if (continuation) {\n // If there is a backslash ending on this line, save it without the backslash\n prevLine = line.substr(0, continuation.index).replace(/\\s+$/, ' ')\n } else {\n // There is no continuation on this line, include in output\n output += line + '\\n'\n }\n }\n\n return output\n}\n\n/**\n * Match delimiters recursively. Replace delimited strings globally.\n *\n * @param str The string to operate on.\n * @param open The opening delimiter characters.\n * @param close The closing delimiter characters.\n * @param newStr The string to replace delimited substrings with.\n */\nfunction replaceDelimitedStrings(str: string, open: string, close: string, newStr: string): string {\n let result = ''\n let start = 0\n let depth = 0\n const n = str.length\n for (let i = 0; i < n; i++) {\n if (str.charAt(i) === open) {\n if (depth === 0) {\n result += str.substring(start, i)\n }\n depth++\n } else if (str.charAt(i) === close && depth > 0) {\n depth--\n if (depth === 0) {\n result += newStr\n start = i + 1\n }\n }\n }\n if (start < n) {\n result += str.substring(start)\n }\n return result\n}\n\n/**\n * Replace all newlines and redundant whitespace into single spaces so\n * that everything is on a single line.\n */\nfunction reduceWhitespace(input: string): string {\n return input.replace(/\\s\\s+/g, ' ').trim()\n}\n\n// Detect one or more consecutive whitespace or underscore characters\nconst reWhitespace = new RegExp('(\\\\s|_)+', 'g')\n\n/**\n * Create a key from the given definition's LHS that can be used during\n * flattening and/or sorting, and include the kind.\n */\nfunction keyForDef(def: string): { key: string; kind: 'eqn' | 'dim' | 'decl' } {\n // Note: The steps in this function were lifted directly from the legacy\n // preprocessor, mainly so that we would retain compatibility when writing\n // tests that compare the legacy parser to the new one.\n\n let key = def\n\n // Strip the \":INTERPOLATE:\"; it should not be included in the key\n key = key.replace(/:INTERPOLATE:/g, '')\n\n let kind: 'eqn' | 'dim' | 'decl'\n if (key.includes('=')) {\n // The line contains an '='; treat this as an equation\n kind = 'eqn'\n key = key.split('=')[0].trim()\n } else if (key.includes(':')) {\n // The line contains a ':'; treat this as a subscript range (dimension)\n kind = 'dim'\n key = key.split(':')[0].trim()\n } else {\n // Treat this as a general declaration\n kind = 'decl'\n }\n\n // Ignore the lookup data if it starts on the first line\n key = splitExceptInQuoted(key, '(')[0]\n\n // Ignore double quotes\n key = key.replace(/\"/g, '')\n\n // Ignore any leading or trailing whitespace that remains\n key = key.trim()\n\n // Remove whitespace on the inside of the brackets\n key = key.replace(/(?<=\\[).*?(?=\\])/g, match => match.replace(/\\s/g, ''))\n\n // Replace one or more consecutive whitespace or underscore characters with a single\n // underscore character; this matches the behavior of Vensim documented here:\n // https://www.vensim.com/documentation/ref_variable_names.html\n key = key.replace(reWhitespace, '_')\n\n // Ignore case\n key = key.toLowerCase()\n\n return { key, kind }\n}\n\n/**\n * Strip out unnecessary parts of the given raw definition string and\n * return a `VensimDef` containing the processed definition along with\n * the units and comment strings.\n */\nfunction processDef(rawDef: RawDef): VensimDef | undefined {\n let input = rawDef.text\n\n // Remove \":RAW:\" flag; it is not needed by SDE and causes problems if left in\n input = input.replace(/:RAW:/g, '')\n\n // Remove inline comments\n input = replaceDelimitedStrings(input, '{', '}', '')\n\n // Remove whitespace\n input = input.trim()\n\n // Skip empty definitions\n if (input.length === 0) {\n return undefined\n }\n\n // Join lines that are separated by a continuation (backslash) character\n input = processBackslashes(input)\n\n // Split on the comment delimiters\n const parts = input.split('~')\n\n // If the definition is malformed, throw an error\n if (parts.length < 3) {\n throw new Error(`Found invalid model definition during preprocessing (missing comment delimiters?):\\n\\n${input}`)\n }\n\n // Get the raw def as a single line\n const rawDefText = reduceWhitespace(parts[0])\n\n // Create the key\n const { key, kind } = keyForDef(rawDefText)\n\n // Rebuild the def with a simple `~~|` ending\n const def = `${rawDefText} ~~|`\n\n // Extract the units text\n const units = reduceWhitespace(parts[1])\n\n // Extract the comment text\n // TODO: Preserve newlines in comments?\n const comment = reduceWhitespace(parts[2])\n\n // TODO: Extract the `:SUPPLEMENTARY:` flags?\n\n // Preserve the group name, if defined\n const group = rawDef.group\n\n return {\n key,\n def,\n kind,\n line: rawDef.line,\n units,\n comment,\n ...(group ? { group } : {})\n }\n}\n\n/**\n * Remove macro definitions from the input string. We replace the text in the input\n * string with blank lines where the macro definition appeared so that line numbers\n * for definitions that follow are unaffected.\n *\n * @param input The original Vensim mdl file content.\n * @return The processed string and the text blocks that were removed.\n */\nfunction removeMacros(input: string): { processed: string; removed: string[] } {\n // Keep an array of removed strings\n const removed: string[] = []\n\n // Find all macro definitions\n const processed = input.replace(/:MACRO:.*:END OF MACRO:/gms, match => {\n // Add the removed macro to the array\n removed.push(match)\n\n // Replace each macro definition with blank lines so that line numbers for\n // definitions that follow are unaffected\n const numBreaks = match.split(/\\r\\n|\\n|\\r/gms).length - 1\n return numBreaks > 0 ? '\\n'.repeat(numBreaks) : ''\n })\n\n return {\n processed,\n removed\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport { ModelVisitor } from 'antlr4-vensim'\n\nimport { createAntlrParser } from './antlr-parser'\nimport { EquationReader } from './equation-reader'\nimport { SubscriptRangeReader } from './subscript-range-reader'\n\nexport class ModelReader extends ModelVisitor {\n /**\n * @public\n * @param {import('../vensim-parse-context').VensimParseContext} parseContext An object\n * that provides access to file system resources (such as external data files) that are\n * referenced during the parse phase.\n */\n constructor(parseContext /*: VensimParseContext*/) {\n super()\n this.parseContext = parseContext\n this.dimensions = []\n this.equations = []\n }\n\n /**\n * Parse the given Vensim model definition and return a `Model` AST node.\n *\n * @public\n * @param {string} modelText A string containing the Vensim model.\n * @returns {import('../../ast/ast-types').Model} A `Model` AST node.\n */\n /*public*/ parse(modelText /*: string*/) /*: Model*/ {\n const parser = createAntlrParser(modelText)\n const modelCtx = parser.model()\n modelCtx.accept(this)\n return this.model\n }\n\n visitModel(ctx) {\n const subscriptRangesCtx = ctx.subscriptRange()\n if (subscriptRangesCtx) {\n // TODO: Can we reuse reader instances?\n const subscriptReader = new SubscriptRangeReader(this.parseContext)\n for (const subscriptRangeCtx of subscriptRangesCtx) {\n const dimensionDef = subscriptReader.visitSubscriptRange(subscriptRangeCtx)\n this.dimensions.push(dimensionDef)\n }\n }\n\n const equationsCtx = ctx.equation()\n if (equationsCtx) {\n // TODO: Can we reuse reader instances?\n const equationReader = new EquationReader()\n for (const equationCtx of equationsCtx) {\n const equation = equationReader.visitEquation(equationCtx)\n this.equations.push(equation)\n }\n }\n\n this.model = {\n dimensions: this.dimensions,\n equations: this.equations\n }\n }\n}\n","// Copyright (c) 2023 Climate Interactive / New Venture Fund\n\nimport type { DimensionDef, Equation, Model } from '../ast/ast-types'\nimport { preprocessVensimModel } from './preprocess-vensim'\nimport type { VensimParseContext } from './vensim-parse-context'\nimport { ModelReader } from './impl/model-reader'\n\n/**\n * Parse the given Vensim model definition and return a `Model` AST node.\n *\n * @param input A string containing the Vensim model.\n * @param context An object that provides access to file system resources (such as\n * external data files) that are referenced during the parse phase.\n * @param sort Whether to sort definitions alphabetically during the preprocessing phase.\n * @returns A `Model` AST node.\n */\nexport function parseVensimModel(input: string, context?: VensimParseContext, sort = false): Model {\n const dimensions: DimensionDef[] = []\n const equations: Equation[] = []\n\n // Run the preprocessor on the input (to separate out units, comments, unsupported\n // sections, etc) so that it can be parsed more easily by `antlr4-vensim`.\n const { defs } = preprocessVensimModel(input)\n if (sort) {\n // Sort the definitions alphabetically by key. This mainly exists for compatibility\n // with the legacy preprocessor; it is not an essential step so is left disabled\n // by default.\n defs.sort((a, b) => {\n return a.key < b.key ? -1 : a.key > b.key ? 1 : 0\n })\n }\n\n // Parse each subscript range or equation definition\n for (const def of defs) {\n // TODO: Reuse reader instance?\n let parsedModel: Model\n try {\n const modelReader = new ModelReader(context)\n parsedModel = modelReader.parse(def.def)\n } catch (e) {\n // Include context such as line/column numbers in the error message if available\n let linePart = ''\n if (e.cause?.code === 'VensimParseError') {\n if (e.cause.line) {\n // The line number reported by ANTLR is relative to the beginning of the\n // preprocessed definition (since we parse each definition individually),\n // so we need to add it to the line of the definition in the original source\n linePart += ` at line ${e.cause.line - 1 + def.line}`\n if (e.cause.column) {\n linePart += `, col ${e.cause.column}`\n }\n }\n }\n const msg = `Failed to parse Vensim model definition${linePart}:\\n${def.def}\\n\\nDetail:\\n ${e.message}`\n throw new Error(msg)\n }\n\n for (const dimensionDef of parsedModel.dimensions) {\n // Fold in the other strings that were extracted during preprocessing\n const group = def.group\n dimensions.push({\n ...dimensionDef,\n comment: def.comment,\n ...(group ? { group } : {})\n })\n }\n\n for (const equation of parsedModel.equations) {\n // Fold in the other strings that were extracted during preprocessing\n const group = def.group\n equations.push({\n ...equation,\n units: def.units,\n comment: def.comment,\n ...(group ? { group } : {})\n })\n }\n }\n\n return {\n dimensions,\n equations\n }\n}\n","// Copyright (c) 2023-2026 Climate Interactive / New Venture Fund\n\nimport type { XmlElement, XmlText } from '@rgrove/parse-xml'\nimport { XmlNode } from '@rgrove/parse-xml'\n\nexport function firstElemOf(parent: XmlElement | undefined, tagName: string): XmlElement | undefined {\n return parent?.children.find(n => {\n if (n.type === XmlNode.TYPE_ELEMENT) {\n const e = n as XmlElement\n return e.name === tagName\n } else {\n return undefined\n }\n }) as XmlElement\n}\n\nexport function firstTextOf(parent: XmlElement | undefined): XmlText | undefined {\n return parent?.children.find(n => {\n return n.type === XmlNode.TYPE_TEXT\n }) as XmlText\n}\n\nexport function elemsOf(parent: XmlElement | undefined, tagNames: string[]): XmlElement[] {\n if (parent === undefined) {\n return []\n }\n\n const elems: XmlElement[] = []\n for (const n of parent.children) {\n if (n.type === XmlNode.TYPE_ELEMENT) {\n const e = n as XmlElement\n if (tagNames.includes(e.name)) {\n elems.push(e)\n }\n }\n }\n return elems\n}\n\nexport function xmlError(elem: XmlElement, msg: string): string {\n return `${msg}: ${JSON.stringify(elem.toJSON(), null, 2)}`\n}\n","// Copyright (c) 2023-2026 Climate Interactive / New Venture Fund\n\nimport type { XmlElement } from '@rgrove/parse-xml'\n\nimport { canonicalId } from '../_shared/canonical-id'\n\nimport type { DimensionDef, SubscriptRef } from '../ast/ast-types'\n\nimport { elemsOf, firstElemOf, xmlError } from './xml'\n\n/**\n * Parse the given XMILE dimension (`<dim>`) definition and return a `DimensionDef` AST node.\n *\n * @param input A string containing the XMILE `<dim>` definition.\n * @returns A `DimensionDef` AST node.\n */\nexport function parseXmileDimensionDef(dimElem: XmlElement): DimensionDef {\n // Extract <dim name=\"...\">\n const dimName = dimElem.attributes?.name\n if (dimName === undefined) {\n throw new Error(xmlError(dimElem, '<dim> name attribute is required for dimension definition'))\n }\n\n // Extract <dim> child <elem> elements\n const elemElems = elemsOf(dimElem, ['elem'])\n if (elemElems.length === 0) {\n throw new Error(xmlError(dimElem, '<dim> must contain one or more <elem> elements'))\n }\n const subscriptRefs: SubscriptRef[] = []\n for (const elem of elemElems) {\n // Extract <elem name=\"...\">\n const subName = elem.attributes?.name\n if (subName === undefined) {\n throw new Error(xmlError(dimElem, '<elem> name attribute is required for dimension element definition'))\n }\n\n const subId = canonicalId(subName)\n subscriptRefs.push({\n subId,\n subName\n })\n }\n\n // Extract <doc> -> comment string\n const comment = firstElemOf(dimElem, 'doc')?.text || ''\n\n const dimId = canonicalId(dimName)\n return {\n dimName,\n dimId,\n // TODO: For Vensim `DimA <-> DimB` aliases, the family name would be `DimB`\n familyName: dimName,\n familyId: dimId,\n subscriptRefs,\n // TODO: Does XMILE support mappings?\n subscriptMappings: [],\n comment\n }\n}\n","// Copyright (c) 2023-2026 Climate Interactive / New Venture Fund\n\nimport type { XmlElement } from '@rgrove/parse-xml'\nimport { parseXml } from '@rgrove/parse-xml'\n\nimport type { DimensionDef, Equation, Model, SimulationSpec } from '../ast/ast-types'\n\nimport { parseXmileDimensionDef } from './parse-xmile-dimension-def'\nimport { parseXmileVariableDef } from './parse-xmile-variable-def'\nimport { firstElemOf, elemsOf, xmlError } from './xml'\n\n/**\n * Parse the given XMILE model definition and return a `Model` AST node.\n *\n * @param input A string containing the XMILE model.\n * @param context An object that provides access to file system resources (such as\n * external data files) that are referenced during the parse phase.\n * @returns A `Model` AST node.\n */\nexport function parseXmileModel(input: string): Model {\n let xml\n try {\n // Enable position tracking to get byte offsets for line number calculation\n xml = parseXml(input, { includeOffsets: true })\n } catch (e) {\n // Include context such as line/column numbers in the error message if available\n const msg = `Failed to parse XMILE model definition:\\n\\n${e.message}`\n throw new Error(msg)\n }\n\n // Extract <sim_specs> -> SimulationSpec\n const simulationSpec: SimulationSpec = parseSimSpecs(xml.root, input)\n\n // Extract <dimensions> -> DimensionDef[]\n const dimensions: DimensionDef[] = parseDimensionDefs(xml.root, input)\n\n // Extract <variables> -> Equation[]\n const equations: Equation[] = parseVariableDefs(xml.root, input)\n\n return {\n simulationSpec,\n dimensions,\n equations\n }\n}\n\nfunction parseSimSpecs(rootElem: XmlElement | undefined, originalXml: string): SimulationSpec {\n // Extract <sim_specs> element\n const simSpecsElem = firstElemOf(rootElem, 'sim_specs')\n if (simSpecsElem === undefined) {\n throw new Error(xmlError(rootElem, '<sim_specs> element is required for XMILE model definition'))\n }\n\n function getSimSpecValue(name: string, required: boolean): number | undefined {\n const elem = firstElemOf(simSpecsElem, name)\n if (required && elem === undefined) {\n const error = new Error(xmlError(simSpecsElem, `<${name}> element is required in XMILE sim specs`))\n throwXmileParseError(error, originalXml, simSpecsElem, 'model')\n }\n if (elem === undefined) {\n return undefined\n }\n const value = Number(elem.text)\n if (!isNaN(value)) {\n return value\n } else {\n const error = new Error(xmlError(elem, `Invalid numeric value for <${name}> element: ${elem.text}`))\n throwXmileParseError(error, originalXml, simSpecsElem, 'model')\n }\n }\n\n // Extract <start> element\n const startTime = getSimSpecValue('start', true)\n\n // Extract <stop> element\n const endTime = getSimSpecValue('stop', true)\n\n // Extract <dt> element\n let timeStep = getSimSpecValue('dt', false)\n if (timeStep === undefined) {\n // The default `dt` value is 1 according to the XMILE spec\n timeStep = 1\n }\n\n return {\n startTime,\n endTime,\n timeStep\n }\n}\n\nfunction parseDimensionDefs(rootElem: XmlElement | undefined, originalXml: string): DimensionDef[] {\n const dimensionDefs: DimensionDef[] = []\n\n const dimensionsElem = firstElemOf(rootElem, 'dimensions')\n if (dimensionsElem) {\n // Extract <dim> -> SubscriptRange\n const dimElems = elemsOf(dimensionsElem, ['dim'])\n for (const dimElem of dimElems) {\n try {\n dimensionDefs.push(parseXmileDimensionDef(dimElem))\n } catch (e) {\n throwXmileParseError(e, originalXml, dimElem, 'dimension')\n }\n }\n }\n\n return dimensionDefs\n}\n\nfunction parseVariableDefs(rootElem: XmlElement | undefined, originalXml: string): Equation[] {\n const modelElem = firstElemOf(rootElem, 'model')\n if (modelElem === undefined) {\n return []\n }\n\n const equations: Equation[] = []\n const variablesElem = firstElemOf(modelElem, 'variables')\n if (variablesElem) {\n // Extract variable definition (e.g., <aux>, <stock>, <flow>, <gf>) -> Equation[]\n const varElems = elemsOf(variablesElem, ['aux', 'stock', 'flow', 'gf'])\n for (const varElem of varElems) {\n try {\n const eqns = parseXmileVariableDef(varElem)\n if (eqns) {\n equations.push(...eqns)\n }\n } catch (e) {\n throwXmileParseError(e, originalXml, varElem, 'variable')\n }\n }\n }\n\n return equations\n}\n\nfunction throwXmileParseError(\n originalError: Error,\n originalXml: string,\n elem: XmlElement,\n elemKind: 'model' | 'dimension' | 'variable'\n): void {\n // Include context such as line/column numbers in the error message if available\n let linePart = ''\n // Try to get line number from the XML element's position\n const lineNumInOriginalXml = getLineNumber(originalXml, elem.start)\n if (lineNumInOriginalXml !== -1) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const cause = (originalError as any).cause as { code?: string; line?: number; column?: number }\n if (cause?.code === 'VensimParseError') {\n if (cause.line) {\n // The line number reported by ANTLR is relative to the beginning of the\n // preprocessed definition (since we parse each definition individually),\n // so we need to add it to the line of the definition in the original source\n const lineNum = cause.line - 1 + lineNumInOriginalXml\n linePart += ` at line ${lineNum}`\n if (cause.column) {\n linePart += `, col ${cause.column}`\n }\n }\n } else {\n // Include the line number from the original XML\n linePart += ` at line ${lineNumInOriginalXml}`\n }\n }\n const elemString = extractXmlLines(originalXml, elem.start, elem.end)\n const msg = `Failed to parse XMILE ${elemKind} definition${linePart}:\\n${elemString}\\n\\nDetail:\\n ${originalError.message}`\n throw new Error(msg)\n}\n\n/**\n * Calculate the line number from a byte offset in the original XML string.\n *\n * @param xmlString The original XML string\n * @param byteOffset The byte offset from the XmlElement\n * @returns The line number (1-indexed) or -1 if offset is invalid\n */\nfunction getLineNumber(xmlString: string, byteOffset: number): number {\n if (byteOffset === -1 || byteOffset >= xmlString.length) {\n return -1\n }\n\n // Count newlines up to the byte offset\n const substring = xmlString.substring(0, byteOffset)\n return substring.split('\\n').length\n}\n\n/**\n * Extract relevant lines from the original XML string using start/end byte offsets.\n * Includes full lines for context, even if start/end are not at line boundaries.\n *\n * @param originalXml The original XML string\n * @param startOffset The starting byte offset\n * @param endOffset The ending byte offset\n * @returns A string containing the relevant lines with line numbers\n */\nfunction extractXmlLines(originalXml: string, startOffset: number, endOffset: number): string {\n if (startOffset === -1 || endOffset === -1 || startOffset >= originalXml.length || endOffset > originalXml.length) {\n return '[Unable to extract XML lines - invalid offsets]'\n }\n\n // Find the start of the line containing the start offset\n let lineStart = startOffset\n while (lineStart > 0 && originalXml[lineStart - 1] !== '\\n') {\n lineStart--\n }\n\n // Find the end of the line containing the end offset\n let lineEnd = endOffset\n while (lineEnd < originalXml.length && originalXml[lineEnd] !== '\\n') {\n lineEnd++\n }\n\n // Extract the lines\n const relevantXml = originalXml.substring(lineStart, lineEnd)\n\n // Return just the XML content without line number prefix\n return relevantXml\n}\n","// Copyright (c) 2023-2026 Climate Interactive / New Venture Fund\n\nimport type { XmlElement } from '@rgrove/parse-xml'\n\nimport { canonicalId } from '../_shared/canonical-id'\n\nimport { call, lookupDef, subRef } from '../ast/ast-builders'\nimport type { Equation, Expr, LookupDef, LookupPoint, SubscriptRef } from '../ast/ast-types'\n\nimport { parseVensimExpr } from '../vensim/parse-vensim-expr'\n\nimport { elemsOf, firstElemOf, firstTextOf, xmlError } from './xml'\n\n/**\n * Parse the given XMILE variable definition and return an array of `Equation` AST nodes\n * corresponding to the variable definition (or definitions, in the case of a\n * non-apply-to-all variable that is defined with an `<element>` for each subscript).\n *\n * @param input A string containing the XMILE equation definition.\n * @returns An `Equation` AST node.\n */\nexport function parseXmileVariableDef(varElem: XmlElement): Equation[] {\n // Extract required variable name\n let varName = parseRequiredAttr(varElem, varElem, 'name')\n // XXX: Variable names in XMILE can contain newline sequences (represented as '\\n'). For now\n // we will replace them with spaces since `canonicalId` does not currently handle this case.\n varName = varName.replace(/\\\\n/g, ' ')\n const varId = canonicalId(varName)\n\n // Extract optional <units> -> units string\n const units = firstElemOf(varElem, 'units')?.text || ''\n\n // Extract optional <doc> -> comment string\n const comment = firstElemOf(varElem, 'doc')?.text || ''\n\n // Helper function that creates a single `Equation` instance with an expression for\n // this variable definition\n function exprEquation(subscriptRefs: SubscriptRef[] | undefined, expr: Expr): Equation {\n return {\n lhs: {\n varDef: {\n kind: 'variable-def',\n varName,\n varId,\n subscriptRefs\n }\n },\n rhs: {\n kind: 'expr',\n expr\n },\n units,\n comment\n }\n }\n\n // Helper function that creates a single `Equation` instance with a lookup for\n // this variable definition\n function lookupEquation(subscriptRefs: SubscriptRef[] | undefined, lookup: LookupDef): Equation {\n return {\n lhs: {\n varDef: {\n kind: 'variable-def',\n varName,\n varId,\n subscriptRefs\n }\n },\n rhs: {\n kind: 'lookup',\n lookupDef: lookup\n },\n units,\n comment\n }\n }\n\n if (varElem.name === 'gf') {\n // This is a top-level <gf>\n // TODO: Are subscripted <gf> elements allowed? If so, handle them here.\n const lookup = parseGfElem(varElem, varElem)\n return [lookupEquation(undefined, lookup)]\n }\n\n // Check for <dimensions>\n const dimensionsElem = firstElemOf(varElem, 'dimensions')\n const equationDefs: Equation[] = []\n if (dimensionsElem === undefined) {\n // This is a non-subscripted variable\n const gfElem = firstElemOf(varElem, 'gf')\n if (gfElem) {\n // The variable is defined with a graphical function\n if (varElem.name !== 'flow' && varElem.name !== 'aux') {\n throw new Error(xmlError(varElem, '<gf> is only allowed for <flow> and <aux> variables'))\n }\n const lookup = parseGfElem(varElem, gfElem)\n equationDefs.push(lookupEquation(undefined, lookup))\n } else {\n // The variable is defined with an equation\n const expr = parseEqnElem(varElem, varElem)\n if (expr) {\n equationDefs.push(exprEquation(undefined, expr))\n }\n }\n } else {\n // This is an array (subscripted) variable. An array variable definition will include\n // a <dimensions> element that declares which dimensions are used.\n const dimElems = elemsOf(dimensionsElem, ['dim'])\n const dimNames: string[] = []\n for (const dimElem of dimElems) {\n const dimName = dimElem.attributes?.name\n if (dimName === undefined) {\n throw new Error(xmlError(varElem, '<dim> name attribute is required in <dimensions> for variable definition'))\n }\n dimNames.push(dimName)\n }\n\n // If it is an apply-to-all variable, there will be a single <eqn>. If it is a\n // non-apply-to-all variable, there will be one or more <element> elements that define\n // the separate equation for each \"instance\".\n // TODO: Handle apply-to-all variable defs that contain <gf>?\n const elementElems = elemsOf(varElem, ['element'])\n if (elementElems.length === 0) {\n // This is an apply-to-all variable\n const dimRefs = dimNames.map(subRef)\n const expr = parseEqnElem(varElem, varElem)\n if (expr) {\n equationDefs.push(exprEquation(dimRefs, expr))\n }\n } else {\n // This is a non-apply-to-all variable\n // TODO: We should change SubscriptRef so that it can include an explicit dimension\n // name/ID (which we can pull from the <dimensions> section of the variable definition).\n // Until then, we will include the subscript name only (and we do not yet support\n // numeric subscript indices).\n // TODO: Handle non-apply-to-all variable defs that contain <gf>?\n for (const elementElem of elementElems) {\n const subscriptAttr = elementElem.attributes?.subscript\n if (subscriptAttr === undefined) {\n throw new Error(xmlError(varElem, '<element> subscript attribute is required in variable definition'))\n }\n const subscriptNames = subscriptAttr.split(',').map(s => s.trim())\n const subRefs: SubscriptRef[] = []\n for (const subscriptName of subscriptNames) {\n if (!isNaN(parseInt(subscriptAttr))) {\n throw new Error(xmlError(varElem, 'Numeric subscript indices are not currently supported'))\n }\n subRefs.push(subRef(subscriptName))\n }\n const expr = parseEqnElem(varElem, elementElem)\n if (expr) {\n equationDefs.push(exprEquation(subRefs, expr))\n }\n }\n }\n }\n\n return equationDefs\n}\n\nfunction parseEqnElem(varElem: XmlElement, parentElem: XmlElement): Expr {\n const varTagName = varElem.name\n const eqnElem = firstElemOf(parentElem, 'eqn')\n\n // Interpret the <eqn> element\n // TODO: Handle the case where <eqn> is defined using CDATA\n const eqnText = eqnElem ? firstTextOf(eqnElem) : undefined\n switch (varTagName) {\n case 'aux': {\n if (eqnText === undefined) {\n // Technically the <eqn> is optional for an <aux>; if not defined, we will skip it\n return undefined\n }\n\n // Check for <init_eqn> element. In XMILE, an aux variable can have a separate\n // init-time equation using <init_eqn>. This is equivalent to Vensim's ACTIVE_INITIAL\n // function, so we synthesize an ACTIVE_INITIAL call when both elements are present.\n const initEqnElem = firstElemOf(parentElem, 'init_eqn')\n const initEqnText = initEqnElem ? firstTextOf(initEqnElem) : undefined\n if (initEqnText !== undefined) {\n // Synthesize ACTIVE INITIAL(eqnExpr, initEqnExpr)\n const eqnExpr = parseExpr(eqnText.text)\n const initEqnExpr = parseExpr(initEqnText.text)\n return call('ACTIVE INITIAL', eqnExpr, initEqnExpr)\n }\n\n return parseExpr(eqnText.text)\n }\n\n case 'stock': {\n // <stock> elements are currently translated to a Vensim-style aux:\n // INTEG({inflow1} + {inflow2} + ... - {outflow1} - {outflow2} - ..., {eqn})\n if (eqnText === undefined) {\n // An <eqn> is currently required for a <stock>\n throw new Error(xmlError(varElem, 'An <eqn> is required for a <stock> variable'))\n }\n const inflowElems = elemsOf(parentElem, ['inflow'])\n const outflowElems = elemsOf(parentElem, ['outflow'])\n // TODO: Handle the case where <inflow> or <outflow> is defined using CDATA\n const inflowTexts = inflowElems.map(inflowElem => {\n const inflowText = firstTextOf(inflowElem)\n if (inflowText === undefined) {\n throw new Error(xmlError(varElem, 'An <inflow> must be non-empty for a <stock> variable'))\n }\n return inflowText.text\n })\n const outflowTexts = outflowElems.map(outflowElem => {\n const outflowText = firstTextOf(outflowElem)\n if (outflowText === undefined) {\n throw new Error(xmlError(varElem, 'An <outflow> must be non-empty for a <stock> variable'))\n }\n return outflowText.text\n })\n\n // TODO: We currently do not support certain <stock> options, so for now we\n // fail fast if we encounter these\n if (firstElemOf(parentElem, 'conveyor')) {\n throw new Error(xmlError(varElem, 'Currently <conveyor> is not supported for a <stock> variable'))\n }\n if (firstElemOf(parentElem, 'queue')) {\n throw new Error(xmlError(varElem, 'Currently <queue> is not supported for a <stock> variable'))\n }\n // TODO: We currently ignore `<non_negative>` elements during parsing since it is noted in the XMILE\n // spec that it is not directly supported by XMILE and an optional vendor-specific feature. More\n // work will be needed to make this work according to the spec, but for now it's OK to ignore it.\n // if (firstElemOf(parentElem, 'non_negative')) {\n // throw new Error(xmlError(varElem, 'Currently <non_negative> is not supported for a <stock> variable'))\n // }\n\n // Combine the inflow and outflow expressions into a single expression\n // TODO: Do we need to worry about parentheses here?\n const inflowParts = inflowTexts.join(' + ')\n let outflowParts = outflowTexts.join(' - ')\n if (outflowTexts.length > 0) {\n if (inflowParts.length > 0) {\n outflowParts = `- ${outflowParts}`\n } else {\n outflowParts = `-${outflowParts}`\n }\n }\n const flowsExpr = parseExpr(`${inflowParts} ${outflowParts}`)\n\n // Synthesize a Vensim-style `INTEG` function call\n const initExpr = parseExpr(eqnText.text)\n return call('INTEG', flowsExpr, initExpr)\n }\n\n case 'flow':\n // <flow> elements with an <eqn> are currently translated to a Vensim-style aux\n // TODO: The XMILE spec says some <flow> variants must not have an equation (in the case\n // of conveyors or queues). For now, we don't support those, and we require an <eqn>.\n if (eqnText === undefined) {\n // An <eqn> is currently required for a <stock>\n throw new Error(xmlError(varElem, 'Currently <eqn> or <gf> is required for a <flow> variable'))\n }\n // TODO: We currently do not support certain <stock> options, so for now we\n // fail fast if we encounter these\n if (firstElemOf(parentElem, 'multiplier')) {\n throw new Error(xmlError(varElem, 'Currently <multiplier> is not supported for a <flow> variable'))\n }\n // TODO: We currently ignore `<non_negative>` elements during parsing since it is noted in the XMILE\n // spec that it is not directly supported by XMILE and an optional vendor-specific feature. More\n // work will be needed to make this work according to the spec, but for now it's OK to ignore it.\n // if (firstElemOf(parentElem, 'non_negative')) {\n // throw new Error(xmlError(varElem, 'Currently <non_negative> is not supported for a <flow> variable'))\n // }\n if (firstElemOf(parentElem, 'overflow')) {\n throw new Error(xmlError(varElem, 'Currently <overflow> is not supported for a <flow> variable'))\n }\n if (firstElemOf(parentElem, 'leak')) {\n throw new Error(xmlError(varElem, 'Currently <leak> is not supported for a <flow> variable'))\n }\n return parseExpr(eqnText.text)\n\n default:\n throw new Error(xmlError(varElem, `Unhandled variable type '${varTagName}'`))\n }\n}\n\nfunction parseExpr(exprText: string): Expr {\n // Except for a few slight differences (e.g., `IF ... THEN ... ELSE ...`), the expression\n // syntax in XMILE is the same as in Vensim, so we will use the existing Vensim expression\n // parser here. The idiomatic way to do conditional statements in XMILE is:\n // IF {condition} THEN {trueExpr} ELSE {falseExpr}\n // But the spec allows for the Vensim form:\n // IF_THEN_ELSE({condition}, {trueExpr}, {falseExpr})\n // Since we only support the latter in the compile package, it's better if we transform\n // the XMILE form to Vensim form, and then we can use the Vensim expression parser.\n exprText = convertConditionalExpressions(exprText)\n\n // XXX: XMILE uses different syntax for array functions than Vensim. XMILE uses an\n // asterisk (wildcard), e.g., `SUM(x[*])`, while Vensim uses e.g., `SUM(x[DimA!])`.\n // To allow for reusing the Vensim expression parser, we will replace the XMILE wildcard\n // with the Vensim syntax (using a placeholder dimension name; the real one will be\n // resolved later).\n exprText = exprText.replace(/\\[([^\\]]*)\\*([^\\]]*)\\]/g, '[$1_SDE_WILDCARD_!$2]')\n\n return parseVensimExpr(exprText)\n}\n\nfunction parseGfElem(varElem: XmlElement, gfElem: XmlElement): LookupDef {\n // Parse the optional `type` attribute\n const typeAttr = parseOptionalAttr(gfElem, 'type')\n if (typeAttr && typeAttr !== 'continuous') {\n throw new Error(xmlError(varElem, 'Currently \"continuous\" is the only type supported for <gf>'))\n }\n\n // Parse the required <ypts>\n const yptsElem = firstElemOf(gfElem, 'ypts')\n if (yptsElem === undefined) {\n throw new Error(xmlError(varElem, '<ypts> must be defined for a <gf>'))\n }\n const ypts = parseGfPts(varElem, yptsElem)\n if (ypts.length === 0) {\n throw new Error(xmlError(varElem, '<ypts> must have at least one element'))\n }\n\n // Check for <xpts> or <xscale> (must be one or the other)\n const xptsElem = firstElemOf(gfElem, 'xpts')\n const xscaleElem = firstElemOf(gfElem, 'xscale')\n if (xptsElem && xscaleElem) {\n throw new Error(xmlError(varElem, '<gf> must contain <xpts> or <xscale> but not both'))\n } else if (xptsElem === undefined && xscaleElem === undefined) {\n throw new Error(xmlError(varElem, '<gf> must contain either <xpts> or <xscale>'))\n }\n\n let xpts: number[]\n if (xptsElem) {\n // Parse the <xpts>\n xpts = parseGfPts(varElem, xptsElem)\n if (xpts.length === 0) {\n throw new Error(xmlError(varElem, '<xpts> must have at least one element'))\n }\n } else {\n // Parse the <xscale>\n const xMin = parseFloatAttr(varElem, xscaleElem, 'min')\n const xMax = parseFloatAttr(varElem, xscaleElem, 'max')\n if (xMin > xMax) {\n throw new Error(xmlError(varElem, '<xscale> max attribute must be > min attribute'))\n }\n xpts = Array(ypts.length)\n const xRange = xMax - xMin\n if (ypts.length === 1) {\n // TODO: Error?\n xpts[0] = 0\n } else {\n for (let i = 0; i < ypts.length; i++) {\n const frac = i / (ypts.length - 1)\n xpts[i] = xMin + xRange * frac\n }\n }\n }\n\n // Check for same length as <ypts>\n if (xpts.length !== ypts.length) {\n throw new Error(xmlError(varElem, '<xpts> and <ypts> must have the same number of elements'))\n }\n\n // Zip the arrays\n const points: LookupPoint[] = []\n for (let i = 0; i < xpts.length; i++) {\n points.push([xpts[i], ypts[i]])\n }\n return lookupDef(points)\n}\n\nfunction parseGfPts(varElem: XmlElement, ptsElem: XmlElement): number[] {\n const ptsText = firstTextOf(ptsElem)?.text\n if (ptsText === undefined) {\n return []\n }\n\n const sep = ptsElem.attributes?.sep || ','\n const elems = ptsText.split(sep)\n const nums: number[] = []\n for (const elem of elems) {\n const numText = elem.trim()\n const num = parseFloat(numText)\n if (isNaN(num)) {\n console.log(JSON.stringify(ptsElem))\n throw new Error(xmlError(varElem, `Invalid number value '${numText}' in <${ptsElem.name}>'`))\n }\n nums.push(num)\n }\n return nums\n}\n\nfunction parseRequiredAttr(varElem: XmlElement, elem: XmlElement, attrName: string): string {\n let s = elem.attributes && elem.attributes[attrName]\n s = s?.trim()\n if (s === undefined || s.length === 0) {\n throw new Error(xmlError(varElem, `<${elem.name}> ${attrName} attribute is required`))\n }\n return s\n}\n\nfunction parseOptionalAttr(elem: XmlElement, attrName: string): string {\n const s = elem.attributes && elem.attributes[attrName]\n return s?.trim()\n}\n\nfunction parseFloatAttr(varElem: XmlElement, elem: XmlElement, attrName: string): number {\n const s = parseRequiredAttr(varElem, elem, attrName)\n const num = parseFloat(s)\n if (isNaN(num)) {\n throw new Error(xmlError(varElem, `Invalid number value '${s}' for <${elem.name}> ${attrName} attribute'`))\n }\n return num\n}\n\n/**\n * Parse XMILE conditional expressions recursively to handle nested IF-THEN-ELSE statements.\n *\n * This transforms XMILE syntax:\n * IF condition THEN trueExpr ELSE falseExpr\n * to Vensim syntax:\n * IF THEN ELSE(condition, trueExpr, falseExpr)\n *\n * Examples of supported nested structures:\n * - Simple: IF x > 0 THEN 1 ELSE 0\n * - Nested: IF x > 0 THEN IF y > 0 THEN 2 ELSE 1 ELSE 0\n * - Complex: IF a > 0 THEN IF b > 0 THEN IF c > 0 THEN 3 ELSE 2 ELSE 1 ELSE 0\n * - In function call: ABS(IF x > 0 THEN 1 ELSE 0) + 1\n */\nfunction convertConditionalExpressions(exprText: string): string {\n // XXX: This function implementation was generated by an LLM and is rather complex.\n // We probably could remove it if we had a new ANTLR grammar/parser for XMILE-style\n // expressions, including nested conditional expressions.\n\n // Trim whitespace and normalize newlines\n const normalizedText = exprText.trim().replace(/\\s+/g, ' ')\n\n // Find the first IF-THEN-ELSE pattern in the expression\n const ifMatch = normalizedText.match(/\\bIF\\s+(.+)$/i)\n if (!ifMatch) {\n return exprText\n }\n\n // Find the position of the IF keyword\n const ifIndex = normalizedText.search(/\\bIF\\s+/i)\n const beforeIf = normalizedText.substring(0, ifIndex)\n const afterIf = normalizedText.substring(ifIndex + 3).trim() // Skip \"IF \"\n\n // Parse the condition part (everything after IF until THEN)\n const thenMatch = afterIf.match(/^(.+?)\\s+THEN\\s+(.+)$/i)\n if (!thenMatch) {\n return exprText\n }\n\n const condition = thenMatch[1].trim()\n const afterThen = thenMatch[2]\n\n // Find the ELSE part by looking for the outermost ELSE that's not inside parentheses\n let elseIndex = -1\n let parenCount = 0\n let inQuotes = false\n let quoteChar = ''\n\n for (let i = 0; i < afterThen.length; i++) {\n const char = afterThen[i]\n\n // Handle quoted strings\n if ((char === '\"' || char === \"'\") && (i === 0 || afterThen[i - 1] !== '\\\\')) {\n if (!inQuotes) {\n inQuotes = true\n quoteChar = char\n } else if (char === quoteChar) {\n inQuotes = false\n quoteChar = ''\n }\n continue\n }\n\n if (inQuotes) {\n continue\n }\n\n // Handle parentheses for nested expressions\n if (char === '(') {\n parenCount++\n } else if (char === ')') {\n parenCount--\n }\n\n // Look for ELSE, but only when not inside parentheses or quoted strings\n if (parenCount === 0 && !inQuotes) {\n const elseMatch = afterThen.substring(i).match(/^ELSE\\s+(.+)$/i)\n if (elseMatch) {\n elseIndex = i\n break\n }\n }\n }\n\n if (elseIndex === -1) {\n return exprText\n }\n\n // Skip \"ELSE \"\n const trueExpr = afterThen.substring(0, elseIndex).trim()\n let falseExpr = afterThen.substring(elseIndex + 5).trim()\n\n // Find the end of the false expression by looking for the end of the conditional. The conditional\n // ends when we reach a closing parenthesis that brings us back to the original level.\n let endIndex = -1\n parenCount = 0\n inQuotes = false\n quoteChar = ''\n\n for (let i = 0; i < falseExpr.length; i++) {\n const char = falseExpr[i]\n\n // Handle quoted strings\n if ((char === '\"' || char === \"'\") && (i === 0 || falseExpr[i - 1] !== '\\\\')) {\n if (!inQuotes) {\n inQuotes = true\n quoteChar = char\n } else if (char === quoteChar) {\n inQuotes = false\n quoteChar = ''\n }\n continue\n }\n\n if (inQuotes) {\n continue\n }\n\n // Handle parentheses for nested expressions\n if (char === '(') {\n parenCount++\n } else if (char === ')') {\n if (parenCount === 0) {\n // This is the closing parenthesis that ends the conditional\n endIndex = i\n break\n }\n parenCount--\n }\n }\n\n if (endIndex !== -1) {\n falseExpr = falseExpr.substring(0, endIndex).trim()\n }\n\n // Recursively parse nested conditionals in the true and false expressions\n const convertedTrueExpr = convertConditionalExpressions(trueExpr)\n const convertedFalseExpr = convertConditionalExpressions(falseExpr)\n\n const convertedCondition = condition\n // Replace logical operators for Vensim compatibility\n .replace(/(?<!\".*?)\\b AND \\b(?!.*?\")/gi, ' :AND: ')\n .replace(/(?<!\".*?)\\b OR \\b(?!.*?\")/gi, ' :OR: ')\n .replace(/(?<!\".*?)\\b\\s?NOT \\b(?!.*?\")/gi, ' :NOT: ')\n // Remove outer parentheses from condition\n .replace(/^\\((.+)\\)$/, '$1')\n\n // Find any text after the conditional expression and calculate where the original conditional\n // expression ends in the normalized text\n const elseStartInAfterIf = afterIf.indexOf(' ELSE ') + 6\n const falseExprStartInAfterIf = elseStartInAfterIf\n const falseExprEndInAfterIf = falseExprStartInAfterIf + falseExpr.length\n\n const conditionalEndInNormalizedText = ifIndex + 3 + falseExprEndInAfterIf\n const afterConditional = normalizedText.substring(conditionalEndInNormalizedText).trim()\n\n return `${beforeIf}IF THEN ELSE(${convertedCondition}, ${convertedTrueExpr}, ${convertedFalseExpr})${afterConditional}`\n}\n"],"mappings":";AAGA,IAAM,iBAAiB,IAAI,OAAO,UAAU,GAAG;AAG/C,IAAM,eAAe,IAAI,OAAO,YAAY,GAAG;AAK/C,IAAM,iBAAiB,IAAI,OAAO,4BAA4B,GAAG;AAe1D,SAAS,YAAY,MAAM;AAChC,SACE,MACA,KAEG,KAAK,EAGL,QAAQ,gBAAgB,GAAG,EAI3B,QAAQ,cAAc,GAAG,EAEzB,QAAQ,gBAAgB,GAAG,EAE3B,YAAY;AAEnB;AAUO,SAAS,eAAe,MAAM;AACnC,QAAM,IAAI,KAAK,MAAM,0BAA0B;AAC/C,MAAI,CAAC,GAAG;AACN,UAAM,IAAI,MAAM,0BAA0B,IAAI,EAAE;AAAA,EAClD;AAEA,MAAI,KAAK,YAAY,EAAE,CAAC,CAAC;AACzB,MAAI,EAAE,CAAC,GAAG;AACR,UAAM,aAAa,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,OAAK,YAAY,CAAC,CAAC;AAC1D,UAAM,IAAI,WAAW,KAAK,GAAG,CAAC;AAAA,EAChC;AAEA,SAAO;AACT;AASO,SAAS,oBAAoB,MAAM;AACxC,SAAO,YAAY,IAAI,EAAE,YAAY;AACvC;;;AC5EA,SAAS,mBAAmB;AAOrB,SAAS,eAAe,MAAY,SAAS,GAAS;AAC3D,QAAM,SAAS,IAAI,OAAO,SAAS,CAAC;AACpC,QAAM,MAAM,CAAC,MAAc;AACzB,YAAQ,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE;AAAA,EAC7B;AAEA,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,UAAI,UAAU,KAAK,IAAI,EAAE;AACzB;AAAA,IAEF,KAAK;AACH,UAAI,WAAW,KAAK,IAAI,EAAE;AAC1B;AAAA,IAEF,KAAK;AACH,UAAI,YAAY,KAAK,IAAI,EAAE;AAC3B;AAAA,IAEF,KAAK;AACH,UAAI,QAAQ,gBAAgB,IAAI,CAAC,EAAE;AACnC;AAAA,IAEF,KAAK;AACH,UAAI,aAAa,KAAK,EAAE,EAAE;AAC1B,qBAAe,KAAK,MAAM,SAAS,CAAC;AACpC;AAAA,IAEF,KAAK;AACH,UAAI,cAAc,KAAK,EAAE,EAAE;AAC3B,qBAAe,KAAK,KAAK,SAAS,CAAC;AACnC,qBAAe,KAAK,KAAK,SAAS,CAAC;AACnC;AAAA,IAEF,KAAK;AACH,UAAI,QAAQ;AACZ,qBAAe,KAAK,MAAM,SAAS,CAAC;AACpC;AAAA,IAEF,KAAK;AAEH,UAAI,YAAY;AAChB;AAAA,IAEF,KAAK;AACH,UAAI,gBAAgB,eAAe,KAAK,MAAM,CAAC,EAAE;AACjD,qBAAe,KAAK,KAAK,SAAS,CAAC;AACnC;AAAA,IAEF,KAAK;AACH,UAAI,kBAAkB,KAAK,IAAI,EAAE;AACjC,WAAK,KAAK,QAAQ,SAAO,eAAe,KAAK,SAAS,CAAC,CAAC;AACxD;AAAA,IAEF;AACE,kBAAY,IAAI;AAAA,EACpB;AACF;AAuBO,SAAS,eAAe,MAAY,MAA2B;AACpE,MAAI,QAAgB,QAAgB,UAAkB;AACtD,MAAI,MAAM,YAAY,MAAM;AAC1B,aAAS;AACT,aAAS;AACT,eAAW;AACX,eAAW;AAAA,EACb,OAAO;AACL,aAAS;AACT,aAAS;AACT,eAAW;AACX,eAAW;AAAA,EACb;AAEA,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,KAAK;AAAA,IAEd,KAAK;AACH,aAAO,IAAI,KAAK,IAAI;AAAA,IAEtB,KAAK;AACH,aAAO,KAAK;AAAA,IAEd,KAAK;AACH,UAAI,MAAM,mBAAmB;AAC3B,eAAO,KAAK,kBAAkB,IAAI;AAAA,MACpC,OAAO;AACL,YAAI,KAAK,eAAe,SAAS,GAAG;AAClC,iBAAO,GAAG,KAAK,OAAO,IAAI,KAAK,cAAc,IAAI,SAAO,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC;AAAA,QACrF,OAAO;AACL,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IAEF,KAAK;AACH,UAAI,KAAK,OAAO,SAAS;AACvB,eAAO,GAAG,KAAK,EAAE,IAAI,eAAe,KAAK,MAAM,IAAI,CAAC;AAAA,MACtD,OAAO;AACL,eAAO,GAAG,KAAK,EAAE,GAAG,eAAe,KAAK,MAAM,IAAI,CAAC;AAAA,MACrD;AAAA,IAEF,KAAK,aAAa;AAChB,UAAI;AACJ,UAAI,MAAM,SAAS,MAAM;AACvB,gBAAQ,KAAK,IAAI;AAAA,UACf,KAAK;AACH,iBAAK;AACL;AAAA,UACF,KAAK;AACH,iBAAK;AACL;AAAA,UACF,KAAK;AACH,iBAAK;AACL;AAAA,UACF,KAAK;AACH,iBAAK;AACL;AAAA,UACF;AACE,iBAAK,KAAK;AACV;AAAA,QACJ;AAAA,MACF,OAAO;AACL,aAAK,KAAK;AAAA,MACZ;AACA,YAAM,MAAM,eAAe,KAAK,KAAK,IAAI;AACzC,YAAM,MAAM,eAAe,KAAK,KAAK,IAAI;AACzC,aAAO,GAAG,GAAG,GAAG,QAAQ,GAAG,EAAE,GAAG,QAAQ,GAAG,GAAG;AAAA,IAChD;AAAA,IAEA,KAAK;AACH,aAAO,GAAG,MAAM,GAAG,eAAe,KAAK,MAAM,IAAI,CAAC,GAAG,MAAM;AAAA,IAE7D,KAAK,cAAc;AACjB,YAAM,cAAc,CAAC,MAAwB;AAC3C,eAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAAA,MACzB;AACA,YAAM,SAAS,KAAK,OAAO,IAAI,WAAW,EAAE,KAAK,QAAQ;AACzD,UAAI,KAAK,OAAO;AACd,cAAM,MAAM,YAAY,KAAK,MAAM,GAAG;AACtC,cAAM,MAAM,YAAY,KAAK,MAAM,GAAG;AACtC,eAAO,GAAG,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,QAAQ,GAAG,MAAM,GAAG,MAAM;AAAA,MAC9D,OAAO;AACL,eAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;AAAA,MACpC;AAAA,IACF;AAAA,IAEA,KAAK,eAAe;AAClB,YAAM,SAAS,eAAe,KAAK,QAAQ,IAAI;AAC/C,YAAM,MAAM,eAAe,KAAK,KAAK,IAAI;AACzC,aAAO,GAAG,MAAM,GAAG,MAAM,GAAG,GAAG,GAAG,MAAM;AAAA,IAC1C;AAAA,IAEA,KAAK,iBAAiB;AACpB,YAAM,OAAO,KAAK,KAAK,IAAI,SAAO,eAAe,KAAK,IAAI,CAAC;AAC3D,aAAO,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,KAAK,KAAK,QAAQ,CAAC,GAAG,MAAM;AAAA,IAC/D;AAAA,IAEA;AACE,kBAAY,IAAI;AAAA,EACpB;AACF;AAKO,SAAS,gBAAgB,MAAY,SAAS,GAAS;AAC5D,QAAM,SAAS,IAAI,OAAO,SAAS,CAAC;AACpC,QAAM,MAAM,CAAC,MAAc;AACzB,YAAQ,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE;AAAA,EAC7B;AACA,MAAI,eAAe,IAAI,CAAC;AAC1B;AAIA,IAAM,QAAN,MAAY;AAAA,EAAZ;AACE,sBAAa;AACb,uBAAc;AACd,SAAS,gBAA0B,oBAAI,IAAI;AAC3C,SAAS,iBAA2B,oBAAI,IAAI;AAC5C,SAAS,eAAyB,oBAAI,IAAI;AAC1C,SAAS,eAAyB,oBAAI,IAAI;AAAA;AAC5C;AAEA,SAAS,UAAU,KAAe,KAAmB;AACnD,QAAM,QAAQ,IAAI,IAAI,GAAG,KAAK;AAC9B,MAAI,IAAI,KAAK,QAAQ,CAAC;AACxB;AAEA,SAAS,aAAa,MAAY,OAAc;AAC9C,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,YAAM;AACN;AAAA,IAEF,KAAK;AAEH;AAAA,IAEF,KAAK;AAEH;AAAA,IAEF,KAAK;AACH,YAAM;AACN;AAAA,IAEF,KAAK;AACH,mBAAa,KAAK,MAAM,KAAK;AAC7B,gBAAU,MAAM,eAAe,KAAK,EAAE;AACtC;AAAA,IAEF,KAAK;AACH,mBAAa,KAAK,KAAK,KAAK;AAC5B,mBAAa,KAAK,KAAK,KAAK;AAC5B,gBAAU,MAAM,gBAAgB,KAAK,EAAE;AACvC;AAAA,IAEF,KAAK;AACH,mBAAa,KAAK,MAAM,KAAK;AAC7B;AAAA,IAEF,KAAK;AAEH;AAAA,IAEF,KAAK;AACH,gBAAU,MAAM,cAAc,gBAAgB,KAAK,MAAM,CAAC;AAC1D,mBAAa,KAAK,KAAK,KAAK;AAC5B;AAAA,IAEF,KAAK;AACH,gBAAU,MAAM,cAAc,KAAK,IAAI;AACvC,WAAK,KAAK,QAAQ,SAAO,aAAa,KAAK,KAAK,CAAC;AACjD;AAAA,IAEF;AACE,kBAAY,IAAI;AAAA,EACpB;AACF;AAKO,SAAS,eAAe,OAAqB;AAClD,QAAM,QAAQ,IAAI,MAAM;AACxB,aAAW,QAAQ,OAAO;AACxB,iBAAa,MAAM,KAAK;AAAA,EAC1B;AAEA,WAAS,WAAW,OAAe,OAAe;AAChD,YAAQ,IAAI,GAAG,MAAM,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,KAAK,EAAE;AAAA,EACxD;AAEA,WAAS,YAAY,KAAuB;AAC1C,UAAM,UAAU,CAAC,GAAG,IAAI,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;AAC1E,QAAI,QAAQ;AACZ,eAAW,SAAS,SAAS;AAC3B,iBAAW,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AAC7B,eAAS,MAAM,CAAC;AAAA,IAClB;AACA,eAAW,OAAO,OAAO;AACzB,WAAO;AAAA,EACT;AAEA,MAAI,YAAY;AAEhB,aAAW,MAAM,YAAY,QAAQ;AACrC,eAAa,MAAM;AAEnB,aAAW,MAAM,aAAa,UAAU;AACxC,eAAa,MAAM;AAEnB,UAAQ,IAAI;AACZ,UAAQ,IAAI,WAAW;AACvB,eAAa,YAAY,MAAM,aAAa;AAE5C,UAAQ,IAAI;AACZ,UAAQ,IAAI,YAAY;AACxB,eAAa,YAAY,MAAM,cAAc;AAE7C,UAAQ,IAAI;AACZ,UAAQ,IAAI,gBAAgB;AAC5B,eAAa,YAAY,MAAM,YAAY;AAE3C,UAAQ,IAAI;AACZ,UAAQ,IAAI,cAAc;AAC1B,eAAa,YAAY,MAAM,YAAY;AAE3C,UAAQ,IAAI;AACZ,UAAQ,IAAI,OAAO;AACnB,aAAW,WAAW,OAAO;AAC/B;AAGA,SAAS,gBAAgB,QAA6B;AACpD,MAAI,OAAO,eAAe,SAAS,GAAG;AACpC,WAAO,GAAG,OAAO,KAAK,IAAI,OAAO,cAAc,IAAI,SAAO,IAAI,KAAK,EAAE,KAAK,GAAG,CAAC;AAAA,EAChF,OAAO;AACL,WAAO,OAAO;AAAA,EAChB;AACF;;;ACzUA,SAAS,eAAAA,oBAAmB;;;AC0CrB,SAAS,OAAO,cAA0C;AAC/D,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,YAAY,YAAY;AAAA,EACjC;AACF;AAkCO,SAAS,IAAI,OAAe,MAA8B;AAC/D,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,MAAM,QAAQ,MAAM,SAAS;AAAA,EAC/B;AACF;AAyBO,SAAS,QAAQ,IAAa,MAAyB;AAC5D,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,SAAS,KAAW,IAAc,KAAyB;AACzE,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,OAAO,MAAwB;AAC7C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,EACF;AACF;AAEO,SAAS,UAAU,QAAuB,OAAgC;AAC/E,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,WAAW,QAAqB,KAAuB;AACrE,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,KAAK,WAAyB,MAA4B;AACxE,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,MAAM,oBAAoB,MAAM;AAAA,IAChC;AAAA,EACF;AACF;;;AD/IO,SAAS,WAAW,MAAY,MAAgC;AACrE,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,UAAI,MAAM,kBAAkB,QAAW;AAGrC,cAAM,eAAe,KAAK,cAAc,IAAI;AAC5C,YAAI,cAAc;AAChB,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IAET,KAAK,YAAY;AAEf,YAAM,QAAQ,WAAW,KAAK,MAAM,IAAI;AACxC,cAAQ,KAAK,IAAI;AAAA,QACf,KAAK;AAEH,iBAAO;AAAA,QACT,KAAK;AACH,cAAI,MAAM,SAAS,UAAU;AAE3B,mBAAO,IAAI,CAAC,MAAM,KAAK;AAAA,UACzB,OAAO;AAEL,mBAAO,QAAQ,KAAK,KAAK;AAAA,UAC3B;AAAA,QACF,KAAK;AACH,cAAI,MAAM,SAAS,UAAU;AAI3B,mBAAO,IAAI,MAAM,UAAU,IAAI,IAAI,CAAC;AAAA,UACtC,OAAO;AAEL,mBAAO,QAAQ,SAAS,KAAK;AAAA,UAC/B;AAAA,QACF;AACE,UAAAC,aAAY,IAAI;AAAA,MACpB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,aAAa;AAGhB,YAAM,MAAM,WAAW,KAAK,KAAK,IAAI;AACrC,YAAM,MAAM,WAAW,KAAK,KAAK,IAAI;AACrC,UAAI,IAAI,SAAS,YAAY,IAAI,SAAS,UAAU;AAElD,gBAAQ,KAAK,IAAI;AAAA,UACf,KAAK;AACH,mBAAO,IAAI,IAAI,QAAQ,IAAI,KAAK;AAAA,UAClC,KAAK;AACH,mBAAO,IAAI,IAAI,QAAQ,IAAI,KAAK;AAAA,UAClC,KAAK;AACH,mBAAO,IAAI,IAAI,QAAQ,IAAI,KAAK;AAAA,UAClC,KAAK;AAEH,mBAAO,IAAI,IAAI,QAAQ,IAAI,KAAK;AAAA,UAClC,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,CAAC;AAAA,UAC3C,KAAK;AACH,mBAAO,IAAI,IAAI,UAAU,IAAI,QAAQ,IAAI,CAAC;AAAA,UAC5C,KAAK;AACH,mBAAO,IAAI,IAAI,UAAU,IAAI,QAAQ,IAAI,CAAC;AAAA,UAC5C,KAAK;AACH,mBAAO,IAAI,IAAI,QAAQ,IAAI,QAAQ,IAAI,CAAC;AAAA,UAC1C,KAAK;AACH,mBAAO,IAAI,IAAI,QAAQ,IAAI,QAAQ,IAAI,CAAC;AAAA,UAC1C,KAAK;AACH,mBAAO,IAAI,IAAI,SAAS,IAAI,QAAQ,IAAI,CAAC;AAAA,UAC3C,KAAK;AACH,mBAAO,IAAI,IAAI,SAAS,IAAI,QAAQ,IAAI,CAAC;AAAA,UAC3C,KAAK;AAEH,mBAAO,IAAI,IAAI,UAAU,KAAK,IAAI,UAAU,IAAI,IAAI,CAAC;AAAA,UACvD,KAAK;AAEH,mBAAO,IAAI,IAAI,UAAU,KAAK,IAAI,UAAU,IAAI,IAAI,CAAC;AAAA,UACvD;AACE,YAAAA,aAAY,IAAI;AAAA,QACpB;AAAA,MACF,WAAW,IAAI,SAAS,YAAY,IAAI,SAAS,UAAU;AAEzD,cAAM,SAAiB,IAAI,SAAS,WAAW,IAAI,QAAQ;AAC3D,cAAM,SAAiB,IAAI,SAAS,WAAW,IAAI,QAAQ;AAC3D,cAAM,WAAW,WAAW,SAAY,SAAS;AACjD,cAAM,YAAY,WAAW,SAAY,MAAM;AAC/C,gBAAQ,KAAK,IAAI;AAAA,UACf,KAAK,KAAK;AACR,gBAAI,aAAa,GAAG;AAGlB,qBAAO;AAAA,YACT,WACE,UAAU,SAAS,eACnB,UAAU,OAAO,QAChB,UAAU,IAAI,SAAS,YAAY,UAAU,IAAI,SAAS,WAC3D;AAGA,oBAAM,kBAA0B,UAAU,IAAI,SAAS,WAAW,UAAU,IAAI,QAAQ;AACxF,oBAAM,kBAA0B,UAAU,IAAI,SAAS,WAAW,UAAU,IAAI,QAAQ;AACxF,oBAAM,sBAAsB,oBAAoB,SAAY,kBAAkB;AAC9E,oBAAM,qBAAqB,oBAAoB,SAAY,UAAU,MAAM,UAAU;AACrF,qBAAO,SAAS,IAAI,WAAW,mBAAmB,GAAG,KAAK,kBAAkB;AAAA,YAC9E;AACA;AAAA,UACF;AAAA,UAEA,KAAK,KAAK;AACR,gBAAI,WAAW,GAAG;AAEhB,qBAAO;AAAA,YACT,WAAW,WAAW,GAAG;AAGvB,qBAAO,QAAQ,KAAK,GAAG;AAAA,YACzB;AACA;AAAA,UACF;AAAA,UAEA,KAAK,KAAK;AACR,gBAAI,aAAa,GAAG;AAGlB,qBAAO,IAAI,CAAC;AAAA,YACd,WAAW,aAAa,GAAG;AAGzB,qBAAO;AAAA,YACT,WACE,UAAU,SAAS,eACnB,UAAU,OAAO,QAChB,UAAU,IAAI,SAAS,YAAY,UAAU,IAAI,SAAS,WAC3D;AAGA,oBAAM,kBAA0B,UAAU,IAAI,SAAS,WAAW,UAAU,IAAI,QAAQ;AACxF,oBAAM,kBAA0B,UAAU,IAAI,SAAS,WAAW,UAAU,IAAI,QAAQ;AACxF,oBAAM,sBAAsB,oBAAoB,SAAY,kBAAkB;AAC9E,oBAAM,qBAAqB,oBAAoB,SAAY,UAAU,MAAM,UAAU;AACrF,qBAAO,SAAS,IAAI,WAAW,mBAAmB,GAAG,KAAK,kBAAkB;AAAA,YAC9E;AACA;AAAA,UACF;AAAA,UAEA,KAAK,KAAK;AACR,gBAAI,WAAW,GAAG;AAEhB,qBAAO;AAAA,YACT;AACA;AAAA,UACF;AAAA,UAEA,KAAK,KAAK;AACR,gBAAI,WAAW,GAAG;AAEhB,qBAAO,IAAI,CAAC;AAAA,YACd,WAAW,WAAW,GAAG;AAEvB,qBAAO;AAAA,YACT;AACA;AAAA,UACF;AAAA,UAEA,KAAK;AAQH,mBAAO,aAAa,IAAI,IAAI,CAAC,IAAI;AAAA,UAEnC,KAAK;AAQH,mBAAO,aAAa,IAAI,IAAI,CAAC,IAAI;AAAA,UAEnC;AACE;AAAA,QACJ;AAAA,MACF;AAGA,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,IAAI,KAAK;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,QAAQ,WAAW,KAAK,MAAM,IAAI;AACxC,aAAO,YAAY,KAAK;AAAA,IAC1B;AAAA,IAEA,KAAK;AAEH,aAAO;AAAA,IAET,KAAK;AAEH,aAAO;AAAA,IAET,KAAK,iBAAiB;AAEpB,UAAI,KAAK,SAAS,iBAAiB;AAEjC,cAAM,gBAAgB,WAAW,KAAK,KAAK,CAAC,GAAG,IAAI;AACnD,YAAI,cAAc,SAAS,UAAU;AAInC,gBAAM,aAAa,cAAc,UAAU,IAAI,WAAW,KAAK,KAAK,CAAC,GAAG,IAAI,IAAI,WAAW,KAAK,KAAK,CAAC,GAAG,IAAI;AAS7G,iBAAO,YAAY,UAAU;AAAA,QAC/B;AAAA,MACF;AAGA,YAAM,cAAc,KAAK,KAAK,IAAI,SAAO,WAAW,KAAK,IAAI,CAAC;AAC9D,YAAM,WAAW,YAAY,MAAM,SAAO,IAAI,SAAS,QAAQ;AAC/D,UAAI,UAAU;AACZ,cAAM,WAAW,CAAC,UAAkB;AAClC,gBAAMC,OAAM,YAAY,KAAK;AAC7B,iBAAOA,KAAI;AAAA,QACb;AACA,gBAAQ,KAAK,MAAM;AAAA,UACjB,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC;AAAA,UAClC,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC;AAAA,UAClC,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC;AAAA,UAClC,KAAK;AACH,mBAAO,YAAY,CAAC;AAAA,UACtB,KAAK;AACH,mBAAO,IAAI,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC;AAAA,UACpC,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC;AAAA,UAClC,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AAAA,UAC/C,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AAAA,UAC/C,KAAK;AACH,mBAAO,IAAI,SAAS,CAAC,IAAI,SAAS,CAAC,CAAC;AAAA,UACtC,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AAAA,UAC/C,KAAK;AACH,mBAAO,IAAI,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC;AAAA,UAClC,KAAK;AACH,mBAAO,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC;AAAA,UACnC;AACE;AAAA,QACJ;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IAEA;AACE,MAAAD,aAAY,IAAI;AAAA,EACpB;AACF;AAaO,SAAS,mBAAmB,MAAY,MAAgC;AAC7E,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAIH,aAAO;AAAA,IAET,KAAK,YAAY;AACf,YAAM,QAAQ,mBAAmB,KAAK,MAAM,IAAI;AAChD,aAAO,QAAQ,KAAK,IAAI,KAAK;AAAA,IAC/B;AAAA,IAEA,KAAK,aAAa;AAChB,YAAM,MAAM,mBAAmB,KAAK,KAAK,IAAI;AAC7C,YAAM,MAAM,mBAAmB,KAAK,KAAK,IAAI;AAC7C,aAAO,SAAS,KAAK,KAAK,IAAI,GAAG;AAAA,IACnC;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,QAAQ,mBAAmB,KAAK,MAAM,IAAI;AAChD,aAAO,YAAY,KAAK;AAAA,IAC1B;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET,KAAK,eAAe;AAClB,YAAM,MAAM,mBAAmB,KAAK,KAAK,IAAI;AAC7C,aAAO,WAAW,KAAK,QAAQ,GAAG;AAAA,IACpC;AAAA,IAEA,KAAK,iBAAiB;AACpB,UAAI,KAAK,SAAS,iBAAiB;AAIjC,cAAM,gBAAgB,WAAW,KAAK,KAAK,CAAC,GAAG,IAAI;AACnD,YAAI,cAAc,SAAS,UAAU;AAInC,gBAAM,aACJ,cAAc,UAAU,IAAI,mBAAmB,KAAK,KAAK,CAAC,GAAG,IAAI,IAAI,mBAAmB,KAAK,KAAK,CAAC,GAAG,IAAI;AAS5G,iBAAO,YAAY,UAAU;AAAA,QAC/B;AAAA,MACF;AAGA,YAAM,cAAc,KAAK,KAAK,IAAI,SAAO,mBAAmB,KAAK,IAAI,CAAC;AACtE,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IAEA;AACE,MAAAA,aAAY,IAAI;AAAA,EACpB;AACF;AAUA,SAAS,YAAY,OAAmB;AACtC,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAGH,aAAO;AAAA,IACT;AAEE,aAAO,OAAO,KAAK;AAAA,EACvB;AACF;;;AEjaA,SAAS,eAAAE,cAAa,oBAAoB;;;ACA1C,OAAO,YAAY;AACnB,SAAS,YAAY,mBAAmB;AAUjC,SAAS,kBAAkB,OAAO;AAIvC,QAAM,gBAAgB,IAAI,oBAAoB,KAAK;AAGnD,MAAI,QAAQ,IAAI,OAAO,YAAY,KAAK;AACxC,MAAI,QAAQ,IAAI,WAAW,KAAK;AAChC,QAAM,qBAAqB;AAC3B,QAAM,iBAAiB,aAAa;AAIpC,MAAI,SAAS,IAAI,OAAO,kBAAkB,KAAK;AAC/C,MAAI,SAAS,IAAI,YAAY,MAAM;AACnC,SAAO,kBAAkB;AACzB,SAAO,qBAAqB;AAC5B,SAAO,iBAAiB,aAAa;AAErC,SAAO;AACT;AAEA,IAAM,sBAAN,cAAkC,OAAO,MAAM,cAAc;AAAA,EAC3D,YAAY,OAAO;AACjB,UAAM;AACN,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,YAAY,aAAa,kBAAkB,MAAM,QAAQ,KAAe;AACtE,UAAM,IAAI,MAAM,KAAK;AAAA,MACnB,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AD3CO,IAAM,uBAAN,cAAmC,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrD,YAAY,cAAuC;AACjD,UAAM;AACN,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASW,MAAM,oBAAoD;AACnE,UAAM,SAAS,kBAAkB,kBAAkB;AACnD,UAAM,oBAAoB,OAAO,eAAe;AAChD,WAAO,KAAK,oBAAoB,iBAAiB;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUW,oBAAoB,KAAoD;AACjF,SAAK,iBAAiB,CAAC;AACvB,SAAK,oBAAoB,CAAC;AAK1B,UAAM,UAAU;AAIhB,UAAM,MAAM,IAAI,GAAG;AACnB,QAAI,IAAI,WAAW,GAAG;AAEpB,YAAM,UAAU,IAAI,CAAC,EAAE,QAAQ;AAC/B,YAAM,QAAQ,YAAY,OAAO;AAGjC,YAAM,oBAAoB,GAAG;AAO7B,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,eAAe,KAAK,eAAe,IAAI,aAAW;AAChD,iBAAO;AAAA,YACL;AAAA,YACA,OAAO,YAAY,OAAO;AAAA,UAC5B;AAAA,QACF,CAAC;AAAA,QACD,mBAAmB,KAAK;AAAA,QACxB;AAAA,MACF;AAAA,IACF,WAAW,IAAI,WAAW,GAAG;AAE3B,YAAM,UAAU,IAAI,CAAC,EAAE,QAAQ;AAC/B,YAAM,QAAQ,YAAY,OAAO;AACjC,YAAM,aAAa,IAAI,CAAC,EAAE,QAAQ;AAClC,YAAM,WAAW,YAAY,UAAU;AACvC,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,CAAC;AAAA,QAChB,mBAAmB,CAAC;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,sBAAsB,KAAK;AAGzB,eAAW,gBAAgB,IAAI,UAAU;AACvC,UAAI,aAAa,QAAQ,SAASC,aAAY,IAAI;AAChD,aAAK,eAAe,KAAK,aAAa,QAAQ,CAAC;AAAA,MACjD,WAAW,aAAa,cAAcA,aAAY,wBAAwB;AACxE,aAAK,uBAAuB,YAAY;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,uBAAuB,KAAK;AAI1B,UAAM,KAAK;AACX,UAAM,MAAM,IAAI,GAAG,EAAE,IAAI,QAAM,GAAG,QAAQ,CAAC;AAC3C,UAAM,UAAU,IAAI,IAAI,QAAM,GAAG,KAAK,EAAE,CAAC;AACzC,QAAI,QAAQ,CAAC,EAAE,CAAC,MAAM,QAAQ,CAAC,EAAE,CAAC,GAAG;AACnC,YAAM,SAAS,QAAQ,CAAC,EAAE,CAAC;AAC3B,YAAM,QAAQ,SAAS,QAAQ,CAAC,EAAE,CAAC,CAAC;AACpC,YAAM,MAAM,SAAS,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClC,eAAS,IAAI,OAAO,KAAK,KAAK,KAAK;AACjC,aAAK,eAAe,KAAK,SAAS,CAAC;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,sBAAsB,KAAK;AAEzB,UAAM,YAAY,IAAI,GAAG,EAAE,QAAQ;AAGnC,SAAK,uBAAuB,CAAC;AAG7B,UAAM,sBAAsB,GAAG;AAG/B,SAAK,kBAAkB,KAAK;AAAA,MAC1B;AAAA,MACA,SAAS,YAAY,SAAS;AAAA,MAC9B,eAAe,KAAK,qBAAqB,IAAI,aAAW;AACtD,eAAO;AAAA,UACL;AAAA,UACA,OAAO,YAAY,OAAO;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,mBAAmB,KAAK;AAGtB,SAAK,uBAAuB,IAAI,GAAG,EAAE,IAAI,QAAM,GAAG,QAAQ,CAAC;AAAA,EAC7D;AAAA,EAEA,UAAU,KAAK;AAEb,UAAM,SAAS,IAAI,GAAG,EAAE,QAAQ;AAChC,UAAM,OAAO,oBAAoB,MAAM;AACvC,QAAI,SAAS,yBAAyB;AACpC,YAAM,UAAU,GAAG;AAAA,IACrB,OAAO;AACL,YAAM,IAAI;AAAA,QACR,4FAA4F,MAAM;AAAA,MACpG;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAc,KAAK;AAIjB,UAAM,OAAO,IAAI,KAAK,EAAE,IAAI,UAAQ;AAClC,YAAM,WAAW,KAAK,QAAQ;AAC9B,aAAO,SAAS,WAAW,KAAK,EAAE;AAAA,IACpC,CAAC;AAGD,UAAM,WAAW,KAAK,CAAC;AACvB,UAAM,iBAAiB,KAAK,CAAC;AAC7B,UAAM,YAAY,KAAK,CAAC;AACxB,UAAM,WAAW,KAAK,CAAC;AACvB,UAAM,SAAS,KAAK,CAAC;AACrB,SAAK,iBACH,KAAK,cAAc,oBAAoB,UAAU,gBAAgB,WAAW,UAAU,MAAM,KAAK,CAAC;AAAA,EACtG;AACF;;;AE7KO,SAAS,0BAA0B,OAAe,SAA4C;AAEnG,QAAM,kBAAkB,IAAI,qBAAqB,OAAO;AACxD,SAAO,gBAAgB,MAAM,KAAK;AACpC;;;AChBA,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AAMlC,IAAM,aAAN,cAAyBC,cAAa;AAAA,EAC3C,cAAc;AACZ,UAAM;AAGN,SAAK,YAAY,CAAC;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASW,MAAM,UAAkC;AACjD,UAAM,SAAS,kBAAkB,QAAQ;AACzC,UAAM,UAAU,OAAO,KAAK;AAC5B,WAAO,KAAK,UAAU,OAAO;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUW,UAAU,KAAkC;AACrD,QAAI,OAAO,IAAI;AACf,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,KAAK;AACd,UAAM,OAAO,IAAI,MAAM,EAAE,QAAQ;AACjC,QAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,GAAG;AAE9C,WAAK,OAAO;AAAA,QACV,MAAM;AAAA,QACN,MAAM,KAAK,OAAO,GAAG,KAAK,SAAS,CAAC;AAAA,MACtC;AAAA,IACF,OAAO;AAEL,YAAM,QAAQ,WAAW,IAAI;AAC7B,WAAK,OAAO;AAAA,QACV,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,KAAK;AAChB,UAAM,OAAO,IAAI,QAAQ,EAAE,QAAQ;AACnC,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,KAAK;AAEb,UAAM,eAAe,IAAI,GAAG,EAAE,QAAQ;AACtC,UAAM,OAAO,oBAAoB,YAAY;AAC7C,SAAK,UAAU,KAAK,EAAE,IAAI,MAAM,MAAM,CAAC,EAAE,CAAC;AAC1C,UAAM,UAAU,GAAG;AACnB,UAAM,WAAW,KAAK,UAAU,IAAI;AACpC,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,SAAS;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,cAAc,KAAK;AACjB,UAAM,QAAQ,IAAI,KAAK;AACvB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AAErC,YAAM,CAAC,EAAE,OAAO,IAAI;AACpB,YAAM,IAAI,KAAK,UAAU;AACzB,UAAI,IAAI,GAAG;AACT,aAAK,UAAU,IAAI,CAAC,EAAE,KAAK,KAAK,KAAK,IAAI;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAS,KAAK;AAEZ,UAAM,gBAAgB,IAAI,GAAG,EAAE,QAAQ,EAAE,KAAK;AAC9C,UAAM,QAAQ,YAAY,aAAa;AAGvC,SAAK,aAAa;AAClB,UAAM,SAAS,GAAG;AAClB,UAAM,iBAAiB,KAAK;AAC5B,UAAM,gBAAgB,gBAAgB,IAAI,UAAQ;AAChD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,YAAY,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AACD,SAAK,aAAa;AAElB,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBAAmB,KAAK;AAEtB,SAAK,aAAa,IAAI,GAAG,EAAE,IAAI,QAAM,GAAG,QAAQ,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,aAAa;AACpB,UAAM,QAAQ,YAAY,KAAK;AAC/B,QAAI,MAAM,UAAU,GAAG;AACrB,aAAO,CAAC,WAAW,MAAM,CAAC,EAAE,QAAQ,CAAC,GAAG,WAAW,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,iBAAiB,KAAK;AACpB,SAAK,cAAc,IAAI,YAAY,EAAE,IAAI,OAAK,KAAK,SAAS,CAAC,CAAC;AAC9D,UAAM,iBAAiB,GAAG;AAAA,EAC5B;AAAA,EAEA,qBAAqB,KAAK;AACxB,SAAK,eAAe,IAAI,YAAY,EAAE,IAAI,OAAK,KAAK,SAAS,CAAC,CAAC;AAC/D,UAAM,qBAAqB,GAAG;AAAA,EAChC;AAAA,EAEA,eAAe,KAAK;AAClB,UAAM,eAAe,GAAG;AACxB,QAAI;AACJ,QAAI,KAAK,eAAe,KAAK,YAAY,WAAW,GAAG;AACrD,cAAQ;AAAA,QACN,KAAK,KAAK,YAAY,CAAC;AAAA,QACvB,KAAK,KAAK,YAAY,CAAC;AAAA,MACzB;AAAA,IACF;AACA,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,KAAK;AAAA,IACf;AACA,SAAK,cAAc;AACnB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,gBAAgB,KAAK;AAEnB,UAAM,gBAAgB,IAAI,GAAG,EAAE,QAAQ;AACvC,UAAM,cAAc,YAAY,aAAa;AAG7C,QAAI,IAAI,cAAc,GAAG;AACvB,UAAI,cAAc,EAAE,OAAO,IAAI;AAAA,IACjC;AACA,UAAM,iBAAiB,KAAK;AAC5B,UAAM,gBAAgB,gBAAgB,IAAI,UAAQ;AAChD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,YAAY,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AACD,SAAK,aAAa;AAElB,UAAM,eAAe;AAAA,MACnB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO;AAAA,MACP;AAAA,IACF;AAGA,QAAI,KAAK,EAAE,OAAO,IAAI;AACtB,UAAM,YAAY,KAAK;AAEvB,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,KAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,IAAkB;AAC9B,UAAM,QAAQ,KAAK;AACnB,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,cAAc,KAAK;AACjB,UAAM,cAAc,GAAG;AACvB,SAAK,cAAc,GAAG;AAAA,EACxB;AAAA,EAEA,cAAc,KAAK;AACjB,UAAM,cAAc,GAAG;AACvB,SAAK,cAAc,GAAG;AAAA,EACxB;AAAA,EAEA,SAAS,KAAK;AACZ,UAAM,SAAS,GAAG;AAClB,SAAK,cAAc,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,KAAK,IAAmB;AACtC,QAAI,KAAK,CAAC,EAAE,OAAO,IAAI;AACvB,UAAM,MAAM,KAAK;AACjB,QAAI,KAAK,CAAC,EAAE,OAAO,IAAI;AACvB,UAAM,MAAM,KAAK;AACjB,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,WAAW,KAAK;AACd,SAAK,gBAAgB,KAAK,GAAG;AAAA,EAC/B;AAAA,EAEA,YAAY,KAAK;AACf,SAAK,gBAAgB,KAAK,IAAI,GAAG,SAASC,YAAW,OAAO,MAAM,GAAG;AAAA,EACvE;AAAA,EAEA,YAAY,KAAK;AACf,SAAK,gBAAgB,KAAK,IAAI,GAAG,SAASA,YAAW,OAAO,MAAM,GAAG;AAAA,EACvE;AAAA,EAEA,gBAAgB,KAAK;AACnB,QAAI;AACJ,YAAQ,IAAI,GAAG,MAAM;AAAA,MACnB,KAAKA,YAAW;AACd,aAAK;AACL;AAAA,MACF,KAAKA,YAAW;AACd,aAAK;AACL;AAAA,MACF,KAAKA,YAAW;AACd,aAAK;AACL;AAAA,MACF,KAAKA,YAAW;AACd,aAAK;AACL;AAAA,MACF;AACE,cAAM,IAAI,MAAM,mCAAmC,EAAE,GAAG;AAAA,IAC5D;AACA,SAAK,gBAAgB,KAAK,EAAE;AAAA,EAC9B;AAAA,EAEA,cAAc,KAAK;AACjB,SAAK,gBAAgB,KAAK,IAAI,GAAG,SAASA,YAAW,QAAQ,MAAM,IAAI;AAAA,EACzE;AAAA,EAEA,SAAS,KAAK;AACZ,SAAK,gBAAgB,KAAK,OAAO;AAAA,EACnC;AAAA,EAEA,QAAQ,KAAK;AACX,SAAK,gBAAgB,KAAK,MAAM;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,KAAK;AACf,UAAM,YAAY,GAAG;AAErB,UAAM,QAAQ,KAAK;AACnB,SAAK,OAAO;AAAA,MACV,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACF;;;ACjTO,SAAS,gBAAgB,OAAqB;AAEnD,QAAM,aAAa,IAAI,WAAW;AAClC,SAAO,WAAW,MAAM,KAAK;AAC/B;;;ACbA,SAAS,gBAAAC,qBAAoB;AAOtB,IAAM,iBAAN,cAA6BC,cAAa;AAAA,EAC/C,cAAc;AACZ,UAAM;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASW,MAAM,cAA0C;AACzD,UAAM,SAAS,kBAAkB,YAAY;AAC7C,UAAM,cAAc,OAAO,SAAS;AACpC,WAAO,KAAK,cAAc,WAAW;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUW,cAAc,KAA0C;AACjE,SAAK,cAAc;AACnB,SAAK,YAAY;AAEjB,QAAI,IAAI,EAAE,OAAO,IAAI;AAErB,QAAI;AACJ,UAAM,UAAU,IAAI,KAAK;AACzB,QAAI,SAAS;AACX,YAAM,aAAa,IAAI,WAAW;AAClC,YAAM,OAAO,WAAW,UAAU,OAAO;AACzC,oBAAc;AAAA,QACZ,MAAM;AAAA,QACN;AAAA,MACF;AAAA,IACF,WAAW,IAAI,UAAU,GAAG;AAC1B,UAAI,UAAU,EAAE,OAAO,IAAI;AAC3B,oBAAc;AAAA,QACZ,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,QAChB,MAAM,KAAK;AAAA,MACb;AAAA,IACF,WAAW,IAAI,OAAO,GAAG;AACvB,UAAI,OAAO,EAAE,OAAO,IAAI;AACxB,oBAAc;AAAA,QACZ,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,MAClB;AAAA,IACF,OAAO;AACL,oBAAc;AAAA,QACZ,MAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,KAAK,aAAa;AACpB,WAAK,WAAW;AAAA,QACd,KAAK,KAAK;AAAA,QACV,KAAK;AAAA;AAAA;AAAA;AAAA,QAIL,OAAO;AAAA,QACP,SAAS;AAAA,MACX;AAAA,IACF;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,mBAAmB,KAAK;AAEtB,QAAI,KAAK,eAAe,QAAW;AAEjC,WAAK,aAAa,IAAI,GAAG,EAAE,IAAI,QAAM,GAAG,QAAQ,CAAC;AAAA,IACnD,OAAO;AAIL,UAAI,KAAK,wBAAwB,QAAW;AAC1C,aAAK,sBAAsB,CAAC;AAAA,MAC9B;AACA,WAAK,oBAAoB,KAAK,IAAI,GAAG,EAAE,IAAI,QAAM,GAAG,QAAQ,CAAC,CAAC;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,SAAS,KAAK;AAEZ,UAAM,aAAa,IAAI,GAAG,EAAE,QAAQ;AACpC,UAAM,WAAW,YAAY,UAAU;AAGvC,UAAM,SAAS,GAAG;AAClB,UAAM,iBAAiB,KAAK;AAC5B,UAAM,gBAAgB,gBAAgB,IAAI,UAAQ;AAChD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,YAAY,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AAGD,UAAM,sBAAsB,KAAK;AACjC,UAAM,yBAAyB,qBAAqB,IAAI,kBAAgB;AACtE,aAAO,aAAa,IAAI,UAAQ;AAC9B,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,YAAY,IAAI;AAAA,QACzB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AACD,SAAK,aAAa;AAClB,SAAK,mBAAmB;AAExB,SAAK,cAAc;AAAA,MACjB,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO;AAAA,QACP;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,KAAK;AAKlB,SAAK,YAAY,IAAI,KAAK,EAAE,IAAI,UAAQ;AACtC,YAAM,OAAO,KAAK,QAAQ;AAC1B,YAAM,QAAQ,WAAW,IAAI;AAC7B,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AACD,SAAK,gBAAgB,IAAI,QAAQ;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,aAAa;AACpB,UAAM,QAAQ,YAAY,KAAK;AAC/B,QAAI,MAAM,UAAU,GAAG;AACrB,aAAO,CAAC,WAAW,MAAM,CAAC,EAAE,QAAQ,CAAC,GAAG,WAAW,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,YAAY,KAAK;AACf,SAAK,cAAc;AACnB,SAAK,eAAe;AAEpB,QAAI,IAAI,YAAY,GAAG;AACrB,UAAI,YAAY,EAAE,OAAO,IAAI;AAAA,IAC/B;AACA,QAAI,IAAI,gBAAgB,GAAG;AACzB,UAAI,gBAAgB,EAAE,OAAO,IAAI;AAAA,IACnC;AAEA,QAAI;AACJ,QAAI,KAAK,eAAe,KAAK,YAAY,WAAW,GAAG;AACrD,cAAQ;AAAA,QACN,KAAK,KAAK,YAAY,CAAC;AAAA,QACvB,KAAK,KAAK,YAAY,CAAC;AAAA,MACzB;AAAA,IACF;AACA,SAAK,YAAY;AAAA,MACf,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA,EAEA,iBAAiB,KAAK;AACpB,SAAK,cAAc,IAAI,YAAY,EAAE,IAAI,OAAK,KAAK,SAAS,CAAC,CAAC;AAC9D,UAAM,iBAAiB,GAAG;AAAA,EAC5B;AAAA,EAEA,qBAAqB,KAAK;AACxB,SAAK,eAAe,IAAI,YAAY,EAAE,IAAI,OAAK,KAAK,SAAS,CAAC,CAAC;AAC/D,UAAM,qBAAqB,GAAG;AAAA,EAChC;AACF;;;AClMO,SAAS,oBAAoB,OAAyB;AAE3D,QAAM,iBAAiB,IAAI,eAAe;AAC1C,SAAO,eAAe,MAAM,KAAK;AACnC;;;ACbA,OAAO,WAAW;AAyGX,SAAS,sBAAsB,OAAe,SAA+D;AAElH,QAAM,cAAc,SAAS;AAC7B,WAAS,aAAa,MAAuB;AAE3C,QAAI,KAAK,SAAS,cAAc,GAAG;AACjC,aAAO;AAAA,IACT;AAGA,QAAI,aAAa;AACf,iBAAW,OAAO,aAAa;AAC7B,YAAI,KAAK,SAAS,GAAG,GAAG;AACtB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAGA,WAAO;AAAA,EACT;AAKA,QAAM,eAAe,aAAa,KAAK;AACvC,UAAQ,aAAa;AAIrB,QAAM,UAAU,UAAU,KAAK;AAG/B,QAAM,aAA0B,CAAC;AACjC,QAAM,gBAA0B,CAAC;AACjC,aAAW,UAAU,SAAS;AAG5B,QAAI,aAAa,OAAO,IAAI,GAAG;AAC7B,oBAAc,KAAK,OAAO,KAAK,KAAK,IAAI,GAAG;AAC3C;AAAA,IACF;AAGA,UAAM,YAAY,WAAW,MAAM;AACnC,QAAI,WAAW;AACb,iBAAW,KAAK,SAAS;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,eAAe,aAAa;AAAA,IAC5B;AAAA,EACF;AACF;AAQA,SAAS,UAAU,OAAyB;AAK1C,QAAM,WAAW,MAAM,OAAO,EAAE,WAAW,KAAK,QAAQ,CAAC,GAAG,GAAG,MAAM,MAAM,KAAK,CAAC;AAIjF,QAAM,UAAU,CAAC;AACjB,MAAI,UAAU;AACd,MAAI;AACJ,WAAS,WAAW,UAAU;AAC5B,QAAI,YAAY,GAAG;AAEjB,gBAAU,QAAQ,QAAQ,WAAW,EAAE;AAAA,IACzC;AAEA,QAAI,QAAQ,SAAS,iBAAiB,GAAG;AAEvC;AAAA,IACF;AAGA,UAAM,QAAQ,QAAQ,MAAM,aAAa;AAIzC,UAAM,oBAAoB,MAAM,CAAC,GAAG,MAAM,cAAc;AACxD,eAAW,mBAAmB,UAAU;AAGxC,QAAI,QAAQ,SAAS,0DAA0D,GAAG;AAEhF,YAAM,aAAa,WAAW,OAAO,EAAE,OAAO,OAAK,EAAE,KAAK,EAAE,SAAS,CAAC;AACtE,qBAAe;AACf,UAAI,WAAW,SAAS,GAAG;AACzB,cAAM,gBAAgB,WAAW,CAAC;AAClC,cAAM,iBAAiB,cAAc,MAAM,aAAa;AACxD,YAAI,gBAAgB;AAClB,yBAAe,eAAe,CAAC;AAAA,QACjC;AAAA,MACF;AAAA,IACF,OAAO;AAEL,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAGA,UAAM,oBAAoB,MAAM,CAAC,GAAG,MAAM,cAAc;AACxD,eAAW,mBAAmB,UAAU;AAAA,EAC1C;AAEA,SAAO;AACT;AAKA,SAAS,WAAW,OAAyB;AAE3C,SAAO,MAAM,MAAM,YAAY;AACjC;AASA,SAAS,oBAAoB,OAAe,KAAuB;AACjE,SAAO,MAAM,OAAO,EAAE,WAAW,KAAK,QAAQ,CAAC,GAAG,EAAE,CAAC;AACvD;AAKA,SAAS,mBAAmB,OAAuB;AACjD,QAAM,aAAa,WAAW,KAAK;AAEnC,MAAI,SAAS;AACb,MAAI,WAAW;AACf,WAAS,QAAQ,YAAY;AAE3B,QAAI,aAAa,IAAI;AACnB,aAAO,WAAW,KAAK,KAAK;AAC5B,iBAAW;AAAA,IACb;AACA,UAAM,eAAe,KAAK,MAAM,QAAQ;AACxC,QAAI,cAAc;AAEhB,iBAAW,KAAK,OAAO,GAAG,aAAa,KAAK,EAAE,QAAQ,QAAQ,GAAG;AAAA,IACnE,OAAO;AAEL,gBAAU,OAAO;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;AAUA,SAAS,wBAAwB,KAAa,MAAc,OAAe,QAAwB;AACjG,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,QAAM,IAAI,IAAI;AACd,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,IAAI,OAAO,CAAC,MAAM,MAAM;AAC1B,UAAI,UAAU,GAAG;AACf,kBAAU,IAAI,UAAU,OAAO,CAAC;AAAA,MAClC;AACA;AAAA,IACF,WAAW,IAAI,OAAO,CAAC,MAAM,SAAS,QAAQ,GAAG;AAC/C;AACA,UAAI,UAAU,GAAG;AACf,kBAAU;AACV,gBAAQ,IAAI;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACA,MAAI,QAAQ,GAAG;AACb,cAAU,IAAI,UAAU,KAAK;AAAA,EAC/B;AACA,SAAO;AACT;AAMA,SAAS,iBAAiB,OAAuB;AAC/C,SAAO,MAAM,QAAQ,UAAU,GAAG,EAAE,KAAK;AAC3C;AAGA,IAAMC,gBAAe,IAAI,OAAO,YAAY,GAAG;AAM/C,SAAS,UAAU,KAA4D;AAK7E,MAAI,MAAM;AAGV,QAAM,IAAI,QAAQ,kBAAkB,EAAE;AAEtC,MAAI;AACJ,MAAI,IAAI,SAAS,GAAG,GAAG;AAErB,WAAO;AACP,UAAM,IAAI,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK;AAAA,EAC/B,WAAW,IAAI,SAAS,GAAG,GAAG;AAE5B,WAAO;AACP,UAAM,IAAI,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK;AAAA,EAC/B,OAAO;AAEL,WAAO;AAAA,EACT;AAGA,QAAM,oBAAoB,KAAK,GAAG,EAAE,CAAC;AAGrC,QAAM,IAAI,QAAQ,MAAM,EAAE;AAG1B,QAAM,IAAI,KAAK;AAGf,QAAM,IAAI,QAAQ,qBAAqB,WAAS,MAAM,QAAQ,OAAO,EAAE,CAAC;AAKxE,QAAM,IAAI,QAAQA,eAAc,GAAG;AAGnC,QAAM,IAAI,YAAY;AAEtB,SAAO,EAAE,KAAK,KAAK;AACrB;AAOA,SAAS,WAAW,QAAuC;AACzD,MAAI,QAAQ,OAAO;AAGnB,UAAQ,MAAM,QAAQ,UAAU,EAAE;AAGlC,UAAQ,wBAAwB,OAAO,KAAK,KAAK,EAAE;AAGnD,UAAQ,MAAM,KAAK;AAGnB,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,UAAQ,mBAAmB,KAAK;AAGhC,QAAM,QAAQ,MAAM,MAAM,GAAG;AAG7B,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,IAAI,MAAM;AAAA;AAAA,EAAyF,KAAK,EAAE;AAAA,EAClH;AAGA,QAAM,aAAa,iBAAiB,MAAM,CAAC,CAAC;AAG5C,QAAM,EAAE,KAAK,KAAK,IAAI,UAAU,UAAU;AAG1C,QAAM,MAAM,GAAG,UAAU;AAGzB,QAAM,QAAQ,iBAAiB,MAAM,CAAC,CAAC;AAIvC,QAAM,UAAU,iBAAiB,MAAM,CAAC,CAAC;AAKzC,QAAM,QAAQ,OAAO;AAErB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,OAAO;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3B;AACF;AAUA,SAAS,aAAa,OAAyD;AAE7E,QAAM,UAAoB,CAAC;AAG3B,QAAM,YAAY,MAAM,QAAQ,8BAA8B,WAAS;AAErE,YAAQ,KAAK,KAAK;AAIlB,UAAM,YAAY,MAAM,MAAM,eAAe,EAAE,SAAS;AACxD,WAAO,YAAY,IAAI,KAAK,OAAO,SAAS,IAAI;AAAA,EAClD,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;;;AC7cA,SAAS,gBAAAC,qBAAoB;AAMtB,IAAM,cAAN,cAA0BC,cAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5C,YAAY,cAAuC;AACjD,UAAM;AACN,SAAK,eAAe;AACpB,SAAK,aAAa,CAAC;AACnB,SAAK,YAAY,CAAC;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASW,MAAM,WAAoC;AACnD,UAAM,SAAS,kBAAkB,SAAS;AAC1C,UAAM,WAAW,OAAO,MAAM;AAC9B,aAAS,OAAO,IAAI;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,WAAW,KAAK;AACd,UAAM,qBAAqB,IAAI,eAAe;AAC9C,QAAI,oBAAoB;AAEtB,YAAM,kBAAkB,IAAI,qBAAqB,KAAK,YAAY;AAClE,iBAAW,qBAAqB,oBAAoB;AAClD,cAAM,eAAe,gBAAgB,oBAAoB,iBAAiB;AAC1E,aAAK,WAAW,KAAK,YAAY;AAAA,MACnC;AAAA,IACF;AAEA,UAAM,eAAe,IAAI,SAAS;AAClC,QAAI,cAAc;AAEhB,YAAM,iBAAiB,IAAI,eAAe;AAC1C,iBAAW,eAAe,cAAc;AACtC,cAAM,WAAW,eAAe,cAAc,WAAW;AACzD,aAAK,UAAU,KAAK,QAAQ;AAAA,MAC9B;AAAA,IACF;AAEA,SAAK,QAAQ;AAAA,MACX,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,IAClB;AAAA,EACF;AACF;;;AC9CO,SAAS,iBAAiB,OAAe,SAA8B,OAAO,OAAc;AACjG,QAAM,aAA6B,CAAC;AACpC,QAAM,YAAwB,CAAC;AAI/B,QAAM,EAAE,KAAK,IAAI,sBAAsB,KAAK;AAC5C,MAAI,MAAM;AAIR,SAAK,KAAK,CAAC,GAAG,MAAM;AAClB,aAAO,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI;AAAA,IAClD,CAAC;AAAA,EACH;AAGA,aAAW,OAAO,MAAM;AAEtB,QAAI;AACJ,QAAI;AACF,YAAM,cAAc,IAAI,YAAY,OAAO;AAC3C,oBAAc,YAAY,MAAM,IAAI,GAAG;AAAA,IACzC,SAAS,GAAG;AAEV,UAAI,WAAW;AACf,UAAI,EAAE,OAAO,SAAS,oBAAoB;AACxC,YAAI,EAAE,MAAM,MAAM;AAIhB,sBAAY,YAAY,EAAE,MAAM,OAAO,IAAI,IAAI,IAAI;AACnD,cAAI,EAAE,MAAM,QAAQ;AAClB,wBAAY,SAAS,EAAE,MAAM,MAAM;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AACA,YAAM,MAAM,0CAA0C,QAAQ;AAAA,EAAM,IAAI,GAAG;AAAA;AAAA;AAAA,IAAkB,EAAE,OAAO;AACtG,YAAM,IAAI,MAAM,GAAG;AAAA,IACrB;AAEA,eAAW,gBAAgB,YAAY,YAAY;AAEjD,YAAM,QAAQ,IAAI;AAClB,iBAAW,KAAK;AAAA,QACd,GAAG;AAAA,QACH,SAAS,IAAI;AAAA,QACb,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MAC3B,CAAC;AAAA,IACH;AAEA,eAAW,YAAY,YAAY,WAAW;AAE5C,YAAM,QAAQ,IAAI;AAClB,gBAAU,KAAK;AAAA,QACb,GAAG;AAAA,QACH,OAAO,IAAI;AAAA,QACX,SAAS,IAAI;AAAA,QACb,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MAC3B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;;;AChFA,SAAS,eAAe;AAEjB,SAAS,YAAY,QAAgC,SAAyC;AACnG,SAAO,QAAQ,SAAS,KAAK,OAAK;AAChC,QAAI,EAAE,SAAS,QAAQ,cAAc;AACnC,YAAM,IAAI;AACV,aAAO,EAAE,SAAS;AAAA,IACpB,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEO,SAAS,YAAY,QAAqD;AAC/E,SAAO,QAAQ,SAAS,KAAK,OAAK;AAChC,WAAO,EAAE,SAAS,QAAQ;AAAA,EAC5B,CAAC;AACH;AAEO,SAAS,QAAQ,QAAgC,UAAkC;AACxF,MAAI,WAAW,QAAW;AACxB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,QAAsB,CAAC;AAC7B,aAAW,KAAK,OAAO,UAAU;AAC/B,QAAI,EAAE,SAAS,QAAQ,cAAc;AACnC,YAAM,IAAI;AACV,UAAI,SAAS,SAAS,EAAE,IAAI,GAAG;AAC7B,cAAM,KAAK,CAAC;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,SAAS,MAAkB,KAAqB;AAC9D,SAAO,GAAG,GAAG,KAAK,KAAK,UAAU,KAAK,OAAO,GAAG,MAAM,CAAC,CAAC;AAC1D;;;ACzBO,SAAS,uBAAuB,SAAmC;AAExE,QAAM,UAAU,QAAQ,YAAY;AACpC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,SAAS,SAAS,2DAA2D,CAAC;AAAA,EAChG;AAGA,QAAM,YAAY,QAAQ,SAAS,CAAC,MAAM,CAAC;AAC3C,MAAI,UAAU,WAAW,GAAG;AAC1B,UAAM,IAAI,MAAM,SAAS,SAAS,gDAAgD,CAAC;AAAA,EACrF;AACA,QAAM,gBAAgC,CAAC;AACvC,aAAW,QAAQ,WAAW;AAE5B,UAAM,UAAU,KAAK,YAAY;AACjC,QAAI,YAAY,QAAW;AACzB,YAAM,IAAI,MAAM,SAAS,SAAS,oEAAoE,CAAC;AAAA,IACzG;AAEA,UAAM,QAAQ,YAAY,OAAO;AACjC,kBAAc,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,UAAU,YAAY,SAAS,KAAK,GAAG,QAAQ;AAErD,QAAM,QAAQ,YAAY,OAAO;AACjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA;AAAA,IAEA,YAAY;AAAA,IACZ,UAAU;AAAA,IACV;AAAA;AAAA,IAEA,mBAAmB,CAAC;AAAA,IACpB;AAAA,EACF;AACF;;;ACvDA,SAAS,gBAAgB;;;ACkBlB,SAAS,sBAAsB,SAAiC;AAErE,MAAI,UAAU,kBAAkB,SAAS,SAAS,MAAM;AAGxD,YAAU,QAAQ,QAAQ,QAAQ,GAAG;AACrC,QAAM,QAAQ,YAAY,OAAO;AAGjC,QAAM,QAAQ,YAAY,SAAS,OAAO,GAAG,QAAQ;AAGrD,QAAM,UAAU,YAAY,SAAS,KAAK,GAAG,QAAQ;AAIrD,WAAS,aAAa,eAA2C,MAAsB;AACrF,WAAO;AAAA,MACL,KAAK;AAAA,QACH,QAAQ;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,MAAM;AAAA,QACN;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAIA,WAAS,eAAe,eAA2C,QAA6B;AAC9F,WAAO;AAAA,MACL,KAAK;AAAA,QACH,QAAQ;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,MAAM;AAAA,QACN,WAAW;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,MAAM;AAGzB,UAAM,SAAS,YAAY,SAAS,OAAO;AAC3C,WAAO,CAAC,eAAe,QAAW,MAAM,CAAC;AAAA,EAC3C;AAGA,QAAM,iBAAiB,YAAY,SAAS,YAAY;AACxD,QAAM,eAA2B,CAAC;AAClC,MAAI,mBAAmB,QAAW;AAEhC,UAAM,SAAS,YAAY,SAAS,IAAI;AACxC,QAAI,QAAQ;AAEV,UAAI,QAAQ,SAAS,UAAU,QAAQ,SAAS,OAAO;AACrD,cAAM,IAAI,MAAM,SAAS,SAAS,qDAAqD,CAAC;AAAA,MAC1F;AACA,YAAM,SAAS,YAAY,SAAS,MAAM;AAC1C,mBAAa,KAAK,eAAe,QAAW,MAAM,CAAC;AAAA,IACrD,OAAO;AAEL,YAAM,OAAO,aAAa,SAAS,OAAO;AAC1C,UAAI,MAAM;AACR,qBAAa,KAAK,aAAa,QAAW,IAAI,CAAC;AAAA,MACjD;AAAA,IACF;AAAA,EACF,OAAO;AAGL,UAAM,WAAW,QAAQ,gBAAgB,CAAC,KAAK,CAAC;AAChD,UAAM,WAAqB,CAAC;AAC5B,eAAW,WAAW,UAAU;AAC9B,YAAM,UAAU,QAAQ,YAAY;AACpC,UAAI,YAAY,QAAW;AACzB,cAAM,IAAI,MAAM,SAAS,SAAS,0EAA0E,CAAC;AAAA,MAC/G;AACA,eAAS,KAAK,OAAO;AAAA,IACvB;AAMA,UAAM,eAAe,QAAQ,SAAS,CAAC,SAAS,CAAC;AACjD,QAAI,aAAa,WAAW,GAAG;AAE7B,YAAM,UAAU,SAAS,IAAI,MAAM;AACnC,YAAM,OAAO,aAAa,SAAS,OAAO;AAC1C,UAAI,MAAM;AACR,qBAAa,KAAK,aAAa,SAAS,IAAI,CAAC;AAAA,MAC/C;AAAA,IACF,OAAO;AAOL,iBAAW,eAAe,cAAc;AACtC,cAAM,gBAAgB,YAAY,YAAY;AAC9C,YAAI,kBAAkB,QAAW;AAC/B,gBAAM,IAAI,MAAM,SAAS,SAAS,kEAAkE,CAAC;AAAA,QACvG;AACA,cAAM,iBAAiB,cAAc,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AACjE,cAAM,UAA0B,CAAC;AACjC,mBAAW,iBAAiB,gBAAgB;AAC1C,cAAI,CAAC,MAAM,SAAS,aAAa,CAAC,GAAG;AACnC,kBAAM,IAAI,MAAM,SAAS,SAAS,uDAAuD,CAAC;AAAA,UAC5F;AACA,kBAAQ,KAAK,OAAO,aAAa,CAAC;AAAA,QACpC;AACA,cAAM,OAAO,aAAa,SAAS,WAAW;AAC9C,YAAI,MAAM;AACR,uBAAa,KAAK,aAAa,SAAS,IAAI,CAAC;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,SAAqB,YAA8B;AACvE,QAAM,aAAa,QAAQ;AAC3B,QAAM,UAAU,YAAY,YAAY,KAAK;AAI7C,QAAM,UAAU,UAAU,YAAY,OAAO,IAAI;AACjD,UAAQ,YAAY;AAAA,IAClB,KAAK,OAAO;AACV,UAAI,YAAY,QAAW;AAEzB,eAAO;AAAA,MACT;AAKA,YAAM,cAAc,YAAY,YAAY,UAAU;AACtD,YAAM,cAAc,cAAc,YAAY,WAAW,IAAI;AAC7D,UAAI,gBAAgB,QAAW;AAE7B,cAAM,UAAU,UAAU,QAAQ,IAAI;AACtC,cAAM,cAAc,UAAU,YAAY,IAAI;AAC9C,eAAO,KAAK,kBAAkB,SAAS,WAAW;AAAA,MACpD;AAEA,aAAO,UAAU,QAAQ,IAAI;AAAA,IAC/B;AAAA,IAEA,KAAK,SAAS;AAGZ,UAAI,YAAY,QAAW;AAEzB,cAAM,IAAI,MAAM,SAAS,SAAS,6CAA6C,CAAC;AAAA,MAClF;AACA,YAAM,cAAc,QAAQ,YAAY,CAAC,QAAQ,CAAC;AAClD,YAAM,eAAe,QAAQ,YAAY,CAAC,SAAS,CAAC;AAEpD,YAAM,cAAc,YAAY,IAAI,gBAAc;AAChD,cAAM,aAAa,YAAY,UAAU;AACzC,YAAI,eAAe,QAAW;AAC5B,gBAAM,IAAI,MAAM,SAAS,SAAS,sDAAsD,CAAC;AAAA,QAC3F;AACA,eAAO,WAAW;AAAA,MACpB,CAAC;AACD,YAAM,eAAe,aAAa,IAAI,iBAAe;AACnD,cAAM,cAAc,YAAY,WAAW;AAC3C,YAAI,gBAAgB,QAAW;AAC7B,gBAAM,IAAI,MAAM,SAAS,SAAS,uDAAuD,CAAC;AAAA,QAC5F;AACA,eAAO,YAAY;AAAA,MACrB,CAAC;AAID,UAAI,YAAY,YAAY,UAAU,GAAG;AACvC,cAAM,IAAI,MAAM,SAAS,SAAS,8DAA8D,CAAC;AAAA,MACnG;AACA,UAAI,YAAY,YAAY,OAAO,GAAG;AACpC,cAAM,IAAI,MAAM,SAAS,SAAS,2DAA2D,CAAC;AAAA,MAChG;AAUA,YAAM,cAAc,YAAY,KAAK,KAAK;AAC1C,UAAI,eAAe,aAAa,KAAK,KAAK;AAC1C,UAAI,aAAa,SAAS,GAAG;AAC3B,YAAI,YAAY,SAAS,GAAG;AAC1B,yBAAe,KAAK,YAAY;AAAA,QAClC,OAAO;AACL,yBAAe,IAAI,YAAY;AAAA,QACjC;AAAA,MACF;AACA,YAAM,YAAY,UAAU,GAAG,WAAW,IAAI,YAAY,EAAE;AAG5D,YAAM,WAAW,UAAU,QAAQ,IAAI;AACvC,aAAO,KAAK,SAAS,WAAW,QAAQ;AAAA,IAC1C;AAAA,IAEA,KAAK;AAIH,UAAI,YAAY,QAAW;AAEzB,cAAM,IAAI,MAAM,SAAS,SAAS,2DAA2D,CAAC;AAAA,MAChG;AAGA,UAAI,YAAY,YAAY,YAAY,GAAG;AACzC,cAAM,IAAI,MAAM,SAAS,SAAS,+DAA+D,CAAC;AAAA,MACpG;AAOA,UAAI,YAAY,YAAY,UAAU,GAAG;AACvC,cAAM,IAAI,MAAM,SAAS,SAAS,6DAA6D,CAAC;AAAA,MAClG;AACA,UAAI,YAAY,YAAY,MAAM,GAAG;AACnC,cAAM,IAAI,MAAM,SAAS,SAAS,yDAAyD,CAAC;AAAA,MAC9F;AACA,aAAO,UAAU,QAAQ,IAAI;AAAA,IAE/B;AACE,YAAM,IAAI,MAAM,SAAS,SAAS,4BAA4B,UAAU,GAAG,CAAC;AAAA,EAChF;AACF;AAEA,SAAS,UAAU,UAAwB;AASzC,aAAW,8BAA8B,QAAQ;AAOjD,aAAW,SAAS,QAAQ,2BAA2B,uBAAuB;AAE9E,SAAO,gBAAgB,QAAQ;AACjC;AAEA,SAAS,YAAY,SAAqB,QAA+B;AAEvE,QAAM,WAAW,kBAAkB,QAAQ,MAAM;AACjD,MAAI,YAAY,aAAa,cAAc;AACzC,UAAM,IAAI,MAAM,SAAS,SAAS,4DAA4D,CAAC;AAAA,EACjG;AAGA,QAAM,WAAW,YAAY,QAAQ,MAAM;AAC3C,MAAI,aAAa,QAAW;AAC1B,UAAM,IAAI,MAAM,SAAS,SAAS,mCAAmC,CAAC;AAAA,EACxE;AACA,QAAM,OAAO,WAAW,SAAS,QAAQ;AACzC,MAAI,KAAK,WAAW,GAAG;AACrB,UAAM,IAAI,MAAM,SAAS,SAAS,uCAAuC,CAAC;AAAA,EAC5E;AAGA,QAAM,WAAW,YAAY,QAAQ,MAAM;AAC3C,QAAM,aAAa,YAAY,QAAQ,QAAQ;AAC/C,MAAI,YAAY,YAAY;AAC1B,UAAM,IAAI,MAAM,SAAS,SAAS,mDAAmD,CAAC;AAAA,EACxF,WAAW,aAAa,UAAa,eAAe,QAAW;AAC7D,UAAM,IAAI,MAAM,SAAS,SAAS,6CAA6C,CAAC;AAAA,EAClF;AAEA,MAAI;AACJ,MAAI,UAAU;AAEZ,WAAO,WAAW,SAAS,QAAQ;AACnC,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,IAAI,MAAM,SAAS,SAAS,uCAAuC,CAAC;AAAA,IAC5E;AAAA,EACF,OAAO;AAEL,UAAM,OAAO,eAAe,SAAS,YAAY,KAAK;AACtD,UAAM,OAAO,eAAe,SAAS,YAAY,KAAK;AACtD,QAAI,OAAO,MAAM;AACf,YAAM,IAAI,MAAM,SAAS,SAAS,gDAAgD,CAAC;AAAA,IACrF;AACA,WAAO,MAAM,KAAK,MAAM;AACxB,UAAM,SAAS,OAAO;AACtB,QAAI,KAAK,WAAW,GAAG;AAErB,WAAK,CAAC,IAAI;AAAA,IACZ,OAAO;AACL,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,cAAM,OAAO,KAAK,KAAK,SAAS;AAChC,aAAK,CAAC,IAAI,OAAO,SAAS;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,WAAW,KAAK,QAAQ;AAC/B,UAAM,IAAI,MAAM,SAAS,SAAS,yDAAyD,CAAC;AAAA,EAC9F;AAGA,QAAM,SAAwB,CAAC;AAC/B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,WAAO,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;AAAA,EAChC;AACA,SAAO,UAAU,MAAM;AACzB;AAEA,SAAS,WAAW,SAAqB,SAA+B;AACtE,QAAM,UAAU,YAAY,OAAO,GAAG;AACtC,MAAI,YAAY,QAAW;AACzB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,MAAM,QAAQ,YAAY,OAAO;AACvC,QAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,QAAM,OAAiB,CAAC;AACxB,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAC1B,UAAMC,OAAM,WAAW,OAAO;AAC9B,QAAI,MAAMA,IAAG,GAAG;AACd,cAAQ,IAAI,KAAK,UAAU,OAAO,CAAC;AACnC,YAAM,IAAI,MAAM,SAAS,SAAS,yBAAyB,OAAO,SAAS,QAAQ,IAAI,IAAI,CAAC;AAAA,IAC9F;AACA,SAAK,KAAKA,IAAG;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,SAAqB,MAAkB,UAA0B;AAC1F,MAAI,IAAI,KAAK,cAAc,KAAK,WAAW,QAAQ;AACnD,MAAI,GAAG,KAAK;AACZ,MAAI,MAAM,UAAa,EAAE,WAAW,GAAG;AACrC,UAAM,IAAI,MAAM,SAAS,SAAS,IAAI,KAAK,IAAI,KAAK,QAAQ,wBAAwB,CAAC;AAAA,EACvF;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,MAAkB,UAA0B;AACrE,QAAM,IAAI,KAAK,cAAc,KAAK,WAAW,QAAQ;AACrD,SAAO,GAAG,KAAK;AACjB;AAEA,SAAS,eAAe,SAAqB,MAAkB,UAA0B;AACvF,QAAM,IAAI,kBAAkB,SAAS,MAAM,QAAQ;AACnD,QAAMA,OAAM,WAAW,CAAC;AACxB,MAAI,MAAMA,IAAG,GAAG;AACd,UAAM,IAAI,MAAM,SAAS,SAAS,yBAAyB,CAAC,UAAU,KAAK,IAAI,KAAK,QAAQ,aAAa,CAAC;AAAA,EAC5G;AACA,SAAOA;AACT;AAgBA,SAAS,8BAA8B,UAA0B;AAM/D,QAAM,iBAAiB,SAAS,KAAK,EAAE,QAAQ,QAAQ,GAAG;AAG1D,QAAM,UAAU,eAAe,MAAM,eAAe;AACpD,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAGA,QAAM,UAAU,eAAe,OAAO,UAAU;AAChD,QAAM,WAAW,eAAe,UAAU,GAAG,OAAO;AACpD,QAAM,UAAU,eAAe,UAAU,UAAU,CAAC,EAAE,KAAK;AAG3D,QAAM,YAAY,QAAQ,MAAM,wBAAwB;AACxD,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,UAAU,CAAC,EAAE,KAAK;AACpC,QAAM,YAAY,UAAU,CAAC;AAG7B,MAAI,YAAY;AAChB,MAAI,aAAa;AACjB,MAAI,WAAW;AACf,MAAI,YAAY;AAEhB,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,OAAO,UAAU,CAAC;AAGxB,SAAK,SAAS,OAAO,SAAS,SAAS,MAAM,KAAK,UAAU,IAAI,CAAC,MAAM,OAAO;AAC5E,UAAI,CAAC,UAAU;AACb,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,SAAS,WAAW;AAC7B,mBAAW;AACX,oBAAY;AAAA,MACd;AACA;AAAA,IACF;AAEA,QAAI,UAAU;AACZ;AAAA,IACF;AAGA,QAAI,SAAS,KAAK;AAChB;AAAA,IACF,WAAW,SAAS,KAAK;AACvB;AAAA,IACF;AAGA,QAAI,eAAe,KAAK,CAAC,UAAU;AACjC,YAAM,YAAY,UAAU,UAAU,CAAC,EAAE,MAAM,gBAAgB;AAC/D,UAAI,WAAW;AACb,oBAAY;AACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,cAAc,IAAI;AACpB,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,UAAU,UAAU,GAAG,SAAS,EAAE,KAAK;AACxD,MAAI,YAAY,UAAU,UAAU,YAAY,CAAC,EAAE,KAAK;AAIxD,MAAI,WAAW;AACf,eAAa;AACb,aAAW;AACX,cAAY;AAEZ,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,OAAO,UAAU,CAAC;AAGxB,SAAK,SAAS,OAAO,SAAS,SAAS,MAAM,KAAK,UAAU,IAAI,CAAC,MAAM,OAAO;AAC5E,UAAI,CAAC,UAAU;AACb,mBAAW;AACX,oBAAY;AAAA,MACd,WAAW,SAAS,WAAW;AAC7B,mBAAW;AACX,oBAAY;AAAA,MACd;AACA;AAAA,IACF;AAEA,QAAI,UAAU;AACZ;AAAA,IACF;AAGA,QAAI,SAAS,KAAK;AAChB;AAAA,IACF,WAAW,SAAS,KAAK;AACvB,UAAI,eAAe,GAAG;AAEpB,mBAAW;AACX;AAAA,MACF;AACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,aAAa,IAAI;AACnB,gBAAY,UAAU,UAAU,GAAG,QAAQ,EAAE,KAAK;AAAA,EACpD;AAGA,QAAM,oBAAoB,8BAA8B,QAAQ;AAChE,QAAM,qBAAqB,8BAA8B,SAAS;AAElE,QAAM,qBAAqB,UAExB,QAAQ,gCAAgC,SAAS,EACjD,QAAQ,+BAA+B,QAAQ,EAC/C,QAAQ,kCAAkC,SAAS,EAEnD,QAAQ,cAAc,IAAI;AAI7B,QAAM,qBAAqB,QAAQ,QAAQ,QAAQ,IAAI;AACvD,QAAM,0BAA0B;AAChC,QAAM,wBAAwB,0BAA0B,UAAU;AAElE,QAAM,iCAAiC,UAAU,IAAI;AACrD,QAAM,mBAAmB,eAAe,UAAU,8BAA8B,EAAE,KAAK;AAEvF,SAAO,GAAG,QAAQ,gBAAgB,kBAAkB,KAAK,iBAAiB,KAAK,kBAAkB,IAAI,gBAAgB;AACvH;;;ADpiBO,SAAS,gBAAgB,OAAsB;AACpD,MAAI;AACJ,MAAI;AAEF,UAAM,SAAS,OAAO,EAAE,gBAAgB,KAAK,CAAC;AAAA,EAChD,SAAS,GAAG;AAEV,UAAM,MAAM;AAAA;AAAA,EAA8C,EAAE,OAAO;AACnE,UAAM,IAAI,MAAM,GAAG;AAAA,EACrB;AAGA,QAAM,iBAAiC,cAAc,IAAI,MAAM,KAAK;AAGpE,QAAM,aAA6B,mBAAmB,IAAI,MAAM,KAAK;AAGrE,QAAM,YAAwB,kBAAkB,IAAI,MAAM,KAAK;AAE/D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,cAAc,UAAkC,aAAqC;AAE5F,QAAM,eAAe,YAAY,UAAU,WAAW;AACtD,MAAI,iBAAiB,QAAW;AAC9B,UAAM,IAAI,MAAM,SAAS,UAAU,4DAA4D,CAAC;AAAA,EAClG;AAEA,WAAS,gBAAgB,MAAc,UAAuC;AAC5E,UAAM,OAAO,YAAY,cAAc,IAAI;AAC3C,QAAI,YAAY,SAAS,QAAW;AAClC,YAAM,QAAQ,IAAI,MAAM,SAAS,cAAc,IAAI,IAAI,0CAA0C,CAAC;AAClG,2BAAqB,OAAO,aAAa,cAAc,OAAO;AAAA,IAChE;AACA,QAAI,SAAS,QAAW;AACtB,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,QAAI,CAAC,MAAM,KAAK,GAAG;AACjB,aAAO;AAAA,IACT,OAAO;AACL,YAAM,QAAQ,IAAI,MAAM,SAAS,MAAM,8BAA8B,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;AACnG,2BAAqB,OAAO,aAAa,cAAc,OAAO;AAAA,IAChE;AAAA,EACF;AAGA,QAAM,YAAY,gBAAgB,SAAS,IAAI;AAG/C,QAAM,UAAU,gBAAgB,QAAQ,IAAI;AAG5C,MAAI,WAAW,gBAAgB,MAAM,KAAK;AAC1C,MAAI,aAAa,QAAW;AAE1B,eAAW;AAAA,EACb;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,UAAkC,aAAqC;AACjG,QAAM,gBAAgC,CAAC;AAEvC,QAAM,iBAAiB,YAAY,UAAU,YAAY;AACzD,MAAI,gBAAgB;AAElB,UAAM,WAAW,QAAQ,gBAAgB,CAAC,KAAK,CAAC;AAChD,eAAW,WAAW,UAAU;AAC9B,UAAI;AACF,sBAAc,KAAK,uBAAuB,OAAO,CAAC;AAAA,MACpD,SAAS,GAAG;AACV,6BAAqB,GAAG,aAAa,SAAS,WAAW;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,UAAkC,aAAiC;AAC5F,QAAM,YAAY,YAAY,UAAU,OAAO;AAC/C,MAAI,cAAc,QAAW;AAC3B,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,YAAwB,CAAC;AAC/B,QAAM,gBAAgB,YAAY,WAAW,WAAW;AACxD,MAAI,eAAe;AAEjB,UAAM,WAAW,QAAQ,eAAe,CAAC,OAAO,SAAS,QAAQ,IAAI,CAAC;AACtE,eAAW,WAAW,UAAU;AAC9B,UAAI;AACF,cAAM,OAAO,sBAAsB,OAAO;AAC1C,YAAI,MAAM;AACR,oBAAU,KAAK,GAAG,IAAI;AAAA,QACxB;AAAA,MACF,SAAS,GAAG;AACV,6BAAqB,GAAG,aAAa,SAAS,UAAU;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,qBACP,eACA,aACA,MACA,UACM;AAEN,MAAI,WAAW;AAEf,QAAM,uBAAuB,cAAc,aAAa,KAAK,KAAK;AAClE,MAAI,yBAAyB,IAAI;AAE/B,UAAM,QAAS,cAAsB;AACrC,QAAI,OAAO,SAAS,oBAAoB;AACtC,UAAI,MAAM,MAAM;AAId,cAAM,UAAU,MAAM,OAAO,IAAI;AACjC,oBAAY,YAAY,OAAO;AAC/B,YAAI,MAAM,QAAQ;AAChB,sBAAY,SAAS,MAAM,MAAM;AAAA,QACnC;AAAA,MACF;AAAA,IACF,OAAO;AAEL,kBAAY,YAAY,oBAAoB;AAAA,IAC9C;AAAA,EACF;AACA,QAAM,aAAa,gBAAgB,aAAa,KAAK,OAAO,KAAK,GAAG;AACpE,QAAM,MAAM,yBAAyB,QAAQ,cAAc,QAAQ;AAAA,EAAM,UAAU;AAAA;AAAA;AAAA,IAAkB,cAAc,OAAO;AAC1H,QAAM,IAAI,MAAM,GAAG;AACrB;AASA,SAAS,cAAc,WAAmB,YAA4B;AACpE,MAAI,eAAe,MAAM,cAAc,UAAU,QAAQ;AACvD,WAAO;AAAA,EACT;AAGA,QAAM,YAAY,UAAU,UAAU,GAAG,UAAU;AACnD,SAAO,UAAU,MAAM,IAAI,EAAE;AAC/B;AAWA,SAAS,gBAAgB,aAAqB,aAAqB,WAA2B;AAC5F,MAAI,gBAAgB,MAAM,cAAc,MAAM,eAAe,YAAY,UAAU,YAAY,YAAY,QAAQ;AACjH,WAAO;AAAA,EACT;AAGA,MAAI,YAAY;AAChB,SAAO,YAAY,KAAK,YAAY,YAAY,CAAC,MAAM,MAAM;AAC3D;AAAA,EACF;AAGA,MAAI,UAAU;AACd,SAAO,UAAU,YAAY,UAAU,YAAY,OAAO,MAAM,MAAM;AACpE;AAAA,EACF;AAGA,QAAM,cAAc,YAAY,UAAU,WAAW,OAAO;AAG5D,SAAO;AACT;","names":["assertNever","assertNever","num","ModelParser","ModelParser","ModelLexer","ModelVisitor","ModelVisitor","ModelLexer","ModelVisitor","ModelVisitor","reWhitespace","ModelVisitor","ModelVisitor","num"]}
|