0.0.19 • Published 3 years ago

dsl-parser v0.0.19

Weekly downloads
2
License
ISC
Repository
github
Last release
3 years ago

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

3 years ago

0.0.18

3 years ago

0.0.17

4 years ago

0.0.16

4 years ago

0.0.15

4 years ago

0.0.14

4 years ago

0.0.13

4 years ago

0.0.12

5 years ago

0.0.11

5 years ago

0.0.10

5 years ago

0.0.9

5 years ago

0.0.8

5 years ago

0.0.7

5 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago