@aigne/ash 0.0.1

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 (146) hide show
  1. package/DESIGN.md +41 -0
  2. package/dist/ai-dev-loop/ash-run-result.cjs +12 -0
  3. package/dist/ai-dev-loop/ash-run-result.d.cts +28 -0
  4. package/dist/ai-dev-loop/ash-run-result.d.cts.map +1 -0
  5. package/dist/ai-dev-loop/ash-run-result.d.mts +28 -0
  6. package/dist/ai-dev-loop/ash-run-result.d.mts.map +1 -0
  7. package/dist/ai-dev-loop/ash-run-result.mjs +11 -0
  8. package/dist/ai-dev-loop/ash-run-result.mjs.map +1 -0
  9. package/dist/ai-dev-loop/ash-typed-error.cjs +51 -0
  10. package/dist/ai-dev-loop/ash-typed-error.d.cts +54 -0
  11. package/dist/ai-dev-loop/ash-typed-error.d.cts.map +1 -0
  12. package/dist/ai-dev-loop/ash-typed-error.d.mts +54 -0
  13. package/dist/ai-dev-loop/ash-typed-error.d.mts.map +1 -0
  14. package/dist/ai-dev-loop/ash-typed-error.mjs +50 -0
  15. package/dist/ai-dev-loop/ash-typed-error.mjs.map +1 -0
  16. package/dist/ai-dev-loop/ash-validate.cjs +27 -0
  17. package/dist/ai-dev-loop/ash-validate.d.cts +7 -0
  18. package/dist/ai-dev-loop/ash-validate.d.cts.map +1 -0
  19. package/dist/ai-dev-loop/ash-validate.d.mts +7 -0
  20. package/dist/ai-dev-loop/ash-validate.d.mts.map +1 -0
  21. package/dist/ai-dev-loop/ash-validate.mjs +28 -0
  22. package/dist/ai-dev-loop/ash-validate.mjs.map +1 -0
  23. package/dist/ai-dev-loop/dev-loop.cjs +134 -0
  24. package/dist/ai-dev-loop/dev-loop.d.cts +28 -0
  25. package/dist/ai-dev-loop/dev-loop.d.cts.map +1 -0
  26. package/dist/ai-dev-loop/dev-loop.d.mts +28 -0
  27. package/dist/ai-dev-loop/dev-loop.d.mts.map +1 -0
  28. package/dist/ai-dev-loop/dev-loop.mjs +135 -0
  29. package/dist/ai-dev-loop/dev-loop.mjs.map +1 -0
  30. package/dist/ai-dev-loop/index.cjs +24 -0
  31. package/dist/ai-dev-loop/index.d.cts +9 -0
  32. package/dist/ai-dev-loop/index.d.mts +9 -0
  33. package/dist/ai-dev-loop/index.mjs +10 -0
  34. package/dist/ai-dev-loop/live-mode.cjs +17 -0
  35. package/dist/ai-dev-loop/live-mode.d.cts +24 -0
  36. package/dist/ai-dev-loop/live-mode.d.cts.map +1 -0
  37. package/dist/ai-dev-loop/live-mode.d.mts +24 -0
  38. package/dist/ai-dev-loop/live-mode.d.mts.map +1 -0
  39. package/dist/ai-dev-loop/live-mode.mjs +17 -0
  40. package/dist/ai-dev-loop/live-mode.mjs.map +1 -0
  41. package/dist/ai-dev-loop/meta-tools.cjs +123 -0
  42. package/dist/ai-dev-loop/meta-tools.d.cts +24 -0
  43. package/dist/ai-dev-loop/meta-tools.d.cts.map +1 -0
  44. package/dist/ai-dev-loop/meta-tools.d.mts +24 -0
  45. package/dist/ai-dev-loop/meta-tools.d.mts.map +1 -0
  46. package/dist/ai-dev-loop/meta-tools.mjs +120 -0
  47. package/dist/ai-dev-loop/meta-tools.mjs.map +1 -0
  48. package/dist/ai-dev-loop/structured-runner.cjs +154 -0
  49. package/dist/ai-dev-loop/structured-runner.d.cts +12 -0
  50. package/dist/ai-dev-loop/structured-runner.d.cts.map +1 -0
  51. package/dist/ai-dev-loop/structured-runner.d.mts +12 -0
  52. package/dist/ai-dev-loop/structured-runner.d.mts.map +1 -0
  53. package/dist/ai-dev-loop/structured-runner.mjs +155 -0
  54. package/dist/ai-dev-loop/structured-runner.mjs.map +1 -0
  55. package/dist/ai-dev-loop/system-prompt.cjs +55 -0
  56. package/dist/ai-dev-loop/system-prompt.d.cts +20 -0
  57. package/dist/ai-dev-loop/system-prompt.d.cts.map +1 -0
  58. package/dist/ai-dev-loop/system-prompt.d.mts +20 -0
  59. package/dist/ai-dev-loop/system-prompt.d.mts.map +1 -0
  60. package/dist/ai-dev-loop/system-prompt.mjs +54 -0
  61. package/dist/ai-dev-loop/system-prompt.mjs.map +1 -0
  62. package/dist/ast.d.cts +140 -0
  63. package/dist/ast.d.cts.map +1 -0
  64. package/dist/ast.d.mts +140 -0
  65. package/dist/ast.d.mts.map +1 -0
  66. package/dist/compiler.cjs +802 -0
  67. package/dist/compiler.d.cts +103 -0
  68. package/dist/compiler.d.cts.map +1 -0
  69. package/dist/compiler.d.mts +103 -0
  70. package/dist/compiler.d.mts.map +1 -0
  71. package/dist/compiler.mjs +802 -0
  72. package/dist/compiler.mjs.map +1 -0
  73. package/dist/index.cjs +14 -0
  74. package/dist/index.d.cts +7 -0
  75. package/dist/index.d.mts +7 -0
  76. package/dist/index.mjs +7 -0
  77. package/dist/lexer.cjs +451 -0
  78. package/dist/lexer.d.cts +14 -0
  79. package/dist/lexer.d.cts.map +1 -0
  80. package/dist/lexer.d.mts +14 -0
  81. package/dist/lexer.d.mts.map +1 -0
  82. package/dist/lexer.mjs +451 -0
  83. package/dist/lexer.mjs.map +1 -0
  84. package/dist/parser.cjs +734 -0
  85. package/dist/parser.d.cts +40 -0
  86. package/dist/parser.d.cts.map +1 -0
  87. package/dist/parser.d.mts +40 -0
  88. package/dist/parser.d.mts.map +1 -0
  89. package/dist/parser.mjs +734 -0
  90. package/dist/parser.mjs.map +1 -0
  91. package/dist/reference.cjs +130 -0
  92. package/dist/reference.d.cts +11 -0
  93. package/dist/reference.d.cts.map +1 -0
  94. package/dist/reference.d.mts +11 -0
  95. package/dist/reference.d.mts.map +1 -0
  96. package/dist/reference.mjs +130 -0
  97. package/dist/reference.mjs.map +1 -0
  98. package/dist/template.cjs +85 -0
  99. package/dist/template.mjs +84 -0
  100. package/dist/template.mjs.map +1 -0
  101. package/dist/type-checker.cjs +582 -0
  102. package/dist/type-checker.d.cts +31 -0
  103. package/dist/type-checker.d.cts.map +1 -0
  104. package/dist/type-checker.d.mts +31 -0
  105. package/dist/type-checker.d.mts.map +1 -0
  106. package/dist/type-checker.mjs +573 -0
  107. package/dist/type-checker.mjs.map +1 -0
  108. package/package.json +29 -0
  109. package/src/ai-dev-loop/ash-run-result.test.ts +113 -0
  110. package/src/ai-dev-loop/ash-run-result.ts +46 -0
  111. package/src/ai-dev-loop/ash-typed-error.test.ts +136 -0
  112. package/src/ai-dev-loop/ash-typed-error.ts +50 -0
  113. package/src/ai-dev-loop/ash-validate.test.ts +54 -0
  114. package/src/ai-dev-loop/ash-validate.ts +34 -0
  115. package/src/ai-dev-loop/dev-loop.test.ts +364 -0
  116. package/src/ai-dev-loop/dev-loop.ts +156 -0
  117. package/src/ai-dev-loop/dry-run.test.ts +107 -0
  118. package/src/ai-dev-loop/e2e-multi-fix.test.ts +473 -0
  119. package/src/ai-dev-loop/e2e.test.ts +324 -0
  120. package/src/ai-dev-loop/index.ts +15 -0
  121. package/src/ai-dev-loop/invariants.test.ts +253 -0
  122. package/src/ai-dev-loop/live-mode.test.ts +63 -0
  123. package/src/ai-dev-loop/live-mode.ts +33 -0
  124. package/src/ai-dev-loop/meta-tools.test.ts +120 -0
  125. package/src/ai-dev-loop/meta-tools.ts +142 -0
  126. package/src/ai-dev-loop/structured-runner.test.ts +159 -0
  127. package/src/ai-dev-loop/structured-runner.ts +209 -0
  128. package/src/ai-dev-loop/system-prompt.test.ts +102 -0
  129. package/src/ai-dev-loop/system-prompt.ts +81 -0
  130. package/src/ast.ts +186 -0
  131. package/src/compiler.test.ts +2933 -0
  132. package/src/compiler.ts +1103 -0
  133. package/src/e2e.test.ts +552 -0
  134. package/src/index.ts +16 -0
  135. package/src/lexer.test.ts +538 -0
  136. package/src/lexer.ts +222 -0
  137. package/src/parser.test.ts +1024 -0
  138. package/src/parser.ts +835 -0
  139. package/src/reference.test.ts +166 -0
  140. package/src/reference.ts +125 -0
  141. package/src/template.test.ts +210 -0
  142. package/src/template.ts +139 -0
  143. package/src/type-checker.test.ts +1494 -0
  144. package/src/type-checker.ts +785 -0
  145. package/tsconfig.json +9 -0
  146. package/tsdown.config.ts +12 -0
