import { ParserDefinitionErrorType as f } from "../parser/parser.js";
import { Terminal as b, NonTerminal as _, Alternative as k, Option as C, RepetitionMandatory as I, RepetitionMandatoryWithSeparator as D, RepetitionWithSeparator as U, Repetition as F, Alternation as V } from "../../../../../../../@chevrotain_gast@11.0.3/node_modules/@chevrotain/gast/lib/src/model.js";
import { GAstVisitor as y } from "../../../../../../../@chevrotain_gast@11.0.3/node_modules/@chevrotain/gast/lib/src/visitor.js";
import { getProductionDslName as R, isOptionalProd as w } from "../../../../../../../@chevrotain_gast@11.0.3/node_modules/@chevrotain/gast/lib/src/helpers.js";
import { getProdType as G, getLookaheadPathsForOptionalProd as W, getLookaheadPathsForOr as $, containsPath as T, isStrictPrefixOfPath as B } from "./lookahead.js";
import { nextPossibleTokensAfter as K } from "./interpreter.js";
import { tokenStructuredMatcher as Y } from "../../scan/tokens.js";
import E from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/forEach.js";
import g from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/map.js";
import d from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/flatMap.js";
import j from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/groupBy.js";
import H from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/pickBy.js";
import S from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/head.js";
import X from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/values.js";
import P from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/reduce.js";
import N from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/isEmpty.js";
import M from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/flatten.js";
import x from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/includes.js";
import q from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/difference.js";
import z from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/clone.js";
import J from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/dropRight.js";
import Q from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/reject.js";
import Z from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/drop.js";
import tt from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/compact.js";
import et from "../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/filter.js";
function Vt(t) {
  const e = t.lookaheadStrategy.validate({
    rules: t.rules,
    tokenTypes: t.tokenTypes,
    grammarName: t.grammarName
  });
  return g(e, (r) => Object.assign({ type: f.CUSTOM_LOOKAHEAD_VALIDATION }, r));
}
function wt(t, e, r, i) {
  const o = d(t, (c) => rt(c, r)), n = mt(t, e, r), s = d(t, (c) => ct(c, r)), a = d(t, (c) => it(c, t, i, r));
  return o.concat(n, s, a);
}
function rt(t, e) {
  const r = new nt();
  t.accept(r);
  const i = r.allProductions, o = j(i, ot), n = H(o, (a) => a.length > 1);
  return g(X(n), (a) => {
    const c = S(a), u = e.buildDuplicateFoundError(t, a), l = R(c), m = {
      message: u,
      type: f.DUPLICATE_PRODUCTIONS,
      ruleName: t.name,
      dslName: l,
      occurrence: c.idx
    }, p = L(c);
    return p && (m.parameter = p), m;
  });
}
function ot(t) {
  return `${R(t)}_#_${t.idx}_#_${L(t)}`;
}
function L(t) {
  return t instanceof b ? t.terminalType.name : t instanceof _ ? t.nonTerminalName : "";
}
class nt extends y {
  constructor() {
    super(...arguments), this.allProductions = [];
  }
  visitNonTerminal(e) {
    this.allProductions.push(e);
  }
  visitOption(e) {
    this.allProductions.push(e);
  }
  visitRepetitionWithSeparator(e) {
    this.allProductions.push(e);
  }
  visitRepetitionMandatory(e) {
    this.allProductions.push(e);
  }
  visitRepetitionMandatoryWithSeparator(e) {
    this.allProductions.push(e);
  }
  visitRepetition(e) {
    this.allProductions.push(e);
  }
  visitAlternation(e) {
    this.allProductions.push(e);
  }
  visitTerminal(e) {
    this.allProductions.push(e);
  }
}
function it(t, e, r, i) {
  const o = [];
  if (P(e, (s, a) => a.name === t.name ? s + 1 : s, 0) > 1) {
    const s = i.buildDuplicateRuleNameError({
      topLevelRule: t,
      grammarName: r
    });
    o.push({
      message: s,
      type: f.DUPLICATE_RULE_NAME,
      ruleName: t.name
    });
  }
  return o;
}
function Gt(t, e, r) {
  const i = [];
  let o;
  return x(e, t) || (o = `Invalid rule override, rule: ->${t}<- cannot be overridden in the grammar: ->${r}<-as it is not defined in any of the super grammars `, i.push({
    message: o,
    type: f.INVALID_RULE_OVERRIDE,
    ruleName: t
  })), i;
}
function st(t, e, r, i = []) {
  const o = [], n = A(e.definition);
  if (N(n))
    return [];
  {
    const s = t.name;
    x(n, t) && o.push({
      message: r.buildLeftRecursionError({
        topLevelRule: t,
        leftRecursionPath: i
      }),
      type: f.LEFT_RECURSION,
      ruleName: s
    });
    const c = q(n, i.concat([t])), u = d(c, (l) => {
      const m = z(i);
      return m.push(l), st(t, l, r, m);
    });
    return o.concat(u);
  }
}
function A(t) {
  let e = [];
  if (N(t))
    return e;
  const r = S(t);
  if (r instanceof _)
    e.push(r.referencedRule);
  else if (r instanceof k || r instanceof C || r instanceof I || r instanceof D || r instanceof U || r instanceof F)
    e = e.concat(A(r.definition));
  else if (r instanceof V)
    e = M(g(r.definition, (n) => A(n.definition)));
  else if (!(r instanceof b)) throw Error("non exhaustive match");
  const i = w(r), o = t.length > 1;
  if (i && o) {
    const n = Z(t);
    return e.concat(A(n));
  } else
    return e;
}
class v extends y {
  constructor() {
    super(...arguments), this.alternations = [];
  }
  visitAlternation(e) {
    this.alternations.push(e);
  }
}
function Wt(t, e) {
  const r = new v();
  t.accept(r);
  const i = r.alternations;
  return d(i, (n) => {
    const s = J(n.definition);
    return d(s, (a, c) => {
      const u = K([a], [], Y, 1);
      return N(u) ? [
        {
          message: e.buildEmptyAlternationError({
            topLevelRule: t,
            alternation: n,
            emptyChoiceIdx: c
          }),
          type: f.NONE_LAST_EMPTY_ALT,
          ruleName: t.name,
          occurrence: n.idx,
          alternative: c + 1
        }
      ] : [];
    });
  });
}
function $t(t, e, r) {
  const i = new v();
  t.accept(i);
  let o = i.alternations;
  return o = Q(o, (s) => s.ignoreAmbiguities === !0), d(o, (s) => {
    const a = s.idx, c = s.maxLookahead || e, u = $(a, t, c, s), l = ut(u, s, t, r), m = lt(u, s, t, r);
    return l.concat(m);
  });
}
class at extends y {
  constructor() {
    super(...arguments), this.allProductions = [];
  }
  visitRepetitionWithSeparator(e) {
    this.allProductions.push(e);
  }
  visitRepetitionMandatory(e) {
    this.allProductions.push(e);
  }
  visitRepetitionMandatoryWithSeparator(e) {
    this.allProductions.push(e);
  }
  visitRepetition(e) {
    this.allProductions.push(e);
  }
}
function ct(t, e) {
  const r = new v();
  t.accept(r);
  const i = r.alternations;
  return d(i, (n) => n.definition.length > 255 ? [
    {
      message: e.buildTooManyAlternativesError({
        topLevelRule: t,
        alternation: n
      }),
      type: f.TOO_MANY_ALTS,
      ruleName: t.name,
      occurrence: n.idx
    }
  ] : []);
}
function Bt(t, e, r) {
  const i = [];
  return E(t, (o) => {
    const n = new at();
    o.accept(n);
    const s = n.allProductions;
    E(s, (a) => {
      const c = G(a), u = a.maxLookahead || e, l = a.idx, p = W(l, o, c, u)[0];
      if (N(M(p))) {
        const h = r.buildEmptyRepetitionError({
          topLevelRule: o,
          repetition: a
        });
        i.push({
          message: h,
          type: f.NO_NON_EMPTY_LOOKAHEAD,
          ruleName: o.name
        });
      }
    });
  }), i;
}
function ut(t, e, r, i) {
  const o = [], n = P(t, (a, c, u) => (e.definition[u].ignoreAmbiguities === !0 || E(c, (l) => {
    const m = [u];
    E(t, (p, h) => {
      u !== h && T(p, l) && // ignore (skip) ambiguities with this "other" alternative
      e.definition[h].ignoreAmbiguities !== !0 && m.push(h);
    }), m.length > 1 && !T(o, l) && (o.push(l), a.push({
      alts: m,
      path: l
    }));
  }), a), []);
  return g(n, (a) => {
    const c = g(a.alts, (l) => l + 1);
    return {
      message: i.buildAlternationAmbiguityError({
        topLevelRule: r,
        alternation: e,
        ambiguityIndices: c,
        prefixPath: a.path
      }),
      type: f.AMBIGUOUS_ALTS,
      ruleName: r.name,
      occurrence: e.idx,
      alternatives: a.alts
    };
  });
}
function lt(t, e, r, i) {
  const o = P(t, (s, a, c) => {
    const u = g(a, (l) => ({ idx: c, path: l }));
    return s.concat(u);
  }, []);
  return tt(d(o, (s) => {
    if (e.definition[s.idx].ignoreAmbiguities === !0)
      return [];
    const c = s.idx, u = s.path, l = et(o, (p) => (
      // ignore (skip) ambiguities with this "other" alternative
      e.definition[p.idx].ignoreAmbiguities !== !0 && p.idx < c && // checking for strict prefix because identical lookaheads
      // will be be detected using a different validation.
      B(p.path, u)
    ));
    return g(l, (p) => {
      const h = [p.idx + 1, c + 1], O = e.idx === 0 ? "" : e.idx;
      return {
        message: i.buildAlternationPrefixAmbiguityError({
          topLevelRule: r,
          alternation: e,
          ambiguityIndices: h,
          prefixPath: p.path
        }),
        type: f.AMBIGUOUS_PREFIX_ALTS,
        ruleName: r.name,
        occurrence: O,
        alternatives: h
      };
    });
  }));
}
function mt(t, e, r) {
  const i = [], o = g(e, (n) => n.name);
  return E(t, (n) => {
    const s = n.name;
    if (x(o, s)) {
      const a = r.buildNamespaceConflictError(n);
      i.push({
        message: a,
        type: f.CONFLICT_TOKENS_RULES_NAMESPACE,
        ruleName: s
      });
    }
  }), i;
}
export {
  nt as OccurrenceValidationCollector,
  at as RepetitionCollector,
  lt as checkPrefixAlternativesAmbiguities,
  A as getFirstNoneTerminal,
  ot as identifyProductionForDuplicates,
  $t as validateAmbiguousAlternationAlternatives,
  Wt as validateEmptyOrAlternative,
  wt as validateGrammar,
  Vt as validateLookahead,
  st as validateNoLeftRecursion,
  it as validateRuleDoesNotAlreadyExist,
  Gt as validateRuleIsOverridden,
  Bt as validateSomeNonEmptyLookaheadPath,
  ct as validateTooManyAlts
};
