redscript-mc 1.2.30 → 2.0.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.
Files changed (269) hide show
  1. package/.claude/commands/build-test.md +10 -0
  2. package/.claude/commands/deploy-demo.md +12 -0
  3. package/.claude/commands/stage-status.md +13 -0
  4. package/.claude/settings.json +12 -0
  5. package/.github/workflows/ci.yml +1 -0
  6. package/CLAUDE.md +231 -0
  7. package/demo.gif +0 -0
  8. package/dist/cli.js +2 -554
  9. package/dist/compile.js +2 -266
  10. package/dist/index.js +2 -159
  11. package/dist/lowering/index.js +5 -3
  12. package/dist/src/__tests__/cli.test.d.ts +1 -0
  13. package/dist/src/__tests__/cli.test.js +104 -0
  14. package/dist/src/__tests__/codegen.test.d.ts +1 -0
  15. package/dist/src/__tests__/codegen.test.js +152 -0
  16. package/dist/src/__tests__/compile-all.test.d.ts +10 -0
  17. package/dist/src/__tests__/compile-all.test.js +108 -0
  18. package/dist/src/__tests__/dce.test.d.ts +1 -0
  19. package/dist/src/__tests__/dce.test.js +102 -0
  20. package/dist/src/__tests__/diagnostics.test.d.ts +4 -0
  21. package/dist/src/__tests__/diagnostics.test.js +177 -0
  22. package/dist/src/__tests__/e2e.test.d.ts +6 -0
  23. package/dist/src/__tests__/e2e.test.js +1789 -0
  24. package/dist/src/__tests__/entity-types.test.d.ts +1 -0
  25. package/dist/src/__tests__/entity-types.test.js +203 -0
  26. package/dist/src/__tests__/formatter.test.d.ts +1 -0
  27. package/dist/src/__tests__/formatter.test.js +40 -0
  28. package/dist/src/__tests__/lexer.test.d.ts +1 -0
  29. package/dist/src/__tests__/lexer.test.js +343 -0
  30. package/dist/src/__tests__/lowering.test.d.ts +1 -0
  31. package/dist/src/__tests__/lowering.test.js +1015 -0
  32. package/dist/src/__tests__/macro.test.d.ts +8 -0
  33. package/dist/src/__tests__/macro.test.js +306 -0
  34. package/dist/src/__tests__/mc-integration.test.d.ts +12 -0
  35. package/dist/src/__tests__/mc-integration.test.js +817 -0
  36. package/dist/src/__tests__/mc-syntax.test.d.ts +1 -0
  37. package/dist/src/__tests__/mc-syntax.test.js +124 -0
  38. package/dist/src/__tests__/nbt.test.d.ts +1 -0
  39. package/dist/src/__tests__/nbt.test.js +82 -0
  40. package/dist/src/__tests__/optimizer-advanced.test.d.ts +1 -0
  41. package/dist/src/__tests__/optimizer-advanced.test.js +124 -0
  42. package/dist/src/__tests__/optimizer.test.d.ts +1 -0
  43. package/dist/src/__tests__/optimizer.test.js +149 -0
  44. package/dist/src/__tests__/parser.test.d.ts +1 -0
  45. package/dist/src/__tests__/parser.test.js +807 -0
  46. package/dist/src/__tests__/repl.test.d.ts +1 -0
  47. package/dist/src/__tests__/repl.test.js +27 -0
  48. package/dist/src/__tests__/runtime.test.d.ts +1 -0
  49. package/dist/src/__tests__/runtime.test.js +289 -0
  50. package/dist/src/__tests__/stdlib-advanced.test.d.ts +4 -0
  51. package/dist/src/__tests__/stdlib-advanced.test.js +374 -0
  52. package/dist/src/__tests__/stdlib-bigint.test.d.ts +7 -0
  53. package/dist/src/__tests__/stdlib-bigint.test.js +426 -0
  54. package/dist/src/__tests__/stdlib-math.test.d.ts +7 -0
  55. package/dist/src/__tests__/stdlib-math.test.js +351 -0
  56. package/dist/src/__tests__/stdlib-vec.test.d.ts +4 -0
  57. package/dist/src/__tests__/stdlib-vec.test.js +263 -0
  58. package/dist/src/__tests__/structure-optimizer.test.d.ts +1 -0
  59. package/dist/src/__tests__/structure-optimizer.test.js +33 -0
  60. package/dist/src/__tests__/typechecker.test.d.ts +1 -0
  61. package/dist/src/__tests__/typechecker.test.js +552 -0
  62. package/dist/src/__tests__/var-allocator.test.d.ts +1 -0
  63. package/dist/src/__tests__/var-allocator.test.js +69 -0
  64. package/dist/src/ast/types.d.ts +515 -0
  65. package/dist/src/ast/types.js +9 -0
  66. package/dist/src/builtins/metadata.d.ts +36 -0
  67. package/dist/src/builtins/metadata.js +1014 -0
  68. package/dist/src/cli.d.ts +11 -0
  69. package/dist/src/cli.js +443 -0
  70. package/dist/src/codegen/cmdblock/index.d.ts +26 -0
  71. package/dist/src/codegen/cmdblock/index.js +45 -0
  72. package/dist/src/codegen/mcfunction/index.d.ts +40 -0
  73. package/dist/src/codegen/mcfunction/index.js +606 -0
  74. package/dist/src/codegen/structure/index.d.ts +24 -0
  75. package/dist/src/codegen/structure/index.js +279 -0
  76. package/dist/src/codegen/var-allocator.d.ts +45 -0
  77. package/dist/src/codegen/var-allocator.js +104 -0
  78. package/dist/src/compile.d.ts +37 -0
  79. package/dist/src/compile.js +165 -0
  80. package/dist/src/diagnostics/index.d.ts +44 -0
  81. package/dist/src/diagnostics/index.js +140 -0
  82. package/dist/src/events/types.d.ts +35 -0
  83. package/dist/src/events/types.js +59 -0
  84. package/dist/src/formatter/index.d.ts +1 -0
  85. package/dist/src/formatter/index.js +26 -0
  86. package/dist/src/index.d.ts +22 -0
  87. package/dist/src/index.js +45 -0
  88. package/dist/src/ir/builder.d.ts +33 -0
  89. package/dist/src/ir/builder.js +99 -0
  90. package/dist/src/ir/types.d.ts +132 -0
  91. package/dist/src/ir/types.js +15 -0
  92. package/dist/src/lexer/index.d.ts +37 -0
  93. package/dist/src/lexer/index.js +569 -0
  94. package/dist/src/lowering/index.d.ts +188 -0
  95. package/dist/src/lowering/index.js +3405 -0
  96. package/dist/src/mc-test/client.d.ts +128 -0
  97. package/dist/src/mc-test/client.js +174 -0
  98. package/dist/src/mc-test/runner.d.ts +28 -0
  99. package/dist/src/mc-test/runner.js +151 -0
  100. package/dist/src/mc-test/setup.d.ts +11 -0
  101. package/dist/src/mc-test/setup.js +98 -0
  102. package/dist/src/mc-validator/index.d.ts +17 -0
  103. package/dist/src/mc-validator/index.js +322 -0
  104. package/dist/src/nbt/index.d.ts +86 -0
  105. package/dist/src/nbt/index.js +250 -0
  106. package/dist/src/optimizer/commands.d.ts +38 -0
  107. package/dist/src/optimizer/commands.js +451 -0
  108. package/dist/src/optimizer/dce.d.ts +34 -0
  109. package/dist/src/optimizer/dce.js +639 -0
  110. package/dist/src/optimizer/passes.d.ts +34 -0
  111. package/dist/src/optimizer/passes.js +243 -0
  112. package/dist/src/optimizer/structure.d.ts +9 -0
  113. package/dist/src/optimizer/structure.js +356 -0
  114. package/dist/src/parser/index.d.ts +93 -0
  115. package/dist/src/parser/index.js +1687 -0
  116. package/dist/src/repl.d.ts +16 -0
  117. package/dist/src/repl.js +165 -0
  118. package/dist/src/runtime/index.d.ts +107 -0
  119. package/dist/src/runtime/index.js +1409 -0
  120. package/dist/src/typechecker/index.d.ts +61 -0
  121. package/dist/src/typechecker/index.js +1034 -0
  122. package/dist/src/types/entity-hierarchy.d.ts +29 -0
  123. package/dist/src/types/entity-hierarchy.js +107 -0
  124. package/dist/src2/__tests__/e2e/basic.test.d.ts +8 -0
  125. package/dist/src2/__tests__/e2e/basic.test.js +140 -0
  126. package/dist/src2/__tests__/e2e/macros.test.d.ts +9 -0
  127. package/dist/src2/__tests__/e2e/macros.test.js +182 -0
  128. package/dist/src2/__tests__/e2e/migrate.test.d.ts +13 -0
  129. package/dist/src2/__tests__/e2e/migrate.test.js +2739 -0
  130. package/dist/src2/__tests__/hir/desugar.test.d.ts +1 -0
  131. package/dist/src2/__tests__/hir/desugar.test.js +234 -0
  132. package/dist/src2/__tests__/lir/lower.test.d.ts +1 -0
  133. package/dist/src2/__tests__/lir/lower.test.js +559 -0
  134. package/dist/src2/__tests__/lir/types.test.d.ts +1 -0
  135. package/dist/src2/__tests__/lir/types.test.js +185 -0
  136. package/dist/src2/__tests__/lir/verify.test.d.ts +1 -0
  137. package/dist/src2/__tests__/lir/verify.test.js +221 -0
  138. package/dist/src2/__tests__/mir/arithmetic.test.d.ts +1 -0
  139. package/dist/src2/__tests__/mir/arithmetic.test.js +130 -0
  140. package/dist/src2/__tests__/mir/control-flow.test.d.ts +1 -0
  141. package/dist/src2/__tests__/mir/control-flow.test.js +205 -0
  142. package/dist/src2/__tests__/mir/verify.test.d.ts +1 -0
  143. package/dist/src2/__tests__/mir/verify.test.js +223 -0
  144. package/dist/src2/__tests__/optimizer/block_merge.test.d.ts +1 -0
  145. package/dist/src2/__tests__/optimizer/block_merge.test.js +78 -0
  146. package/dist/src2/__tests__/optimizer/branch_simplify.test.d.ts +1 -0
  147. package/dist/src2/__tests__/optimizer/branch_simplify.test.js +58 -0
  148. package/dist/src2/__tests__/optimizer/constant_fold.test.d.ts +1 -0
  149. package/dist/src2/__tests__/optimizer/constant_fold.test.js +131 -0
  150. package/dist/src2/__tests__/optimizer/copy_prop.test.d.ts +1 -0
  151. package/dist/src2/__tests__/optimizer/copy_prop.test.js +91 -0
  152. package/dist/src2/__tests__/optimizer/dce.test.d.ts +1 -0
  153. package/dist/src2/__tests__/optimizer/dce.test.js +76 -0
  154. package/dist/src2/__tests__/optimizer/pipeline.test.d.ts +1 -0
  155. package/dist/src2/__tests__/optimizer/pipeline.test.js +102 -0
  156. package/dist/src2/emit/compile.d.ts +19 -0
  157. package/dist/src2/emit/compile.js +80 -0
  158. package/dist/src2/emit/index.d.ts +17 -0
  159. package/dist/src2/emit/index.js +172 -0
  160. package/dist/src2/hir/lower.d.ts +15 -0
  161. package/dist/src2/hir/lower.js +378 -0
  162. package/dist/src2/hir/types.d.ts +373 -0
  163. package/dist/src2/hir/types.js +16 -0
  164. package/dist/src2/lir/lower.d.ts +15 -0
  165. package/dist/src2/lir/lower.js +453 -0
  166. package/dist/src2/lir/types.d.ts +136 -0
  167. package/dist/src2/lir/types.js +11 -0
  168. package/dist/src2/lir/verify.d.ts +14 -0
  169. package/dist/src2/lir/verify.js +113 -0
  170. package/dist/src2/mir/lower.d.ts +9 -0
  171. package/dist/src2/mir/lower.js +1030 -0
  172. package/dist/src2/mir/macro.d.ts +22 -0
  173. package/dist/src2/mir/macro.js +168 -0
  174. package/dist/src2/mir/types.d.ts +183 -0
  175. package/dist/src2/mir/types.js +11 -0
  176. package/dist/src2/mir/verify.d.ts +16 -0
  177. package/dist/src2/mir/verify.js +216 -0
  178. package/dist/src2/optimizer/block_merge.d.ts +12 -0
  179. package/dist/src2/optimizer/block_merge.js +84 -0
  180. package/dist/src2/optimizer/branch_simplify.d.ts +9 -0
  181. package/dist/src2/optimizer/branch_simplify.js +28 -0
  182. package/dist/src2/optimizer/constant_fold.d.ts +10 -0
  183. package/dist/src2/optimizer/constant_fold.js +85 -0
  184. package/dist/src2/optimizer/copy_prop.d.ts +9 -0
  185. package/dist/src2/optimizer/copy_prop.js +113 -0
  186. package/dist/src2/optimizer/dce.d.ts +8 -0
  187. package/dist/src2/optimizer/dce.js +155 -0
  188. package/dist/src2/optimizer/pipeline.d.ts +10 -0
  189. package/dist/src2/optimizer/pipeline.js +42 -0
  190. package/dist/tsconfig.tsbuildinfo +1 -0
  191. package/docs/compiler-pipeline-redesign.md +2243 -0
  192. package/docs/optimization-ideas.md +1076 -0
  193. package/editors/vscode/package-lock.json +3 -3
  194. package/editors/vscode/package.json +1 -1
  195. package/jest.config.js +1 -1
  196. package/package.json +6 -5
  197. package/scripts/postbuild.js +15 -0
  198. package/src/__tests__/cli.test.ts +8 -220
  199. package/src/__tests__/dce.test.ts +11 -56
  200. package/src/__tests__/diagnostics.test.ts +59 -38
  201. package/src/__tests__/mc-integration.test.ts +1 -2
  202. package/src/ast/types.ts +6 -1
  203. package/src/cli.ts +29 -156
  204. package/src/compile.ts +6 -162
  205. package/src/index.ts +14 -178
  206. package/src/mc-test/runner.ts +4 -3
  207. package/src/parser/index.ts +1 -1
  208. package/src/repl.ts +1 -1
  209. package/src/runtime/index.ts +1 -1
  210. package/src2/__tests__/e2e/basic.test.ts +154 -0
  211. package/src2/__tests__/e2e/macros.test.ts +199 -0
  212. package/src2/__tests__/e2e/migrate.test.ts +3008 -0
  213. package/src2/__tests__/hir/desugar.test.ts +263 -0
  214. package/src2/__tests__/lir/lower.test.ts +619 -0
  215. package/src2/__tests__/lir/types.test.ts +207 -0
  216. package/src2/__tests__/lir/verify.test.ts +249 -0
  217. package/src2/__tests__/mir/arithmetic.test.ts +156 -0
  218. package/src2/__tests__/mir/control-flow.test.ts +242 -0
  219. package/src2/__tests__/mir/verify.test.ts +254 -0
  220. package/src2/__tests__/optimizer/block_merge.test.ts +84 -0
  221. package/src2/__tests__/optimizer/branch_simplify.test.ts +64 -0
  222. package/src2/__tests__/optimizer/constant_fold.test.ts +145 -0
  223. package/src2/__tests__/optimizer/copy_prop.test.ts +99 -0
  224. package/src2/__tests__/optimizer/dce.test.ts +83 -0
  225. package/src2/__tests__/optimizer/pipeline.test.ts +116 -0
  226. package/src2/emit/compile.ts +99 -0
  227. package/src2/emit/index.ts +222 -0
  228. package/src2/hir/lower.ts +428 -0
  229. package/src2/hir/types.ts +216 -0
  230. package/src2/lir/lower.ts +556 -0
  231. package/src2/lir/types.ts +109 -0
  232. package/src2/lir/verify.ts +129 -0
  233. package/src2/mir/lower.ts +1160 -0
  234. package/src2/mir/macro.ts +167 -0
  235. package/src2/mir/types.ts +106 -0
  236. package/src2/mir/verify.ts +218 -0
  237. package/src2/optimizer/block_merge.ts +93 -0
  238. package/src2/optimizer/branch_simplify.ts +27 -0
  239. package/src2/optimizer/constant_fold.ts +88 -0
  240. package/src2/optimizer/copy_prop.ts +106 -0
  241. package/src2/optimizer/dce.ts +133 -0
  242. package/src2/optimizer/pipeline.ts +44 -0
  243. package/tsconfig.json +2 -2
  244. package/src/__tests__/codegen.test.ts +0 -161
  245. package/src/__tests__/e2e.test.ts +0 -2039
  246. package/src/__tests__/entity-types.test.ts +0 -236
  247. package/src/__tests__/lowering.test.ts +0 -1185
  248. package/src/__tests__/macro.test.ts +0 -343
  249. package/src/__tests__/nbt.test.ts +0 -58
  250. package/src/__tests__/optimizer-advanced.test.ts +0 -144
  251. package/src/__tests__/optimizer.test.ts +0 -162
  252. package/src/__tests__/runtime.test.ts +0 -305
  253. package/src/__tests__/stdlib-advanced.test.ts +0 -379
  254. package/src/__tests__/stdlib-bigint.test.ts +0 -427
  255. package/src/__tests__/stdlib-math.test.ts +0 -374
  256. package/src/__tests__/stdlib-vec.test.ts +0 -259
  257. package/src/__tests__/structure-optimizer.test.ts +0 -38
  258. package/src/__tests__/var-allocator.test.ts +0 -75
  259. package/src/codegen/cmdblock/index.ts +0 -63
  260. package/src/codegen/mcfunction/index.ts +0 -662
  261. package/src/codegen/structure/index.ts +0 -346
  262. package/src/codegen/var-allocator.ts +0 -104
  263. package/src/ir/builder.ts +0 -116
  264. package/src/ir/types.ts +0 -134
  265. package/src/lowering/index.ts +0 -3876
  266. package/src/optimizer/commands.ts +0 -534
  267. package/src/optimizer/dce.ts +0 -679
  268. package/src/optimizer/passes.ts +0 -250
  269. package/src/optimizer/structure.ts +0 -450
