UNPKG

imba

Version:

Intuitive and powerful language for building webapps that fly

3,598 lines 120 kB
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// vendor/jison/util/typal.js
var require_typal = __commonJS({
  "vendor/jison/util/typal.js"(exports2) {
    var typal2 = /* @__PURE__ */ function() {
      var create = Object.create || function(o2) {
        function F() {
        }
        F.prototype = o2;
        return new F();
      };
      var position = /^(before|after)/;
      function layerMethod(k, fun) {
        var pos = k.match(position)[0], key = k.replace(position, ""), prop = this[key];
        if (pos === "after") {
          this[key] = function() {
            var ret = prop.apply(this, arguments);
            var args = [].slice.call(arguments);
            args.splice(0, 0, ret);
            fun.apply(this, args);
            return ret;
          };
        } else if (pos === "before") {
          this[key] = function() {
            fun.apply(this, arguments);
            var ret = prop.apply(this, arguments);
            return ret;
          };
        }
      }
      function typal_mix() {
        var self2 = this;
        for (var i = 0, o2, k; i < arguments.length; i++) {
          o2 = arguments[i];
          if (!o2) continue;
          if (Object.prototype.hasOwnProperty.call(o2, "constructor"))
            this.constructor = o2.constructor;
          if (Object.prototype.hasOwnProperty.call(o2, "toString"))
            this.toString = o2.toString;
          for (k in o2) {
            if (Object.prototype.hasOwnProperty.call(o2, k)) {
              if (k.match(position) && typeof this[k.replace(position, "")] === "function")
                layerMethod.call(this, k, o2[k]);
              else
                this[k] = o2[k];
            }
          }
        }
        return this;
      }
      return {
        // extend object with own typalperties of each argument
        mix: typal_mix,
        // sugar for object begetting and mixing
        // - Object.create(typal).mix(etc, etc);
        // + typal.beget(etc, etc);
        beget: function typal_beget() {
          return arguments.length ? typal_mix.apply(create(this), arguments) : create(this);
        },
        // Creates a new Class function based on an object with a constructor method
        construct: function typal_construct() {
          var o2 = typal_mix.apply(create(this), arguments);
          var constructor = o2.constructor;
          var Klass = o2.constructor = function() {
            return constructor.apply(this, arguments);
          };
          Klass.prototype = o2;
          Klass.mix = typal_mix;
          return Klass;
        },
        // no op
        constructor: function typal_constructor() {
          return this;
        }
      };
    }();
    if (typeof exports2 !== "undefined")
      exports2.typal = typal2;
  }
});

// vendor/jison/util/set.js
var require_set = __commonJS({
  "vendor/jison/util/set.js"(exports2) {
    var typal2 = require_typal().typal;
    var setMixin = {
      constructor: function Set_constructor(set, raw) {
        this._items = [];
        if (set && set.constructor === Array)
          this._items = raw ? set : set.slice(0);
        else if (arguments.length)
          this._items = [].slice.call(arguments, 0);
      },
      concat: function concat(setB) {
        this._items.push.apply(this._items, setB._items || setB);
        return this;
      },
      eq: function eq(set) {
        return this._items.length === set._items.length && this.subset(set);
      },
      indexOf: function indexOf(item) {
        if (item && item.eq) {
          for (var k = 0; k < this._items.length; k++)
            if (item.eq(this._items[k]))
              return k;
          return -1;
        }
        return this._items.indexOf(item);
      },
      union: function union(set) {
        return new Set2(this._items).concat(this.complement(set));
      },
      intersection: function intersection(set) {
        return this.filter(function(elm) {
          return set.contains(elm);
        });
      },
      complement: function complement(set) {
        var that = this;
        return set.filter(function sub_complement(elm) {
          return !that.contains(elm);
        });
      },
      subset: function subset(set) {
        var cont = true;
        for (var i = 0; i < this._items.length && cont; i++) {
          cont = cont && set.contains(this._items[i]);
        }
        return cont;
      },
      superset: function superset(set) {
        return set.subset(this);
      },
      joinSet: function joinSet(set) {
        return this.concat(this.complement(set));
      },
      contains: function contains(item) {
        return this.indexOf(item) !== -1;
      },
      item: function item(v, val) {
        return this._items[v];
      },
      i: function i(v, val) {
        return this._items[v];
      },
      first: function first() {
        return this._items[0];
      },
      last: function last() {
        return this._items[this._items.length - 1];
      },
      size: function size() {
        return this._items.length;
      },
      isEmpty: function isEmpty() {
        return this._items.length === 0;
      },
      copy: function copy() {
        return new Set2(this._items);
      },
      toString: function toString() {
        return this._items.toString();
      }
    };
    "push shift unshift forEach some every join sort".split(" ").forEach(function(e, i) {
      setMixin[e] = function() {
        return Array.prototype[e].apply(this._items, arguments);
      };
      setMixin[e].name = e;
    });
    "filter slice map".split(" ").forEach(function(e, i) {
      setMixin[e] = function() {
        return new Set2(Array.prototype[e].apply(this._items, arguments), true);
      };
      setMixin[e].name = e;
    });
    var Set2 = typal2.construct(setMixin).mix({
      union: function(a, b) {
        var ar = {};
        for (var k = a.length - 1; k >= 0; --k) {
          ar[a[k]] = true;
        }
        for (var i = b.length - 1; i >= 0; --i) {
          if (!ar[b[i]]) {
            a.push(b[i]);
          }
        }
        return a;
      }
    });
    if (typeof exports2 !== "undefined")
      exports2.Set = Set2;
  }
});

