@naiv/swan-dsl 0.0.1

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.
@@ -0,0 +1,25 @@
1
+ import type { ParseOptions, Program } from "./types";
2
+ export type { ParseOptions, Program } from "./types";
3
+ export type { AppDecl, BinaryExpr, BinaryOperator, BooleanLiteral, ButtonStmt, ClickStmt, ComponentDecl, ConditionalStmt, Expression, FieldStmt, HandlerStmt, HeaderStmt, IdentifierExpr, InputStmt, LinkStmt, Literal, MemberExpr, NavTarget, NumberLiteral, OutcomeClause, PageDecl, Position, SemanticRuleCode, Statement, StringLiteral, SubmitStmt, TextStmt, UnaryExpr, UseStmt, } from "./types.js";
4
+ export { ParseError, SemanticError } from "./types.js";
5
+ /**
6
+ * Parse and semantically validate a SWAN DSL source string.
7
+ *
8
+ * @param source - The DSL program text
9
+ * @param options - Optional: `{ strictMode: true }` enables SR-4 orphan page check
10
+ * @returns A fully-typed `Program` AST
11
+ * @throws {ParseError} on syntax errors
12
+ * @throws {SemanticError} on semantic violations (SR-1 through SR-6)
13
+ */
14
+ export declare function parse(source: string, options?: ParseOptions): Program;
15
+ /**
16
+ * Read a SWAN DSL file from disk, then parse and semantically validate it.
17
+ *
18
+ * @param filePath - Absolute or relative path to the `.swan` / `.dsl` file
19
+ * @param options - Optional: `{ strictMode: true }` enables SR-4 orphan page check
20
+ * @returns A fully-typed `Program` AST
21
+ * @throws {ParseError} on syntax errors
22
+ * @throws {SemanticError} on semantic violations (SR-1 through SR-6)
23
+ */
24
+ export declare function parseFile(filePath: string, options?: ParseOptions): Promise<Program>;
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAErD,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACrD,YAAY,EACR,OAAO,EACP,UAAU,EACV,cAAc,EACd,cAAc,EACd,UAAU,EACV,SAAS,EACT,aAAa,EACb,eAAe,EACf,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,cAAc,EACd,SAAS,EACT,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,aAAa,EACb,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,SAAS,EACT,OAAO,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAMvD;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAIzE;AAMD;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,YAAiB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAGlB"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ // ─────────────────────────────────────────────────────────────────────────────
3
+ // SWAN DSL — Public API
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SemanticError = exports.ParseError = void 0;
7
+ exports.parse = parse;
8
+ exports.parseFile = parseFile;
9
+ const promises_1 = require("node:fs/promises");
10
+ const parser_1 = require("./parser");
11
+ const semantic_1 = require("./semantic");
12
+ var types_js_1 = require("./types.js");
13
+ Object.defineProperty(exports, "ParseError", { enumerable: true, get: function () { return types_js_1.ParseError; } });
14
+ Object.defineProperty(exports, "SemanticError", { enumerable: true, get: function () { return types_js_1.SemanticError; } });
15
+ // ---------------------------------------------------------------------------
16
+ // parse — from a DSL source string
17
+ // ---------------------------------------------------------------------------
18
+ /**
19
+ * Parse and semantically validate a SWAN DSL source string.
20
+ *
21
+ * @param source - The DSL program text
22
+ * @param options - Optional: `{ strictMode: true }` enables SR-4 orphan page check
23
+ * @returns A fully-typed `Program` AST
24
+ * @throws {ParseError} on syntax errors
25
+ * @throws {SemanticError} on semantic violations (SR-1 through SR-6)
26
+ */
27
+ function parse(source, options = {}) {
28
+ const program = (0, parser_1.parse)(source);
29
+ (0, semantic_1.checkSemantics)(program, { strictMode: options.strictMode });
30
+ return program;
31
+ }
32
+ // ---------------------------------------------------------------------------
33
+ // parseFile — from a file path
34
+ // ---------------------------------------------------------------------------
35
+ /**
36
+ * Read a SWAN DSL file from disk, then parse and semantically validate it.
37
+ *
38
+ * @param filePath - Absolute or relative path to the `.swan` / `.dsl` file
39
+ * @param options - Optional: `{ strictMode: true }` enables SR-4 orphan page check
40
+ * @returns A fully-typed `Program` AST
41
+ * @throws {ParseError} on syntax errors
42
+ * @throws {SemanticError} on semantic violations (SR-1 through SR-6)
43
+ */
44
+ async function parseFile(filePath, options = {}) {
45
+ const source = await (0, promises_1.readFile)(filePath, "utf-8");
46
+ return parse(source, options);
47
+ }
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,wBAAwB;AACxB,gFAAgF;;;AAsDhF,sBAIC;AAeD,8BAMC;AA7ED,+CAA4C;AAC5C,qCAAgD;AAChD,yCAA4C;AAmC5C,uCAAuD;AAA9C,sGAAA,UAAU,OAAA;AAAE,yGAAA,aAAa,OAAA;AAElC,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,SAAgB,KAAK,CAAC,MAAc,EAAE,UAAwB,EAAE;IAC5D,MAAM,OAAO,GAAG,IAAA,cAAW,EAAC,MAAM,CAAC,CAAC;IACpC,IAAA,yBAAc,EAAC,OAAO,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5D,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,8EAA8E;AAC9E,+BAA+B;AAC/B,8EAA8E;AAE9E;;;;;;;;GAQG;AACI,KAAK,UAAU,SAAS,CAC3B,QAAgB,EAChB,UAAwB,EAAE;IAE1B,MAAM,MAAM,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import moo from "moo";
2
+ export declare const KEYWORDS: readonly ["app", "page", "component", "entry", "use", "header", "text", "button", "link", "field", "input", "submit", "click", "on", "if", "true", "false"];
3
+ export type Keyword = (typeof KEYWORDS)[number];
4
+ export type TokenType = Keyword | "IDENT" | "STRING" | "NUMBER" | "ARROW" | "LBRACE" | "RBRACE" | "DOT" | "EQ" | "NEQ" | "LTE" | "GTE" | "LT" | "GT" | "AND" | "OR" | "BANG" | "NL" | "WS" | "COMMENT";
5
+ export declare const lexer: moo.Lexer;
6
+ //# sourceMappingURL=lexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../src/lexer.ts"],"names":[],"mappings":"AAIA,OAAO,GAAG,MAAM,KAAK,CAAC;AAItB,eAAO,MAAM,QAAQ,6JAkBX,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD,MAAM,MAAM,SAAS,GACf,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,KAAK,GACL,IAAI,GACJ,KAAK,GACL,KAAK,GACL,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,MAAM,GACN,IAAI,GACJ,IAAI,GACJ,SAAS,CAAC;AAMhB,eAAO,MAAM,KAAK,WAoChB,CAAC"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ // ─────────────────────────────────────────────────────────────────────────────
3
+ // SWAN DSL — Moo Lexer
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.lexer = exports.KEYWORDS = void 0;
10
+ const moo_1 = __importDefault(require("moo"));
11
+ // All DSL keywords — must come before the general IDENT rule so moo
12
+ // matches them by their longest-match keyword priority.
13
+ exports.KEYWORDS = [
14
+ "app",
15
+ "page",
16
+ "component",
17
+ "entry",
18
+ "use",
19
+ "header",
20
+ "text",
21
+ "button",
22
+ "link",
23
+ "field",
24
+ "input",
25
+ "submit",
26
+ "click",
27
+ "on",
28
+ "if",
29
+ "true",
30
+ "false",
31
+ ];
32
+ // Build the moo lexer rules.
33
+ // moo uses longest-match semantics and processes rules top-to-bottom
34
+ // within equal-length matches, so operators with shared prefixes must
35
+ // be listed longest-first (e.g. "<=" before "<").
36
+ exports.lexer = moo_1.default.compile({
37
+ WS: { match: /[ \t]+/, lineBreaks: false },
38
+ NL: { match: /\r?\n/, lineBreaks: true },
39
+ COMMENT: /\/\/[^\n]*/,
40
+ // Multi-char operators (longest first to avoid prefix collisions)
41
+ ARROW: "->",
42
+ EQ: "==",
43
+ NEQ: "!=",
44
+ LTE: "<=",
45
+ GTE: ">=",
46
+ AND: "&&",
47
+ OR: "||",
48
+ // Single-char operators / punctuation
49
+ LT: "<",
50
+ GT: ">",
51
+ BANG: "!",
52
+ LBRACE: "{",
53
+ RBRACE: "}",
54
+ DOT: ".",
55
+ // Literals
56
+ STRING: { match: /"[^"]*"/, value: (s) => s.slice(1, -1) },
57
+ NUMBER: {
58
+ match: /[0-9]+(?:\.[0-9]+)?/,
59
+ value: (s) => s,
60
+ },
61
+ // Keywords and identifiers — moo.keywords maps specific values
62
+ // of the IDENT rule to their keyword token type automatically.
63
+ IDENT: {
64
+ match: /[A-Za-z][A-Za-z0-9_]*/,
65
+ type: moo_1.default.keywords(Object.fromEntries(exports.KEYWORDS.map((k) => [k, k]))),
66
+ },
67
+ });
68
+ //# sourceMappingURL=lexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexer.js","sourceRoot":"","sources":["../../src/lexer.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,uBAAuB;AACvB,gFAAgF;;;;;;AAEhF,8CAAsB;AAEtB,oEAAoE;AACpE,wDAAwD;AAC3C,QAAA,QAAQ,GAAG;IACpB,KAAK;IACL,MAAM;IACN,WAAW;IACX,OAAO;IACP,KAAK;IACL,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,IAAI;IACJ,IAAI;IACJ,MAAM;IACN,OAAO;CACD,CAAC;AA0BX,6BAA6B;AAC7B,qEAAqE;AACrE,sEAAsE;AACtE,kDAAkD;AACrC,QAAA,KAAK,GAAG,aAAG,CAAC,OAAO,CAAC;IAC7B,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE;IAC1C,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE;IACxC,OAAO,EAAE,YAAY;IACrB,kEAAkE;IAClE,KAAK,EAAE,IAAI;IACX,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;IACT,EAAE,EAAE,IAAI;IACR,sCAAsC;IACtC,EAAE,EAAE,GAAG;IACP,EAAE,EAAE,GAAG;IACP,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,GAAG;IACX,GAAG,EAAE,GAAG;IACR,WAAW;IACX,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;IAC1D,MAAM,EAAE;QACJ,KAAK,EAAE,qBAAqB;QAC5B,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;KAClB;IACD,+DAA+D;IAC/D,+DAA+D;IAC/D,KAAK,EAAE;QACH,KAAK,EAAE,uBAAuB;QAC9B,IAAI,EAAE,aAAG,CAAC,QAAQ,CACd,MAAM,CAAC,WAAW,CAAC,gBAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAG7C,CACJ;KACJ;CACJ,CAAC,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { type Expression, type Program } from "./types";
2
+ export declare class Parser {
3
+ private tokens;
4
+ private pos;
5
+ constructor(input: string);
6
+ private peek;
7
+ private advance;
8
+ private isAtEnd;
9
+ private tokenPos;
10
+ private currentPos;
11
+ /**
12
+ * Expect a token of the given type (or value) and advance.
13
+ * Throws ParseError if the next token doesn't match.
14
+ */
15
+ private expect;
16
+ /**
17
+ * Consume a token only if it matches the given type/value.
18
+ */
19
+ private match;
20
+ private check;
21
+ parseProgram(): Program;
22
+ private parseAppDecl;
23
+ private parsePageDecl;
24
+ private parseComponentDecl;
25
+ private parseBlock;
26
+ private parseStatement;
27
+ private parseHeaderStmt;
28
+ private parseTextStmt;
29
+ private parseButtonStmt;
30
+ private parseLinkStmt;
31
+ private parseFieldStmt;
32
+ private parseInputStmt;
33
+ private parseUseStmt;
34
+ private parseSubmitStmt;
35
+ private parseClickStmt;
36
+ private parseHandlerStmt;
37
+ private parseOutcomeClause;
38
+ private parseConditionalStmt;
39
+ private parseNavTarget;
40
+ parseExpression(): Expression;
41
+ private parseOr;
42
+ private parseAnd;
43
+ private readonly COMPARISON_OPS;
44
+ private parseComparison;
45
+ private parseUnary;
46
+ private parsePrimary;
47
+ /**
48
+ * Expect an IDENT token (not a keyword).
49
+ * Moo assigns keyword token types to matched words, so we need to accept
50
+ * both generic IDENT tokens and keyword tokens when used as identifiers
51
+ * (e.g. outcome labels like "success", "error").
52
+ */
53
+ private expectIdent;
54
+ private expectString;
55
+ }
56
+ export declare function parse(source: string): Program;
57
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser.ts"],"names":[],"mappings":"AAMA,OAAO,EAUH,KAAK,UAAU,EAaf,KAAK,OAAO,EAOf,MAAM,SAAS,CAAC;AASjB,qBAAa,MAAM;IACf,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,GAAG,CAAK;gBAEJ,KAAK,EAAE,MAAM;IAWzB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAKlB;;;OAGG;IACH,OAAO,CAAC,MAAM;IAiBd;;OAEG;IACH,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,KAAK;IAQb,YAAY,IAAI,OAAO;IAwBvB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,cAAc;IActB,eAAe,IAAI,UAAU;IAI7B,OAAO,CAAC,OAAO;IAiBf,OAAO,CAAC,QAAQ;IAiBhB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAO5B;IAEH,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,YAAY;IAwEpB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IA+BnB,OAAO,CAAC,YAAY;CASvB;AAMD,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAG7C"}