@@ -0,0 +1,569 @@
1
+ "use strict";
2
+ /**
3
+ * RedScript Lexer
4
+ *
5
+ * Tokenizes RedScript source code into a stream of tokens.
6
+ * Handles special cases like entity selectors vs decorators,
7
+ * range literals, and raw commands.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.Lexer = void 0;
11
+ const diagnostics_1 = require("../diagnostics");
12
+ // ---------------------------------------------------------------------------
13
+ // Keywords Map
14
+ // ---------------------------------------------------------------------------
15
+ const KEYWORDS = {
16
+ fn: 'fn',
17
+ let: 'let',
18
+ const: 'const',
19
+ if: 'if',
20
+ else: 'else',
21
+ while: 'while',
22
+ for: 'for',
23
+ foreach: 'foreach',
24
+ match: 'match',
25
+ return: 'return',
26
+ break: 'break',
27
+ continue: 'continue',
28
+ as: 'as',
29
+ at: 'at',
30
+ in: 'in',
31
+ is: 'is',
32
+ struct: 'struct',
33
+ impl: 'impl',
34
+ enum: 'enum',
35
+ trigger: 'trigger',
36
+ namespace: 'namespace',
37
+ module: 'module',
38
+ execute: 'execute',
39
+ run: 'run',
40
+ unless: 'unless',
41
+ declare: 'declare',
42
+ int: 'int',
43
+ bool: 'bool',
44
+ float: 'float',
45
+ string: 'string',
46
+ void: 'void',
47
+ BlockPos: 'BlockPos',
48
+ true: 'true',
49
+ false: 'false',
50
+ };
51
+ // Entity selector base characters
52
+ const SELECTOR_CHARS = new Set(['a', 'e', 's', 'p', 'r', 'n']);
53
+ // ---------------------------------------------------------------------------
54
+ // Lexer Class
55
+ // ---------------------------------------------------------------------------
56
+ class Lexer {
57
+ constructor(source, filePath) {
58
+ this.pos = 0;
59
+ this.line = 1;
60
+ this.col = 1;
61
+ this.tokens = [];
62
+ this.source = source;
63
+ this.sourceLines = source.split('\n');
64
+ this.filePath = filePath;
65
+ }
66
+ error(message, line, col) {
67
+ throw new diagnostics_1.DiagnosticError('LexError', message, { file: this.filePath, line: line ?? this.line, col: col ?? this.col }, this.sourceLines);
68
+ }
69
+ tokenize() {
70
+ while (!this.isAtEnd()) {
71
+ this.scanToken();
72
+ }
73
+ this.tokens.push({ kind: 'eof', value: '', line: this.line, col: this.col });
74
+ return this.tokens;
75
+ }
76
+ isAtEnd() {
77
+ return this.pos >= this.source.length;
78
+ }
79
+ peek(offset = 0) {
80
+ const idx = this.pos + offset;
81
+ if (idx >= this.source.length)
82
+ return '\0';
83
+ return this.source[idx];
84
+ }
85
+ advance() {
86
+ const char = this.source[this.pos++];
87
+ if (char === '\n') {
88
+ this.line++;
89
+ this.col = 1;
90
+ }
91
+ else {
92
+ this.col++;
93
+ }
94
+ return char;
95
+ }
96
+ addToken(kind, value, line, col) {
97
+ this.tokens.push({ kind, value, line, col });
98
+ }
99
+ scanToken() {
100
+ const startLine = this.line;
101
+ const startCol = this.col;
102
+ const char = this.advance();
103
+ // Whitespace
104
+ if (/\s/.test(char))
105
+ return;
106
+ // Comments
107
+ if (char === '/' && this.peek() === '/') {
108
+ // Skip to end of line
109
+ while (!this.isAtEnd() && this.peek() !== '\n') {
110
+ this.advance();
111
+ }
112
+ return;
113
+ }
114
+ // Block comments: /* ... */ and /** ... */
115
+ if (char === '/' && this.peek() === '*') {
116
+ this.advance(); // consume '*'
117
+ while (!this.isAtEnd()) {
118
+ if (this.peek() === '*' && this.peek(1) === '/') {
119
+ this.advance(); // consume '*'
120
+ this.advance(); // consume '/'
121
+ break;
122
+ }
123
+ this.advance();
124
+ }
125
+ return;
126
+ }
127
+ // Two-character operators
128
+ if (char === '-' && this.peek() === '>') {
129
+ this.advance();
130
+ this.addToken('->', '->', startLine, startCol);
131
+ return;
132
+ }
133
+ if (char === '=' && this.peek() === '>') {
134
+ this.advance();
135
+ this.addToken('=>', '=>', startLine, startCol);
136
+ return;
137
+ }
138
+ if (char === '=' && this.peek() === '=') {
139
+ this.advance();
140
+ this.addToken('==', '==', startLine, startCol);
141
+ return;
142
+ }
143
+ if (char === '!' && this.peek() === '=') {
144
+ this.advance();
145
+ this.addToken('!=', '!=', startLine, startCol);
146
+ return;
147
+ }
148
+ if (char === '<' && this.peek() === '=') {
149
+ this.advance();
150
+ this.addToken('<=', '<=', startLine, startCol);
151
+ return;
152
+ }
153
+ if (char === '>' && this.peek() === '=') {
154
+ this.advance();
155
+ this.addToken('>=', '>=', startLine, startCol);
156
+ return;
157
+ }
158
+ if (char === '&' && this.peek() === '&') {
159
+ this.advance();
160
+ this.addToken('&&', '&&', startLine, startCol);
161
+ return;
162
+ }
163
+ if (char === '|' && this.peek() === '|') {
164
+ this.advance();
165
+ this.addToken('||', '||', startLine, startCol);
166
+ return;
167
+ }
168
+ if (char === '+' && this.peek() === '=') {
169
+ this.advance();
170
+ this.addToken('+=', '+=', startLine, startCol);
171
+ return;
172
+ }
173
+ if (char === '-' && this.peek() === '=') {
174
+ this.advance();
175
+ this.addToken('-=', '-=', startLine, startCol);
176
+ return;
177
+ }
178
+ if (char === '*' && this.peek() === '=') {
179
+ this.advance();
180
+ this.addToken('*=', '*=', startLine, startCol);
181
+ return;
182
+ }
183
+ if (char === '/' && this.peek() === '=') {
184
+ this.advance();
185
+ this.addToken('/=', '/=', startLine, startCol);
186
+ return;
187
+ }
188
+ if (char === '%' && this.peek() === '=') {
189
+ this.advance();
190
+ this.addToken('%=', '%=', startLine, startCol);
191
+ return;
192
+ }
193
+ // Double colon ::
194
+ if (char === ':' && this.peek() === ':') {
195
+ this.advance();
196
+ this.addToken('::', '::', startLine, startCol);
197
+ return;
198
+ }
199
+ // Range literal starting with ..
200
+ if (char === '.' && this.peek() === '.') {
201
+ this.advance(); // consume second .
202
+ let value = '..';
203
+ while (/[0-9]/.test(this.peek())) {
204
+ value += this.advance();
205
+ }
206
+ this.addToken('range_lit', value, startLine, startCol);
207
+ return;
208
+ }
209
+ // Relative coordinate: ~ or ~5 or ~-3 or ~0.5
210
+ if (char === '~') {
211
+ let value = '~';
212
+ // Check for optional sign
213
+ if (this.peek() === '-' || this.peek() === '+') {
214
+ value += this.advance();
215
+ }
216
+ // Check for number
217
+ while (/[0-9]/.test(this.peek())) {
218
+ value += this.advance();
219
+ }
220
+ // Check for decimal part
221
+ if (this.peek() === '.' && /[0-9]/.test(this.peek(1))) {
222
+ value += this.advance(); // .
223
+ while (/[0-9]/.test(this.peek())) {
224
+ value += this.advance();
225
+ }
226
+ }
227
+ // Check for ident (e.g. ~height → macro variable offset)
228
+ if (/[a-zA-Z_]/.test(this.peek())) {
229
+ let ident = '';
230
+ while (/[a-zA-Z0-9_]/.test(this.peek())) {
231
+ ident += this.advance();
232
+ }
233
+ // Store as rel_coord with embedded ident: ~height
234
+ value += ident;
235
+ }
236
+ this.addToken('rel_coord', value, startLine, startCol);
237
+ return;
238
+ }
239
+ // Local coordinate: ^ or ^5 or ^-3 or ^0.5 or ^varname (macro variable)
240
+ if (char === '^') {
241
+ let value = '^';
242
+ // Check for identifier (variable name for macro substitution, e.g. ^px, ^height)
243
+ if (/[a-zA-Z_]/.test(this.peek())) {
244
+ while (/[a-zA-Z0-9_]/.test(this.peek())) {
245
+ value += this.advance();
246
+ }
247
+ this.addToken('local_coord', value, startLine, startCol);
248
+ return;
249
+ }
250
+ // Check for optional sign
251
+ if (this.peek() === '-' || this.peek() === '+') {
252
+ value += this.advance();
253
+ }
254
+ // Check for number
255
+ while (/[0-9]/.test(this.peek())) {
256
+ value += this.advance();
257
+ }
258
+ // Check for decimal part
259
+ if (this.peek() === '.' && /[0-9]/.test(this.peek(1))) {
260
+ value += this.advance(); // .
261
+ while (/[0-9]/.test(this.peek())) {
262
+ value += this.advance();
263
+ }
264
+ }
265
+ this.addToken('local_coord', value, startLine, startCol);
266
+ return;
267
+ }
268
+ // Single-character operators and delimiters
269
+ const singleChar = ['+', '-', '*', '/', '%', '<', '>', '!', '=',
270
+ '{', '}', '(', ')', '[', ']', ',', ';', ':', '.'];
271
+ if (singleChar.includes(char)) {
272
+ this.addToken(char, char, startLine, startCol);
273
+ return;
274
+ }
275
+ // @ - selector or decorator
276
+ if (char === '@') {
277
+ this.scanAtToken(startLine, startCol);
278
+ return;
279
+ }
280
+ // f-string literal
281
+ if (char === 'f' && this.peek() === '"') {
282
+ this.advance();
283
+ this.scanFString(startLine, startCol);
284
+ return;
285
+ }
286
+ // String literal
287
+ if (char === '"') {
288
+ this.scanString(startLine, startCol);
289
+ return;
290
+ }
291
+ // MC name literal: #ident (e.g. #health, #red, #hasKey)
292
+ if (char === '#') {
293
+ const nextChar = this.peek();
294
+ if (/[a-zA-Z_]/.test(nextChar)) {
295
+ let name = '#';
296
+ while (/[a-zA-Z0-9_]/.test(this.peek())) {
297
+ name += this.advance();
298
+ }
299
+ this.addToken('mc_name', name, startLine, startCol);
300
+ return;
301
+ }
302
+ // Lone # (not followed by ident) — treat as unknown char error
303
+ this.error(`Unexpected character '#'`, startLine, startCol);
304
+ return;
305
+ }
306
+ // Number (int or float) or range literal starting with number
307
+ if (/[0-9]/.test(char)) {
308
+ this.scanNumber(char, startLine, startCol);
309
+ return;
310
+ }
311
+ // Identifier or keyword
312
+ if (/[a-zA-Z_]/.test(char)) {
313
+ this.scanIdentifier(char, startLine, startCol);
314
+ return;
315
+ }
316
+ this.error(`Unexpected character '${char}'`, startLine, startCol);
317
+ }
318
+ scanAtToken(startLine, startCol) {
319
+ // Check if it's a selector (@a, @e, @s, @p, @r, @n)
320
+ const nextChar = this.peek();
321
+ const afterNext = this.peek(1);
322
+ // Selector: @a/@e/@s/@p/@r/@n followed by non-letter (or end, or [)
323
+ if (SELECTOR_CHARS.has(nextChar) && !/[a-zA-Z_0-9]/.test(afterNext)) {
324
+ const selectorChar = this.advance(); // consume a/e/s/p/r/n
325
+ let value = '@' + selectorChar;
326
+ // Check for [...] parameters
327
+ if (this.peek() === '[') {
328
+ value += this.scanSelectorParams();
329
+ }
330
+ this.addToken('selector', value, startLine, startCol);
331
+ return;
332
+ }
333
+ // Otherwise it's a decorator (@tick, @on_trigger, etc.)
334
+ let value = '@';
335
+ while (/[a-zA-Z_0-9]/.test(this.peek())) {
336
+ value += this.advance();
337
+ }
338
+ // Check for decorator arguments (rate=N)
339
+ if (this.peek() === '(') {
340
+ value += this.advance(); // (
341
+ let parenDepth = 1;
342
+ while (!this.isAtEnd() && parenDepth > 0) {
343
+ const c = this.advance();
344
+ value += c;
345
+ if (c === '(')
346
+ parenDepth++;
347
+ if (c === ')')
348
+ parenDepth--;
349
+ }
350
+ }
351
+ this.addToken('decorator', value, startLine, startCol);
352
+ }
353
+ scanSelectorParams() {
354
+ let result = this.advance(); // consume [
355
+ let depth = 1;
356
+ let braceDepth = 0;
357
+ while (!this.isAtEnd() && depth > 0) {
358
+ const c = this.advance();
359
+ result += c;
360
+ if (c === '{')
361
+ braceDepth++;
362
+ else if (c === '}')
363
+ braceDepth--;
364
+ else if (c === '[' && braceDepth === 0)
365
+ depth++;
366
+ else if (c === ']' && braceDepth === 0)
367
+ depth--;
368
+ }
369
+ return result;
370
+ }
371
+ scanString(startLine, startCol) {
372
+ let value = '';
373
+ let interpolationDepth = 0;
374
+ let interpolationString = false;
375
+ while (!this.isAtEnd()) {
376
+ if (interpolationDepth === 0 && this.peek() === '"') {
377
+ break;
378
+ }
379
+ if (this.peek() === '\\' && this.peek(1) === '"') {
380
+ this.advance(); // skip backslash
381
+ value += this.advance(); // add escaped quote
382
+ continue;
383
+ }
384
+ if (interpolationDepth === 0 && this.peek() === '$' && this.peek(1) === '{') {
385
+ value += this.advance();
386
+ value += this.advance();
387
+ interpolationDepth = 1;
388
+ interpolationString = false;
389
+ continue;
390
+ }
391
+ const char = this.advance();
392
+ value += char;
393
+ if (interpolationDepth === 0)
394
+ continue;
395
+ if (char === '"') {
396
+ interpolationString = !interpolationString;
397
+ continue;
398
+ }
399
+ if (interpolationString)
400
+ continue;
401
+ if (char === '{')
402
+ interpolationDepth++;
403
+ if (char === '}')
404
+ interpolationDepth--;
405
+ }
406
+ if (this.isAtEnd()) {
407
+ this.error(`Unterminated string`, startLine, startCol);
408
+ }
409
+ this.advance(); // closing quote
410
+ this.addToken('string_lit', value, startLine, startCol);
411
+ }
412
+ scanFString(startLine, startCol) {
413
+ let value = '';
414
+ let interpolationDepth = 0;
415
+ let interpolationString = false;
416
+ while (!this.isAtEnd()) {
417
+ if (interpolationDepth === 0 && this.peek() === '"') {
418
+ break;
419
+ }
420
+ if (this.peek() === '\\' && this.peek(1) === '"') {
421
+ this.advance();
422
+ value += this.advance();
423
+ continue;
424
+ }
425
+ if (interpolationDepth === 0 && this.peek() === '{') {
426
+ value += this.advance();
427
+ interpolationDepth = 1;
428
+ interpolationString = false;
429
+ continue;
430
+ }
431
+ const char = this.advance();
432
+ value += char;
433
+ if (interpolationDepth === 0)
434
+ continue;
435
+ if (char === '"' && this.source[this.pos - 2] !== '\\') {
436
+ interpolationString = !interpolationString;
437
+ continue;
438
+ }
439
+ if (interpolationString)
440
+ continue;
441
+ if (char === '{')
442
+ interpolationDepth++;
443
+ if (char === '}')
444
+ interpolationDepth--;
445
+ }
446
+ if (this.isAtEnd()) {
447
+ this.error('Unterminated f-string', startLine, startCol);
448
+ }
449
+ this.advance(); // closing quote
450
+ this.addToken('f_string', value, startLine, startCol);
451
+ }
452
+ scanNumber(firstChar, startLine, startCol) {
453
+ let value = firstChar;
454
+ // Consume integer part
455
+ while (/[0-9]/.test(this.peek())) {
456
+ value += this.advance();
457
+ }
458
+ // Check for range literal (e.g., 1.., 1..10)
459
+ if (this.peek() === '.' && this.peek(1) === '.') {
460
+ value += this.advance(); // first .
461
+ value += this.advance(); // second .
462
+ // Optional max value
463
+ while (/[0-9]/.test(this.peek())) {
464
+ value += this.advance();
465
+ }
466
+ this.addToken('range_lit', value, startLine, startCol);
467
+ return;
468
+ }
469
+ // Check for float
470
+ if (this.peek() === '.' && /[0-9]/.test(this.peek(1))) {
471
+ value += this.advance(); // .
472
+ while (/[0-9]/.test(this.peek())) {
473
+ value += this.advance();
474
+ }
475
+ // Check for NBT float/double suffix
476
+ const floatSuffix = this.peek().toLowerCase();
477
+ if (floatSuffix === 'f') {
478
+ value += this.advance();
479
+ this.addToken('float_lit', value, startLine, startCol);
480
+ return;
481
+ }
482
+ if (floatSuffix === 'd') {
483
+ value += this.advance();
484
+ this.addToken('double_lit', value, startLine, startCol);
485
+ return;
486
+ }
487
+ this.addToken('float_lit', value, startLine, startCol);
488
+ return;
489
+ }
490
+ // Check for NBT integer suffix (b, s, L/l, f, d)
491
+ const intSuffix = this.peek().toLowerCase();
492
+ if (intSuffix === 'b' && !/[a-zA-Z_0-9]/.test(this.peek(1))) {
493
+ value += this.advance();
494
+ this.addToken('byte_lit', value, startLine, startCol);
495
+ return;
496
+ }
497
+ if (intSuffix === 's' && !/[a-zA-Z_0-9]/.test(this.peek(1))) {
498
+ value += this.advance();
499
+ this.addToken('short_lit', value, startLine, startCol);
500
+ return;
501
+ }
502
+ if (intSuffix === 'l' && !/[a-zA-Z_0-9]/.test(this.peek(1))) {
503
+ value += this.advance();
504
+ this.addToken('long_lit', value, startLine, startCol);
505
+ return;
506
+ }
507
+ if (intSuffix === 'f' && !/[a-zA-Z_0-9]/.test(this.peek(1))) {
508
+ value += this.advance();
509
+ this.addToken('float_lit', value, startLine, startCol);
510
+ return;
511
+ }
512
+ if (intSuffix === 'd' && !/[a-zA-Z_0-9]/.test(this.peek(1))) {
513
+ value += this.advance();
514
+ this.addToken('double_lit', value, startLine, startCol);
515
+ return;
516
+ }
517
+ this.addToken('int_lit', value, startLine, startCol);
518
+ }
519
+ scanIdentifier(firstChar, startLine, startCol) {
520
+ let value = firstChar;
521
+ while (/[a-zA-Z_0-9]/.test(this.peek())) {
522
+ value += this.advance();
523
+ }
524
+ // Check for raw command
525
+ if (value === 'raw' && this.peek() === '(') {
526
+ this.advance(); // consume (
527
+ // Skip whitespace
528
+ while (/\s/.test(this.peek())) {
529
+ this.advance();
530
+ }
531
+ // Expect string
532
+ if (this.peek() === '"') {
533
+ this.advance(); // consume opening quote
534
+ let rawContent = '';
535
+ while (!this.isAtEnd() && this.peek() !== '"') {
536
+ if (this.peek() === '\\' && this.peek(1) === '"') {
537
+ this.advance();
538
+ rawContent += this.advance();
539
+ }
540
+ else {
541
+ rawContent += this.advance();
542
+ }
543
+ }
544
+ if (this.peek() === '"') {
545
+ this.advance(); // closing quote
546
+ }
547
+ // Skip whitespace and closing paren
548
+ while (/\s/.test(this.peek())) {
549
+ this.advance();
550
+ }
551
+ if (this.peek() === ')') {
552
+ this.advance(); // closing paren
553
+ }
554
+ this.addToken('raw_cmd', rawContent, startLine, startCol);
555
+ return;
556
+ }
557
+ }
558
+ // Check for keyword
559
+ const keyword = KEYWORDS[value];
560
+ if (keyword) {
561
+ this.addToken(keyword, value, startLine, startCol);
562
+ }
563
+ else {
564
+ this.addToken('ident', value, startLine, startCol);
565
+ }
566
+ }
567
+ }
568
+ exports.Lexer = Lexer;
569
+ //# sourceMappingURL=index.js.map