@chanmeng666/archlang 0.2.0 → 0.3.0
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/{chunk-ICYNEDSM.js → chunk-3YUQPQPZ.js} +725 -521
- package/dist/chunk-3YUQPQPZ.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +44 -43
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ICYNEDSM.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lexer.ts","../src/geometry.ts","../src/elements/wall.ts","../src/elements/room.ts","../src/elements/door.ts","../src/elements/window.ts","../src/elements/furniture.ts","../src/elements/dim.ts","../src/elements/column.ts","../src/elements/index.ts","../src/parser.ts","../src/ir.ts","../src/registry.ts","../src/render.ts","../src/diagnostics.ts","../src/index.ts"],"sourcesContent":["/** Hand-written lexer for ArchLang. Zero dependencies; tracks line/col. */\r\n\r\nexport type TokenType =\r\n | \"ident\"\r\n | \"number\"\r\n | \"string\"\r\n | \"dimension\" // e.g. 4000x3000\r\n | \"lparen\"\r\n | \"rparen\"\r\n | \"lcurly\"\r\n | \"rcurly\"\r\n | \"comma\"\r\n | \"equals\"\r\n | \"colon\"\r\n | \"arrow\" // ->\r\n | \"eof\";\r\n\r\nexport interface Token {\r\n type: TokenType;\r\n value: string;\r\n /** For \"number\": the parsed value. For \"dimension\": w. */\r\n num?: number;\r\n /** For \"dimension\": h. */\r\n num2?: number;\r\n line: number;\r\n col: number;\r\n /** Byte offset of the token's first character into the source. */\r\n start: number;\r\n /** Byte offset just past the token's last character. */\r\n end: number;\r\n}\r\n\r\nexport interface LexResult {\r\n tokens: Token[];\r\n errors: { message: string; span: { start: number; end: number } }[];\r\n}\r\n\r\nconst isDigit = (c: string) => c >= \"0\" && c <= \"9\";\r\nconst isIdentStart = (c: string) =>\r\n (c >= \"a\" && c <= \"z\") || (c >= \"A\" && c <= \"Z\") || c === \"_\";\r\nconst isIdentPart = (c: string) => isIdentStart(c) || isDigit(c);\r\n\r\nexport function lex(src: string): LexResult {\r\n const tokens: Token[] = [];\r\n const errors: { message: string; span: { start: number; end: number } }[] = [];\r\n let i = 0;\r\n let line = 1;\r\n let col = 1;\r\n\r\n const peek = (o = 0) => src[i + o] ?? \"\";\r\n const advance = () => {\r\n const c = src[i++];\r\n if (c === \"\\n\") {\r\n line++;\r\n col = 1;\r\n } else {\r\n col++;\r\n }\r\n return c;\r\n };\r\n const push = (\r\n type: TokenType,\r\n value: string,\r\n startLine: number,\r\n startCol: number,\r\n startIdx: number,\r\n extra?: Partial<Token>,\r\n ) => tokens.push({ type, value, line: startLine, col: startCol, ...extra, start: startIdx, end: i });\r\n\r\n while (i < src.length) {\r\n const c = peek();\r\n const startLine = line;\r\n const startCol = col;\r\n const startIdx = i;\r\n\r\n // Whitespace\r\n if (c === \" \" || c === \"\\t\" || c === \"\\r\" || c === \"\\n\") {\r\n advance();\r\n continue;\r\n }\r\n\r\n // Comment to end of line\r\n if (c === \"#\") {\r\n while (i < src.length && peek() !== \"\\n\") advance();\r\n continue;\r\n }\r\n\r\n // String literal with \\\" and \\\\ escapes\r\n if (c === '\"') {\r\n advance();\r\n let value = \"\";\r\n let terminated = false;\r\n while (i < src.length) {\r\n const ch = peek();\r\n if (ch === \"\\\\\") {\r\n advance();\r\n const esc = advance();\r\n value += esc === \"n\" ? \"\\n\" : esc;\r\n continue;\r\n }\r\n if (ch === '\"') {\r\n advance();\r\n terminated = true;\r\n break;\r\n }\r\n if (ch === \"\\n\") break; // strings don't span lines\r\n value += advance();\r\n }\r\n if (!terminated) {\r\n errors.push({ message: \"Unterminated string literal\", span: { start: startIdx, end: i } });\r\n }\r\n push(\"string\", value, startLine, startCol, startIdx);\r\n continue;\r\n }\r\n\r\n // Punctuation & operators\r\n if (c === \"(\") { advance(); push(\"lparen\", \"(\", startLine, startCol, startIdx); continue; }\r\n if (c === \")\") { advance(); push(\"rparen\", \")\", startLine, startCol, startIdx); continue; }\r\n if (c === \"{\") { advance(); push(\"lcurly\", \"{\", startLine, startCol, startIdx); continue; }\r\n if (c === \"}\") { advance(); push(\"rcurly\", \"}\", startLine, startCol, startIdx); continue; }\r\n if (c === \",\") { advance(); push(\"comma\", \",\", startLine, startCol, startIdx); continue; }\r\n if (c === \"=\") { advance(); push(\"equals\", \"=\", startLine, startCol, startIdx); continue; }\r\n if (c === \":\") { advance(); push(\"colon\", \":\", startLine, startCol, startIdx); continue; }\r\n if (c === \"-\" && peek(1) === \">\") { advance(); advance(); push(\"arrow\", \"->\", startLine, startCol, startIdx); continue; }\r\n\r\n // Number (optionally part of a dimension WxH)\r\n if (isDigit(c) || (c === \"-\" && isDigit(peek(1))) || (c === \".\" && isDigit(peek(1)))) {\r\n let raw = \"\";\r\n if (c === \"-\") raw += advance();\r\n while (isDigit(peek())) raw += advance();\r\n if (peek() === \".\") {\r\n raw += advance();\r\n while (isDigit(peek())) raw += advance();\r\n }\r\n const first = parseFloat(raw);\r\n // Dimension: <num>x<num>\r\n if (peek() === \"x\" && (isDigit(peek(1)) || (peek(1) === \"-\" && isDigit(peek(2))) || (peek(1) === \".\" && isDigit(peek(2))))) {\r\n advance(); // consume 'x'\r\n let raw2 = \"\";\r\n if (peek() === \"-\") raw2 += advance();\r\n while (isDigit(peek())) raw2 += advance();\r\n if (peek() === \".\") {\r\n raw2 += advance();\r\n while (isDigit(peek())) raw2 += advance();\r\n }\r\n const second = parseFloat(raw2);\r\n push(\"dimension\", `${raw}x${raw2}`, startLine, startCol, startIdx, { num: first, num2: second });\r\n continue;\r\n }\r\n push(\"number\", raw, startLine, startCol, startIdx, { num: first });\r\n continue;\r\n }\r\n\r\n // Identifier / keyword\r\n if (isIdentStart(c)) {\r\n let value = \"\";\r\n while (i < src.length && isIdentPart(peek())) value += advance();\r\n push(\"ident\", value, startLine, startCol, startIdx);\r\n continue;\r\n }\r\n\r\n // Unknown character\r\n errors.push({ message: `Unexpected character ${JSON.stringify(c)}`, span: { start: startIdx, end: startIdx + 1 } });\r\n advance();\r\n }\r\n\r\n push(\"eof\", \"\", line, col, i);\r\n return { tokens, errors };\r\n}\r\n","/** Pure geometry helpers. All coordinates in millimetres. Deterministic. */\r\n\r\nimport type { Point } from \"./ast.js\";\r\n\r\nexport interface Vec {\r\n x: number;\r\n y: number;\r\n}\r\n\r\nexport const sub = (a: Point, b: Point): Vec => ({ x: a.x - b.x, y: a.y - b.y });\r\nexport const add = (a: Point, b: Vec): Point => ({ x: a.x + b.x, y: a.y + b.y });\r\nexport const mul = (v: Vec, s: number): Vec => ({ x: v.x * s, y: v.y * s });\r\nexport const length = (v: Vec): number => Math.hypot(v.x, v.y);\r\nexport function unit(v: Vec): Vec {\r\n const l = length(v);\r\n return l === 0 ? { x: 0, y: 0 } : { x: v.x / l, y: v.y / l };\r\n}\r\n/** Left normal (rotate +90°). */\r\nexport const normal = (v: Vec): Vec => ({ x: -v.y, y: v.x });\r\n\r\nexport interface Bounds {\r\n minX: number;\r\n minY: number;\r\n maxX: number;\r\n maxY: number;\r\n}\r\n\r\nexport const emptyBounds = (): Bounds => ({\r\n minX: Infinity,\r\n minY: Infinity,\r\n maxX: -Infinity,\r\n maxY: -Infinity,\r\n});\r\n\r\nexport function extendBounds(b: Bounds, x: number, y: number): void {\r\n if (x < b.minX) b.minX = x;\r\n if (y < b.minY) b.minY = y;\r\n if (x > b.maxX) b.maxX = x;\r\n if (y > b.maxY) b.maxY = y;\r\n}\r\n\r\n/** Distance from point p to segment ab. */\r\nexport function distPointToSegment(p: Point, a: Point, b: Point): number {\r\n const abx = b.x - a.x;\r\n const aby = b.y - a.y;\r\n const apx = p.x - a.x;\r\n const apy = p.y - a.y;\r\n const len2 = abx * abx + aby * aby;\r\n let t = len2 === 0 ? 0 : (apx * abx + apy * aby) / len2;\r\n t = Math.max(0, Math.min(1, t));\r\n const cx = a.x + t * abx;\r\n const cy = a.y + t * aby;\r\n return Math.hypot(p.x - cx, p.y - cy);\r\n}\r\n\r\n/** Axis-aligned rectangle corners (clockwise) from origin + size. */\r\nexport function rectCorners(x: number, y: number, w: number, h: number): Point[] {\r\n return [\r\n { x, y },\r\n { x: x + w, y },\r\n { x: x + w, y: y + h },\r\n { x, y: y + h },\r\n ];\r\n}\r\n\r\n/**\r\n * Square-capped offset rectangle for a wall segment: the segment is widened by\r\n * `thickness` and extended by `thickness/2` at each end so orthogonal corners\r\n * fill cleanly when adjacent segments are drawn.\r\n */\r\nexport function segmentRectangle(a: Point, b: Point, thickness: number): Point[] {\r\n const d = unit(sub(b, a));\r\n const n = normal(d);\r\n const half = thickness / 2;\r\n const a2 = add(a, mul(d, -half));\r\n const b2 = add(b, mul(d, half));\r\n return [\r\n add(a2, mul(n, half)),\r\n add(b2, mul(n, half)),\r\n add(b2, mul(n, -half)),\r\n add(a2, mul(n, -half)),\r\n ];\r\n}\r\n\r\nexport interface WallSegment {\r\n a: Point;\r\n b: Point;\r\n thickness: number;\r\n category: string;\r\n}\r\n\r\n/** Minimal wall shape needed by the segment/hosting helpers (a resolved wall). */\r\nexport interface WallLike {\r\n id: string;\r\n category: string;\r\n thickness: number;\r\n points: Point[];\r\n closed: boolean;\r\n}\r\n\r\n/** Flatten a single wall into its individual segments. */\r\nexport function segmentsOfWall(w: WallLike): WallSegment[] {\r\n const segs: WallSegment[] = [];\r\n for (let k = 0; k < w.points.length - 1; k++) {\r\n segs.push({ a: w.points[k], b: w.points[k + 1], thickness: w.thickness, category: w.category });\r\n }\r\n if (w.closed && w.points.length > 2) {\r\n segs.push({ a: w.points[w.points.length - 1], b: w.points[0], thickness: w.thickness, category: w.category });\r\n }\r\n return segs;\r\n}\r\n\r\n/** The wall segment hosting an opening point (nearest), filtered by ref if given. */\r\nexport function hostSegmentForWalls(walls: WallLike[], at: Point, ref?: string): WallSegment | null {\r\n const candidates = ref ? walls.filter((w) => w.id === ref || w.category === ref) : walls;\r\n let best: WallSegment | null = null;\r\n let bestDist = Infinity;\r\n for (const w of candidates) {\r\n for (const s of segmentsOfWall(w)) {\r\n const dist = distPointToSegment(at, s.a, s.b);\r\n if (dist < bestDist) {\r\n bestDist = dist;\r\n best = s;\r\n }\r\n }\r\n }\r\n return best;\r\n}\r\n\r\n/** Whether a point lies within tolerance of some wall (filtered by ref if given). */\r\nexport function isOnSomeWall(walls: WallLike[], at: Point, ref?: string): boolean {\r\n const candidates = ref ? walls.filter((w) => w.id === ref || w.category === ref) : walls;\r\n for (const w of candidates) {\r\n const tol = w.thickness / 2 + Math.max(w.thickness, 1);\r\n for (const s of segmentsOfWall(w)) {\r\n if (distPointToSegment(at, s.a, s.b) <= tol) return true;\r\n }\r\n }\r\n return false;\r\n}\r\n","/** `wall <category> thickness N { (x,y)… [close] }` — poché fill + crisp faces. */\r\n\r\nimport type { Point, WallNode } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, RenderOp, ResolveCtx } from \"../registry.js\";\r\nimport type { RWall } from \"../ir.js\";\r\nimport { add, mul, normal, segmentRectangle, segmentsOfWall, sub, unit } from \"../geometry.js\";\r\n\r\nexport const wall: ElementDef = {\r\n kind: \"wall\",\r\n keyword: \"wall\",\r\n\r\n parse(ctx: ParseCtx): WallNode {\r\n const kw = ctx.eatKeyword(\"wall\");\r\n const id = ctx.parseIdOpt();\r\n const category = ctx.eatIdent().value;\r\n ctx.eatKeyword(\"thickness\");\r\n const thickness = ctx.eatNumber();\r\n ctx.eat(\"lcurly\");\r\n const points: Point[] = [];\r\n let closed = false;\r\n while (!ctx.isType(\"rcurly\") && !ctx.isType(\"eof\")) {\r\n if (ctx.isKeyword(\"close\")) {\r\n ctx.next();\r\n closed = true;\r\n break;\r\n }\r\n if (ctx.isType(\"lparen\")) {\r\n points.push(ctx.parsePoint());\r\n continue;\r\n }\r\n ctx.fail(`Expected a point \"(x,y)\" or \"close\" in wall body but found ${describe(ctx)}`);\r\n }\r\n ctx.eat(\"rcurly\");\r\n if (points.length < 2) ctx.fail(\"A wall needs at least two points\", kw);\r\n return { kind: \"wall\", id, category, thickness, points, closed, line: kw.line };\r\n },\r\n\r\n idPrefix: (node) => (node as WallNode).category || \"wall\",\r\n\r\n resolve(node, ctx: ResolveCtx): RWall {\r\n const n = node as WallNode;\r\n const id = ctx.idOf(n);\r\n const points = n.points.map(ctx.snapPt);\r\n const thickness = ctx.snap(n.thickness) || n.thickness;\r\n if (thickness <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Wall \"${id}\" must have a positive thickness`, code: \"E_WALL_THICKNESS\", span: n.span });\r\n }\r\n return { kind: \"wall\", id, category: n.category, thickness, points, closed: n.closed, span: n.span };\r\n },\r\n\r\n bounds(resolved): Point[] {\r\n const w = resolved as RWall;\r\n return segmentsOfWall(w).flatMap((s) => segmentRectangle(s.a, s.b, s.thickness));\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const w = resolved as RWall;\r\n const { fmt, pt, theme, sizes } = ctx;\r\n const segs = segmentsOfWall(w);\r\n const ops: RenderOp[] = [];\r\n for (const s of segs) {\r\n const poly = segmentRectangle(s.a, s.b, s.thickness);\r\n ops.push({ pass: \"wallFill\", svg: `<polygon points=\"${poly.map(pt).join(\" \")}\" fill=\"url(#poche)\"/>` });\r\n }\r\n for (const s of segs) {\r\n const d = unit(sub(s.b, s.a));\r\n const n = normal(d);\r\n const h = s.thickness / 2;\r\n const fa1 = add(s.a, mul(n, h));\r\n const fb1 = add(s.b, mul(n, h));\r\n const fa2 = add(s.a, mul(n, -h));\r\n const fb2 = add(s.b, mul(n, -h));\r\n ops.push({\r\n pass: \"wallFace\",\r\n svg: `<line x1=\"${fmt(fa1.x)}\" y1=\"${fmt(fa1.y)}\" x2=\"${fmt(fb1.x)}\" y2=\"${fmt(fb1.y)}\" stroke=\"${theme.wallStroke}\" stroke-width=\"${fmt(sizes.wallStroke)}\" stroke-linecap=\"square\"/>`,\r\n });\r\n ops.push({\r\n pass: \"wallFace\",\r\n svg: `<line x1=\"${fmt(fa2.x)}\" y1=\"${fmt(fa2.y)}\" x2=\"${fmt(fb2.x)}\" y2=\"${fmt(fb2.y)}\" stroke=\"${theme.wallStroke}\" stroke-width=\"${fmt(sizes.wallStroke)}\" stroke-linecap=\"square\"/>`,\r\n });\r\n }\r\n return ops;\r\n },\r\n};\r\n\r\nfunction describe(ctx: ParseCtx): string {\r\n const t = ctx.peek();\r\n if (t.type === \"eof\") return \"end of input\";\r\n if (t.type === \"string\") return `string ${JSON.stringify(t.value)}`;\r\n return `\"${t.value}\"`;\r\n}\r\n","/** `room [id=] at (x,y) size WxH [label \"…\"]` — floor fill + label + computed area. */\r\n\r\nimport type { Point, RoomNode } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, RenderOp, ResolveCtx } from \"../registry.js\";\r\nimport type { RRoom } from \"../ir.js\";\r\nimport { rectCorners } from \"../geometry.js\";\r\n\r\nexport const room: ElementDef = {\r\n kind: \"room\",\r\n keyword: \"room\",\r\n\r\n parse(ctx: ParseCtx): RoomNode {\r\n const kw = ctx.eatKeyword(\"room\");\r\n const id = ctx.parseIdOpt();\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"size\");\r\n const dim = ctx.eat(\"dimension\");\r\n const node: RoomNode = { kind: \"room\", id, at, size: { w: dim.num!, h: dim.num2! }, line: kw.line };\r\n if (ctx.isKeyword(\"label\")) {\r\n ctx.next();\r\n node.label = ctx.eatString();\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: () => \"room\",\r\n\r\n resolve(node, ctx: ResolveCtx): RRoom {\r\n const n = node as RoomNode;\r\n const id = ctx.idOf(n);\r\n const at = ctx.snapPt(n.at);\r\n const size = { w: ctx.snap(n.size.w), h: ctx.snap(n.size.h) };\r\n if (size.w <= 0 || size.h <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Room \"${id}\" must have a positive size`, code: \"E_ROOM_SIZE\", span: n.span });\r\n }\r\n return { kind: \"room\", id, at, size, label: n.label, span: n.span };\r\n },\r\n\r\n bounds(resolved): Point[] {\r\n const r = resolved as RRoom;\r\n return rectCorners(r.at.x, r.at.y, r.size.w, r.size.h);\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const r = resolved as RRoom;\r\n const { fmt, pt, xml, theme, sizes } = ctx;\r\n const ops: RenderOp[] = [];\r\n const c = rectCorners(r.at.x, r.at.y, r.size.w, r.size.h);\r\n ops.push({ pass: \"floor\", svg: `<polygon points=\"${c.map(pt).join(\" \")}\" fill=\"${theme.roomFill}\"/>` });\r\n\r\n const cx = r.at.x + r.size.w / 2;\r\n const cy = r.at.y + r.size.h / 2;\r\n const areaM2 = ((r.size.w / 1000) * (r.size.h / 1000)).toFixed(1);\r\n if (r.label) {\r\n ops.push({\r\n pass: \"labels\",\r\n svg: `<text x=\"${fmt(cx)}\" y=\"${fmt(cy - sizes.roomFont * 0.2)}\" font-size=\"${fmt(sizes.roomFont)}\" fill=\"${theme.roomLabel}\" text-anchor=\"middle\" dominant-baseline=\"central\" font-weight=\"600\">${xml(r.label)}</text>`,\r\n });\r\n }\r\n ops.push({\r\n pass: \"labels\",\r\n svg: `<text x=\"${fmt(cx)}\" y=\"${fmt(cy + (r.label ? sizes.roomFont * 0.9 : 0))}\" font-size=\"${fmt(sizes.areaFont)}\" fill=\"${theme.areaLabel}\" text-anchor=\"middle\" dominant-baseline=\"central\">${areaM2} m²</text>`,\r\n });\r\n return ops;\r\n },\r\n};\r\n","/** `door [id=] at (x,y) width N [wall ref] [hinge l|r] [swing in|out]` — opening + leaf + swing arc. */\r\n\r\nimport type { DoorNode, Point } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, RenderOp, ResolveCtx } from \"../registry.js\";\r\nimport type { RDoor } from \"../ir.js\";\r\nimport { add, mul, normal, sub, unit } from \"../geometry.js\";\r\n\r\nexport const door: ElementDef = {\r\n kind: \"door\",\r\n keyword: \"door\",\r\n\r\n parse(ctx: ParseCtx): DoorNode {\r\n const kw = ctx.eatKeyword(\"door\");\r\n const id = ctx.parseIdOpt();\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"width\");\r\n const width = ctx.eatNumber();\r\n const node: DoorNode = { kind: \"door\", id, at, width, hinge: \"left\", swing: \"in\", line: kw.line };\r\n if (ctx.isKeyword(\"wall\")) {\r\n ctx.next();\r\n node.wall = ctx.eatIdent().value;\r\n }\r\n if (ctx.isKeyword(\"hinge\")) {\r\n ctx.next();\r\n const h = ctx.eatIdent().value;\r\n if (h !== \"left\" && h !== \"right\") ctx.fail(`Expected hinge \"left\" or \"right\" but found \"${h}\"`);\r\n node.hinge = h;\r\n }\r\n if (ctx.isKeyword(\"swing\")) {\r\n ctx.next();\r\n const s = ctx.eatIdent().value;\r\n if (s !== \"in\" && s !== \"out\") ctx.fail(`Expected swing \"in\" or \"out\" but found \"${s}\"`);\r\n node.swing = s;\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: () => \"door\",\r\n\r\n resolve(node, ctx: ResolveCtx): RDoor {\r\n const n = node as DoorNode;\r\n const id = ctx.idOf(n);\r\n const at = ctx.snapPt(n.at);\r\n const width = ctx.snap(n.width) || n.width;\r\n if (width <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Door \"${id}\" must have a positive width`, code: \"E_DOOR_WIDTH\", span: n.span });\r\n }\r\n if (ctx.walls.length > 0 && !ctx.isOnWall(at, n.wall)) {\r\n ctx.diag({ severity: \"warning\", message: `Door \"${id}\" does not lie on any wall`, code: \"W_DOOR_OFF_WALL\", span: n.span });\r\n }\r\n return { kind: \"door\", id, at, width, hinge: n.hinge, swing: n.swing, host: ctx.hostSegment(at, n.wall), span: n.span };\r\n },\r\n\r\n bounds: () => [],\r\n\r\n render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const dr = resolved as RDoor;\r\n const seg = dr.host;\r\n if (!seg) return [];\r\n const { fmt, pt, theme, sizes } = ctx;\r\n const d = unit(sub(seg.b, seg.a));\r\n const n = normal(d);\r\n const h = seg.thickness / 2 + sizes.wallStroke;\r\n const hw = dr.width / 2;\r\n const cover: Point[] = [\r\n add(add(dr.at, mul(d, -hw)), mul(n, h)),\r\n add(add(dr.at, mul(d, hw)), mul(n, h)),\r\n add(add(dr.at, mul(d, hw)), mul(n, -h)),\r\n add(add(dr.at, mul(d, -hw)), mul(n, -h)),\r\n ];\r\n const ops: RenderOp[] = [];\r\n ops.push({ pass: \"doors\", svg: `<polygon points=\"${cover.map(pt).join(\" \")}\" fill=\"${theme.opening}\"/>` });\r\n const hinge = dr.hinge === \"left\" ? add(dr.at, mul(d, -hw)) : add(dr.at, mul(d, hw));\r\n const farJamb = dr.hinge === \"left\" ? add(dr.at, mul(d, hw)) : add(dr.at, mul(d, -hw));\r\n const leafDir = dr.swing === \"in\" ? n : mul(n, -1);\r\n const leafEnd = add(hinge, mul(leafDir, dr.width));\r\n const cross = (leafEnd.x - hinge.x) * (farJamb.y - hinge.y) - (leafEnd.y - hinge.y) * (farJamb.x - hinge.x);\r\n const sweep = cross < 0 ? 1 : 0;\r\n ops.push({\r\n pass: \"doors\",\r\n svg: `<line x1=\"${fmt(hinge.x)}\" y1=\"${fmt(hinge.y)}\" x2=\"${fmt(leafEnd.x)}\" y2=\"${fmt(leafEnd.y)}\" stroke=\"${theme.doorLeaf}\" stroke-width=\"${fmt(sizes.thin * 1.3)}\"/>`,\r\n });\r\n ops.push({\r\n pass: \"doors\",\r\n svg: `<path d=\"M ${pt(leafEnd)} A ${fmt(dr.width)} ${fmt(dr.width)} 0 0 ${sweep} ${pt(farJamb)}\" fill=\"none\" stroke=\"${theme.doorLeaf}\" stroke-width=\"${fmt(sizes.thin)}\" stroke-dasharray=\"${fmt(sizes.thin * 4)} ${fmt(sizes.thin * 3)}\"/>`,\r\n });\r\n return ops;\r\n },\r\n};\r\n","/** `window [id=] at (x,y) width N [wall ref]` — opening + glazing panes. */\r\n\r\nimport type { Point, WindowNode } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, RenderOp, ResolveCtx } from \"../registry.js\";\r\nimport type { RWindow } from \"../ir.js\";\r\nimport { add, mul, normal, sub, unit } from \"../geometry.js\";\r\n\r\nexport const windowEl: ElementDef = {\r\n kind: \"window\",\r\n keyword: \"window\",\r\n\r\n parse(ctx: ParseCtx): WindowNode {\r\n const kw = ctx.eatKeyword(\"window\");\r\n const id = ctx.parseIdOpt();\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"width\");\r\n const width = ctx.eatNumber();\r\n const node: WindowNode = { kind: \"window\", id, at, width, line: kw.line };\r\n if (ctx.isKeyword(\"wall\")) {\r\n ctx.next();\r\n node.wall = ctx.eatIdent().value;\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: () => \"window\",\r\n\r\n resolve(node, ctx: ResolveCtx): RWindow {\r\n const n = node as WindowNode;\r\n const id = ctx.idOf(n);\r\n const at = ctx.snapPt(n.at);\r\n const width = ctx.snap(n.width) || n.width;\r\n if (width <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Window \"${id}\" must have a positive width`, code: \"E_WINDOW_WIDTH\", span: n.span });\r\n }\r\n if (ctx.walls.length > 0 && !ctx.isOnWall(at, n.wall)) {\r\n ctx.diag({ severity: \"warning\", message: `Window \"${id}\" does not lie on any wall`, code: \"W_WINDOW_OFF_WALL\", span: n.span });\r\n }\r\n return { kind: \"window\", id, at, width, host: ctx.hostSegment(at, n.wall), span: n.span };\r\n },\r\n\r\n bounds: () => [],\r\n\r\n render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const wn = resolved as RWindow;\r\n const seg = wn.host;\r\n if (!seg) return [];\r\n const { fmt, pt, theme, sizes } = ctx;\r\n const d = unit(sub(seg.b, seg.a));\r\n const n = normal(d);\r\n const h = seg.thickness / 2;\r\n const he = h + sizes.wallStroke;\r\n const hw = wn.width / 2;\r\n const cover: Point[] = [\r\n add(add(wn.at, mul(d, -hw)), mul(n, he)),\r\n add(add(wn.at, mul(d, hw)), mul(n, he)),\r\n add(add(wn.at, mul(d, hw)), mul(n, -he)),\r\n add(add(wn.at, mul(d, -hw)), mul(n, -he)),\r\n ];\r\n const ops: RenderOp[] = [];\r\n ops.push({ pass: \"windows\", svg: `<polygon points=\"${cover.map(pt).join(\" \")}\" fill=\"${theme.opening}\"/>` });\r\n const jA = add(wn.at, mul(d, -hw));\r\n const jB = add(wn.at, mul(d, hw));\r\n for (const off of [h, -h]) {\r\n const a = add(jA, mul(n, off));\r\n const bb = add(jB, mul(n, off));\r\n ops.push({\r\n pass: \"windows\",\r\n svg: `<line x1=\"${fmt(a.x)}\" y1=\"${fmt(a.y)}\" x2=\"${fmt(bb.x)}\" y2=\"${fmt(bb.y)}\" stroke=\"${theme.wallStroke}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\r\n }\r\n ops.push({\r\n pass: \"windows\",\r\n svg: `<line x1=\"${fmt(jA.x)}\" y1=\"${fmt(jA.y)}\" x2=\"${fmt(jB.x)}\" y2=\"${fmt(jB.y)}\" stroke=\"${theme.windowPane}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\r\n return ops;\r\n },\r\n};\r\n","/** `furniture <category> [id=] at (x,y) size WxH [label \"…\"]` — outlined fill + label. */\r\n\r\nimport type { FurnitureNode, Point } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, RenderOp, ResolveCtx } from \"../registry.js\";\r\nimport type { RFurniture } from \"../ir.js\";\r\nimport { rectCorners } from \"../geometry.js\";\r\n\r\nexport const furniture: ElementDef = {\r\n kind: \"furniture\",\r\n keyword: \"furniture\",\r\n\r\n parse(ctx: ParseCtx): FurnitureNode {\r\n const kw = ctx.eatKeyword(\"furniture\");\r\n const id = ctx.parseIdOpt();\r\n const category = ctx.eatIdent().value;\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"size\");\r\n const dim = ctx.eat(\"dimension\");\r\n const node: FurnitureNode = { kind: \"furniture\", id, category, at, size: { w: dim.num!, h: dim.num2! }, line: kw.line };\r\n if (ctx.isKeyword(\"label\")) {\r\n ctx.next();\r\n node.label = ctx.eatString();\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: (node) => (node as FurnitureNode).category || \"furniture\",\r\n\r\n resolve(node, ctx: ResolveCtx): RFurniture {\r\n const n = node as FurnitureNode;\r\n const id = ctx.idOf(n);\r\n const at = ctx.snapPt(n.at);\r\n const size = { w: ctx.snap(n.size.w), h: ctx.snap(n.size.h) };\r\n if (size.w <= 0 || size.h <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Furniture \"${id}\" must have a positive size`, code: \"E_FURN_SIZE\", span: n.span });\r\n }\r\n return { kind: \"furniture\", id, category: n.category, at, size, label: n.label, span: n.span };\r\n },\r\n\r\n bounds(resolved): Point[] {\r\n const f = resolved as RFurniture;\r\n return rectCorners(f.at.x, f.at.y, f.size.w, f.size.h);\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const f = resolved as RFurniture;\r\n const { fmt, pt, xml, theme, sizes } = ctx;\r\n const ops: RenderOp[] = [];\r\n const c = rectCorners(f.at.x, f.at.y, f.size.w, f.size.h);\r\n ops.push({\r\n pass: \"furniture\",\r\n svg: `<polygon points=\"${c.map(pt).join(\" \")}\" fill=\"${theme.furnitureFill}\" stroke=\"${theme.furnitureStroke}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\r\n if (f.label) {\r\n const cx = f.at.x + f.size.w / 2;\r\n const cy = f.at.y + f.size.h / 2;\r\n ops.push({\r\n pass: \"furniture\",\r\n svg: `<text x=\"${fmt(cx)}\" y=\"${fmt(cy)}\" font-size=\"${fmt(sizes.furnFont)}\" fill=\"${theme.furnitureLabel}\" text-anchor=\"middle\" dominant-baseline=\"central\">${xml(f.label)}</text>`,\r\n });\r\n }\r\n return ops;\r\n },\r\n};\r\n","/** `dim (x,y)->(x,y) [offset N] [text \"…\"]` — dimension line with ticks + length. */\r\n\r\nimport type { DimNode } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, RenderOp, ResolveCtx } from \"../registry.js\";\r\nimport type { RDim } from \"../ir.js\";\r\nimport { add, length, mul, normal, sub, unit } from \"../geometry.js\";\r\n\r\nexport const dim: ElementDef = {\r\n kind: \"dim\",\r\n keyword: \"dim\",\r\n\r\n parse(ctx: ParseCtx): DimNode {\r\n const kw = ctx.eatKeyword(\"dim\");\r\n const from = ctx.parsePoint();\r\n ctx.eat(\"arrow\");\r\n const to = ctx.parsePoint();\r\n const node: DimNode = { kind: \"dim\", id: \"\", from, to, offset: 300, line: kw.line };\r\n if (ctx.isKeyword(\"offset\")) {\r\n ctx.next();\r\n node.offset = ctx.eatNumber();\r\n }\r\n if (ctx.isKeyword(\"text\")) {\r\n ctx.next();\r\n node.text = ctx.eatString();\r\n }\r\n return node;\r\n },\r\n\r\n idPrefix: () => \"dim\",\r\n\r\n resolve(node, ctx: ResolveCtx): RDim {\r\n const n = node as DimNode;\r\n return {\r\n kind: \"dim\",\r\n id: ctx.idOf(n),\r\n from: ctx.snapPt(n.from),\r\n to: ctx.snapPt(n.to),\r\n offset: n.offset,\r\n text: n.text,\r\n span: n.span,\r\n };\r\n },\r\n\r\n bounds(resolved) {\r\n const dm = resolved as RDim;\r\n return [dm.from, dm.to];\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const dm = resolved as RDim;\r\n const { fmt, xml, theme, sizes } = ctx;\r\n const dir = unit(sub(dm.to, dm.from));\r\n const n = normal(dir);\r\n const off = mul(n, dm.offset);\r\n const p1 = add(dm.from, off);\r\n const p2 = add(dm.to, off);\r\n const tick = sizes.refDim * 0.012;\r\n const ops: RenderOp[] = [];\r\n ops.push({\r\n pass: \"dims\",\r\n svg: `<line x1=\"${fmt(dm.from.x)}\" y1=\"${fmt(dm.from.y)}\" x2=\"${fmt(p1.x)}\" y2=\"${fmt(p1.y)}\" stroke=\"${theme.dim}\" stroke-width=\"${fmt(sizes.thin * 0.7)}\"/>`,\r\n });\r\n ops.push({\r\n pass: \"dims\",\r\n svg: `<line x1=\"${fmt(dm.to.x)}\" y1=\"${fmt(dm.to.y)}\" x2=\"${fmt(p2.x)}\" y2=\"${fmt(p2.y)}\" stroke=\"${theme.dim}\" stroke-width=\"${fmt(sizes.thin * 0.7)}\"/>`,\r\n });\r\n ops.push({\r\n pass: \"dims\",\r\n svg: `<line x1=\"${fmt(p1.x)}\" y1=\"${fmt(p1.y)}\" x2=\"${fmt(p2.x)}\" y2=\"${fmt(p2.y)}\" stroke=\"${theme.dim}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\r\n for (const p of [p1, p2]) {\r\n const t1 = add(p, mul(unit({ x: dir.x + n.x, y: dir.y + n.y }), tick));\r\n const t2 = add(p, mul(unit({ x: dir.x + n.x, y: dir.y + n.y }), -tick));\r\n ops.push({\r\n pass: \"dims\",\r\n svg: `<line x1=\"${fmt(t1.x)}\" y1=\"${fmt(t1.y)}\" x2=\"${fmt(t2.x)}\" y2=\"${fmt(t2.y)}\" stroke=\"${theme.dim}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n });\r\n }\r\n const mid = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 };\r\n const tp = add(mid, mul(n, sizes.dimFont * 0.7));\r\n let angle = (Math.atan2(dir.y, dir.x) * 180) / Math.PI;\r\n if (angle > 90) angle -= 180;\r\n if (angle < -90) angle += 180;\r\n const label = dm.text ?? String(Math.round(length(sub(dm.to, dm.from))));\r\n ops.push({\r\n pass: \"dims\",\r\n svg: `<text x=\"${fmt(tp.x)}\" y=\"${fmt(tp.y)}\" font-size=\"${fmt(sizes.dimFont)}\" fill=\"${theme.dim}\" text-anchor=\"middle\" dominant-baseline=\"central\" transform=\"rotate(${fmt(angle)} ${fmt(tp.x)} ${fmt(tp.y)})\">${xml(label)}</text>`,\r\n });\r\n return ops;\r\n },\r\n};\r\n","/**\r\n * `column [id=] at (x,y) size WxH` — a solid structural column.\r\n *\r\n * This module is the extensibility proof for the v0.3 registry: a brand-new\r\n * element type added as ONE file + one `register` line in `index.ts`, with no\r\n * edits to the parser, resolver, or renderer cores.\r\n */\r\n\r\nimport type { ColumnNode, Point } from \"../ast.js\";\r\nimport type { ElementDef, ParseCtx, RenderCtx, RenderOp, ResolveCtx } from \"../registry.js\";\r\nimport type { RColumn } from \"../ir.js\";\r\nimport { rectCorners } from \"../geometry.js\";\r\n\r\nexport const column: ElementDef = {\r\n kind: \"column\",\r\n keyword: \"column\",\r\n\r\n parse(ctx: ParseCtx): ColumnNode {\r\n const kw = ctx.eatKeyword(\"column\");\r\n const id = ctx.parseIdOpt();\r\n ctx.eatKeyword(\"at\");\r\n const at = ctx.parsePoint();\r\n ctx.eatKeyword(\"size\");\r\n const dim = ctx.eat(\"dimension\");\r\n return { kind: \"column\", id, at, size: { w: dim.num!, h: dim.num2! }, line: kw.line };\r\n },\r\n\r\n idPrefix: () => \"column\",\r\n\r\n resolve(node, ctx: ResolveCtx): RColumn {\r\n const n = node as ColumnNode;\r\n const id = ctx.idOf(n);\r\n const at = ctx.snapPt(n.at);\r\n const size = { w: ctx.snap(n.size.w), h: ctx.snap(n.size.h) };\r\n if (size.w <= 0 || size.h <= 0) {\r\n ctx.diag({ severity: \"error\", message: `Column \"${id}\" must have a positive size`, code: \"E_COLUMN_SIZE\", span: n.span });\r\n }\r\n return { kind: \"column\", id, at, size, span: n.span };\r\n },\r\n\r\n bounds(resolved): Point[] {\r\n const c = resolved as RColumn;\r\n return rectCorners(c.at.x, c.at.y, c.size.w, c.size.h);\r\n },\r\n\r\n render(resolved, ctx: RenderCtx): RenderOp[] {\r\n const c = resolved as RColumn;\r\n const { fmt, pt, theme, sizes } = ctx;\r\n const pts = rectCorners(c.at.x, c.at.y, c.size.w, c.size.h);\r\n return [\r\n {\r\n pass: \"furniture\",\r\n svg: `<polygon points=\"${pts.map(pt).join(\" \")}\" fill=\"${theme.column}\" stroke=\"${theme.wallStroke}\" stroke-width=\"${fmt(sizes.thin)}\"/>`,\r\n },\r\n ];\r\n },\r\n};\r\n","/**\r\n * Element registry assembly. Registration order is canonical: it drives id\r\n * assignment and resolve ordering (walls first, so openings can host against\r\n * them). To add an element: write one module and add one `register()` line.\r\n */\r\n\r\nimport type { ElementDef } from \"../registry.js\";\r\nimport { wall } from \"./wall.js\";\r\nimport { room } from \"./room.js\";\r\nimport { door } from \"./door.js\";\r\nimport { windowEl } from \"./window.js\";\r\nimport { furniture } from \"./furniture.js\";\r\nimport { dim } from \"./dim.js\";\r\nimport { column } from \"./column.js\";\r\n\r\n/** Defs in canonical (registration) order. */\r\nexport const registryOrder: ElementDef[] = [];\r\n/** Lookup by keyword. */\r\nexport const registry = new Map<string, ElementDef>();\r\n\r\nfunction register(def: ElementDef): void {\r\n registry.set(def.keyword, def);\r\n registryOrder.push(def);\r\n}\r\n\r\nregister(wall);\r\nregister(room);\r\nregister(door);\r\nregister(windowEl);\r\nregister(furniture);\r\nregister(dim);\r\nregister(column);\r\n","/** Recursive-descent parser: tokens -> PlanNode. Registry-driven element dispatch. */\r\n\r\nimport type { Token } from \"./lexer.js\";\r\nimport { lex } from \"./lexer.js\";\r\nimport type { Diagnostic, Span } from \"./diagnostics.js\";\r\nimport type { NorthDir, PlanNode, Point, TitleNode } from \"./ast.js\";\r\nimport type { ParseCtx } from \"./registry.js\";\r\nimport { registry } from \"./elements/index.js\";\r\n\r\nexport interface ParseOutcome {\r\n plan?: PlanNode;\r\n diagnostics: Diagnostic[];\r\n}\r\n\r\n/** Plan-level settings (not registry elements). */\r\nconst SETTINGS = [\"units\", \"grid\", \"scale\", \"north\", \"title\"];\r\n/** Keywords that begin a plan-body statement; recovery resynchronizes to one. */\r\nconst STATEMENT_STARTS = new Set<string>([...SETTINGS, ...registry.keys()]);\r\n\r\n/** Thrown internally by `eat*` helpers; always caught within the parser. */\r\nclass ParseError extends Error {\r\n constructor(public override message: string, public span: Span) {\r\n super(message);\r\n }\r\n}\r\n\r\nexport function parse(src: string): ParseOutcome {\r\n const { tokens, errors: lexErrors } = lex(src);\r\n const lexDiags: Diagnostic[] = lexErrors.map((e) => ({\r\n severity: \"error\" as const,\r\n message: e.message,\r\n span: e.span,\r\n }));\r\n\r\n const p = new Parser(tokens);\r\n let plan: PlanNode | undefined;\r\n try {\r\n plan = p.parsePlan();\r\n } catch (e) {\r\n // Only a malformed plan *header* escapes parsePlan's per-statement recovery.\r\n if (e instanceof ParseError) {\r\n p.diagnostics.push({ severity: \"error\", message: e.message, span: e.span });\r\n } else {\r\n throw e;\r\n }\r\n }\r\n return { plan, diagnostics: [...lexDiags, ...p.diagnostics] };\r\n}\r\n\r\nclass Parser {\r\n private pos = 0;\r\n public diagnostics: Diagnostic[] = [];\r\n /** Facade passed to element parse functions (see registry.ts). */\r\n private readonly ctx: ParseCtx;\r\n\r\n constructor(private toks: Token[]) {\r\n this.ctx = {\r\n peek: (o) => this.peek(o),\r\n next: () => this.next(),\r\n eat: (type) => this.eat(type),\r\n eatKeyword: (kw) => this.eatKeyword(kw),\r\n eatIdent: () => this.eatIdent(),\r\n eatNumber: () => this.eatNumber(),\r\n eatString: () => this.eatString(),\r\n isKeyword: (kw, o) => this.isKeyword(kw, o),\r\n isType: (type) => this.isType(type),\r\n parsePoint: () => this.parsePoint(),\r\n parseIdOpt: () => this.parseIdOpt(),\r\n fail: (msg, t) => this.fail(msg, t),\r\n };\r\n }\r\n\r\n private peek(o = 0): Token {\r\n return this.toks[Math.min(this.pos + o, this.toks.length - 1)];\r\n }\r\n private next(): Token {\r\n return this.toks[Math.min(this.pos++, this.toks.length - 1)];\r\n }\r\n private fail(msg: string, t = this.peek()): never {\r\n throw new ParseError(msg, { start: t.start, end: t.end });\r\n }\r\n\r\n /** Span from a start offset to the end of the last consumed token. */\r\n private spanFrom(start: number): Span {\r\n const last = this.toks[Math.max(0, Math.min(this.pos - 1, this.toks.length - 1))];\r\n return { start, end: last.end };\r\n }\r\n\r\n /** Recover after a statement error: skip to the next statement start or block end. */\r\n private synchronize(): void {\r\n // Always make progress so a hard-stuck token can't loop forever.\r\n if (!this.isType(\"rcurly\") && !this.isType(\"eof\")) this.next();\r\n while (!this.isType(\"rcurly\") && !this.isType(\"eof\")) {\r\n const t = this.peek();\r\n if (t.type === \"ident\" && STATEMENT_STARTS.has(t.value)) return;\r\n this.next();\r\n }\r\n }\r\n\r\n private isKeyword(kw: string, o = 0): boolean {\r\n const t = this.peek(o);\r\n return t.type === \"ident\" && t.value === kw;\r\n }\r\n private eatKeyword(kw: string): Token {\r\n const t = this.peek();\r\n if (t.type !== \"ident\" || t.value !== kw) this.fail(`Expected \"${kw}\" but found ${describe(t)}`);\r\n return this.next();\r\n }\r\n private eat(type: Token[\"type\"]): Token {\r\n const t = this.peek();\r\n if (t.type !== type) this.fail(`Expected ${type} but found ${describe(t)}`);\r\n return this.next();\r\n }\r\n private eatIdent(): Token {\r\n return this.eat(\"ident\");\r\n }\r\n private eatNumber(): number {\r\n const t = this.eat(\"number\");\r\n return t.num!;\r\n }\r\n private eatString(): string {\r\n return this.eat(\"string\").value;\r\n }\r\n\r\n parsePlan(): PlanNode {\r\n this.eatKeyword(\"plan\");\r\n const name = this.eatString();\r\n this.eat(\"lcurly\");\r\n\r\n const plan: PlanNode = {\r\n name,\r\n units: \"mm\",\r\n grid: 0,\r\n north: \"up\",\r\n elements: [],\r\n };\r\n\r\n while (!this.isType(\"rcurly\") && !this.isType(\"eof\")) {\r\n const t = this.peek();\r\n const start = t.start;\r\n try {\r\n if (t.type !== \"ident\") this.fail(`Expected a statement but found ${describe(t)}`);\r\n const def = registry.get(t.value);\r\n if (def) {\r\n const node = def.parse(this.ctx);\r\n node.span = this.spanFrom(start);\r\n plan.elements.push(node);\r\n continue;\r\n }\r\n switch (t.value) {\r\n case \"units\": {\r\n this.next();\r\n const u = this.eatIdent().value;\r\n if (u !== \"mm\") this.fail(`Unsupported units \"${u}\" (only \"mm\" is supported)`, t);\r\n plan.units = \"mm\";\r\n break;\r\n }\r\n case \"grid\":\r\n this.next();\r\n plan.grid = this.eatNumber();\r\n break;\r\n case \"scale\": {\r\n this.next();\r\n const a = this.eatNumber();\r\n this.eat(\"colon\");\r\n const b = this.eatNumber();\r\n plan.scale = `${a}:${b}`;\r\n break;\r\n }\r\n case \"north\":\r\n this.next();\r\n plan.north = this.parseNorth();\r\n break;\r\n case \"title\": {\r\n const n = this.parseTitle();\r\n n.span = this.spanFrom(start);\r\n plan.title = n;\r\n break;\r\n }\r\n default:\r\n this.fail(`Unknown statement \"${t.value}\"`, t);\r\n }\r\n } catch (e) {\r\n if (e instanceof ParseError) {\r\n this.diagnostics.push({ severity: \"error\", message: e.message, span: e.span });\r\n this.synchronize();\r\n } else {\r\n throw e;\r\n }\r\n }\r\n }\r\n // A missing closing brace is reported but the partial plan is still returned.\r\n try {\r\n this.eat(\"rcurly\");\r\n } catch (e) {\r\n if (e instanceof ParseError) {\r\n this.diagnostics.push({ severity: \"error\", message: e.message, span: e.span });\r\n } else {\r\n throw e;\r\n }\r\n }\r\n return plan;\r\n }\r\n\r\n private isType(type: Token[\"type\"]): boolean {\r\n return this.peek().type === type;\r\n }\r\n\r\n /** Optional `id=<ident>` prefix; returns \"\" when absent. */\r\n private parseIdOpt(): string {\r\n if (this.isKeyword(\"id\")) {\r\n this.next();\r\n this.eat(\"equals\");\r\n return this.eatIdent().value;\r\n }\r\n return \"\";\r\n }\r\n\r\n private parseNorth(): NorthDir {\r\n const t = this.peek();\r\n if (t.type === \"number\") {\r\n this.next();\r\n return { deg: t.num! };\r\n }\r\n if (t.type === \"ident\" && [\"up\", \"down\", \"left\", \"right\"].includes(t.value)) {\r\n this.next();\r\n return t.value as NorthDir;\r\n }\r\n this.fail(`Expected a north direction (up|down|left|right|<degrees>) but found ${describe(t)}`);\r\n }\r\n\r\n private parsePoint(): Point {\r\n this.eat(\"lparen\");\r\n const x = this.eatNumber();\r\n this.eat(\"comma\");\r\n const y = this.eatNumber();\r\n this.eat(\"rparen\");\r\n return { x, y };\r\n }\r\n\r\n private parseTitle(): TitleNode {\r\n const kw = this.eatKeyword(\"title\");\r\n this.eat(\"lcurly\");\r\n const node: TitleNode = { line: kw.line };\r\n while (!this.isType(\"rcurly\") && !this.isType(\"eof\")) {\r\n const t = this.peek();\r\n if (t.type !== \"ident\") this.fail(`Expected a title field but found ${describe(t)}`);\r\n switch (t.value) {\r\n case \"project\":\r\n this.next();\r\n node.project = this.eatString();\r\n break;\r\n case \"drawn_by\":\r\n this.next();\r\n node.drawnBy = this.eatString();\r\n break;\r\n case \"date\":\r\n this.next();\r\n node.date = this.eatString();\r\n break;\r\n default:\r\n this.fail(`Unknown title field \"${t.value}\"`, t);\r\n }\r\n }\r\n this.eat(\"rcurly\");\r\n return node;\r\n }\r\n}\r\n\r\nfunction describe(t: Token): string {\r\n if (t.type === \"eof\") return \"end of input\";\r\n if (t.type === \"string\") return `string ${JSON.stringify(t.value)}`;\r\n return `\"${t.value}\"`;\r\n}\r\n","/**\r\n * Intermediate representation + `resolve(ast)`.\r\n *\r\n * `resolve` is the single place semantics live: it grid-snaps coordinates,\r\n * assigns ids, hosts openings, and runs semantic checks — producing a NEW\r\n * immutable IR (the input AST is never mutated). `render` consumes IR only.\r\n */\r\n\r\nimport type { AstElement, ElementKind, NorthDir, PlanNode, Point, TitleNode } from \"./ast.js\";\r\nimport type { Diagnostic, Span } from \"./diagnostics.js\";\r\nimport type { ResolveCtx } from \"./registry.js\";\r\nimport type { WallSegment } from \"./geometry.js\";\r\nimport { hostSegmentForWalls, isOnSomeWall } from \"./geometry.js\";\r\nimport { registryOrder } from \"./elements/index.js\";\r\n\r\nexport interface RBase {\r\n kind: ElementKind;\r\n id: string;\r\n span?: Span;\r\n}\r\n\r\nexport interface RWall extends RBase {\r\n kind: \"wall\";\r\n category: string;\r\n thickness: number;\r\n points: Point[];\r\n closed: boolean;\r\n}\r\nexport interface RRoom extends RBase {\r\n kind: \"room\";\r\n at: Point;\r\n size: { w: number; h: number };\r\n label?: string;\r\n}\r\nexport interface RDoor extends RBase {\r\n kind: \"door\";\r\n at: Point;\r\n width: number;\r\n hinge: \"left\" | \"right\";\r\n swing: \"in\" | \"out\";\r\n host: WallSegment | null;\r\n}\r\nexport interface RWindow extends RBase {\r\n kind: \"window\";\r\n at: Point;\r\n width: number;\r\n host: WallSegment | null;\r\n}\r\nexport interface RFurniture extends RBase {\r\n kind: \"furniture\";\r\n category: string;\r\n at: Point;\r\n size: { w: number; h: number };\r\n label?: string;\r\n}\r\nexport interface RDim extends RBase {\r\n kind: \"dim\";\r\n from: Point;\r\n to: Point;\r\n offset: number;\r\n text?: string;\r\n}\r\nexport interface RColumn extends RBase {\r\n kind: \"column\";\r\n at: Point;\r\n size: { w: number; h: number };\r\n}\r\n\r\nexport type ResolvedElement = RWall | RRoom | RDoor | RWindow | RFurniture | RDim | RColumn;\r\n\r\nexport interface ResolvedPlan {\r\n name: string;\r\n units: \"mm\";\r\n grid: number;\r\n scale?: string;\r\n north: NorthDir;\r\n title?: TitleNode;\r\n /** Resolved elements, in source order (for rendering). */\r\n elements: ResolvedElement[];\r\n /** Resolved walls (for bounds/hosting), in source order. */\r\n walls: RWall[];\r\n}\r\n\r\nexport function resolve(ast: PlanNode): { ir: ResolvedPlan; diagnostics: Diagnostic[] } {\r\n const diagnostics: Diagnostic[] = [];\r\n const g = ast.grid;\r\n const snap = (v: number) => (g > 0 ? Math.round(v / g) * g : v);\r\n const snapPt = (p: Point): Point => ({ x: snap(p.x), y: snap(p.y) });\r\n\r\n // 1. Assign ids in registry (canonical) order so cross-kind collisions and\r\n // auto-id numbering are byte-identical to the v0.2 validate pass.\r\n const idMap = new Map<AstElement, string>();\r\n const seen = new Set<string>();\r\n const assignId = (provided: string, prefix: string, idx: number, span?: Span): string => {\r\n if (provided) {\r\n if (seen.has(provided)) {\r\n diagnostics.push({ severity: \"error\", message: `Duplicate id \"${provided}\"`, code: \"E_DUP_ID\", span });\r\n }\r\n seen.add(provided);\r\n return provided;\r\n }\r\n let auto = `${prefix}_${idx}`;\r\n while (seen.has(auto)) auto = `${auto}_`;\r\n seen.add(auto);\r\n return auto;\r\n };\r\n for (const def of registryOrder) {\r\n let idx = 0;\r\n for (const node of ast.elements) {\r\n if (node.kind !== def.kind) continue;\r\n idx++;\r\n idMap.set(node, assignId(node.id, def.idPrefix(node), idx, node.span));\r\n }\r\n }\r\n\r\n // 2. Resolve in registry order (walls first → openings can host against them).\r\n const walls: RWall[] = [];\r\n const ctx: ResolveCtx = {\r\n grid: g,\r\n snap,\r\n snapPt,\r\n idOf: (node) => idMap.get(node) ?? node.id,\r\n walls,\r\n hostSegment: (at, ref) => hostSegmentForWalls(walls, at, ref),\r\n isOnWall: (at, ref) => isOnSomeWall(walls, at, ref),\r\n diag: (d) => diagnostics.push(d),\r\n };\r\n const rmap = new Map<AstElement, ResolvedElement>();\r\n for (const def of registryOrder) {\r\n for (const node of ast.elements) {\r\n if (node.kind !== def.kind) continue;\r\n const r = def.resolve(node, ctx);\r\n rmap.set(node, r);\r\n if (r.kind === \"wall\") walls.push(r);\r\n }\r\n }\r\n\r\n // 3. IR element list in source order (for rendering).\r\n const elements = ast.elements.map((n) => rmap.get(n)!);\r\n\r\n // 4. Cross-element checks.\r\n const drawable = elements.some(\r\n (e) => e.kind === \"wall\" || e.kind === \"room\" || e.kind === \"furniture\" || e.kind === \"column\",\r\n );\r\n if (!drawable) {\r\n diagnostics.push({\r\n severity: \"warning\",\r\n message: \"Plan has no walls, rooms, or furniture — nothing to draw\",\r\n code: \"W_EMPTY_PLAN\",\r\n });\r\n }\r\n const rooms = elements.filter((e): e is RRoom => e.kind === \"room\");\r\n for (let a = 0; a < rooms.length; a++) {\r\n for (let b = a + 1; b < rooms.length; b++) {\r\n const r1 = rooms[a];\r\n const r2 = rooms[b];\r\n const ox = Math.max(0, Math.min(r1.at.x + r1.size.w, r2.at.x + r2.size.w) - Math.max(r1.at.x, r2.at.x));\r\n const oy = Math.max(0, Math.min(r1.at.y + r1.size.h, r2.at.y + r2.size.h) - Math.max(r1.at.y, r2.at.y));\r\n if (ox > 1 && oy > 1) {\r\n diagnostics.push({\r\n severity: \"warning\",\r\n message: `Rooms \"${r1.id}\" and \"${r2.id}\" overlap`,\r\n code: \"W_ROOM_OVERLAP\",\r\n span: r2.span,\r\n });\r\n }\r\n }\r\n }\r\n\r\n const ir: ResolvedPlan = {\r\n name: ast.name,\r\n units: ast.units,\r\n grid: ast.grid,\r\n scale: ast.scale,\r\n north: ast.north,\r\n title: ast.title,\r\n elements,\r\n walls,\r\n };\r\n return { ir, diagnostics };\r\n}\r\n","/**\r\n * Element registry: the single extension point. Each element type is one module\r\n * exporting an {@link ElementDef}; parse/resolve/render iterate the registry\r\n * rather than a hard-coded switch. Adding an element = one new module + one\r\n * `register` line in `elements/index.ts`.\r\n */\r\n\r\nimport type { Token } from \"./lexer.js\";\r\nimport type { AstElement, ElementKind, Point } from \"./ast.js\";\r\nimport type { Diagnostic } from \"./diagnostics.js\";\r\nimport type { ResolvedElement, RWall } from \"./ir.js\";\r\nimport type { Bounds, WallSegment } from \"./geometry.js\";\r\n\r\n/**\r\n * Ordered render layers. Element ops are bucketed by pass and emitted in this\r\n * order, preserving source order within a pass — this exactly reproduces the\r\n * v0.1 global draw order (all wall fills, then all wall faces, doors before\r\n * windows, labels above fills, …).\r\n */\r\nexport const RENDER_PASSES = [\r\n \"floor\",\r\n \"furniture\",\r\n \"wallFill\",\r\n \"wallFace\",\r\n \"doors\",\r\n \"windows\",\r\n \"labels\",\r\n \"dims\",\r\n \"annotations\",\r\n] as const;\r\nexport type RenderPass = (typeof RENDER_PASSES)[number];\r\n\r\nexport interface RenderOp {\r\n pass: RenderPass;\r\n svg: string;\r\n}\r\n\r\n/** Parser facade handed to `ElementDef.parse` — the existing recursive-descent helpers. */\r\nexport interface ParseCtx {\r\n peek(o?: number): Token;\r\n next(): Token;\r\n eat(type: Token[\"type\"]): Token;\r\n eatKeyword(kw: string): Token;\r\n eatIdent(): Token;\r\n eatNumber(): number;\r\n eatString(): string;\r\n isKeyword(kw: string, o?: number): boolean;\r\n isType(type: Token[\"type\"]): boolean;\r\n parsePoint(): Point;\r\n parseIdOpt(): string;\r\n /** Report a fatal parse error at `t` (defaults to the current token); never returns. */\r\n fail(msg: string, t?: Token): never;\r\n}\r\n\r\n/** Semantic-analysis facade handed to `ElementDef.resolve`. */\r\nexport interface ResolveCtx {\r\n grid: number;\r\n snap(v: number): number;\r\n snapPt(p: Point): Point;\r\n /** Resolved id for an AST node (assigned in registry order before resolve). */\r\n idOf(node: AstElement): string;\r\n /** Resolved walls, ready before openings resolve (walls resolve first). */\r\n walls: RWall[];\r\n hostSegment(at: Point, ref?: string): WallSegment | null;\r\n isOnWall(at: Point, ref?: string): boolean;\r\n diag(d: Diagnostic): void;\r\n}\r\n\r\nexport interface RenderSizes {\r\n refDim: number;\r\n wallStroke: number;\r\n thin: number;\r\n roomFont: number;\r\n areaFont: number;\r\n dimFont: number;\r\n furnFont: number;\r\n margin: number;\r\n hatchGap: number;\r\n}\r\n\r\n/** Render facade: number formatting, theme, derived sizes, and drawing bounds. */\r\nexport interface RenderCtx {\r\n fmt(v: number): string;\r\n pt(p: Point): string;\r\n xml(s: string): string;\r\n theme: Record<string, string>;\r\n sizes: RenderSizes;\r\n bounds: Bounds;\r\n}\r\n\r\n/**\r\n * One element type. `TNode`/`TResolved` are the concrete node/IR types; the\r\n * registry stores these widened to the unions, and each module narrows via the\r\n * `kind` discriminant.\r\n */\r\nexport interface ElementDef {\r\n kind: ElementKind;\r\n keyword: string;\r\n parse(ctx: ParseCtx): AstElement;\r\n /** Auto-id prefix (e.g. \"room\", or a wall/furniture's category). */\r\n idPrefix(node: AstElement): string;\r\n resolve(node: AstElement, ctx: ResolveCtx): ResolvedElement;\r\n /** Points this element contributes to the drawing bounds. */\r\n bounds(resolved: ResolvedElement): Point[];\r\n render(resolved: ResolvedElement, ctx: RenderCtx): RenderOp[];\r\n}\r\n","/** Renders a resolved plan (IR) to a professional SVG floor plan. Deterministic. */\r\n\r\nimport type { Point } from \"./ast.js\";\r\nimport type { CompileOptions } from \"./types.js\";\r\nimport type { ResolvedPlan } from \"./ir.js\";\r\nimport type { RenderCtx, RenderSizes } from \"./registry.js\";\r\nimport { RENDER_PASSES } from \"./registry.js\";\r\nimport { registry } from \"./elements/index.js\";\r\nimport type { Bounds } from \"./geometry.js\";\r\nimport { emptyBounds, extendBounds } from \"./geometry.js\";\r\n\r\nconst THEME: Record<string, string> = {\r\n bg: \"#ffffff\",\r\n pocheBase: \"#e9e4db\",\r\n pocheHatch: \"#b9b1a4\",\r\n wallStroke: \"#1b1b1b\",\r\n roomFill: \"#fbfaf7\",\r\n roomLabel: \"#222222\",\r\n areaLabel: \"#7a7a7a\",\r\n furnitureStroke: \"#a8a29a\",\r\n furnitureFill: \"#f4f2ee\",\r\n furnitureLabel: \"#9a948c\",\r\n opening: \"#ffffff\",\r\n doorLeaf: \"#555555\",\r\n windowPane: \"#3a6ea5\",\r\n dim: \"#0E5484\",\r\n annotation: \"#333333\",\r\n annotationMuted: \"#888888\",\r\n column: \"#4a4a4a\",\r\n};\r\n\r\n/** Round to 2 decimals and strip trailing zeros — keeps output stable & compact. */\r\nfunction fmt(v: number): string {\r\n const r = Math.round(v * 100) / 100;\r\n return Object.is(r, -0) ? \"0\" : String(r);\r\n}\r\nconst pt = (p: Point): string => `${fmt(p.x)},${fmt(p.y)}`;\r\n\r\nfunction xml(s: string): string {\r\n return s\r\n .replace(/&/g, \"&\")\r\n .replace(/</g, \"<\")\r\n .replace(/>/g, \">\")\r\n .replace(/\"/g, \""\");\r\n}\r\n\r\nconst NICE_LENGTHS = [500, 1000, 2000, 5000, 10000, 20000, 50000, 100000];\r\nfunction niceBarLength(target: number): number {\r\n let best = NICE_LENGTHS[0];\r\n for (const v of NICE_LENGTHS) if (v <= target) best = v;\r\n return best;\r\n}\r\n\r\n/** Drawing bounds: each element contributes points via its registry `bounds`. */\r\nfunction planBounds(ir: ResolvedPlan): Bounds {\r\n const b = emptyBounds();\r\n for (const el of ir.elements) {\r\n const def = registry.get(el.kind);\r\n if (!def) continue;\r\n for (const p of def.bounds(el)) extendBounds(b, p.x, p.y);\r\n }\r\n if (!isFinite(b.minX)) {\r\n // Nothing to draw; provide a default frame.\r\n return { minX: 0, minY: 0, maxX: 1000, maxY: 1000 };\r\n }\r\n return b;\r\n}\r\n\r\nexport function render(ir: ResolvedPlan, opts: CompileOptions = {}): string {\r\n const b = planBounds(ir);\r\n const drawW = b.maxX - b.minX;\r\n const drawH = b.maxY - b.minY;\r\n const refDim = Math.max(drawW, drawH, 1);\r\n\r\n const sizes: RenderSizes = {\r\n refDim,\r\n wallStroke: refDim * 0.0028,\r\n thin: refDim * 0.0016,\r\n roomFont: refDim * 0.03,\r\n areaFont: refDim * 0.022,\r\n dimFont: refDim * 0.02,\r\n furnFont: refDim * 0.017,\r\n margin: refDim * 0.17,\r\n hatchGap: refDim * 0.013,\r\n };\r\n const { thin, margin, hatchGap } = sizes;\r\n\r\n const vbX = b.minX - margin;\r\n const vbY = b.minY - margin;\r\n const vbW = drawW + margin * 2;\r\n const vbH = drawH + margin * 2;\r\n\r\n const out: string[] = [];\r\n const svgAttrs = opts.width\r\n ? `width=\"${fmt(opts.width)}\" height=\"${fmt((opts.width * vbH) / vbW)}\"`\r\n : \"\";\r\n out.push(\r\n `<svg xmlns=\"http://www.w3.org/2000/svg\" ${svgAttrs} viewBox=\"${fmt(vbX)} ${fmt(vbY)} ${fmt(vbW)} ${fmt(vbH)}\" font-family=\"Helvetica, Arial, sans-serif\">`,\r\n );\r\n\r\n // Defs: poché hatch pattern\r\n out.push(\r\n `<defs><pattern id=\"poche\" patternUnits=\"userSpaceOnUse\" width=\"${fmt(hatchGap)}\" height=\"${fmt(hatchGap)}\" patternTransform=\"rotate(45)\">` +\r\n `<rect width=\"${fmt(hatchGap)}\" height=\"${fmt(hatchGap)}\" fill=\"${THEME.pocheBase}\"/>` +\r\n `<line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"${fmt(hatchGap)}\" stroke=\"${THEME.pocheHatch}\" stroke-width=\"${fmt(thin * 0.7)}\"/>` +\r\n `</pattern></defs>`,\r\n );\r\n\r\n // Background\r\n out.push(`<rect x=\"${fmt(vbX)}\" y=\"${fmt(vbY)}\" width=\"${fmt(vbW)}\" height=\"${fmt(vbH)}\" fill=\"${THEME.bg}\"/>`);\r\n\r\n // Elements: collect ops once (preserving source order), then emit pass by pass.\r\n const ctx: RenderCtx = { fmt, pt, xml, theme: THEME, sizes, bounds: b };\r\n const ops = ir.elements.flatMap((el) => {\r\n const def = registry.get(el.kind);\r\n return def ? def.render(el, ctx) : [];\r\n });\r\n for (const pass of RENDER_PASSES) {\r\n for (const op of ops) if (op.pass === pass) out.push(op.svg);\r\n }\r\n\r\n // Plan-level annotations (after element passes): north, scale bar, title block.\r\n out.push(northArrow(ir, b, margin, refDim));\r\n out.push(scaleBar(b, margin, refDim, thin));\r\n const tb = titleBlock(ir, b, margin, refDim, thin);\r\n if (tb) out.push(tb);\r\n\r\n out.push(\"</svg>\");\r\n return out.join(\"\\n\");\r\n}\r\n\r\nfunction northArrow(ir: ResolvedPlan, b: Bounds, margin: number, refDim: number): string {\r\n const r = refDim * 0.045;\r\n const cx = b.maxX - r;\r\n const cy = b.minY - margin * 0.55;\r\n let deg: number;\r\n switch (ir.north) {\r\n case \"up\": deg = 0; break;\r\n case \"down\": deg = 180; break;\r\n case \"left\": deg = 270; break;\r\n case \"right\": deg = 90; break;\r\n default: deg = typeof ir.north === \"object\" ? ir.north.deg : 0;\r\n }\r\n const fs = refDim * 0.026;\r\n // Triangle points \"up\" before rotation; only the arrow rotates — the \"N\"\r\n // label stays upright at the pointing end so it always reads correctly.\r\n const tri = `${fmt(cx)},${fmt(cy - r)} ${fmt(cx - r * 0.5)},${fmt(cy + r * 0.6)} ${fmt(cx)},${fmt(cy + r * 0.25)} ${fmt(cx + r * 0.5)},${fmt(cy + r * 0.6)}`;\r\n const rad = (deg * Math.PI) / 180;\r\n // North screen vector (rotate the \"up\" vector (0,-1) clockwise by deg).\r\n const nx = Math.sin(rad);\r\n const ny = -Math.cos(rad);\r\n const lx = cx + nx * (r + fs * 0.8);\r\n const ly = cy + ny * (r + fs * 0.8);\r\n return (\r\n `<g>` +\r\n `<polygon points=\"${tri}\" fill=\"${THEME.annotation}\" transform=\"rotate(${fmt(deg)} ${fmt(cx)} ${fmt(cy)})\"/>` +\r\n `<text x=\"${fmt(lx)}\" y=\"${fmt(ly)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"middle\" dominant-baseline=\"central\">N</text>` +\r\n `</g>`\r\n );\r\n}\r\n\r\nfunction scaleBar(b: Bounds, margin: number, refDim: number, thin: number): string {\r\n const barLen = niceBarLength(refDim * 0.3);\r\n const x0 = b.minX;\r\n const y0 = b.maxY + margin * 0.55;\r\n const hgt = refDim * 0.014;\r\n const fs = refDim * 0.02;\r\n const parts: string[] = [];\r\n const half = barLen / 2;\r\n // two-segment alternating bar\r\n parts.push(`<rect x=\"${fmt(x0)}\" y=\"${fmt(y0)}\" width=\"${fmt(half)}\" height=\"${fmt(hgt)}\" fill=\"${THEME.annotation}\"/>`);\r\n parts.push(\r\n `<rect x=\"${fmt(x0 + half)}\" y=\"${fmt(y0)}\" width=\"${fmt(half)}\" height=\"${fmt(hgt)}\" fill=\"none\" stroke=\"${THEME.annotation}\" stroke-width=\"${fmt(thin)}\"/>`,\r\n );\r\n parts.push(\r\n `<text x=\"${fmt(x0)}\" y=\"${fmt(y0 + hgt + fs)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"start\" dominant-baseline=\"central\">0</text>`,\r\n );\r\n parts.push(\r\n `<text x=\"${fmt(x0 + barLen)}\" y=\"${fmt(y0 + hgt + fs)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"middle\" dominant-baseline=\"central\">${barLen / 1000} m</text>`,\r\n );\r\n return `<g>${parts.join(\"\")}</g>`;\r\n}\r\n\r\nfunction titleBlock(ir: ResolvedPlan, b: Bounds, margin: number, refDim: number, thin: number): string | null {\r\n const t = ir.title;\r\n if (!t && !ir.scale) return null;\r\n const boxW = refDim * 0.34;\r\n const boxH = margin * 0.82;\r\n const x0 = b.maxX - boxW;\r\n const y0 = b.maxY + margin * 0.15;\r\n const fs = refDim * 0.019;\r\n const pad = boxW * 0.05;\r\n const lines: { k: string; v: string }[] = [];\r\n if (t?.project) lines.push({ k: \"PROJECT\", v: t.project });\r\n if (t?.drawnBy) lines.push({ k: \"DRAWN BY\", v: t.drawnBy });\r\n if (t?.date) lines.push({ k: \"DATE\", v: t.date });\r\n if (ir.scale) lines.push({ k: \"SCALE\", v: ir.scale });\r\n\r\n const parts: string[] = [];\r\n parts.push(\r\n `<rect x=\"${fmt(x0)}\" y=\"${fmt(y0)}\" width=\"${fmt(boxW)}\" height=\"${fmt(boxH)}\" fill=\"none\" stroke=\"${THEME.annotation}\" stroke-width=\"${fmt(thin)}\"/>`,\r\n );\r\n const rowH = boxH / Math.max(lines.length, 1);\r\n lines.forEach((ln, i) => {\r\n const ly = y0 + rowH * (i + 0.5);\r\n parts.push(\r\n `<text x=\"${fmt(x0 + pad)}\" y=\"${fmt(ly)}\" font-size=\"${fmt(fs * 0.8)}\" fill=\"${THEME.annotationMuted}\" dominant-baseline=\"central\">${xml(ln.k)}</text>`,\r\n );\r\n parts.push(\r\n `<text x=\"${fmt(x0 + boxW - pad)}\" y=\"${fmt(ly)}\" font-size=\"${fmt(fs)}\" fill=\"${THEME.annotation}\" text-anchor=\"end\" dominant-baseline=\"central\">${xml(ln.v)}</text>`,\r\n );\r\n if (i > 0)\r\n parts.push(\r\n `<line x1=\"${fmt(x0)}\" y1=\"${fmt(y0 + rowH * i)}\" x2=\"${fmt(x0 + boxW)}\" y2=\"${fmt(y0 + rowH * i)}\" stroke=\"${THEME.annotation}\" stroke-width=\"${fmt(thin * 0.5)}\"/>`,\r\n );\r\n });\r\n return `<g>${parts.join(\"\")}</g>`;\r\n}\r\n","/**\r\n * Diagnostics for the ArchLang compiler.\r\n *\r\n * A {@link Diagnostic} is the single, span-carrying problem record produced by\r\n * every compiler stage (lex/parse/validate). The legacy `{message, line, col}`\r\n * `errors`/`warnings` arrays on {@link import(\"./types.js\").CompileResult} are\r\n * *derived* from these. {@link formatDiagnostic} renders a codespan-style,\r\n * caret-framed snippet — zero dependencies, pure, isomorphic.\r\n */\r\n\r\n/** A half-open byte range `[start, end)` into the source string. */\r\nexport interface Span {\r\n start: number;\r\n end: number;\r\n}\r\n\r\nexport type Severity = \"error\" | \"warning\";\r\n\r\nexport interface Diagnostic {\r\n severity: Severity;\r\n message: string;\r\n /** Source location; absent for whole-program problems (e.g. an empty plan). */\r\n span?: Span;\r\n /** Stable machine code, e.g. `\"E_ROOM_SIZE\"`. */\r\n code?: string;\r\n /** Optional follow-up suggestions, each rendered as a `= help:` line. */\r\n hints?: string[];\r\n}\r\n\r\n/** Convert a byte offset into a 1-based `{line, col}`. Offsets are clamped. */\r\nexport function offsetToLineCol(source: string, offset: number): { line: number; col: number } {\r\n const o = Math.max(0, Math.min(offset, source.length));\r\n let line = 1;\r\n let col = 1;\r\n for (let k = 0; k < o; k++) {\r\n if (source[k] === \"\\n\") {\r\n line++;\r\n col = 1;\r\n } else {\r\n col++;\r\n }\r\n }\r\n return { line, col };\r\n}\r\n\r\n/** Byte offset of the start of the line containing `offset`. */\r\nfunction lineStart(source: string, offset: number): number {\r\n let k = Math.max(0, Math.min(offset, source.length));\r\n while (k > 0 && source[k - 1] !== \"\\n\") k--;\r\n return k;\r\n}\r\n\r\n/** Byte offset just past the end of the line containing `offset` (excludes `\\n`). */\r\nfunction lineEnd(source: string, offset: number): number {\r\n let k = Math.max(0, Math.min(offset, source.length));\r\n while (k < source.length && source[k] !== \"\\n\") k++;\r\n return k;\r\n}\r\n\r\n/**\r\n * Render a diagnostic as a framed source snippet:\r\n *\r\n * ```text\r\n * error[E_ROOM_SIZE]: room \"bed\" must have a positive size\r\n * --> 4:30\r\n * |\r\n * 4 | room id=bed at (0,0) size 0x4000\r\n * | ^^^^^^ width is 0\r\n * = help: did you mean 3000x4000?\r\n * ```\r\n *\r\n * With no `span`, only the header line is produced.\r\n */\r\nexport function formatDiagnostic(source: string, d: Diagnostic): string {\r\n const codeTag = d.code ? `[${d.code}]` : \"\";\r\n const header = `${d.severity}${codeTag}: ${d.message}`;\r\n const lines: string[] = [header];\r\n\r\n if (d.span) {\r\n const { line, col } = offsetToLineCol(source, d.span.start);\r\n const ls = lineStart(source, d.span.start);\r\n const le = lineEnd(source, d.span.start);\r\n const srcLine = source.slice(ls, le);\r\n // Underline within this one line; multi-line spans underline to line end.\r\n const caretStart = d.span.start - ls;\r\n const caretEnd = Math.min(d.span.end, le) - ls;\r\n const caretLen = Math.max(1, caretEnd - caretStart);\r\n\r\n const gutter = String(line);\r\n const pad = \" \".repeat(gutter.length);\r\n lines.push(`${pad} --> ${line}:${col}`);\r\n lines.push(`${pad} |`);\r\n lines.push(`${gutter} | ${srcLine}`);\r\n lines.push(`${pad} | ${\" \".repeat(caretStart)}${\"^\".repeat(caretLen)}`);\r\n for (const hint of d.hints ?? []) {\r\n lines.push(`${pad} = help: ${hint}`);\r\n }\r\n } else {\r\n for (const hint of d.hints ?? []) {\r\n lines.push(` = help: ${hint}`);\r\n }\r\n }\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n","/**\r\n * ArchLang — compile declarative floor-plan source to a professional SVG.\r\n *\r\n * @example\r\n * import { compile } from \"@chanmeng666/archlang\";\r\n * const { svg, errors } = compile(`plan \"Demo\" { room at (0,0) size 4000x3000 label \"Room\" }`);\r\n */\r\n\r\nimport { parse } from \"./parser.js\";\r\nimport { resolve } from \"./ir.js\";\r\nimport { render } from \"./render.js\";\r\nimport { offsetToLineCol } from \"./diagnostics.js\";\r\nimport type { Diagnostic } from \"./diagnostics.js\";\r\nimport type { CompileError, CompileOptions, CompileResult } from \"./types.js\";\r\n\r\nexport type {\r\n CompileError,\r\n CompileOptions,\r\n CompileResult,\r\n CompileWarning,\r\n Diagnostic,\r\n Span,\r\n Severity,\r\n} from \"./types.js\";\r\nexport { formatDiagnostic, offsetToLineCol } from \"./diagnostics.js\";\r\nexport type * from \"./ast.js\";\r\n\r\n/** Small LRU-ish memo cache keyed by source+options. Bounded to 64 entries. */\r\nconst cache = new Map<string, CompileResult>();\r\nconst CACHE_MAX = 64;\r\n\r\nexport function compile(source: string, opts: CompileOptions = {}): CompileResult {\r\n const key = JSON.stringify([source, opts.width ?? null]);\r\n if (!opts.noCache) {\r\n const hit = cache.get(key);\r\n if (hit) return hit;\r\n }\r\n\r\n const result = compileUncached(source, opts);\r\n\r\n if (!opts.noCache) {\r\n if (cache.size >= CACHE_MAX) {\r\n const oldest = cache.keys().next().value;\r\n if (oldest !== undefined) cache.delete(oldest);\r\n }\r\n cache.set(key, result);\r\n }\r\n return result;\r\n}\r\n\r\n/** Project a span-carrying diagnostic onto the legacy `{message, line, col}` shape. */\r\nfunction toLegacy(source: string, d: Diagnostic): CompileError {\r\n if (!d.span) return { message: d.message };\r\n const { line, col } = offsetToLineCol(source, d.span.start);\r\n return { message: d.message, line, col };\r\n}\r\n\r\nfunction compileUncached(source: string, opts: CompileOptions): CompileResult {\r\n const { plan, diagnostics: parseDiags } = parse(source);\r\n\r\n // parse → resolve (AST→IR, the single place semantics live) → render.\r\n const resolved = plan ? resolve(plan) : null;\r\n const diagnostics: Diagnostic[] = resolved\r\n ? [...parseDiags, ...resolved.diagnostics]\r\n : [...parseDiags];\r\n\r\n const errs = diagnostics.filter((d) => d.severity === \"error\");\r\n const errors = errs.map((d) => toLegacy(source, d));\r\n const warnings = diagnostics\r\n .filter((d) => d.severity === \"warning\")\r\n .map((d) => toLegacy(source, d));\r\n\r\n // Warnings never block rendering; any error (or no plan) aborts with svg = \"\".\r\n const svg = resolved && errs.length === 0 ? render(resolved.ir, opts) : \"\";\r\n\r\n return { svg, errors, warnings, diagnostics, ast: plan };\r\n}\r\n\r\n/** Clear the internal compile cache (useful in long-lived processes/tests). */\r\nexport function clearCache(): void {\r\n cache.clear();\r\n}\r\n"],"mappings":"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","names":["fmt","pt","dim","fmt","pt","xml","fmt","pt","fmt","pt","dim","fmt","pt","xml","fmt","xml","dim","fmt","pt","describe"]}
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -44,7 +44,11 @@ declare function offsetToLineCol(source: string, offset: number): {
|
|
|
44
44
|
*/
|
|
45
45
|
declare function formatDiagnostic(source: string, d: Diagnostic): string;
|
|
46
46
|
|
|
47
|
-
/** Abstract syntax tree for an ArchLang `plan`. All distances are in millimetres.
|
|
47
|
+
/** Abstract syntax tree for an ArchLang `plan`. All distances are in millimetres.
|
|
48
|
+
*
|
|
49
|
+
* The AST is the raw, immutable output of parsing: `resolve()` (see ir.ts) reads
|
|
50
|
+
* it and produces a separate IR — nothing here is mutated after parse.
|
|
51
|
+
*/
|
|
48
52
|
|
|
49
53
|
interface Point {
|
|
50
54
|
x: number;
|
|
@@ -54,102 +58,99 @@ interface Point {
|
|
|
54
58
|
type NorthDir = "up" | "down" | "left" | "right" | {
|
|
55
59
|
deg: number;
|
|
56
60
|
};
|
|
57
|
-
|
|
61
|
+
/** Discriminant identifying an element's type (also its registry keyword). */
|
|
62
|
+
type ElementKind = "wall" | "room" | "door" | "window" | "furniture" | "dim" | "column";
|
|
63
|
+
/** Fields every element AST node carries. */
|
|
64
|
+
interface NodeBase {
|
|
58
65
|
id: string;
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
line: number;
|
|
67
|
+
/** Byte-offset span from the leading keyword to the last consumed token. */
|
|
68
|
+
span?: Span;
|
|
69
|
+
}
|
|
70
|
+
interface WallNode extends NodeBase {
|
|
71
|
+
kind: "wall";
|
|
72
|
+
/** Free-form category, e.g. "exterior" or "partition". Also a door/window ref. */
|
|
73
|
+
category: string;
|
|
61
74
|
/** Wall thickness in mm. */
|
|
62
75
|
thickness: number;
|
|
63
76
|
/** Polyline vertices in order. */
|
|
64
77
|
points: Point[];
|
|
65
78
|
/** Whether the polyline closes back to its first vertex. */
|
|
66
79
|
closed: boolean;
|
|
67
|
-
line: number;
|
|
68
|
-
/** Byte-offset span from the leading keyword to the last consumed token. */
|
|
69
|
-
span?: Span;
|
|
70
80
|
}
|
|
71
|
-
interface RoomNode {
|
|
72
|
-
|
|
81
|
+
interface RoomNode extends NodeBase {
|
|
82
|
+
kind: "room";
|
|
73
83
|
at: Point;
|
|
74
84
|
size: {
|
|
75
85
|
w: number;
|
|
76
86
|
h: number;
|
|
77
87
|
};
|
|
78
88
|
label?: string;
|
|
79
|
-
line: number;
|
|
80
|
-
/** Byte-offset span from the leading keyword to the last consumed token. */
|
|
81
|
-
span?: Span;
|
|
82
89
|
}
|
|
83
|
-
interface DoorNode {
|
|
84
|
-
|
|
90
|
+
interface DoorNode extends NodeBase {
|
|
91
|
+
kind: "door";
|
|
85
92
|
at: Point;
|
|
86
93
|
width: number;
|
|
87
|
-
/** Optional wall (id or
|
|
94
|
+
/** Optional wall (id or category) the door is hosted by. */
|
|
88
95
|
wall?: string;
|
|
89
96
|
hinge: "left" | "right";
|
|
90
97
|
swing: "in" | "out";
|
|
91
|
-
line: number;
|
|
92
|
-
/** Byte-offset span from the leading keyword to the last consumed token. */
|
|
93
|
-
span?: Span;
|
|
94
98
|
}
|
|
95
|
-
interface WindowNode {
|
|
96
|
-
|
|
99
|
+
interface WindowNode extends NodeBase {
|
|
100
|
+
kind: "window";
|
|
97
101
|
at: Point;
|
|
98
102
|
width: number;
|
|
99
103
|
wall?: string;
|
|
100
|
-
line: number;
|
|
101
|
-
/** Byte-offset span from the leading keyword to the last consumed token. */
|
|
102
|
-
span?: Span;
|
|
103
104
|
}
|
|
104
|
-
interface FurnitureNode {
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
interface FurnitureNode extends NodeBase {
|
|
106
|
+
kind: "furniture";
|
|
107
|
+
/** Free-form category, e.g. "bed" or "sofa". */
|
|
108
|
+
category: string;
|
|
107
109
|
at: Point;
|
|
108
110
|
size: {
|
|
109
111
|
w: number;
|
|
110
112
|
h: number;
|
|
111
113
|
};
|
|
112
114
|
label?: string;
|
|
113
|
-
line: number;
|
|
114
|
-
/** Byte-offset span from the leading keyword to the last consumed token. */
|
|
115
|
-
span?: Span;
|
|
116
115
|
}
|
|
117
|
-
interface DimNode {
|
|
118
|
-
|
|
116
|
+
interface DimNode extends NodeBase {
|
|
117
|
+
kind: "dim";
|
|
119
118
|
from: Point;
|
|
120
119
|
to: Point;
|
|
121
120
|
/** Perpendicular offset of the dimension line from the measured segment, mm. */
|
|
122
121
|
offset: number;
|
|
123
122
|
/** Override text; defaults to the measured length. */
|
|
124
123
|
text?: string;
|
|
125
|
-
line: number;
|
|
126
|
-
/** Byte-offset span from the leading keyword to the last consumed token. */
|
|
127
|
-
span?: Span;
|
|
128
124
|
}
|
|
125
|
+
interface ColumnNode extends NodeBase {
|
|
126
|
+
kind: "column";
|
|
127
|
+
at: Point;
|
|
128
|
+
size: {
|
|
129
|
+
w: number;
|
|
130
|
+
h: number;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/** Discriminated union of all element AST nodes (registry-dispatchable). */
|
|
134
|
+
type AstElement = WallNode | RoomNode | DoorNode | WindowNode | FurnitureNode | DimNode | ColumnNode;
|
|
129
135
|
interface TitleNode {
|
|
130
136
|
project?: string;
|
|
131
137
|
drawnBy?: string;
|
|
132
138
|
date?: string;
|
|
133
139
|
line: number;
|
|
134
|
-
/** Byte-offset span from the leading keyword to the last consumed token. */
|
|
135
140
|
span?: Span;
|
|
136
141
|
}
|
|
137
142
|
interface PlanNode {
|
|
138
143
|
name: string;
|
|
139
|
-
/** Only "mm" is supported
|
|
144
|
+
/** Only "mm" is supported. */
|
|
140
145
|
units: "mm";
|
|
141
146
|
/** Snap module in mm; 0 disables snapping. */
|
|
142
147
|
grid: number;
|
|
143
148
|
/** e.g. "1:50". */
|
|
144
149
|
scale?: string;
|
|
145
150
|
north: NorthDir;
|
|
146
|
-
walls: WallNode[];
|
|
147
|
-
rooms: RoomNode[];
|
|
148
|
-
doors: DoorNode[];
|
|
149
|
-
windows: WindowNode[];
|
|
150
|
-
furniture: FurnitureNode[];
|
|
151
|
-
dims: DimNode[];
|
|
152
151
|
title?: TitleNode;
|
|
152
|
+
/** All elements, in source order. */
|
|
153
|
+
elements: AstElement[];
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
interface CompileError {
|
|
@@ -198,4 +199,4 @@ declare function compile(source: string, opts?: CompileOptions): CompileResult;
|
|
|
198
199
|
/** Clear the internal compile cache (useful in long-lived processes/tests). */
|
|
199
200
|
declare function clearCache(): void;
|
|
200
201
|
|
|
201
|
-
export { type CompileError, type CompileOptions, type CompileResult, type CompileWarning, type Diagnostic, type DimNode, type DoorNode, type FurnitureNode, type NorthDir, type PlanNode, type Point, type RoomNode, type Severity, type Span, type TitleNode, type WallNode, type WindowNode, clearCache, compile, formatDiagnostic, offsetToLineCol };
|
|
202
|
+
export { type AstElement, type ColumnNode, type CompileError, type CompileOptions, type CompileResult, type CompileWarning, type Diagnostic, type DimNode, type DoorNode, type ElementKind, type FurnitureNode, type NodeBase, type NorthDir, type PlanNode, type Point, type RoomNode, type Severity, type Span, type TitleNode, type WallNode, type WindowNode, clearCache, compile, formatDiagnostic, offsetToLineCol };
|
package/dist/index.js
CHANGED
package/package.json
CHANGED