'use strict';

var parser = require('../parser/parser.js');
var visitor = require('../../../../../../../@chevrotain_gast@11.0.3/node_modules/@chevrotain/gast/lib/src/visitor.js');
var forEach = require('../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/forEach.js');
var values = require('../../../../../../../lodash-es@4.17.21/node_modules/lodash-es/values.js');

function resolveGrammar(topLevels, errMsgProvider) {
    const refResolver = new GastRefResolverVisitor(topLevels, errMsgProvider);
    refResolver.resolveRefs();
    return refResolver.errors;
}
class GastRefResolverVisitor extends visitor.GAstVisitor {
    constructor(nameToTopRule, errMsgProvider) {
        super();
        this.nameToTopRule = nameToTopRule;
        this.errMsgProvider = errMsgProvider;
        this.errors = [];
    }
    resolveRefs() {
        forEach.default(values.default(this.nameToTopRule), (prod) => {
            this.currTopLevel = prod;
            prod.accept(this);
        });
    }
    visitNonTerminal(node) {
        const ref = this.nameToTopRule[node.nonTerminalName];
        if (!ref) {
            const msg = this.errMsgProvider.buildRuleNotFoundError(this.currTopLevel, node);
            this.errors.push({
                message: msg,
                type: parser.ParserDefinitionErrorType.UNRESOLVED_SUBRULE_REF,
                ruleName: this.currTopLevel.name,
                unresolvedRefName: node.nonTerminalName,
            });
        }
        else {
            node.referencedRule = ref;
        }
    }
}

exports.GastRefResolverVisitor = GastRefResolverVisitor;
exports.resolveGrammar = resolveGrammar;
