"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BNF = void 0;
const Terminal_js_1 = require("./Terminal.js");
const NonTerminal_js_1 = require("./NonTerminal.js");
class BNF {
    constructor(other) {
        this.symbols = new Map();
        this.productions = [];
        if (other !== undefined) {
            for (let [key, value] of other.symbols)
                this.symbols.set(key, value);
            this.productions.push(...other.productions);
        }
    }
    reset() {
        this.symbols.clear();
        this.productions.length = 0;
    }
    removeStartProduction() {
        var i = this.productions.length;
        while (i--) {
            if (this.productions[i].getLeft().equals(BNF.ARTIFICIAL_START_SYMBOL)) {
                this.productions.splice(i, 1);
                break;
            }
        }
    }
    addProduction(p) {
        let existing = this.productions.findIndex(v => v.equals(p));
        if (existing != -1) {
            console.log("Production already exists: " + p);
            return this.productions[existing];
        }
        this.productions.push(p);
        this.symbols.set(p.getLeft().getSymbol(), p.getLeft());
        for (let sym of p.getRight()) {
            if (!sym.isEpsilon())
                this.symbols.set(sym.getSymbol(), sym);
        }
        return p;
    }
    getSymbol(symbol) {
        let ret = this.symbols.get(symbol);
        if (ret === undefined)
            throw new Error("Could not find symbol " + symbol);
        return ret;
    }
    getProductions(left) {
        return this.productions.filter(p => p.getLeft().equals(left));
    }
    toString() {
        let ret = "";
        for (let p of this.productions) {
            ret += p.toString() + "\n";
        }
        return ret;
    }
}
exports.BNF = BNF;
BNF.ARTIFICIAL_START_SYMBOL = new NonTerminal_js_1.NonTerminal("S'");
BNF.ARTIFICIAL_STOP_SYMBOL = Terminal_js_1.Terminal.END_OF_INPUT;
//# sourceMappingURL=BNF.js.map