// vendor/jison/jison.js
var require_jison = __commonJS({
  "vendor/jison/jison.js"(exports, module) {
    var typal = require_typal().typal;
    var Set = require_set().Set;
    var Jison = exports.Jison = exports;
    if (typeof console !== "undefined" && console.log) {
      Jison.print = console.log;
    } else if (typeof puts !== "undefined") {
      Jison.print = function print2() {
        puts([].join.call(arguments, " "));
      };
    } else if (typeof print !== "undefined") {
      Jison.print = print;
    } else {
      Jison.print = function print2() {
      };
    }
    Jison.Parser = function() {
      function each(obj, func) {
        if (obj.forEach) {
          obj.forEach(func);
        } else {
          var p2;
          for (p2 in obj) {
            if (obj.hasOwnProperty(p2)) {
              func.call(obj, obj[p2], p2, obj);
            }
          }
        }
      }
      var Nonterminal = typal.construct({
        constructor: function Nonterminal2(symbol) {
          this.symbol = symbol;
          this.productions = new Set();
          this.first = [];
          this.follows = [];
          this.nullable = false;
        },
        toString: function Nonterminal_toString() {
          var str = this.symbol + "\n";
          str += this.nullable ? "nullable" : "not nullable";
          str += "\nFirsts: " + this.first.join(", ");
          str += "\nFollows: " + this.first.join(", ");
          str += "\nProductions:\n  " + this.productions.join("\n  ");
          return str;
        }
      });
      var Production = typal.construct({
        constructor: function Production2(symbol, handle, id) {
          this.symbol = symbol;
          this.handle = handle;
          this.nullable = false;
          this.id = id;
          this.first = [];
          this.precedence = 0;
        },
        toString: function Production_toString() {
          return this.symbol + " -> " + this.handle.join(" ");
        }
      });
      var generator = typal.beget();
      generator.constructor = function Jison_Generator(grammar2, opt) {
        var options = typal.mix.call({}, grammar2.options, opt);
        this.terms = {};
        this.operators = {};
        this.productions = [];
        this.conflicts = 0;
        this.resolutions = [];
        this.options = options;
        this.parseParams = grammar2.parseParams;
        this.yy = {};
        if (grammar2.actionInclude) {
          if (typeof grammar2.actionInclude === "function") {
            grammar2.actionInclude = String(grammar2.actionInclude).replace(/^\s*function \(\) \{/, "").replace(/\}\s*$/, "");
          }
          this.actionInclude = grammar2.actionInclude;
        }
        this.moduleInclude = grammar2.moduleInclude || "";
        this.DEBUG = options.debug || false;
        if (this.DEBUG) this.mix(generatorDebug);
        this.processGrammar(grammar2);
      };
      generator.processGrammar = function processGrammarDef(grammar2) {
        var bnf = grammar2.bnf, tokens2 = grammar2.tokens, nonterminals = this.nonterminals = {}, productions = this.productions, self2 = this;
        if (tokens2) {
          if (typeof tokens2 === "string") {
            tokens2 = tokens2.trim().split(" ");
          } else {
            tokens2 = tokens2.slice(0);
          }
        }
        var symbols = this.symbols = [];
        var operators2 = this.operators = processOperators(grammar2.operators);
        this.buildProductions(bnf, productions, nonterminals, symbols, operators2);
        if (tokens2 && this.terminals.length !== tokens2.length) {
          self2.trace("Warning: declared tokens differ from tokens found in rules.");
          self2.trace(this.terminals);
          self2.trace(tokens2);
        }
        this.augmentGrammar(grammar2);
      };
      generator.augmentGrammar = function augmentGrammar(grammar2) {
        if (this.productions.length === 0) {
          throw new Error("Grammar error: must have at least one rule.");
        }
        this.startSymbol = grammar2.start || grammar2.startSymbol || this.productions[0].symbol;
        if (!this.nonterminals[this.startSymbol]) {
          throw new Error("Grammar error: startSymbol must be a non-terminal found in your grammar.");
        }
        this.EOF = "$end";
        var acceptProduction = new Production("$accept", [this.startSymbol, "$end"], 0);
        this.productions.unshift(acceptProduction);
        this.symbols.unshift("$accept", this.EOF);
        this.symbols_.$accept = 0;
        this.symbols_[this.EOF] = 1;
        this.terminals.unshift(this.EOF);
        this.nonterminals.$accept = new Nonterminal("$accept");
        this.nonterminals.$accept.productions.push(acceptProduction);
        this.nonterminals[this.startSymbol].follows.push(this.EOF);
      };
      function processOperators(ops) {
        if (!ops) return {};
        var operators2 = {};
        for (var i = 0, k, prec; prec = ops[i]; i++) {
          for (k = 1; k < prec.length; k++) {
            operators2[prec[k]] = { precedence: i + 1, assoc: prec[0] };
          }
        }
        return operators2;
      }
      generator.buildProductions = function buildProductions(bnf, productions, nonterminals, symbols, operators2) {
        var actions = [
          "/* self == yyval */",
          this.actionInclude || "",
          "var $0 = $$.length - 1;",
          "switch (yystate) {"
        ];
        var actionGroups = {};
        var prods, symbol;
        var productions_ = [0];
        var symbolId = 1;
        var symbols_ = {};
        var her = false;
        function addSymbol(s) {
          if (s && !symbols_[s]) {
            symbols_[s] = ++symbolId;
            symbols.push(s);
          }
        }
        addSymbol("error");
        for (symbol in bnf) {
          if (!bnf.hasOwnProperty(symbol)) continue;
          addSymbol(symbol);
          nonterminals[symbol] = new Nonterminal(symbol);
          if (typeof bnf[symbol] === "string") {
            prods = bnf[symbol].split(/\s*\|\s*/g);
          } else {
            prods = bnf[symbol].slice(0);
          }
          prods.forEach(buildProduction);
        }
        for (var action in actionGroups)
          actions.push(actionGroups[action].join(" "), action, "break;");
        var sym, terms = [], terms_ = {};
        each(symbols_, function(id, sym2) {
          if (!nonterminals[sym2]) {
            terms.push(sym2);
            terms_[id] = sym2;
          }
        });
        this.hasErrorRecovery = her;
        this.terminals = terms;
        this.terminals_ = terms_;
        this.symbols_ = symbols_;
        this.productions_ = productions_;
        actions.push("}");
        actions = actions.join("\n").replace(/YYABORT/g, "return false").replace(/YYACCEPT/g, "return true");
        var yyvalParam = "this";
        var parameters = "self, yytext, yy, yystate /* action[1] */, $$ /* vstack */";
        if (this.parseParams) parameters += ", " + this.parseParams.join(", ");
        this.performAction = "function performAction(" + parameters + ") {\n" + actions + "\n}";
        function buildProduction(handle) {
          var r, rhs, i;
          if (handle.constructor === Array) {
            rhs = typeof handle[0] === "string" ? handle[0].trim().split(" ") : handle[0].slice(0);
            for (i = 0; i < rhs.length; i++) {
              if (rhs[i] === "error") her = true;
              if (!symbols_[rhs[i]]) {
                addSymbol(rhs[i]);
              }
            }
            if (typeof handle[1] === "string" || handle.length == 3) {
              var label = "case " + (productions.length + 1) + ":", action2 = handle[1];
              if (action2.match(/[$@][a-zA-Z][a-zA-Z0-9_]*/)) {
                var count = {}, names = {};
                for (i = 0; i < rhs.length; i++) {
                  var rhs_i = rhs[i].match(/\[[a-zA-Z][a-zA-Z0-9_-]*\]/);
                  if (rhs_i) {
                    rhs_i = rhs_i[0].substr(1, rhs_i[0].length - 2);
                    rhs[i] = rhs[i].substr(0, rhs[i].indexOf("["));
                  } else {
                    rhs_i = rhs[i];
                  }
                  if (names[rhs_i]) {
                    names[rhs_i + ++count[rhs_i]] = i + 1;
                  } else {
                    names[rhs_i] = i + 1;
                    names[rhs_i + "1"] = i + 1;
                    count[rhs_i] = 1;
                  }
                }
                action2 = action2.replace(/\$([a-zA-Z][a-zA-Z0-9_]*)/g, function(str, pl) {
                  return names[pl] ? "$" + names[pl] : str;
                }).replace(/@([a-zA-Z][a-zA-Z0-9_]*)/g, function(str, pl) {
                  return names[pl] ? "@" + names[pl] : str;
                });
              }
              action2 = action2.replace(/([^'"])\$\$|^\$\$/g, "$1self.$").replace(/@[0$]/g, "self._$").replace(/\$(-?\d+)/g, function(_, n) {
                return "$$[$0" + (parseInt(n, 10) - rhs.length || "") + "]";
              }).replace(/@(-?\d+)/g, function(_, n) {
                return "_$[$0" + (n - rhs.length || "") + "]";
              });
              if (action2 in actionGroups) actionGroups[action2].push(label);
              else actionGroups[action2] = [label];
              rhs = rhs.map(function(e, i2) {
                return e.replace(/\[[a-zA-Z_][a-zA-Z0-9_-]*\]/g, "");
              });
              r = new Production(symbol, rhs, productions.length + 1);
              if (handle[2] && operators2[handle[2].prec]) {
                r.precedence = operators2[handle[2].prec].precedence;
              }
            } else {
              rhs = rhs.map(function(e, i2) {
                return e.replace(/\[[a-zA-Z_][a-zA-Z0-9_-]*\]/g, "");
              });
              r = new Production(symbol, rhs, productions.length + 1);
              if (operators2[handle[1].prec]) {
                r.precedence = operators2[handle[1].prec].precedence;
              }
            }
          } else {
            handle = handle.replace(/\[[a-zA-Z_][a-zA-Z0-9_-]*\]/g, "");
            rhs = handle.trim().split(" ");
            for (i = 0; i < rhs.length; i++) {
              if (rhs[i] === "error") her = true;
              if (!symbols_[rhs[i]]) {
                addSymbol(rhs[i]);
              }
            }
            r = new Production(symbol, rhs, productions.length + 1);
          }
          if (r.precedence === 0) {
            for (i = r.handle.length - 1; i >= 0; i--) {
              if (!(r.handle[i] in nonterminals) && r.handle[i] in operators2) {
                r.precedence = operators2[r.handle[i]].precedence;
              }
            }
          }
          productions.push(r);
          productions_.push([symbols_[r.symbol], r.handle[0] === "" ? 0 : r.handle.length]);
          nonterminals[symbol].productions.push(r);
        }
      };
      generator.createParser = function createParser2() {
        throw new Error("Calling abstract method.");
      };
      generator.trace = function trace() {
      };
      generator.warn = function warn() {
        var args = Array.prototype.slice.call(arguments, 0);
        Jison.print.call(null, args.join(""));
      };
      generator.error = function error(msg) {
        throw new Error(msg);
      };
      var generatorDebug = {
        trace: function trace() {
          Jison.print.apply(null, arguments);
        },
        beforeprocessGrammar: function() {
          this.trace("Processing grammar.");
        },
        afteraugmentGrammar: function() {
          var trace = this.trace;
          each(this.symbols, function(sym, i) {
            trace(sym + "(" + i + ")");
          });
        }
      };
      var lookaheadMixin = {};
      lookaheadMixin.computeLookaheads = function computeLookaheads() {
        if (this.DEBUG) this.mix(lookaheadDebug);
        this.computeLookaheads = function() {
        };
        this.nullableSets();
        this.firstSets();
        this.followSets();
      };
      lookaheadMixin.followSets = function followSets() {
        var productions = this.productions, nonterminals = this.nonterminals, self2 = this, cont = true;
        while (cont) {
          cont = false;
          productions.forEach(function Follow_prod_forEach(production, k) {
            var q;
            var ctx = !!self2.go_;
            var set = [], oldcount;
            for (var i = 0, t; t = production.handle[i]; ++i) {
              if (!nonterminals[t]) continue;
              if (ctx)
                q = self2.go_(production.symbol, production.handle.slice(0, i));
              var bool = !ctx || q === parseInt(self2.nterms_[t], 10);
              if (i === production.handle.length + 1 && bool) {
                set = nonterminals[production.symbol].follows;
              } else {
                var part = production.handle.slice(i + 1);
                set = self2.first(part);
                if (self2.nullable(part) && bool) {
                  set.push.apply(set, nonterminals[production.symbol].follows);
                }
              }
              oldcount = nonterminals[t].follows.length;
              Set.union(nonterminals[t].follows, set);
              if (oldcount !== nonterminals[t].follows.length) {
                cont = true;
              }
            }
          });
        }
      };
      lookaheadMixin.first = function first(symbol) {
        if (symbol === "") {
          return [];
        } else if (symbol instanceof Array) {
          var firsts = [];
          for (var i = 0, t; t = symbol[i]; ++i) {
            if (!this.nonterminals[t]) {
              if (firsts.indexOf(t) === -1)
                firsts.push(t);
            } else {
              Set.union(firsts, this.nonterminals[t].first);
            }
            if (!this.nullable(t))
              break;
          }
          return firsts;
        } else if (!this.nonterminals[symbol]) {
          return [symbol];
        } else {
          return this.nonterminals[symbol].first;
        }
      };
      lookaheadMixin.firstSets = function firstSets() {
        var productions = this.productions, nonterminals = this.nonterminals, self2 = this, cont = true, symbol, firsts;
        while (cont) {
          cont = false;
          productions.forEach(function FirstSets_forEach(production, k) {
            var firsts2 = self2.first(production.handle);
            if (firsts2.length !== production.first.length) {
              production.first = firsts2;
              cont = true;
            }
          });
          for (symbol in nonterminals) {
            firsts = [];
            nonterminals[symbol].productions.forEach(function(production) {
              Set.union(firsts, production.first);
            });
            if (firsts.length !== nonterminals[symbol].first.length) {
              nonterminals[symbol].first = firsts;
              cont = true;
            }
          }
        }
      };
      lookaheadMixin.nullableSets = function nullableSets() {
        var firsts = this.firsts = {}, nonterminals = this.nonterminals, self2 = this, cont = true;
        while (cont) {
          cont = false;
          this.productions.forEach(function(production2, k) {
            if (!production2.nullable) {
              for (var i2 = 0, n = 0, t; t = production2.handle[i2]; ++i2) {
                if (self2.nullable(t)) n++;
              }
              if (n === i2) {
                production2.nullable = cont = true;
              }
            }
          });
          for (var symbol in nonterminals) {
            if (!this.nullable(symbol)) {
              for (var i = 0, production; production = nonterminals[symbol].productions.item(i); i++) {
                if (production.nullable)
                  nonterminals[symbol].nullable = cont = true;
              }
            }
          }
        }
      };
      lookaheadMixin.nullable = function nullable(symbol) {
        if (symbol === "") {
          return true;
        } else if (symbol instanceof Array) {
          for (var i = 0, t; t = symbol[i]; ++i) {
            if (!this.nullable(t))
              return false;
          }
          return true;
        } else if (!this.nonterminals[symbol]) {
          return false;
        } else {
          return this.nonterminals[symbol].nullable;
        }
      };
      var lookaheadDebug = {
        beforenullableSets: function() {
          this.trace("Computing Nullable sets.");
        },
        beforefirstSets: function() {
          this.trace("Computing First sets.");
        },
        beforefollowSets: function() {
          this.trace("Computing Follow sets.");
        },
        afterfollowSets: function() {
          var trace = this.trace;
          each(this.nonterminals, function(nt, t) {
            trace(nt, "\n");
          });
        }
      };
      var lrGeneratorMixin = {};
      lrGeneratorMixin.buildTable = function buildTable() {
        if (this.DEBUG) this.mix(lrGeneratorDebug);
        this.states = this.canonicalCollection();
        this.table = this.parseTable(this.states);
        this.defaultActions = findDefaults(this.table);
      };
      lrGeneratorMixin.Item = typal.construct({
        constructor: function Item(production, dot, f, predecessor) {
          this.production = production;
          this.dotPosition = dot || 0;
          this.follows = f || [];
          this.predecessor = predecessor;
          this.id = parseInt(production.id + "a" + this.dotPosition, 36);
          this.markedSymbol = this.production.handle[this.dotPosition];
        },
        remainingHandle: function() {
          return this.production.handle.slice(this.dotPosition + 1);
        },
        eq: function(e) {
          return e.id === this.id;
        },
        handleToString: function() {
          var handle = this.production.handle.slice(0);
          handle[this.dotPosition] = "." + (handle[this.dotPosition] || "");
          return handle.join(" ");
        },
        toString: function() {
          var temp = this.production.handle.slice(0);
          temp[this.dotPosition] = "." + (temp[this.dotPosition] || "");
          return this.production.symbol + " -> " + temp.join(" ") + (this.follows.length === 0 ? "" : " #lookaheads= " + this.follows.join(" "));
        }
      });
      lrGeneratorMixin.ItemSet = Set.prototype.construct({
        afterconstructor: function() {
          this.reductions = [];
          this.goes = {};
          this.edges = {};
          this.shifts = false;
          this.inadequate = false;
          this.hash_ = {};
          for (var i = this._items.length - 1; i >= 0; i--) {
            this.hash_[this._items[i].id] = true;
          }
        },
        concat: function concat(set) {
          var a = set._items || set;
          for (var i = a.length - 1; i >= 0; i--) {
            this.hash_[a[i].id] = true;
          }
          this._items.push.apply(this._items, a);
          return this;
        },
        push: function(item) {
          this.hash_[item.id] = true;
          return this._items.push(item);
        },
        contains: function(item) {
          return this.hash_[item.id];
        },
        valueOf: function toValue() {
          var v = this._items.map(function(a) {
            return a.id;
          }).sort().join("|");
          this.valueOf = function toValue_inner() {
            return v;
          };
          return v;
        }
      });
      lrGeneratorMixin.closureOperation = function closureOperation(itemSet) {
        var closureSet = new this.ItemSet();
        var self2 = this;
        var set = itemSet, itemQueue, syms = {};
        do {
          itemQueue = new Set();
          closureSet.concat(set);
          set.forEach(function CO_set_forEach(item) {
            var symbol = item.markedSymbol;
            if (symbol && self2.nonterminals[symbol]) {
              if (!syms[symbol]) {
                self2.nonterminals[symbol].productions.forEach(function CO_nt_forEach(production) {
                  var newItem = new self2.Item(production, 0);
                  if (!closureSet.contains(newItem))
                    itemQueue.push(newItem);
                });
                syms[symbol] = true;
              }
            } else if (!symbol) {
              closureSet.reductions.push(item);
              closureSet.inadequate = closureSet.reductions.length > 1 || closureSet.shifts;
            } else {
              closureSet.shifts = true;
              closureSet.inadequate = closureSet.reductions.length > 0;
            }
          });
          set = itemQueue;
        } while (!itemQueue.isEmpty());
        return closureSet;
      };
      lrGeneratorMixin.gotoOperation = function gotoOperation(itemSet, symbol) {
        var gotoSet = new this.ItemSet(), self2 = this;
        itemSet.forEach(function goto_forEach(item, n) {
          if (item.markedSymbol === symbol) {
            gotoSet.push(new self2.Item(item.production, item.dotPosition + 1, item.follows, n));
          }
        });
        return gotoSet.isEmpty() ? gotoSet : this.closureOperation(gotoSet);
      };
      lrGeneratorMixin.canonicalCollection = function canonicalCollection() {
        var item1 = new this.Item(this.productions[0], 0, [this.EOF]);
        var firstState = this.closureOperation(new this.ItemSet(item1)), states = new Set(firstState), marked = 0, self2 = this, itemSet;
        states.has = {};
        states.has[firstState] = 0;
        while (marked !== states.size()) {
          itemSet = states.item(marked);
          marked++;
          itemSet.forEach(function CC_itemSet_forEach(item) {
            if (item.markedSymbol && item.markedSymbol !== self2.EOF)
              self2.canonicalCollectionInsert(item.markedSymbol, itemSet, states, marked - 1);
          });
        }
        return states;
      };
      lrGeneratorMixin.canonicalCollectionInsert = function canonicalCollectionInsert(symbol, itemSet, states, stateNum) {
        var g = this.gotoOperation(itemSet, symbol);
        if (!g.predecessors)
          g.predecessors = {};
        if (!g.isEmpty()) {
          var gv = g.valueOf(), i = states.has[gv];
          if (i === -1 || typeof i === "undefined") {
            states.has[gv] = states.size();
            itemSet.edges[symbol] = states.size();
            states.push(g);
            g.predecessors[symbol] = [stateNum];
          } else {
            itemSet.edges[symbol] = i;
            states.item(i).predecessors[symbol].push(stateNum);
          }
        }
      };
      var NONASSOC = 0;
      lrGeneratorMixin.parseTable = function parseTable(itemSets) {
        var states = [], nonterminals = this.nonterminals, operators2 = this.operators, conflictedStates = {}, self2 = this, s = 1, r = 2, a = 3;
        itemSets.forEach(function(itemSet, k) {
          var state = states[k] = {};
          var action, stackSymbol;
          for (stackSymbol in itemSet.edges) {
            itemSet.forEach(function(item, j) {
              if (item.markedSymbol == stackSymbol) {
                var gotoState = itemSet.edges[stackSymbol];
                if (nonterminals[stackSymbol]) {
                  state[self2.symbols_[stackSymbol]] = gotoState;
                } else {
                  state[self2.symbols_[stackSymbol]] = [s, gotoState];
                }
              }
            });
          }
          itemSet.forEach(function(item, j) {
            if (item.markedSymbol == self2.EOF) {
              state[self2.symbols_[self2.EOF]] = [a];
            }
          });
          var allterms = self2.lookAheads ? false : self2.terminals;
          itemSet.reductions.forEach(function(item, j) {
            var terminals = allterms || self2.lookAheads(itemSet, item);
            terminals.forEach(function(stackSymbol2) {
              action = state[self2.symbols_[stackSymbol2]];
              var op = operators2[stackSymbol2];
              if (action || action && action.length) {
                var sol = resolveConflict(item.production, op, [r, item.production.id], action[0] instanceof Array ? action[0] : action);
                self2.resolutions.push([k, stackSymbol2, sol]);
                if (sol.bydefault) {
                  self2.conflicts++;
                  if (!self2.DEBUG) {
                    self2.warn("Conflict in grammar: multiple actions possible when lookahead token is ", stackSymbol2, " in state ", k, "\n- ", printAction(sol.r, self2), "\n- ", printAction(sol.s, self2));
                    conflictedStates[k] = true;
                  }
                  if (self2.options.noDefaultResolve) {
                    if (!(action[0] instanceof Array))
                      action = [action];
                    action.push(sol.r);
                  }
                } else {
                  action = sol.action;
                }
              } else {
                action = [r, item.production.id];
              }
              if (action && action.length) {
                state[self2.symbols_[stackSymbol2]] = action;
              } else if (action === NONASSOC) {
                state[self2.symbols_[stackSymbol2]] = void 0;
              }
            });
          });
        });
        if (!self2.DEBUG && self2.conflicts > 0) {
          self2.warn("\nStates with conflicts:");
          each(conflictedStates, function(val, state) {
            self2.warn("State " + state);
            self2.warn("  ", itemSets.item(state).join("\n  "));
          });
        }
        return states;
      };
      function findDefaults(states) {
        var defaults = {};
        states.forEach(function(state, k) {
          var i = 0;
          for (var act in state) {
            if ({}.hasOwnProperty.call(state, act)) i++;
          }
          if (i === 1 && state[act][0] === 2) {
            defaults[k] = state[act];
          }
        });
        return defaults;
      }
      function resolveConflict(production, op, reduce, shift) {
        var sln = { production, operator: op, r: reduce, s: shift }, s = 1, r = 2, a = 3;
        if (shift[0] === r) {
          sln.msg = "Resolve R/R conflict (use first production declared in grammar.)";
          sln.action = shift[1] < reduce[1] ? shift : reduce;
          if (shift[1] !== reduce[1]) sln.bydefault = true;
          return sln;
        }
        if (production.precedence === 0 || !op) {
          sln.msg = "Resolve S/R conflict (shift by default.)";
          sln.bydefault = true;
          sln.action = shift;
        } else if (production.precedence < op.precedence) {
          sln.msg = "Resolve S/R conflict (shift for higher precedent operator.)";
          sln.action = shift;
        } else if (production.precedence === op.precedence) {
          if (op.assoc === "right") {
            sln.msg = "Resolve S/R conflict (shift for right associative operator.)";
            sln.action = shift;
          } else if (op.assoc === "left") {
            sln.msg = "Resolve S/R conflict (reduce for left associative operator.)";
            sln.action = reduce;
          } else if (op.assoc === "nonassoc") {
            sln.msg = "Resolve S/R conflict (no action for non-associative operator.)";
            sln.action = NONASSOC;
          }
        } else {
          sln.msg = "Resolve conflict (reduce for higher precedent production.)";
          sln.action = reduce;
        }
        return sln;
      }
      lrGeneratorMixin.generate = function parser_generate(opt) {
        opt = typal.mix.call({}, this.options, opt);
        var code = "";
        if (!opt.moduleName || !opt.moduleName.match(/^[A-Za-z_$][A-Za-z0-9_$]*$/)) {
          opt.moduleName = "parser";
        }
        switch (opt.moduleType) {
          case "js":
            code = this.generateModule(opt);
            break;
          case "amd":
            code = this.generateAMDModule(opt);
            break;
          default:
            code = this.generateCommonJSModule(opt);
            break;
        }
        return code;
      };
      lrGeneratorMixin.generateAMDModule = function generateAMDModule(opt) {
        opt = typal.mix.call({}, this.options, opt);
        var module2 = this.generateModule_();
        var out = "\n\ndefine(function(require){\n" + module2.commonCode + "\nvar parser = " + module2.moduleCode + "\n" + this.moduleInclude + (this.lexer && this.lexer.generateModule ? "\n" + this.lexer.generateModule() + "\nparser.lexer = lexer;" : "") + "\nreturn parser;\n});";
        return out;
      };
      lrGeneratorMixin.generateCommonJSModule = function generateCommonJSModule(opt) {
        opt = typal.mix.call({}, this.options, opt);
        var moduleName = opt.moduleName || "parser";
        var out = this.generateModule(opt) + "\n\n\nif (typeof require !== 'undefined' && typeof exports !== 'undefined') {\nexports.parser = " + moduleName + ";\nexports.Parser = " + moduleName + ".Parser;\nexports.parse = function () { return " + moduleName + ".parse.apply(" + moduleName + ", arguments); };\n}";
        return out;
      };
      lrGeneratorMixin.generateModule = function generateModule(opt) {
        opt = typal.mix.call({}, this.options, opt);
        var moduleName = opt.moduleName || "parser";
        var out = "/* parser generated by jison-fork */\n";
        out += (moduleName.match(/\./) ? moduleName : "var " + moduleName) + " = " + this.generateModuleExpr();
        return out;
      };
      lrGeneratorMixin.generateModuleExpr = function generateModuleExpr() {
        var out = "";
        var module2 = this.generateModule_();
        out += "(function(){\n";
        out += module2.commonCode;
        out += "\nvar parser = " + module2.moduleCode;
        out += "\n" + this.moduleInclude;
        if (this.lexer && this.lexer.generateModule) {
          out += this.lexer.generateModule();
          out += "\nparser.lexer = lexer;";
        }
        out += "\nfunction Parser () {\n  this.yy = {};\n}\nParser.prototype = parser;parser.Parser = Parser;\nreturn new Parser;\n})();";
        return out;
      };
      function addTokenStack(fn) {
        var parseFn = fn;
        return fn;
      }
      function tokenStackLex() {
        var token;
        token = tstack.pop() || lexer.lex() || EOF;
        if (typeof token !== "number") {
          if (token instanceof Array) {
            tstack = token;
            token = tstack.pop();
          }
          token = self.symbols_[token] || token;
        }
        return token;
      }
      lrGeneratorMixin.generateModule_ = function generateModule_() {
        var parseFn = String(parser.parse);
        nextVariableId = 0;
        var tableCode = this.generateTableCode(this.table);
        var commonCode = tableCode.commonCode;
        var moduleCode = "{";
        moduleCode += [
          "trace: " + String(this.trace || parser.trace),
          "yy: {}",
          "symbols_: " + JSON.stringify(this.symbols_),
          "terminals_: " + JSON.stringify(this.terminals_).replace(/"([0-9]+)":/g, "$1:"),
          "productions_: " + JSON.stringify(this.productions_),
          "performAction: " + String(this.performAction),
          "table: " + tableCode.moduleCode,
          "defaultActions: " + JSON.stringify(this.defaultActions).replace(/"([0-9]+)":/g, "$1:"),
          "parseError: " + String(this.parseError || (this.hasErrorRecovery ? traceParseError : parser.parseError)),
          "parse: " + parseFn
        ].join(",\n");
        moduleCode += "};";
        return { commonCode, moduleCode };
      };
      lrGeneratorMixin.generateTableCode = function(table) {
        var moduleCode = JSON.stringify(table);
        var variables = [createObjectCode];
        moduleCode = moduleCode.replace(/"([0-9]+)"(?=:)/g, "$1");
        moduleCode = moduleCode.replace(/\{\d+:[^\}]+,\d+:[^\}]+\}/g, function(object) {
          var value, frequentValue, key, keys = {}, keyCount, maxKeyCount = 0, keyValue, keyValues = [], keyValueMatcher = /(\d+):([^:]+)(?=,\d+:|\})/g;
          while (keyValue = keyValueMatcher.exec(object)) {
            key = keyValue[1];
            value = keyValue[2];
            keyCount = 1;
            if (!(value in keys)) {
              keys[value] = [key];
            } else {
              keyCount = keys[value].push(key);
            }
            if (keyCount > maxKeyCount) {
              maxKeyCount = keyCount;
              frequentValue = value;
            }
          }
          if (maxKeyCount > 1) {
            for (value in keys) {
              if (value !== frequentValue) {
                for (var k = keys[value], i = 0, l = k.length; i < l; i++) {
                  keyValues.push(k[i] + ":" + value);
                }
              }
            }
            keyValues = keyValues.length ? ",{" + keyValues.join(",") + "}" : "";
            object = "o([" + keys[frequentValue].join(",") + "]," + frequentValue + keyValues + ")";
          }
          return object;
        });
        var list;
        var lists = {};
        var listMatcher = /\[[0-9,]+\]/g;
        while (list = listMatcher.exec(moduleCode)) {
          lists[list] = (lists[list] || 0) + 1;
        }
        moduleCode = moduleCode.replace(listMatcher, function(list2) {
          var listId = lists[list2];
          if (typeof listId === "number") {
            if (listId === 1) {
              lists[list2] = listId = list2;
            } else {
              lists[list2] = listId = createVariable();
              variables.push(listId + "=" + list2);
            }
          }
          return listId;
        });
        return {
          commonCode: "var " + variables.join(",") + ";",
          moduleCode
        };
      };
      var createObjectCode = "o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o}";
      function createVariable() {
        var id = nextVariableId++;
        var name = "$V";
        do {
          name += variableTokens[id % variableTokensLength];
          id = ~~(id / variableTokensLength);
        } while (id !== 0);
        return name;
      }
      var nextVariableId = 0;
      var variableTokens = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$";
      var variableTokensLength = variableTokens.length;
      function printAction(a, gen) {
        var s = a[0] == 1 ? "shift token (then go to state " + a[1] + ")" : a[0] == 2 ? "reduce by rule: " + gen.productions[a[1]] : "accept";
        return s;
      }
      var lrGeneratorDebug = {
        beforeparseTable: function() {
          this.trace("Building parse table.");
        },
        afterparseTable: function() {
          var self2 = this;
          if (this.conflicts > 0) {
            this.resolutions.forEach(function(r, i) {
              if (r[2].bydefault) {
                self2.warn("Conflict at state: ", r[0], ", token: ", r[1], "\n  ", printAction(r[2].r, self2), "\n  ", printAction(r[2].s, self2));
              }
            });
            this.trace("\n" + this.conflicts + " Conflict(s) found in grammar.");
          }
          this.trace("Done.");
        },
        aftercanonicalCollection: function(states) {
          var trace = this.trace;
          trace("\nItem sets\n------");
          states.forEach(function(state, i) {
            trace("\nitem set", i, "\n" + state.join("\n"), "\ntransitions -> ", JSON.stringify(state.edges));
          });
        }
      };
      var parser = typal.beget();
      lrGeneratorMixin.createParser = function createParser() {
        var p = eval(this.generateModuleExpr());
        p.productions = this.productions;
        var self = this;
        function bind(method) {
          return function() {
            self.lexer = p.lexer;
            return self[method].apply(self, arguments);
          };
        }
        p.generate = bind("generate");
        p.generateAMDModule = bind("generateAMDModule");
        p.generateModule = bind("generateModule");
        p.generateCommonJSModule = bind("generateCommonJSModule");
        return p;
      };
      parser.trace = generator.trace;
      parser.warn = generator.warn;
      parser.error = generator.error;
      function traceParseError(err, hash) {
        this.trace(err);
      }
      function parseError(str, hash) {
        if (hash.recoverable) {
          this.trace(str);
        } else {
          throw new Error(str);
        }
      }
      parser.parseError = lrGeneratorMixin.parseError = parseError;
      parser.parse = function parse(input, script = null) {
        var self2 = this, stack = [0], tstack2 = [], vstack = [null], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF2 = 1;
        var lexer2 = Object.create(this.lexer);
        var yy = this.yy;
        lexer2.setInput(input, yy);
        if (typeof yy.parseError === "function") {
          this.parseError = yy.parseError;
        } else {
          this.parseError = Object.getPrototypeOf(this).parseError;
        }
        function popStack(n) {
          stack.length = stack.length - 2 * n;
          vstack.length = vstack.length - n;
        }
        var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p2, len, newState, expected;
        function handleError() {
          var error_rule_depth;
          var errStr = "";
          function locateNearestErrorRecoveryRule(state2) {
            var stack_probe = stack.length - 1;
            var depth = 0;
            for (; ; ) {
              if (TERROR.toString() in table[state2]) {
                return depth;
              }
              if (state2 === 0 || stack_probe < 2) {
                return false;
              }
              stack_probe -= 2;
              state2 = stack[stack_probe];
              ++depth;
            }
          }
          if (!recovering) {
            error_rule_depth = locateNearestErrorRecoveryRule(state);
            expected = [];
            var tsym = lexer2.yytext;
            var lastToken = tsym;
            var tok = self2.terminals_[symbol] || symbol;
            let tidx = lexer2.tokens.indexOf(tsym);
            let ttok = tsym;
            while (ttok && !(ttok._loc >= 0)) {
              ttok = lexer2.tokens[--tidx];
            }
            if (!ttok) {
              let k = lexer2.tokens.length;
              while (--k >= 0) {
                let t = lexer2.tokens[k];
                if (t && t._loc >= 0) {
                  ttok = t;
                  break;
                }
              }
            }
            var tloc = ttok ? ttok._loc : -1;
            var tend = tloc > -1 ? tloc + (ttok._len || 0) : -1;
            var tpos = tloc != -1 ? "[" + ttok._loc + ":" + ttok._len + "]" : "[0:0]";
            var tokenDescriptions = {
              TERMINATOR: "newline",
              INDENT: "indentation",
              OUTDENT: "end of block",
              EMPTY_BLOCK: "empty block",
              CALL_END: "')'",
              CALL_START: "'('",
              INDEX_END: "']'",
              INDEX_START: "'['",
              STRING_START: "start of string",
              STRING_END: "end of string",
              TAG_START: "'<'",
              TAG_END: "'>'"
            };
            if (lexer2.showPosition) {
              errStr = "Parse error at " + tpos + ":\n" + lexer2.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + tok + "'";
            } else {
              errStr = "Unexpected " + (symbol == EOF2 ? "end of input" : tokenDescriptions[tok] || "'" + tok + "'");
            }
            if (script) {
              let err = script.addDiagnostic("error", {
                message: errStr,
                source: "imba-parser",
                range: script.rangeAt(tloc, tend)
              });
              err.raise();
            }
            self2.parseError(errStr, {
              lexer: lexer2,
              text: lexer2.match,
              token: tok,
              offset: tloc,
              length: tend - tloc,
              start: { offset: tloc },
              end: { offset: tend },
              line: lexer2.yylineno,
              expected,
              recoverable: error_rule_depth !== false
            });
          } else if (preErrorSymbol !== EOF2) {
            error_rule_depth = locateNearestErrorRecoveryRule(state);
          }
          if (recovering == 3) {
            if (symbol === EOF2 || preErrorSymbol === EOF2) {
              throw new Error(errStr || "Parsing halted while starting to recover from another error.");
            }
            yytext = lexer2.yytext;
          }
          if (error_rule_depth === false) {
            throw new Error(errStr || "Parsing halted. No suitable error recovery rule available.");
          }
          popStack(error_rule_depth);
          preErrorSymbol = symbol == TERROR ? null : symbol;
          symbol = TERROR;
          state = stack[stack.length - 1];
          action = table[state] && table[state][TERROR];
          recovering = 3;
        }
        var __sym = this.symbols_;
        var __prod = this.productions_;
        while (true) {
          state = stack[stack.length - 1];
          if (symbol === null || typeof symbol == "undefined") {
            symbol = __sym[lexer2.lex()] || EOF2;
          }
          action = table[state] && table[state][symbol];
          _handle_error:
            if (typeof action === "undefined" || !action.length || !action[0]) {
              handleError();
            }
          switch (action[0]) {
            case 1:
              stack.push(symbol);
              stack.push(action[1]);
              vstack.push(lexer2.yytext);
              symbol = null;
              if (!preErrorSymbol) {
                yytext = lexer2.yytext;
                if (recovering > 0) {
                  recovering--;
                }
              } else {
                symbol = preErrorSymbol;
                preErrorSymbol = null;
              }
              break;
            case 2:
              len = __prod[action[1]][1];
              yyval.$ = vstack[vstack.length - len];
              r = this.performAction(yyval, yytext, yy, action[1], vstack);
              if (typeof r !== "undefined") {
                return r;
              }
              while (len > 0) {
                stack.pop();
                stack.pop();
                vstack.pop();
                len--;
              }
              stack.push(__prod[action[1]][0]);
              newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
              stack.push(newState);
              vstack.push(yyval.$);
              break;
            case 3:
              return true;
          }
        }
        return true;
      };
      parser.init = function parser_init(dict) {
        this.table = dict.table;
        this.defaultActions = dict.defaultActions;
        this.performAction = dict.performAction;
        this.productions_ = dict.productions_;
        this.symbols_ = dict.symbols_;
        this.terminals_ = dict.terminals_;
      };
      var lr0 = generator.beget(lookaheadMixin, lrGeneratorMixin, {
        type: "LR(0)",
        afterconstructor: function lr0_afterconstructor() {
          this.buildTable();
        }
      });
      var LR0Generator = exports.LR0Generator = lr0.construct();
      var lalr = generator.beget(lookaheadMixin, lrGeneratorMixin, {
        type: "LALR(1)",
        afterconstructor: function(grammar2, options) {
          if (this.DEBUG) this.mix(lrGeneratorDebug, lalrGeneratorDebug);
          options = options || {};
          this.states = this.canonicalCollection();
          this.terms_ = {};
          var newg = this.newg = typal.beget(lookaheadMixin, {
            oldg: this,
            trace: this.trace,
            nterms_: {},
            DEBUG: false,
            go_: function(r, B) {
              r = r.split(":")[0];
              B = B.map(function(b) {
                return b.slice(b.indexOf(":") + 1);
              });
              return this.oldg.go(r, B);
            }
          });
          newg.nonterminals = {};
          newg.productions = [];
          this.inadequateStates = [];
          this.onDemandLookahead = options.onDemandLookahead || false;
          this.buildNewGrammar();
          newg.computeLookaheads();
          this.unionLookaheads();
          this.table = this.parseTable(this.states);
          this.defaultActions = findDefaults(this.table);
        },
        lookAheads: function LALR_lookaheads(state, item) {
          return !!this.onDemandLookahead && !state.inadequate ? this.terminals : item.follows;
        },
        go: function LALR_go(p2, w) {
          var q = parseInt(p2, 10);
          for (var i = 0; i < w.length; i++) {
            q = this.states.item(q).edges[w[i]] || q;
          }
          return q;
        },
        goPath: function LALR_goPath(p2, w) {
          var q = parseInt(p2, 10), t, path = [];
          for (var i = 0; i < w.length; i++) {
            t = w[i] ? q + ":" + w[i] : "";
            if (t) this.newg.nterms_[t] = q;
            path.push(t);
            q = this.states.item(q).edges[w[i]] || q;
            this.terms_[t] = w[i];
          }
          return { path, endState: q };
        },
        // every disjoint reduction of a nonterminal becomes a produciton in G'
        buildNewGrammar: function LALR_buildNewGrammar() {
          var self2 = this, newg = this.newg;
          this.states.forEach(function(state, i) {
            state.forEach(function(item) {
              if (item.dotPosition === 0) {
                var symbol = i + ":" + item.production.symbol;
                self2.terms_[symbol] = item.production.symbol;
                newg.nterms_[symbol] = i;
                if (!newg.nonterminals[symbol])
                  newg.nonterminals[symbol] = new Nonterminal(symbol);
                var pathInfo = self2.goPath(i, item.production.handle);
                var p2 = new Production(symbol, pathInfo.path, newg.productions.length);
                newg.productions.push(p2);
                newg.nonterminals[symbol].productions.push(p2);
                var handle = item.production.handle.join(" ");
                var goes = self2.states.item(pathInfo.endState).goes;
                if (!goes[handle])
                  goes[handle] = [];
                goes[handle].push(symbol);
              }
            });
            if (state.inadequate)
              self2.inadequateStates.push(i);
          });
        },
        unionLookaheads: function LALR_unionLookaheads() {
          var self2 = this, newg = this.newg, states = !!this.onDemandLookahead ? this.inadequateStates : this.states;
          states.forEach(function union_states_forEach(i) {
            var state = typeof i === "number" ? self2.states.item(i) : i, follows = [];
            if (state.reductions.length)
              state.reductions.forEach(function union_reduction_forEach(item) {
                var follows2 = {};
                for (var k = 0; k < item.follows.length; k++) {
                  follows2[item.follows[k]] = true;
                }
                state.goes[item.production.handle.join(" ")].forEach(function reduction_goes_forEach(symbol) {
                  newg.nonterminals[symbol].follows.forEach(function goes_follows_forEach(symbol2) {
                    var terminal = self2.terms_[symbol2];
                    if (!follows2[terminal]) {
                      follows2[terminal] = true;
                      item.follows.push(terminal);
                    }
                  });
                });
              });
          });
        }
      });
      var LALRGenerator = exports.LALRGenerator = lalr.construct();
      var lalrGeneratorDebug = {
        trace: function trace() {
          Jison.print.apply(null, arguments);
        },
        beforebuildNewGrammar: function() {
          this.trace(this.states.size() + " states.");
          this.trace("Building lookahead grammar.");
        },
        beforeunionLookaheads: function() {
          this.trace("Computing lookaheads.");
        }
      };
      var lrLookaheadGenerator = generator.beget(lookaheadMixin, lrGeneratorMixin, {
        afterconstructor: function lr_aftercontructor() {
          this.computeLookaheads();
          this.buildTable();
        }
      });
      var SLRGenerator = exports.SLRGenerator = lrLookaheadGenerator.construct({
        type: "SLR(1)",
        lookAheads: function SLR_lookAhead(state, item) {
          return this.nonterminals[item.production.symbol].follows;
        }
      });
      var lr1 = lrLookaheadGenerator.beget({
        type: "Canonical LR(1)",
        lookAheads: function LR_lookAheads(state, item) {
          return item.follows;
        },
        Item: lrGeneratorMixin.Item.prototype.construct({
          afterconstructor: function() {
            this.id = this.production.id + "a" + this.dotPosition + "a" + this.follows.sort().join(",");
          },
          eq: function(e) {
            return e.id === this.id;
          }
        }),
        closureOperation: function LR_ClosureOperation(itemSet) {
          var closureSet = new this.ItemSet();
          var self2 = this;
          var set = itemSet, itemQueue, syms = {};
          do {
            itemQueue = new Set();
            closureSet.concat(set);
            set.forEach(function(item) {
              var symbol = item.markedSymbol;
              var b, r;
              if (symbol && self2.nonterminals[symbol]) {
                r = item.remainingHandle();
                b = self2.first(item.remainingHandle());
                if (b.length === 0 || item.production.nullable || self2.nullable(r)) {
                  b = b.concat(item.follows);
                }
                self2.nonterminals[symbol].productions.forEach(function(production) {
                  var newItem = new self2.Item(production, 0, b);
                  if (!closureSet.contains(newItem) && !itemQueue.contains(newItem)) {
                    itemQueue.push(newItem);
                  }
                });
              } else if (!symbol) {
                closureSet.reductions.push(item);
              }
            });
            set = itemQueue;
          } while (!itemQueue.isEmpty());
          return closureSet;
        }
      });
      var LR1Generator = exports.LR1Generator = lr1.construct();
      var ll = generator.beget(lookaheadMixin, {
        type: "LL(1)",
        afterconstructor: function ll_aftercontructor() {
          this.computeLookaheads();
          this.table = this.parseTable(this.productions);
        },
        parseTable: function llParseTable(productions) {
          var table = {}, self2 = this;
          productions.forEach(function(production, i) {
            var row = table[production.symbol] || {};
            var tokens2 = production.first;
            if (self2.nullable(production.handle)) {
              Set.union(tokens2, self2.nonterminals[production.symbol].follows);
            }
            tokens2.forEach(function(token) {
              if (row[token]) {
                row[token].push(i);
                self2.conflicts++;
              } else {
                row[token] = [i];
              }
            });
            table[production.symbol] = row;
          });
          return table;
        }
      });
      var LLGenerator = exports.LLGenerator = ll.construct();
      Jison.Generator = function Jison_Generator(g, options) {
        var opt = typal.mix.call({}, g.options, options);
        switch (opt.type) {
          case "lr0":
            return new LR0Generator(g, opt);
          case "slr":
            return new SLRGenerator(g, opt);
          case "lr":
            return new LR1Generator(g, opt);
          case "ll":
            return new LLGenerator(g, opt);
          default:
            return new LALRGenerator(g, opt);
        }
      };
      return function Parser2(g, options) {
        var gen = Jison.Generator(g, options);
        return gen.createParser();
      };
    }();
  }
});

