feat: add typed WRN declarations

This commit is contained in:
2026-07-19 18:44:27 +05:30
parent 0d3ec79ee4
commit 94ae40d8bd
81 changed files with 942 additions and 241 deletions
+70 -1
View File
@@ -9,7 +9,17 @@
*/
export type TokenType =
"ident" | "string" | "lbrace" | "rbrace" | "lparen" | "rparen" | "at" | "eq" | "comma" | "eof";
| "ident"
| "string"
| "lbrace"
| "rbrace"
| "lparen"
| "rparen"
| "at"
| "eq"
| "colon"
| "comma"
| "eof";
export interface Token {
type: TokenType;
@@ -71,6 +81,9 @@ export class Lexer {
case "=":
this.pos++;
return { type: "eq", value: c, pos };
case ":":
this.pos++;
return { type: "colon", value: c, pos };
case ",":
this.pos++;
return { type: "comma", value: c, pos };
@@ -133,6 +146,62 @@ export class Lexer {
return v.trim();
}
/**
* Read a TypeScript-style type annotation after `:`. Reading stops at a
* top-level `=` or line ending, while nested object/tuple/generic syntax is
* preserved. The optional `=` is consumed for the caller.
*/
readTypeAnnotation(): { type: string; hasDefault: boolean } {
const { src } = this;
let value = "";
let angle = 0;
let square = 0;
let brace = 0;
let paren = 0;
let quote: string | null = null;
while (this.pos < src.length) {
const c = src[this.pos]!;
if (quote) {
value += c;
this.pos++;
if (c === "\\" && this.pos < src.length) value += src[this.pos++]!;
else if (c === quote) quote = null;
continue;
}
if (c === '"' || c === "'" || c === "`") {
quote = c;
value += c;
this.pos++;
continue;
}
if (c === "<") angle++;
else if (c === ">" && angle > 0) angle--;
else if (c === "[") square++;
else if (c === "]" && square > 0) square--;
else if (c === "{") brace++;
else if (c === "}" && brace > 0) brace--;
else if (c === "(") paren++;
else if (c === ")" && paren > 0) paren--;
if (angle === 0 && square === 0 && brace === 0 && paren === 0) {
if (c === "=") {
this.pos++;
const type = value.trim();
if (!type) throw new LexError(`Expected a type annotation at offset ${this.pos}`);
return { type, hasDefault: true };
}
if (c === "\n" || c === "\r") break;
}
value += c;
this.pos++;
}
const type = value.trim();
if (!type) throw new LexError(`Expected a type annotation at offset ${this.pos}`);
return { type, hasDefault: false };
}
/**
* Read a `{ ... }` block and return its INNER text (no outer braces), with
* brace counting that respects string and template literals so a `}` inside a