import { first as F } from "./first.js";
import { RestWalker as L } from "./rest.js";
import { Alternative as O, NonTerminal as M, Option as b, RepetitionMandatory as _, Repetition as S, RepetitionMandatoryWithSeparator as D, Terminal as T, RepetitionWithSeparator as g, Alternation as v, Rule as G } from "../../../../../../../@chevrotain_gast@11.0.3/node_modules/@chevrotain/gast/lib/src/model.js";
import A from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/clone.js";
import V from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/forEach.js";
import x from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/drop.js";
import P from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/isEmpty.js";
import I from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/dropRight.js";
import j from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/last.js";
import y from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/head.js";
class q extends L {
  constructor(i, t) {
    super(), this.topProd = i, this.path = t, this.possibleTokTypes = [], this.nextProductionName = "", this.nextProductionOccurrence = 0, this.found = !1, this.isAtEndOfPath = !1;
  }
  startWalking() {
    if (this.found = !1, this.path.ruleStack[0] !== this.topProd.name)
      throw Error("The path does not start with the walker's top Rule!");
    return this.ruleStack = A(this.path.ruleStack).reverse(), this.occurrenceStack = A(this.path.occurrenceStack).reverse(), this.ruleStack.pop(), this.occurrenceStack.pop(), this.updateExpectedNext(), this.walk(this.topProd), this.possibleTokTypes;
  }
  walk(i, t = []) {
    this.found || super.walk(i, t);
  }
  walkProdRef(i, t, s) {
    if (i.referencedRule.name === this.nextProductionName && i.idx === this.nextProductionOccurrence) {
      const n = t.concat(s);
      this.updateExpectedNext(), this.walk(i.referencedRule, n);
    }
  }
  updateExpectedNext() {
    P(this.ruleStack) ? (this.nextProductionName = "", this.nextProductionOccurrence = 0, this.isAtEndOfPath = !0) : (this.nextProductionName = this.ruleStack.pop(), this.nextProductionOccurrence = this.occurrenceStack.pop());
  }
}
class ne extends q {
  constructor(i, t) {
    super(i, t), this.path = t, this.nextTerminalName = "", this.nextTerminalOccurrence = 0, this.nextTerminalName = this.path.lastTok.name, this.nextTerminalOccurrence = this.path.lastTokOccurrence;
  }
  walkTerminal(i, t, s) {
    if (this.isAtEndOfPath && i.terminalType.name === this.nextTerminalName && i.idx === this.nextTerminalOccurrence && !this.found) {
      const n = t.concat(s), w = new O({ definition: n });
      this.possibleTokTypes = F(w), this.found = !0;
    }
  }
}
class R extends L {
  constructor(i, t) {
    super(), this.topRule = i, this.occurrence = t, this.result = {
      token: void 0,
      occurrence: void 0,
      isEndOfRule: void 0
    };
  }
  startWalking() {
    return this.walk(this.topRule), this.result;
  }
}
class ie extends R {
  walkMany(i, t, s) {
    if (i.idx === this.occurrence) {
      const n = y(t.concat(s));
      this.result.isEndOfRule = n === void 0, n instanceof T && (this.result.token = n.terminalType, this.result.occurrence = n.idx);
    } else
      super.walkMany(i, t, s);
  }
}
class ce extends R {
  walkManySep(i, t, s) {
    if (i.idx === this.occurrence) {
      const n = y(t.concat(s));
      this.result.isEndOfRule = n === void 0, n instanceof T && (this.result.token = n.terminalType, this.result.occurrence = n.idx);
    } else
      super.walkManySep(i, t, s);
  }
}
class se extends R {
  walkAtLeastOne(i, t, s) {
    if (i.idx === this.occurrence) {
      const n = y(t.concat(s));
      this.result.isEndOfRule = n === void 0, n instanceof T && (this.result.token = n.terminalType, this.result.occurrence = n.idx);
    } else
      super.walkAtLeastOne(i, t, s);
  }
}
class oe extends R {
  walkAtLeastOneSep(i, t, s) {
    if (i.idx === this.occurrence) {
      const n = y(t.concat(s));
      this.result.isEndOfRule = n === void 0, n instanceof T && (this.result.token = n.terminalType, this.result.occurrence = n.idx);
    } else
      super.walkAtLeastOneSep(i, t, s);
  }
}
function z(a, i, t = []) {
  t = A(t);
  let s = [], n = 0;
  function w(c) {
    return c.concat(x(a, n + 1));
  }
  function k(c) {
    const f = z(w(c), i, t);
    return s.concat(f);
  }
  for (; t.length < i && n < a.length; ) {
    const c = a[n];
    if (c instanceof O)
      return k(c.definition);
    if (c instanceof M)
      return k(c.definition);
    if (c instanceof b)
      s = k(c.definition);
    else if (c instanceof _) {
      const f = c.definition.concat([
        new S({
          definition: c.definition
        })
      ]);
      return k(f);
    } else if (c instanceof D) {
      const f = [
        new O({ definition: c.definition }),
        new S({
          definition: [new T({ terminalType: c.separator })].concat(c.definition)
        })
      ];
      return k(f);
    } else if (c instanceof g) {
      const f = c.definition.concat([
        new S({
          definition: [new T({ terminalType: c.separator })].concat(c.definition)
        })
      ]);
      s = k(f);
    } else if (c instanceof S) {
      const f = c.definition.concat([
        new S({
          definition: c.definition
        })
      ]);
      s = k(f);
    } else {
      if (c instanceof v)
        return V(c.definition, (f) => {
          P(f.definition) === !1 && (s = k(f.definition));
        }), s;
      if (c instanceof T)
        t.push(c.terminalType);
      else
        throw Error("non exhaustive match");
    }
    n++;
  }
  return s.push({
    partialPath: t,
    suffixDef: x(a, n)
  }), s;
}
function re(a, i, t, s) {
  const n = "EXIT_NONE_TERMINAL", w = [n], k = "EXIT_ALTERNATIVE";
  let c = !1;
  const f = i.length, X = f - s - 1, W = [], o = [];
  for (o.push({
    idx: -1,
    def: a,
    ruleStack: [],
    occurrenceStack: []
  }); !P(o); ) {
    const E = o.pop();
    if (E === k) {
      c && j(o).idx <= X && o.pop();
      continue;
    }
    const d = E.def, u = E.idx, h = E.ruleStack, p = E.occurrenceStack;
    if (P(d))
      continue;
    const e = d[0];
    if (e === n) {
      const r = {
        idx: u,
        def: x(d),
        ruleStack: I(h),
        occurrenceStack: I(p)
      };
      o.push(r);
    } else if (e instanceof T)
      if (u < f - 1) {
        const r = u + 1, l = i[r];
        if (t(l, e.terminalType)) {
          const m = {
            idx: r,
            def: x(d),
            ruleStack: h,
            occurrenceStack: p
          };
          o.push(m);
        }
      } else if (u === f - 1)
        W.push({
          nextTokenType: e.terminalType,
          nextTokenOccurrence: e.idx,
          ruleStack: h,
          occurrenceStack: p
        }), c = !0;
      else
        throw Error("non exhaustive match");
    else if (e instanceof M) {
      const r = A(h);
      r.push(e.nonTerminalName);
      const l = A(p);
      l.push(e.idx);
      const m = {
        idx: u,
        def: e.definition.concat(w, x(d)),
        ruleStack: r,
        occurrenceStack: l
      };
      o.push(m);
    } else if (e instanceof b) {
      const r = {
        idx: u,
        def: x(d),
        ruleStack: h,
        occurrenceStack: p
      };
      o.push(r), o.push(k);
      const l = {
        idx: u,
        def: e.definition.concat(x(d)),
        ruleStack: h,
        occurrenceStack: p
      };
      o.push(l);
    } else if (e instanceof _) {
      const r = new S({
        definition: e.definition,
        idx: e.idx
      }), l = e.definition.concat([r], x(d)), m = {
        idx: u,
        def: l,
        ruleStack: h,
        occurrenceStack: p
      };
      o.push(m);
    } else if (e instanceof D) {
      const r = new T({
        terminalType: e.separator
      }), l = new S({
        definition: [r].concat(e.definition),
        idx: e.idx
      }), m = e.definition.concat([l], x(d)), N = {
        idx: u,
        def: m,
        ruleStack: h,
        occurrenceStack: p
      };
      o.push(N);
    } else if (e instanceof g) {
      const r = {
        idx: u,
        def: x(d),
        ruleStack: h,
        occurrenceStack: p
      };
      o.push(r), o.push(k);
      const l = new T({
        terminalType: e.separator
      }), m = new S({
        definition: [l].concat(e.definition),
        idx: e.idx
      }), N = e.definition.concat([m], x(d)), C = {
        idx: u,
        def: N,
        ruleStack: h,
        occurrenceStack: p
      };
      o.push(C);
    } else if (e instanceof S) {
      const r = {
        idx: u,
        def: x(d),
        ruleStack: h,
        occurrenceStack: p
      };
      o.push(r), o.push(k);
      const l = new S({
        definition: e.definition,
        idx: e.idx
      }), m = e.definition.concat([l], x(d)), N = {
        idx: u,
        def: m,
        ruleStack: h,
        occurrenceStack: p
      };
      o.push(N);
    } else if (e instanceof v)
      for (let r = e.definition.length - 1; r >= 0; r--) {
        const l = e.definition[r], m = {
          idx: u,
          def: l.definition.concat(x(d)),
          ruleStack: h,
          occurrenceStack: p
        };
        o.push(m), o.push(k);
      }
    else if (e instanceof O)
      o.push({
        idx: u,
        def: e.definition.concat(x(d)),
        ruleStack: h,
        occurrenceStack: p
      });
    else if (e instanceof G)
      o.push(B(e, u, h, p));
    else
      throw Error("non exhaustive match");
  }
  return W;
}
function B(a, i, t, s) {
  const n = A(t);
  n.push(a.name);
  const w = A(s);
  return w.push(1), {
    idx: i,
    def: a.definition,
    ruleStack: n,
    occurrenceStack: w
  };
}
export {
  q as AbstractNextPossibleTokensWalker,
  R as AbstractNextTerminalAfterProductionWalker,
  ne as NextAfterTokenWalker,
  oe as NextTerminalAfterAtLeastOneSepWalker,
  se as NextTerminalAfterAtLeastOneWalker,
  ce as NextTerminalAfterManySepWalker,
  ie as NextTerminalAfterManyWalker,
  re as nextPossibleTokensAfter,
  z as possiblePathsFrom
};
