planscript 0.1.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.
Files changed (55) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +277 -0
  3. package/dist/ast/types.d.ts +195 -0
  4. package/dist/ast/types.d.ts.map +1 -0
  5. package/dist/ast/types.js +5 -0
  6. package/dist/ast/types.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +100 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/compiler.d.ts +30 -0
  12. package/dist/compiler.d.ts.map +1 -0
  13. package/dist/compiler.js +80 -0
  14. package/dist/compiler.js.map +1 -0
  15. package/dist/exporters/json.d.ts +13 -0
  16. package/dist/exporters/json.d.ts.map +1 -0
  17. package/dist/exporters/json.js +17 -0
  18. package/dist/exporters/json.js.map +1 -0
  19. package/dist/exporters/svg.d.ts +27 -0
  20. package/dist/exporters/svg.d.ts.map +1 -0
  21. package/dist/exporters/svg.js +684 -0
  22. package/dist/exporters/svg.js.map +1 -0
  23. package/dist/geometry/index.d.ts +13 -0
  24. package/dist/geometry/index.d.ts.map +1 -0
  25. package/dist/geometry/index.js +333 -0
  26. package/dist/geometry/index.js.map +1 -0
  27. package/dist/geometry/types.d.ts +34 -0
  28. package/dist/geometry/types.d.ts.map +1 -0
  29. package/dist/geometry/types.js +2 -0
  30. package/dist/geometry/types.js.map +1 -0
  31. package/dist/index.d.ts +10 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +20 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/lowering/index.d.ts +25 -0
  36. package/dist/lowering/index.d.ts.map +1 -0
  37. package/dist/lowering/index.js +217 -0
  38. package/dist/lowering/index.js.map +1 -0
  39. package/dist/parser/grammar.d.ts +168 -0
  40. package/dist/parser/grammar.d.ts.map +1 -0
  41. package/dist/parser/grammar.js +7341 -0
  42. package/dist/parser/grammar.js.map +1 -0
  43. package/dist/parser/index.d.ts +27 -0
  44. package/dist/parser/index.d.ts.map +1 -0
  45. package/dist/parser/index.js +26 -0
  46. package/dist/parser/index.js.map +1 -0
  47. package/dist/validation/index.d.ts +22 -0
  48. package/dist/validation/index.d.ts.map +1 -0
  49. package/dist/validation/index.js +243 -0
  50. package/dist/validation/index.js.map +1 -0
  51. package/examples/house-with-dimensions.svg +106 -0
  52. package/examples/house.json +478 -0
  53. package/examples/house.psc +86 -0
  54. package/examples/house.svg +57 -0
  55. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2026 José F. Romaniello <jfromaniello@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,277 @@
