"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const model = require("../@chevrotain/gast/lib-src-model.cjs");
const helpers = require("../@chevrotain/gast/lib-src-helpers.cjs");
const uniq = require("../lodash-es/uniq.cjs");
const map = require("../lodash-es/map.cjs");
const flatten = require("../lodash-es/flatten.cjs");
function first(prod) {
  if (prod instanceof model.NonTerminal) {
    return first(prod.referencedRule);
  } else if (prod instanceof model.Terminal) {
    return firstForTerminal(prod);
  } else if (helpers.isSequenceProd(prod)) {
    return firstForSequence(prod);
  } else if (helpers.isBranchingProd(prod)) {
    return firstForBranching(prod);
  } else {
    throw Error("non exhaustive match");
  }
}
function firstForSequence(prod) {
  let firstSet = [];
  const seq = prod.definition;
  let nextSubProdIdx = 0;
  let hasInnerProdsRemaining = seq.length > nextSubProdIdx;
  let currSubProd;
  let isLastInnerProdOptional = true;
  while (hasInnerProdsRemaining && isLastInnerProdOptional) {
    currSubProd = seq[nextSubProdIdx];
    isLastInnerProdOptional = helpers.isOptionalProd(currSubProd);
    firstSet = firstSet.concat(first(currSubProd));
    nextSubProdIdx = nextSubProdIdx + 1;
    hasInnerProdsRemaining = seq.length > nextSubProdIdx;
  }
  return uniq.default(firstSet);
}
function firstForBranching(prod) {
  const allAlternativesFirsts = map.default(prod.definition, (innerProd) => {
    return first(innerProd);
  });
  return uniq.default(flatten.default(allAlternativesFirsts));
}
function firstForTerminal(terminal) {
  return [terminal.terminalType];
}
exports.first = first;
exports.firstForBranching = firstForBranching;
exports.firstForSequence = firstForSequence;
exports.firstForTerminal = firstForTerminal;
//# sourceMappingURL=lib-src-parse-grammar-first.cjs.map
