bolt/src/expander.ts
2020-02-25 18:34:21 +01:00

76 lines
1.7 KiB
TypeScript

import {
TokenStream,
SyntaxKind,
Syntax,
SourceFile,
Decl,
Statement
} from "./ast"
import { Parser, ParseError } from "./parser"
type Transformer = (tokens: TokenStream) => Syntax;
export class Expander {
transformers = new Map<string, Transformer>();
constructor(public parser: Parser) {
this.transformers.set('fn', parser.parseFuncDecl.bind(parser))
this.transformers.set('import', parser.parseImportDecl.bind(parser))
this.transformers.set('foreign', parser.parseFuncDecl.bind(parser))
this.transformers.set('let', parser.parseVarDecl.bind(parser))
this.transformers.set('return', parser.parseRetStmt.bind(parser))
}
getFullyExpanded(node: Syntax): Syntax {
if (node.kind === SyntaxKind.SourceFile) {
const expanded: (Decl | Statement)[] = [];
for (const element of node.elements) {
if (element.kind === SyntaxKind.Sentence) {
const newElement = this.getFullyExpanded(element)
expanded.push(newElement as Decl | Statement)
}
}
return new SourceFile(expanded, null, node);
} else if (node.kind === SyntaxKind.Sentence) {
while (true) {
console.log('expanding sententce')
const tokens: TokenStream = node.toTokenStream()
const t0 = tokens.peek();
if (t0.kind !== SyntaxKind.Identifier) {
throw new ParseError(t0, [SyntaxKind.Identifier]);
}
if (!this.transformers.has(t0.text)) {
return this.parser.parseCallExpr(tokens)
}
node = this.transformers.get(t0.text)!(tokens)
if (node.kind !== SyntaxKind.Sentence) {
break;
}
}
return node
} else {
throw new Error(`unrecognised node of kind ${node.kind}`)
}
}
}