diff --git a/.gitignore b/.gitignore index 5c20209..7157292 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ parser.out.ts +new.ast.out.ts + diff --git a/ast b/ast index c99b4cc..7619893 100644 --- a/ast +++ b/ast @@ -1,20 +1,27 @@ Statement { - Enum(enum_: Enum) - Node(node: Node) + Enum(Enum) + Node(Node) } Enum(name: Name, nodes: Node[]) Node(name: Name, params: Param[]) -Param(name: Name, type_: Type) - -Type { - Name(name: Name) - Optional(type_: Type) - Multiple(type_: Type) +Param { + Named(name: Name, type_: Type) + Unnamed(Type) } -Name(value: string) +Type { + Name(Name) + Optional(Type) + Multiple(Type) +} + +Name( + string, + line: number, + col: number, +) diff --git a/ast.out.ts b/ast.out.ts index 99ab9da..fca5482 100644 --- a/ast.out.ts +++ b/ast.out.ts @@ -1,14 +1,14 @@ // Generated file by ast_generator export type EnumStatement = { kind: "Enum"; - enum_: Enum; + [0]: Enum; }; -export const EnumStatement = (enum_: Enum): EnumStatement => ({ kind: "Enum", enum_ }); +export const EnumStatement = (v0: Enum): EnumStatement => ({ kind: "Enum", [0]: v0 }); export type NodeStatement = { kind: "Node"; - node: Node; + [0]: Node; }; -export const NodeStatement = (node: Node): NodeStatement => ({ kind: "Node", node }); +export const NodeStatement = (v0: Node): NodeStatement => ({ kind: "Node", [0]: v0 }); export type Statement = EnumStatement | NodeStatement; export type Enum = { name: Name; @@ -20,29 +20,38 @@ export type Node = { params: Param[]; }; export const Node = (name: Name, params: Param[]): Node => ({ name, params }); -export type Param = { +export type NamedParam = { + kind: "Named"; name: Name; type_: Type; }; -export const Param = (name: Name, type_: Type): Param => ({ name, type_ }); +export const NamedParam = (name: Name, type_: Type): NamedParam => ({ kind: "Named", name, type_ }); +export type UnnamedParam = { + kind: "Unnamed"; + [0]: Type; +}; +export const UnnamedParam = (v0: Type): UnnamedParam => ({ kind: "Unnamed", [0]: v0 }); +export type Param = NamedParam | UnnamedParam; export type NameType = { kind: "Name"; - name: Name; + [0]: Name; }; -export const NameType = (name: Name): NameType => ({ kind: "Name", name }); +export const NameType = (v0: Name): NameType => ({ kind: "Name", [0]: v0 }); export type OptionalType = { kind: "Optional"; - type_: Type; + [0]: Type; }; -export const OptionalType = (type_: Type): OptionalType => ({ kind: "Optional", type_ }); +export const OptionalType = (v0: Type): OptionalType => ({ kind: "Optional", [0]: v0 }); export type MultipleType = { kind: "Multiple"; - type_: Type; + [0]: Type; }; -export const MultipleType = (type_: Type): MultipleType => ({ kind: "Multiple", type_ }); +export const MultipleType = (v0: Type): MultipleType => ({ kind: "Multiple", [0]: v0 }); export type Type = NameType | OptionalType | MultipleType; export type Name = { - value: string; + [0]: string; + line: number; + col: number; }; -export const Name = (value: string): Name => ({ value }); +export const Name = (v0: string, line: number, col: number): Name => ({ [0]: v0, line, col }); diff --git a/ast_generator.ts b/ast_generator.ts index c429e4b..01a65a9 100644 --- a/ast_generator.ts +++ b/ast_generator.ts @@ -4,7 +4,7 @@ import { } from "https://deno.land/x/nearley@2.19.7-deno/mod.ts"; import compiledParserGrammar from "./parser.out.ts"; -import { Enum, Name, Node, Param, Statement, Type } from "./ast.out.ts"; +import { Enum, Name, NamedParam, Node, Statement, Type } from "./ast.out.ts"; class TypescriptGenerator { private result = ""; @@ -14,10 +14,10 @@ class TypescriptGenerator { for (const statement of ast) { switch (statement.kind) { case "Enum": - this.generateEnum(statement.enum_); + this.generateEnum(statement[0]); break; case "Node": - this.generateNode(statement.node); + this.generateNode(statement[0]); break; } } @@ -49,22 +49,47 @@ class TypescriptGenerator { if (kind) { this.result += ` kind: "${kind}";\n`; } - for (const param of node.params) { - this.result += ` ${this.makeParam(param)};\n`; + for ( + const [param, index] of node.params + .map((v, i) => [v, i] as const) + ) { + switch (param.kind) { + case "Named": + this.result += ` ${this.makeNamedParam(param)};\n`; + break; + case "Unnamed": + this.result += ` [${index}]: ${ + this.makeType(param[0]) + };\n`; + } } this.result += "};\n"; - const fnParams = node.params.map((param) => this.makeParam(param)).join( - ", ", - ); + const fnParams = node.params + .map((param, index) => { + switch (param.kind) { + case "Named": + return this.makeNamedParam(param); + case "Unnamed": + return `v${index}: ${this.makeType(param[0])}`; + } + }) + .join(", "); const fields = [ ...(kind ? [`kind: "${kind}"`] : []), - ...node.params.map((param) => this.makeName(param.name)), + ...node.params.map((param, index) => { + switch (param.kind) { + case "Named": + return this.makeName(param.name); + case "Unnamed": + return `[${index}]: v${index}`; + } + }), ].join(", "); this.result += `export const ${name} = (${fnParams}): ${name} => ({ ${fields} });\n`; } - private makeParam(param: Param): string { + private makeNamedParam(param: NamedParam): string { const name = this.makeName(param.name); const type_ = this.makeType(param.type_); return `${name}: ${type_}`; @@ -73,16 +98,16 @@ class TypescriptGenerator { private makeType(type_: Type): string { switch (type_.kind) { case "Name": - return this.makeName(type_.name); + return this.makeName(type_[0]); case "Optional": - return `${this.makeType(type_.type_)} | null`; + return `${this.makeType(type_[0])} | null`; case "Multiple": - return `${this.makeType(type_.type_)}[]`; + return `${this.makeType(type_[0])}[]`; } } private makeName(name: Name): string { - return name.value; + return name[0]; } } diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..ef44ba6 --- /dev/null +++ b/deno.lock @@ -0,0 +1,9 @@ +{ + "version": "3", + "remote": { + "https://deno.land/x/moo@0.5.1-deno.2/mod.ts": "fbccad242a370172385c0545886e8051ab4c2cc86b4635798fcf490db718af4e", + "https://deno.land/x/moo@0.5.1-deno.2/moo.js": "90e55b04d273feb1ccf0bd7f20df24259715bbfbbffe0e462882c5c5caeb232b", + "https://deno.land/x/nearley@2.19.7-deno/lib/nearley.js": "4d69e17885788c78f0aa4776de6ce587a99e1562468fb826c5a5b649a59b9d43", + "https://deno.land/x/nearley@2.19.7-deno/mod.ts": "a52f8fe208afc6790bd4167e433f397c578838547bf7161eef144810c28d57db" + } +} diff --git a/parser.ne b/parser.ne index a9bb7f5..7333152 100644 --- a/parser.ne +++ b/parser.ne @@ -55,7 +55,12 @@ params -> _ (param paramTail (_ ","):? _):? {% v => v[1] ? [v[1][0], ...v[1][1]] paramTail -> ("," _ param):* {% v => v[0].map(w => w[2]) %} -param -> name _ ":" _ type {% v => ast.Param(v[0], v[4]) %} +param -> namedParam {% id %} + | unnamedParam {% id %} + +namedParam -> name _ ":" _ type {% v => ast.NamedParam(v[0], v[4]) %} + +unnamedParam -> type {% v => ast.UnnamedParam(v[0]) %} type -> optional {% id %} | multiple {% id %} @@ -65,7 +70,7 @@ optional -> type "?" {% v => ast.OptionalType(v[0]) %} multiple -> type "[" "]" {% v => ast.MultipleType(v[0]) %} -name -> %name {% v => ast.Name(v[0]) %} +name -> %name {% v => ast.Name(v[0].value, v[0].line, v[0].col) %} _ -> __:? __ -> (%whitespace|%newline|%singeLineComment|%multiLineComment):+