@@ -0,0 +1,14 @@
1
+ //#region src/lexer.d.ts
2
+ type TokenType = "JOB" | "FIND" | "WHERE" | "MAP" | "SAVE" | "PUBLISH" | "TEE" | "FANOUT" | "INPUT" | "OUTPUT" | "ACTION" | "ROUTE" | "LOOKUP" | "ARROW" | "PLUS" | "MINUS" | "STAR" | "SLASH" | "PIPE" | "ASSIGN" | "DOT" | "COMMA" | "COLON" | "LPAREN" | "RPAREN" | "LBRACKET" | "RBRACKET" | "LBRACE" | "RBRACE" | "IDENTIFIER" | "STRING" | "NUMBER" | "PATH" | "AT" | "GT" | "LT" | "GTE" | "LTE" | "EQ" | "NEQ" | "LET" | "PARAM" | "ON" | "DOLLAR" | "COUNT" | "GROUP_BY" | "NEWLINE" | "EOF";
3
+ interface Token {
4
+ type: TokenType;
5
+ value: string;
6
+ line: number;
7
+ column: number;
8
+ }
9
+ declare class AshLexer {
10
+ tokenize(source: string): Token[];
11
+ }
12
+ //#endregion
13
+ export { AshLexer, Token, TokenType };
14
+ //# sourceMappingURL=lexer.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.d.cts","names":[],"sources":["../src/lexer.ts"],"mappings":";KAAY,SAAA;AAAA,UAWK,KAAA;EACf,IAAA,EAAM,SAAA;EACN,KAAA;EACA,IAAA;EACA,MAAA;AAAA;AAAA,cAuBW,QAAA;EACX,QAAA,CAAS,MAAA,WAAiB,KAAA;AAAA"}
@@ -0,0 +1,14 @@
1
+ //#region src/lexer.d.ts
2
+ type TokenType = "JOB" | "FIND" | "WHERE" | "MAP" | "SAVE" | "PUBLISH" | "TEE" | "FANOUT" | "INPUT" | "OUTPUT" | "ACTION" | "ROUTE" | "LOOKUP" | "ARROW" | "PLUS" | "MINUS" | "STAR" | "SLASH" | "PIPE" | "ASSIGN" | "DOT" | "COMMA" | "COLON" | "LPAREN" | "RPAREN" | "LBRACKET" | "RBRACKET" | "LBRACE" | "RBRACE" | "IDENTIFIER" | "STRING" | "NUMBER" | "PATH" | "AT" | "GT" | "LT" | "GTE" | "LTE" | "EQ" | "NEQ" | "LET" | "PARAM" | "ON" | "DOLLAR" | "COUNT" | "GROUP_BY" | "NEWLINE" | "EOF";
3
+ interface Token {
4
+ type: TokenType;
5
+ value: string;
6
+ line: number;
7
+ column: number;
8
+ }
9
+ declare class AshLexer {
10
+ tokenize(source: string): Token[];
11
+ }
12
+ //#endregion
13
+ export { AshLexer, Token, TokenType };
14
+ //# sourceMappingURL=lexer.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.d.mts","names":[],"sources":["../src/lexer.ts"],"mappings":";KAAY,SAAA;AAAA,UAWK,KAAA;EACf,IAAA,EAAM,SAAA;EACN,KAAA;EACA,IAAA;EACA,MAAA;AAAA;AAAA,cAuBW,QAAA;EACX,QAAA,CAAS,MAAA,WAAiB,KAAA;AAAA"}
package/dist/lexer.mjs ADDED
@@ -0,0 +1,451 @@
1
+ //#region src/lexer.ts
2
+ const KEYWORDS = {
3
+ job: "JOB",
4
+ find: "FIND",
5
+ where: "WHERE",
6
+ map: "MAP",
7
+ save: "SAVE",
8
+ publish: "PUBLISH",
9
+ tee: "TEE",
10
+ fanout: "FANOUT",
11
+ input: "INPUT",
12
+ output: "OUTPUT",
13
+ let: "LET",
14
+ count: "COUNT",
15
+ action: "ACTION",
16
+ route: "ROUTE",
17
+ lookup: "LOOKUP",
18
+ param: "PARAM",
19
+ on: "ON"
20
+ };
21
+ var AshLexer = class {
22
+ tokenize(source) {
23
+ const tokens = [];
24
+ let pos = 0;
25
+ let line = 1;
26
+ let col = 1;
27
+ while (pos < source.length) {
28
+ const ch = source[pos];
29
+ if (ch === "\n" || ch === "\r") {
30
+ if (ch === "\r" && source[pos + 1] === "\n") pos++;
31
+ tokens.push({
32
+ type: "NEWLINE",
33
+ value: "\\n",
34
+ line,
35
+ column: col
36
+ });
37
+ pos++;
38
+ line++;
39
+ col = 1;
40
+ continue;
41
+ }
42
+ if (ch === " " || ch === " ") {
43
+ pos++;
44
+ col++;
45
+ continue;
46
+ }
47
+ if (ch === "#") {
48
+ while (pos < source.length && source[pos] !== "\n" && source[pos] !== "\r") {
49
+ pos++;
50
+ col++;
51
+ }
52
+ continue;
53
+ }
54
+ if (ch === "\"") {
55
+ const startCol = col;
56
+ pos++;
57
+ col++;
58
+ let value = "";
59
+ while (pos < source.length && source[pos] !== "\"") {
60
+ if (source[pos] === "\\") {
61
+ pos++;
62
+ col++;
63
+ if (pos >= source.length) break;
64
+ const escaped = source[pos];
65
+ if (escaped === "\"") value += "\"";
66
+ else if (escaped === "\\") value += "\\";
67
+ else if (escaped === "n") value += "\n";
68
+ else if (escaped === "t") value += " ";
69
+ else if (escaped === "$") value += "\\$";
70
+ else value += escaped;
71
+ } else {
72
+ if (source[pos] === "\n") throw new Error(`Unterminated string at line ${line}, column ${startCol}`);
73
+ value += source[pos];
74
+ }
75
+ pos++;
76
+ col++;
77
+ }
78
+ if (pos >= source.length) throw new Error(`Unterminated string at line ${line}, column ${startCol}`);
79
+ pos++;
80
+ col++;
81
+ tokens.push({
82
+ type: "STRING",
83
+ value,
84
+ line,
85
+ column: startCol
86
+ });
87
+ continue;
88
+ }
89
+ if (ch >= "0" && ch <= "9") {
90
+ const startCol = col;
91
+ let num = "";
92
+ while (pos < source.length && (source[pos] >= "0" && source[pos] <= "9" || source[pos] === ".")) {
93
+ num += source[pos];
94
+ pos++;
95
+ col++;
96
+ }
97
+ tokens.push({
98
+ type: "NUMBER",
99
+ value: num,
100
+ line,
101
+ column: startCol
102
+ });
103
+ continue;
104
+ }
105
+ if (ch === "/") {
106
+ const next = source[pos + 1];
107
+ if (next !== void 0 && (next >= "a" && next <= "z" || next >= "A" && next <= "Z" || next === "_" || next === "." || next === "/")) {
108
+ const startCol = col;
109
+ let path = "";
110
+ while (pos < source.length && source[pos] !== " " && source[pos] !== " " && source[pos] !== "\n" && source[pos] !== "\r" && source[pos] !== "|" && source[pos] !== "}" && source[pos] !== ")" && source[pos] !== "," && source[pos] !== ":") {
111
+ if (source[pos] === "$" && pos + 1 < source.length && source[pos + 1] === "{") {
112
+ path += source[pos];
113
+ pos++;
114
+ col++;
115
+ path += source[pos];
116
+ pos++;
117
+ col++;
118
+ while (pos < source.length && source[pos] !== "}") {
119
+ path += source[pos];
120
+ pos++;
121
+ col++;
122
+ }
123
+ if (pos < source.length) {
124
+ path += source[pos];
125
+ pos++;
126
+ col++;
127
+ }
128
+ continue;
129
+ }
130
+ path += source[pos];
131
+ pos++;
132
+ col++;
133
+ }
134
+ tokens.push({
135
+ type: "PATH",
136
+ value: path,
137
+ line,
138
+ column: startCol
139
+ });
140
+ continue;
141
+ }
142
+ tokens.push({
143
+ type: "SLASH",
144
+ value: "/",
145
+ line,
146
+ column: col
147
+ });
148
+ pos++;
149
+ col++;
150
+ continue;
151
+ }
152
+ if (ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch === "_") {
153
+ const startCol = col;
154
+ let ident = "";
155
+ while (pos < source.length && (source[pos] >= "a" && source[pos] <= "z" || source[pos] >= "A" && source[pos] <= "Z" || source[pos] >= "0" && source[pos] <= "9" || source[pos] === "_")) {
156
+ ident += source[pos];
157
+ pos++;
158
+ col++;
159
+ }
160
+ if (ident === "group" && pos < source.length && source[pos] === "-") {
161
+ if (source.slice(pos + 1, pos + 3) === "by") {
162
+ pos += 3;
163
+ col += 3;
164
+ tokens.push({
165
+ type: "GROUP_BY",
166
+ value: "group-by",
167
+ line,
168
+ column: startCol
169
+ });
170
+ continue;
171
+ }
172
+ }
173
+ const kw = Object.hasOwn(KEYWORDS, ident) ? KEYWORDS[ident] : void 0;
174
+ tokens.push({
175
+ type: kw ?? "IDENTIFIER",
176
+ value: ident,
177
+ line,
178
+ column: startCol
179
+ });
180
+ continue;
181
+ }
182
+ if (ch === "+") {
183
+ tokens.push({
184
+ type: "PLUS",
185
+ value: "+",
186
+ line,
187
+ column: col
188
+ });
189
+ pos++;
190
+ col++;
191
+ continue;
192
+ }
193
+ if (ch === "-") {
194
+ if (source[pos + 1] === ">") {
195
+ tokens.push({
196
+ type: "ARROW",
197
+ value: "->",
198
+ line,
199
+ column: col
200
+ });
201
+ pos += 2;
202
+ col += 2;
203
+ continue;
204
+ }
205
+ tokens.push({
206
+ type: "MINUS",
207
+ value: "-",
208
+ line,
209
+ column: col
210
+ });
211
+ pos++;
212
+ col++;
213
+ continue;
214
+ }
215
+ if (ch === "*") {
216
+ tokens.push({
217
+ type: "STAR",
218
+ value: "*",
219
+ line,
220
+ column: col
221
+ });
222
+ pos++;
223
+ col++;
224
+ continue;
225
+ }
226
+ if (ch === "|") {
227
+ tokens.push({
228
+ type: "PIPE",
229
+ value: "|",
230
+ line,
231
+ column: col
232
+ });
233
+ pos++;
234
+ col++;
235
+ continue;
236
+ }
237
+ if (ch === "=") {
238
+ if (source[pos + 1] === "=") {
239
+ tokens.push({
240
+ type: "EQ",
241
+ value: "==",
242
+ line,
243
+ column: col
244
+ });
245
+ pos += 2;
246
+ col += 2;
247
+ continue;
248
+ }
249
+ tokens.push({
250
+ type: "ASSIGN",
251
+ value: "=",
252
+ line,
253
+ column: col
254
+ });
255
+ pos++;
256
+ col++;
257
+ continue;
258
+ }
259
+ if (ch === "!") {
260
+ if (source[pos + 1] === "=") {
261
+ tokens.push({
262
+ type: "NEQ",
263
+ value: "!=",
264
+ line,
265
+ column: col
266
+ });
267
+ pos += 2;
268
+ col += 2;
269
+ continue;
270
+ }
271
+ }
272
+ if (ch === ">") {
273
+ if (source[pos + 1] === "=") {
274
+ tokens.push({
275
+ type: "GTE",
276
+ value: ">=",
277
+ line,
278
+ column: col
279
+ });
280
+ pos += 2;
281
+ col += 2;
282
+ continue;
283
+ }
284
+ tokens.push({
285
+ type: "GT",
286
+ value: ">",
287
+ line,
288
+ column: col
289
+ });
290
+ pos++;
291
+ col++;
292
+ continue;
293
+ }
294
+ if (ch === "<") {
295
+ if (source[pos + 1] === "=") {
296
+ tokens.push({
297
+ type: "LTE",
298
+ value: "<=",
299
+ line,
300
+ column: col
301
+ });
302
+ pos += 2;
303
+ col += 2;
304
+ continue;
305
+ }
306
+ tokens.push({
307
+ type: "LT",
308
+ value: "<",
309
+ line,
310
+ column: col
311
+ });
312
+ pos++;
313
+ col++;
314
+ continue;
315
+ }
316
+ if (ch === ".") {
317
+ tokens.push({
318
+ type: "DOT",
319
+ value: ".",
320
+ line,
321
+ column: col
322
+ });
323
+ pos++;
324
+ col++;
325
+ continue;
326
+ }
327
+ if (ch === ",") {
328
+ tokens.push({
329
+ type: "COMMA",
330
+ value: ",",
331
+ line,
332
+ column: col
333
+ });
334
+ pos++;
335
+ col++;
336
+ continue;
337
+ }
338
+ if (ch === "(") {
339
+ tokens.push({
340
+ type: "LPAREN",
341
+ value: "(",
342
+ line,
343
+ column: col
344
+ });
345
+ pos++;
346
+ col++;
347
+ continue;
348
+ }
349
+ if (ch === ")") {
350
+ tokens.push({
351
+ type: "RPAREN",
352
+ value: ")",
353
+ line,
354
+ column: col
355
+ });
356
+ pos++;
357
+ col++;
358
+ continue;
359
+ }
360
+ if (ch === "[") {
361
+ tokens.push({
362
+ type: "LBRACKET",
363
+ value: "[",
364
+ line,
365
+ column: col
366
+ });
367
+ pos++;
368
+ col++;
369
+ continue;
370
+ }
371
+ if (ch === "]") {
372
+ tokens.push({
373
+ type: "RBRACKET",
374
+ value: "]",
375
+ line,
376
+ column: col
377
+ });
378
+ pos++;
379
+ col++;
380
+ continue;
381
+ }
382
+ if (ch === "{") {
383
+ tokens.push({
384
+ type: "LBRACE",
385
+ value: "{",
386
+ line,
387
+ column: col
388
+ });
389
+ pos++;
390
+ col++;
391
+ continue;
392
+ }
393
+ if (ch === "}") {
394
+ tokens.push({
395
+ type: "RBRACE",
396
+ value: "}",
397
+ line,
398
+ column: col
399
+ });
400
+ pos++;
401
+ col++;
402
+ continue;
403
+ }
404
+ if (ch === "@") {
405
+ tokens.push({
406
+ type: "AT",
407
+ value: "@",
408
+ line,
409
+ column: col
410
+ });
411
+ pos++;
412
+ col++;
413
+ continue;
414
+ }
415
+ if (ch === "$") {
416
+ tokens.push({
417
+ type: "DOLLAR",
418
+ value: "$",
419
+ line,
420
+ column: col
421
+ });
422
+ pos++;
423
+ col++;
424
+ continue;
425
+ }
426
+ if (ch === ":") {
427
+ tokens.push({
428
+ type: "COLON",
429
+ value: ":",
430
+ line,
431
+ column: col
432
+ });
433
+ pos++;
434
+ col++;
435
+ continue;
436
+ }
437
+ throw new Error(`Unrecognized character '${ch}' at line ${line}, column ${col}`);
438
+ }
439
+ tokens.push({
440
+ type: "EOF",
441
+ value: "",
442
+ line,
443
+ column: col
444
+ });
445
+ return tokens;
446
+ }
447
+ };
448
+
449
+ //#endregion
450
+ export { AshLexer };
451
+ //# sourceMappingURL=lexer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.mjs","names":[],"sources":["../src/lexer.ts"],"sourcesContent":["export type TokenType =\n | \"JOB\" | \"FIND\" | \"WHERE\" | \"MAP\" | \"SAVE\" | \"PUBLISH\" | \"TEE\" | \"FANOUT\" | \"INPUT\" | \"OUTPUT\"\n | \"ACTION\" | \"ROUTE\" | \"LOOKUP\" | \"ARROW\"\n | \"PLUS\" | \"MINUS\" | \"STAR\" | \"SLASH\"\n | \"PIPE\" | \"ASSIGN\" | \"DOT\" | \"COMMA\" | \"COLON\"\n | \"LPAREN\" | \"RPAREN\" | \"LBRACKET\" | \"RBRACKET\" | \"LBRACE\" | \"RBRACE\"\n | \"IDENTIFIER\" | \"STRING\" | \"NUMBER\" | \"PATH\" | \"AT\"\n | \"GT\" | \"LT\" | \"GTE\" | \"LTE\" | \"EQ\" | \"NEQ\"\n | \"LET\" | \"PARAM\" | \"ON\" | \"DOLLAR\" | \"COUNT\" | \"GROUP_BY\"\n | \"NEWLINE\" | \"EOF\";\n\nexport interface Token {\n type: TokenType;\n value: string;\n line: number;\n column: number;\n}\n\nconst KEYWORDS: Record<string, TokenType> = {\n job: \"JOB\",\n find: \"FIND\",\n where: \"WHERE\",\n map: \"MAP\",\n save: \"SAVE\",\n publish: \"PUBLISH\",\n tee: \"TEE\",\n fanout: \"FANOUT\",\n input: \"INPUT\",\n output: \"OUTPUT\",\n let: \"LET\",\n count: \"COUNT\",\n action: \"ACTION\",\n route: \"ROUTE\",\n lookup: \"LOOKUP\",\n param: \"PARAM\",\n on: \"ON\",\n};\n\nexport class AshLexer {\n tokenize(source: string): Token[] {\n const tokens: Token[] = [];\n let pos = 0;\n let line = 1;\n let col = 1;\n\n while (pos < source.length) {\n const ch = source[pos];\n\n // Newline\n if (ch === \"\\n\" || ch === \"\\r\") {\n if (ch === \"\\r\" && source[pos + 1] === \"\\n\") pos++;\n tokens.push({ type: \"NEWLINE\", value: \"\\\\n\", line, column: col });\n pos++;\n line++;\n col = 1;\n continue;\n }\n\n // Whitespace (skip)\n if (ch === \" \" || ch === \"\\t\") {\n pos++;\n col++;\n continue;\n }\n\n // Comment: # to end of line\n if (ch === \"#\") {\n while (pos < source.length && source[pos] !== \"\\n\" && source[pos] !== \"\\r\") {\n pos++;\n col++;\n }\n continue;\n }\n\n // String literal\n if (ch === '\"') {\n const startCol = col;\n pos++; col++;\n let value = \"\";\n while (pos < source.length && source[pos] !== '\"') {\n if (source[pos] === \"\\\\\") {\n pos++; col++;\n if (pos >= source.length) break;\n const escaped = source[pos];\n if (escaped === '\"') value += '\"';\n else if (escaped === \"\\\\\") value += \"\\\\\";\n else if (escaped === \"n\") value += \"\\n\";\n else if (escaped === \"t\") value += \"\\t\";\n else if (escaped === \"$\") value += \"\\\\$\"; // preserve for template escape detection\n else value += escaped;\n } else {\n if (source[pos] === \"\\n\") {\n throw new Error(`Unterminated string at line ${line}, column ${startCol}`);\n }\n value += source[pos];\n }\n pos++; col++;\n }\n if (pos >= source.length) {\n throw new Error(`Unterminated string at line ${line}, column ${startCol}`);\n }\n pos++; col++; // closing quote\n tokens.push({ type: \"STRING\", value, line, column: startCol });\n continue;\n }\n\n // Number\n if (ch >= \"0\" && ch <= \"9\") {\n const startCol = col;\n let num = \"\";\n while (pos < source.length && ((source[pos] >= \"0\" && source[pos] <= \"9\") || source[pos] === \".\")) {\n num += source[pos];\n pos++; col++;\n }\n tokens.push({ type: \"NUMBER\", value: num, line, column: startCol });\n continue;\n }\n\n // Path or SLASH: `/` followed by a letter, `.`, `_`, or `/` starts a PATH; otherwise SLASH\n if (ch === \"/\") {\n const next = source[pos + 1];\n if (next !== undefined && ((next >= \"a\" && next <= \"z\") || (next >= \"A\" && next <= \"Z\") || next === \"_\" || next === \".\" || next === \"/\")) {\n const startCol = col;\n let path = \"\";\n while (pos < source.length && source[pos] !== \" \" && source[pos] !== \"\\t\" && source[pos] !== \"\\n\" && source[pos] !== \"\\r\" && source[pos] !== \"|\" && source[pos] !== \"}\" && source[pos] !== \")\" && source[pos] !== \",\" && source[pos] !== \":\") {\n // Handle ${...} template blocks atomically — don't stop at } inside template\n if (source[pos] === \"$\" && pos + 1 < source.length && source[pos + 1] === \"{\") {\n path += source[pos]; pos++; col++; // $\n path += source[pos]; pos++; col++; // {\n while (pos < source.length && source[pos] !== \"}\") {\n path += source[pos]; pos++; col++;\n }\n if (pos < source.length) {\n path += source[pos]; pos++; col++; // closing }\n }\n continue;\n }\n path += source[pos];\n pos++; col++;\n }\n tokens.push({ type: \"PATH\", value: path, line, column: startCol });\n continue;\n }\n tokens.push({ type: \"SLASH\", value: \"/\", line, column: col }); pos++; col++; continue;\n }\n\n // Identifier / keyword\n if ((ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\") {\n const startCol = col;\n let ident = \"\";\n while (pos < source.length && ((source[pos] >= \"a\" && source[pos] <= \"z\") || (source[pos] >= \"A\" && source[pos] <= \"Z\") || (source[pos] >= \"0\" && source[pos] <= \"9\") || source[pos] === \"_\")) {\n ident += source[pos];\n pos++; col++;\n }\n // Handle compound keyword: group-by\n if (ident === \"group\" && pos < source.length && source[pos] === \"-\") {\n const rest = source.slice(pos + 1, pos + 3);\n if (rest === \"by\") {\n pos += 3; col += 3;\n tokens.push({ type: \"GROUP_BY\", value: \"group-by\", line, column: startCol });\n continue;\n }\n }\n const kw = Object.hasOwn(KEYWORDS, ident) ? KEYWORDS[ident] : undefined;\n tokens.push({ type: kw ?? \"IDENTIFIER\", value: ident, line, column: startCol });\n continue;\n }\n\n // Operators and punctuation\n // Arithmetic operators\n if (ch === \"+\") { tokens.push({ type: \"PLUS\", value: \"+\", line, column: col }); pos++; col++; continue; }\n if (ch === \"-\") {\n if (source[pos + 1] === \">\") {\n tokens.push({ type: \"ARROW\", value: \"->\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"MINUS\", value: \"-\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"*\") { tokens.push({ type: \"STAR\", value: \"*\", line, column: col }); pos++; col++; continue; }\n\n if (ch === \"|\") { tokens.push({ type: \"PIPE\", value: \"|\", line, column: col }); pos++; col++; continue; }\n if (ch === \"=\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"EQ\", value: \"==\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"ASSIGN\", value: \"=\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"!\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"NEQ\", value: \"!=\", line, column: col }); pos += 2; col += 2; continue;\n }\n }\n if (ch === \">\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"GTE\", value: \">=\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"GT\", value: \">\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"<\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"LTE\", value: \"<=\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"LT\", value: \"<\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \".\") { tokens.push({ type: \"DOT\", value: \".\", line, column: col }); pos++; col++; continue; }\n if (ch === \",\") { tokens.push({ type: \"COMMA\", value: \",\", line, column: col }); pos++; col++; continue; }\n if (ch === \"(\") { tokens.push({ type: \"LPAREN\", value: \"(\", line, column: col }); pos++; col++; continue; }\n if (ch === \")\") { tokens.push({ type: \"RPAREN\", value: \")\", line, column: col }); pos++; col++; continue; }\n if (ch === \"[\") { tokens.push({ type: \"LBRACKET\", value: \"[\", line, column: col }); pos++; col++; continue; }\n if (ch === \"]\") { tokens.push({ type: \"RBRACKET\", value: \"]\", line, column: col }); pos++; col++; continue; }\n if (ch === \"{\") { tokens.push({ type: \"LBRACE\", value: \"{\", line, column: col }); pos++; col++; continue; }\n if (ch === \"}\") { tokens.push({ type: \"RBRACE\", value: \"}\", line, column: col }); pos++; col++; continue; }\n if (ch === \"@\") { tokens.push({ type: \"AT\", value: \"@\", line, column: col }); pos++; col++; continue; }\n if (ch === \"$\") { tokens.push({ type: \"DOLLAR\", value: \"$\", line, column: col }); pos++; col++; continue; }\n if (ch === \":\") { tokens.push({ type: \"COLON\", value: \":\", line, column: col }); pos++; col++; continue; }\n\n throw new Error(`Unrecognized character '${ch}' at line ${line}, column ${col}`);\n }\n\n tokens.push({ type: \"EOF\", value: \"\", line, column: col });\n return tokens;\n }\n}\n"],"mappings":"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"}