// src/compiler/grammar.mjs
var grammar_exports = {};
__export(grammar_exports, {
  parser: () => parser2
});
module.exports = __toCommonJS(grammar_exports);
var import_jison = __toESM(require_jison(), 1);
function iter$(a) {
  return a ? a.toArray ? a.toArray() : a : [];
}
var Parser = import_jison.default.Parser;
var unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
var o = function(patternString, action, options) {
  var match;
  patternString = patternString.replace(/\s{2,}/g, " ");
  var patternCount = patternString.split(" ").length;
  if (!action) {
    return [patternString, "$$ = $1;", options];
  }
  ;
  if (match = unwrap.exec(action)) {
    action = match[1];
  } else {
    action = "(" + action + "())";
  }
  ;
  action = action.replace(/\bA(\d+)/g, "$$$1");
  action = action.replace(/\bnew /g, "$&yy.");
  action = action.replace(/\b(?:Block\.wrap|extend)\b/g, "yy.$&");
  action = action.replace(/\bAST\b/g, "yy");
  return [patternString, "$$ = " + action + ";", options];
};
var grammar = {
  // The **Root** is the top-level node in the syntax tree. Since we parse bottom-up,
  // all parsing must end here.
  Root: [
    o("", function() {
      return new Root([]);
    }),
    o("Body", function() {
      return new Root(A1);
    }),
    o("Block TERMINATOR")
  ],
  // Any list of statements and expressions, separated by line breaks or semicolons.
  Body: [
    o("BODYSTART", function() {
      return new Block([]);
    }),
    o("Line", function() {
      return new Block([]).add(A1);
    }),
    // o 'HEADER Line' do Block.new([A2])
    // o 'LeadingTerminator' do Block.new([Terminator.new(A1)])
    o("Body Terminator Line", function() {
      return A1.break(A2).add(A3);
    }),
    // A3.prebreak(A2) # why not add as real nodes?!
    o("Body Terminator", function() {
      return A1.break(A2);
    })
  ],
  Terminator: [
    o("TERMINATOR", function() {
      return new Terminator(A1);
    })
  ],
  Type: [
    o("TYPE", function() {
      return new TypeAnnotation(A1);
    }),
    o("GENERICS", function() {
      return new Generics(A1);
    })
  ],
  // An indented block of expressions. Note that the [Rewriter](rewriter.html)
  // will convert some postfix forms into blocks for us, by adjusting the
  // token stream.
  Block: [
    o("EMPTY_BLOCK", function() {
      return new Block([]);
    }),
    o("INDENT OUTDENT", function() {
      return new Block([]).indented(A1, A2);
    }),
    o("INDENT Body OUTDENT", function() {
      return A2.indented(A1, A3);
    }),
    // hacky way to support terminators at the start of blocks
    o("INDENT TERMINATOR Body OUTDENT", function() {
      return A3.prebreak(A2).indented(A1, A4);
    }),
    o("INDENT TERMINATOR OUTDENT", function() {
      return new Block([]).indented(A1, A3);
    })
  ],
  // Block and statements, which make up a line in a body.
  Line: [
    o("CSSDeclaration"),
    o("Expression"),
    // ?
    o("VarDecl", function() {
      return A1.option("block", true);
    }),
    o("Comment"),
    o("Statement"),
    o("Decorators"),
    o("ImportDeclaration"),
    o("ExportDeclaration"),
    o("GLOBAL Line", function() {
      return AST.GLOBAL(A2, A1);
    }),
    o("DECLARE Line", function() {
      return AST.DECLARE(A2, A1);
    })
    // A2.set(declareOnly: A1)
  ],
  // Pure statements which cannot be expressions.
  Statement: [
    o("Return"),
    o("Yield"),
    o("Throw"),
    o("STATEMENT", function() {
      return new Literal(A1);
    }),
    o("BREAK", function() {
      return new BreakStatement(A1);
    }),
    o("BREAK CALL_START Expression CALL_END", function() {
      return new BreakStatement(A1, A3);
    }),
    o("CONTINUE", function() {
      return new ContinueStatement(A1);
    }),
    o("CONTINUE CALL_START Expression CALL_END", function() {
      return new ContinueStatement(A1, A3);
    }),
    o("DEBUGGER", function() {
      return new DebuggerStatement(A1);
    })
  ],
  ExtendObject: [
    // o 'CLASS ClassName ClassBody' do ClassDeclaration.new(A2, null, A3).set(keyword: A1)
    o("EXTEND Identifier ClassBody", function() {
      return new ExtendDeclaration(A2, null, A3).set({ instanceOnly: true, extension: A1 });
    })
  ],
  ExportDeclaration: [
    o("ENV_FLAG ExportDeclaration", function() {
      return A2.addEnv(A1);
    }),
    o("EXPORT { ImportSpecifierList }", function() {
      return new ExportNamedDeclaration(A1, [A3]).setEnds(A1, A4);
    }),
    o("EXPORT { ImportSpecifierList } FROM String", function() {
      return new ExportNamedDeclaration(A1, [A3], A6).setEnds(A1, A6);
    }),
    o("EXPORT EXPORT_ALL FROM String", function() {
      return new ExportAllDeclaration(A1, [new ExportAllSpecifier(A2)], A4).setEnds(A1, A4);
    }),
    o("EXPORT EXPORT_ALL AS Identifier FROM String", function() {
      return new ExportAllDeclaration(A1, [new ExportAllSpecifier(A2, A4)], A6).setEnds(A1, A6);
    }),
    o("EXPORT Exportable", function() {
      return new Export(A2).set({ keyword: A1 }).setEnds(A1, A2);
    }),
    o("EXPORT DEFAULT DefaultExportable", function() {
      return new Export(A3).set({ keyword: A1, "default": A2 }).setEnds(A1, A3);
    })
  ],
  Exportable: [
    o("MethodDeclaration"),
    o("Class"),
    o("CSSDeclaration"),
    o("TagDeclaration"),
    o("VarAssign"),
    o("GLOBAL Exportable", function() {
      return AST.GLOBAL(A2, A1);
    })
  ],
  DefaultExportable: [
    o("Expression"),
    o("GLOBAL Exportable", function() {
      return AST.GLOBAL(A2, A1);
    })
  ],
  ImportOrExport: [
    o("IMPORT"),
    o("EXPORT")
  ],
  ImportDefaultSpecifier: [
    o("Identifier", function() {
      return new ImportDefaultSpecifier(A1);
    })
  ],
  ImportDeclaration: [
    o("ENV_FLAG ImportDeclaration", function() {
      return A2.addEnv(A1);
    }),
    o("IMPORT String", function() {
      return new ImportDeclaration(A1, null, A2);
    }),
    o("IMPORT ImportDefaultSpecifier FROM String", function() {
      return new ImportDeclaration(A1, [A2], A4);
    }),
    o("IMPORT TYPEIMPORT ImportDefaultSpecifier FROM String", function() {
      return new ImportTypeDeclaration(A1, [A3], A5);
    }),
    o("IMPORT ImportNamespaceSpecifier FROM String", function() {
      return new ImportDeclaration(A1, [A2], A4);
    }),
    o("IMPORT { } FROM String", function() {
      return new ImportDeclaration(A1, null, A5);
    }),
    o("IMPORT { ImportSpecifierList } FROM String", function() {
      return new ImportDeclaration(A1, [A3], A6);
    }),
    o("IMPORT TYPEIMPORT { ImportSpecifierList } FROM String", function() {
      return new ImportTypeDeclaration(A1, [A4], A7);
    }),
    o("IMPORT ImportDefaultSpecifier IMPORT_COMMA ImportNamespaceSpecifier FROM String", function() {
      return new ImportDeclaration(A1, [A2, A4], A6);
    }),
    o("IMPORT ImportDefaultSpecifier IMPORT_COMMA { ImportSpecifierList } FROM String", function() {
      return new ImportDeclaration(A1, [A2, A5], A8);
    })
  ],
  ImportFrom: [
    o("STRING")
  ],
  ImportNamespaceSpecifier: [
    o("IMPORT_ALL AS Identifier", function() {
      return new ImportNamespaceSpecifier(new Literal(A1), A3);
    })
  ],
  ImportSpecifierList: [
    o("ImportSpecifier", function() {
      return new ESMSpecifierList([]).add(A1);
    }),
    o("ImportSpecifierList , ImportSpecifier", function() {
      return A1.add(A3);
    }),
    o("ImportSpecifierList OptComma TERMINATOR ImportSpecifier", function() {
      return A1.add(A4);
    }),
    o("INDENT ImportSpecifierList OptComma OUTDENT", function() {
      return A2;
    }),
    o("INDENT ImportSpecifierList OptComma TERMINATOR OUTDENT", function() {
      return A2;
    }),
    o("ImportSpecifierList OptComma INDENT ImportSpecifierList OptComma OUTDENT", function() {
      return A1.concat(A4);
    })
  ],
  ImportSpecifier: [
    o("Identifier", function() {
      return new ImportSpecifier(A1);
    }),
    o("DecoratorIdentifier", function() {
      return new ImportSpecifier(A1);
    }),
    o("StyleMixinIdentifier", function() {
      return new ImportSpecifier(A1);
    }),
    o("Identifier AS Identifier", function() {
      return new ImportSpecifier(A1, A3);
    }),
    o("DEFAULT", function() {
      return new ImportSpecifier(new Literal(A1));
    }),
    o("DEFAULT AS Identifier", function() {
      return new ImportSpecifier(new Literal(A1), A3);
    })
  ],
  Require: [
    o("REQUIRE RequireArg", function() {
      return new Require(A2).set({ keyword: A1 });
    })
  ],
  RequireArg: [
    o("Literal"),
    o("Parenthetical"),
    o("")
  ],
  // All the different types of expressions in our language. The basic unit of
  // Imba is the **Expression** -- everything that can be an expression
  // is one. Blocks serve as the building blocks of many other rules, making
  // them somewhat circular.
  Expression: [
    o("Await"),
    o("Value"),
    o("Code"),
    o("Operation"),
    o("Assign"),
    o("If"),
    o("Ternary"),
    o("Try"),
    o("While"),
    o("For"),
    o("Switch"),
    o("ExtendObject"),
    o("Class"),
    o("TagDeclaration"),
    o("Tag")
  ],
  ExpressionBlock: [
    o("Expression"),
    o("INDENT ExpressionBlock Outdent", function() {
      return A2.indented(A1, A3);
    })
  ],
  // A literal identifier, a variable name or property.
  Identifier: [
    o("IDENTIFIER", function() {
      return new Identifier(A1);
    })
  ],
  SymbolIdentifier: [
    o("SYMBOLID", function() {
      return new SymbolIdentifier(A1);
    }),
    o("# Interpolation", function() {
      return new InterpolatedSymbolIdentifier(A1, A2);
    })
  ],
  DecoratorIdentifier: [
    o("DECORATOR", function() {
      return new DecoratorIdentifier(A1);
    })
  ],
  StyleMixinIdentifier: [
    o("CSS_MIXIN", function() {
      return new MixinIdentifier(A1);
    })
  ],
  Key: [
    o("KEY", function() {
      return new Identifier(A1);
    })
  ],
  Argvar: [
    o("ARGVAR", function() {
      return new Argvar(A1).setEnds(A1, A1);
    })
  ],
  Symbol: [
    o("SYMBOL", function() {
      return new Symbol(A1);
    })
  ],
  Decorator: [
    o("DecoratorIdentifier", function() {
      return new Decorator(A1);
    }),
    // kinda hacky, should be defined as something else
    o("DecoratorIdentifier Arguments", function() {
      return new Decorator(A1).set({ params: A2 });
    }),
    // o 'DecoratorIdentifier ( ArgList )' do Decorator.new(A1).set(params: A3)
    o("Decorator . Identifier", function() {
      return A1.add(A3);
    })
  ],
  Decorators: [
    o("Decorator", function() {
      return [A1];
    }),
    o("Decorators Decorator", function() {
      return A1.concat(A2);
    })
  ],
  // Alphanumerics are separated from the other **Literal** matchers because
  // they can also serve as keys in object literals.
  AlphaNumeric: [
    o("NUMBER UNIT", function() {
      return new NumWithUnit(A1, A2);
    }),
    o("NUMBER", function() {
      return new Num(A1);
    }),
    o("STRING", function() {
      return new Str(A1);
    }),
    o("Symbol"),
    o("InterpolatedString")
  ],
  String: [
    o("STRING", function() {
      return new Str(A1);
    })
  ],
  InterpolatedString: [
    o("STRING_START", function() {
      return new InterpolatedString([], { open: A1 });
    }),
    o("InterpolatedString NEOSTRING", function() {
      return A1.add(A2);
    }),
    o("InterpolatedString Interpolation", function() {
      return A2 ? A1.add(A2) : A1;
    }),
    o("InterpolatedString STRING_END", function() {
      return A1.option("close", A2);
    })
  ],
  // The list of arguments to a function call.
  Interpolation: [
    o("{{ }}", function() {
      return null;
    }),
    o("{{ Expression }}", function() {
      return A2;
    })
  ],
  // All of our immediate values. Generally these can be passed straight
  // through and printed to JavaScript.
  Literal: [
    o("AlphaNumeric"),
    o("JS", function() {
      return new Literal(A1);
    }),
    o("REGEX", function() {
      return new RegExp(A1);
    }),
    o("BOOL", function() {
      return new Bool(A1);
    }),
    o("TRUE", function() {
      return new True(A1);
    }),
    // AST.TRUE # should not cheat like this
    o("FALSE", function() {
      return new False(A1);
    }),
    // AST.FALSE
    o("NULL", function() {
      return new Nil(A1);
    }),
    // AST.NIL
    o("UNDEFINED", function() {
      return new Undefined(A1);
    })
    // AST.UNDEFINED
    // we loose locations for these
  ],
  // A return statement from a function body.
  Return: [
    o("RETURN Expression", function() {
      return new Return(A2).set({ keyword: A1 });
    }),
    o("RETURN Arguments", function() {
      return new Return(A2).set({ keyword: A1 });
    }),
    // should probably force as array
    o("RETURN", function() {
      return new Return().set({ keyword: A1 });
    })
  ],
  Yield: [
    o("YIELD Expression", function() {
      return new Yield(A2).set({ keyword: A1 });
    }),
    o("YIELD Arguments", function() {
      return new Yield(A2).set({ keyword: A1 });
    }),
    // should probably force as array
    o("YIELD", function() {
      return new Yield().set({ keyword: A1 });
    })
  ],
  Selector: [
    o("SELECTOR_START", function() {
      return new Selector([], { type: A1, open: A1 });
    }),
    o("Selector SELECTOR_PART", function() {
      return A1.add(A2);
    }),
    o("Selector { Expression }", function() {
      return A1.add(A3);
    }),
    o("Selector SELECTOR_END", function() {
      return A1.option("close", A2);
    })
  ],
  Tag: [
    o("TAG_START TagOptions TAG_END", function() {
      return A2.setEnds({ open: A1, close: A3 }).setEnds(A1, A3);
    }),
    o("TAG_START TagOptions TAG_END TagBody", function() {
      return A2.set({ body: A4, open: A1, close: A3 });
    })
  ],
  TagTypeName: [
    o("Self", function() {
      return A1;
    }),
    o("IDENTIFIER", function() {
      return new TagTypeIdentifier(A1);
    }),
    o("TAG_TYPE", function() {
      return new TagTypeIdentifier(A1);
    }),
    o("TagIdentifier", function() {
      return new ExpressionNode(A1);
    }),
    o("", function() {
      return new TagTypeIdentifier("div");
    })
  ],
  StyleBlockDeclaration: [
    o("CSS CSS_SEL StyleBody CSS_END", function() {
      return new StyleRuleSet(A2, A3).set({ name: A1 });
    })
  ],
  CSSDeclaration: [
    // o 'GLOBAL CSS CSS_SEL StyleBody CSS_END' do StyleRuleSet.new(A3,A4).set(global: A1)
    o("StyleBlockDeclaration", function() {
      return A1.set({ toplevel: true });
    }),
    // o 'GLOBAL CSSDeclaration' do A2.set(global: A1)
    o("LOCAL CSSDeclaration", function() {
      return A2.set({ local: A1 });
    })
  ],
  StyleBlockBody: [
    o("INDENT Terminator OUTDENT", function() {
      return new StyleBody([]).indented(A1, A3);
    }),
    o("INDENT StyleBody Outdent", function() {
      return A2.indented(A1, A3);
    })
  ],
  OptStyleBody: [
    o("", function() {
      return new StyleBody([]);
    }),
    o("StyleBody")
  ],
  StyleBody: [
    o("StyleNode", function() {
      return new StyleBody([A1]);
    }),
    o("StyleBody StyleDeclaration", function() {
      return A1.add(A2);
    }),
    // o 'Style2Body , Style2Node' do A1.add A3
    o("StyleBody Terminator StyleNode", function() {
      return A1.add(A3);
    }),
    o("INDENT StyleBody Outdent", function() {
      return A2.indented(A1, A3);
    })
  ],
  StyleNode: [
    o("StyleDeclaration"),
    o("CSS_SEL StyleBlockBody CSS_END", function() {
      return new StyleRuleSet(A1, A2);
    })
  ],
  StyleDeclaration: [
    o("StyleProperty : StyleExpressions", function() {
      return new StyleDeclaration(A1, A3.set({ parens: false }));
    }),
    o("StyleProperty = StyleExpressions", function() {
      return new StyleDeclaration(A1, A3.set({ parens: false }));
    })
  ],
  StyleProperty: [
    o("CSSPROP", function() {
      return new StyleProperty([A1]);
    })
  ],
  StyleOperator: [
    o("MATH"),
    o("+"),
    o("-")
  ],
  StyleExpressions: [
    o("StyleExpression", function() {
      return new StyleExpressions([A1]);
    }),
    o("StyleExpressions , StyleExpression", function() {
      return A1.add(A3);
    })
  ],
  // the values
  StyleExpression: [
    o("StyleTerm", function() {
      return new StyleExpression().add(A1);
    }),
    o("StyleExpression StyleOperator", function() {
      return A1.add(A2);
    }),
    o("StyleExpression StyleTerm", function() {
      return A1.add(A2);
    }),
    o("StyleExpression / StyleTerm", function() {
      return A1.addParam(A3, A2);
    })
  ],
  StyleValue: [
    o("StyleTerm"),
    o("StyleOperation")
  ],
  StyleOperation: [
    o("StyleTerm StyleOperator StyleTerm", function() {
      return new StyleOperation([A1, A2, A3]);
    }),
    o("StyleOperation StyleOperator StyleTerm", function() {
      return A1.add([A2, A3]);
    })
  ],
  StyleFunctionArgs: [
    o("StyleFunctionArg", function() {
      return new StyleExpressions([A1]);
    }),
    o("StyleFunctionArgs , StyleFunctionArg", function() {
      return A1.add(A3);
    })
  ],
  StyleFunctionArg: [
    o("StyleTerm", function() {
      return new StyleExpression().add(A1);
    }),
    o("StyleFunctionArg StyleOperator", function() {
      return A1.add(A2);
    }),
    o("StyleFunctionArg StyleTerm", function() {
      return A1.add(A2);
    }),
    o("StyleFunctionArg / StyleTerm", function() {
      return A1.addParam(A3, A2);
    })
  ],
  StyleTermPlaceholder: [
    o("{ Expression }", function() {
      return new StyleInterpolationExpression(A2).setEnds(A1, A3);
    }),
    o("StyleTermPlaceholder CSSUNIT", function() {
      return A1.set({ unit: A2 });
    })
  ],
  StyleParens: [
    o("( StyleValue )", function() {
      return new StyleParens(A2).setEnds(A1, A3);
    }),
    o("StyleParens CSSUNIT", function() {
      return A1.set({ unit: A2 });
    })
  ],
  StyleColor: [
    o("COLOR", function() {
      return new StyleColor(A1);
    }),
    o("COLORMIX ( StyleFunctionArgs )", function() {
      return new StyleColorMix(A1, A3.setEnds(A2, A4)).set({ params: A3 }).setEnds(A1, A4);
    })
  ],
  StyleTerm: [
    o("StyleParens"),
    o("CSSVAR", function() {
      return new StyleVar(A1);
    }),
    o("DIMENSION", function() {
      return new StyleDimension(A1);
    }),
    // o 'COLOR ( StyleFunctionArgs )' do StyleColor.new(A1,A3).set(params: A3)
    o("StyleColor"),
    o("PERCENTAGE", function() {
      return new StyleDimension(A1);
    }),
    o("NUMBER", function() {
      return new StyleNumber(A1);
    }),
    o("String", function() {
      return A1;
    }),
    o("StyleTermPlaceholder", function() {
      return A1;
    }),
    o("CSSURL", function() {
      return new StyleURL(A1);
    }),
    o("CSSFUNCTION ( StyleFunctionArgs )", function() {
      return new StyleFunction(A1, A3.setEnds(A2, A4)).setEnds(A1, A4);
    }),
    o("CSSIDENTIFIER", function() {
      return new StyleIdentifier(A1);
    }),
    o("COMPARE StyleTerm", function() {
      return A2.set({ op: A1 });
    })
  ],
  TagOptions: [
    o("TagTypeName TAG_REF", function() {
      return new Tag({ type: A1, reference: A2 });
    }),
    o("TagTypeName", function() {
      return new Tag({ type: A1 });
    }),
    o("TagOptions TAG_ID", function() {
      return A1.addPart(A2, AST.TagId);
    }),
    o("TagOptions TAG_SYMBOL_ID", function() {
      return A1.addPart(new IdentifierExpression(A2.cloneSlice(1)), AST.TagId);
    }),
    o("TagOptions SYMBOL_ID", function() {
      return A1.addPart(new IdentifierExpression(A2.cloneSlice(1)), AST.TagId);
    }),
    o("TagOptions TAG_FLAG", function() {
      return A1.addPart(A2, AST.TagFlag);
    }),
    o("TagOptions TAG_ATTR", function() {
      return A1.addPart(A2, AST.TagAttr);
    }),
    o("TagOptions STYLE_START STYLE_END", function() {
      return A1;
    }),
    o("TagOptions STYLE_START StyleBody STYLE_END", function() {
      return A1.addPart(new StyleRuleSet(null, A3), AST.TagFlag);
    }),
    o("TagOptions T. STYLE_START StyleBody STYLE_END", function() {
      return A1.addPart(new StyleRuleSet(null, A4), AST.TagFlag);
    }),
    o("TagOptions CSS_MIXIN", function() {
      return A1.addPart(new MixinIdentifier(A2), AST.TagFlag);
    }),
    o("TagOptions T: TagIdentifier", function() {
      return A1.addPart(A3, AST.TagHandler);
    }),
    o("TagOptions T@ TagIdentifier", function() {
      return A1.addPart(A3, AST.TagHandler);
    }),
    o("TagOptions T. @ TAG_LITERAL", function() {
      return A1.addPart(A4.prepend("_"), AST.TagFlag);
    }),
    // not supported anymore
    o("TagOptions T. UNARY TAG_LITERAL", function() {
      return A1.addPart(A4.prepend("!"), AST.TagFlag);
    }),
    o("TagOptions T. TagIdentifier", function() {
      return A1.addPart(A3, AST.TagFlag);
    }),
    o("TagOptions # TagIdentifier", function() {
      return A1.addPart(A3, AST.TagId);
    }),
    o("TagOptions TAG_WS TagIdentifier", function() {
      return A1.addPart(A2, AST.TagSep).addPart(A3, AST.TagAttr);
    }),
    o("TagOptions ( )", function() {
      return A1.addPart(new ArgList([]), AST.TagArgList);
    }),
    o("TagOptions ( ArgList )", function() {
      return A1.addPart(A3, AST.TagArgList);
    }),
    o("TagOptions CALL_START CALL_END", function() {
      return A1.addPart(null, AST.TagArgList);
    }),
    o("TagOptions CALL_START ArgList CALL_END", function() {
      return A1.addPart(A3, AST.TagArgList);
    }),
    o("TagOptions TAG_WS", function() {
      return A1.addPart(A2, AST.TagSep);
    }),
    o("TagOptions Comment", function() {
      return A1;
    }),
    o("TagOptions TERMINATOR", function() {
      return A1;
    }),
    // o 'TagOptions TagFlag' do A1.addPart(A2)
    o("TagOptions = TagAttrValue", function() {
      return A1.addPart(A3, AST.TagAttrValue, A2);
    })
  ],
  TagIdentifier: [
    o("TAG_LITERAL", function() {
      return new IdentifierExpression(A1);
    }),
    o("{ Expression }", function() {
      return new IdentifierExpression(A2);
    }),
    o("TagIdentifier TAG_LITERAL", function() {
      return A1.add(A2);
    }),
    o("TagIdentifier { Expression }", function() {
      return A1.add(A3);
    })
    // o '{ Expression }' do TagIdentifier.new(A2)
  ],
  TagFlag: [
    o("%", function() {
      return new TagFlag();
    }),
    o("TagFlag TagPartIdentifier", function() {
      return A1.add(A2);
    })
  ],
  TagAttrValue: [
    o("VALUE_START Expression VALUE_END", function() {
      return A2;
    })
  ],
  TagBody: [
    o("INDENT OUTDENT", function() {
      return new TagBody([]).indented(A1, A2);
    }),
    o("INDENT TERMINATOR OUTDENT", function() {
      return new TagBody([]).indented(A1, A3);
    }),
    o("INDENT TagBodyList OUTDENT", function() {
      return A2.indented(A1, A3);
    }),
    o("CALL_START TagBodyList CALL_END", function() {
      return A2;
    }),
    o("Tag", function() {
      return new TagBody([A1]);
    })
  ],
  TagBodyList: [
    o("TagBodyItem", function() {
      return new TagBody([]).add(A1);
    }),
    o("TagBodyList , TagBodyItem", function() {
      return A1.add(A3);
    }),
    o("TagBodyList OptComma Terminator TagBodyItem", function() {
      return A1.add(A3).add(A4);
    }),
    o("TagBodyList OptComma TERMINATOR SEPARATOR Terminator TagBodyItem", function() {
      return A1.add(A5).add(A6);
    }),
    o("INDENT TagBodyList OptComma Outdent", function() {
      return A2.indented(A1, A4);
    }),
    o("TagBodyList OptComma INDENT TagBodyList OptComma Outdent", function() {
      return A1.concat(A4);
    })
  ],
  // Valid arguments are Blocks or Splats.
  TagBodyItem: [
    o("Expression"),
    o("... Expression", function() {
      return new Splat(A2).set({ keyword: A1 });
    }),
    o("Splat"),
    o("LOGIC"),
    o("Comment"),
    o("StyleBlockDeclaration", function() {
      return A1.set({ inTagTree: true });
    })
  ],
  // Class definitions have optional bodies of prototype property assignments,
  // and optional references to the superclass.
  TagDeclaration: [
    o("TagDeclarationBlock", function() {
      return A1;
    }),
    o("EXTEND TagDeclarationBlock", function() {
      return A2.set({ extension: true });
    }),
    o("LOCAL TagDeclarationBlock", function() {
      return A2.set({ local: true });
    })
    // o 'GLOBAL TagDeclarationBlock' do A2.set(global: A1)
  ],
  TagDeclarationBlock: [
    o("TAG TagType", function() {
      return new TagDeclaration(A2).set({ keyword: A1 });
    }),
    o("TAG TagType ClassBody", function() {
      return new TagDeclaration(A2, null, A3).set({ keyword: A1 });
    }),
    o("TAG TagType COMPARE TagType", function() {
      return new TagDeclaration(A2, A4).set({ keyword: A1, extends: A3 });
    }),
    o("TAG TagType COMPARE TagType ClassBody", function() {
      return new TagDeclaration(A2, A4, A5).set({ keyword: A1, extends: A3 });
    })
  ],
  // Going to move back to fewer custom tokens
  TagType: [
    o("TAG_TYPE", function() {
      return new TagTypeIdentifier(A1);
    })
  ],
  TagId: [
    o("# IDENTIFIER", function() {
      return new TagIdRef(A2);
    })
  ],
  // Assignment of a variable, property, or index to a value.
  Assign: [
    o("VarAssign"),
    o("Assignable = Expression", function() {
      return new Assign(A2, A1, A3).setEnds(A1, A3);
    }),
    o("Assignable = INDENT Expression Outdent", function() {
      return new Assign(A2, A1, A4.indented(A3, A5));
    })
  ],
  // Assignment when it happens within an object literal. The difference from
  // the ordinary **Assign** is that these allow numbers and strings as keys.
  AssignObj: [
    o("... Expression", function() {
      return new ObjRestAttr(A2).set({ spread: A1 });
    }),
    o("MethodDeclaration", function() {
      return A1.set({ inObject: true });
    }),
    o("ObjAssignable", function() {
      return new ObjAttr(A1);
    }),
    o("ObjAssignable : Expression", function() {
      return new ObjAttr(A1, A3);
    }),
    o("ObjAssignable : INDENT Expression Outdent", function() {
      return new ObjAttr(A1, A4.indented(A3, A5));
    }),
    o("SimpleObjAssignable = Expression", function() {
      return new ObjAttr(A1, null, A3);
    }),
    o("SimpleObjAssignable = INDENT Expression Outdent", function() {
      return new ObjAttr(A1, null, A4.indented(A3, A5));
    }),
    o("Comment")
  ],
  SimpleObjAssignable: [
    o("Identifier"),
    o("Identifier Type", function() {
      return AST.SETTYPE(A1, A2);
    }),
    o("SymbolIdentifier"),
    o("Key")
  ],
  ObjAssignable: [
    o("SimpleObjAssignable"),
    // this is the interpolated string
    o("[ Expression ]", function() {
      return new IdentifierExpression(A2);
    }),
    o("( Expression )", function() {
      return new IdentifierExpression(A2);
    }),
    o("AlphaNumeric")
  ],
  // A block comment.
  Comment: [
    o("HERECOMMENT", function() {
      return new Comment(A1, true);
    }),
    o("COMMENT", function() {
      return new Comment(A1, false);
    })
  ],
  // The **Code** node is the function literal. It's defined by an indented block
  // of **Block** preceded by a function arrow, with an optional parameter
  // list.
  Code: [
    o("Method"),
    o("Do"),
    o("Begin")
  ],
  Begin: [
    o("BEGIN Block", function() {
      return new Begin(A2);
    })
  ],
  Do: [
    o("DO Block", function() {
      return new Lambda([], A2, null, null, { bound: true, keyword: A1 });
    }),
    o("DO BLOCK_PARAM_START ParamList BLOCK_PARAM_END Block", function() {
      return new Lambda(A3, A5, null, null, { bound: true, keyword: A1 });
    })
  ],
  // FIXME clean up method
  Method: [
    o("MethodDeclaration", function() {
      return A1;
    }),
    // o 'GLOBAL MethodDeclaration' do A2.set(global: A1)
    o("STATIC MethodDeclaration", function() {
      return A2.set({ static: A1 });
    })
  ],
  MethodDeclaration: [
    o("DEF MethodScope MethodScopeType MethodIdentifier MethodParams MethodBody", function() {
      return new MethodDeclaration(A5, A6, A4, A2, A3).set({ def: A1, keyword: A1, datatype: A4.option("datatype") });
    }),
    o("DEF MethodIdentifier MethodParams MethodBody", function() {
      return new MethodDeclaration(A3, A4, A2, null).set({ def: A1, keyword: A1, datatype: A2.option("datatype") });
    })
  ],
  MethodParams: [
    o("ParamList", function() {
      return A1;
    }),
    o("CALL_START ParamList CALL_END", function() {
      return A2;
    })
  ],
  MethodScopeType: [
    o(".", function() {
      return { static: true };
    }),
    o("#", function() {
      return {};
    })
  ],
  MethodIdentifier: [
    o("Identifier"),
    o("DecoratorIdentifier"),
    o("SymbolIdentifier", function() {
      return A1.set({ as: "property" });
    }),
    // InterpolatedIdentifier.new(A1)
    o("[ Expression ]", function() {
      return new InterpolatedIdentifier(A2);
    }),
    o("MethodIdentifier Type", function() {
      return AST.SETTYPE(A1, A2);
    })
  ],
  MethodBody: [
    o("DEF_BODY Block", function() {
      return A2;
    }),
    o("DEF_BODY DO Block", function() {
      return A3;
    }),
    o("DEF_EMPTY", function() {
      return new Block([]).set({ end: A1._loc });
    })
  ],
  // should support much more
  MethodScope: [
    o("MethodIdentifier"),
    o("This"),
    o("Self")
  ],
  // An optional, trailing comma.
  OptComma: [
    o(""),
    o(",")
  ],
  OptSemicolon: [
    o(""),
    o(";")
  ],
  // The list of parameters that a function accepts can be of any length.
  ParamList: [
    o("", function() {
      return [];
    }),
    o("Param", function() {
      return [A1];
    }),
    o("ParamList , Param", function() {
      return A1.concat(A3);
    })
  ],
  ParamExpression: [
    o("Value"),
    o("Code"),
    o("Operation"),
    o("Assign"),
    o("Ternary"),
    o("Tag")
  ],
  ParamValue: [
    o("Expression")
    // o 'Expression'
    // o 'Parenthetical'
    // o 'Operation'
    // o 'Assign'
    // o 'Ternary'
    // o 'Tag'
  ],
  // A single parameter in a function definition can be ordinary, or a splat
  // that hoovers up the remaining arguments.
  Param: [
    o("Object", function() {
      return new Param(A1);
    }),
    o("Array", function() {
      return new Param(A1);
    }),
    o("ParamVar"),
    // do RequiredParam.new A1
    o("... ParamVar", function() {
      return A2.set({ splat: A1 });
    }),
    // BlockParam.new A2, null, A1
    o("BLOCK_ARG ParamVar", function() {
      return A2.set({ blk: A1 });
    }),
    // BlockParam.new A2, null, A1
    o("ParamVar = ParamValue", function() {
      return new Param(A1.value(), A3).set({ datatype: A1.option("datatype") });
    }),
    o("Object = ParamValue", function() {
      return new Param(A1, A3);
    }),
    o("Array = ParamValue", function() {
      return new Param(A1, A3);
    }),
    o("...", function() {
      return new RestParam(A1);
    })
  ],
  // Function Parameters
  ParamVar: [
    o("Identifier", function() {
      return new Param(A1);
    }),
    o("Identifier Type", function() {
      return AST.SETTYPE(new Param(A1), A2);
    })
  ],
  // A splat that occurs outside of a parameter list.
  Splat: [
    o("SPLAT Expression", function() {
      return AST.SPLAT(A2);
    })
  ],
  GlobalDeclaration: [
    o("GLOBAL GlobalAssignable = Expression", function() {
      return new GlobalDeclaration(A2, A4).set({ keyword: A1, op: A3 });
    }),
    o("GLOBAL GlobalAssignable", function() {
      return new GlobalDeclaration(A2).set({ keyword: A1 });
    })
    // o 'GlobalDeclaration = Expression' do A1.set(op: A2, value: A3)
  ],
  GlobalAssignable: [
    o("Identifier"),
    o("Identifier Type", function() {
      return AST.SETTYPE(A1, A2);
    })
  ],
  VarKeyword: [
    o("VAR"),
    o("LET"),
    o("CONST")
  ],
  VarAssignable: [
    o("Identifier"),
    o("Identifier Type", function() {
      return AST.SETTYPE(A1, A2);
    }),
    o("Array"),
    // all kinds?
    o("Object")
    // not supported anymore
  ],
  VarDecl: [
    o("VarKeyword VarAssignable", function() {
      return new VarReference(A2, A1);
    }),
    o("STATIC VarDecl", function() {
      return A2.set({ static: A1 });
    })
  ],
  VarAssign: [
    o("VarDecl = Expression", function() {
      return new Assign(A2, A1, A3);
    }),
    o("VarDecl = INDENT Expression Outdent", function() {
      return new Assign(A2, A1, A4.indented(A3, A5));
    })
  ],
  // Variables and properties that can be assigned to.
  SimpleAssignable: [
    o("ENV_FLAG", function() {
      return new EnvFlag(A1);
    }),
    o("Argvar"),
    o("Self"),
    // not sure if self should be assignable really
    o("Identifier", function() {
      return new VarOrAccess(A1);
    }),
    // LocalIdentifier.new(A1)
    o("SymbolIdentifier", function() {
      return new Access(".", null, A1);
    }),
    // LocalIdentifier.new(A1)
    o("Access"),
    // FIXME this isn really assignable?
    // o 'Value . NEW' do LegacyNew.new(A1).set(keyword: A3)
    // o 'Value . Super' do SuperAccess.new('.',A1,A3)
    o("SimpleAssignable Type", function() {
      return AST.SETTYPE(A1, A2);
    })
  ],
  Access: [
    o("Value SoakableOp Identifier", function() {
      return AST.OP(A2, A1, A3);
    }),
    // PropertyAccess.new(A2,A1,A3) # TODO change to regular access
    o("Value SoakableOp SymbolIdentifier", function() {
      return new IndexAccess(A2, A1, A3);
    }),
    // AST.OP(A2,A1,A3) # PropertyAccess.new(A2,A1,A3) # TODO change to regular access
    o("Value INDEX_START IndexValue INDEX_END", function() {
      return new IndexAccess(".", A1, A3.setEnds(A2, A4));
    }),
    o("Value ?. [ IndexValue ]", function() {
      return AST.OP(A2, A1, A4);
    })
  ],
  SoakableOp: [
    ".",
    "?."
  ],
  Super: [
    o("SUPER", function() {
      return new Super(A1);
    })
  ],
  // Everything that can be assigned to.
  Assignable: [
    o("SimpleAssignable"),
    o("Array"),
    //  do A1
    o("Object")
    // not supported anymore
  ],
  TaggedTemplate: [
    o("SimpleAssignable InterpolatedString", function() {
      return new TaggedTemplate(A1, A2);
    }),
    o("SimpleAssignable String", function() {
      return new TaggedTemplate(A1, A2);
    })
  ],
  Await: [
    o("AWAIT Expression", function() {
      return new Await(A2).set({ keyword: A1 });
    })
  ],
  // The types of things that can be treated as values -- assigned to, invoked
  // as functions, indexed into, named as a class, etc.
  Value: [
    o("Assignable"),
    o("Super"),
    o("Literal"),
    o("Literal Type", function() {
      return AST.SETTYPE(A1, A2);
    }),
    o("Parenthetical"),
    o("Range"),
    o("ARGUMENTS", function() {
      return AST.ARGUMENTS;
    }),
    o("This"),
    o("TagId"),
    o("Selector"),
    o("Invocation"),
    o("TaggedTemplate"),
    o("Require"),
    o("AMPER_REF", function() {
      return new AmperRef(A1);
    }),
    // TODO Makes no sense that this is not more specific
    o("Value BANG", function() {
      return new BangCall(A1).set({ keyword: A2 });
    })
  ],
  IndexValue: [
    o("Expression", function() {
      return new Index(A1);
    })
  ],
  // In Imba, an object literal is simply a list of assignments.
  Object: [
    o("{ AssignList OptComma }", function() {
      return new Obj(A2, A1.generated).setEnds(A1, A4);
    })
  ],
  // Assignment of properties within an object literal can be separated by
  // comma, as in JavaScript, or simply by newline.
  AssignList: [
    o("", function() {
      return new AssignList([]);
    }),
    o("AssignObj", function() {
      return new AssignList([A1]);
    }),
    o("AssignList , AssignObj", function() {
      return A1.add(A3);
    }),
    o("AssignList OptComma Terminator AssignObj", function() {
      return A1.add(A3).add(A4);
    }),
    // A4.prebreak(A3)
    o("AssignList OptComma INDENT AssignList OptComma Outdent", function() {
      return A1.concat(A4.indented(A3, A6));
    })
  ],
  ExpressionList: [
    o("Expression", function() {
      return new ExpressionList([]).add(A1);
    }),
    o("ExpressionList , Expression", function() {
      return A1.add(A3);
    }),
    o("ExpressionList OptComma Terminator Expression", function() {
      return A1.add(A3).add(A4);
    }),
    o("INDENT ExpressionList OptComma Outdent", function() {
      return A2.indented(A1, A4);
    }),
    o("ExpressionList OptComma INDENT ExpressionList OptComma Outdent", function() {
      return A1.concat(A4);
    })
  ],
  // Class definitions have optional bodies of prototype property assignments,
  // and optional references to the superclass.
  // might as well handle this in the lexer instead
  Class: [
    o("ClassStart", function() {
      return A1;
    }),
    o("ABSTRACT ClassStart", function() {
      return A2.set({ abstract: A1 });
    }),
    o("EXTEND ClassStart", function() {
      return A2.set({ extension: A1 });
    })
  ],
  ClassStart: [
    // o 'CLASS ClassName ClassConstructorParams ClassBody' do ClassDeclaration.new(A2, null, A4).set(keyword: A1,params: A3)
    // o 'CLASS ClassName ClassConstructorParams' do ClassDeclaration.new(A2, null, []).set(keyword: A1,params: A3)
    o("CLASS ClassName ClassBody", function() {
      return new ClassDeclaration(A2, null, A3).set({ keyword: A1 });
    }),
    o("CLASS ClassName", function() {
      return new ClassDeclaration(A2, null, []).set({ keyword: A1 });
    }),
    o("CLASS ClassBody", function() {
      return new ClassDeclaration(null, null, A2).set({ keyword: A1 });
    }),
    // o 'CLASS ClassName ClassConstructorParams COMPARE Expression ClassBody' do ClassDeclaration.new(A2, A5, A6).set(keyword: A1, params: A3)
    // o 'CLASS ClassName ClassConstructorParams COMPARE Expression' do ClassDeclaration.new(A2, A6, []).set(keyword: A1, params: A3)
    o("CLASS ClassName COMPARE Expression", function() {
      return new ClassDeclaration(A2, A4, []).set({ keyword: A1, extends: A3 });
    }),
    o("CLASS ClassName COMPARE Expression ClassBody", function() {
      return new ClassDeclaration(A2, A4, A5).set({ keyword: A1, extends: A3 });
    }),
    o("CLASS COMPARE Expression ClassBody", function() {
      return new ClassDeclaration(null, A3, A4).set({ keyword: A1, extends: A2 });
    })
  ],
  Class2: [
    o("CLASS ClassStart", function() {
      return A2.set({ keyword: A1 });
    }),
    o("ABSTRACT Class", function() {
      return A2.set({ abstract: A1 });
    }),
    o("EXTEND Class", function() {
      return A2.set({ extension: A1 });
    })
  ],
  ClassStart2: [
    // o 'CLASS ClassName ClassConstructorParams ClassBody' do ClassDeclaration.new(A2, null, A4).set(keyword: A1,params: A3)
    // o 'CLASS ClassName ClassConstructorParams' do ClassDeclaration.new(A2, null, []).set(keyword: A1,params: A3)
    o("ClassName ClassBody", function() {
      return new ClassDeclaration(A1, null, A2);
    }),
    o("ClassName", function() {
      return new ClassDeclaration(A1, null, []);
    }),
    o("ClassBody", function() {
      return new ClassDeclaration(null, null, A1);
    }),
    // o 'CLASS ClassName ClassConstructorParams COMPARE Expression ClassBody' do ClassDeclaration.new(A2, A5, A6).set(keyword: A1, params: A3)
    // o 'CLASS ClassName ClassConstructorParams COMPARE Expression' do ClassDeclaration.new(A2, A6, []).set(keyword: A1, params: A3)
    o("ClassName COMPARE Expression", function() {
      return new ClassDeclaration(A1, A3, []).set({ extends: A2 });
    }),
    o("ClassName COMPARE Expression ClassBody", function() {
      return new ClassDeclaration(A1, A3, A4).set({ extends: A2 });
    }),
    o("COMPARE Expression ClassBody", function() {
      return new ClassDeclaration(null, A2, A3).set({ extends: A1 });
    })
  ],
  ClassName: [
    o("DecoratorIdentifier"),
    o("Identifier", function() {
      return new VarOrAccess(A1);
    }),
    // do ClassName.new(A1)
    o("SymbolIdentifier", function() {
      return new Access(".", null, A1);
    }),
    // IndexAccess.new(A2,A1,A3) # AST.OP(A2,A1,A3)
    o("ClassName . Identifier", function() {
      return AST.OP(A2, A1, A3);
    }),
    o("ClassName . SymbolIdentifier", function() {
      return new IndexAccess(A2, A1, A3);
    }),
    // AST.OP(A2,A1,A3)
    o("ClassName Type", function() {
      return AST.SETTYPE(A1, A2);
    })
  ],
  ClassBody: [
    o("INDENT OUTDENT", function() {
      return new ClassBody([]).indented(A1, A2);
    }),
    o("INDENT ClassBodyBlock OUTDENT", function() {
      return A2.indented(A1, A3);
    }),
    o("INDENT TERMINATOR ClassBodyBlock OUTDENT", function() {
      return A3.prebreak(A2).indented(A1, A4);
    }),
    o("INDENT TERMINATOR OUTDENT", function() {
      return new ClassBody([]).indented(A1, A3);
    })
  ],
  ClassBodyBlock: [
    o("ClassBodyLine", function() {
      return new ClassBody([]).add(A1);
    }),
    o("ClassBodyBlock Terminator ClassBodyLine", function() {
      return A1.break(A2).add(A3);
    }),
    o("ClassBodyBlock Terminator", function() {
      return A1.break(A2);
    })
  ],
  ClassBodyLine: [
    o("Decorators"),
    o("ClassDeclLine"),
    o("Decorators ClassDeclLine", function() {
      return A1.concat([A2]);
    }),
    o("CSSDeclaration"),
    o("RELATION ClassName", function() {
      return new ClassRelation(A2).set({ keyword: A1 });
    }),
    o("Comment"),
    o("Tag")
  ],
  ClassDeclLine: [
    o("STATIC ClassFieldDeclaration", function() {
      return A2.set({ static: A1 });
    }),
    o("STATIC MethodDeclaration", function() {
      return A2.set({ static: A1 });
    }),
    o("MethodDeclaration"),
    o("ClassFieldDeclaration"),
    o("PROTECTED ClassDeclLine", function() {
      return A2.set({ protected: A1 });
    }),
    o("DECLARE ClassDeclLine", function() {
      return AST.DECLARE(A2, A1);
    }),
    o("ENV_FLAG ClassDeclLine", function() {
      return A2.addEnv(A1);
    })
  ],
  ClassFieldDeclaration: [
    o("ClassField ClassFieldOp Expression", function() {
      return A1.set({ value: A3, op: A2 });
    }),
    // ClassField.new(A1, A3)
    o("ClassField", function() {
      return A1;
    }),
    o("ClassFieldDeclaration AS AccessorBody", function() {
      return A1.set({ wrapper: A3 });
    }),
    o("ClassFieldDeclaration FieldDescriptorFull", function() {
      return A1.set({ wrapper: A2 });
    })
  ],
  FieldDescriptor: [
    o("DECORATOR", function() {
      return new Descriptor(A1);
    }),
    // kinda hacky, should be defined as something else
    o("@ CALL_START Expression CALL_END", function() {
      return new Descriptor(A3);
    }),
    // o 'FieldDescriptor ( )' do A1.add(ArgList.new([]))
    // o 'FieldDescriptor ( ArgList )' do A1.add(A3,'!')
    o("FieldDescriptor Arguments", function() {
      return A1.add(A2, "!");
    }),
    o("FieldDescriptor INDEX_START ArgList INDEX_END", function() {
      return A1.add(A3, "=");
    }),
    o("FieldDescriptor . Identifier", function() {
      return A1.add(A3);
    })
    // o 'FieldDescriptor = Value' do A1.add(A3,'value')
    // o 'FieldDescriptor = DescriptorValue' do A1.add(A3,'value')
  ],
  FieldDescriptorFull: [
    o("FieldDescriptor"),
    o("FieldDescriptor = Expression", function() {
      return A1.set({ "default": A3 });
    }),
    o("FieldDescriptor Do", function() {
      return A1.set({ callback: A2 });
    })
  ],
  AccessorBody: [
    "FieldDescriptorFull",
    "Value"
  ],
  ClassFieldDecoration: [
    o("ClassFieldDeclaration @ WatchBody", function() {
      return A1.set({ watch: A3 });
    })
  ],
  WatchBody: [
    o("Block"),
    o("Expression")
  ],
  ClassFieldOp: [
    "=",
    "COMPOUND_ASSIGN"
  ],
  ClassField: [
    o("ClassFieldIdentifier", function() {
      return new ClassField(A1);
    }),
    o("PROP ClassFieldIdentifier", function() {
      return new ClassProperty(A2).set({ keyword: A1 });
    }),
    o("ATTR ClassFieldIdentifier", function() {
      return new ClassAttribute(A2).set({ keyword: A1 });
    }),
    o("ClassField Type", function() {
      return AST.SETTYPE(A1, A2);
    }),
    o("ClassField CALL_START CALL_END", function() {
      return A1.set({ controller: A2 });
    })
  ],
  ClassFieldIdentifier: [
    o("Identifier"),
    o("REGEX", function() {
      return new RegExpIdentifier(A1);
    }),
    o("SymbolIdentifier")
  ],
  ClassFieldBody: [
    o("WATCH Expression Terminator", function() {
      return [A1, A2];
    })
  ],
  // Ordinary function invocation, or a chained series of calls.
  Invocation: [
    o("Value OptFuncExist Arguments", function() {
      return new Call(A1, A3, A2);
    }),
    o("Value Do", function() {
      return A1.addBlock(A2);
    })
  ],
  // An optional existence check on a function.
  OptFuncExist: [
    o("", function() {
      return false;
    }),
    o("FUNC_EXIST", function() {
      return true;
    })
  ],
  // The list of arguments to a function call.
  Arguments: [
    o("CALL_START CALL_END", function() {
      return new ArgList([]).setEnds(A1, A2);
    }),
    o("CALL_START ArgList OptComma CALL_END", function() {
      return A2.setEnds(A1, A4);
    })
  ],
  // A reference to the *this* current object.
  This: [
    o("THIS", function() {
      return new This(A1);
    })
    // Value.new Literal.new 'this'
  ],
  Self: [
    o("SELF", function() {
      return new Self(A1);
    })
  ],
  // The array literal.
  Array: [
    o("[ ]", function() {
      return new Arr(new ArgList([])).setEnds(A1, A2);
    }),
    o("[ ArgList OptComma ]", function() {
      return new Arr(A2).setEnds(A1, A4);
    }),
    o("Array Type", function() {
      return AST.SETTYPE(A1, A2);
    })
  ],
  // Inclusive and exclusive range dots.
  // should return the tokens instead
  RangeDots: [
    o("..", function() {
      return "..";
    }),
    o("...", function() {
      return "...";
    })
  ],
  Range: [
    o("[ Expression RangeDots Expression ]", function() {
      return AST.OP(A3, A2, A4);
    })
    // Range.new A2, A4, A3
  ],
  // The **ArgList** is both the list of objects passed into a function call,
  // as well as the contents of an array literal
  // (i.e. comma-separated expressions). Newlines work as well.
  ArgList: [
    o("Arg", function() {
      return new ArgList([A1]);
    }),
    o("ArgList , Arg", function() {
      return A1.add(A3);
    }),
    o("ArgList OptComma Terminator Arg", function() {
      return A1.add(A3).add(A4);
    }),
    o("ArgList OptComma TERMINATOR SEPARATOR Terminator Arg", function() {
      return A1.add(A5).add(A6);
    }),
    o("INDENT ArgList OptComma Outdent", function() {
      return A2.indented(A1, A4);
    }),
    o("ArgList OptComma INDENT ArgList OptComma Outdent", function() {
      return A1.concat(A4);
    })
  ],
  Outdent: [
    o("Terminator OUTDENT", function() {
      return A1;
    }),
    // we are going to change how this works
    o("OUTDENT", function() {
      return A1;
    })
  ],
  // Valid arguments are Blocks or Splats.
  Arg: [
    o("Expression"),
    o("... Expression", function() {
      return new Splat(A2).set({ keyword: A1 });
    }),
    o("Splat"),
    o("DO_PLACEHOLDER", function() {
      return new DoPlaceholder(A1);
    }),
    o("Comment")
  ],
  // Just simple, comma-separated, required arguments (no fancy syntax). We need
  // this to be separate from the **ArgList** for use in **Switch** blocks, where
  // having the newlines wouldn't make sense.
  SimpleArgs: [
    o("Expression"),
    o("SimpleArgs , Expression", function() {
      return [].concat(A1, A3);
    })
  ],
  // The variants of *try/catch/finally* exception handling blocks.
  Try: [
    o("TRY Block", function() {
      return new Try(A2);
    }),
    o("TRY Block Catch", function() {
      return new Try(A2, A3);
    }),
    o("TRY Block Finally", function() {
      return new Try(A2, null, A3);
    }),
    o("TRY Block Catch Finally", function() {
      return new Try(A2, A3, A4);
    })
  ],
  Finally: [
    o("FINALLY Block", function() {
      return new Finally(A2);
    })
  ],
  // A catch clause names its error and runs a block of code.
  Catch: [
    o("CATCH CATCH_VAR Block", function() {
      return new Catch(A3, A2);
    }),
    o("CATCH Block", function() {
      return new Catch(A2, null);
    })
    // o 'CATCH CATCH_VAR Expression' do Catch.new(A3,A2)
  ],
  // Throw an exception object.
  Throw: [
    o("THROW Expression", function() {
      return new Throw(A2);
    })
  ],
  // Parenthetical expressions. Note that the **Parenthetical** is a **Value**,
  // not an **Expression**, so if you need to use an expression in a place
  // where only values are accepted, wrapping it in parentheses will always do
  // the trick.
  Parenthetical: [
    o("( ExpressionList )", function() {
      return new Parens(A2, A1, A3);
    }),
    o("( ExpressionList ) UNIT", function() {
      return new ExpressionWithUnit(new Parens(A2, A1, A3), A4);
    }),
    o("Parenthetical Type", function() {
      return AST.SETTYPE(A1, A2);
    })
    // o '( INDENT ExpressionList OUTDENT )' do Parens.new(A3,A1,A5)
  ],
  // The condition portion of a while loop.
  WhileSource: [
    o("WHILE Expression", function() {
      return new While(A2, { keyword: A1 });
    }),
    o("WHILE Expression WHEN Expression", function() {
      return new While(A2, { guard: A4, keyword: A1 });
    }),
    o("UNTIL Expression", function() {
      return new While(A2, { invert: true, keyword: A1 });
    }),
    o("UNTIL Expression WHEN Expression", function() {
      return new While(A2, { invert: true, guard: A4, keyword: A1 });
    })
  ],
  // The while loop can either be normal, with a block of expressions to execute,
  // or postfix, with a single expression. There is no do..while.
  // should be solved by POST_WHILE instead
  While: [
    o("WhileSource Block", function() {
      return A1.addBody(A2);
    }),
    o("Statement  WhileSource", function() {
      return A2.addBody(Block.wrap([A1]));
    }),
    o("Expression WhileSource", function() {
      return A2.addBody(Block.wrap([A1]));
    }),
    o("Loop", function() {
      return A1;
    })
  ],
  // should deprecate
  Loop: [
    o("LOOP Block", function() {
      return new While(new Literal("true", { keyword: A1 })).addBody(A2);
    }),
    o("LOOP Expression", function() {
      return new While(new Literal("true", { keyword: A1 })).addBody(Block.wrap([A2]));
    })
  ],
  // Array, object, and range comprehensions, at the most generic level.
  // Comprehensions can either be normal, with a block of expressions to execute,
  // or postfix, with a single expression.
  For: [
    o("Statement  ForBody", function() {
      return A2.addBody([A1]);
    }),
    o("Expression ForBody", function() {
      return A2.addBody([A1]);
    }),
    o("ForBody    Block", function() {
      return A1.addBody(A2);
    }),
    o("ForBody    Block ELSE Block", function() {
      return A1.addBody(A2).addElse(A4);
    })
  ],
  ForKeyword: [
    o("FOR"),
    o("POST_FOR")
  ],
  ForBody: [
    o("ForKeyword Range", function() {
      return { source: new ValueNode(A2) };
    }),
    o("ForStart ForSource", function() {
      return A2.configure({ own: A1.own, await: A1.await, name: A1[0], index: A1[1], keyword: A1.keyword, params: A1 });
    })
  ],
  ForStart: [
    o("ForKeyword ForVariables", function() {
      return (A2.keyword = A1) && A2;
    }),
    // should link to the actual keyword instead
    o("ForKeyword AWAIT ForVariables", function() {
      return (A3.await = A2) && (A3.keyword = A1) && A3;
    }),
    o("ForKeyword OWN ForVariables", function() {
      return (A3.own = true) && (A3.keyword = A1) && A3;
    })
  ],
  // An array of all accepted values for a variable inside the loop.
  // This enables support for pattern matching.
  ForValue: [
    o("Identifier"),
    o("Identifier Type", function() {
      return AST.SETTYPE(A1, A2);
    }),
    o("Array"),
    // do ValueNode.new A1
    o("Object")
    // do ValueNode.new A1
  ],
  // An array or range comprehension has variables for the current element
  // and (optional) reference to the current index. Or, *key, value*, in the case
  // of object comprehensions.
  ForVariables: [
    o("ForValue", function() {
      return [A1];
    }),
    o("ForValue , ForValue", function() {
      return [A1, A3];
    }),
    o("ForValue , ForValue , ForValue", function() {
      return [A1, A3, A5];
    })
  ],
  // The source of a comprehension is an array or object with an optional guard
  // clause. If it's an array comprehension, you can also choose to step through
  // in fixed-size increments.
  ForSource: [
    o("FORIN Expression", function() {
      return new ForIn({ source: A2 });
    }),
    o("FOROF Expression", function() {
      return new ForOf({ source: A2, object: true });
    }),
    o("FORIN Expression WHEN Expression", function() {
      return new ForIn({ source: A2, guard: A4 });
    }),
    o("FOROF Expression WHEN Expression", function() {
      return new ForOf({ source: A2, guard: A4, object: true });
    }),
    o("FORIN Expression BY Expression", function() {
      return new ForIn({ source: A2, step: A4 });
    }),
    o("FORIN Expression WHEN Expression BY Expression", function() {
      return new ForIn({ source: A2, guard: A4, step: A6 });
    }),
    o("FORIN Expression BY Expression WHEN Expression", function() {
      return new ForIn({ source: A2, step: A4, guard: A6 });
    })
  ],
  Switch: [
    o("SWITCH Expression INDENT Whens OUTDENT", function() {
      return new Switch(A2, A4);
    }),
    o("SWITCH Expression INDENT Whens ELSE Block Outdent", function() {
      return new Switch(A2, A4, A6);
    }),
    o("SWITCH INDENT Whens OUTDENT", function() {
      return new Switch(null, A3);
    }),
    o("SWITCH INDENT Whens ELSE Block OUTDENT", function() {
      return new Switch(null, A3, A5);
    })
  ],
  Whens: [
    o("When"),
    o("Whens When", function() {
      return A1.concat(A2);
    })
  ],
  // An individual **When** clause, with action.
  When: [
    o("LEADING_WHEN SimpleArgs Block", function() {
      return [new SwitchCase(A2, A3)];
    }),
    o("LEADING_WHEN SimpleArgs Block TERMINATOR", function() {
      return [new SwitchCase(A2, A3)];
    })
  ],
  // The most basic form of *if* is a condition and an action. The following
  // if-related rules are broken up along these lines in order to avoid
  // ambiguity.
  IfBlock: [
    o("IF Expression Block", function() {
      return new If(A2, A3, { type: A1 });
    }),
    o("IfBlock ELSE IF Expression Block", function() {
      return A1.addElse(new If(A4, A5, { type: A3 }));
    }),
    // seems like this refers to the wrong blocks no?
    o("IfBlock ELIF Expression Block", function() {
      return A1.addElse(new If(A3, A4, { type: A2 }));
    }),
    o("IfBlock ELSE Block", function() {
      return A1.addElse(A3.set({ keyword: A2 }));
    })
  ],
  // The full complement of *if* expressions, including postfix one-liner
  // *if* and *unless*.
  If: [
    o("IfBlock"),
    o("Statement  POST_IF Expression", function() {
      return new If(A3, new Block([A1]), { type: A2, statement: true });
    }),
    o("Expression POST_IF Expression", function() {
      return new If(A3, new Block([A1]), { type: A2 });
    })
    // , statement: true # why is this a statement?!?
  ],
  Ternary: [
    o("Expression ? Expression : Expression", function() {
      return AST.If.ternary(A1, A3, A5);
    })
  ],
  // Arithmetic and logical operators, working on one or more operands.
  // Here they are grouped by order of precedence. The actual precedence rules
  // are defined at the bottom of the page. It would be shorter if we could
  // combine most of these rules into a single generic *Operand OpSymbol Operand*
  // -type rule, but in order to make the precedence binding possible, separate
  // rules are necessary.
  Operation: [
    o("NEW Expression", function() {
      return AST.Instantiation.for(A2, A1).setEnds(A1, A2);
    }),
    o("UNARY Expression", function() {
      return AST.OP(A1, A2).setEnds(A1, A2);
    }),
    o("--- Expression", function() {
      return AST.OP(A1, A2).setEnds(A1, A2);
    }),
    o("+++ Expression", function() {
      return AST.OP(A1, A2).setEnds(A1, A2);
    }),
    o("- Expression", function() {
      return AST.OP(A1, A2).setEnds(A1, A2);
    }, { prec: "UNARY" }),
    o("+ Expression", function() {
      return AST.OP(A1, A2).setEnds(A1, A2);
    }, { prec: "UNARY" }),
    o("-- SimpleAssignable", function() {
      return new UnaryOp(A1, null, A2).setEnds(A1, A2);
    }),
    o("++ SimpleAssignable", function() {
      return new UnaryOp(A1, null, A2).setEnds(A1, A2);
    }),
    o("SimpleAssignable --", function() {
      return new UnaryOp(A2, A1, null, true).setEnds(A1, A2);
    }),
    o("SimpleAssignable ++", function() {
      return new UnaryOp(A2, A1, null, true).setEnds(A1, A2);
    }),
    o("Expression + Expression", function() {
      return new Op(A2, A1, A3).setEnds(A1, A3);
    }),
    o("Expression - Expression", function() {
      return new Op(A2, A1, A3).setEnds(A1, A3);
    }),
    o("Expression EXP      Expression", function() {
      return AST.OP(A2, A1, A3).setEnds(A1, A3);
    }),
    o("Expression MATH     Expression", function() {
      return AST.OP(A2, A1, A3).setEnds(A1, A3);
    }),
    o("Expression SHIFT    Expression", function() {
      return AST.OP(A2, A1, A3).setEnds(A1, A3);
    }),
    o("Expression COMPARE  Expression", function() {
      return AST.OP(A2, A1, A3).setEnds(A1, A3);
    }),
    o("Expression LOGIC    Expression", function() {
      return AST.OP(A2, A1, A3).setEnds(A1, A3);
    }),
    o("Expression NOT RELATION Expression", function() {
      return AST.OP(A3, A1, A4).invert(A2);
    }),
    o("Expression RELATION Expression", function() {
      return AST.OP(A2, A1, A3).setEnds(A1, A3);
    }),
    o("SimpleAssignable COMPOUND_ASSIGN Expression", function() {
      return AST.OP(A2, A1, A3);
    }),
    o("SimpleAssignable COMPOUND_ASSIGN INDENT Expression Outdent", function() {
      return AST.OP(A2, A1, A4.indented(A3, A5));
    })
  ]
};
var operators = [
  ["left", ".", "?.", "::", ".:"],
  ["left", "CALL_START", "CALL_END"],
  // ['left',      '{{', '}}']
  // ['left', 'STRING_START','STRING_END']
  ["nonassoc", "++", "--"],
  ["right", "UNARY", "NEW", "THROW", "NOT"],
  ["right", "AWAIT"],
  ["right", "EXP"],
  ["left", "MATH"],
  ["left", "+", "-", "+++", "---"],
  ["left", "SHIFT"],
  ["left", "RELATION"],
  ["left", "COMPARE"],
  ["left", "LOGIC"],
  ["right", "?"],
  ["nonassoc", "INDENT", "OUTDENT"],
  ["right", "=", ":", "COMPOUND_ASSIGN", "RETURN", "YIELD", "THROW", "EXTENDS"],
  ["right", "FORIN", "FOROF", "BY", "WHEN"],
  ["right", "TAG_END"],
  ["right", "IF", "ELSE", "FOR", "DO", "WHILE", "UNTIL", "LOOP", "SUPER", "CLASS", "MIXIN", "INTERFACE", "MODULE", "TAG", "EVENT", "TRIGGER", "TAG_END", "IMPORT", "EXPORT"],
  ["right", "POST_IF", "POST_FOR"],
  ["right", "NEW_TAG"],
  ["right", "TAG_ATTR_SET"],
  ["right", "SPLAT"],
  ["left", "SELECTOR_START"],
  ["left", "CSS"]
];
var tokens = [];
for (let name in grammar) {
  let alternatives;
  alternatives = grammar[name];
  let res = [];
  for (let i = 0, items = iter$(alternatives), len = items.length, alt; i < len; i++) {
    alt = items[i];
    for (let j = 0, ary = iter$(alt[0].split(" ")), len2 = ary.length, token; j < len2; j++) {
      token = ary[j];
      if (!grammar[token]) {
        tokens.push(token);
      }
      ;
    }
    ;
    if (name === "Root") {
      alt[1] = "return " + alt[1];
    }
    ;
    res.push(alt);
  }
  ;
  grammar[name] = res;
}
var parser2 = new Parser(
  {
    tokens: tokens.join(" "),
    bnf: grammar,
    operators: operators.reverse(),
    startSymbol: "Root"
  }
);
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  parser
});