@aigne/ash 0.0.2-beta.2 → 0.0.2-beta.3
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/lexer.cjs +41 -1
- package/dist/lexer.mjs +41 -1
- package/dist/lexer.mjs.map +1 -1
- package/package.json +1 -1
package/dist/lexer.cjs
CHANGED
|
@@ -106,7 +106,7 @@ var AshLexer = class {
|
|
|
106
106
|
}
|
|
107
107
|
if (ch === "/") {
|
|
108
108
|
const next = source[pos + 1];
|
|
109
|
-
if (next !== void 0 && (next >= "a" && next <= "z" || next >= "A" && next <= "Z" || next === "_" || next === "." || next === "/")) {
|
|
109
|
+
if (next !== void 0 && (next >= "a" && next <= "z" || next >= "A" && next <= "Z" || next === "_" || next === "." || next === "/" || next === ":" || next === "*")) {
|
|
110
110
|
const startCol = col;
|
|
111
111
|
let path = "";
|
|
112
112
|
while (pos < source.length && source[pos] !== " " && source[pos] !== " " && source[pos] !== "\n" && source[pos] !== "\r" && source[pos] !== "|" && source[pos] !== "}" && source[pos] !== ")" && source[pos] !== "," && source[pos] !== ":") {
|
|
@@ -415,6 +415,46 @@ var AshLexer = class {
|
|
|
415
415
|
continue;
|
|
416
416
|
}
|
|
417
417
|
if (ch === "$") {
|
|
418
|
+
if (pos + 1 < source.length && source[pos + 1] === "{") {
|
|
419
|
+
let scanPos = pos + 2;
|
|
420
|
+
while (scanPos < source.length && source[scanPos] !== "}") scanPos++;
|
|
421
|
+
if (scanPos < source.length) scanPos++;
|
|
422
|
+
if (scanPos < source.length && source[scanPos] === "/") {
|
|
423
|
+
const startCol = col;
|
|
424
|
+
let path = "";
|
|
425
|
+
while (pos < source.length && source[pos] !== " " && source[pos] !== " " && source[pos] !== "\n" && source[pos] !== "\r" && source[pos] !== "|" && source[pos] !== "}" && source[pos] !== ")" && source[pos] !== "," && source[pos] !== ":") {
|
|
426
|
+
if (source[pos] === "$" && pos + 1 < source.length && source[pos + 1] === "{") {
|
|
427
|
+
path += source[pos];
|
|
428
|
+
pos++;
|
|
429
|
+
col++;
|
|
430
|
+
path += source[pos];
|
|
431
|
+
pos++;
|
|
432
|
+
col++;
|
|
433
|
+
while (pos < source.length && source[pos] !== "}") {
|
|
434
|
+
path += source[pos];
|
|
435
|
+
pos++;
|
|
436
|
+
col++;
|
|
437
|
+
}
|
|
438
|
+
if (pos < source.length) {
|
|
439
|
+
path += source[pos];
|
|
440
|
+
pos++;
|
|
441
|
+
col++;
|
|
442
|
+
}
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
path += source[pos];
|
|
446
|
+
pos++;
|
|
447
|
+
col++;
|
|
448
|
+
}
|
|
449
|
+
tokens.push({
|
|
450
|
+
type: "PATH",
|
|
451
|
+
value: path,
|
|
452
|
+
line,
|
|
453
|
+
column: startCol
|
|
454
|
+
});
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
418
458
|
tokens.push({
|
|
419
459
|
type: "DOLLAR",
|
|
420
460
|
value: "$",
|
package/dist/lexer.mjs
CHANGED
|
@@ -105,7 +105,7 @@ var AshLexer = class {
|
|
|
105
105
|
}
|
|
106
106
|
if (ch === "/") {
|
|
107
107
|
const next = source[pos + 1];
|
|
108
|
-
if (next !== void 0 && (next >= "a" && next <= "z" || next >= "A" && next <= "Z" || next === "_" || next === "." || next === "/")) {
|
|
108
|
+
if (next !== void 0 && (next >= "a" && next <= "z" || next >= "A" && next <= "Z" || next === "_" || next === "." || next === "/" || next === ":" || next === "*")) {
|
|
109
109
|
const startCol = col;
|
|
110
110
|
let path = "";
|
|
111
111
|
while (pos < source.length && source[pos] !== " " && source[pos] !== " " && source[pos] !== "\n" && source[pos] !== "\r" && source[pos] !== "|" && source[pos] !== "}" && source[pos] !== ")" && source[pos] !== "," && source[pos] !== ":") {
|
|
@@ -414,6 +414,46 @@ var AshLexer = class {
|
|
|
414
414
|
continue;
|
|
415
415
|
}
|
|
416
416
|
if (ch === "$") {
|
|
417
|
+
if (pos + 1 < source.length && source[pos + 1] === "{") {
|
|
418
|
+
let scanPos = pos + 2;
|
|
419
|
+
while (scanPos < source.length && source[scanPos] !== "}") scanPos++;
|
|
420
|
+
if (scanPos < source.length) scanPos++;
|
|
421
|
+
if (scanPos < source.length && source[scanPos] === "/") {
|
|
422
|
+
const startCol = col;
|
|
423
|
+
let path = "";
|
|
424
|
+
while (pos < source.length && source[pos] !== " " && source[pos] !== " " && source[pos] !== "\n" && source[pos] !== "\r" && source[pos] !== "|" && source[pos] !== "}" && source[pos] !== ")" && source[pos] !== "," && source[pos] !== ":") {
|
|
425
|
+
if (source[pos] === "$" && pos + 1 < source.length && source[pos + 1] === "{") {
|
|
426
|
+
path += source[pos];
|
|
427
|
+
pos++;
|
|
428
|
+
col++;
|
|
429
|
+
path += source[pos];
|
|
430
|
+
pos++;
|
|
431
|
+
col++;
|
|
432
|
+
while (pos < source.length && source[pos] !== "}") {
|
|
433
|
+
path += source[pos];
|
|
434
|
+
pos++;
|
|
435
|
+
col++;
|
|
436
|
+
}
|
|
437
|
+
if (pos < source.length) {
|
|
438
|
+
path += source[pos];
|
|
439
|
+
pos++;
|
|
440
|
+
col++;
|
|
441
|
+
}
|
|
442
|
+
continue;
|
|
443
|
+
}
|
|
444
|
+
path += source[pos];
|
|
445
|
+
pos++;
|
|
446
|
+
col++;
|
|
447
|
+
}
|
|
448
|
+
tokens.push({
|
|
449
|
+
type: "PATH",
|
|
450
|
+
value: path,
|
|
451
|
+
line,
|
|
452
|
+
column: startCol
|
|
453
|
+
});
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
417
457
|
tokens.push({
|
|
418
458
|
type: "DOLLAR",
|
|
419
459
|
value: "$",
|
package/dist/lexer.mjs.map
CHANGED
|
@@ -1 +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\" | \"IN\"\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 in: \"IN\",\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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"}
|
|
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\" | \"IN\"\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 in: \"IN\",\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 // `:` enables `/:event` root-path triggers; `*` enables `/*:event` wildcard triggers\n if (ch === \"/\") {\n const next = source[pos + 1];\n if (next !== undefined && ((next >= \"a\" && next <= \"z\") || (next >= \"A\" && next <= \"Z\") || next === \"_\" || next === \".\" || 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 // $ followed by { starts a template expression — if followed by path segments, treat as PATH\n // This enables `action ${data.providerPath}/some/path` syntax\n if (ch === \"$\") {\n if (pos + 1 < source.length && source[pos + 1] === \"{\") {\n // Look ahead: if after ${...} there's a /, treat the whole thing as PATH\n let scanPos = pos + 2;\n while (scanPos < source.length && source[scanPos] !== \"}\") scanPos++;\n if (scanPos < source.length) scanPos++; // skip }\n if (scanPos < source.length && source[scanPos] === \"/\") {\n // This is a dynamic path: ${var}/rest/of/path — collect as PATH token\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 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++;\n }\n continue;\n }\n path += source[pos]; pos++; col++;\n }\n tokens.push({ type: \"PATH\", value: path, line, column: startCol });\n continue;\n }\n }\n tokens.push({ type: \"DOLLAR\", value: \"$\", line, column: col }); pos++; col++; continue;\n }\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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"}
|