1
+ # PlanScript
2
+
3
+ A DSL for defining floor plans. Compile `.psc` files to SVG or JSON.
4
+
5
+ ## Example
6
+
7
+ ```planscript
8
+ units m
9
+ defaults {
10
+ door_width 0.9
11
+ window_width 2.4
12
+ }
13
+
14
+ plan "Example House" {
15
+ footprint rect (0,0) (20,30)
16
+
17
+ room living {
18
+ rect (1,1) (9,7)
19
+ label "Living Room"
20
+ }
21
+
22
+ room kitchen {
23
+ rect size (4,6)
24
+ attach east_of living
25
+ align top
26
+ gap 0
27
+ label "Kitchen"
28
+ }
29
+
30
+ room hall {
31
+ rect span x from living.left to kitchen.right y (7, 9)
32
+ label "Hallway"
33
+ }
34
+
35
+ room bedroom {
36
+ rect at (1,9) size (3.6,4.0)
37
+ label "Master Bedroom"
38
+ }
39
+
40
+ room bath {
41
+ rect size (2.6,2.2)
42
+ attach east_of bedroom
43
+ align top
44
+ label "Bathroom"
45
+ }
46
+
47
+ opening door d1 { between living and hall on shared_edge at 60% }
48
+ opening door d2 { between living and kitchen on shared_edge at 50% }
49
+ opening door d3 { between hall and bedroom on shared_edge at 50% }
50
+ opening window w1 { on living.edge south at 2.0 }
51
+ }
52
+ ```
53
+
54
+ **Output:**
55
+
56
+ <p align="center">
57
+ <img src="examples/house.svg" alt="Floor plan without dimensions" width="45%">
58
+ <img src="examples/house-with-dimensions.svg" alt="Floor plan with dimensions" width="45%">
59
+ </p>
60
+
61
+ <p align="center">
62
+ <em>Without dimensions</em> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>With <code>--dimensions</code> flag</em>
63
+ </p>
64
+
65
+ ## Installation
66
+
67
+ ```bash
68
+ npm install planscript
69
+ ```
70
+
71
+ ## CLI Usage
72
+
73
+ ```bash
74
+ # Compile to SVG
75
+ planscript house.psc --svg house.svg
76
+
77
+ # Compile to SVG with dimension lines
78
+ planscript house.psc --svg house.svg --dimensions
79
+
80
+ # Compile to JSON
81
+ planscript house.psc --json house.json
82
+
83
+ # Both outputs
84
+ planscript house.psc --svg house.svg --json house.json
85
+ ```
86
+
87
+ ## Library Usage
88
+
89
+ ### Simple Compilation
90
+
91
+ ```typescript
92
+ import { compile } from 'planscript';
93
+
94
+ const source = `
95
+ units m
96
+ defaults {
97
+ door_width 0.9
98
+ }
99
+ plan "My House" {
100
+ footprint rect (0,0) (15,12)
101
+
102
+ room living {
103
+ rect (1,1) (8,6)
104
+ label "Living Room"
105
+ }
106
+
107
+ room kitchen {
108
+ rect (8,1) (14,6)
109
+ label "Kitchen"
110
+ }
111
+
112
+ opening door d1 {
113
+ between living and kitchen
114
+ on shared_edge
115
+ at 50%
116
+ }
117
+ }
118
+ `;
119
+
120
+ const result = compile(source);
121
+
122
+ if (result.success) {
123
+ console.log(result.svg); // SVG string
124
+ console.log(result.geometry); // Geometry IR
125
+ } else {
126
+ console.error(result.errors);
127
+ }
128
+ ```
129
+
130
+ ### Step-by-Step Pipeline
131
+
132
+ ```typescript
133
+ import {
134
+ parse,
135
+ lower,
136
+ generateGeometry,
137
+ validate,
138
+ exportSVG,
139
+ exportJSON
140
+ } from 'planscript';
141
+
142
+ // 1. Parse source to AST
143
+ const ast = parse(source);
144
+
145
+ // 2. Lower to resolved geometry
146
+ const lowered = lower(ast);
147
+
148
+ // 3. Generate geometry IR (walls, openings)
149
+ const geometry = generateGeometry(lowered);
150
+
151
+ // 4. Validate assertions
152
+ const errors = validate(lowered, geometry);
153
+ if (errors.length > 0) {
154
+ throw new Error(errors[0].message);
155
+ }
156
+
157
+ // 5. Export
158
+ const svg = exportSVG(geometry, { width: 800, height: 600 });
159
+ const json = exportJSON(geometry, { pretty: true }, ast);
160
+ ```
161
+
162
+ ### Export Options
163
+
164
+ ```typescript
165
+ // SVG options
166
+ const svg = exportSVG(geometry, {
167
+ width: 1000, // Canvas width (default: 1000)
168
+ height: 800, // Canvas height (default: 800)
169
+ padding: 50, // Padding around floor plan (default: 50)
170
+ showDimensions: true, // Show dimension lines (default: false)
171
+ showLabels: true, // Show room labels (default: true)
172
+ wallColor: '#2c3e50',
173
+ roomFillColor: '#ecf0f1',
174
+ doorColor: '#e74c3c',
175
+ windowColor: '#3498db',
176
+ });
177
+
178
+ // JSON options
179
+ const json = exportJSON(geometry, {
180
+ pretty: true // Pretty-print JSON (default: false)
181
+ }, ast);
182
+ ```
183
+
184
+ ## Language Syntax
185
+
186
+ ### Basic Structure
187
+
188
+ ```planscript
189
+ units m # meters, cm, mm, ft, in
190
+ origin (0,0) # optional origin point
191
+ defaults {
192
+ door_width 0.9 # default door width
193
+ window_width 1.2 # default window width
194
+ }
195
+
196
+ plan "House Name" {
197
+ footprint rect (0,0) (20,15)
198
+
199
+ # rooms...
200
+ # openings...
201
+ # assertions...
202
+ }
203
+ ```
204
+
205
+ ### Room Definitions
206
+
207
+ ```planscript
208
+ # Rectangle with two corners
209
+ room living {
210
+ rect (0,0) (8,6)
211
+ label "Living Room"
212
+ }
213
+
214
+ # Rectangle with position and size
215
+ room bedroom {
216
+ rect at (0,6) size (4,4)
217
+ }
218
+
219
+ # Relative placement
220
+ room kitchen {
221
+ rect size (4,6)
222
+ attach east_of living
223
+ align top
224
+ gap 0
225
+ }
226
+
227
+ # Span syntax (reference other rooms)
228
+ room hallway {
229
+ rect span x from living.left to kitchen.right y (6, 8)
230
+ }
231
+ ```
232
+
233
+ ### Openings
234
+
235
+ ```planscript
236
+ # Door between rooms
237
+ opening door d1 {
238
+ between living and kitchen
239
+ on shared_edge
240
+ at 50% # 50% along wall (centered)
241
+ width 0.9 # optional if defaults set
242
+ }
243
+
244
+ # Window on room edge
245
+ opening window w1 {
246
+ on living.edge south
247
+ at 2.0 # 2 meters from wall start
248
+ width 1.5
249
+ sill 0.9 # sill height
250
+ }
251
+ ```
252
+
253
+ ### Position Syntax
254
+
255
+ - `at 50%` - percentage along wall (0-100)
256
+ - `at 2.0` - absolute distance in meters from wall start
257
+
258
+ ### Assertions
259
+
260
+ ```planscript
261
+ assert no_overlap rooms # rooms don't overlap
262
+ assert inside footprint all_rooms # rooms within footprint
263
+ assert min_room_area bedroom >= 12 # minimum area check
264
+ ```
265
+
266
+ ## VS Code Extension
267
+
268
+ Install the PlanScript VS Code extension for:
269
+ - Syntax highlighting
270
+ - Go to Definition (Ctrl+Click)
271
+ - Hover information
272
+ - Document outline
273
+ - Autocomplete
274
+
275
+ ## License
276
+
277
+ MIT
@@ -0,0 +1,195 @@
1
+ export interface Point {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ export interface SourceLocation {
6
+ line: number;
7
+ column: number;
8
+ offset: number;
9
+ }
10
+ export interface SourceSpan {
11
+ start: SourceLocation;
12
+ end: SourceLocation;
13
+ }
14
+ export interface ASTNode {
15
+ type: string;
16
+ span?: SourceSpan;
17
+ }
18
+ export type UnitType = 'm' | 'meters' | 'cm' | 'mm' | 'ft' | 'in';
19
+ export interface UnitsDeclaration extends ASTNode {
20
+ type: 'UnitsDeclaration';
21
+ unit: UnitType;
22
+ }
23
+ export interface OriginDeclaration extends ASTNode {
24
+ type: 'OriginDeclaration';
25
+ point: Point;
26
+ }
27
+ export type AxisDirection = 'right' | 'left' | 'up' | 'down';
28
+ export interface AxisDeclaration extends ASTNode {
29
+ type: 'AxisDeclaration';
30
+ x: AxisDirection;
31
+ y: AxisDirection;
32
+ }
33
+ export interface GridDeclaration extends ASTNode {
34
+ type: 'GridDeclaration';
35
+ size: number;
36
+ }
37
+ export interface DefaultsDeclaration extends ASTNode {
38
+ type: 'DefaultsDeclaration';
39
+ doorWidth?: number;
40
+ windowWidth?: number;
41
+ }
42
+ export interface FootprintPolygon extends ASTNode {
43
+ type: 'FootprintPolygon';
44
+ points: Point[];
45
+ }
46
+ export interface FootprintRect extends ASTNode {
47
+ type: 'FootprintRect';
48
+ p1: Point;
49
+ p2: Point;
50
+ }
51
+ export type Footprint = FootprintPolygon | FootprintRect;
52
+ export interface RoomPolygon extends ASTNode {
53
+ type: 'RoomPolygon';
54
+ points: Point[];
55
+ }
56
+ export interface RoomRectDiagonal extends ASTNode {
57
+ type: 'RoomRectDiagonal';
58
+ p1: Point;
59
+ p2: Point;
60
+ }
61
+ export interface RoomRectAtSize extends ASTNode {
62
+ type: 'RoomRectAtSize';
63
+ at: Point;
64
+ size: Point;
65
+ }
66
+ export interface RoomRectCenterSize extends ASTNode {
67
+ type: 'RoomRectCenterSize';
68
+ center: Point;
69
+ size: Point;
70
+ }
71
+ export interface RoomRectSizeOnly extends ASTNode {
72
+ type: 'RoomRectSizeOnly';
73
+ size: Point;
74
+ }
75
+ export type RoomGeometry = RoomPolygon | RoomRectDiagonal | RoomRectAtSize | RoomRectCenterSize | RoomRectSizeOnly;
76
+ export type RelativeDirection = 'north_of' | 'south_of' | 'east_of' | 'west_of';
77
+ export type AlignmentType = 'top' | 'bottom' | 'left' | 'right' | 'center';
78
+ export interface AttachDirective extends ASTNode {
79
+ type: 'AttachDirective';
80
+ direction: RelativeDirection;
81
+ target: string;
82
+ }
83
+ export interface AlignDirective extends ASTNode {
84
+ type: 'AlignDirective';
85
+ alignment: AlignmentType;
86
+ }
87
+ export interface GapDirective extends ASTNode {
88
+ type: 'GapDirective';
89
+ distance: number;
90
+ }
91
+ export interface SpanX extends ASTNode {
92
+ type: 'SpanX';
93
+ from: EdgeReference;
94
+ to: EdgeReference;
95
+ }
96
+ export interface SpanY extends ASTNode {
97
+ type: 'SpanY';
98
+ from: number;
99
+ to: number;
100
+ }
101
+ export interface EdgeReference {
102
+ room: string;
103
+ edge: 'left' | 'right' | 'top' | 'bottom';
104
+ }
105
+ export interface RoomRectSpan extends ASTNode {
106
+ type: 'RoomRectSpan';
107
+ spanX: SpanX;
108
+ spanY: SpanY;
109
+ }
110
+ export interface RoomDefinition extends ASTNode {
111
+ type: 'RoomDefinition';
112
+ name: string;
113
+ label?: string;
114
+ geometry: RoomGeometry | RoomRectSpan;
115
+ attach?: AttachDirective;
116
+ align?: AlignDirective;
117
+ gap?: GapDirective;
118
+ }
119
+ export type OpeningType = 'door' | 'window';
120
+ export type SwingDirection = string;
121
+ export interface PositionAbsolute {
122
+ type: 'absolute';
123
+ value: number;
124
+ }
125
+ export interface PositionPercentage {
126
+ type: 'percentage';
127
+ value: number;
128
+ }
129
+ export type Position = PositionAbsolute | PositionPercentage;
130
+ export interface DoorOpening extends ASTNode {
131
+ type: 'DoorOpening';
132
+ name: string;
133
+ between: [string, string];
134
+ on: 'shared_edge';
135
+ at: Position;
136
+ width: number;
137
+ swing?: SwingDirection;
138
+ }
139
+ export type EdgeSide = 'north' | 'south' | 'east' | 'west';
140
+ export interface WindowOpening extends ASTNode {
141
+ type: 'WindowOpening';
142
+ name: string;
143
+ room: string;
144
+ edge: EdgeSide;
145
+ at: Position;
146
+ width: number;
147
+ sill?: number;
148
+ }
149
+ export type Opening = DoorOpening | WindowOpening;
150
+ export interface WallThicknessOverride extends ASTNode {
151
+ type: 'WallThicknessOverride';
152
+ room: string;
153
+ edge: EdgeSide;
154
+ thickness: number;
155
+ }
156
+ export type AssertionType = 'inside_footprint' | 'no_overlap' | 'openings_on_walls' | 'min_room_area' | 'rooms_connected';
157
+ export interface AssertionInsideFootprint extends ASTNode {
158
+ type: 'AssertionInsideFootprint';
159
+ target: 'all_rooms' | string;
160
+ }
161
+ export interface AssertionNoOverlap extends ASTNode {
162
+ type: 'AssertionNoOverlap';
163
+ target: 'rooms';
164
+ }
165
+ export interface AssertionOpeningsOnWalls extends ASTNode {
166
+ type: 'AssertionOpeningsOnWalls';
167
+ }
168
+ export interface AssertionMinRoomArea extends ASTNode {
169
+ type: 'AssertionMinRoomArea';
170
+ room: string;
171
+ minArea: number;
172
+ }
173
+ export interface AssertionRoomsConnected extends ASTNode {
174
+ type: 'AssertionRoomsConnected';
175
+ }
176
+ export type Assertion = AssertionInsideFootprint | AssertionNoOverlap | AssertionOpeningsOnWalls | AssertionMinRoomArea | AssertionRoomsConnected;
177
+ export interface PlanDefinition extends ASTNode {
178
+ type: 'PlanDefinition';
179
+ name: string;
180
+ footprint: Footprint;
181
+ rooms: RoomDefinition[];
182
+ openings: Opening[];
183
+ wallOverrides: WallThicknessOverride[];
184
+ assertions: Assertion[];
185
+ }
186
+ export interface Program extends ASTNode {
187
+ type: 'Program';
188
+ units?: UnitsDeclaration;
189
+ origin?: OriginDeclaration;
190
+ axis?: AxisDeclaration;
191
+ grid?: GridDeclaration;
192
+ defaults?: DefaultsDeclaration;
193
+ plan: PlanDefinition;
194
+ }
195
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ast/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ // ============================================================================
2
+ // Core Types
3
+ // ============================================================================
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ast/types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,aAAa;AACb,+EAA+E"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync, writeFileSync } from 'fs';
3
+ import { compile } from './compiler.js';
4
+ const args = process.argv.slice(2);
5
+ if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
6
+ console.log(`
7
+ PlanScript Compiler - A DSL for defining floor plans
8
+
9
+ Usage:
10
+ planscript <input.psc> [options]
11
+
12
+ Options:
13
+ --svg <output.svg> Write SVG output to file
14
+ --json <output.json> Write JSON output to file
15
+ --dimensions Include dimension lines in SVG
16
+ --no-labels Don't show room labels in SVG
17
+ --no-svg Don't generate SVG
18
+ --help, -h Show this help message
19
+
20
+ Examples:
21
+ planscript house.psc --svg house.svg
22
+ planscript house.psc --svg house.svg --dimensions
23
+ planscript house.psc --json house.json --no-svg
24
+ `);
25
+ process.exit(0);
26
+ }
27
+ const inputFile = args[0];
28
+ let svgOutput;
29
+ let jsonOutput;
30
+ let emitSVG = true;
31
+ let emitJSON = false;
32
+ let showDimensions = false;
33
+ let showLabels = true;
34
+ for (let i = 1; i < args.length; i++) {
35
+ const arg = args[i];
36
+ if (arg === '--svg' && args[i + 1]) {
37
+ svgOutput = args[++i];
38
+ }
39
+ else if (arg === '--json' && args[i + 1]) {
40
+ jsonOutput = args[++i];
41
+ emitJSON = true;
42
+ }
43
+ else if (arg === '--no-svg') {
44
+ emitSVG = false;
45
+ }
46
+ else if (arg === '--dimensions') {
47
+ showDimensions = true;
48
+ }
49
+ else if (arg === '--no-labels') {
50
+ showLabels = false;
51
+ }
52
+ }
53
+ try {
54
+ const source = readFileSync(inputFile, 'utf-8');
55
+ const result = compile(source, {
56
+ emitSVG,
57
+ emitJSON,
58
+ svgOptions: {
59
+ showDimensions,
60
+ showLabels,
61
+ },
62
+ jsonOptions: { pretty: true },
63
+ });
64
+ if (!result.success) {
65
+ console.error('Compilation failed:');
66
+ for (const error of result.errors) {
67
+ const location = error.location ? ` at line ${error.location.line}:${error.location.column}` : '';
68
+ const code = error.code ? ` [${error.code}]` : '';
69
+ console.error(` ${error.phase}${code}${location}: ${error.message}`);
70
+ }
71
+ process.exit(1);
72
+ }
73
+ console.log('Compilation successful!');
74
+ if (svgOutput && result.svg) {
75
+ writeFileSync(svgOutput, result.svg);
76
+ console.log(` SVG written to: ${svgOutput}`);
77
+ }
78
+ else if (result.svg) {
79
+ console.log(` SVG: ${result.svg.length} bytes generated`);
80
+ }
81
+ if (jsonOutput && result.json) {
82
+ writeFileSync(jsonOutput, result.json);
83
+ console.log(` JSON written to: ${jsonOutput}`);
84
+ }
85
+ if (result.geometry) {
86
+ console.log(` Rooms: ${result.geometry.rooms.length}`);
87
+ console.log(` Walls: ${result.geometry.walls.length}`);
88
+ console.log(` Openings: ${result.geometry.openings.length}`);
89
+ }
90
+ }
91
+ catch (e) {
92
+ if (e instanceof Error) {
93
+ console.error(`Error: ${e.message}`);
94
+ }
95
+ else {
96
+ console.error('Unknown error occurred');
97
+ }
98
+ process.exit(1);
99
+ }
100
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { SVGExportOptions } from './exporters/svg.js';
2
+ import { JSONExportOptions } from './exporters/json.js';
3
+ import type { Program } from './ast/types.js';
4
+ import type { GeometryIR } from './geometry/types.js';
5
+ export interface CompileError {
6
+ phase: 'parse' | 'lower' | 'validate';
7
+ message: string;
8
+ location?: {
9
+ line: number;
10
+ column: number;
11
+ };
12
+ code?: string;
13
+ details?: Record<string, unknown>;
14
+ }
15
+ export interface CompileResult {
16
+ success: boolean;
17
+ errors: CompileError[];
18
+ ast?: Program;
19
+ geometry?: GeometryIR;
20
+ svg?: string;
21
+ json?: string;
22
+ }
23
+ export interface CompileOptions {
24
+ emitSVG?: boolean;
25
+ emitJSON?: boolean;
26
+ svgOptions?: SVGExportOptions;
27
+ jsonOptions?: JSONExportOptions;
28
+ }
29
+ export declare function compile(source: string, options?: CompileOptions): CompileResult;
30
+ //# sourceMappingURL=compiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAc,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMtD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAMD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAMD,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CA6EnF"}