UNPKG

@designliquido/foles

Version:

Linguagem de folhas de estilo para documentos em geral em português

1,254 lines 69.8 kB
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AvaliadorSintatico = void 0;
const _1 = require(".");
const declaracoes_1 = require("../declaracoes");
const superclasse_1 = require("../modificadores/superclasse");
const seletor_valor_1 = require("../valores/seletor-valor");
const foles_1 = __importDefault(require("../tipos-de-simbolos/foles"));
const seletor_pseudoclasse_1 = require("../pseudoclasses/seletor-pseudoclasse");
const seletores_1 = require("../seletores");
const seletor_estruturas_lmht_1 = require("../estruturas/seletor-estruturas-lmht");
const seletor_espaco_reservado_1 = require("../seletores/seletor-espaco-reservado");
const valor_numerico_1 = require("../../testes/listas/valor-numerico");
const declaracao_variavel_1 = require("../declaracoes/declaracao-variavel");
/**
 * Implementação do avaliador sintático.
 */
class AvaliadorSintatico {
    constructor(importador) {
        this.referenciaDeclaracoes = [];
        this.importador = importador;
        this.simbolos = [];
    }
    erro(simbolo, mensagemDeErro) {
        const excecao = new _1.ErroAvaliadorSintatico(simbolo, mensagemDeErro);
        this.erros.push(excecao);
        return excecao;
    }
    estaNoFinal() {
        return this.atual === this.simbolos.length;
    }
    avancarEDevolverAnterior() {
        if (!this.estaNoFinal())
            this.atual += 1;
        return this.simbolos[this.atual - 1];
    }
    verificarTipoSimboloAtual(tipo) {
        if (this.estaNoFinal())
            return false;
        return this.simbolos[this.atual].tipo === tipo;
    }
    consumir(tipo, mensagemDeErro) {
        if (this.verificarTipoSimboloAtual(tipo))
            return this.avancarEDevolverAnterior();
        throw this.erro(this.simbolos[this.atual], mensagemDeErro);
    }
    resolverMetodo(lexema) {
        switch (lexema) {
            case "#":
                const codigoHEX = this.consumir(foles_1.default.IDENTIFICADOR, "Esperado código HEX válido após #'.");
                return new seletor_valor_1.SeletorValor("hex", [codigoHEX.lexema]);
            case "borrar":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'borrar'.");
                const valorBorrar = this.avancarEDevolverAnterior();
                let quantificadorBorrar;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorBorrar = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorBorrar = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'borrar'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorBorrar,
                    quantificadorBorrar,
                ]);
            case "brilho":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'brilho'.");
                const valorBrilho = this.avancarEDevolverAnterior();
                let quantificadorBrilho;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorBrilho = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorBrilho = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'brilho'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorBrilho,
                    quantificadorBrilho,
                ]);
            case "calcular":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'calcular'.");
                const valorCalc1 = this.avancarEDevolverAnterior();
                const quantificadorCalc1 = this.avancarEDevolverAnterior();
                const operadorCalc = this.avancarEDevolverAnterior();
                const valorCalc2 = this.avancarEDevolverAnterior();
                const quantificadorCalc2 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'calcular'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorCalc1,
                    quantificadorCalc1,
                    operadorCalc,
                    valorCalc2,
                    quantificadorCalc2,
                ]);
            case "contraste":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'contraste'.");
                const valorContraste = this.avancarEDevolverAnterior();
                let quantificadorContraste;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorContraste = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorContraste = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'contraste'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorContraste,
                    quantificadorContraste,
                ]);
            case "curva-cúbica":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'curva-cúbica'.");
                const parametro1 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método curva-cúbica.");
                const parametro2 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após segundo argumento do método curva-cúbica.");
                const parametro3 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após terceiro argumento do método curva-cúbica.");
                const parametro4 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após quarto argumento do método curva-cúbica.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    parametro1,
                    parametro2,
                    parametro3,
                    parametro4,
                ]);
            case "curva-cubica":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'curva-cúbica'.");
                const parametro1cc = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método curva-cúbica.");
                const parametro2cc = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após segundo argumento do método curva-cúbica.");
                const parametro3cc = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após terceiro argumento do método curva-cúbica.");
                const parametro4cc = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após quarto argumento do método curva-cúbica.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    parametro1cc,
                    parametro2cc,
                    parametro3cc,
                    parametro4cc,
                ]);
            case "encaixar-conteudo":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'encaixar-conteúdo'.");
                const valorFit = this.avancarEDevolverAnterior();
                const quantificadorFit = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método encaixar-conteúdo.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorFit["lexema"],
                    quantificadorFit["lexema"],
                ]);
            case "encaixar-conteúdo":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'encaixar-conteúdo'.");
                const valorFit1 = this.avancarEDevolverAnterior();
                const quantificadorFit1 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método encaixar-conteúdo.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorFit1["lexema"],
                    quantificadorFit1["lexema"],
                ]);
            case "escala-cinza":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'escala-cinza'.");
                const valorEscala = this.avancarEDevolverAnterior();
                let quantificadorEscala;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorEscala = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorEscala = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'escala-cinza'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorEscala,
                    quantificadorEscala,
                ]);
            case "escalamento":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'escalamento'.");
                const valorScale1 = this.avancarEDevolverAnterior();
                let valorScale2;
                if (this.simbolos[this.atual].tipo === "VIRGULA") {
                    this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método escalamento.");
                    valorScale2 = this.avancarEDevolverAnterior();
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método escalamento.");
                return new seletor_valor_1.SeletorValor(lexema, [valorScale1, valorScale2]);
            case "escalamento-3d":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'escalamento-3d'.");
                const valorScale3d1 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método escalamento-3d.");
                const valorScale3d2 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após segundo argumento do método escalamento-3d.");
                const valorScale3d3 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método escalamento-3d.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorScale3d1,
                    valorScale3d2,
                    valorScale3d3,
                ]);
            case "escalamento-eixo-z":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'escalamento-eixo-z'.");
                const valorScaleZ = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método escalamento-eixo-z.");
                return new seletor_valor_1.SeletorValor(lexema, [valorScaleZ]);
            case "escalamento-horizontal":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'escalamento-horizontal'.");
                const valorScaleX = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método escalamento-horizontal.");
                return new seletor_valor_1.SeletorValor(lexema, [valorScaleX]);
            case "escalamento-vertical":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'escalamento-vertical'.");
                const valorScaleY = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método escalamento-vertical.");
                return new seletor_valor_1.SeletorValor(lexema, [valorScaleY]);
            case "gradiente-linear":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'gradiente-linear'.");
                const valorAngulo = this.avancarEDevolverAnterior();
                let quantificadorAngulo;
                if (valorAngulo.tipo === "QUALITATIVO") {
                    switch (valorAngulo.lexema) {
                        case "superior":
                            valorAngulo.lexema = "0";
                            valorAngulo.tipo = "NUMERO";
                            quantificadorAngulo = {
                                tipo: "QUANTIFICADOR",
                                lexema: "deg",
                            };
                            break;
                        case "direita":
                            valorAngulo.lexema = "90";
                            valorAngulo.tipo = "NUMERO";
                            quantificadorAngulo = {
                                tipo: "QUANTIFICADOR",
                                lexema: "deg",
                            };
                            break;
                        case "inferior":
                            valorAngulo.lexema = "180";
                            valorAngulo.tipo = "NUMERO";
                            quantificadorAngulo = {
                                tipo: "QUANTIFICADOR",
                                lexema: "deg",
                            };
                            break;
                        case "esquerda":
                            valorAngulo.lexema = "270";
                            valorAngulo.tipo = "NUMERO";
                            quantificadorAngulo = {
                                tipo: "QUANTIFICADOR",
                                lexema: "deg",
                            };
                            break;
                        default:
                            break;
                    }
                }
                else {
                    quantificadorAngulo = this.avancarEDevolverAnterior();
                }
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após segundo argumento do método gradiente-linear.");
                const cor1 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após segundo argumento do método gradiente-linear.");
                const cor2 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'gradiente-linear'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorAngulo,
                    quantificadorAngulo,
                    cor1,
                    cor2,
                ]);
            case "hsl":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'hsl'.");
                const HdeHSL = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após argumento de matiz (H) no método 'hsl'.");
                const SdeHSL = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.QUANTIFICADOR, "Esperado símbolo percentual após argumento de saturação (S) no método 'hsl'.");
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após argumento de saturação (S) no método 'hsl'.");
                const LdeHSL = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.QUANTIFICADOR, "Esperado símbolo percentual após argumento de luminosidade (L) no método 'hsl'.");
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após argumentos de método 'hsl'.");
                return new seletor_valor_1.SeletorValor(lexema, [HdeHSL, SdeHSL, LdeHSL]);
            case "hsla":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'hsla'.");
                const HdeHSLA = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após argumento de matiz (H) no método 'hsla'.");
                const SdeHSLA = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.QUANTIFICADOR, "Esperado símbolo percentual após argumento de saturação (S) no método 'hsla'.");
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após argumento de saturação (S) no método 'hsla'.");
                const LdeHSLA = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.QUANTIFICADOR, "Esperado símbolo percentual após argumento de luminosidade (L) no método 'hsla'.");
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após argumentos de método 'hsla'.");
                return new seletor_valor_1.SeletorValor(lexema, [HdeHSLA, SdeHSLA, LdeHSLA]);
            case "inclinar":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'inclinar'.");
                const valorInclinar1 = this.avancarEDevolverAnterior();
                let quantificadorInclinar1;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorInclinar1 = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorInclinar1 = null;
                }
                let valorInclinar2;
                let quantificadorInclinar2;
                if (this.simbolos[this.atual].tipo === "VIRGULA") {
                    this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método 'inclinar'.");
                    valorInclinar2 = this.avancarEDevolverAnterior();
                    quantificadorInclinar2 = this.avancarEDevolverAnterior();
                }
                else {
                    valorInclinar2 = null;
                    quantificadorInclinar2 = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'inclinar'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorInclinar1,
                    quantificadorInclinar1,
                    valorInclinar2,
                    quantificadorInclinar2,
                ]);
            case "inclinar-horizontal":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'inclinar-horizontal'.");
                const valorInclinarX = this.avancarEDevolverAnterior();
                let quantificadorInclinarX;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorInclinarX = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorInclinarX = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'inclinar-horizontal'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorInclinarX,
                    quantificadorInclinarX,
                ]);
            case "inclinar-vertical":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'inclinar-vertical'.");
                const valorInclinarY = this.avancarEDevolverAnterior();
                let quantificadorInclinarY;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorInclinarY = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorInclinarY = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'inclinar-vertical'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorInclinarY,
                    quantificadorInclinarY,
                ]);
            case "inverter":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'inverter'.");
                const valorInverter = this.avancarEDevolverAnterior();
                let quantificadorInverter;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorInverter = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorInverter = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'inverter'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorInverter,
                    quantificadorInverter,
                ]);
            case "limitar":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'limitar'.");
                const valorMin = this.avancarEDevolverAnterior();
                const quantificadorMin = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método 'limitar'.");
                const valorMed = this.avancarEDevolverAnterior();
                const quantificadorMed = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após segundo argumento do método 'limitar'.");
                const valorMax = this.avancarEDevolverAnterior();
                const quantificadorMax = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método limitar.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorMin,
                    quantificadorMin,
                    valorMed,
                    quantificadorMed,
                    valorMax,
                    quantificadorMax,
                ]);
            case "linear":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'linear'.");
                const valor1 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método linear.");
                const valor2 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após segundo argumento do método linear.");
                const valor3 = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após terceiro argumento do método linear.");
                return new seletor_valor_1.SeletorValor(lexema, [valor1, valor2, valor3]);
            case "minmax":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'minmax'.");
                const valor01 = this.avancarEDevolverAnterior();
                let parametro01 = null;
                if (Number(valor01["lexema"])) {
                    const quantificador01 = this.avancarEDevolverAnterior();
                    parametro01 = `${valor01["lexema"]}${quantificador01["lexema"]}`;
                }
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método minmax.");
                const valor02 = this.avancarEDevolverAnterior();
                let parametro02 = null;
                if (Number(valor02["lexema"])) {
                    const quantificador02 = this.avancarEDevolverAnterior();
                    parametro02 = `${valor02["lexema"]}${quantificador02["lexema"]}`;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método minmax.");
                if (parametro01 !== null) {
                    return new seletor_valor_1.SeletorValor(lexema, [
                        parametro01,
                        valor02["lexema"],
                    ]);
                }
                else if (parametro02 !== null) {
                    return new seletor_valor_1.SeletorValor(lexema, [
                        valor01["lexema"],
                        parametro02,
                    ]);
                }
            case "opacar":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'opacar'.");
                const valorOpaco = this.avancarEDevolverAnterior();
                let quantificadorOpaco;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorOpaco = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorOpaco = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'opacar'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorOpaco,
                    quantificadorOpaco,
                ]);
            case "passos":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'passos'.");
                const valorNumerico = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método passos.");
                const termoSalto = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após segundo argumento do método passos.");
                return new seletor_valor_1.SeletorValor(lexema, [valorNumerico, termoSalto]);
            case "perspectivar":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'perspectivar'.");
                const valorPerspectivar = this.avancarEDevolverAnterior();
                let quantificadorPerspectivar;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorPerspectivar = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorPerspectivar = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'perspectivar'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorPerspectivar,
                    quantificadorPerspectivar,
                ]);
            case "projetar-sombra":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'projetar-sombra'.");
                let corSombra = null;
                if (this.simbolos[this.atual].tipo === "QUALITATIVO") {
                    corSombra = this.avancarEDevolverAnterior();
                }
                const valorSombra1 = this.avancarEDevolverAnterior();
                const quantificadorSombra1 = this.avancarEDevolverAnterior();
                const valorSombra2 = this.avancarEDevolverAnterior();
                const quantificadorSombra2 = this.avancarEDevolverAnterior();
                let valorSombra3;
                let quantificadorSombra3;
                if (this.simbolos[this.atual].tipo === "NUMERO") {
                    valorSombra3 = this.avancarEDevolverAnterior();
                    quantificadorSombra3 = this.avancarEDevolverAnterior();
                }
                else {
                    valorSombra3 = null;
                    quantificadorSombra3 = null;
                }
                if (this.simbolos[this.atual].tipo === "QUALITATIVO") {
                    corSombra = this.avancarEDevolverAnterior();
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'projetar-sombra'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorSombra1,
                    quantificadorSombra1,
                    valorSombra2,
                    quantificadorSombra2,
                    valorSombra3,
                    quantificadorSombra3,
                    corSombra,
                ]);
            case "raio":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'raio'.");
                let posicaoRaio;
                if (this.simbolos[this.atual].tipo === "QUALITATIVO") {
                    posicaoRaio = this.avancarEDevolverAnterior();
                }
                else {
                    posicaoRaio = null;
                }
                const numeroRaio = this.avancarEDevolverAnterior();
                const quantificadorRaio = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após argumentos de método 'raio'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    posicaoRaio,
                    numeroRaio,
                    quantificadorRaio,
                ]);
            case "rgb":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'rgb'.");
                const vermelho = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após argumento de cor vermelha.");
                const verde = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após argumento de cor verde.");
                const azul = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após argumentos de método 'rgb'.");
                return new seletor_valor_1.SeletorValor(lexema, [vermelho, verde, azul]);
            case "rgba":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'rgba'.");
                const vermelhoRgba = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após argumento de cor vermelha.");
                const verdeRgba = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após argumento de cor verde.");
                const azulRgba = this.avancarEDevolverAnterior();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após argumentos de método 'rgba'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    vermelhoRgba,
                    verdeRgba,
                    azulRgba,
                ]);
            case "rotacionar":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'rotacionar'.");
                const valorRotacionar = this.avancarEDevolverAnterior();
                let quantificadorRotacionar;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorRotacionar = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorRotacionar = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'rotacionar'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorRotacionar,
                    quantificadorRotacionar,
                ]);
            case "rotacionar-eixo-z":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'rotacionar-eixo-z'.");
                const valorRotacionarZ = this.avancarEDevolverAnterior();
                let quantificadorRotacionarZ;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorRotacionarZ = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorRotacionarZ = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'rotacionar-eixo-z'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorRotacionarZ,
                    quantificadorRotacionarZ,
                ]);
            case "rotacionar-horizontal":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'rotacionar-horizontal'.");
                const valorRotacionarX = this.avancarEDevolverAnterior();
                let quantificadorRotacionarX;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorRotacionarX = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorRotacionarX = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'rotacionar-horizontal'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorRotacionarX,
                    quantificadorRotacionarX,
                ]);
            case "rotacionar-matiz":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'rotacionar-matiz'.");
                const valorRotacao = this.avancarEDevolverAnterior();
                let quantificadorRotacao;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorRotacao = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorRotacao = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'rotacionar-matiz'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorRotacao,
                    quantificadorRotacao,
                ]);
            case "rotacionar-vertical":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'rotacionar-vertical'.");
                const valorRotacionarY = this.avancarEDevolverAnterior();
                let quantificadorRotacionarY;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorRotacionarY = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorRotacionarY = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'rotacionar-vertical'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorRotacionarY,
                    quantificadorRotacionarY,
                ]);
            case "saturar":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'saturar'.");
                const valorSaturar = this.avancarEDevolverAnterior();
                let quantificadorSaturar;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorSaturar = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorSaturar = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'saturar'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorSaturar,
                    quantificadorSaturar,
                ]);
            case "sepia":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'sepia'.");
                const valorSepia = this.avancarEDevolverAnterior();
                let quantificadorSepia;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorSepia = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorSepia = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'sepia'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorSepia,
                    quantificadorSepia,
                ]);
            case "sépia":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'sépia'.");
                const valorSépia = this.avancarEDevolverAnterior();
                let quantificadorSépia;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorSépia = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorSépia = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'sépia'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorSépia,
                    quantificadorSépia,
                ]);
            case "translação":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação'.");
                const valorTranslacao1 = this.avancarEDevolverAnterior();
                let quantificadorTranslacao1;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranslacao1 = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranslacao1 = null;
                }
                let valorTranslacao2;
                let quantificadorTranslacao2;
                if (this.simbolos[this.atual].tipo === "VIRGULA") {
                    this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método 'translação'.");
                    valorTranslacao2 = this.avancarEDevolverAnterior();
                    quantificadorTranslacao2 = this.avancarEDevolverAnterior();
                }
                else {
                    valorTranslacao2 = null;
                    quantificadorTranslacao2 = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslacao1,
                    quantificadorTranslacao1,
                    valorTranslacao2,
                    quantificadorTranslacao2,
                ]);
            case "translacao":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação'.");
                const valorTranslacao01 = this.avancarEDevolverAnterior();
                let quantificadorTranlacao01;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranlacao01 = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranlacao01 = null;
                }
                let valorTranslacao02;
                let quantificadorTranlacao02;
                if (this.simbolos[this.atual].tipo === "VIRGULA") {
                    this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método 'translação'.");
                    valorTranslacao02 = this.avancarEDevolverAnterior();
                    quantificadorTranlacao02 = this.avancarEDevolverAnterior();
                }
                else {
                    valorTranslacao02 = null;
                    quantificadorTranlacao02 = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslacao01,
                    quantificadorTranlacao01,
                    valorTranslacao02,
                    quantificadorTranlacao02,
                ]);
            case "translação-3d":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação-3d'.");
                const valorTranslacao3d1 = this.avancarEDevolverAnterior();
                let quantificadorTranlacao3d1;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranlacao3d1 = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranlacao3d1 = null;
                }
                let valorTranslacao3d2;
                let quantificadorTranlacao3d2;
                if (this.simbolos[this.atual].tipo === "VIRGULA") {
                    this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método 'translação-3d'.");
                    valorTranslacao3d2 = this.avancarEDevolverAnterior();
                    if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                        quantificadorTranlacao3d2 =
                            this.avancarEDevolverAnterior();
                    }
                    else {
                        quantificadorTranlacao3d2 = null;
                    }
                }
                else {
                    valorTranslacao3d2 = null;
                    quantificadorTranlacao3d2 = null;
                }
                let valorTranslacao3d3;
                let quantificadorTranlacao3d3;
                if (this.simbolos[this.atual].tipo === "VIRGULA") {
                    this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método 'translação-3d'.");
                    valorTranslacao3d3 = this.avancarEDevolverAnterior();
                    if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                        quantificadorTranlacao3d3 =
                            this.avancarEDevolverAnterior();
                    }
                    else {
                        quantificadorTranlacao3d3 = null;
                    }
                }
                else {
                    valorTranslacao3d3 = null;
                    quantificadorTranlacao3d3 = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação-3d'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslacao3d1,
                    quantificadorTranlacao3d1,
                    valorTranslacao3d2,
                    quantificadorTranlacao3d2,
                    valorTranslacao3d3,
                    quantificadorTranlacao3d3,
                ]);
            case "translacao-3d":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação-3d'.");
                const valorTranslacao3d01 = this.avancarEDevolverAnterior();
                let quantificadorTranlacao3d01;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranlacao3d01 =
                        this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranlacao3d01 = null;
                }
                let valorTranslacao3d02;
                let quantificadorTranlacao3d02;
                if (this.simbolos[this.atual].tipo === "VIRGULA") {
                    this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método 'translação-3d'.");
                    valorTranslacao3d02 = this.avancarEDevolverAnterior();
                    if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                        quantificadorTranlacao3d02 =
                            this.avancarEDevolverAnterior();
                    }
                    else {
                        quantificadorTranlacao3d02 = null;
                    }
                }
                else {
                    valorTranslacao3d02 = null;
                    quantificadorTranlacao3d02 = null;
                }
                let valorTranslacao3d03;
                let quantificadorTranlacao3d03;
                if (this.simbolos[this.atual].tipo === "VIRGULA") {
                    this.consumir(foles_1.default.VIRGULA, "Esperado vírgula após primeiro argumento do método 'translação-3d'.");
                    valorTranslacao3d03 = this.avancarEDevolverAnterior();
                    if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                        quantificadorTranlacao3d03 =
                            this.avancarEDevolverAnterior();
                    }
                    else {
                        quantificadorTranlacao3d03 = null;
                    }
                }
                else {
                    valorTranslacao3d03 = null;
                    quantificadorTranlacao3d03 = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação-3d'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslacao3d01,
                    quantificadorTranlacao3d01,
                    valorTranslacao3d02,
                    quantificadorTranlacao3d02,
                    valorTranslacao3d03,
                    quantificadorTranlacao3d03,
                ]);
            case "translação-eixo-z":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação-eixo-z'.");
                const valorTranslaçaoZ = this.avancarEDevolverAnterior();
                let quantificadorTranslaçaoZ;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranslaçaoZ = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranslaçaoZ = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação-eixo-z'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslaçaoZ,
                    quantificadorTranslaçaoZ,
                ]);
            case "translacao-eixo-z":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação-eixo-z'.");
                const valorTranslacaoZ = this.avancarEDevolverAnterior();
                let quantificadorTranslacaoZ;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranslacaoZ = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranslacaoZ = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação-eixo-z'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslacaoZ,
                    quantificadorTranslacaoZ,
                ]);
            case "translação-horizontal":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação-horizontal'.");
                const valorTranslaçaoX = this.avancarEDevolverAnterior();
                let quantificadorTranslaçaoX;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranslaçaoX = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranslaçaoX = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação-horizontal'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslaçaoX,
                    quantificadorTranslaçaoX,
                ]);
            case "translacao-horizontal":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação-horizontal'.");
                const valorTranslacaoX = this.avancarEDevolverAnterior();
                let quantificadorTranslacaoX;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranslacaoX = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranslacaoX = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação-horizontal'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslacaoX,
                    quantificadorTranslacaoX,
                ]);
            case "translação-vertical":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação-vertical'.");
                const valorTranslaçaoY = this.avancarEDevolverAnterior();
                let quantificadorTranslaçaoY;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranslaçaoY = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranslaçaoY = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação-vertical'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslaçaoY,
                    quantificadorTranslaçaoY,
                ]);
            case "translacao-vertical":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'translação-vertical'.");
                const valorTranslacaoY = this.avancarEDevolverAnterior();
                let quantificadorTranslacaoY;
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    quantificadorTranslacaoY = this.avancarEDevolverAnterior();
                }
                else {
                    quantificadorTranslacaoY = null;
                }
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após método 'translação-vertical'.");
                return new seletor_valor_1.SeletorValor(lexema, [
                    valorTranslacaoY,
                    quantificadorTranslacaoY,
                ]);
            case "url":
                this.consumir(foles_1.default.PARENTESE_ESQUERDO, "Esperado parêntese esquerdo após método 'url'.");
                const url = this.validacaoUrl();
                this.consumir(foles_1.default.PARENTESE_DIREITO, "Esperado parêntese direito após argumento do método url.");
                return new seletor_valor_1.SeletorValor(lexema, [url]);
        }
        throw new Error(`Método ${lexema} não reconhecido em FolEs.`);
    }
    validacaoUrl() {
        const primeiroSimbolo = this.avancarEDevolverAnterior();
        switch (primeiroSimbolo.tipo) {
            case foles_1.default.IDENTIFICADOR:
                return this.validacaoUrlSimbolos(primeiroSimbolo);
            default:
                return this.validacaoUrlTexto(primeiroSimbolo.literal);
        }
    }
    validacaoUrlSimbolos(primeiroSimbolo) {
        if (!["http", "https"].includes(primeiroSimbolo.lexema.toLowerCase())) {
            throw new Error(`URL inválida. URLs devem começar com 'http' ou 'https'.`);
        }
        this.consumir(foles_1.default.DOIS_PONTOS, `Esperado dois-pontos após '${primeiroSimbolo.lexema}'.`);
        this.consumir(foles_1.default.BARRA, `Esperado barra após '${primeiroSimbolo.lexema + ":"}'`);
        this.consumir(foles_1.default.BARRA, `Esperado segunda barra após '${primeiroSimbolo.lexema + ":/"}'`);
        let url = `${primeiroSimbolo.lexema}://`;
        while (this.simbolos[this.atual].tipo !== foles_1.default.PARENTESE_DIREITO) {
            let proximoSimbolo = this.avancarEDevolverAnterior();
            url += proximoSimbolo.literal || proximoSimbolo.lexema;
        }
        this.validacaoUrlTexto(url);
        return url;
    }
    validacaoUrlTexto(textoUrl) {
        if (!/^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/gi.test(textoUrl)) {
            throw new Error(`URL ${textoUrl} inválida.`);
        }
        return textoUrl;
    }
    valoresModificador() {
        const modificadores = [];
        while (this.simbolos[this.atual].hasOwnProperty("tipo") &&
            this.simbolos[this.atual].tipo !== foles_1.default.PONTO_E_VIRGULA) {
            const valorModificador = this.avancarEDevolverAnterior();
            switch (valorModificador.tipo) {
                case foles_1.default.METODO:
                    const metodo = this.resolverMetodo(valorModificador.lexema);
                    modificadores.push(metodo);
                default:
                    const modificador = valorModificador;
                    modificadores.push(modificador);
            }
        }
        return modificadores;
    }
    tratarAtribuicaoAbreviada(valoresModificador) {
        let atribuicaoAbreviada = "";
        for (let i = 0; i < valoresModificador.length; i += 1) {
            if (i === 0) {
                atribuicaoAbreviada += `${valoresModificador[i].lexema}`;
            }
            else {
                switch (valoresModificador[i].tipo) {
                    case foles_1.default.QUANTIFICADOR:
                        atribuicaoAbreviada += `${valoresModificador[i].lexema}`;
                        break;
                    case foles_1.default.VIRGULA:
                        atribuicaoAbreviada += ",";
                        break;
                    default:
                        atribuicaoAbreviada += " ";
                        atribuicaoAbreviada += `${valoresModificador[i].lexema}`;
                        break;
                }
            }
        }
        return atribuicaoAbreviada;
    }
    tratarValorNumerico(modificador) {
        if (!valor_numerico_1.ValorNumerico.includes(modificador.lexema)) {
            if (valor_numerico_1.ValorNumericoComQuantificador.includes(modificador.lexema)) {
                if (this.simbolos[this.atual].tipo === "QUANTIFICADOR") {
                    return true;
                }
                else {
                    return false;
                }
            }
            else {
                return true;
            }
        }
        return false;
    }
    resolverPseudoclasse() {
        let pseudoclasse;
        if (this.verificarTipoSimboloAtual(foles_1.default.DOIS_PONTOS)) {
            this.avancarEDevolverAnterior();
            pseudoclasse = this.consumir(foles_1.default.PSEUDO_CLASSE, "Esperado nome de pseudoclasse.");
            return new seletor_pseudoclasse_1.SeletorPseudoclasse(pseudoclasse.lexema, {
                linha: pseudoclasse.linha,
                colunaInicial: pseudoclasse.colunaInicial,
                colunaFinal: pseudoclasse.colunaFinal,
            });
        }
        return pseudoclasse;
    }
    seletorPorEspacoReservado() {
        const simboloSeletor = this.avancarEDevolverAnterior();
        // Aqui não tem problema o espaço reservado usar um nome de estrutura.
        if (![
            foles_1.default.IDENTIFICADOR,
            foles_1.default.ESTRUTURA,
        ].includes(this.simbolos[this.atual].tipo)) {
            throw this.erro(this.simbolos[this.atual], "Esperado identificador válido para espaço reservado.");
        }
        const nomeEspacoReservado = this.avancarEDevolverAnterior();
        return new seletor_espaco_reservado_1.SeletorEspacoReservado(nomeEspacoReservado.lexema, {
            linha: simboloSeletor.linha,
            colunaInicial: simboloSeletor.colunaInicial,
            colunaFinal: simboloSeletor.colunaFinal,
        });
    }
    seletorPorEstrutura() {
        const simboloSeletor = this.avancarEDevolverAnterior();
        const pseudoclasse = this.resolverPseudoclasse();
        return new seletores_1.SeletorEstrutura(new seletor_estruturas_lmht_1.SeletorEstruturasLmht(simboloSeletor.lexema, {
            linha: simboloSeletor.linha,
            colunaInicial: simboloSeletor.colunaInicial,
            colunaFinal: simboloSeletor.colunaFinal,
        }), pseudoclasse);
    }
    seletorPorId() {
        this.atual += 1;
        const simboloSeletor = this.avancarEDevolverAnterior();
        const pseudoclasse = this.resolverPseudoclasse();
        return new seletores_1.SeletorId(simboloSeletor.lexema, pseudoclasse, {
            linha: simboloSeletor.linha,
            colunaInicial: simboloSeletor.colunaInicial,
            colunaFinal: simboloSeletor.colunaFinal,
        });
    }
    seletorPorNomeDeClasse() {
        this.atual += 1;
        const simboloSeletor = this.avancarEDevolverAnterior();
        const pseudoclasse = this.resolverPseudoclasse();
        return new seletores_1.SeletorClasse(simboloSeletor.lexema, pseudoclasse, {
            linha: simboloSeletor.linha,
            colunaInicial: simboloSeletor.colunaInicial,
            colunaFinal: simboloSeletor.colunaFinal,
        });
    }
    declaracaoVariavel() {
        let nomeVariavel;
        let simboloValorVariavel;
        let valorVariavel;
        let quantificadorVariavel;
        while (this.simbolos[this.atual].tipo !== foles_1.default.PONTO_E_VIRGULA) {
            this.consumir(foles_1.default.CIFRAO, "Esperado cifrão antes de declaração de variável.");
            const declaracaoVariavel = this.consumir(foles_1.default.VARIAVEL, "Esperada nomenclatura para declaração de variável.");
            nomeVariavel = declaracaoVariavel.lexema;
            this.consumir(foles_1.default.DOIS_PONTOS, "Esperado ':' após declaração de variável.");
            switch (this.simbolos[this.atual].tipo) {
                case foles_1.default.IDENTIFICADOR:
                    simboloValorVariavel = this.consumir(foles_1.default.IDENTIFICADOR, "Esperado nome do modificador após declaração de variável.");
                    valorVariavel = simboloValorVariavel.lexema;
                    break;
                case foles_1.default.QUALITATIVO:
                    simboloValorVariavel = this.consumir(foles_1.default.QUALITATIVO, "Esperado qualitativo após declaração de variável.");
                    valorVariavel = simboloValorVariavel.lexema;
                    break;
                case foles_1.default.NUMERO:
                    simboloValorVariavel = this.consumir(foles_1.default.NUMERO, "Esperado valor numérico após declaração de variável");
                    valorVariavel = simboloValorVariavel.lexema;
                    if (this.simbolos[this.atual].tipo ===
                        foles_1.default.QUANTIFICADOR) {
                        const quantificador = this.consumir(foles_1.default.QUANTIFICADOR, "Esperado quantificador após valor numérico atribuído à variável.");
                        quantificadorVariavel = quantificador.lexema;
                    }
                    break;
                case foles_1.default.METODO:
                    this.consumir(foles_1.default.METODO, "Esperada declaração de método no valor atribuído à variável.");
                    const tratarMetodo = this.resolverMetodo(this.simbolos[this.atual - 1].lexema);
                    valorVariavel = tratarMetodo;
                    break;
                default:
                    console.log("Não deveria cair aqui!");
            }
        }
        this.consumir(foles_1.default.PONTO_E_VIRGULA, "Esperado ponto e vírgula após atribuição de valor à variável");
        const variavel = {
            nome: nomeVariavel,
            valor: valorVariavel,
            quantificador: quantificadorVariavel ? quantificadorVariavel : null,
        };
        return variavel;
    }
    /**
     * Resolve os seletores.
     * @param espacoReservado
     */
    resolverSeletores(espacoReservado = null) {
        const seletores = [];
        do {
            switch (this.simbolos[this.atual].tipo) {
                case foles_1.default.ESTRUTURA:
                    seletores.push(this.seletorPorEstrutura());
                    break;
                case foles_1.default.PERCENTUAL:
                    seletores.push(this.seletorPorEspacoReservado());
                    break;
                case foles_1.default.PONTO:
                    seletores.push(this.seletorPorNomeDeClasse());
                    break;
                case foles_1.default.CERQUILHA:
                    seletores.push(this.seletorPorId());
                    break;
            }
        } while (this.simbolos[this.atual].tipo === foles_1.default.VIRGULA);
        return seletores;
    }
    resolverModificador() {
        const modificador = this.consumir(foles_1.default.IDENTIFICADOR, "Esperado nome do modificador.");
        this.consumir(foles_1.default.DOIS_PONTOS, "Esperado ':' após nome do modificador.");
        let valoresModificador = this.valoresModificador();
        let quantificador;
        for (const [index, valorModificador] of valoresModificador.entries()) {
            if (valorModificador.hasOwnProperty("tipo") &&
                valorModificador.tipo === foles_1.default.NUMERO) {
                const tratarValorNumerico = this.tratarValorNumerico(valorModificador);
                if (tratarValorNumerico) {
                    quantificador = valoresModificador[index + 1];
                }
            }
            if (valorModificador.hasOwnProperty("tipo") &&
                valorModificador.tipo === foles_1.default.METODO) {
                valoresModificador.splice(index, 1);
            }
        }
        // TODO: Pensar num teste melhor pra isso.
        /*if (!(valorModificador instanceof Metodo)) {
            quantificador = this.avancarEDevolverAnterior();
        }*/
        if (valoresModificador.length === 0) {
            const proximoSimbolo = this.avancarEDevolverAnterior();
            valoresModificador.push(proximoSimbolo);
        }
        this.consumir(foles_1.default.PONTO_E_VIRGULA, `Esperado ';' após declaração de valor de modificador '${modificador.lexema}'.`);
        if (valoresModificador[0].tipo === foles_1.default.CIFRAO) {
            const valorVariavel = true;
            const classeModificadora = new superclasse_1.SeletorModificador(modificador.lexema, valoresModificador[1].lexema, quantificador && quantificador.hasOwnProperty("lexema")
                ? quantificador.lexema
                : quantificador, {
                linha: modificador.linha,
                colunaInicial: modificador.colunaInicial,
                colunaFinal: modificador.colunaFinal,
            }, valorVariavel);
            return classeModificadora;
        }
        if (valoresModificador.length < 2 ||
            valoresModificador.length <= 2 && (quantificador && quantificador.hasOwnProperty("lexema"))) {
            const classeModificadora = new superclasse_1.SeletorModificador(modificador.lexema, valoresModificador[0].hasOwnProperty("lexema")
                ? valoresModificador[0].lexema
                : valoresModificador[0], quantificador && quantificador.hasOwnProperty("lexema")
                ? quantificador.lexema
                : quantificador, {
                linha: modificador.linha,
                colunaInicial: modificador.colunaInicial,
                colunaFinal: modificador.colunaFinal,
            });
            return classeModificadora;
        }
        if (valoresModificador[0].tipo === foles_1.default.PONTO) {
            const valorComPonto = `${valoresModificador[0].lexema}${valoresModificador[1].lexema}`;
            const classeModificadora = new superclasse_1.SeletorModificador(modificador.lexema, valorComPonto, quantificador && quantificador.hasOwnProperty("lexema")
                ? quantificador.lexema
                : quantificador, {
                linha: modificador.linha,
                colunaInicial: modificador.colunaInicial,
                colunaFinal: modificador.colunaFinal,
            });
            return classeModificadora;
        }
        const atribuicaoAbreviada = this.tratarAtribuicaoAbreviada(valoresModificador);
        const classeModificadora = new superclasse_1.SeletorModificador(modificador.lexema, atribuicaoAbreviada, quantificador && quantificador.hasOwnProperty("lexema")
            ? quantificador.lexema
            : quantificador, {
            linha: modificador.linha,
            colunaInicial: modificador.colunaInicial,
            colunaFinal: modificador.colunaFinal,
        });
        return classeModificadora;
    }
    resolverModificadoresEDeclaracoesAninhadas() {
        this.consumir(foles_1.default.CHAVE_ESQUERDA, "Esperado '{' após declaração de seletor.");
        const modificadores = [];
        const declaracoesAninhadas = [];
        while (!this.verificarTipoSimboloAtual(foles_1.default.CHAVE_DIREITA)) {
            switch (this.simbolos[this.atual].tipo) {
                case foles_1.default.IDENTIFICADOR:
                    const modificador = this.resolverModificador();
                    modificadores.push(modificador);
                    break;
                default:
                    const declaracaoAninhada = this.declaracao();
                    declaracoesAninhadas.push(declaracaoAninhada);
                    break;
            }
        }
        this.avancarEDevolverAnterior(); // chave direita
        return {
            modificadores,
            declaracoesAninhadas,
        };
    }
    declaracao() {
        if (this.estaNoFinal())
            return null;
        switch (this.simbolos[this.atual].tipo) {
            case foles_1.default.IMPORTAR:
                this.avancarEDevolverAnterior();
                const caminhoArquivo = this.simbolos[this.atual];
                const resultadoImportacao = this.importador.importar(caminhoArquivo.literal, false);
                this.simbolos.splice(this.atual - 1, 2, ...resultadoImportacao[1].simbolos);
                this.atual -= 1;
                return null;
            case foles_1.default.CIFRAO:
                const variavel = this.declaracaoVariavel();
                return new declaracao_variavel_1.DeclaracaoVariavel(variavel.nome, variavel.valor, variavel.quantificador);
            default:
                const seletores = this.resolverSeletores();
                const modificadoresEDeclaracoesAninhadas = this.resolverModificadoresEDeclaracoesAninhadas();
                return new declaracoes_1.BlocoDeclaracao(seletores, modificadoresEDeclaracoesAninhadas.modificadores, modificadoresEDeclaracoesAninhadas.declaracoesAninhadas);
        }
    }
    analisar(simbolos) {
        this.simbolos = simbolos;
        this.erros = [];
        this.atual = 0;
        const declaracoes = [];
        while (!this.estaNoFinal()) {
            declaracoes.push(this.declaracao());
            this.referenciaDeclaracoes = declaracoes;
        }
        return declaracoes.filter((d) => d);
    }
}
exports.AvaliadorSintatico = AvaliadorSintatico;
//# sourceMappingURL=avaliador-sintatico.js.map