/** * Recursive-descent parser for `.wrn`, producing a small AST. * * Grammar (subset of the vision, but real): * * page { * state = // zero or more * view { } // plain HTML (see parseHtmlView) * seo { title = "Home" description = "..." } * ssr { api { } functions { } } * client { api { } functions { } } * style { } // zero or more, inlined with the page * functions { } // zero or more, shared helpers * api { } // zero or more * realtime { on () { } * } // zero or more * } * * The `view` block is written as ordinary HTML — nothing new to learn. Text may * contain `{expr}` interpolation, attributes may be hyphenated (`data-*`), and * `@event="..."` declares a client event binding. See `parseHtmlView`. */ import { Lexer, LexError, type Token } from "./tokenizer.ts"; export interface StateDecl { name: string; /** Raw JS initializer expression, e.g. `0` or `'x'`. */ expr: string; } export interface Attr { name: string; value: string; /** True for `@event` bindings (vs. plain HTML attributes). */ event: boolean; /** True for a valueless boolean attribute, e.g. `