@preprocessor typescript @{% import * as moo from "https://deno.land/x/moo@0.5.1-deno.2/mod.ts"; import * as ast from "./ast.out.ts"; const lexer: any = moo.compile({ newline: { match: /[\n]+/, lineBreaks: true }, whitespace: /[ \t]+/, 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({ keyword: [], }), }, lparen: "(", rparen: ")", lbrace: "{", rbrace: "}", lbracket: "[", rbracket: "]", colon: ":", comma: ",", questionmark: "?", }); %} @lexer lexer file -> elements {% id %} elements -> _ (element elementTail _):? {% v => v[1] ? [v[1][0], ...v[1][1]] : [] %} elementTail -> (nl__ element):* {% v => v[0].map(w => w[1]) %} 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]) %} nodes -> _ (node nodeTail _):? {% v => v[1] ? [v[1][0], ...v[1][1]] : [] %} nodeTail -> (nl__ node):* {% v => v[0].map(w => w[1]) %} node -> name (_ paramList):? {% v => ast.Node(v[0], v[1] ? v[1][1] : []) %} paramList -> "(" params ")" {% v => v[1] %} params -> _ (param paramTail (_ ","):? _):? {% v => v[1] ? [v[1][0], ...v[1][1]] : [] %} paramTail -> ("," _ param):* {% v => v[0].map(w => w[2]) %} param -> namedParam {% id %} | unnamedParam {% id %} namedParam -> name _ ":" _ type {% v => ast.Param.Named(v[0], v[4]) %} unnamedParam -> type {% v => ast.Param.Unnamed(v[0]) %} type -> optional {% id %} | multiple {% id %} | name {% v => ast.Type.Name(v[0]) %} optional -> type "?" {% v => ast.Type.Optional(v[0]) %} multiple -> type "[" "]" {% v => ast.Type.Multiple(v[0]) %} name -> %name {% v => ast.Name(v[0].value, v[0].line, v[0].col) %} _ -> __:? __ -> (%whitespace|%newline|%singleLineComment|%multiLineComment):+ nl__ -> sl_ (%newline sl_):+ sl_ -> sl__:? sl__ -> (%whitespace|%singleLineComment|%multiLineComment):+