"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AstBuilder = exports.Production = void 0;
const Terminal_js_1 = require("./Terminal.js");
var AstBuilder;
(function (AstBuilder) {
    AstBuilder.DEFAULT = (parent, ...children) => parent.addChildren(...children);
})(AstBuilder || (exports.AstBuilder = AstBuilder = {}));
class Production {
    constructor(left, ...right) {
        this.astBuilder = undefined;
        this.extensionListener = undefined;
        this.left = left;
        this.right = Production.removeEpsilon(right);
    }
    static removeEpsilon(arr) {
        return arr.filter((value) => !value.equals(Terminal_js_1.Terminal.EPSILON));
    }
    getLeft() {
        return this.left;
    }
    getRight() {
        return this.right;
    }
    setAstBuilder(astBuilder) {
        this.astBuilder = astBuilder;
    }
    builtAST(parent, ...children) {
        if (this.astBuilder !== undefined) {
            this.astBuilder(parent, ...children);
            return;
        }
        parent.addChildren(...children);
    }
    wasExtended(parent, ...children) {
        if (this.extensionListener !== undefined)
            this.extensionListener(parent, ...children);
    }
    onExtension(listener) {
        if (this.extensionListener !== undefined)
            throw new Error("ExtensionListener cannot be overwritten");
        this.extensionListener = listener;
    }
    toString() {
        let left = this.getLeft().toString();
        let sb = "";
        for (let k = 0; k < (50 - left.length); k++)
            sb += ' ';
        sb += left;
        sb += " -> ";
        let right = this.getRight();
        for (let symbol of right) {
            sb += symbol + " ";
        }
        return sb;
    }
    equals(o) {
        if (!(o instanceof Production))
            return false;
        const p = o;
        return this.left.equals(p.left) && Production.arraysEqual(this.right, p.right);
    }
    static arraysEqual(a, b) {
        if (a === b)
            return true;
        if (a == null || b == null)
            return false;
        if (a.length !== b.length)
            return false;
        // If you don't care about the order of the elements inside
        // the array, you should sort both arrays here.
        // Please note that calling sort on an array will modify that array.
        // you might want to clone your array first.
        for (var i = 0; i < a.length; ++i) {
            if (!a[i].equals(b[i]))
                return false;
        }
        return true;
    }
}
exports.Production = Production;
//# sourceMappingURL=Production.js.map