"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const parser = require("./lib-src-parse-parser-parser.cjs");
const keys = require("./lib-src-parse-grammar-keys.cjs");
const visitor = require("../@chevrotain/gast/lib-src-visitor.cjs");
const helpers = require("../@chevrotain/gast/lib-src-helpers.cjs");
const llk_lookahead = require("./lib-src-parse-grammar-llk_lookahead.cjs");
const has = require("../lodash-es/has.cjs");
const forEach = require("../lodash-es/forEach.cjs");
class LooksAhead {
  initLooksAhead(config) {
    this.dynamicTokensEnabled = has.default(config, "dynamicTokensEnabled") ? config.dynamicTokensEnabled : parser.DEFAULT_PARSER_CONFIG.dynamicTokensEnabled;
    this.maxLookahead = has.default(config, "maxLookahead") ? config.maxLookahead : parser.DEFAULT_PARSER_CONFIG.maxLookahead;
    this.lookaheadStrategy = has.default(config, "lookaheadStrategy") ? config.lookaheadStrategy : new llk_lookahead.LLkLookaheadStrategy({ maxLookahead: this.maxLookahead });
    this.lookAheadFuncsCache = /* @__PURE__ */ new Map();
  }
  preComputeLookaheadFunctions(rules) {
    forEach.default(rules, (currRule) => {
      this.TRACE_INIT(`${currRule.name} Rule Lookahead`, () => {
        const { alternation, repetition, option, repetitionMandatory, repetitionMandatoryWithSeparator, repetitionWithSeparator } = collectMethods(currRule);
        forEach.default(alternation, (currProd) => {
          const prodIdx = currProd.idx === 0 ? "" : currProd.idx;
          this.TRACE_INIT(`${helpers.getProductionDslName(currProd)}${prodIdx}`, () => {
            const laFunc = this.lookaheadStrategy.buildLookaheadForAlternation({
              prodOccurrence: currProd.idx,
              rule: currRule,
              maxLookahead: currProd.maxLookahead || this.maxLookahead,
              hasPredicates: currProd.hasPredicates,
              dynamicTokensEnabled: this.dynamicTokensEnabled
            });
            const key = keys.getKeyForAutomaticLookahead(this.fullRuleNameToShort[currRule.name], keys.OR_IDX, currProd.idx);
            this.setLaFuncCache(key, laFunc);
          });
        });
        forEach.default(repetition, (currProd) => {
          this.computeLookaheadFunc(currRule, currProd.idx, keys.MANY_IDX, "Repetition", currProd.maxLookahead, helpers.getProductionDslName(currProd));
        });
        forEach.default(option, (currProd) => {
          this.computeLookaheadFunc(currRule, currProd.idx, keys.OPTION_IDX, "Option", currProd.maxLookahead, helpers.getProductionDslName(currProd));
        });
        forEach.default(repetitionMandatory, (currProd) => {
          this.computeLookaheadFunc(currRule, currProd.idx, keys.AT_LEAST_ONE_IDX, "RepetitionMandatory", currProd.maxLookahead, helpers.getProductionDslName(currProd));
        });
        forEach.default(repetitionMandatoryWithSeparator, (currProd) => {
          this.computeLookaheadFunc(currRule, currProd.idx, keys.AT_LEAST_ONE_SEP_IDX, "RepetitionMandatoryWithSeparator", currProd.maxLookahead, helpers.getProductionDslName(currProd));
        });
        forEach.default(repetitionWithSeparator, (currProd) => {
          this.computeLookaheadFunc(currRule, currProd.idx, keys.MANY_SEP_IDX, "RepetitionWithSeparator", currProd.maxLookahead, helpers.getProductionDslName(currProd));
        });
      });
    });
  }
  computeLookaheadFunc(rule, prodOccurrence, prodKey, prodType, prodMaxLookahead, dslMethodName) {
    this.TRACE_INIT(`${dslMethodName}${prodOccurrence === 0 ? "" : prodOccurrence}`, () => {
      const laFunc = this.lookaheadStrategy.buildLookaheadForOptional({
        prodOccurrence,
        rule,
        maxLookahead: prodMaxLookahead || this.maxLookahead,
        dynamicTokensEnabled: this.dynamicTokensEnabled,
        prodType
      });
      const key = keys.getKeyForAutomaticLookahead(this.fullRuleNameToShort[rule.name], prodKey, prodOccurrence);
      this.setLaFuncCache(key, laFunc);
    });
  }
  // this actually returns a number, but it is always used as a string (object prop key)
  getKeyForAutomaticLookahead(dslMethodIdx, occurrence) {
    const currRuleShortName = this.getLastExplicitRuleShortName();
    return keys.getKeyForAutomaticLookahead(currRuleShortName, dslMethodIdx, occurrence);
  }
  getLaFuncFromCache(key) {
    return this.lookAheadFuncsCache.get(key);
  }
  /* istanbul ignore next */
  setLaFuncCache(key, value) {
    this.lookAheadFuncsCache.set(key, value);
  }
}
class DslMethodsCollectorVisitor extends visitor.GAstVisitor {
  constructor() {
    super(...arguments);
    this.dslMethods = {
      option: [],
      alternation: [],
      repetition: [],
      repetitionWithSeparator: [],
      repetitionMandatory: [],
      repetitionMandatoryWithSeparator: []
    };
  }
  reset() {
    this.dslMethods = {
      option: [],
      alternation: [],
      repetition: [],
      repetitionWithSeparator: [],
      repetitionMandatory: [],
      repetitionMandatoryWithSeparator: []
    };
  }
  visitOption(option) {
    this.dslMethods.option.push(option);
  }
  visitRepetitionWithSeparator(manySep) {
    this.dslMethods.repetitionWithSeparator.push(manySep);
  }
  visitRepetitionMandatory(atLeastOne) {
    this.dslMethods.repetitionMandatory.push(atLeastOne);
  }
  visitRepetitionMandatoryWithSeparator(atLeastOneSep) {
    this.dslMethods.repetitionMandatoryWithSeparator.push(atLeastOneSep);
  }
  visitRepetition(many) {
    this.dslMethods.repetition.push(many);
  }
  visitAlternation(or) {
    this.dslMethods.alternation.push(or);
  }
}
const collectorVisitor = new DslMethodsCollectorVisitor();
function collectMethods(rule) {
  collectorVisitor.reset();
  rule.accept(collectorVisitor);
  const dslMethods = collectorVisitor.dslMethods;
  collectorVisitor.reset();
  return dslMethods;
}
exports.LooksAhead = LooksAhead;
exports.collectMethods = collectMethods;
//# sourceMappingURL=lib-src-parse-parser-traits-looksahead.cjs.map
