From a0d27dafe251a0a6adeeaca4d4697f15210e3508 Mon Sep 17 00:00:00 2001 From: SimonFJ20 Date: Mon, 29 Jul 2024 02:54:28 +0200 Subject: [PATCH] add types and code blocks --- ast | 3 +++ ast.out.ts | 46 ++++++++++++++++++++++++++++++++++------------ ast_generator.ts | 14 ++++++++++++-- parser.ne | 13 +++++++++++-- 4 files changed, 60 insertions(+), 16 deletions(-) diff --git a/ast b/ast index 8293d6d..2d5a12a 100644 --- a/ast +++ b/ast @@ -1,9 +1,12 @@ Statement { + CodeBlock(CodeBlock) Enum(Enum) Node(Node) } +CodeBlock(string) + Enum(name: Name, nodes: Node[]) Node(name: Name, params: Param[]) diff --git a/ast.out.ts b/ast.out.ts index 0847334..6d79cb1 100644 --- a/ast.out.ts +++ b/ast.out.ts @@ -1,66 +1,88 @@ // Generated file by ast_generator +export type Statement_CodeBlock = { + type: "Statement", + kind: "CodeBlock", + [0]: CodeBlock, +}; +export const Statement_CodeBlock = (v0: CodeBlock): Statement_CodeBlock => ({ type: "Statement", kind: "CodeBlock", [0]: v0 }); export type Statement_Enum = { + type: "Statement", kind: "Enum", [0]: Enum, }; -export const Statement_Enum = (v0: Enum): Statement_Enum => ({ kind: "Enum", [0]: v0 }); +export const Statement_Enum = (v0: Enum): Statement_Enum => ({ type: "Statement", kind: "Enum", [0]: v0 }); export type Statement_Node = { + type: "Statement", kind: "Node", [0]: Node, }; -export const Statement_Node = (v0: Node): Statement_Node => ({ kind: "Node", [0]: v0 }); -export type Statement = Statement_Enum | Statement_Node; -export const Statement = { Enum: Statement_Enum, Node: Statement_Node } as const; +export const Statement_Node = (v0: Node): Statement_Node => ({ type: "Statement", kind: "Node", [0]: v0 }); +export type Statement = Statement_CodeBlock | Statement_Enum | Statement_Node; +export const Statement = { CodeBlock: Statement_CodeBlock, Enum: Statement_Enum, Node: Statement_Node } as const; + +export type CodeBlock = { + type: "CodeBlock"; + [0]: string; +}; +export const CodeBlock = (v0: string): CodeBlock => ({ type: "CodeBlock", [0]: v0 }); export type Enum = { + type: "Enum"; name: Name; nodes: Node[]; }; -export const Enum = (name: Name, nodes: Node[]): Enum => ({ name, nodes }); +export const Enum = (name: Name, nodes: Node[]): Enum => ({ type: "Enum", name, nodes }); export type Node = { + type: "Node"; name: Name; params: Param[]; }; -export const Node = (name: Name, params: Param[]): Node => ({ name, params }); +export const Node = (name: Name, params: Param[]): Node => ({ type: "Node", name, params }); export type Param_Named = { + type: "Param", kind: "Named", name: Name, type_: Type, }; -export const Param_Named = (name: Name, type_: Type): Param_Named => ({ kind: "Named", name, type_ }); +export const Param_Named = (name: Name, type_: Type): Param_Named => ({ type: "Param", kind: "Named", name, type_ }); export type Param_Unnamed = { + type: "Param", kind: "Unnamed", [0]: Type, }; -export const Param_Unnamed = (v0: Type): Param_Unnamed => ({ kind: "Unnamed", [0]: v0 }); +export const Param_Unnamed = (v0: Type): Param_Unnamed => ({ type: "Param", kind: "Unnamed", [0]: v0 }); export type Param = Param_Named | Param_Unnamed; export const Param = { Named: Param_Named, Unnamed: Param_Unnamed } as const; export type Type_Name = { + type: "Type", kind: "Name", [0]: Name, }; -export const Type_Name = (v0: Name): Type_Name => ({ kind: "Name", [0]: v0 }); +export const Type_Name = (v0: Name): Type_Name => ({ type: "Type", kind: "Name", [0]: v0 }); export type Type_Optional = { + type: "Type", kind: "Optional", [0]: Type, }; -export const Type_Optional = (v0: Type): Type_Optional => ({ kind: "Optional", [0]: v0 }); +export const Type_Optional = (v0: Type): Type_Optional => ({ type: "Type", kind: "Optional", [0]: v0 }); export type Type_Multiple = { + type: "Type", kind: "Multiple", [0]: Type, }; -export const Type_Multiple = (v0: Type): Type_Multiple => ({ kind: "Multiple", [0]: v0 }); +export const Type_Multiple = (v0: Type): Type_Multiple => ({ type: "Type", kind: "Multiple", [0]: v0 }); export type Type = Type_Name | Type_Optional | Type_Multiple; export const Type = { Name: Type_Name, Optional: Type_Optional, Multiple: Type_Multiple } as const; export type Name = { + type: "Name"; [0]: string; line: number; col: number; }; -export const Name = (v0: string, line: number, col: number): Name => ({ [0]: v0, line, col }); +export const Name = (v0: string, line: number, col: number): Name => ({ type: "Name", [0]: v0, line, col }); diff --git a/ast_generator.ts b/ast_generator.ts index 286ce94..0d1f300 100644 --- a/ast_generator.ts +++ b/ast_generator.ts @@ -5,6 +5,7 @@ import { import compiledParserGrammar from "./parser.out.ts"; import { + CodeBlock, Enum, Name, Node, @@ -21,6 +22,9 @@ class TypescriptGenerator { this.result += "// Generated file by ast_generator\n"; for (const statement of ast) { switch (statement.kind) { + case "CodeBlock": + this.generateCodeBlock(statement[0]); + break; case "Enum": this.generateEnum(statement[0]); break; @@ -33,6 +37,10 @@ class TypescriptGenerator { return this.result; } + private generateCodeBlock(block: CodeBlock) { + this.result += `${block[0]}\n`; + } + private generateEnum(enum_: Enum) { if (this.isShallowEnum(enum_)) { return this.generateShallowEnumBody(enum_); @@ -62,6 +70,7 @@ class TypescriptGenerator { const fullName = `${enumName}_${name}`; nodeNames.push([name, fullName]); this.result += `export type ${fullName} = {\n`; + this.result += ` type: "${enumName}",\n`; this.result += ` kind: "${name}",\n`; this.result += node.params.map((p, i) => this.makeParamField(p, i)) .map((field) => ` ${field},\n`).join(""); @@ -70,7 +79,7 @@ class TypescriptGenerator { const fields = this.makeFnFields(node.params); this.result += `export const ${fullName}` + ` = (${fnParams}): ${fullName}` + - ` => ({ kind: "${name}", ${fields} });\n`; + ` => ({ type: "${enumName}", kind: "${name}", ${fields} });\n`; } const typeList = nodeNames .map(([_, fullName]) => fullName) @@ -97,6 +106,7 @@ class TypescriptGenerator { ) { const name = this.makeName(node.name); this.result += `export type ${name} = {\n`; + this.result += ` type: "${name}";\n`; for ( const [param, index] of node.params .map((v, i) => [v, i] as const) @@ -117,7 +127,7 @@ class TypescriptGenerator { const fields = this.makeFnFields(node.params); this.result += `export const ${name}` + ` = (${fnParams}): ${name}` + - ` => ({ ${fields} });\n`; + ` => ({ type: "${name}", ${fields} });\n`; } private makeFnParams(params: Param[]): string { diff --git a/parser.ne b/parser.ne index 414e83a..1fb0040 100644 --- a/parser.ne +++ b/parser.ne @@ -13,6 +13,12 @@ const lexer: any = moo.compile({ singleLineComment: /\/\/.*?$/, multiLineComment: { match: /\*[^*]*\*+(?:[^/*][^*]*\*+)*/, lineBreaks: true }, + codeBlock: { + match: /\{%[^%]*?%\}/, + lineBreaks: true, + value: s => s.slice(2, s.length - 2), + }, + name: { match: /[a-zA-Z0-9_]+/, type: moo.keywords({ @@ -40,8 +46,11 @@ elements -> _ (element elementTail _):? {% v => v[1] ? [v[1][0], ...v[1][1]] : [ elementTail -> (nl__ element):* {% v => v[0].map(w => w[1]) %} -element -> enum {% v => ast.Statement.Enum(v[0]) %} - | node {% v => ast.Statement.Node(v[0]) %} +element -> codeBlock {% v => ast.Statement.CodeBlock(v[0]) %} + | enum {% v => ast.Statement.Enum(v[0]) %} + | node {% v => ast.Statement.Node(v[0]) %} + +codeBlock -> %codeBlock {% v => ast.CodeBlock(v[0].value) %} enum -> name _ "{" nodes "}" {% v => ast.Enum(v[0], v[3]) %}