Miss any of our Open RFC calls?Watch the recordings here! »

dsl-parser

0.0.17 • Public • Published

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)); 

Install

npm i dsl-parser

DownloadsWeekly Downloads

10

Version

0.0.17

License

ISC

Unpacked Size

30.2 kB

Total Files

14

Last publish

Collaborators

  • avatar