dsl-parser
v0.0.19
Published
A simple lexer and bottom-up parser for creating domain specific languages
Downloads
42
Maintainers
Readme
The example below shows a simple domain specific language for arithmetic.
import { Lexer, LexTree, Terminal } from "./Lexer";
import { Parser, ParseTree, RuleSet } from "./Parser";
import { skipOneChild, Visitor } from "./Visitor";
const terminals: Terminal[] = [
// Terminals are matched by their pattern (in order)
{ type: "number", pattern: /[0-9]+/ },
{ type: "add", pattern: /[+-]/ },
{ type: "mul", pattern: /[*\/]/ },
// Terminals with type 'whitespace' are ignored
{ type: "whitespace", pattern: /\s+/ }
];
const rules: RuleSet = {
root: [
// The root can expand to an addExpr
["addExpr"]
],
addExpr: [
// An addExpr can expand to an addExpr + a mulExpr
["addExpr", "add", "mulExpr"],
// Or just a mulExpr
["mulExpr"]
],
mulExpr: [
// An addExpr can expand to a mulExpr * a number
["mulExpr", "mul", "number"],
// Or just a number
["number"]
]
};
class ArithVisitor extends Visitor<number, void> {
@skipOneChild
public visit_addExpr(state: void, tree: ParseTree): number {
// Compute the lhs and rhs
const lhs = this.visit(state, tree.children[0]);
const rhs = this.visit(state, tree.children[2]);
switch ((tree.children[1] as LexTree).match[0]) {
case "+":
return lhs + rhs;
case "-":
return lhs - rhs;
}
throw new Error("Unreachable");
}
@skipOneChild
public visit_mulExpr(state: void, tree: ParseTree): number {
// Compute the lhs and rhs
const lhs = this.visit(state, tree.children[0]);
const rhs = this.visit(state, tree.children[tree.children.length - 1]);
switch ((tree.children[1] as LexTree).match[0]) {
case "*":
return lhs * rhs;
case "/":
return lhs / rhs;
}
throw new Error("Unreachable");
}
public visit_number(state: void, tree: LexTree): number {
return parseFloat(tree.match[0]);
}
}
const lexer = new Lexer(terminals);
const parser = new Parser(rules, "root");
const visitor = new ArithVisitor();
const parseTree = parser.parse(lexer, Lexer.split("3 + 2 * 1"));
console.log(visitor.visit(undefined, parseTree));