@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.
- package/DESIGN.md +41 -0
- package/dist/ai-dev-loop/ash-run-result.cjs +12 -0
- package/dist/ai-dev-loop/ash-run-result.d.cts +28 -0
- package/dist/ai-dev-loop/ash-run-result.d.cts.map +1 -0
- package/dist/ai-dev-loop/ash-run-result.d.mts +28 -0
- package/dist/ai-dev-loop/ash-run-result.d.mts.map +1 -0
- package/dist/ai-dev-loop/ash-run-result.mjs +11 -0
- package/dist/ai-dev-loop/ash-run-result.mjs.map +1 -0
- package/dist/ai-dev-loop/ash-typed-error.cjs +51 -0
- package/dist/ai-dev-loop/ash-typed-error.d.cts +54 -0
- package/dist/ai-dev-loop/ash-typed-error.d.cts.map +1 -0
- package/dist/ai-dev-loop/ash-typed-error.d.mts +54 -0
- package/dist/ai-dev-loop/ash-typed-error.d.mts.map +1 -0
- package/dist/ai-dev-loop/ash-typed-error.mjs +50 -0
- package/dist/ai-dev-loop/ash-typed-error.mjs.map +1 -0
- package/dist/ai-dev-loop/ash-validate.cjs +27 -0
- package/dist/ai-dev-loop/ash-validate.d.cts +7 -0
- package/dist/ai-dev-loop/ash-validate.d.cts.map +1 -0
- package/dist/ai-dev-loop/ash-validate.d.mts +7 -0
- package/dist/ai-dev-loop/ash-validate.d.mts.map +1 -0
- package/dist/ai-dev-loop/ash-validate.mjs +28 -0
- package/dist/ai-dev-loop/ash-validate.mjs.map +1 -0
- package/dist/ai-dev-loop/dev-loop.cjs +134 -0
- package/dist/ai-dev-loop/dev-loop.d.cts +28 -0
- package/dist/ai-dev-loop/dev-loop.d.cts.map +1 -0
- package/dist/ai-dev-loop/dev-loop.d.mts +28 -0
- package/dist/ai-dev-loop/dev-loop.d.mts.map +1 -0
- package/dist/ai-dev-loop/dev-loop.mjs +135 -0
- package/dist/ai-dev-loop/dev-loop.mjs.map +1 -0
- package/dist/ai-dev-loop/index.cjs +24 -0
- package/dist/ai-dev-loop/index.d.cts +9 -0
- package/dist/ai-dev-loop/index.d.mts +9 -0
- package/dist/ai-dev-loop/index.mjs +10 -0
- package/dist/ai-dev-loop/live-mode.cjs +17 -0
- package/dist/ai-dev-loop/live-mode.d.cts +24 -0
- package/dist/ai-dev-loop/live-mode.d.cts.map +1 -0
- package/dist/ai-dev-loop/live-mode.d.mts +24 -0
- package/dist/ai-dev-loop/live-mode.d.mts.map +1 -0
- package/dist/ai-dev-loop/live-mode.mjs +17 -0
- package/dist/ai-dev-loop/live-mode.mjs.map +1 -0
- package/dist/ai-dev-loop/meta-tools.cjs +123 -0
- package/dist/ai-dev-loop/meta-tools.d.cts +24 -0
- package/dist/ai-dev-loop/meta-tools.d.cts.map +1 -0
- package/dist/ai-dev-loop/meta-tools.d.mts +24 -0
- package/dist/ai-dev-loop/meta-tools.d.mts.map +1 -0
- package/dist/ai-dev-loop/meta-tools.mjs +120 -0
- package/dist/ai-dev-loop/meta-tools.mjs.map +1 -0
- package/dist/ai-dev-loop/structured-runner.cjs +154 -0
- package/dist/ai-dev-loop/structured-runner.d.cts +12 -0
- package/dist/ai-dev-loop/structured-runner.d.cts.map +1 -0
- package/dist/ai-dev-loop/structured-runner.d.mts +12 -0
- package/dist/ai-dev-loop/structured-runner.d.mts.map +1 -0
- package/dist/ai-dev-loop/structured-runner.mjs +155 -0
- package/dist/ai-dev-loop/structured-runner.mjs.map +1 -0
- package/dist/ai-dev-loop/system-prompt.cjs +55 -0
- package/dist/ai-dev-loop/system-prompt.d.cts +20 -0
- package/dist/ai-dev-loop/system-prompt.d.cts.map +1 -0
- package/dist/ai-dev-loop/system-prompt.d.mts +20 -0
- package/dist/ai-dev-loop/system-prompt.d.mts.map +1 -0
- package/dist/ai-dev-loop/system-prompt.mjs +54 -0
- package/dist/ai-dev-loop/system-prompt.mjs.map +1 -0
- package/dist/ast.d.cts +140 -0
- package/dist/ast.d.cts.map +1 -0
- package/dist/ast.d.mts +140 -0
- package/dist/ast.d.mts.map +1 -0
- package/dist/compiler.cjs +802 -0
- package/dist/compiler.d.cts +103 -0
- package/dist/compiler.d.cts.map +1 -0
- package/dist/compiler.d.mts +103 -0
- package/dist/compiler.d.mts.map +1 -0
- package/dist/compiler.mjs +802 -0
- package/dist/compiler.mjs.map +1 -0
- package/dist/index.cjs +14 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +7 -0
- package/dist/lexer.cjs +451 -0
- package/dist/lexer.d.cts +14 -0
- package/dist/lexer.d.cts.map +1 -0
- package/dist/lexer.d.mts +14 -0
- package/dist/lexer.d.mts.map +1 -0
- package/dist/lexer.mjs +451 -0
- package/dist/lexer.mjs.map +1 -0
- package/dist/parser.cjs +734 -0
- package/dist/parser.d.cts +40 -0
- package/dist/parser.d.cts.map +1 -0
- package/dist/parser.d.mts +40 -0
- package/dist/parser.d.mts.map +1 -0
- package/dist/parser.mjs +734 -0
- package/dist/parser.mjs.map +1 -0
- package/dist/reference.cjs +130 -0
- package/dist/reference.d.cts +11 -0
- package/dist/reference.d.cts.map +1 -0
- package/dist/reference.d.mts +11 -0
- package/dist/reference.d.mts.map +1 -0
- package/dist/reference.mjs +130 -0
- package/dist/reference.mjs.map +1 -0
- package/dist/template.cjs +85 -0
- package/dist/template.mjs +84 -0
- package/dist/template.mjs.map +1 -0
- package/dist/type-checker.cjs +582 -0
- package/dist/type-checker.d.cts +31 -0
- package/dist/type-checker.d.cts.map +1 -0
- package/dist/type-checker.d.mts +31 -0
- package/dist/type-checker.d.mts.map +1 -0
- package/dist/type-checker.mjs +573 -0
- package/dist/type-checker.mjs.map +1 -0
- package/package.json +29 -0
- package/src/ai-dev-loop/ash-run-result.test.ts +113 -0
- package/src/ai-dev-loop/ash-run-result.ts +46 -0
- package/src/ai-dev-loop/ash-typed-error.test.ts +136 -0
- package/src/ai-dev-loop/ash-typed-error.ts +50 -0
- package/src/ai-dev-loop/ash-validate.test.ts +54 -0
- package/src/ai-dev-loop/ash-validate.ts +34 -0
- package/src/ai-dev-loop/dev-loop.test.ts +364 -0
- package/src/ai-dev-loop/dev-loop.ts +156 -0
- package/src/ai-dev-loop/dry-run.test.ts +107 -0
- package/src/ai-dev-loop/e2e-multi-fix.test.ts +473 -0
- package/src/ai-dev-loop/e2e.test.ts +324 -0
- package/src/ai-dev-loop/index.ts +15 -0
- package/src/ai-dev-loop/invariants.test.ts +253 -0
- package/src/ai-dev-loop/live-mode.test.ts +63 -0
- package/src/ai-dev-loop/live-mode.ts +33 -0
- package/src/ai-dev-loop/meta-tools.test.ts +120 -0
- package/src/ai-dev-loop/meta-tools.ts +142 -0
- package/src/ai-dev-loop/structured-runner.test.ts +159 -0
- package/src/ai-dev-loop/structured-runner.ts +209 -0
- package/src/ai-dev-loop/system-prompt.test.ts +102 -0
- package/src/ai-dev-loop/system-prompt.ts +81 -0
- package/src/ast.ts +186 -0
- package/src/compiler.test.ts +2933 -0
- package/src/compiler.ts +1103 -0
- package/src/e2e.test.ts +552 -0
- package/src/index.ts +16 -0
- package/src/lexer.test.ts +538 -0
- package/src/lexer.ts +222 -0
- package/src/parser.test.ts +1024 -0
- package/src/parser.ts +835 -0
- package/src/reference.test.ts +166 -0
- package/src/reference.ts +125 -0
- package/src/template.test.ts +210 -0
- package/src/template.ts +139 -0
- package/src/type-checker.test.ts +1494 -0
- package/src/type-checker.ts +785 -0
- package/tsconfig.json +9 -0
- package/tsdown.config.ts +12 -0
package/dist/lexer.d.cts
ADDED
|
@@ -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"}
|
package/dist/lexer.d.mts
ADDED
|
@@ -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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"}
|