"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RegraParadigmaConsistente = void 0;
const leia_1 = require("../../construtos/leia");
const declaracoes_1 = require("../../declaracoes");
const mapeamento_paradigmas_1 = require("../../lexador/mapeamento-paradigmas");
/**
 * Regra que enforça consistência de paradigma em palavras reservadas.
 *
 * Em português, instruções podem ser expressas no imperativo (escreva, leia)
 * ou no infinitivo (escrever, ler). Esta regra permite escolher um paradigma
 * único para manter a consistência do código.
 *
 * Exemplos:
 * - Modo imperativo: `escreva()`, `leia()`, `tente { } pegue { }`
 * - Modo infinitivo: `escrever()`, `ler()`, `tentar { } pegar { }`
 */
class RegraParadigmaConsistente {
    constructor(opcoes = {}) {
        this.nome = 'paradigma-consistente';
        this.descricao = 'Enforça consistência de paradigma (imperativo/infinitivo) em palavras reservadas';
        this.opcoes = {
            paradigma: opcoes.paradigma || 'ambos',
        };
        this.mapaLexemaParaParadigma = (0, mapeamento_paradigmas_1.obterMapaLexemaParaParadigma)();
    }
    aplicarEmDeclaracao(declaracao) {
        // Processa Escreva
        if (declaracao instanceof declaracoes_1.Escreva || declaracao instanceof declaracoes_1.EscrevaMesmaLinha) {
            return this.processarDeclaracaoComSimbolo(declaracao, 'simboloEscreva');
        }
        return declaracao;
    }
    aplicarEmConstruto(construto) {
        // Processa Leia
        if (construto instanceof leia_1.Leia) {
            return this.processarConstrutoComSimbolo(construto, 'simbolo');
        }
        return construto;
    }
    /**
     * Processa uma declaração que tem um símbolo específico.
     */
    processarDeclaracaoComSimbolo(declaracao, nomeCampoSimbolo) {
        const simbolo = declaracao[nomeCampoSimbolo];
        if (!simbolo) {
            return declaracao;
        }
        const lexemaAtual = simbolo.lexema.toLowerCase();
        const paradigmaLexema = this.mapaLexemaParaParadigma.get(lexemaAtual);
        // Se for neutro ou ambos, não faz nada
        if (paradigmaLexema === 'neutro' || this.opcoes.paradigma === 'ambos') {
            return declaracao;
        }
        // Se o lexema não pertence ao paradigma configurado, transforma
        if (!(0, mapeamento_paradigmas_1.pertenceAoParadigma)(lexemaAtual, this.opcoes.paradigma)) {
            const formaAlternativa = (0, mapeamento_paradigmas_1.obterFormaAlternativa)(lexemaAtual, this.opcoes.paradigma);
            if (formaAlternativa) {
                simbolo.lexema = formaAlternativa;
            }
        }
        return declaracao;
    }
    /**
     * Processa um construto que tem um símbolo específico.
     */
    processarConstrutoComSimbolo(construto, nomeCampoSimbolo) {
        const simbolo = construto[nomeCampoSimbolo];
        if (!simbolo) {
            return construto;
        }
        const lexemaAtual = simbolo.lexema.toLowerCase();
        const paradigmaLexema = this.mapaLexemaParaParadigma.get(lexemaAtual);
        // Se for neutro ou ambos, não faz nada
        if (paradigmaLexema === 'neutro' || this.opcoes.paradigma === 'ambos') {
            return construto;
        }
        // Se o lexema não pertence ao paradigma configurado, transforma
        if (!(0, mapeamento_paradigmas_1.pertenceAoParadigma)(lexemaAtual, this.opcoes.paradigma)) {
            const formaAlternativa = (0, mapeamento_paradigmas_1.obterFormaAlternativa)(lexemaAtual, this.opcoes.paradigma);
            if (formaAlternativa) {
                simbolo.lexema = formaAlternativa;
            }
        }
        return construto;
    }
}
exports.RegraParadigmaConsistente = RegraParadigmaConsistente;
//# sourceMappingURL=paradigma-consistente.js.map