@tokens-studio/tokenscript-interpreter 0.36.3 → 0.37.0
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/chunk-2EEKBDOX.js +5308 -0
- package/dist/chunk-2EEKBDOX.js.map +1 -0
- package/dist/chunk-2NMUBWBX.js +5861 -0
- package/dist/chunk-2NMUBWBX.js.map +1 -0
- package/dist/chunk-2OHE65GL.js +5779 -0
- package/dist/chunk-2OHE65GL.js.map +1 -0
- package/dist/chunk-2PZR6BQ6.js +5773 -0
- package/dist/chunk-2PZR6BQ6.js.map +1 -0
- package/dist/chunk-2QDDLPUW.js +5858 -0
- package/dist/chunk-2QDDLPUW.js.map +1 -0
- package/dist/chunk-4DUQBXYY.js +5762 -0
- package/dist/chunk-4DUQBXYY.js.map +1 -0
- package/dist/chunk-4SLJE4IW.js +5322 -0
- package/dist/chunk-4SLJE4IW.js.map +1 -0
- package/dist/chunk-6ABZOYUP.js +5802 -0
- package/dist/chunk-6ABZOYUP.js.map +1 -0
- package/dist/chunk-6HQZVWXZ.js +5341 -0
- package/dist/chunk-6HQZVWXZ.js.map +1 -0
- package/dist/chunk-6UY773C4.js +5292 -0
- package/dist/chunk-6UY773C4.js.map +1 -0
- package/dist/chunk-75Z55XEZ.js +5681 -0
- package/dist/chunk-75Z55XEZ.js.map +1 -0
- package/dist/chunk-7IWYKR22.js +5778 -0
- package/dist/chunk-7IWYKR22.js.map +1 -0
- package/dist/chunk-AVZUAMNS.js +5757 -0
- package/dist/chunk-AVZUAMNS.js.map +1 -0
- package/dist/chunk-BL7GZSRR.js +5724 -0
- package/dist/chunk-BL7GZSRR.js.map +1 -0
- package/dist/chunk-BMZ5NY7J.js +93 -0
- package/dist/chunk-BMZ5NY7J.js.map +1 -0
- package/dist/{chunk-AXH5N7KV.js → chunk-BNLQ6GCU.js} +2 -6
- package/dist/chunk-BNLQ6GCU.js.map +1 -0
- package/dist/chunk-BSJBGMCX.js +93 -0
- package/dist/{chunk-RI2BWY7D.js.map → chunk-BSJBGMCX.js.map} +1 -1
- package/dist/chunk-BUJRELXW.js +5342 -0
- package/dist/chunk-BUJRELXW.js.map +1 -0
- package/dist/chunk-DCOIGXSK.js +5763 -0
- package/dist/chunk-DCOIGXSK.js.map +1 -0
- package/dist/chunk-DZDZDYPO.js +5654 -0
- package/dist/chunk-DZDZDYPO.js.map +1 -0
- package/dist/{chunk-5S3H4SYX.js → chunk-GAE7SZLZ.js} +154 -9
- package/dist/chunk-GAE7SZLZ.js.map +1 -0
- package/dist/chunk-HFLLWRRV.js +5791 -0
- package/dist/chunk-HFLLWRRV.js.map +1 -0
- package/dist/{lib/chunk-ODVWXGOM.js → chunk-JL4UU4PY.js} +2 -8
- package/dist/chunk-JL4UU4PY.js.map +1 -0
- package/dist/{chunk-CKLFRLH7.js → chunk-JUGNHFDN.js} +220 -338
- package/dist/chunk-JUGNHFDN.js.map +1 -0
- package/dist/{chunk-RI2BWY7D.js → chunk-K2OUSWUX.js} +2 -3
- package/dist/chunk-K2OUSWUX.js.map +1 -0
- package/dist/chunk-KOLA6XR5.js +5770 -0
- package/dist/chunk-KOLA6XR5.js.map +1 -0
- package/dist/{chunk-3ZOUTFP5.js → chunk-L77CTMYP.js} +169 -296
- package/dist/chunk-L77CTMYP.js.map +1 -0
- package/dist/chunk-LIXBSHBJ.js +99 -0
- package/dist/chunk-LIXBSHBJ.js.map +1 -0
- package/dist/chunk-LM5SZQV5.js +5763 -0
- package/dist/chunk-LM5SZQV5.js.map +1 -0
- package/dist/chunk-M76AGXPG.js +5772 -0
- package/dist/chunk-M76AGXPG.js.map +1 -0
- package/dist/{chunk-QP7M6WUR.js → chunk-OV2GMYVM.js} +221 -341
- package/dist/chunk-OV2GMYVM.js.map +1 -0
- package/dist/{chunk-33CDF4L4.js → chunk-P4VLJQEI.js} +235 -838
- package/dist/chunk-P4VLJQEI.js.map +1 -0
- package/dist/chunk-QLSMLF5S.js +5302 -0
- package/dist/chunk-QLSMLF5S.js.map +1 -0
- package/dist/chunk-QYTZHMUN.js +5831 -0
- package/dist/chunk-QYTZHMUN.js.map +1 -0
- package/dist/chunk-SBM4WTQW.js +5771 -0
- package/dist/chunk-SBM4WTQW.js.map +1 -0
- package/dist/chunk-UAQCLV6Y.js +5816 -0
- package/dist/chunk-UAQCLV6Y.js.map +1 -0
- package/dist/chunk-YIZGWYGL.js +5300 -0
- package/dist/chunk-YIZGWYGL.js.map +1 -0
- package/dist/chunk-Z437BNC5.js +107 -0
- package/dist/chunk-Z437BNC5.js.map +1 -0
- package/dist/cli.js +182 -17
- package/dist/cli.js.map +1 -1
- package/dist/compliance-suite.js +3 -5
- package/dist/compliance-suite.js.map +1 -1
- package/dist/config-Bb9I9K-y.d.ts +1005 -0
- package/dist/config-Be-GTPYh.d.ts +976 -0
- package/dist/config-BkIqJNxv.d.ts +1009 -0
- package/dist/config-Cp5BqDfR.d.ts +731 -0
- package/dist/config-D36YRJGj.d.ts +1007 -0
- package/dist/{config-CFhN7-6U.d.ts → config-DB5rZBMx.d.ts} +109 -17
- package/dist/config-DQj8LHMT.d.ts +995 -0
- package/dist/{config-DtbN3iyg.d.ts → config-Mw_Iq324.d.ts} +5 -2
- package/dist/config-P6Ivo_zY.d.ts +997 -0
- package/dist/config-RCpZF46f.d.ts +960 -0
- package/dist/lib/{chunk-PXS4WZYB.cjs → chunk-EMRAAGPR.cjs} +102 -100
- package/dist/lib/chunk-EMRAAGPR.cjs.map +1 -0
- package/dist/lib/{chunk-XHA2RNU7.cjs → chunk-JQKYSUJJ.cjs} +728 -568
- package/dist/lib/chunk-JQKYSUJJ.cjs.map +1 -0
- package/dist/lib/{chunk-73YLAUUC.js → chunk-MD2DETZV.js} +5 -3
- package/dist/lib/chunk-MD2DETZV.js.map +1 -0
- package/dist/lib/chunk-SLITBMFB.js +114 -0
- package/dist/lib/chunk-SLITBMFB.js.map +1 -0
- package/dist/lib/{chunk-F5SBEZH2.js → chunk-VXZQQBEA.js} +175 -16
- package/dist/lib/chunk-VXZQQBEA.js.map +1 -0
- package/dist/lib/{chunk-LEYHQJTL.cjs → chunk-ZMMIYWFF.cjs} +11 -2
- package/dist/lib/chunk-ZMMIYWFF.cjs.map +1 -0
- package/dist/lib/index.cjs +99 -91
- package/dist/lib/index.d.cts +4 -4
- package/dist/lib/index.d.ts +4 -4
- package/dist/lib/index.js +3 -3
- package/dist/lib/{interpreter-6QwMkUqD.d.cts → interpreter-ByrEtz7T.d.ts} +54 -4
- package/dist/lib/{interpreter-v7WiwSP9.d.ts → interpreter-CG0Jw_k-.d.cts} +54 -4
- package/dist/lib/interpreter.cjs +81 -73
- package/dist/lib/interpreter.d.cts +7 -6
- package/dist/lib/interpreter.d.ts +7 -6
- package/dist/lib/interpreter.js +3 -3
- package/dist/lib/processor-node.cjs +12 -12
- package/dist/lib/processor-node.d.cts +3 -3
- package/dist/lib/processor-node.d.ts +3 -3
- package/dist/lib/processor-node.js +3 -3
- package/dist/lib/processor.cjs +17 -17
- package/dist/lib/processor.d.cts +4 -4
- package/dist/lib/processor.d.ts +4 -4
- package/dist/lib/processor.js +3 -3
- package/dist/lib/schema.cjs +5 -5
- package/dist/lib/schema.d.cts +1 -1
- package/dist/lib/schema.d.ts +1 -1
- package/dist/lib/schema.js +3 -3
- package/dist/lib/syntax-highlighting.cjs +15 -15
- package/dist/lib/syntax-highlighting.d.cts +1 -1
- package/dist/lib/syntax-highlighting.d.ts +1 -1
- package/dist/lib/syntax-highlighting.js +2 -2
- package/dist/lib/{types-BI0AZ4Ej.d.ts → types-BZAWM2oN.d.ts} +2 -2
- package/dist/lib/{types-cFwP43uv.d.cts → types-BhyJ6plH.d.cts} +2 -2
- package/dist/lib/{types-EB8V9c46.d.cts → types-DA9_CC7p.d.cts} +5 -2
- package/dist/lib/{types-EB8V9c46.d.ts → types-DA9_CC7p.d.ts} +5 -2
- package/dist/lib/types.cjs +10 -6
- package/dist/lib/types.d.cts +1 -1
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/types.js +1 -1
- package/dist/processor/index.d.ts +1 -1
- package/dist/processor/index.js +18 -2
- package/dist/processor/index.js.map +1 -1
- package/dist/repl.d.ts +15 -3
- package/dist/repl.js +6 -8
- package/dist/repl.js.map +1 -1
- package/dist/token-schemas.js +414 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-33CDF4L4.js.map +0 -1
- package/dist/chunk-3ZOUTFP5.js.map +0 -1
- package/dist/chunk-5S3H4SYX.js.map +0 -1
- package/dist/chunk-AXH5N7KV.js.map +0 -1
- package/dist/chunk-CKLFRLH7.js.map +0 -1
- package/dist/chunk-GJIOYGP6.js +0 -6446
- package/dist/chunk-GJIOYGP6.js.map +0 -1
- package/dist/chunk-HHCPY4WI.js +0 -6456
- package/dist/chunk-HHCPY4WI.js.map +0 -1
- package/dist/chunk-MXKGYBE4.js +0 -6457
- package/dist/chunk-MXKGYBE4.js.map +0 -1
- package/dist/chunk-NGG6MBER.js +0 -6452
- package/dist/chunk-NGG6MBER.js.map +0 -1
- package/dist/chunk-QP7M6WUR.js.map +0 -1
- package/dist/lib/chunk-73YLAUUC.js.map +0 -1
- package/dist/lib/chunk-F5SBEZH2.js.map +0 -1
- package/dist/lib/chunk-LEYHQJTL.cjs.map +0 -1
- package/dist/lib/chunk-ODVWXGOM.js.map +0 -1
- package/dist/lib/chunk-PXS4WZYB.cjs.map +0 -1
- package/dist/lib/chunk-XHA2RNU7.cjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SupportedFormats, ReservedKeyword, UNINTERPRETED_KEYWORDS } from './chunk-
|
|
2
|
-
import {
|
|
1
|
+
import { SupportedFormats, ReservedKeyword, UNINTERPRETED_KEYWORDS } from './chunk-BNLQ6GCU.js';
|
|
2
|
+
import { type } from 'arktype';
|
|
3
3
|
|
|
4
4
|
// src/interpreter/errors/messages/en.ts
|
|
5
5
|
var messages = {
|
|
@@ -17,7 +17,6 @@ var messages = {
|
|
|
17
17
|
["PARSER_CONDITION_MUST_BE_BOOLEAN" /* CONDITION_MUST_BE_BOOLEAN */]: "If/elif condition must be a boolean",
|
|
18
18
|
["PARSER_INVALID_SYNTAX" /* INVALID_SYNTAX */]: (data) => data?.message ? String(data.message) : "Invalid syntax",
|
|
19
19
|
["PARSER_UNEXPECTED_END" /* UNEXPECTED_END */]: "Unexpected end of input",
|
|
20
|
-
["PARSER_TOLERANT_REQUIRES_INLINE" /* TOLERANT_REQUIRES_INLINE */]: "Tolerant mode only supports inline expressions. Use parse(true) for tolerant parsing.",
|
|
21
20
|
// Interpreter errors
|
|
22
21
|
["INT_UNKNOWN_NODE_TYPE" /* UNKNOWN_NODE_TYPE */]: (data) => `No visit method for AST node type: ${data.nodeType}`,
|
|
23
22
|
["INT_ARITHMETIC_REQUIRES_NUMBER" /* ARITHMETIC_REQUIRES_NUMBER */]: (data) => `Arithmetic operator ${data.operator} requires Number or NumberWithUnit operands, got ${data.leftType} and ${data.rightType}.`,
|
|
@@ -44,9 +43,6 @@ var messages = {
|
|
|
44
43
|
["INT_MAX_ITERATIONS_EXCEEDED" /* MAX_ITERATIONS_EXCEEDED */]: "Max iterations exceeded in while loop.",
|
|
45
44
|
["INT_WHILE_CONDITION_NOT_BOOLEAN" /* WHILE_CONDITION_NOT_BOOLEAN */]: "While loop condition must be a boolean.",
|
|
46
45
|
["INT_IF_CONDITION_NOT_BOOLEAN" /* IF_CONDITION_NOT_BOOLEAN */]: "If/elif condition must be a boolean.",
|
|
47
|
-
["INT_FOR_EACH_NOT_LIST" /* FOR_EACH_NOT_LIST */]: (data) => `for...in requires a List, got ${data.actualType}.`,
|
|
48
|
-
["INT_FOR_EACH_VARIABLE_SHADOW" /* FOR_EACH_VARIABLE_SHADOW */]: (data) => `for...in variable '${data.name}' shadows an existing variable in this scope.`,
|
|
49
|
-
["INT_FOR_EACH_DUPLICATE_VARS" /* FOR_EACH_DUPLICATE_VARS */]: (data) => `for...in item and index variables must have different names, both are '${data.name}'.`,
|
|
50
46
|
["INT_UNKNOWN_ERROR" /* UNKNOWN_ERROR */]: "An unknown error occurred during interpretation.",
|
|
51
47
|
// Operations errors
|
|
52
48
|
["OP_UNSUPPORTED_OPERAND_TYPE" /* UNSUPPORTED_OPERAND_TYPE */]: (data) => `Unsupported operand type for unit decomposition: ${data.type}`,
|
|
@@ -1830,59 +1826,6 @@ function stringifyInterpreterResult(value) {
|
|
|
1830
1826
|
return String(value);
|
|
1831
1827
|
}
|
|
1832
1828
|
|
|
1833
|
-
// src/interpreter/tolerant/partial-nodes.ts
|
|
1834
|
-
var PartialReferenceNode = class {
|
|
1835
|
-
constructor(partialValue, token) {
|
|
1836
|
-
this.partialValue = partialValue;
|
|
1837
|
-
this.token = token;
|
|
1838
|
-
this.nodeType = "PartialReferenceNode";
|
|
1839
|
-
}
|
|
1840
|
-
};
|
|
1841
|
-
var PartialStringNode = class {
|
|
1842
|
-
constructor(partialValue, quoteType, token) {
|
|
1843
|
-
this.partialValue = partialValue;
|
|
1844
|
-
this.quoteType = quoteType;
|
|
1845
|
-
this.token = token;
|
|
1846
|
-
this.nodeType = "PartialStringNode";
|
|
1847
|
-
}
|
|
1848
|
-
};
|
|
1849
|
-
var PartialFunctionCallNode = class {
|
|
1850
|
-
constructor(name, args, token) {
|
|
1851
|
-
this.name = name;
|
|
1852
|
-
this.args = args;
|
|
1853
|
-
this.token = token;
|
|
1854
|
-
this.nodeType = "PartialFunctionCallNode";
|
|
1855
|
-
}
|
|
1856
|
-
};
|
|
1857
|
-
var PartialBinOpNode = class {
|
|
1858
|
-
constructor(left, opToken) {
|
|
1859
|
-
this.left = left;
|
|
1860
|
-
this.opToken = opToken;
|
|
1861
|
-
this.nodeType = "PartialBinOpNode";
|
|
1862
|
-
this.token = opToken;
|
|
1863
|
-
}
|
|
1864
|
-
get op() {
|
|
1865
|
-
return this.opToken.value;
|
|
1866
|
-
}
|
|
1867
|
-
};
|
|
1868
|
-
var PartialUnaryOpNode = class {
|
|
1869
|
-
constructor(opToken) {
|
|
1870
|
-
this.opToken = opToken;
|
|
1871
|
-
this.nodeType = "PartialUnaryOpNode";
|
|
1872
|
-
this.token = opToken;
|
|
1873
|
-
}
|
|
1874
|
-
get op() {
|
|
1875
|
-
return this.opToken.value;
|
|
1876
|
-
}
|
|
1877
|
-
};
|
|
1878
|
-
var PartialParenNode = class {
|
|
1879
|
-
constructor(expr, token) {
|
|
1880
|
-
this.expr = expr;
|
|
1881
|
-
this.token = token;
|
|
1882
|
-
this.nodeType = "PartialParenNode";
|
|
1883
|
-
}
|
|
1884
|
-
};
|
|
1885
|
-
|
|
1886
1829
|
// src/interpreter/ast.ts
|
|
1887
1830
|
var BinOpNode = class {
|
|
1888
1831
|
constructor(left, opToken, right, token) {
|
|
@@ -1915,13 +1858,6 @@ var StringNode = class {
|
|
|
1915
1858
|
this.value = token.value;
|
|
1916
1859
|
}
|
|
1917
1860
|
};
|
|
1918
|
-
var TemplateStringNode = class {
|
|
1919
|
-
constructor(parts, token) {
|
|
1920
|
-
this.parts = parts;
|
|
1921
|
-
this.token = token;
|
|
1922
|
-
this.nodeType = "TemplateStringNode";
|
|
1923
|
-
}
|
|
1924
|
-
};
|
|
1925
1861
|
var UnaryOpNode = class {
|
|
1926
1862
|
constructor(opToken, expr, token) {
|
|
1927
1863
|
this.opToken = opToken;
|
|
@@ -2071,16 +2007,6 @@ var WhileNode = class {
|
|
|
2071
2007
|
this.nodeType = "WhileNode";
|
|
2072
2008
|
}
|
|
2073
2009
|
};
|
|
2074
|
-
var ForEachNode = class {
|
|
2075
|
-
constructor(itemVar, indexVar, collection, body, token) {
|
|
2076
|
-
this.itemVar = itemVar;
|
|
2077
|
-
this.indexVar = indexVar;
|
|
2078
|
-
this.collection = collection;
|
|
2079
|
-
this.body = body;
|
|
2080
|
-
this.token = token;
|
|
2081
|
-
this.nodeType = "ForEachNode";
|
|
2082
|
-
}
|
|
2083
|
-
};
|
|
2084
2010
|
var IfConditionNode = class {
|
|
2085
2011
|
constructor(condition, body, token) {
|
|
2086
2012
|
this.condition = condition;
|
|
@@ -2114,7 +2040,6 @@ var StatementListNode = class {
|
|
|
2114
2040
|
};
|
|
2115
2041
|
var AttributeAccessNode = class {
|
|
2116
2042
|
// 'left' is the object, 'right' is the attribute (IdentifierNode) or method (FunctionCallNode)
|
|
2117
|
-
// In tolerant mode, 'right' may also be a PartialFunctionCallNode
|
|
2118
2043
|
constructor(left, right, token) {
|
|
2119
2044
|
this.left = left;
|
|
2120
2045
|
this.right = right;
|
|
@@ -2150,9 +2075,6 @@ function walkAST(node, onVisit) {
|
|
|
2150
2075
|
} else if (node instanceof WhileNode) {
|
|
2151
2076
|
walkAST(node.condition, onVisit);
|
|
2152
2077
|
walkAST(node.body, onVisit);
|
|
2153
|
-
} else if (node instanceof ForEachNode) {
|
|
2154
|
-
walkAST(node.collection, onVisit);
|
|
2155
|
-
walkAST(node.body, onVisit);
|
|
2156
2078
|
} else if (node instanceof IfConditionNode) {
|
|
2157
2079
|
walkAST(node.condition, onVisit);
|
|
2158
2080
|
walkAST(node.body, onVisit);
|
|
@@ -2169,23 +2091,11 @@ function walkAST(node, onVisit) {
|
|
|
2169
2091
|
for (const statement of node.statements) {
|
|
2170
2092
|
walkAST(statement, onVisit);
|
|
2171
2093
|
}
|
|
2172
|
-
} else if (node instanceof TemplateStringNode) {
|
|
2173
|
-
for (const part of node.parts) {
|
|
2174
|
-
walkAST(part, onVisit);
|
|
2175
|
-
}
|
|
2176
2094
|
} else if (node instanceof AttributeAccessNode) {
|
|
2177
2095
|
walkAST(node.left, onVisit);
|
|
2178
|
-
if (node.right instanceof FunctionCallNode
|
|
2096
|
+
if (node.right instanceof FunctionCallNode) {
|
|
2179
2097
|
walkAST(node.right, onVisit);
|
|
2180
2098
|
}
|
|
2181
|
-
} else if (node instanceof PartialBinOpNode) {
|
|
2182
|
-
walkAST(node.left, onVisit);
|
|
2183
|
-
} else if (node instanceof PartialUnaryOpNode) ; else if (node instanceof PartialFunctionCallNode) {
|
|
2184
|
-
for (const arg of node.args) {
|
|
2185
|
-
walkAST(arg, onVisit);
|
|
2186
|
-
}
|
|
2187
|
-
} else if (node instanceof PartialParenNode) {
|
|
2188
|
-
walkAST(node.expr, onVisit);
|
|
2189
2099
|
}
|
|
2190
2100
|
}
|
|
2191
2101
|
function filterAST(ast, predicate) {
|
|
@@ -2245,7 +2155,7 @@ for (const val of Object.values(ReservedKeyword)) {
|
|
|
2245
2155
|
RESERVED_KEYWORD_STRINGS[val.toLowerCase()] = val;
|
|
2246
2156
|
}
|
|
2247
2157
|
var Lexer = class {
|
|
2248
|
-
constructor(text
|
|
2158
|
+
constructor(text) {
|
|
2249
2159
|
this.pos = 0;
|
|
2250
2160
|
this.line = 1;
|
|
2251
2161
|
this.column = 1;
|
|
@@ -2258,10 +2168,8 @@ var Lexer = class {
|
|
|
2258
2168
|
* @see docs/tokenscript/edge-cases/format-unit-parsing.md
|
|
2259
2169
|
*/
|
|
2260
2170
|
this._lastUnitableToken = null;
|
|
2261
|
-
this.collectedTokens = [];
|
|
2262
2171
|
this.text = text;
|
|
2263
|
-
this.currentChar = this.
|
|
2264
|
-
this.tolerant = options?.tolerant ?? false;
|
|
2172
|
+
this.currentChar = this.text[this.pos];
|
|
2265
2173
|
}
|
|
2266
2174
|
/**
|
|
2267
2175
|
* Check if a FORMAT token (unit suffix) is valid at the given position.
|
|
@@ -2297,7 +2205,7 @@ var Lexer = class {
|
|
|
2297
2205
|
}
|
|
2298
2206
|
}
|
|
2299
2207
|
peek(n = 1) {
|
|
2300
|
-
return this.text[this.pos + n]
|
|
2208
|
+
return this.text[this.pos + n];
|
|
2301
2209
|
}
|
|
2302
2210
|
skipWhitespace() {
|
|
2303
2211
|
while (isSpace(this.currentChar)) {
|
|
@@ -2405,9 +2313,6 @@ var Lexer = class {
|
|
|
2405
2313
|
let result = "";
|
|
2406
2314
|
while (this.currentChar !== null && this.currentChar !== "}") {
|
|
2407
2315
|
if (this.currentChar === "{") {
|
|
2408
|
-
if (this.tolerant) {
|
|
2409
|
-
break;
|
|
2410
|
-
}
|
|
2411
2316
|
this.error("LEXER_UNTERMINATED_REFERENCE" /* UNTERMINATED_REFERENCE */, {});
|
|
2412
2317
|
}
|
|
2413
2318
|
if (isSpace(this.currentChar)) {
|
|
@@ -2418,27 +2323,9 @@ var Lexer = class {
|
|
|
2418
2323
|
this.advance();
|
|
2419
2324
|
}
|
|
2420
2325
|
if (this.currentChar === null) {
|
|
2421
|
-
if (this.tolerant) {
|
|
2422
|
-
return {
|
|
2423
|
-
type: "PARTIAL_REFERENCE" /* PARTIAL_REFERENCE */,
|
|
2424
|
-
value: result,
|
|
2425
|
-
line: this.line,
|
|
2426
|
-
pos: refStartPos,
|
|
2427
|
-
endPos: this.pos
|
|
2428
|
-
};
|
|
2429
|
-
}
|
|
2430
2326
|
this.error("LEXER_UNTERMINATED_REFERENCE" /* UNTERMINATED_REFERENCE */, {});
|
|
2431
2327
|
}
|
|
2432
2328
|
if (result === "") {
|
|
2433
|
-
if (this.tolerant) {
|
|
2434
|
-
return {
|
|
2435
|
-
type: "PARTIAL_REFERENCE" /* PARTIAL_REFERENCE */,
|
|
2436
|
-
value: "",
|
|
2437
|
-
line: this.line,
|
|
2438
|
-
pos: refStartPos,
|
|
2439
|
-
endPos: this.pos
|
|
2440
|
-
};
|
|
2441
|
-
}
|
|
2442
2329
|
this.error("LEXER_EMPTY_VARIABLE_NAME" /* EMPTY_VARIABLE_NAME */, {});
|
|
2443
2330
|
}
|
|
2444
2331
|
const refEndPos = this.pos;
|
|
@@ -2462,15 +2349,6 @@ var Lexer = class {
|
|
|
2462
2349
|
this.advance();
|
|
2463
2350
|
}
|
|
2464
2351
|
if (this.currentChar === null) {
|
|
2465
|
-
if (this.tolerant) {
|
|
2466
|
-
return {
|
|
2467
|
-
type: "PARTIAL_STRING" /* PARTIAL_STRING */,
|
|
2468
|
-
value: result,
|
|
2469
|
-
line: this.line,
|
|
2470
|
-
pos: startPos,
|
|
2471
|
-
endPos: this.pos
|
|
2472
|
-
};
|
|
2473
|
-
}
|
|
2474
2352
|
this.error("LEXER_UNTERMINATED_STRING" /* UNTERMINATED_STRING */, { quoteType });
|
|
2475
2353
|
}
|
|
2476
2354
|
this.eat(quoteType);
|
|
@@ -2482,51 +2360,6 @@ var Lexer = class {
|
|
|
2482
2360
|
endPos: this.pos
|
|
2483
2361
|
};
|
|
2484
2362
|
}
|
|
2485
|
-
/**
|
|
2486
|
-
* Read a backtick-delimited template string.
|
|
2487
|
-
* Supports escape sequences: \{ \$ \` \\
|
|
2488
|
-
* The raw content (with escapes preserved) is stored as the token value.
|
|
2489
|
-
* The parser handles splitting into segments.
|
|
2490
|
-
*/
|
|
2491
|
-
templateString() {
|
|
2492
|
-
const startPos = this.pos;
|
|
2493
|
-
this.eat("`");
|
|
2494
|
-
let result = "";
|
|
2495
|
-
while (this.currentChar !== null && this.currentChar !== "`") {
|
|
2496
|
-
if (this.currentChar === "\\") {
|
|
2497
|
-
const next = this.peek();
|
|
2498
|
-
if (next === "{" || next === "$" || next === "`" || next === "\\") {
|
|
2499
|
-
result += "\\";
|
|
2500
|
-
result += next;
|
|
2501
|
-
this.advance();
|
|
2502
|
-
this.advance();
|
|
2503
|
-
continue;
|
|
2504
|
-
}
|
|
2505
|
-
}
|
|
2506
|
-
result += this.currentChar;
|
|
2507
|
-
this.advance();
|
|
2508
|
-
}
|
|
2509
|
-
if (this.currentChar === null) {
|
|
2510
|
-
if (this.tolerant) {
|
|
2511
|
-
return {
|
|
2512
|
-
type: "TEMPLATE_STRING" /* TEMPLATE_STRING */,
|
|
2513
|
-
value: result,
|
|
2514
|
-
line: this.line,
|
|
2515
|
-
pos: startPos,
|
|
2516
|
-
endPos: this.pos
|
|
2517
|
-
};
|
|
2518
|
-
}
|
|
2519
|
-
this.error("LEXER_UNTERMINATED_TEMPLATE_STRING" /* UNTERMINATED_TEMPLATE_STRING */, {});
|
|
2520
|
-
}
|
|
2521
|
-
this.eat("`");
|
|
2522
|
-
return {
|
|
2523
|
-
type: "TEMPLATE_STRING" /* TEMPLATE_STRING */,
|
|
2524
|
-
value: result,
|
|
2525
|
-
line: this.line,
|
|
2526
|
-
pos: startPos,
|
|
2527
|
-
endPos: this.pos
|
|
2528
|
-
};
|
|
2529
|
-
}
|
|
2530
2363
|
hexColor() {
|
|
2531
2364
|
const startPos = this.pos;
|
|
2532
2365
|
let result = "";
|
|
@@ -2535,15 +2368,6 @@ var Lexer = class {
|
|
|
2535
2368
|
this.advance();
|
|
2536
2369
|
}
|
|
2537
2370
|
if (result.length !== 4 && result.length !== 5 && result.length !== 7 && result.length !== 9) {
|
|
2538
|
-
if (this.tolerant) {
|
|
2539
|
-
return {
|
|
2540
|
-
type: "HEX_COLOR" /* HEX_COLOR */,
|
|
2541
|
-
value: result,
|
|
2542
|
-
line: this.line,
|
|
2543
|
-
pos: startPos,
|
|
2544
|
-
endPos: this.pos
|
|
2545
|
-
};
|
|
2546
|
-
}
|
|
2547
2371
|
this.error("LEXER_INVALID_HEX_COLOR_FORMAT" /* INVALID_HEX_COLOR_FORMAT */, {
|
|
2548
2372
|
value: result,
|
|
2549
2373
|
expectedLength: "#RGB, #RGBA, #RRGGBB, or #RRGGBBAA"
|
|
@@ -2557,12 +2381,6 @@ var Lexer = class {
|
|
|
2557
2381
|
endPos: this.pos
|
|
2558
2382
|
};
|
|
2559
2383
|
}
|
|
2560
|
-
collectToken(token) {
|
|
2561
|
-
if (this.tolerant) {
|
|
2562
|
-
this.collectedTokens.push(token);
|
|
2563
|
-
}
|
|
2564
|
-
return token;
|
|
2565
|
-
}
|
|
2566
2384
|
nextToken() {
|
|
2567
2385
|
while (this.currentChar !== null) {
|
|
2568
2386
|
this.skipWhitespace();
|
|
@@ -2572,130 +2390,127 @@ var Lexer = class {
|
|
|
2572
2390
|
continue;
|
|
2573
2391
|
}
|
|
2574
2392
|
if (this.isDigit()) {
|
|
2575
|
-
return this.
|
|
2393
|
+
return this.number();
|
|
2576
2394
|
}
|
|
2577
2395
|
if (this.currentChar === "'" || this.currentChar === '"') {
|
|
2578
|
-
return this.
|
|
2579
|
-
}
|
|
2580
|
-
if (this.currentChar === "`") {
|
|
2581
|
-
return this.collectToken(this.templateString());
|
|
2396
|
+
return this.explicitString(this.currentChar);
|
|
2582
2397
|
}
|
|
2583
2398
|
if (this.isValidIdentifierStart(this.currentChar)) {
|
|
2584
|
-
return this.
|
|
2399
|
+
return this.stringElement();
|
|
2585
2400
|
}
|
|
2586
2401
|
if (this.currentChar === "{") {
|
|
2587
|
-
return this.
|
|
2402
|
+
return this.reference();
|
|
2588
2403
|
}
|
|
2589
2404
|
if (this.currentChar === "[") {
|
|
2590
2405
|
const startPos = this.pos;
|
|
2591
2406
|
this.eat("[");
|
|
2592
|
-
return
|
|
2407
|
+
return {
|
|
2593
2408
|
type: "LBLOCK" /* LBLOCK */,
|
|
2594
2409
|
value: "[",
|
|
2595
2410
|
line: this.line,
|
|
2596
2411
|
pos: startPos,
|
|
2597
2412
|
endPos: this.pos
|
|
2598
|
-
}
|
|
2413
|
+
};
|
|
2599
2414
|
}
|
|
2600
2415
|
if (this.currentChar === "]") {
|
|
2601
2416
|
const startPos = this.pos;
|
|
2602
2417
|
this.eat("]");
|
|
2603
|
-
return
|
|
2418
|
+
return {
|
|
2604
2419
|
type: "RBLOCK" /* RBLOCK */,
|
|
2605
2420
|
value: "]",
|
|
2606
2421
|
line: this.line,
|
|
2607
2422
|
pos: startPos,
|
|
2608
2423
|
endPos: this.pos
|
|
2609
|
-
}
|
|
2424
|
+
};
|
|
2610
2425
|
}
|
|
2611
2426
|
if (this.currentChar === "!" && this.peek() === "=") {
|
|
2612
2427
|
const startPos = this.pos;
|
|
2613
2428
|
this.eat("!");
|
|
2614
2429
|
this.eat("=");
|
|
2615
|
-
return
|
|
2430
|
+
return {
|
|
2616
2431
|
type: "IS_NOT_EQ" /* IS_NOT_EQ */,
|
|
2617
2432
|
value: "!=",
|
|
2618
2433
|
line: this.line,
|
|
2619
2434
|
pos: startPos,
|
|
2620
2435
|
endPos: this.pos
|
|
2621
|
-
}
|
|
2436
|
+
};
|
|
2622
2437
|
}
|
|
2623
2438
|
if (this.currentChar === "+") {
|
|
2624
2439
|
const startPos = this.pos;
|
|
2625
2440
|
this.eat("+");
|
|
2626
|
-
return
|
|
2441
|
+
return {
|
|
2627
2442
|
type: "OPERATION" /* OPERATION */,
|
|
2628
2443
|
value: "+" /* ADD */,
|
|
2629
2444
|
line: this.line,
|
|
2630
2445
|
pos: startPos,
|
|
2631
2446
|
endPos: this.pos
|
|
2632
|
-
}
|
|
2447
|
+
};
|
|
2633
2448
|
}
|
|
2634
2449
|
if (this.currentChar === "-") {
|
|
2635
2450
|
const startPos = this.pos;
|
|
2636
2451
|
this.eat("-");
|
|
2637
|
-
return
|
|
2452
|
+
return {
|
|
2638
2453
|
type: "OPERATION" /* OPERATION */,
|
|
2639
2454
|
value: "-" /* SUBTRACT */,
|
|
2640
2455
|
line: this.line,
|
|
2641
2456
|
pos: startPos,
|
|
2642
2457
|
endPos: this.pos
|
|
2643
|
-
}
|
|
2458
|
+
};
|
|
2644
2459
|
}
|
|
2645
2460
|
if (this.currentChar === "*") {
|
|
2646
2461
|
const startPos = this.pos;
|
|
2647
2462
|
this.eat("*");
|
|
2648
|
-
return
|
|
2463
|
+
return {
|
|
2649
2464
|
type: "OPERATION" /* OPERATION */,
|
|
2650
2465
|
value: "*" /* MULTIPLY */,
|
|
2651
2466
|
line: this.line,
|
|
2652
2467
|
pos: startPos,
|
|
2653
2468
|
endPos: this.pos
|
|
2654
|
-
}
|
|
2469
|
+
};
|
|
2655
2470
|
}
|
|
2656
2471
|
if (this.currentChar === "/") {
|
|
2657
2472
|
const startPos = this.pos;
|
|
2658
2473
|
this.eat("/");
|
|
2659
|
-
return
|
|
2474
|
+
return {
|
|
2660
2475
|
type: "OPERATION" /* OPERATION */,
|
|
2661
2476
|
value: "/" /* DIVIDE */,
|
|
2662
2477
|
line: this.line,
|
|
2663
2478
|
pos: startPos,
|
|
2664
2479
|
endPos: this.pos
|
|
2665
|
-
}
|
|
2480
|
+
};
|
|
2666
2481
|
}
|
|
2667
2482
|
if (this.currentChar === "^") {
|
|
2668
2483
|
const startPos = this.pos;
|
|
2669
2484
|
this.eat("^");
|
|
2670
|
-
return
|
|
2485
|
+
return {
|
|
2671
2486
|
type: "OPERATION" /* OPERATION */,
|
|
2672
2487
|
value: "^" /* POWER */,
|
|
2673
2488
|
line: this.line,
|
|
2674
2489
|
pos: startPos,
|
|
2675
2490
|
endPos: this.pos
|
|
2676
|
-
}
|
|
2491
|
+
};
|
|
2677
2492
|
}
|
|
2678
2493
|
if (this.currentChar === "!") {
|
|
2679
2494
|
const startPos = this.pos;
|
|
2680
2495
|
this.eat("!");
|
|
2681
|
-
return
|
|
2496
|
+
return {
|
|
2682
2497
|
type: "OPERATION" /* OPERATION */,
|
|
2683
2498
|
value: "!" /* LOGIC_NOT */,
|
|
2684
2499
|
line: this.line,
|
|
2685
2500
|
pos: startPos,
|
|
2686
2501
|
endPos: this.pos
|
|
2687
|
-
}
|
|
2502
|
+
};
|
|
2688
2503
|
}
|
|
2689
2504
|
if (this.currentChar === "(") {
|
|
2690
2505
|
const startPos = this.pos;
|
|
2691
2506
|
this.eat("(");
|
|
2692
|
-
return
|
|
2507
|
+
return {
|
|
2693
2508
|
type: "LPAREN" /* LPAREN */,
|
|
2694
2509
|
value: "(",
|
|
2695
2510
|
line: this.line,
|
|
2696
2511
|
pos: startPos,
|
|
2697
2512
|
endPos: this.pos
|
|
2698
|
-
}
|
|
2513
|
+
};
|
|
2699
2514
|
}
|
|
2700
2515
|
if (this.currentChar === ")") {
|
|
2701
2516
|
const startPos = this.pos;
|
|
@@ -2708,162 +2523,158 @@ var Lexer = class {
|
|
|
2708
2523
|
endPos: this.pos
|
|
2709
2524
|
};
|
|
2710
2525
|
this._lastUnitableToken = token;
|
|
2711
|
-
return
|
|
2526
|
+
return token;
|
|
2712
2527
|
}
|
|
2713
2528
|
if (this.currentChar === ",") {
|
|
2714
2529
|
const startPos = this.pos;
|
|
2715
2530
|
this.eat(",");
|
|
2716
|
-
return
|
|
2531
|
+
return {
|
|
2717
2532
|
type: "COMMA" /* COMMA */,
|
|
2718
2533
|
value: ",",
|
|
2719
2534
|
line: this.line,
|
|
2720
2535
|
pos: startPos,
|
|
2721
2536
|
endPos: this.pos
|
|
2722
|
-
}
|
|
2537
|
+
};
|
|
2723
2538
|
}
|
|
2724
2539
|
if (this.currentChar === ".") {
|
|
2725
2540
|
if (this.peek() !== null && isNumber2(this.peek())) {
|
|
2726
|
-
return this.
|
|
2541
|
+
return this.number();
|
|
2727
2542
|
}
|
|
2728
2543
|
const startPos = this.pos;
|
|
2729
2544
|
this.eat(".");
|
|
2730
|
-
return
|
|
2545
|
+
return {
|
|
2731
2546
|
type: "DOT" /* DOT */,
|
|
2732
2547
|
value: ".",
|
|
2733
2548
|
line: this.line,
|
|
2734
2549
|
pos: startPos,
|
|
2735
2550
|
endPos: this.pos
|
|
2736
|
-
}
|
|
2551
|
+
};
|
|
2737
2552
|
}
|
|
2738
2553
|
if (this.currentChar === "#") {
|
|
2739
|
-
return this.
|
|
2554
|
+
return this.hexColor();
|
|
2740
2555
|
}
|
|
2741
2556
|
if (this.currentChar === "%") {
|
|
2742
2557
|
const startPos = this.pos;
|
|
2743
2558
|
this.eat("%");
|
|
2744
|
-
return
|
|
2559
|
+
return {
|
|
2745
2560
|
type: "FORMAT" /* FORMAT */,
|
|
2746
2561
|
value: "%" /* PERCENTAGE */,
|
|
2747
2562
|
line: this.line,
|
|
2748
2563
|
pos: startPos,
|
|
2749
2564
|
endPos: this.pos
|
|
2750
|
-
}
|
|
2565
|
+
};
|
|
2751
2566
|
}
|
|
2752
2567
|
if (this.currentChar === "=") {
|
|
2753
2568
|
const startPos = this.pos;
|
|
2754
2569
|
if (this.peek() === "=") {
|
|
2755
2570
|
this.eat("=");
|
|
2756
2571
|
this.eat("=");
|
|
2757
|
-
return
|
|
2572
|
+
return {
|
|
2758
2573
|
type: "IS_EQ" /* IS_EQ */,
|
|
2759
2574
|
value: "==",
|
|
2760
2575
|
line: this.line,
|
|
2761
2576
|
pos: startPos,
|
|
2762
2577
|
endPos: this.pos
|
|
2763
|
-
}
|
|
2578
|
+
};
|
|
2764
2579
|
}
|
|
2765
2580
|
this.eat("=");
|
|
2766
|
-
return
|
|
2581
|
+
return {
|
|
2767
2582
|
type: "ASSIGN" /* ASSIGN */,
|
|
2768
2583
|
value: "=",
|
|
2769
2584
|
line: this.line,
|
|
2770
2585
|
pos: startPos,
|
|
2771
2586
|
endPos: this.pos
|
|
2772
|
-
}
|
|
2587
|
+
};
|
|
2773
2588
|
}
|
|
2774
2589
|
if (this.currentChar === ">") {
|
|
2775
2590
|
const startPos = this.pos;
|
|
2776
2591
|
if (this.peek() === "=") {
|
|
2777
2592
|
this.eat(">");
|
|
2778
2593
|
this.eat("=");
|
|
2779
|
-
return
|
|
2594
|
+
return {
|
|
2780
2595
|
type: "IS_GT_EQ" /* IS_GT_EQ */,
|
|
2781
2596
|
value: ">=",
|
|
2782
2597
|
line: this.line,
|
|
2783
2598
|
pos: startPos,
|
|
2784
2599
|
endPos: this.pos
|
|
2785
|
-
}
|
|
2600
|
+
};
|
|
2786
2601
|
}
|
|
2787
2602
|
this.eat(">");
|
|
2788
|
-
return
|
|
2603
|
+
return {
|
|
2789
2604
|
type: "GT" /* IS_GT */,
|
|
2790
2605
|
value: ">",
|
|
2791
2606
|
line: this.line,
|
|
2792
2607
|
pos: startPos,
|
|
2793
2608
|
endPos: this.pos
|
|
2794
|
-
}
|
|
2609
|
+
};
|
|
2795
2610
|
}
|
|
2796
2611
|
if (this.currentChar === "<") {
|
|
2797
2612
|
const startPos = this.pos;
|
|
2798
2613
|
if (this.peek() === "=") {
|
|
2799
2614
|
this.eat("<");
|
|
2800
2615
|
this.eat("=");
|
|
2801
|
-
return
|
|
2616
|
+
return {
|
|
2802
2617
|
type: "IS_LT_EQ" /* IS_LT_EQ */,
|
|
2803
2618
|
value: "<=",
|
|
2804
2619
|
line: this.line,
|
|
2805
2620
|
pos: startPos,
|
|
2806
2621
|
endPos: this.pos
|
|
2807
|
-
}
|
|
2622
|
+
};
|
|
2808
2623
|
}
|
|
2809
2624
|
this.eat("<");
|
|
2810
|
-
return
|
|
2625
|
+
return {
|
|
2811
2626
|
type: "LT" /* IS_LT */,
|
|
2812
2627
|
value: "<",
|
|
2813
2628
|
line: this.line,
|
|
2814
2629
|
pos: startPos,
|
|
2815
2630
|
endPos: this.pos
|
|
2816
|
-
}
|
|
2631
|
+
};
|
|
2817
2632
|
}
|
|
2818
2633
|
if (this.currentChar === ";") {
|
|
2819
2634
|
const startPos = this.pos;
|
|
2820
2635
|
this.eat(";");
|
|
2821
|
-
return
|
|
2636
|
+
return {
|
|
2822
2637
|
type: "SEMICOLON" /* SEMICOLON */,
|
|
2823
2638
|
value: ";",
|
|
2824
2639
|
line: this.line,
|
|
2825
2640
|
pos: startPos,
|
|
2826
2641
|
endPos: this.pos
|
|
2827
|
-
}
|
|
2642
|
+
};
|
|
2828
2643
|
}
|
|
2829
2644
|
if (this.currentChar === "&" && this.peek() === "&") {
|
|
2830
2645
|
const startPos = this.pos;
|
|
2831
2646
|
this.eat("&");
|
|
2832
2647
|
this.eat("&");
|
|
2833
|
-
return
|
|
2648
|
+
return {
|
|
2834
2649
|
type: "LOGIC_AND" /* LOGIC_AND */,
|
|
2835
2650
|
value: "&&" /* LOGIC_AND */,
|
|
2836
2651
|
line: this.line,
|
|
2837
2652
|
pos: startPos,
|
|
2838
2653
|
endPos: this.pos
|
|
2839
|
-
}
|
|
2654
|
+
};
|
|
2840
2655
|
}
|
|
2841
2656
|
if (this.currentChar === "|" && this.peek() === "|") {
|
|
2842
2657
|
const startPos = this.pos;
|
|
2843
2658
|
this.eat("|");
|
|
2844
2659
|
this.eat("|");
|
|
2845
|
-
return
|
|
2660
|
+
return {
|
|
2846
2661
|
type: "LOGIC_OR" /* LOGIC_OR */,
|
|
2847
2662
|
value: "||" /* LOGIC_OR */,
|
|
2848
2663
|
line: this.line,
|
|
2849
2664
|
pos: startPos,
|
|
2850
2665
|
endPos: this.pos
|
|
2851
|
-
}
|
|
2666
|
+
};
|
|
2852
2667
|
}
|
|
2853
2668
|
if (this.currentChar === ":") {
|
|
2854
2669
|
const startPos = this.pos;
|
|
2855
2670
|
this.eat(":");
|
|
2856
|
-
return
|
|
2671
|
+
return {
|
|
2857
2672
|
type: "COLON" /* COLON */,
|
|
2858
2673
|
value: ":",
|
|
2859
2674
|
line: this.line,
|
|
2860
2675
|
pos: startPos,
|
|
2861
2676
|
endPos: this.pos
|
|
2862
|
-
}
|
|
2863
|
-
}
|
|
2864
|
-
if (this.tolerant) {
|
|
2865
|
-
this.advance();
|
|
2866
|
-
continue;
|
|
2677
|
+
};
|
|
2867
2678
|
}
|
|
2868
2679
|
const char = this.currentChar === null ? "end of input" : this.currentChar;
|
|
2869
2680
|
this.error("LEXER_INVALID_CHARACTER" /* INVALID_CHARACTER */, {
|
|
@@ -2871,48 +2682,18 @@ var Lexer = class {
|
|
|
2871
2682
|
position: this.pos
|
|
2872
2683
|
});
|
|
2873
2684
|
}
|
|
2874
|
-
|
|
2875
|
-
type: "EOF" /* EOF */,
|
|
2876
|
-
value: null,
|
|
2877
|
-
line: this.line,
|
|
2878
|
-
pos: this.pos,
|
|
2879
|
-
endPos: this.pos
|
|
2880
|
-
};
|
|
2881
|
-
return this.collectToken(eofToken);
|
|
2882
|
-
}
|
|
2883
|
-
/**
|
|
2884
|
-
* Get all tokens that have been collected during tokenization.
|
|
2885
|
-
* This is useful for tolerant parsing to get all tokens including partial ones.
|
|
2886
|
-
*/
|
|
2887
|
-
getAllTokens() {
|
|
2888
|
-
return [...this.collectedTokens];
|
|
2889
|
-
}
|
|
2890
|
-
/**
|
|
2891
|
-
* Tokenize the entire input and return all tokens.
|
|
2892
|
-
* This is a convenience method for tolerant parsing.
|
|
2893
|
-
*/
|
|
2894
|
-
tokenizeAll() {
|
|
2895
|
-
const tokens = [];
|
|
2896
|
-
let token = this.nextToken();
|
|
2897
|
-
while (token.type !== "EOF" /* EOF */) {
|
|
2898
|
-
tokens.push(token);
|
|
2899
|
-
token = this.nextToken();
|
|
2900
|
-
}
|
|
2901
|
-
tokens.push(token);
|
|
2902
|
-
return tokens;
|
|
2685
|
+
return { type: "EOF" /* EOF */, value: null, line: this.line, pos: this.pos, endPos: this.pos };
|
|
2903
2686
|
}
|
|
2904
2687
|
peekToken() {
|
|
2905
2688
|
const savedPos = this.pos;
|
|
2906
2689
|
const savedChar = this.currentChar;
|
|
2907
2690
|
const savedLine = this.line;
|
|
2908
2691
|
const savedColumn = this.column;
|
|
2909
|
-
const savedCollectedLength = this.collectedTokens.length;
|
|
2910
2692
|
const nextToken = this.nextToken();
|
|
2911
2693
|
this.pos = savedPos;
|
|
2912
2694
|
this.currentChar = savedChar;
|
|
2913
2695
|
this.line = savedLine;
|
|
2914
2696
|
this.column = savedColumn;
|
|
2915
|
-
this.collectedTokens.length = savedCollectedLength;
|
|
2916
2697
|
return nextToken.type === "EOF" /* EOF */ ? null : nextToken;
|
|
2917
2698
|
}
|
|
2918
2699
|
peekTokens(n) {
|
|
@@ -2920,7 +2701,6 @@ var Lexer = class {
|
|
|
2920
2701
|
const savedChar = this.currentChar;
|
|
2921
2702
|
const savedLine = this.line;
|
|
2922
2703
|
const savedColumn = this.column;
|
|
2923
|
-
const savedCollectedLength = this.collectedTokens.length;
|
|
2924
2704
|
const tokens = [];
|
|
2925
2705
|
for (let i = 0; i < n; i++) {
|
|
2926
2706
|
const token = this.nextToken();
|
|
@@ -2933,7 +2713,6 @@ var Lexer = class {
|
|
|
2933
2713
|
this.currentChar = savedChar;
|
|
2934
2714
|
this.line = savedLine;
|
|
2935
2715
|
this.column = savedColumn;
|
|
2936
|
-
this.collectedTokens.length = savedCollectedLength;
|
|
2937
2716
|
return tokens.length > 0 ? tokens : null;
|
|
2938
2717
|
}
|
|
2939
2718
|
isEOF() {
|
|
@@ -2956,41 +2735,11 @@ var Lexer = class {
|
|
|
2956
2735
|
};
|
|
2957
2736
|
|
|
2958
2737
|
// src/interpreter/parser.ts
|
|
2959
|
-
var Parser = class
|
|
2960
|
-
constructor(lexer
|
|
2738
|
+
var Parser = class {
|
|
2739
|
+
constructor(lexer) {
|
|
2961
2740
|
this.requiredReferences = /* @__PURE__ */ new Set();
|
|
2962
|
-
this.incompleteInfo = [];
|
|
2963
2741
|
this.lexer = lexer;
|
|
2964
2742
|
this.currentToken = this.lexer.nextToken();
|
|
2965
|
-
this.tolerant = options?.tolerant ?? false;
|
|
2966
|
-
}
|
|
2967
|
-
/**
|
|
2968
|
-
* In tolerant mode, check if the current token is EOF after consuming an operator.
|
|
2969
|
-
* If so, record the incomplete info and return a PartialBinOpNode.
|
|
2970
|
-
* Returns null if not at EOF or not in tolerant mode.
|
|
2971
|
-
*/
|
|
2972
|
-
tryRecoverMissingOperand(left, opToken) {
|
|
2973
|
-
if (this.tolerant && this.currentToken.type === "EOF" /* EOF */) {
|
|
2974
|
-
this.incompleteInfo.push({
|
|
2975
|
-
type: "missing_operand" /* MISSING_OPERAND */,
|
|
2976
|
-
startPos: opToken.pos,
|
|
2977
|
-
endPos: opToken.endPos
|
|
2978
|
-
});
|
|
2979
|
-
return new PartialBinOpNode(left, opToken);
|
|
2980
|
-
}
|
|
2981
|
-
return null;
|
|
2982
|
-
}
|
|
2983
|
-
/**
|
|
2984
|
-
* Check if the parser encountered any incomplete constructs
|
|
2985
|
-
*/
|
|
2986
|
-
hasIncomplete() {
|
|
2987
|
-
return this.incompleteInfo.length > 0;
|
|
2988
|
-
}
|
|
2989
|
-
/**
|
|
2990
|
-
* Get information about incomplete constructs
|
|
2991
|
-
*/
|
|
2992
|
-
getIncomplete() {
|
|
2993
|
-
return [...this.incompleteInfo];
|
|
2994
2743
|
}
|
|
2995
2744
|
formatError(message, token = this.currentToken) {
|
|
2996
2745
|
const {
|
|
@@ -3114,8 +2863,6 @@ ${contextText}`;
|
|
|
3114
2863
|
return this.returnStatement();
|
|
3115
2864
|
case "while" /* WHILE */:
|
|
3116
2865
|
return this.whileStatement();
|
|
3117
|
-
case "for" /* FOR */:
|
|
3118
|
-
return this.forStatement();
|
|
3119
2866
|
case "if" /* IF */:
|
|
3120
2867
|
return this.ifStatement();
|
|
3121
2868
|
case "variable" /* VARIABLE */:
|
|
@@ -3171,18 +2918,7 @@ ${contextText}`;
|
|
|
3171
2918
|
return new ReassignNode(name, assignmentExpr, varNameToken);
|
|
3172
2919
|
}
|
|
3173
2920
|
reference() {
|
|
3174
|
-
const
|
|
3175
|
-
if (token.type === "PARTIAL_REFERENCE" /* PARTIAL_REFERENCE */) {
|
|
3176
|
-
this.eat("PARTIAL_REFERENCE" /* PARTIAL_REFERENCE */);
|
|
3177
|
-
this.incompleteInfo.push({
|
|
3178
|
-
type: "unclosed_reference" /* UNCLOSED_REFERENCE */,
|
|
3179
|
-
startPos: token.pos,
|
|
3180
|
-
endPos: token.endPos,
|
|
3181
|
-
partialValue: token.value
|
|
3182
|
-
});
|
|
3183
|
-
return new PartialReferenceNode(token.value, token);
|
|
3184
|
-
}
|
|
3185
|
-
const node = new ReferenceNode(token);
|
|
2921
|
+
const node = new ReferenceNode(this.currentToken);
|
|
3186
2922
|
this.eat("REFERENCE" /* REFERENCE */);
|
|
3187
2923
|
this.requiredReferences.add(node.value);
|
|
3188
2924
|
if (this.currentToken.type === "FORMAT" /* FORMAT */) {
|
|
@@ -3195,8 +2931,6 @@ ${contextText}`;
|
|
|
3195
2931
|
let node = this.logicTerm();
|
|
3196
2932
|
while (this.currentToken.type === "LOGIC_AND" /* LOGIC_AND */ || this.currentToken.type === "LOGIC_OR" /* LOGIC_OR */) {
|
|
3197
2933
|
const token = this.eat(this.currentToken.type);
|
|
3198
|
-
const partial = this.tryRecoverMissingOperand(node, token);
|
|
3199
|
-
if (partial) return partial;
|
|
3200
2934
|
node = new BinOpNode(node, token, this.logicTerm());
|
|
3201
2935
|
}
|
|
3202
2936
|
return node;
|
|
@@ -3225,48 +2959,6 @@ ${contextText}`;
|
|
|
3225
2959
|
const body = this.block();
|
|
3226
2960
|
return new WhileNode(condition, body.statements, whileToken);
|
|
3227
2961
|
}
|
|
3228
|
-
forStatement() {
|
|
3229
|
-
const forToken = this.eat("RESERVED_KEYWORD" /* RESERVED_KEYWORD */);
|
|
3230
|
-
if (!this.isIdentifierToken()) {
|
|
3231
|
-
throw new ParserError("PARSER_EXPECTED_TOKEN_TYPE" /* EXPECTED_TOKEN_TYPE */, {
|
|
3232
|
-
token: this.currentToken,
|
|
3233
|
-
data: { expectedType: "identifier", actualType: this.currentToken.type }
|
|
3234
|
-
});
|
|
3235
|
-
}
|
|
3236
|
-
const firstVar = this.currentToken.value;
|
|
3237
|
-
this.eat(this.currentToken.type);
|
|
3238
|
-
let indexVar = null;
|
|
3239
|
-
if (this.currentToken.type === "COMMA" /* COMMA */) {
|
|
3240
|
-
this.eat("COMMA" /* COMMA */);
|
|
3241
|
-
if (!this.isIdentifierToken()) {
|
|
3242
|
-
throw new ParserError("PARSER_EXPECTED_TOKEN_TYPE" /* EXPECTED_TOKEN_TYPE */, {
|
|
3243
|
-
token: this.currentToken,
|
|
3244
|
-
data: { expectedType: "identifier", actualType: this.currentToken.type }
|
|
3245
|
-
});
|
|
3246
|
-
}
|
|
3247
|
-
indexVar = this.currentToken.value;
|
|
3248
|
-
this.eat(this.currentToken.type);
|
|
3249
|
-
}
|
|
3250
|
-
if (!this.isIdentifierToken() || this.currentToken.value !== "in") {
|
|
3251
|
-
throw new ParserError("PARSER_EXPECTED_TOKEN_TYPE" /* EXPECTED_TOKEN_TYPE */, {
|
|
3252
|
-
token: this.currentToken,
|
|
3253
|
-
data: { expectedType: "'in'", actualType: this.currentToken.value }
|
|
3254
|
-
});
|
|
3255
|
-
}
|
|
3256
|
-
this.eat(this.currentToken.type);
|
|
3257
|
-
const collection = this.expr();
|
|
3258
|
-
const body = this.block();
|
|
3259
|
-
if (this.currentToken.type === "SEMICOLON" /* SEMICOLON */) {
|
|
3260
|
-
this.eat("SEMICOLON" /* SEMICOLON */);
|
|
3261
|
-
}
|
|
3262
|
-
return new ForEachNode(
|
|
3263
|
-
firstVar,
|
|
3264
|
-
indexVar,
|
|
3265
|
-
collection,
|
|
3266
|
-
body.statements,
|
|
3267
|
-
forToken
|
|
3268
|
-
);
|
|
3269
|
-
}
|
|
3270
2962
|
ifStatement() {
|
|
3271
2963
|
const ifToken = this.eat("RESERVED_KEYWORD" /* RESERVED_KEYWORD */);
|
|
3272
2964
|
this.eat("LPAREN" /* LPAREN */);
|
|
@@ -3295,21 +2987,6 @@ ${contextText}`;
|
|
|
3295
2987
|
this.eat("RBLOCK" /* RBLOCK */);
|
|
3296
2988
|
return new BlockNode(statements);
|
|
3297
2989
|
}
|
|
3298
|
-
// Explicit list literal: [expr, expr, ...]
|
|
3299
|
-
explicitList() {
|
|
3300
|
-
const token = this.currentToken;
|
|
3301
|
-
this.eat("LBLOCK" /* LBLOCK */);
|
|
3302
|
-
const elements = [];
|
|
3303
|
-
if (this.currentToken.type !== "RBLOCK" /* RBLOCK */) {
|
|
3304
|
-
elements.push(this.expr());
|
|
3305
|
-
while (this.currentToken.type === "COMMA" /* COMMA */) {
|
|
3306
|
-
this.eat("COMMA" /* COMMA */);
|
|
3307
|
-
elements.push(this.expr());
|
|
3308
|
-
}
|
|
3309
|
-
}
|
|
3310
|
-
this.eat("RBLOCK" /* RBLOCK */);
|
|
3311
|
-
return new ListNode(elements, token);
|
|
3312
|
-
}
|
|
3313
2990
|
// implicit_list_expr : factor ((COMMA) factor)*
|
|
3314
2991
|
implicitListExpr() {
|
|
3315
2992
|
const token = this.currentToken;
|
|
@@ -3338,8 +3015,6 @@ ${contextText}`;
|
|
|
3338
3015
|
let node = this.comparison();
|
|
3339
3016
|
while (this.currentToken.type === "OPERATION" /* OPERATION */ && (this.currentToken.value === "+" /* ADD */ || this.currentToken.value === "-" /* SUBTRACT */)) {
|
|
3340
3017
|
const token = this.eat("OPERATION" /* OPERATION */);
|
|
3341
|
-
const partial = this.tryRecoverMissingOperand(node, token);
|
|
3342
|
-
if (partial) return partial;
|
|
3343
3018
|
node = new BinOpNode(node, token, this.comparison());
|
|
3344
3019
|
}
|
|
3345
3020
|
return node;
|
|
@@ -3349,8 +3024,6 @@ ${contextText}`;
|
|
|
3349
3024
|
let node = this.term();
|
|
3350
3025
|
while (this.currentToken.type === "IS_EQ" /* IS_EQ */ || this.currentToken.type === "IS_NOT_EQ" /* IS_NOT_EQ */ || this.currentToken.type === "GT" /* IS_GT */ || this.currentToken.type === "LT" /* IS_LT */ || this.currentToken.type === "IS_GT_EQ" /* IS_GT_EQ */ || this.currentToken.type === "IS_LT_EQ" /* IS_LT_EQ */) {
|
|
3351
3026
|
const token = this.eat(this.currentToken.type);
|
|
3352
|
-
const partial = this.tryRecoverMissingOperand(node, token);
|
|
3353
|
-
if (partial) return partial;
|
|
3354
3027
|
node = new BinOpNode(node, token, this.term());
|
|
3355
3028
|
}
|
|
3356
3029
|
return node;
|
|
@@ -3360,8 +3033,6 @@ ${contextText}`;
|
|
|
3360
3033
|
let node = this.power();
|
|
3361
3034
|
while (this.currentToken.type === "OPERATION" /* OPERATION */ && (this.currentToken.value === "*" /* MULTIPLY */ || this.currentToken.value === "/" /* DIVIDE */)) {
|
|
3362
3035
|
const token = this.eat("OPERATION" /* OPERATION */);
|
|
3363
|
-
const partial = this.tryRecoverMissingOperand(node, token);
|
|
3364
|
-
if (partial) return partial;
|
|
3365
3036
|
node = new BinOpNode(node, token, this.power());
|
|
3366
3037
|
}
|
|
3367
3038
|
return node;
|
|
@@ -3371,8 +3042,6 @@ ${contextText}`;
|
|
|
3371
3042
|
let node = this.factor();
|
|
3372
3043
|
while (this.currentToken.type === "OPERATION" /* OPERATION */ && this.currentToken.value === "^" /* POWER */) {
|
|
3373
3044
|
const token = this.eat("OPERATION" /* OPERATION */);
|
|
3374
|
-
const partial = this.tryRecoverMissingOperand(node, token);
|
|
3375
|
-
if (partial) return partial;
|
|
3376
3045
|
node = new BinOpNode(node, token, this.factor());
|
|
3377
3046
|
}
|
|
3378
3047
|
return node;
|
|
@@ -3401,19 +3070,8 @@ ${contextText}`;
|
|
|
3401
3070
|
// | HEX_COLOR
|
|
3402
3071
|
factor() {
|
|
3403
3072
|
const token = this.currentToken;
|
|
3404
|
-
if (token.type === "LBLOCK" /* LBLOCK */) {
|
|
3405
|
-
return this.explicitList();
|
|
3406
|
-
}
|
|
3407
3073
|
if (token.type === "OPERATION" /* OPERATION */ && (token.value === "+" /* ADD */ || token.value === "-" /* SUBTRACT */ || token.value === "!" /* LOGIC_NOT */)) {
|
|
3408
3074
|
this.eat("OPERATION" /* OPERATION */);
|
|
3409
|
-
if (this.tolerant && this.currentToken.type === "EOF" /* EOF */) {
|
|
3410
|
-
this.incompleteInfo.push({
|
|
3411
|
-
type: "missing_operand" /* MISSING_OPERAND */,
|
|
3412
|
-
startPos: token.pos,
|
|
3413
|
-
endPos: token.endPos
|
|
3414
|
-
});
|
|
3415
|
-
return new PartialUnaryOpNode(token);
|
|
3416
|
-
}
|
|
3417
3075
|
return new UnaryOpNode(token, this.factor());
|
|
3418
3076
|
}
|
|
3419
3077
|
if (token.type === "RESERVED_KEYWORD" /* RESERVED_KEYWORD */ && (token.value === "true" /* TRUE */ || token.value === "false" /* FALSE */)) {
|
|
@@ -3428,34 +3086,14 @@ ${contextText}`;
|
|
|
3428
3086
|
return this.number();
|
|
3429
3087
|
}
|
|
3430
3088
|
if (token.type === "LPAREN" /* LPAREN */) {
|
|
3431
|
-
const lparenToken = token;
|
|
3432
3089
|
this.eat("LPAREN" /* LPAREN */);
|
|
3433
|
-
if (this.tolerant && this.currentToken.type === "EOF" /* EOF */) {
|
|
3434
|
-
this.incompleteInfo.push({
|
|
3435
|
-
type: "unclosed_paren" /* UNCLOSED_PAREN */,
|
|
3436
|
-
startPos: lparenToken.pos
|
|
3437
|
-
});
|
|
3438
|
-
return new PartialParenNode(new NullNode(lparenToken), lparenToken);
|
|
3439
|
-
}
|
|
3440
3090
|
const node = this.expr();
|
|
3441
|
-
if (this.tolerant && this.currentToken.type === "EOF" /* EOF */) {
|
|
3442
|
-
this.incompleteInfo.push({
|
|
3443
|
-
type: "unclosed_paren" /* UNCLOSED_PAREN */,
|
|
3444
|
-
startPos: lparenToken.pos
|
|
3445
|
-
});
|
|
3446
|
-
return new PartialParenNode(node, lparenToken);
|
|
3447
|
-
}
|
|
3448
3091
|
this.eat("RPAREN" /* RPAREN */);
|
|
3449
3092
|
if (this.currentToken.type === "FORMAT" /* FORMAT */) {
|
|
3450
3093
|
return this.format(node);
|
|
3451
3094
|
}
|
|
3452
3095
|
return node;
|
|
3453
3096
|
}
|
|
3454
|
-
if (token.type === "PARTIAL_REFERENCE" /* PARTIAL_REFERENCE */) {
|
|
3455
|
-
let node = this.reference();
|
|
3456
|
-
node = this.attributeAccess(node);
|
|
3457
|
-
return node;
|
|
3458
|
-
}
|
|
3459
3097
|
if (token.type === "REFERENCE" /* REFERENCE */) {
|
|
3460
3098
|
let node = this.reference();
|
|
3461
3099
|
node = this.attributeAccess(node);
|
|
@@ -3465,18 +3103,6 @@ ${contextText}`;
|
|
|
3465
3103
|
this.eat("HEX_COLOR" /* HEX_COLOR */);
|
|
3466
3104
|
return new HexColorNode(token);
|
|
3467
3105
|
}
|
|
3468
|
-
if (token.type === "PARTIAL_STRING" /* PARTIAL_STRING */) {
|
|
3469
|
-
this.eat("PARTIAL_STRING" /* PARTIAL_STRING */);
|
|
3470
|
-
const sourceText = this.lexer.getSourceInfo().text;
|
|
3471
|
-
const quoteType = sourceText[token.pos] ?? '"';
|
|
3472
|
-
this.incompleteInfo.push({
|
|
3473
|
-
type: "unclosed_string" /* UNCLOSED_STRING */,
|
|
3474
|
-
startPos: token.pos,
|
|
3475
|
-
endPos: token.endPos,
|
|
3476
|
-
partialValue: token.value
|
|
3477
|
-
});
|
|
3478
|
-
return new PartialStringNode(token.value, quoteType, token);
|
|
3479
|
-
}
|
|
3480
3106
|
if (this.isIdentifierToken(token)) {
|
|
3481
3107
|
this.eat(token.type);
|
|
3482
3108
|
let node;
|
|
@@ -3488,39 +3114,27 @@ ${contextText}`;
|
|
|
3488
3114
|
node = this.attributeAccess(node);
|
|
3489
3115
|
return node;
|
|
3490
3116
|
}
|
|
3491
|
-
if (token.type === "TEMPLATE_STRING" /* TEMPLATE_STRING */) {
|
|
3492
|
-
return this.templateString();
|
|
3493
|
-
}
|
|
3494
3117
|
if (token.type === "EXPLICIT_STRING" /* EXPLICIT_STRING */) {
|
|
3495
3118
|
this.eat("EXPLICIT_STRING" /* EXPLICIT_STRING */);
|
|
3496
3119
|
let node = new StringNode(token);
|
|
3497
3120
|
node = this.attributeAccess(node);
|
|
3498
3121
|
return node;
|
|
3499
3122
|
}
|
|
3500
|
-
if (this.tolerant && token.type === "EOF" /* EOF */) {
|
|
3501
|
-
return new NullNode(token);
|
|
3502
|
-
}
|
|
3503
3123
|
this.error("PARSER_UNEXPECTED_TOKEN" /* UNEXPECTED_TOKEN */, { token: String(token.value) });
|
|
3504
3124
|
}
|
|
3505
3125
|
attributeAccess(leftNode) {
|
|
3506
3126
|
let node = leftNode;
|
|
3507
3127
|
while (this.currentToken.type === "DOT" /* DOT */) {
|
|
3508
|
-
|
|
3509
|
-
if (this.tolerant && this.currentToken.type === "EOF" /* EOF */) {
|
|
3510
|
-
this.incompleteInfo.push({
|
|
3511
|
-
type: "trailing_dot" /* TRAILING_DOT */,
|
|
3512
|
-
startPos: dotToken.pos,
|
|
3513
|
-
endPos: dotToken.endPos
|
|
3514
|
-
});
|
|
3515
|
-
break;
|
|
3516
|
-
}
|
|
3128
|
+
this.eat("DOT" /* DOT */);
|
|
3517
3129
|
if (this.isIdentifierToken()) {
|
|
3518
3130
|
const nextToken = this.lexer.peekToken();
|
|
3519
3131
|
if (nextToken && nextToken.type === "LPAREN" /* LPAREN */) {
|
|
3520
3132
|
const methodName = this.currentToken.value;
|
|
3521
3133
|
this.eat(this.currentToken.type);
|
|
3522
|
-
|
|
3523
|
-
|
|
3134
|
+
node = new AttributeAccessNode(
|
|
3135
|
+
node,
|
|
3136
|
+
this.functionCall({ ...this.currentToken, value: methodName })
|
|
3137
|
+
);
|
|
3524
3138
|
} else {
|
|
3525
3139
|
const attrToken = this.currentToken;
|
|
3526
3140
|
this.eat(this.currentToken.type);
|
|
@@ -3534,14 +3148,6 @@ ${contextText}`;
|
|
|
3534
3148
|
this.eat("LPAREN" /* LPAREN */);
|
|
3535
3149
|
const args = [];
|
|
3536
3150
|
while (this.currentToken.type !== "RPAREN" /* RPAREN */) {
|
|
3537
|
-
if (this.tolerant && this.currentToken.type === "EOF" /* EOF */) {
|
|
3538
|
-
this.incompleteInfo.push({
|
|
3539
|
-
type: "unclosed_function" /* UNCLOSED_FUNCTION */,
|
|
3540
|
-
startPos: functionName.pos,
|
|
3541
|
-
partialValue: functionName.value
|
|
3542
|
-
});
|
|
3543
|
-
return new PartialFunctionCallNode(functionName.value, args, functionName);
|
|
3544
|
-
}
|
|
3545
3151
|
if (this.currentToken.type === "COMMA" /* COMMA */) {
|
|
3546
3152
|
this.eat("COMMA" /* COMMA */);
|
|
3547
3153
|
}
|
|
@@ -3550,126 +3156,7 @@ ${contextText}`;
|
|
|
3550
3156
|
this.eat("RPAREN" /* RPAREN */);
|
|
3551
3157
|
return new FunctionCallNode(functionName.value, args, functionName);
|
|
3552
3158
|
}
|
|
3553
|
-
/**
|
|
3554
|
-
* Parse a TEMPLATE_STRING token into a TemplateStringNode.
|
|
3555
|
-
* Scans the raw content for:
|
|
3556
|
-
* - {ref.path} → ReferenceNode
|
|
3557
|
-
* - ${expression} → parsed sub-expression
|
|
3558
|
-
* - \{ \${ \` \\ → escaped literals (backslash removed)
|
|
3559
|
-
* - everything else → literal StringNode segments
|
|
3560
|
-
*/
|
|
3561
|
-
templateString() {
|
|
3562
|
-
const token = this.currentToken;
|
|
3563
|
-
const raw = token.value;
|
|
3564
|
-
this.eat("TEMPLATE_STRING" /* TEMPLATE_STRING */);
|
|
3565
|
-
const parts = [];
|
|
3566
|
-
let literal = "";
|
|
3567
|
-
let i = 0;
|
|
3568
|
-
const flushLiteral = () => {
|
|
3569
|
-
if (literal.length > 0) {
|
|
3570
|
-
parts.push(new StringNode({ ...token, value: literal }));
|
|
3571
|
-
literal = "";
|
|
3572
|
-
}
|
|
3573
|
-
};
|
|
3574
|
-
while (i < raw.length) {
|
|
3575
|
-
const ch = raw[i];
|
|
3576
|
-
if (ch === "\\" && i + 1 < raw.length) {
|
|
3577
|
-
const next = raw[i + 1];
|
|
3578
|
-
if (next === "{" || next === "`" || next === "\\") {
|
|
3579
|
-
literal += next;
|
|
3580
|
-
i += 2;
|
|
3581
|
-
continue;
|
|
3582
|
-
}
|
|
3583
|
-
if (next === "$") {
|
|
3584
|
-
if (i + 2 < raw.length && raw[i + 2] === "{") {
|
|
3585
|
-
literal += "${";
|
|
3586
|
-
i += 3;
|
|
3587
|
-
} else {
|
|
3588
|
-
literal += "$";
|
|
3589
|
-
i += 2;
|
|
3590
|
-
}
|
|
3591
|
-
continue;
|
|
3592
|
-
}
|
|
3593
|
-
}
|
|
3594
|
-
if (ch === "$" && i + 1 < raw.length && raw[i + 1] === "{") {
|
|
3595
|
-
flushLiteral();
|
|
3596
|
-
const start = i + 2;
|
|
3597
|
-
let depth = 1;
|
|
3598
|
-
let j = start;
|
|
3599
|
-
while (j < raw.length && depth > 0) {
|
|
3600
|
-
if (raw[j] === "`") {
|
|
3601
|
-
this.error("PARSER_INVALID_SYNTAX" /* INVALID_SYNTAX */, {
|
|
3602
|
-
message: "Nested template strings are not allowed inside ${...}"
|
|
3603
|
-
});
|
|
3604
|
-
}
|
|
3605
|
-
if (raw[j] === "{") depth++;
|
|
3606
|
-
else if (raw[j] === "}") depth--;
|
|
3607
|
-
if (depth > 0) j++;
|
|
3608
|
-
}
|
|
3609
|
-
if (depth !== 0) {
|
|
3610
|
-
this.error("PARSER_INVALID_SYNTAX" /* INVALID_SYNTAX */, {
|
|
3611
|
-
message: "Unterminated ${...} in template string"
|
|
3612
|
-
});
|
|
3613
|
-
}
|
|
3614
|
-
const exprStr = raw.slice(start, j);
|
|
3615
|
-
const subLexer = new Lexer(exprStr);
|
|
3616
|
-
const subParser = new _Parser(subLexer);
|
|
3617
|
-
const exprNode = subParser.expr();
|
|
3618
|
-
for (const ref of subParser.requiredReferences) {
|
|
3619
|
-
this.requiredReferences.add(ref);
|
|
3620
|
-
}
|
|
3621
|
-
parts.push(exprNode);
|
|
3622
|
-
i = j + 1;
|
|
3623
|
-
continue;
|
|
3624
|
-
}
|
|
3625
|
-
if (ch === "{") {
|
|
3626
|
-
flushLiteral();
|
|
3627
|
-
const start = i + 1;
|
|
3628
|
-
let j = start;
|
|
3629
|
-
while (j < raw.length && raw[j] !== "}") {
|
|
3630
|
-
if (raw[j] === "{") {
|
|
3631
|
-
this.error("PARSER_INVALID_SYNTAX" /* INVALID_SYNTAX */, {
|
|
3632
|
-
message: "Nested braces in template reference"
|
|
3633
|
-
});
|
|
3634
|
-
}
|
|
3635
|
-
j++;
|
|
3636
|
-
}
|
|
3637
|
-
if (j >= raw.length) {
|
|
3638
|
-
this.error("PARSER_INVALID_SYNTAX" /* INVALID_SYNTAX */, {
|
|
3639
|
-
message: "Unterminated {ref} in template string"
|
|
3640
|
-
});
|
|
3641
|
-
}
|
|
3642
|
-
let refPath = raw.slice(start, j);
|
|
3643
|
-
refPath = refPath.replace(/[ \t]/g, "");
|
|
3644
|
-
if (refPath.length === 0) {
|
|
3645
|
-
this.error("PARSER_INVALID_SYNTAX" /* INVALID_SYNTAX */, {
|
|
3646
|
-
message: "Empty reference in template string"
|
|
3647
|
-
});
|
|
3648
|
-
}
|
|
3649
|
-
this.requiredReferences.add(refPath);
|
|
3650
|
-
parts.push(
|
|
3651
|
-
new ReferenceNode({
|
|
3652
|
-
...token,
|
|
3653
|
-
type: "REFERENCE" /* REFERENCE */,
|
|
3654
|
-
value: refPath
|
|
3655
|
-
})
|
|
3656
|
-
);
|
|
3657
|
-
i = j + 1;
|
|
3658
|
-
continue;
|
|
3659
|
-
}
|
|
3660
|
-
literal += ch;
|
|
3661
|
-
i++;
|
|
3662
|
-
}
|
|
3663
|
-
flushLiteral();
|
|
3664
|
-
if (parts.length === 1 && parts[0] instanceof StringNode) {
|
|
3665
|
-
return parts[0];
|
|
3666
|
-
}
|
|
3667
|
-
return new TemplateStringNode(parts, token);
|
|
3668
|
-
}
|
|
3669
3159
|
parse(inlineMode = false) {
|
|
3670
|
-
if (this.tolerant && !inlineMode) {
|
|
3671
|
-
this.error("PARSER_TOLERANT_REQUIRES_INLINE" /* TOLERANT_REQUIRES_INLINE */);
|
|
3672
|
-
}
|
|
3673
3160
|
if (this.currentToken.type === "EOF" /* EOF */) return null;
|
|
3674
3161
|
if (inlineMode) return this.listExpr();
|
|
3675
3162
|
const node = this.statementsList();
|
|
@@ -3715,11 +3202,49 @@ function renameReferences(originalValue, ast, renameMap) {
|
|
|
3715
3202
|
}
|
|
3716
3203
|
return result;
|
|
3717
3204
|
}
|
|
3718
|
-
var
|
|
3719
|
-
|
|
3720
|
-
|
|
3205
|
+
var ScriptBlockSchema = type({
|
|
3206
|
+
type: "string",
|
|
3207
|
+
script: "string"
|
|
3208
|
+
});
|
|
3209
|
+
var InitializerSchema = type({
|
|
3210
|
+
"title?": "string",
|
|
3211
|
+
keyword: "string",
|
|
3212
|
+
"description?": "string",
|
|
3213
|
+
// schema: type({ "...": "unknown" }),
|
|
3214
|
+
script: ScriptBlockSchema
|
|
3215
|
+
});
|
|
3216
|
+
var ConversionSchema = type({
|
|
3217
|
+
source: "string",
|
|
3218
|
+
target: "string",
|
|
3219
|
+
"description?": "string",
|
|
3220
|
+
lossless: "boolean",
|
|
3221
|
+
script: ScriptBlockSchema
|
|
3222
|
+
});
|
|
3721
3223
|
var validSchemaTypes = ["number", "string", "color"];
|
|
3722
|
-
|
|
3224
|
+
type({
|
|
3225
|
+
type: "'number' | 'string' | 'color'"
|
|
3226
|
+
});
|
|
3227
|
+
var SpecSchemaSchema = type({
|
|
3228
|
+
type: "'object'",
|
|
3229
|
+
properties: type("Record<string, unknown>").narrow((v) => {
|
|
3230
|
+
if (!isObject(v)) return false;
|
|
3231
|
+
return Object.values(v).every(
|
|
3232
|
+
(prop) => ["number", "string", "color"].includes(prop?.type)
|
|
3233
|
+
);
|
|
3234
|
+
}),
|
|
3235
|
+
"required?": "string[]",
|
|
3236
|
+
"order?": "string[]",
|
|
3237
|
+
"additionalProperties?": "boolean"
|
|
3238
|
+
});
|
|
3239
|
+
var ColorSpecificationSchema = type({
|
|
3240
|
+
name: "string",
|
|
3241
|
+
type: "'color'",
|
|
3242
|
+
"description?": "string",
|
|
3243
|
+
"schema?": SpecSchemaSchema,
|
|
3244
|
+
initializers: InitializerSchema.array(),
|
|
3245
|
+
conversions: ConversionSchema.array()
|
|
3246
|
+
});
|
|
3247
|
+
var specName = (spec) => spec.name.toLowerCase();
|
|
3723
3248
|
|
|
3724
3249
|
// src/utils/schema-uri.ts
|
|
3725
3250
|
var DEFAULT_REGISTRY_URL = "https://schema.tokenscript.dev.gcp.tokens.studio";
|
|
@@ -4139,11 +3664,6 @@ var BaseManager = class {
|
|
|
4139
3664
|
|
|
4140
3665
|
// src/interpreter/config/managers/functions/builtin/math.ts
|
|
4141
3666
|
function extractNumber(arg, functionName) {
|
|
4142
|
-
if (arg === void 0 || arg === null) {
|
|
4143
|
-
throw new InterpreterError("FN_EXPECTS_NUMBER_ARGUMENTS" /* EXPECTS_NUMBER_ARGUMENTS */, {
|
|
4144
|
-
data: { functionName }
|
|
4145
|
-
});
|
|
4146
|
-
}
|
|
4147
3667
|
if (arg instanceof NumberSymbol) return arg.value;
|
|
4148
3668
|
if (arg instanceof NumberWithUnitSymbol) return arg.value;
|
|
4149
3669
|
if (typeof arg.value === "number") return arg.value;
|
|
@@ -4398,10 +3918,21 @@ var mathFunctions = {
|
|
|
4398
3918
|
// Constants
|
|
4399
3919
|
pi: () => new NumberSymbol(Math.PI)
|
|
4400
3920
|
};
|
|
4401
|
-
var
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
3921
|
+
var FunctionSpecificationSchema = type({
|
|
3922
|
+
name: "string",
|
|
3923
|
+
type: "'function'",
|
|
3924
|
+
"input?": {
|
|
3925
|
+
type: "'object'",
|
|
3926
|
+
"properties?": "Record<string, unknown>"
|
|
3927
|
+
},
|
|
3928
|
+
script: {
|
|
3929
|
+
type: "string",
|
|
3930
|
+
script: "string"
|
|
3931
|
+
},
|
|
3932
|
+
keyword: "string",
|
|
3933
|
+
"description?": "string",
|
|
3934
|
+
"requirements?": "string[]"
|
|
3935
|
+
});
|
|
4405
3936
|
|
|
4406
3937
|
// src/interpreter/config/managers/functions/manager.ts
|
|
4407
3938
|
var FunctionsManager = class _FunctionsManager extends BaseManager {
|
|
@@ -4423,12 +3954,18 @@ var FunctionsManager = class _FunctionsManager extends BaseManager {
|
|
|
4423
3954
|
}
|
|
4424
3955
|
register(name, spec) {
|
|
4425
3956
|
let parsedSpec;
|
|
4426
|
-
|
|
4427
|
-
const
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
3957
|
+
if (typeof spec === "string") {
|
|
3958
|
+
const parseResult = FunctionSpecificationSchema(JSON.parse(spec));
|
|
3959
|
+
if (parseResult instanceof type.errors) {
|
|
3960
|
+
throw new Error(`Invalid function specification for ${name}: ${parseResult.summary}`);
|
|
3961
|
+
}
|
|
3962
|
+
parsedSpec = parseResult;
|
|
3963
|
+
} else {
|
|
3964
|
+
const parseResult = FunctionSpecificationSchema(spec);
|
|
3965
|
+
if (parseResult instanceof type.errors) {
|
|
3966
|
+
throw new Error(`Invalid function specification for ${name}: ${parseResult.summary}`);
|
|
3967
|
+
}
|
|
3968
|
+
parsedSpec = parseResult;
|
|
4432
3969
|
}
|
|
4433
3970
|
const functionName = parsedSpec.keyword.toLowerCase();
|
|
4434
3971
|
this.specs.set(functionName, parsedSpec);
|
|
@@ -4499,72 +4036,6 @@ var FunctionsManager = class _FunctionsManager extends BaseManager {
|
|
|
4499
4036
|
this.registerFunction("is_color", (arg) => {
|
|
4500
4037
|
return new BooleanSymbol(arg.type === "Color");
|
|
4501
4038
|
});
|
|
4502
|
-
this.registerFunction("range", (...args) => {
|
|
4503
|
-
if (args.length < 1 || args.length > 2) {
|
|
4504
|
-
throw new InterpreterError("FN_REQUIRES_MIN_ARGUMENTS" /* REQUIRES_MIN_ARGUMENTS */, {
|
|
4505
|
-
data: { functionName: "range", minArgs: 1 }
|
|
4506
|
-
});
|
|
4507
|
-
}
|
|
4508
|
-
let start;
|
|
4509
|
-
let end;
|
|
4510
|
-
if (args.length === 1) {
|
|
4511
|
-
if (!(args[0] instanceof NumberSymbol)) {
|
|
4512
|
-
throw new InterpreterError("FN_EXPECTS_TYPE_ARGUMENT" /* EXPECTS_TYPE_ARGUMENT */, {
|
|
4513
|
-
data: { functionName: "range", expectedType: "Number", argumentPosition: "first" }
|
|
4514
|
-
});
|
|
4515
|
-
}
|
|
4516
|
-
const v = args[0].value;
|
|
4517
|
-
if (v !== Math.trunc(v) || Number.isNaN(v) || !Number.isFinite(v) || v < 0 || v > 1e6) {
|
|
4518
|
-
throw new InterpreterError("FN_ARGUMENT_OUT_OF_RANGE" /* ARGUMENT_OUT_OF_RANGE */, {
|
|
4519
|
-
data: {
|
|
4520
|
-
functionName: "range",
|
|
4521
|
-
constraint: `count must be a non-negative integer <= 1000000, got ${v}`
|
|
4522
|
-
}
|
|
4523
|
-
});
|
|
4524
|
-
}
|
|
4525
|
-
start = 0;
|
|
4526
|
-
end = v;
|
|
4527
|
-
} else {
|
|
4528
|
-
if (!(args[0] instanceof NumberSymbol)) {
|
|
4529
|
-
throw new InterpreterError("FN_EXPECTS_TYPE_ARGUMENT" /* EXPECTS_TYPE_ARGUMENT */, {
|
|
4530
|
-
data: { functionName: "range", expectedType: "Number", argumentPosition: "first" }
|
|
4531
|
-
});
|
|
4532
|
-
}
|
|
4533
|
-
if (!(args[1] instanceof NumberSymbol)) {
|
|
4534
|
-
throw new InterpreterError("FN_EXPECTS_TYPE_ARGUMENT" /* EXPECTS_TYPE_ARGUMENT */, {
|
|
4535
|
-
data: { functionName: "range", expectedType: "Number", argumentPosition: "second" }
|
|
4536
|
-
});
|
|
4537
|
-
}
|
|
4538
|
-
const sv = args[0].value;
|
|
4539
|
-
const ev = args[1].value;
|
|
4540
|
-
if (sv !== Math.trunc(sv) || ev !== Math.trunc(ev) || Number.isNaN(sv) || Number.isNaN(ev) || !Number.isFinite(sv) || !Number.isFinite(ev)) {
|
|
4541
|
-
throw new InterpreterError("FN_ARGUMENT_OUT_OF_RANGE" /* ARGUMENT_OUT_OF_RANGE */, {
|
|
4542
|
-
data: {
|
|
4543
|
-
functionName: "range",
|
|
4544
|
-
constraint: `arguments must be integers, got ${sv} and ${ev}`
|
|
4545
|
-
}
|
|
4546
|
-
});
|
|
4547
|
-
}
|
|
4548
|
-
if (ev - sv > 1e6) {
|
|
4549
|
-
throw new InterpreterError("FN_ARGUMENT_OUT_OF_RANGE" /* ARGUMENT_OUT_OF_RANGE */, {
|
|
4550
|
-
data: {
|
|
4551
|
-
functionName: "range",
|
|
4552
|
-
constraint: `size exceeds limit (1000000), got ${ev - sv}`
|
|
4553
|
-
}
|
|
4554
|
-
});
|
|
4555
|
-
}
|
|
4556
|
-
start = sv;
|
|
4557
|
-
end = ev;
|
|
4558
|
-
}
|
|
4559
|
-
if (end < start) {
|
|
4560
|
-
return new ListSymbol([], false);
|
|
4561
|
-
}
|
|
4562
|
-
const elements = [];
|
|
4563
|
-
for (let i = start; i < end; i++) {
|
|
4564
|
-
elements.push(new NumberSymbol(i));
|
|
4565
|
-
}
|
|
4566
|
-
return new ListSymbol(elements, false);
|
|
4567
|
-
});
|
|
4568
4039
|
}
|
|
4569
4040
|
registerFunction(name, impl) {
|
|
4570
4041
|
this.functionMap.set(name.toLowerCase(), impl);
|
|
@@ -4616,33 +4087,26 @@ var FunctionsManager = class _FunctionsManager extends BaseManager {
|
|
|
4616
4087
|
getFunctionNames() {
|
|
4617
4088
|
return Array.from(this.functionMap.keys());
|
|
4618
4089
|
}
|
|
4619
|
-
getFunctionSchemas() {
|
|
4620
|
-
return this.specs;
|
|
4621
|
-
}
|
|
4622
|
-
/**
|
|
4623
|
-
* Validate that a function call has the correct number of arguments
|
|
4624
|
-
* based on its schema spec. Only validates schema-registered functions
|
|
4625
|
-
* (not builtins which handle their own argument validation).
|
|
4626
|
-
*/
|
|
4627
|
-
validateFunctionArgs(name, args, token) {
|
|
4628
|
-
const fnName = name.toLowerCase();
|
|
4629
|
-
const spec = this.specs.get(fnName);
|
|
4630
|
-
if (!spec?.input?.properties) return;
|
|
4631
|
-
const requiredCount = Object.values(spec.input.properties).filter(
|
|
4632
|
-
(prop) => !prop?.optional
|
|
4633
|
-
).length;
|
|
4634
|
-
if (args.length < requiredCount) {
|
|
4635
|
-
throw new InterpreterError("FN_REQUIRES_MIN_ARGUMENTS" /* REQUIRES_MIN_ARGUMENTS */, {
|
|
4636
|
-
token,
|
|
4637
|
-
data: { functionName: name, minArgs: requiredCount }
|
|
4638
|
-
});
|
|
4639
|
-
}
|
|
4640
|
-
}
|
|
4641
4090
|
};
|
|
4642
|
-
var
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4091
|
+
var ScriptBlockSchema2 = type({
|
|
4092
|
+
"type?": "string",
|
|
4093
|
+
script: "string"
|
|
4094
|
+
});
|
|
4095
|
+
var ConversionSchema2 = type({
|
|
4096
|
+
source: "string",
|
|
4097
|
+
target: "string",
|
|
4098
|
+
script: ScriptBlockSchema2,
|
|
4099
|
+
"description?": "string"
|
|
4100
|
+
});
|
|
4101
|
+
var UnitSpecificationSchema = type({
|
|
4102
|
+
name: "string",
|
|
4103
|
+
type: "'absolute' | 'relative'",
|
|
4104
|
+
keyword: "string",
|
|
4105
|
+
"description?": "string",
|
|
4106
|
+
"conversions?": ConversionSchema2.array(),
|
|
4107
|
+
"to_absolute?": ScriptBlockSchema2
|
|
4108
|
+
});
|
|
4109
|
+
var specName2 = (spec) => spec.name.toLowerCase();
|
|
4646
4110
|
|
|
4647
4111
|
// src/interpreter/config/managers/unit/manager.ts
|
|
4648
4112
|
var PIXEL_UNIT = buildSchemaUri({
|
|
@@ -4721,7 +4185,7 @@ var UnitManager = class _UnitManager extends BaseManager {
|
|
|
4721
4185
|
}
|
|
4722
4186
|
}
|
|
4723
4187
|
getSpecName(spec) {
|
|
4724
|
-
return
|
|
4188
|
+
return specName2(spec);
|
|
4725
4189
|
}
|
|
4726
4190
|
/**
|
|
4727
4191
|
* Creates a clone of this class to be passed down to initializers and conversion functions
|
|
@@ -4755,19 +4219,26 @@ var UnitManager = class _UnitManager extends BaseManager {
|
|
|
4755
4219
|
}
|
|
4756
4220
|
register(uri, spec) {
|
|
4757
4221
|
let parsedSpec;
|
|
4758
|
-
|
|
4759
|
-
const
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
const jsonSuffix = typeof spec === "string" ? `
|
|
4222
|
+
if (typeof spec === "string") {
|
|
4223
|
+
const parseResult = UnitSpecificationSchema(JSON.parse(spec));
|
|
4224
|
+
if (parseResult instanceof type.errors) {
|
|
4225
|
+
throw new Error(
|
|
4226
|
+
`Invalid unit specification for URI ${uri}: ${parseResult.summary}
|
|
4764
4227
|
|
|
4765
4228
|
Json:
|
|
4766
|
-
${spec}`
|
|
4767
|
-
|
|
4229
|
+
${spec}`
|
|
4230
|
+
);
|
|
4231
|
+
}
|
|
4232
|
+
parsedSpec = parseResult;
|
|
4233
|
+
} else {
|
|
4234
|
+
const parseResult = UnitSpecificationSchema(spec);
|
|
4235
|
+
if (parseResult instanceof type.errors) {
|
|
4236
|
+
throw new Error(`Invalid unit specification for URI ${uri}: ${parseResult.summary}`);
|
|
4237
|
+
}
|
|
4238
|
+
parsedSpec = parseResult;
|
|
4768
4239
|
}
|
|
4769
4240
|
this.specs.set(uri, parsedSpec);
|
|
4770
|
-
this.specTypes.set(
|
|
4241
|
+
this.specTypes.set(specName2(parsedSpec), uri);
|
|
4771
4242
|
this.unitKeywords.set(parsedSpec.keyword.toUpperCase(), uri);
|
|
4772
4243
|
this.registerConversions(uri, parsedSpec);
|
|
4773
4244
|
return parsedSpec;
|
|
@@ -5038,16 +4509,23 @@ var ColorManager = class _ColorManager extends BaseManager {
|
|
|
5038
4509
|
}
|
|
5039
4510
|
register(uri, spec) {
|
|
5040
4511
|
let parsedSpec;
|
|
5041
|
-
|
|
5042
|
-
const
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
const jsonSuffix = typeof spec === "string" ? `
|
|
4512
|
+
if (typeof spec === "string") {
|
|
4513
|
+
const parseResult = ColorSpecificationSchema(JSON.parse(spec));
|
|
4514
|
+
if (parseResult instanceof type.errors) {
|
|
4515
|
+
throw new Error(
|
|
4516
|
+
`Invalid color specification for URI ${uri}: ${parseResult.summary}
|
|
5047
4517
|
|
|
5048
4518
|
Json:
|
|
5049
|
-
${spec}`
|
|
5050
|
-
|
|
4519
|
+
${spec}`
|
|
4520
|
+
);
|
|
4521
|
+
}
|
|
4522
|
+
parsedSpec = parseResult;
|
|
4523
|
+
} else {
|
|
4524
|
+
const parseResult = ColorSpecificationSchema(spec);
|
|
4525
|
+
if (parseResult instanceof type.errors) {
|
|
4526
|
+
throw new Error(`Invalid color specification for URI ${uri}: ${parseResult.summary}`);
|
|
4527
|
+
}
|
|
4528
|
+
parsedSpec = parseResult;
|
|
5051
4529
|
}
|
|
5052
4530
|
this.specs.set(uri, parsedSpec);
|
|
5053
4531
|
this.specTypes.set(specName(parsedSpec), uri);
|
|
@@ -5055,8 +4533,8 @@ ${spec}` : "";
|
|
|
5055
4533
|
this.registerConversions(uri, parsedSpec);
|
|
5056
4534
|
return parsedSpec;
|
|
5057
4535
|
}
|
|
5058
|
-
getSpecByType(
|
|
5059
|
-
const uri = this.specTypes.get(
|
|
4536
|
+
getSpecByType(type9) {
|
|
4537
|
+
const uri = this.specTypes.get(type9.toLowerCase());
|
|
5060
4538
|
if (!uri) return;
|
|
5061
4539
|
return this.getSpec(uri);
|
|
5062
4540
|
}
|
|
@@ -5269,14 +4747,28 @@ ${spec}` : "";
|
|
|
5269
4747
|
}
|
|
5270
4748
|
return "";
|
|
5271
4749
|
}
|
|
5272
|
-
getColorSchemas() {
|
|
5273
|
-
return this.specs;
|
|
5274
|
-
}
|
|
5275
4750
|
};
|
|
5276
|
-
var
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
4751
|
+
var SpecSchemaSchema2 = type({
|
|
4752
|
+
type: "'object' | 'number' | 'string' | 'list'",
|
|
4753
|
+
"properties?": "Record<string, unknown>",
|
|
4754
|
+
// Simplified validation
|
|
4755
|
+
"validations?": "Record<string, string>",
|
|
4756
|
+
"required?": "string[]",
|
|
4757
|
+
"order?": "string[]",
|
|
4758
|
+
"additionalProperties?": "boolean",
|
|
4759
|
+
"items?": "unknown"
|
|
4760
|
+
// For list types - validated at runtime
|
|
4761
|
+
});
|
|
4762
|
+
var TokenSpecificationSchema = type({
|
|
4763
|
+
name: "string",
|
|
4764
|
+
type: "'token'",
|
|
4765
|
+
"description?": "string",
|
|
4766
|
+
"url?": "string",
|
|
4767
|
+
"schema?": SpecSchemaSchema2,
|
|
4768
|
+
"validation?": "string | unknown"
|
|
4769
|
+
// Allow string or object, validated at runtime in manager
|
|
4770
|
+
});
|
|
4771
|
+
var specName3 = (spec) => spec.name.toLowerCase();
|
|
5280
4772
|
|
|
5281
4773
|
// src/interpreter/config/managers/token/manager.ts
|
|
5282
4774
|
var MAX_VALIDATION_DEPTH = 10;
|
|
@@ -5301,10 +4793,10 @@ var TokenManager = class _TokenManager extends BaseManager {
|
|
|
5301
4793
|
this.validationInterpreterCache = /* @__PURE__ */ new Map();
|
|
5302
4794
|
}
|
|
5303
4795
|
getSpecName(spec) {
|
|
5304
|
-
return
|
|
4796
|
+
return specName3(spec);
|
|
5305
4797
|
}
|
|
5306
|
-
getSpecByType(
|
|
5307
|
-
const uri = this.specTypes.get(
|
|
4798
|
+
getSpecByType(type9) {
|
|
4799
|
+
const uri = this.specTypes.get(type9.toLowerCase());
|
|
5308
4800
|
if (!uri) return;
|
|
5309
4801
|
return this.getSpec(uri);
|
|
5310
4802
|
}
|
|
@@ -5320,18 +4812,25 @@ var TokenManager = class _TokenManager extends BaseManager {
|
|
|
5320
4812
|
}
|
|
5321
4813
|
register(uri, spec) {
|
|
5322
4814
|
let parsedSpec;
|
|
5323
|
-
|
|
5324
|
-
const
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
const jsonSuffix = typeof spec === "string" ? `
|
|
4815
|
+
if (typeof spec === "string") {
|
|
4816
|
+
const parseResult = TokenSpecificationSchema(JSON.parse(spec));
|
|
4817
|
+
if (parseResult instanceof type.errors) {
|
|
4818
|
+
throw new Error(
|
|
4819
|
+
`Invalid token specification for URI ${uri}: ${parseResult.summary}
|
|
5329
4820
|
Json:
|
|
5330
|
-
${spec}`
|
|
5331
|
-
|
|
4821
|
+
${spec}`
|
|
4822
|
+
);
|
|
4823
|
+
}
|
|
4824
|
+
parsedSpec = parseResult;
|
|
4825
|
+
} else {
|
|
4826
|
+
const parseResult = TokenSpecificationSchema(spec);
|
|
4827
|
+
if (parseResult instanceof type.errors) {
|
|
4828
|
+
throw new Error(`Invalid token specification for URI ${uri}: ${parseResult.summary}`);
|
|
4829
|
+
}
|
|
4830
|
+
parsedSpec = parseResult;
|
|
5332
4831
|
}
|
|
5333
4832
|
this.specs.set(uri, parsedSpec);
|
|
5334
|
-
this.specTypes.set(
|
|
4833
|
+
this.specTypes.set(specName3(parsedSpec), uri);
|
|
5335
4834
|
if (parsedSpec.validation) {
|
|
5336
4835
|
this.registerValidation(parsedSpec.name, parsedSpec.validation);
|
|
5337
4836
|
}
|
|
@@ -5367,8 +4866,8 @@ ${spec}` : "";
|
|
|
5367
4866
|
return this.extractErrorTypesFromAST(tokenType);
|
|
5368
4867
|
}
|
|
5369
4868
|
const allErrors = /* @__PURE__ */ new Set();
|
|
5370
|
-
for (const
|
|
5371
|
-
for (const error of this.extractErrorTypesFromAST(
|
|
4869
|
+
for (const type9 of this.validationScripts.keys()) {
|
|
4870
|
+
for (const error of this.extractErrorTypesFromAST(type9)) {
|
|
5372
4871
|
allErrors.add(error);
|
|
5373
4872
|
}
|
|
5374
4873
|
}
|
|
@@ -5921,9 +5420,6 @@ var SymbolTable = class {
|
|
|
5921
5420
|
isDefined(name) {
|
|
5922
5421
|
return !!this.symbols[name.toLowerCase()];
|
|
5923
5422
|
}
|
|
5924
|
-
delete(name) {
|
|
5925
|
-
delete this.symbols[name.toLowerCase()];
|
|
5926
|
-
}
|
|
5927
5423
|
reset() {
|
|
5928
5424
|
this.symbols = {};
|
|
5929
5425
|
}
|
|
@@ -6033,47 +5529,6 @@ var Interpreter = class {
|
|
|
6033
5529
|
visitStringNode(node) {
|
|
6034
5530
|
return new StringSymbol(node.value, this.config);
|
|
6035
5531
|
}
|
|
6036
|
-
visitTemplateStringNode(node) {
|
|
6037
|
-
if (node.parts.length === 0) {
|
|
6038
|
-
return new StringSymbol("", this.config);
|
|
6039
|
-
}
|
|
6040
|
-
if (node.parts.length === 1) {
|
|
6041
|
-
const val = this.visit(node.parts[0]);
|
|
6042
|
-
this.validateTemplateValue(val, node);
|
|
6043
|
-
return val;
|
|
6044
|
-
}
|
|
6045
|
-
let result = "";
|
|
6046
|
-
for (const part of node.parts) {
|
|
6047
|
-
const val = this.visit(part);
|
|
6048
|
-
this.validateTemplateValue(val, node);
|
|
6049
|
-
result += val.toString();
|
|
6050
|
-
}
|
|
6051
|
-
return new StringSymbol(result, this.config);
|
|
6052
|
-
}
|
|
6053
|
-
/**
|
|
6054
|
-
* Validate that a value is a primitive type allowed in template string interpolation.
|
|
6055
|
-
* Lists, Dictionaries, and non-hex Colors are rejected.
|
|
6056
|
-
*/
|
|
6057
|
-
validateTemplateValue(val, node) {
|
|
6058
|
-
if (val instanceof ListSymbol) {
|
|
6059
|
-
throw new InterpreterError("INT_TEMPLATE_INVALID_TYPE" /* TEMPLATE_INVALID_TYPE */, {
|
|
6060
|
-
token: node.token,
|
|
6061
|
-
data: { valueType: "List" }
|
|
6062
|
-
});
|
|
6063
|
-
}
|
|
6064
|
-
if (val instanceof DictionarySymbol) {
|
|
6065
|
-
throw new InterpreterError("INT_TEMPLATE_INVALID_TYPE" /* TEMPLATE_INVALID_TYPE */, {
|
|
6066
|
-
token: node.token,
|
|
6067
|
-
data: { valueType: "Dictionary" }
|
|
6068
|
-
});
|
|
6069
|
-
}
|
|
6070
|
-
if (val instanceof ColorSymbol && !val.isHex()) {
|
|
6071
|
-
throw new InterpreterError("INT_TEMPLATE_INVALID_TYPE" /* TEMPLATE_INVALID_TYPE */, {
|
|
6072
|
-
token: node.token,
|
|
6073
|
-
data: { valueType: `Color.${val.subType}` }
|
|
6074
|
-
});
|
|
6075
|
-
}
|
|
6076
|
-
}
|
|
6077
5532
|
/**
|
|
6078
5533
|
* Bare identifiers are treated as string literals if not found as variables
|
|
6079
5534
|
* Check symbol table first (variables override references), then references
|
|
@@ -6168,7 +5623,6 @@ var Interpreter = class {
|
|
|
6168
5623
|
const fnName = node.name.toLowerCase();
|
|
6169
5624
|
const args = node.args.map((arg) => this.visit(arg));
|
|
6170
5625
|
if (this.config.functionsManager.hasFunction(fnName)) {
|
|
6171
|
-
this.config.functionsManager.validateFunctionArgs(fnName, args, node.token);
|
|
6172
5626
|
const fn = this.config.functionsManager.getFunction(fnName);
|
|
6173
5627
|
if (fn) {
|
|
6174
5628
|
return fn(...args);
|
|
@@ -6346,63 +5800,6 @@ var Interpreter = class {
|
|
|
6346
5800
|
this.visit(node.body);
|
|
6347
5801
|
}
|
|
6348
5802
|
}
|
|
6349
|
-
visitForEachNode(node) {
|
|
6350
|
-
if (this.symbolTable.isDefined(node.itemVar)) {
|
|
6351
|
-
throw new InterpreterError("INT_FOR_EACH_VARIABLE_SHADOW" /* FOR_EACH_VARIABLE_SHADOW */, {
|
|
6352
|
-
token: node.token,
|
|
6353
|
-
data: { name: node.itemVar }
|
|
6354
|
-
});
|
|
6355
|
-
}
|
|
6356
|
-
if (node.indexVar !== null) {
|
|
6357
|
-
if (node.indexVar === node.itemVar) {
|
|
6358
|
-
throw new InterpreterError("INT_FOR_EACH_DUPLICATE_VARS" /* FOR_EACH_DUPLICATE_VARS */, {
|
|
6359
|
-
token: node.token,
|
|
6360
|
-
data: { name: node.itemVar }
|
|
6361
|
-
});
|
|
6362
|
-
}
|
|
6363
|
-
if (this.symbolTable.isDefined(node.indexVar)) {
|
|
6364
|
-
throw new InterpreterError("INT_FOR_EACH_VARIABLE_SHADOW" /* FOR_EACH_VARIABLE_SHADOW */, {
|
|
6365
|
-
token: node.token,
|
|
6366
|
-
data: { name: node.indexVar }
|
|
6367
|
-
});
|
|
6368
|
-
}
|
|
6369
|
-
}
|
|
6370
|
-
const collectionVal = this.visit(node.collection);
|
|
6371
|
-
if (!(collectionVal instanceof ListSymbol)) {
|
|
6372
|
-
throw new InterpreterError("INT_FOR_EACH_NOT_LIST" /* FOR_EACH_NOT_LIST */, {
|
|
6373
|
-
token: node.token,
|
|
6374
|
-
data: { actualType: collectionVal?.type ?? "null" }
|
|
6375
|
-
});
|
|
6376
|
-
}
|
|
6377
|
-
const elements = collectionVal.value;
|
|
6378
|
-
const results = [];
|
|
6379
|
-
for (let idx = 0; idx < elements.length; idx++) {
|
|
6380
|
-
const item = elements[idx];
|
|
6381
|
-
this.symbolTable.set(node.itemVar, item);
|
|
6382
|
-
if (node.indexVar !== null) {
|
|
6383
|
-
this.symbolTable.set(node.indexVar, new NumberSymbol(idx, this.config));
|
|
6384
|
-
}
|
|
6385
|
-
let bodyResult = null;
|
|
6386
|
-
try {
|
|
6387
|
-
bodyResult = this.visit(node.body);
|
|
6388
|
-
} catch (e) {
|
|
6389
|
-
if (e instanceof ReturnSignal) {
|
|
6390
|
-
this.symbolTable.delete(node.itemVar);
|
|
6391
|
-
if (node.indexVar !== null) {
|
|
6392
|
-
this.symbolTable.delete(node.indexVar);
|
|
6393
|
-
}
|
|
6394
|
-
throw e;
|
|
6395
|
-
}
|
|
6396
|
-
throw e;
|
|
6397
|
-
}
|
|
6398
|
-
results.push(bodyResult ?? new NullSymbol(this.config));
|
|
6399
|
-
}
|
|
6400
|
-
this.symbolTable.delete(node.itemVar);
|
|
6401
|
-
if (node.indexVar !== null) {
|
|
6402
|
-
this.symbolTable.delete(node.indexVar);
|
|
6403
|
-
}
|
|
6404
|
-
return new ListSymbol(results, false, this.config);
|
|
6405
|
-
}
|
|
6406
5803
|
visitIfNode(node) {
|
|
6407
5804
|
for (const conditionNode of node.conditions) {
|
|
6408
5805
|
const condition = this.visit(conditionNode.condition);
|
|
@@ -6439,6 +5836,6 @@ var Interpreter = class {
|
|
|
6439
5836
|
}
|
|
6440
5837
|
};
|
|
6441
5838
|
|
|
6442
|
-
export { BaseSymbolType, BooleanSymbol, ColorManager, ColorSymbol, Config, DictionarySymbol, Interpreter, InterpreterError, Lexer, LexerError, ListSymbol, NullSymbol, NumberSymbol, NumberWithUnitSymbol, Parser, ParserError, ProcessorError, StringSymbol, TokenSymbol, getAssignmentInfo, getKeyAlt, getReassignmentInfo, isArray, isBoolean, isLanguageError, isNone, isNull, isNumber, isObject, isString, isTokenscriptSymbol, jsValueToSymbolType,
|
|
6443
|
-
//# sourceMappingURL=chunk-
|
|
6444
|
-
//# sourceMappingURL=chunk-
|
|
5839
|
+
export { BaseSymbolType, BooleanSymbol, ColorManager, ColorSpecificationSchema, ColorSymbol, Config, DictionarySymbol, FunctionSpecificationSchema, Interpreter, InterpreterError, Lexer, LexerError, ListSymbol, NullSymbol, NumberSymbol, NumberWithUnitSymbol, Parser, ParserError, ProcessorError, StringSymbol, TokenSymbol, getAssignmentInfo, getKeyAlt, getReassignmentInfo, isArray, isBoolean, isLanguageError, isNone, isNull, isNumber, isObject, isString, isTokenscriptSymbol, jsValueToSymbolType, parseExpression, renameReferences, serializeInterpreterResult, stringifyInterpreterResult };
|
|
5840
|
+
//# sourceMappingURL=chunk-P4VLJQEI.js.map
|
|
5841
|
+
//# sourceMappingURL=chunk-P4VLJQEI.js.map
|