@k67/kaitai-struct-ts 0.2.0 → 0.5.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/index.mjs CHANGED
@@ -824,17 +824,23 @@ var Context = class _Context {
824
824
  * @param _io - Binary stream being read
825
825
  * @param _root - Root object of the parse tree
826
826
  * @param _parent - Parent object (optional)
827
+ * @param enums - Enum definitions from schema (optional)
827
828
  */
828
- constructor(_io, _root = null, _parent = null) {
829
+ constructor(_io, _root = null, _parent = null, enums) {
829
830
  this._io = _io;
830
831
  this._root = _root;
831
832
  /** Stack of parent objects */
832
833
  this.parentStack = [];
833
834
  /** Current object being parsed */
834
835
  this._current = {};
836
+ /** Enum definitions from schema */
837
+ this._enums = {};
835
838
  if (_parent !== null) {
836
839
  this.parentStack.push(_parent);
837
840
  }
841
+ if (enums) {
842
+ this._enums = enums;
843
+ }
838
844
  }
839
845
  /**
840
846
  * Get the current I/O stream.
@@ -931,6 +937,36 @@ var Context = class _Context {
931
937
  set(name, value) {
932
938
  this._current[name] = value;
933
939
  }
940
+ /**
941
+ * Get enum value by name.
942
+ * Used for enum access in expressions (EnumName::value).
943
+ *
944
+ * @param enumName - Name of the enum
945
+ * @param valueName - Name of the enum value
946
+ * @returns Enum value (number) or undefined
947
+ */
948
+ getEnumValue(enumName, valueName) {
949
+ const enumDef = this._enums[enumName];
950
+ if (!enumDef) {
951
+ return void 0;
952
+ }
953
+ for (const [key, value] of Object.entries(enumDef)) {
954
+ if (value === valueName) {
955
+ const numKey = Number(key);
956
+ return isNaN(numKey) ? key : numKey;
957
+ }
958
+ }
959
+ return void 0;
960
+ }
961
+ /**
962
+ * Check if an enum exists.
963
+ *
964
+ * @param enumName - Name of the enum
965
+ * @returns True if enum exists
966
+ */
967
+ hasEnum(enumName) {
968
+ return enumName in this._enums;
969
+ }
934
970
  /**
935
971
  * Create a child context for nested parsing.
936
972
  * The current object becomes the parent in the child context.
@@ -942,7 +978,8 @@ var Context = class _Context {
942
978
  const childContext = new _Context(
943
979
  stream || this._io,
944
980
  this._root || this._current,
945
- this._current
981
+ this._current,
982
+ this._enums
946
983
  );
947
984
  return childContext;
948
985
  }
@@ -953,13 +990,917 @@ var Context = class _Context {
953
990
  * @returns Cloned context
954
991
  */
955
992
  clone() {
956
- const cloned = new _Context(this._io, this._root, this.parent);
993
+ const cloned = new _Context(this._io, this._root, this.parent, this._enums);
957
994
  cloned._current = { ...this._current };
958
995
  cloned.parentStack = [...this.parentStack];
959
996
  return cloned;
960
997
  }
961
998
  };
962
999
 
1000
+ // src/expression/Token.ts
1001
+ function createToken(type, value = null, position = 0) {
1002
+ return { type, value, position };
1003
+ }
1004
+
1005
+ // src/expression/Lexer.ts
1006
+ var Lexer = class {
1007
+ /**
1008
+ * Create a new lexer.
1009
+ *
1010
+ * @param input - Expression string to tokenize
1011
+ */
1012
+ constructor(input) {
1013
+ this.position = 0;
1014
+ this.current = null;
1015
+ this.input = input;
1016
+ this.current = input.length > 0 ? input[0] : null;
1017
+ }
1018
+ /**
1019
+ * Tokenize the entire input string.
1020
+ *
1021
+ * @returns Array of tokens
1022
+ * @throws {ParseError} If invalid syntax is encountered
1023
+ */
1024
+ tokenize() {
1025
+ const tokens = [];
1026
+ while (this.current !== null) {
1027
+ if (this.isWhitespace(this.current)) {
1028
+ this.skipWhitespace();
1029
+ continue;
1030
+ }
1031
+ if (this.isDigit(this.current)) {
1032
+ tokens.push(this.readNumber());
1033
+ continue;
1034
+ }
1035
+ if (this.isIdentifierStart(this.current)) {
1036
+ tokens.push(this.readIdentifierOrKeyword());
1037
+ continue;
1038
+ }
1039
+ if (this.current === '"' || this.current === "'") {
1040
+ tokens.push(this.readString());
1041
+ continue;
1042
+ }
1043
+ const token = this.readOperator();
1044
+ if (token) {
1045
+ tokens.push(token);
1046
+ continue;
1047
+ }
1048
+ throw new ParseError(
1049
+ `Unexpected character: ${this.current}`,
1050
+ this.position
1051
+ );
1052
+ }
1053
+ tokens.push(createToken("EOF" /* EOF */, null, this.position));
1054
+ return tokens;
1055
+ }
1056
+ /**
1057
+ * Advance to the next character.
1058
+ * @private
1059
+ */
1060
+ advance() {
1061
+ this.position++;
1062
+ this.current = this.position < this.input.length ? this.input[this.position] : null;
1063
+ }
1064
+ /**
1065
+ * Peek at the next character without advancing.
1066
+ * @private
1067
+ */
1068
+ peek(offset = 1) {
1069
+ const pos = this.position + offset;
1070
+ return pos < this.input.length ? this.input[pos] : null;
1071
+ }
1072
+ /**
1073
+ * Check if character is whitespace.
1074
+ * @private
1075
+ */
1076
+ isWhitespace(char) {
1077
+ return /\s/.test(char);
1078
+ }
1079
+ /**
1080
+ * Check if character is a digit.
1081
+ * @private
1082
+ */
1083
+ isDigit(char) {
1084
+ return /[0-9]/.test(char);
1085
+ }
1086
+ /**
1087
+ * Check if character can start an identifier.
1088
+ * @private
1089
+ */
1090
+ isIdentifierStart(char) {
1091
+ return /[a-zA-Z_]/.test(char);
1092
+ }
1093
+ /**
1094
+ * Check if character can be part of an identifier.
1095
+ * @private
1096
+ */
1097
+ isIdentifierPart(char) {
1098
+ return /[a-zA-Z0-9_]/.test(char);
1099
+ }
1100
+ /**
1101
+ * Skip whitespace characters.
1102
+ * @private
1103
+ */
1104
+ skipWhitespace() {
1105
+ while (this.current !== null && this.isWhitespace(this.current)) {
1106
+ this.advance();
1107
+ }
1108
+ }
1109
+ /**
1110
+ * Read a number token.
1111
+ * @private
1112
+ */
1113
+ readNumber() {
1114
+ const start = this.position;
1115
+ let value = "";
1116
+ if (this.current === "0" && this.peek() === "x") {
1117
+ value += this.current;
1118
+ this.advance();
1119
+ value += this.current;
1120
+ this.advance();
1121
+ while (this.current !== null && /[0-9a-fA-F]/.test(this.current)) {
1122
+ value += this.current;
1123
+ this.advance();
1124
+ }
1125
+ return createToken("NUMBER" /* NUMBER */, parseInt(value, 16), start);
1126
+ }
1127
+ while (this.current !== null && this.isDigit(this.current)) {
1128
+ value += this.current;
1129
+ this.advance();
1130
+ }
1131
+ if (this.current === "." && this.peek() && this.isDigit(this.peek())) {
1132
+ value += this.current;
1133
+ this.advance();
1134
+ while (this.current !== null && this.isDigit(this.current)) {
1135
+ value += this.current;
1136
+ this.advance();
1137
+ }
1138
+ return createToken("NUMBER" /* NUMBER */, parseFloat(value), start);
1139
+ }
1140
+ return createToken("NUMBER" /* NUMBER */, parseInt(value, 10), start);
1141
+ }
1142
+ /**
1143
+ * Read an identifier or keyword token.
1144
+ * @private
1145
+ */
1146
+ readIdentifierOrKeyword() {
1147
+ const start = this.position;
1148
+ let value = "";
1149
+ while (this.current !== null && this.isIdentifierPart(this.current)) {
1150
+ value += this.current;
1151
+ this.advance();
1152
+ }
1153
+ switch (value) {
1154
+ case "true":
1155
+ return createToken("BOOLEAN" /* BOOLEAN */, true, start);
1156
+ case "false":
1157
+ return createToken("BOOLEAN" /* BOOLEAN */, false, start);
1158
+ case "and":
1159
+ return createToken("AND" /* AND */, value, start);
1160
+ case "or":
1161
+ return createToken("OR" /* OR */, value, start);
1162
+ case "not":
1163
+ return createToken("NOT" /* NOT */, value, start);
1164
+ default:
1165
+ return createToken("IDENTIFIER" /* IDENTIFIER */, value, start);
1166
+ }
1167
+ }
1168
+ /**
1169
+ * Read a string token.
1170
+ * @private
1171
+ */
1172
+ readString() {
1173
+ const start = this.position;
1174
+ const quote = this.current;
1175
+ let value = "";
1176
+ this.advance();
1177
+ while (this.current !== null && this.current !== quote) {
1178
+ if (this.current === "\\") {
1179
+ this.advance();
1180
+ if (this.current === null) {
1181
+ throw new ParseError("Unterminated string", start);
1182
+ }
1183
+ const ch = this.current;
1184
+ if (ch === "n") {
1185
+ value += "\n";
1186
+ } else if (ch === "t") {
1187
+ value += " ";
1188
+ } else if (ch === "r") {
1189
+ value += "\r";
1190
+ } else if (ch === "\\") {
1191
+ value += "\\";
1192
+ } else if (ch === '"') {
1193
+ value += '"';
1194
+ } else if (ch === "'") {
1195
+ value += "'";
1196
+ } else {
1197
+ value += ch;
1198
+ }
1199
+ } else {
1200
+ value += this.current;
1201
+ }
1202
+ this.advance();
1203
+ }
1204
+ if (this.current === null) {
1205
+ throw new ParseError("Unterminated string", start);
1206
+ }
1207
+ this.advance();
1208
+ return createToken("STRING" /* STRING */, value, start);
1209
+ }
1210
+ /**
1211
+ * Read an operator or punctuation token.
1212
+ * @private
1213
+ */
1214
+ readOperator() {
1215
+ const start = this.position;
1216
+ const char = this.current;
1217
+ switch (char) {
1218
+ case "+":
1219
+ this.advance();
1220
+ return createToken("PLUS" /* PLUS */, char, start);
1221
+ case "-":
1222
+ this.advance();
1223
+ return createToken("MINUS" /* MINUS */, char, start);
1224
+ case "*":
1225
+ this.advance();
1226
+ return createToken("STAR" /* STAR */, char, start);
1227
+ case "/":
1228
+ this.advance();
1229
+ return createToken("SLASH" /* SLASH */, char, start);
1230
+ case "%":
1231
+ this.advance();
1232
+ return createToken("PERCENT" /* PERCENT */, char, start);
1233
+ case "<":
1234
+ this.advance();
1235
+ if (this.current === "=") {
1236
+ this.advance();
1237
+ return createToken("LE" /* LE */, "<=", start);
1238
+ } else if (this.current === "<") {
1239
+ this.advance();
1240
+ return createToken("LSHIFT" /* LSHIFT */, "<<", start);
1241
+ }
1242
+ return createToken("LT" /* LT */, "<", start);
1243
+ case ">":
1244
+ this.advance();
1245
+ if (this.current === "=") {
1246
+ this.advance();
1247
+ return createToken("GE" /* GE */, ">=", start);
1248
+ } else if (this.current === ">") {
1249
+ this.advance();
1250
+ return createToken("RSHIFT" /* RSHIFT */, ">>", start);
1251
+ }
1252
+ return createToken("GT" /* GT */, ">", start);
1253
+ case "=":
1254
+ this.advance();
1255
+ if (this.current === "=") {
1256
+ this.advance();
1257
+ return createToken("EQ" /* EQ */, "==", start);
1258
+ }
1259
+ throw new ParseError("Expected == for equality", start);
1260
+ case "!":
1261
+ this.advance();
1262
+ if (this.current === "=") {
1263
+ this.advance();
1264
+ return createToken("NE" /* NE */, "!=", start);
1265
+ }
1266
+ throw new ParseError("Expected != for inequality", start);
1267
+ case "&":
1268
+ this.advance();
1269
+ return createToken("AMPERSAND" /* AMPERSAND */, char, start);
1270
+ case "|":
1271
+ this.advance();
1272
+ return createToken("PIPE" /* PIPE */, char, start);
1273
+ case "^":
1274
+ this.advance();
1275
+ return createToken("CARET" /* CARET */, char, start);
1276
+ case "?":
1277
+ this.advance();
1278
+ return createToken("QUESTION" /* QUESTION */, char, start);
1279
+ case ":":
1280
+ this.advance();
1281
+ if (this.current === ":") {
1282
+ this.advance();
1283
+ return createToken("DOUBLE_COLON" /* DOUBLE_COLON */, "::", start);
1284
+ }
1285
+ return createToken("COLON" /* COLON */, char, start);
1286
+ case "(":
1287
+ this.advance();
1288
+ return createToken("LPAREN" /* LPAREN */, char, start);
1289
+ case ")":
1290
+ this.advance();
1291
+ return createToken("RPAREN" /* RPAREN */, char, start);
1292
+ case "[":
1293
+ this.advance();
1294
+ return createToken("LBRACKET" /* LBRACKET */, char, start);
1295
+ case "]":
1296
+ this.advance();
1297
+ return createToken("RBRACKET" /* RBRACKET */, char, start);
1298
+ case ".":
1299
+ this.advance();
1300
+ return createToken("DOT" /* DOT */, char, start);
1301
+ case ",":
1302
+ this.advance();
1303
+ return createToken("COMMA" /* COMMA */, char, start);
1304
+ default:
1305
+ return null;
1306
+ }
1307
+ }
1308
+ };
1309
+
1310
+ // src/expression/AST.ts
1311
+ function createLiteral(value) {
1312
+ return { kind: "Literal", value };
1313
+ }
1314
+ function createIdentifier(name) {
1315
+ return { kind: "Identifier", name };
1316
+ }
1317
+ function createBinaryOp(operator, left, right) {
1318
+ return { kind: "BinaryOp", operator, left, right };
1319
+ }
1320
+ function createUnaryOp(operator, operand) {
1321
+ return { kind: "UnaryOp", operator, operand };
1322
+ }
1323
+ function createTernary(condition, ifTrue, ifFalse) {
1324
+ return { kind: "Ternary", condition, ifTrue, ifFalse };
1325
+ }
1326
+ function createMemberAccess(object, property) {
1327
+ return { kind: "MemberAccess", object, property };
1328
+ }
1329
+ function createIndexAccess(object, index) {
1330
+ return { kind: "IndexAccess", object, index };
1331
+ }
1332
+ function createMethodCall(object, method, args) {
1333
+ return { kind: "MethodCall", object, method, args };
1334
+ }
1335
+ function createEnumAccess(enumName, value) {
1336
+ return { kind: "EnumAccess", enumName, value };
1337
+ }
1338
+
1339
+ // src/expression/Parser.ts
1340
+ var ExpressionParser = class {
1341
+ /**
1342
+ * Create a new expression parser.
1343
+ *
1344
+ * @param tokens - Array of tokens to parse
1345
+ */
1346
+ constructor(tokens) {
1347
+ this.position = 0;
1348
+ this.tokens = tokens;
1349
+ }
1350
+ /**
1351
+ * Parse the tokens into an AST.
1352
+ *
1353
+ * @returns Root AST node
1354
+ * @throws {ParseError} If invalid syntax is encountered
1355
+ */
1356
+ parse() {
1357
+ const expr = this.parseTernary();
1358
+ if (!this.isAtEnd()) {
1359
+ throw new ParseError(
1360
+ `Unexpected token: ${this.current().type}`,
1361
+ this.current().position
1362
+ );
1363
+ }
1364
+ return expr;
1365
+ }
1366
+ /**
1367
+ * Get the current token.
1368
+ * @private
1369
+ */
1370
+ current() {
1371
+ return this.tokens[this.position];
1372
+ }
1373
+ /**
1374
+ * Check if we're at the end of tokens.
1375
+ * @private
1376
+ */
1377
+ isAtEnd() {
1378
+ return this.current().type === "EOF" /* EOF */;
1379
+ }
1380
+ /**
1381
+ * Advance to the next token.
1382
+ * @private
1383
+ */
1384
+ advance() {
1385
+ if (!this.isAtEnd()) {
1386
+ this.position++;
1387
+ }
1388
+ return this.tokens[this.position - 1];
1389
+ }
1390
+ /**
1391
+ * Check if current token matches any of the given types.
1392
+ * @private
1393
+ */
1394
+ match(...types) {
1395
+ for (const type of types) {
1396
+ if (this.current().type === type) {
1397
+ this.advance();
1398
+ return true;
1399
+ }
1400
+ }
1401
+ return false;
1402
+ }
1403
+ /**
1404
+ * Expect a specific token type and advance.
1405
+ * @private
1406
+ */
1407
+ expect(type, message) {
1408
+ if (this.current().type !== type) {
1409
+ throw new ParseError(message, this.current().position);
1410
+ }
1411
+ return this.advance();
1412
+ }
1413
+ /**
1414
+ * Parse ternary conditional (lowest precedence).
1415
+ * condition ? ifTrue : ifFalse
1416
+ * @private
1417
+ */
1418
+ parseTernary() {
1419
+ let expr = this.parseLogicalOr();
1420
+ if (this.match("QUESTION" /* QUESTION */)) {
1421
+ const ifTrue = this.parseTernary();
1422
+ this.expect("COLON" /* COLON */, "Expected : in ternary expression");
1423
+ const ifFalse = this.parseTernary();
1424
+ return createTernary(expr, ifTrue, ifFalse);
1425
+ }
1426
+ return expr;
1427
+ }
1428
+ /**
1429
+ * Parse logical OR.
1430
+ * @private
1431
+ */
1432
+ parseLogicalOr() {
1433
+ let left = this.parseLogicalAnd();
1434
+ while (this.match("OR" /* OR */)) {
1435
+ const operator = "or";
1436
+ const right = this.parseLogicalAnd();
1437
+ left = createBinaryOp(operator, left, right);
1438
+ }
1439
+ return left;
1440
+ }
1441
+ /**
1442
+ * Parse logical AND.
1443
+ * @private
1444
+ */
1445
+ parseLogicalAnd() {
1446
+ let left = this.parseBitwiseOr();
1447
+ while (this.match("AND" /* AND */)) {
1448
+ const operator = "and";
1449
+ const right = this.parseBitwiseOr();
1450
+ left = createBinaryOp(operator, left, right);
1451
+ }
1452
+ return left;
1453
+ }
1454
+ /**
1455
+ * Parse bitwise OR.
1456
+ * @private
1457
+ */
1458
+ parseBitwiseOr() {
1459
+ let left = this.parseBitwiseXor();
1460
+ while (this.match("PIPE" /* PIPE */)) {
1461
+ const operator = "|";
1462
+ const right = this.parseBitwiseXor();
1463
+ left = createBinaryOp(operator, left, right);
1464
+ }
1465
+ return left;
1466
+ }
1467
+ /**
1468
+ * Parse bitwise XOR.
1469
+ * @private
1470
+ */
1471
+ parseBitwiseXor() {
1472
+ let left = this.parseBitwiseAnd();
1473
+ while (this.match("CARET" /* CARET */)) {
1474
+ const operator = "^";
1475
+ const right = this.parseBitwiseAnd();
1476
+ left = createBinaryOp(operator, left, right);
1477
+ }
1478
+ return left;
1479
+ }
1480
+ /**
1481
+ * Parse bitwise AND.
1482
+ * @private
1483
+ */
1484
+ parseBitwiseAnd() {
1485
+ let left = this.parseEquality();
1486
+ while (this.match("AMPERSAND" /* AMPERSAND */)) {
1487
+ const operator = "&";
1488
+ const right = this.parseEquality();
1489
+ left = createBinaryOp(operator, left, right);
1490
+ }
1491
+ return left;
1492
+ }
1493
+ /**
1494
+ * Parse equality operators (==, !=).
1495
+ * @private
1496
+ */
1497
+ parseEquality() {
1498
+ let left = this.parseRelational();
1499
+ while (this.match("EQ" /* EQ */, "NE" /* NE */)) {
1500
+ const operator = this.tokens[this.position - 1].value;
1501
+ const right = this.parseRelational();
1502
+ left = createBinaryOp(operator, left, right);
1503
+ }
1504
+ return left;
1505
+ }
1506
+ /**
1507
+ * Parse relational operators (<, <=, >, >=).
1508
+ * @private
1509
+ */
1510
+ parseRelational() {
1511
+ let left = this.parseBitShift();
1512
+ while (this.match("LT" /* LT */, "LE" /* LE */, "GT" /* GT */, "GE" /* GE */)) {
1513
+ const operator = this.tokens[this.position - 1].value;
1514
+ const right = this.parseBitShift();
1515
+ left = createBinaryOp(operator, left, right);
1516
+ }
1517
+ return left;
1518
+ }
1519
+ /**
1520
+ * Parse bit shift operators (<<, >>).
1521
+ * @private
1522
+ */
1523
+ parseBitShift() {
1524
+ let left = this.parseAdditive();
1525
+ while (this.match("LSHIFT" /* LSHIFT */, "RSHIFT" /* RSHIFT */)) {
1526
+ const operator = this.tokens[this.position - 1].value;
1527
+ const right = this.parseAdditive();
1528
+ left = createBinaryOp(operator, left, right);
1529
+ }
1530
+ return left;
1531
+ }
1532
+ /**
1533
+ * Parse additive operators (+, -).
1534
+ * @private
1535
+ */
1536
+ parseAdditive() {
1537
+ let left = this.parseMultiplicative();
1538
+ while (this.match("PLUS" /* PLUS */, "MINUS" /* MINUS */)) {
1539
+ const operator = this.tokens[this.position - 1].value;
1540
+ const right = this.parseMultiplicative();
1541
+ left = createBinaryOp(operator, left, right);
1542
+ }
1543
+ return left;
1544
+ }
1545
+ /**
1546
+ * Parse multiplicative operators (*, /, %).
1547
+ * @private
1548
+ */
1549
+ parseMultiplicative() {
1550
+ let left = this.parseUnary();
1551
+ while (this.match("STAR" /* STAR */, "SLASH" /* SLASH */, "PERCENT" /* PERCENT */)) {
1552
+ const operator = this.tokens[this.position - 1].value;
1553
+ const right = this.parseUnary();
1554
+ left = createBinaryOp(operator, left, right);
1555
+ }
1556
+ return left;
1557
+ }
1558
+ /**
1559
+ * Parse unary operators (-, not).
1560
+ * @private
1561
+ */
1562
+ parseUnary() {
1563
+ if (this.match("MINUS" /* MINUS */, "NOT" /* NOT */)) {
1564
+ const operator = this.tokens[this.position - 1].value;
1565
+ const operand = this.parseUnary();
1566
+ return createUnaryOp(operator, operand);
1567
+ }
1568
+ return this.parsePostfix();
1569
+ }
1570
+ /**
1571
+ * Parse postfix operators (., [], ()).
1572
+ * @private
1573
+ */
1574
+ parsePostfix() {
1575
+ let expr = this.parsePrimary();
1576
+ while (true) {
1577
+ if (this.match("DOT" /* DOT */)) {
1578
+ const property = this.expect(
1579
+ "IDENTIFIER" /* IDENTIFIER */,
1580
+ "Expected property name after ."
1581
+ );
1582
+ expr = createMemberAccess(expr, property.value);
1583
+ } else if (this.match("LBRACKET" /* LBRACKET */)) {
1584
+ const index = this.parseTernary();
1585
+ this.expect("RBRACKET" /* RBRACKET */, "Expected ] after array index");
1586
+ expr = createIndexAccess(expr, index);
1587
+ } else if (this.current().type === "LPAREN" /* LPAREN */) {
1588
+ if (expr.kind === "MemberAccess") {
1589
+ this.advance();
1590
+ const args = [];
1591
+ if (this.current().type !== "RPAREN" /* RPAREN */) {
1592
+ args.push(this.parseTernary());
1593
+ while (this.match("COMMA" /* COMMA */)) {
1594
+ args.push(this.parseTernary());
1595
+ }
1596
+ }
1597
+ this.expect("RPAREN" /* RPAREN */, "Expected ) after arguments");
1598
+ const memberExpr = expr;
1599
+ expr = createMethodCall(memberExpr.object, memberExpr.property, args);
1600
+ } else {
1601
+ break;
1602
+ }
1603
+ } else {
1604
+ break;
1605
+ }
1606
+ }
1607
+ return expr;
1608
+ }
1609
+ /**
1610
+ * Parse primary expressions (literals, identifiers, grouping).
1611
+ * @private
1612
+ */
1613
+ parsePrimary() {
1614
+ if (this.match("NUMBER" /* NUMBER */, "STRING" /* STRING */, "BOOLEAN" /* BOOLEAN */)) {
1615
+ const token = this.tokens[this.position - 1];
1616
+ return createLiteral(token.value);
1617
+ }
1618
+ if (this.match("IDENTIFIER" /* IDENTIFIER */)) {
1619
+ const name = this.tokens[this.position - 1].value;
1620
+ if (this.match("DOUBLE_COLON" /* DOUBLE_COLON */)) {
1621
+ const value = this.expect(
1622
+ "IDENTIFIER" /* IDENTIFIER */,
1623
+ "Expected enum value after ::"
1624
+ );
1625
+ return createEnumAccess(name, value.value);
1626
+ }
1627
+ return createIdentifier(name);
1628
+ }
1629
+ if (this.match("LPAREN" /* LPAREN */)) {
1630
+ const expr = this.parseTernary();
1631
+ this.expect("RPAREN" /* RPAREN */, "Expected ) after expression");
1632
+ return expr;
1633
+ }
1634
+ throw new ParseError(
1635
+ `Unexpected token: ${this.current().type}`,
1636
+ this.current().position
1637
+ );
1638
+ }
1639
+ };
1640
+
1641
+ // src/expression/Evaluator.ts
1642
+ var Evaluator = class {
1643
+ /**
1644
+ * Evaluate an AST node in the given context.
1645
+ *
1646
+ * @param node - AST node to evaluate
1647
+ * @param context - Execution context
1648
+ * @returns Evaluated value
1649
+ * @throws {ParseError} If evaluation fails
1650
+ */
1651
+ evaluate(node, context) {
1652
+ const n = node;
1653
+ switch (node.kind) {
1654
+ case "Literal":
1655
+ return n.value;
1656
+ case "Identifier":
1657
+ return this.evaluateIdentifier(n.name, context);
1658
+ case "BinaryOp":
1659
+ return this.evaluateBinaryOp(n.operator, n.left, n.right, context);
1660
+ case "UnaryOp":
1661
+ return this.evaluateUnaryOp(n.operator, n.operand, context);
1662
+ case "Ternary":
1663
+ return this.evaluateTernary(n.condition, n.ifTrue, n.ifFalse, context);
1664
+ case "MemberAccess":
1665
+ return this.evaluateMemberAccess(n.object, n.property, context);
1666
+ case "IndexAccess":
1667
+ return this.evaluateIndexAccess(n.object, n.index, context);
1668
+ case "MethodCall":
1669
+ return this.evaluateMethodCall(n.object, n.method, n.args, context);
1670
+ case "EnumAccess":
1671
+ return this.evaluateEnumAccess(n.enumName, n.value, context);
1672
+ default:
1673
+ throw new ParseError(`Unknown AST node kind: ${node.kind}`);
1674
+ }
1675
+ }
1676
+ /**
1677
+ * Evaluate an identifier.
1678
+ * @private
1679
+ */
1680
+ evaluateIdentifier(name, context) {
1681
+ return context.resolve(name);
1682
+ }
1683
+ /**
1684
+ * Evaluate a binary operation.
1685
+ * @private
1686
+ */
1687
+ evaluateBinaryOp(operator, left, right, context) {
1688
+ const leftVal = this.evaluate(left, context);
1689
+ const rightVal = this.evaluate(right, context);
1690
+ switch (operator) {
1691
+ // Arithmetic
1692
+ case "+":
1693
+ return this.add(leftVal, rightVal);
1694
+ case "-":
1695
+ return this.toNumber(leftVal) - this.toNumber(rightVal);
1696
+ case "*":
1697
+ return this.toNumber(leftVal) * this.toNumber(rightVal);
1698
+ case "/":
1699
+ return this.toNumber(leftVal) / this.toNumber(rightVal);
1700
+ case "%":
1701
+ return this.modulo(this.toNumber(leftVal), this.toNumber(rightVal));
1702
+ // Comparison
1703
+ case "<":
1704
+ return this.compare(leftVal, rightVal) < 0;
1705
+ case "<=":
1706
+ return this.compare(leftVal, rightVal) <= 0;
1707
+ case ">":
1708
+ return this.compare(leftVal, rightVal) > 0;
1709
+ case ">=":
1710
+ return this.compare(leftVal, rightVal) >= 0;
1711
+ case "==":
1712
+ return this.equals(leftVal, rightVal);
1713
+ case "!=":
1714
+ return !this.equals(leftVal, rightVal);
1715
+ // Bitwise
1716
+ case "<<":
1717
+ return this.toInt(leftVal) << this.toInt(rightVal);
1718
+ case ">>":
1719
+ return this.toInt(leftVal) >> this.toInt(rightVal);
1720
+ case "&":
1721
+ return this.toInt(leftVal) & this.toInt(rightVal);
1722
+ case "|":
1723
+ return this.toInt(leftVal) | this.toInt(rightVal);
1724
+ case "^":
1725
+ return this.toInt(leftVal) ^ this.toInt(rightVal);
1726
+ // Logical
1727
+ case "and":
1728
+ return this.toBoolean(leftVal) && this.toBoolean(rightVal);
1729
+ case "or":
1730
+ return this.toBoolean(leftVal) || this.toBoolean(rightVal);
1731
+ default:
1732
+ throw new ParseError(`Unknown binary operator: ${operator}`);
1733
+ }
1734
+ }
1735
+ /**
1736
+ * Evaluate a unary operation.
1737
+ * @private
1738
+ */
1739
+ evaluateUnaryOp(operator, operand, context) {
1740
+ const value = this.evaluate(operand, context);
1741
+ switch (operator) {
1742
+ case "-":
1743
+ return -this.toNumber(value);
1744
+ case "not":
1745
+ return !this.toBoolean(value);
1746
+ default:
1747
+ throw new ParseError(`Unknown unary operator: ${operator}`);
1748
+ }
1749
+ }
1750
+ /**
1751
+ * Evaluate a ternary conditional.
1752
+ * @private
1753
+ */
1754
+ evaluateTernary(condition, ifTrue, ifFalse, context) {
1755
+ const condValue = this.evaluate(condition, context);
1756
+ return this.toBoolean(condValue) ? this.evaluate(ifTrue, context) : this.evaluate(ifFalse, context);
1757
+ }
1758
+ /**
1759
+ * Evaluate member access (object.property).
1760
+ * @private
1761
+ */
1762
+ evaluateMemberAccess(object, property, context) {
1763
+ const obj = this.evaluate(object, context);
1764
+ if (obj === null || obj === void 0) {
1765
+ throw new ParseError(
1766
+ `Cannot access property ${property} of null/undefined`
1767
+ );
1768
+ }
1769
+ if (typeof obj === "object") {
1770
+ return obj[property];
1771
+ }
1772
+ throw new ParseError(`Cannot access property ${property} of non-object`);
1773
+ }
1774
+ /**
1775
+ * Evaluate index access (array[index]).
1776
+ * @private
1777
+ */
1778
+ evaluateIndexAccess(object, index, context) {
1779
+ const obj = this.evaluate(object, context);
1780
+ const idx = this.evaluate(index, context);
1781
+ if (Array.isArray(obj)) {
1782
+ const numIdx = this.toInt(idx);
1783
+ return obj[numIdx];
1784
+ }
1785
+ if (obj instanceof Uint8Array) {
1786
+ const numIdx = this.toInt(idx);
1787
+ return obj[numIdx];
1788
+ }
1789
+ throw new ParseError("Index access requires an array");
1790
+ }
1791
+ /**
1792
+ * Evaluate method call (object.method()).
1793
+ * @private
1794
+ */
1795
+ evaluateMethodCall(object, method, _args, context) {
1796
+ const obj = this.evaluate(object, context);
1797
+ if (method === "length" || method === "size") {
1798
+ if (Array.isArray(obj)) return obj.length;
1799
+ if (obj instanceof Uint8Array) return obj.length;
1800
+ if (typeof obj === "string") return obj.length;
1801
+ throw new ParseError(`Object does not have a ${method} property`);
1802
+ }
1803
+ if (method === "to_i") {
1804
+ return this.toInt(obj);
1805
+ }
1806
+ if (method === "to_s") {
1807
+ return String(obj);
1808
+ }
1809
+ throw new ParseError(`Unknown method: ${method}`);
1810
+ }
1811
+ /**
1812
+ * Evaluate enum access (EnumName::value).
1813
+ * @private
1814
+ */
1815
+ evaluateEnumAccess(enumName, valueName, context) {
1816
+ const value = context.getEnumValue(enumName, valueName);
1817
+ if (value === void 0) {
1818
+ throw new ParseError(`Enum value "${enumName}::${valueName}" not found`);
1819
+ }
1820
+ return value;
1821
+ }
1822
+ /**
1823
+ * Helper: Add two values (handles strings and numbers).
1824
+ * @private
1825
+ */
1826
+ add(left, right) {
1827
+ if (typeof left === "string" || typeof right === "string") {
1828
+ return String(left) + String(right);
1829
+ }
1830
+ return this.toNumber(left) + this.toNumber(right);
1831
+ }
1832
+ /**
1833
+ * Helper: Modulo operation (Kaitai-style, not remainder).
1834
+ * @private
1835
+ */
1836
+ modulo(a, b) {
1837
+ const result = a % b;
1838
+ return result < 0 ? result + b : result;
1839
+ }
1840
+ /**
1841
+ * Helper: Compare two values.
1842
+ * @private
1843
+ */
1844
+ compare(left, right) {
1845
+ if (typeof left === "string" && typeof right === "string") {
1846
+ return left < right ? -1 : left > right ? 1 : 0;
1847
+ }
1848
+ const leftNum = this.toNumber(left);
1849
+ const rightNum = this.toNumber(right);
1850
+ return leftNum < rightNum ? -1 : leftNum > rightNum ? 1 : 0;
1851
+ }
1852
+ /**
1853
+ * Helper: Check equality.
1854
+ * @private
1855
+ */
1856
+ equals(left, right) {
1857
+ if (typeof left === "bigint" || typeof right === "bigint") {
1858
+ return BigInt(left) === BigInt(right);
1859
+ }
1860
+ return left === right;
1861
+ }
1862
+ /**
1863
+ * Helper: Convert to number.
1864
+ * @private
1865
+ */
1866
+ toNumber(value) {
1867
+ if (typeof value === "number") return value;
1868
+ if (typeof value === "bigint") return Number(value);
1869
+ if (typeof value === "boolean") return value ? 1 : 0;
1870
+ if (typeof value === "string") return parseFloat(value);
1871
+ throw new ParseError(`Cannot convert ${typeof value} to number`);
1872
+ }
1873
+ /**
1874
+ * Helper: Convert to integer.
1875
+ * @private
1876
+ */
1877
+ toInt(value) {
1878
+ return Math.floor(this.toNumber(value));
1879
+ }
1880
+ /**
1881
+ * Helper: Convert to boolean.
1882
+ * @private
1883
+ */
1884
+ toBoolean(value) {
1885
+ if (typeof value === "boolean") return value;
1886
+ if (typeof value === "number") return value !== 0;
1887
+ if (typeof value === "bigint") return value !== 0n;
1888
+ if (typeof value === "string") return value.length > 0;
1889
+ if (value === null || value === void 0) return false;
1890
+ return true;
1891
+ }
1892
+ };
1893
+
1894
+ // src/expression/index.ts
1895
+ function evaluateExpression(expression, context) {
1896
+ const lexer = new Lexer(expression);
1897
+ const tokens = lexer.tokenize();
1898
+ const parser = new ExpressionParser(tokens);
1899
+ const ast = parser.parse();
1900
+ const evaluator = new Evaluator();
1901
+ return evaluator.evaluate(ast, context);
1902
+ }
1903
+
963
1904
  // src/interpreter/TypeInterpreter.ts
964
1905
  var TypeInterpreter = class _TypeInterpreter {
965
1906
  /**
@@ -983,12 +1924,21 @@ var TypeInterpreter = class _TypeInterpreter {
983
1924
  *
984
1925
  * @param stream - Binary stream to parse
985
1926
  * @param parent - Parent object (for nested types)
1927
+ * @param typeArgs - Arguments for parametric types
986
1928
  * @returns Parsed object
987
1929
  */
988
- parse(stream, parent) {
1930
+ parse(stream, parent, typeArgs) {
989
1931
  const result = {};
990
- const context = new Context(stream, result, parent);
1932
+ const context = new Context(stream, result, parent, this.schema.enums);
991
1933
  context.current = result;
1934
+ if (typeArgs && this.schema.params) {
1935
+ for (let i = 0; i < this.schema.params.length && i < typeArgs.length; i++) {
1936
+ const param = this.schema.params[i];
1937
+ const argValue = typeArgs[i];
1938
+ const evaluatedArg = typeof argValue === "string" ? this.evaluateValue(argValue, context) : argValue;
1939
+ context.set(param.id, evaluatedArg);
1940
+ }
1941
+ }
992
1942
  if (this.schema.seq) {
993
1943
  for (const attr of this.schema.seq) {
994
1944
  const value = this.parseAttribute(attr, context);
@@ -997,8 +1947,83 @@ var TypeInterpreter = class _TypeInterpreter {
997
1947
  }
998
1948
  }
999
1949
  }
1950
+ if (this.schema.instances) {
1951
+ this.setupInstances(result, stream, context);
1952
+ }
1000
1953
  return result;
1001
1954
  }
1955
+ /**
1956
+ * Set up lazy-evaluated instance getters.
1957
+ * Instances are computed on first access and cached.
1958
+ *
1959
+ * @param result - Result object to add getters to
1960
+ * @param stream - Stream for parsing
1961
+ * @param context - Execution context
1962
+ * @private
1963
+ */
1964
+ setupInstances(result, stream, context) {
1965
+ if (!this.schema.instances) return;
1966
+ for (const [name, instance] of Object.entries(this.schema.instances)) {
1967
+ let cached = void 0;
1968
+ let evaluated = false;
1969
+ Object.defineProperty(result, name, {
1970
+ get: () => {
1971
+ if (!evaluated) {
1972
+ cached = this.parseInstance(
1973
+ instance,
1974
+ stream,
1975
+ context
1976
+ );
1977
+ evaluated = true;
1978
+ }
1979
+ return cached;
1980
+ },
1981
+ enumerable: true,
1982
+ configurable: true
1983
+ });
1984
+ }
1985
+ }
1986
+ /**
1987
+ * Parse an instance (lazy-evaluated field).
1988
+ *
1989
+ * @param instance - Instance specification
1990
+ * @param stream - Stream to read from
1991
+ * @param context - Execution context
1992
+ * @returns Parsed or calculated value
1993
+ * @private
1994
+ */
1995
+ parseInstance(instance, stream, context) {
1996
+ if ("value" in instance) {
1997
+ return this.evaluateValue(
1998
+ instance.value,
1999
+ context
2000
+ );
2001
+ }
2002
+ const savedPos = stream.pos;
2003
+ try {
2004
+ if (instance.pos !== void 0) {
2005
+ const pos = this.evaluateValue(
2006
+ instance.pos,
2007
+ context
2008
+ );
2009
+ if (typeof pos === "number") {
2010
+ stream.seek(pos);
2011
+ } else if (typeof pos === "bigint") {
2012
+ stream.seek(Number(pos));
2013
+ } else {
2014
+ throw new ParseError(
2015
+ `pos must evaluate to a number, got ${typeof pos}`
2016
+ );
2017
+ }
2018
+ }
2019
+ const value = this.parseAttribute(instance, context);
2020
+ return value;
2021
+ } finally {
2022
+ if (instance.pos !== void 0) {
2023
+ stream.seek(savedPos);
2024
+ }
2025
+ }
2026
+ }
1002
2027
  /**
1003
2028
  * Parse a single attribute according to its specification.
1004
2029
  *
@@ -1010,11 +2035,20 @@ var TypeInterpreter = class _TypeInterpreter {
1010
2035
  parseAttribute(attr, context) {
1011
2036
  const stream = context.io;
1012
2037
  if (attr.if) {
1013
- throw new NotImplementedError("Conditional parsing (if)");
2038
+ const condition = this.evaluateValue(attr.if, context);
2039
+ if (!condition) {
2040
+ return void 0;
2041
+ }
1014
2042
  }
1015
2043
  if (attr.pos !== void 0) {
1016
- const pos = typeof attr.pos === "number" ? attr.pos : 0;
1017
- stream.seek(pos);
2044
+ const pos = this.evaluateValue(attr.pos, context);
2045
+ if (typeof pos === "number") {
2046
+ stream.seek(pos);
2047
+ } else if (typeof pos === "bigint") {
2048
+ stream.seek(Number(pos));
2049
+ } else {
2050
+ throw new ParseError(`pos must evaluate to a number, got ${typeof pos}`);
2051
+ }
1018
2052
  }
1019
2053
  if (attr.io) {
1020
2054
  throw new NotImplementedError("Custom I/O streams");
@@ -1025,7 +2059,8 @@ var TypeInterpreter = class _TypeInterpreter {
1025
2059
  if (attr.contents) {
1026
2060
  return this.parseContents(attr, context);
1027
2061
  }
1028
- return this.parseValue(attr, context);
2062
+ const value = this.parseValue(attr, context);
2063
+ return value;
1029
2064
  }
1030
2065
  /**
1031
2066
  * Parse a repeated attribute.
@@ -1036,14 +2071,22 @@ var TypeInterpreter = class _TypeInterpreter {
1036
2071
  * @private
1037
2072
  */
1038
2073
  parseRepeated(attr, context) {
1039
- const result = [];
1040
2074
  const stream = context.io;
2075
+ const result = [];
1041
2076
  switch (attr.repeat) {
1042
2077
  case "expr": {
1043
- const count = typeof attr["repeat-expr"] === "number" ? attr["repeat-expr"] : 0;
2078
+ const countValue = this.evaluateValue(attr["repeat-expr"], context);
2079
+ const count = typeof countValue === "number" ? countValue : typeof countValue === "bigint" ? Number(countValue) : 0;
2080
+ if (count < 0) {
2081
+ throw new ParseError(`repeat-expr must be non-negative, got ${count}`);
2082
+ }
1044
2083
  for (let i = 0; i < count; i++) {
1045
2084
  context.set("_index", i);
1046
- result.push(this.parseValue(attr, context));
2085
+ const value = this.parseAttribute(
2086
+ { ...attr, repeat: void 0, "repeat-expr": void 0 },
2087
+ context
2088
+ );
2089
+ result.push(value);
1047
2090
  }
1048
2091
  break;
1049
2092
  }
@@ -1058,7 +2101,25 @@ var TypeInterpreter = class _TypeInterpreter {
1058
2101
  if (!attr["repeat-until"]) {
1059
2102
  throw new ParseError("repeat-until expression is required");
1060
2103
  }
1061
- throw new NotImplementedError("repeat-until");
2104
+ let index = 0;
2105
+ while (true) {
2106
+ context.set("_index", index);
2107
+ const value = this.parseAttribute(
2108
+ { ...attr, repeat: void 0, "repeat-until": void 0 },
2109
+ context
2110
+ );
2111
+ result.push(value);
2112
+ context.set("_", value);
2113
+ const condition = this.evaluateValue(attr["repeat-until"], context);
2114
+ if (condition) {
2115
+ break;
2116
+ }
2117
+ if (stream.isEof()) {
2118
+ break;
2119
+ }
2120
+ index++;
2121
+ }
2122
+ break;
1062
2123
  }
1063
2124
  default:
1064
2125
  throw new ParseError(`Unknown repeat type: ${attr.repeat}`);
@@ -1111,17 +2172,34 @@ var TypeInterpreter = class _TypeInterpreter {
1111
2172
  const stream = context.io;
1112
2173
  const type = attr.type;
1113
2174
  if (attr.size !== void 0) {
1114
- const size = typeof attr.size === "number" ? attr.size : 0;
2175
+ const sizeValue = this.evaluateValue(attr.size, context);
2176
+ const size = typeof sizeValue === "number" ? sizeValue : typeof sizeValue === "bigint" ? Number(sizeValue) : 0;
2177
+ if (size < 0) {
2178
+ throw new ParseError(`size must be non-negative, got ${size}`);
2179
+ }
1115
2180
  if (type === "str" || !type) {
1116
2181
  const encoding = attr.encoding || this.schema.meta.encoding || "UTF-8";
2182
+ let data;
1117
2183
  if (type === "str") {
1118
- return stream.readStr(size, encoding);
2184
+ data = stream.readBytes(size);
2185
+ if (attr.process) {
2186
+ data = this.applyProcessing(data, attr.process);
2187
+ }
2188
+ return new TextDecoder(encoding).decode(data);
1119
2189
  } else {
1120
- return stream.readBytes(size);
2190
+ data = stream.readBytes(size);
2191
+ if (attr.process) {
2192
+ data = this.applyProcessing(data, attr.process);
2193
+ }
2194
+ return data;
1121
2195
  }
1122
2196
  } else {
1123
- const substream = stream.substream(size);
1124
- return this.parseType(type, substream, context);
2197
+ let data = stream.readBytes(size);
2198
+ if (attr.process) {
2199
+ data = this.applyProcessing(data, attr.process);
2200
+ }
2201
+ const substream = new KaitaiStream(data);
2202
+ return this.parseType(type, substream, context, attr["type-args"]);
1125
2203
  }
1126
2204
  }
1127
2205
  if (attr["size-eos"]) {
@@ -1136,7 +2214,7 @@ var TypeInterpreter = class _TypeInterpreter {
1136
2214
  if (!type) {
1137
2215
  throw new ParseError("Attribute must have either type, size, or contents");
1138
2216
  }
1139
- return this.parseType(type, stream, context);
2217
+ return this.parseType(type, stream, context, attr["type-args"]);
1140
2218
  }
1141
2219
  /**
1142
2220
  * Parse a value of a specific type.
@@ -1144,12 +2222,17 @@ var TypeInterpreter = class _TypeInterpreter {
1144
2222
  * @param type - Type name or switch specification
1145
2223
  * @param stream - Stream to read from
1146
2224
  * @param context - Execution context
2225
+ * @param typeArgs - Arguments for parametric types
1147
2226
  * @returns Parsed value
1148
2227
  * @private
1149
2228
  */
1150
- parseType(type, stream, context) {
2229
+ parseType(type, stream, context, typeArgs) {
1151
2230
  if (typeof type === "object") {
1152
- throw new NotImplementedError("Switch types");
2231
+ return this.parseSwitchType(
2232
+ type,
2233
+ stream,
2234
+ context
2235
+ );
1153
2236
  }
1154
2237
  if (isBuiltinType(type)) {
1155
2238
  return this.parseBuiltinType(type, stream, context);
@@ -1157,11 +2240,49 @@ var TypeInterpreter = class _TypeInterpreter {
1157
2240
  if (this.schema.types && type in this.schema.types) {
1158
2241
  const typeSchema = this.schema.types[type];
1159
2242
  const meta = this.schema.meta || this.parentMeta;
2243
+ if (this.schema.enums && !typeSchema.enums) {
2244
+ typeSchema.enums = this.schema.enums;
2245
+ }
2246
+ if (this.schema.types && !typeSchema.types) {
2247
+ typeSchema.types = this.schema.types;
2248
+ }
1160
2249
  const interpreter = new _TypeInterpreter(typeSchema, meta);
1161
- return interpreter.parse(stream, context.current);
2250
+ return interpreter.parse(stream, context.current, typeArgs);
1162
2251
  }
1163
2252
  throw new ParseError(`Unknown type: ${type}`);
1164
2253
  }
2254
+ /**
2255
+ * Parse a switch type (type selection based on expression).
2256
+ *
2257
+ * @param switchType - Switch type specification
2258
+ * @param stream - Stream to read from
2259
+ * @param context - Execution context
2260
+ * @returns Parsed value
2261
+ * @private
2262
+ */
2263
+ parseSwitchType(switchType, stream, context) {
2264
+ const switchOn = switchType["switch-on"];
2265
+ const cases = switchType["cases"];
2266
+ const defaultType = switchType["default"];
2267
+ if (!switchOn || typeof switchOn !== "string") {
2268
+ throw new ParseError("switch-on expression is required for switch types");
2269
+ }
2270
+ if (!cases) {
2271
+ throw new ParseError("cases are required for switch types");
2272
+ }
2273
+ const switchValue = this.evaluateValue(switchOn, context);
2274
+ const switchKey = String(switchValue);
2275
+ let selectedType = cases[switchKey];
2276
+ if (selectedType === void 0 && defaultType) {
2277
+ selectedType = defaultType;
2278
+ }
2279
+ if (selectedType === void 0) {
2280
+ throw new ParseError(
2281
+ `No matching case for switch value "${switchKey}" and no default type specified`
2282
+ );
2283
+ }
2284
+ return this.parseType(selectedType, stream, context);
2285
+ }
1165
2286
  /**
1166
2287
  * Parse a built-in type.
1167
2288
  *
@@ -1238,6 +2359,50 @@ var TypeInterpreter = class _TypeInterpreter {
1238
2359
  throw new ParseError(`Unknown float type: ${type}`);
1239
2360
  }
1240
2361
  }
2362
+ /**
2363
+ * Apply processing transformation to data.
2364
+ * Supports basic transformations like zlib decompression.
2365
+ *
2366
+ * @param data - Data to process
2367
+ * @param process - Processing specification
2368
+ * @returns Processed data
2369
+ * @private
2370
+ */
2371
+ applyProcessing(data, process) {
2372
+ const processType = typeof process === "string" ? process : process.algorithm;
2373
+ if (processType) {
2374
+ throw new NotImplementedError(
2375
+ `Processing type "${processType}" is not yet implemented. Supported in future versions with zlib, encryption, etc.`
2376
+ );
2377
+ }
2378
+ return data;
2379
+ }
2380
+ /**
2381
+ * Evaluate a value that can be an expression or literal.
2382
+ *
2383
+ * @param value - Value to evaluate (expression string, number, or boolean)
2384
+ * @param context - Execution context
2385
+ * @returns Evaluated result
2386
+ * @private
2387
+ */
2388
+ evaluateValue(value, context) {
2389
+ if (value === void 0) {
2390
+ return void 0;
2391
+ }
2392
+ if (typeof value === "number" || typeof value === "boolean") {
2393
+ return value;
2394
+ }
2395
+ if (typeof value === "string") {
2396
+ try {
2397
+ return evaluateExpression(value, context);
2398
+ } catch (error) {
2399
+ throw new ParseError(
2400
+ `Failed to evaluate expression "${value}": ${error instanceof Error ? error.message : String(error)}`
2401
+ );
2402
+ }
2403
+ }
2404
+ return value;
2405
+ }
1241
2406
  };
1242
2407
 
1243
2408
  // src/index.ts
@@ -1316,6 +2481,42 @@ export {
1316
2481
  * @author Fabiano Pinto
1317
2482
  * @license MIT
1318
2483
  */
2484
+ /**
2485
+ * @fileoverview Token types for Kaitai Struct expression language
2486
+ * @module expression/Token
2487
+ * @author Fabiano Pinto
2488
+ * @license MIT
2489
+ */
2490
+ /**
2491
+ * @fileoverview Lexer for Kaitai Struct expression language
2492
+ * @module expression/Lexer
2493
+ * @author Fabiano Pinto
2494
+ * @license MIT
2495
+ */
2496
+ /**
2497
+ * @fileoverview Abstract Syntax Tree nodes for expression language
2498
+ * @module expression/AST
2499
+ * @author Fabiano Pinto
2500
+ * @license MIT
2501
+ */
2502
+ /**
2503
+ * @fileoverview Parser for Kaitai Struct expression language
2504
+ * @module expression/Parser
2505
+ * @author Fabiano Pinto
2506
+ * @license MIT
2507
+ */
2508
+ /**
2509
+ * @fileoverview Evaluator for Kaitai Struct expression AST
2510
+ * @module expression/Evaluator
2511
+ * @author Fabiano Pinto
2512
+ * @license MIT
2513
+ */
2514
+ /**
2515
+ * @fileoverview Expression evaluation module
2516
+ * @module expression
2517
+ * @author Fabiano Pinto
2518
+ * @license MIT
2519
+ */
1319
2520
  /**
1320
2521
  * @fileoverview Type interpreter for executing Kaitai Struct schemas
1321
2522
  * @module interpreter/TypeInterpreter