UNPKG

@designliquido/foles

Version:

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

314 lines 10.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Lexador = void 0; const simbolo_1 = require("./simbolo"); const foles_1 = __importDefault(require("./palavras-reservadas/foles")); const foles_2 = __importDefault(require("../tipos-de-simbolos/foles")); /** * O Lexador de FolEs, baseado no Lexador de [Delégua](https://github.com/DesignLiquido/delegua/blob/principal/fontes/lexador/lexador.ts). */ class Lexador { constructor() { this.codigo = [""]; this.simbolos = []; this.erros = []; this.atual = 0; this.linha = 0; this.inicioSimbolo = 0; } /** * Indica se o código está na última linha. * @returns Verdadeiro se contador de linhas está na última linha. * Falso caso contrário. */ eUltimaLinha() { return this.linha >= this.codigo.length - 1; } eFinalDoCodigo() { return (this.eUltimaLinha() && this.codigo[this.codigo.length - 1].length <= this.atual); } eFinalDaLinha() { if (this.codigo.length === this.linha) { return true; } return this.atual >= this.codigo[this.linha].length; } caractereAtual() { if (this.eFinalDaLinha()) return "\0"; return this.codigo[this.linha].charAt(this.atual); } proximoSimbolo() { return this.codigo[this.linha].charAt(this.atual + 1); } eAlfabeto(caractere) { const acentuacoes = [ "á", "Á", "ã", "Ã", "â", "Â", "à", "À", "é", "É", "ê", "Ê", "í", "Í", "ó", "Ó", "õ", "Õ", "ô", "Ô", "ú", "Ú", "ç", "Ç", "_", "-", ]; return ((caractere >= "a" && caractere <= "z") || (caractere >= "A" && caractere <= "Z") || acentuacoes.includes(caractere)); } eDigito(caractere) { return caractere >= "0" && caractere <= "9"; } eAlfabetoOuDigito(caractere) { return this.eDigito(caractere) || this.eAlfabeto(caractere); } avancar() { this.atual += 1; if (this.eFinalDaLinha() && !this.eUltimaLinha()) { this.linha++; this.atual = 0; } } adicionarSimbolo(tipo, literal = null, lexema = null) { let texto; texto = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual); if (tipo === foles_2.default.TEXTO) { texto = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual + 1); } this.simbolos.push(new simbolo_1.Simbolo(tipo, texto || lexema, literal, this.linha + 1, this.inicioSimbolo + 1, this.atual)); } analisarNumero() { while (this.eDigito(this.caractereAtual())) { this.avancar(); } if (this.caractereAtual() == "." && this.eDigito(this.proximoSimbolo())) { this.avancar(); while (this.eDigito(this.caractereAtual())) { this.avancar(); } } const numeroCompleto = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual); this.adicionarSimbolo(foles_2.default.NUMERO, parseFloat(numeroCompleto)); } analisarDiretiva() { this.avancar(); while (this.eAlfabetoOuDigito(this.caractereAtual())) { this.avancar(); } const nomeDiretiva = this.codigo[this.linha].substring(this.inicioSimbolo + 1, this.atual); switch (nomeDiretiva) { case "importar": this.avancar(); // Espaço esperado entre @importar e o texto do arquivo this.adicionarSimbolo(foles_2.default.IMPORTAR, null, null); break; default: throw new Error(`Diretiva não reconhecida: ${nomeDiretiva}`); } } analisarTexto(delimitador = '"') { while (this.caractereAtual() !== delimitador && !this.eFinalDoCodigo()) { this.avancar(); } if (this.eFinalDoCodigo()) { this.erros.push({ linha: this.linha + 1, caractere: this.codigo[this.linha].charAt(this.atual - 1), mensagem: "Texto não finalizado.", }); return; } const valor = this.codigo[this.linha].substring(this.inicioSimbolo + 1, this.atual); this.adicionarSimbolo(foles_2.default.TEXTO, valor); } identificarVariaveis() { if (this.simbolos.length !== 0) { const indexAnterior = this.simbolos.length - 1; return this.simbolos[indexAnterior].tipo === foles_2.default.CIFRAO; } } identificarPalavraChave() { while (this.eAlfabetoOuDigito(this.caractereAtual())) { this.avancar(); } const variavel = this.identificarVariaveis(); if (variavel) return this.adicionarSimbolo(foles_2.default.VARIAVEL); const codigo = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual); const tipo = codigo in foles_1.default ? foles_1.default[codigo] : foles_2.default.IDENTIFICADOR; this.adicionarSimbolo(tipo); } avancarParaProximaLinha() { this.linha++; this.atual = 0; } encontrarFimComentarioAsterisco() { while (!this.eFinalDoCodigo()) { this.avancar(); if (this.caractereAtual() === "*" && this.proximoSimbolo() === "/") { this.avancar(); this.avancar(); break; } } } analisarToken() { const caractere = this.caractereAtual(); switch (caractere) { case "{": this.adicionarSimbolo(foles_2.default.CHAVE_ESQUERDA); this.avancar(); break; case "}": this.adicionarSimbolo(foles_2.default.CHAVE_DIREITA); this.avancar(); break; case "(": this.adicionarSimbolo(foles_2.default.PARENTESE_ESQUERDO); this.avancar(); break; case ")": this.adicionarSimbolo(foles_2.default.PARENTESE_DIREITO); this.avancar(); break; case ":": this.adicionarSimbolo(foles_2.default.DOIS_PONTOS); this.avancar(); break; case ";": this.adicionarSimbolo(foles_2.default.PONTO_E_VIRGULA); this.avancar(); break; case ",": this.adicionarSimbolo(foles_2.default.VIRGULA, null, ","); this.avancar(); break; case "%": if (this.atual === 0) { this.adicionarSimbolo(foles_2.default.PERCENTUAL, null, "%"); } else { this.adicionarSimbolo(foles_2.default.QUANTIFICADOR, null, "%"); } this.avancar(); break; case ".": this.adicionarSimbolo(foles_2.default.PONTO, null, "."); this.avancar(); break; case "#": if (this.atual === 0) { this.adicionarSimbolo(foles_2.default.CERQUILHA, null, "#"); } else { this.adicionarSimbolo(foles_2.default.METODO, null, "#"); } this.avancar(); break; case " ": case "\0": case "\r": case "\t": case ";": this.avancar(); break; case "/": // Se houver um dois-pontos antes da primeira barra, pode ser uma url. if (this.atual > 0 && this.codigo[this.linha].charAt(this.atual - 1) === ":") { this.avancar(); this.adicionarSimbolo(foles_2.default.BARRA, null, "/"); break; } else { this.avancar(); switch (this.caractereAtual()) { case "/": this.avancarParaProximaLinha(); break; case "*": this.encontrarFimComentarioAsterisco(); break; default: this.adicionarSimbolo(foles_2.default.BARRA, null, "/"); break; } } break; case '"': this.avancar(); this.analisarTexto('"'); this.avancar(); break; case "'": this.avancar(); this.analisarTexto("'"); this.avancar(); break; case "@": this.analisarDiretiva(); break; case "$": this.adicionarSimbolo(foles_2.default.CIFRAO, null, "$"); this.avancar(); break; default: if (this.eDigito(caractere)) this.analisarNumero(); else if (this.eAlfabeto(caractere)) this.identificarPalavraChave(); else { this.erros.push({ linha: this.linha + 1, caractere: caractere, mensagem: "Caractere inesperado.", }); this.avancar(); } } } mapear(codigo) { this.atual = 0; this.linha = 0; this.inicioSimbolo = 0; this.erros = []; this.simbolos = []; this.codigo = codigo || [""]; while (!this.eFinalDoCodigo()) { this.inicioSimbolo = this.atual; this.analisarToken(); } return { simbolos: this.simbolos, erros: this.erros, }; } } exports.Lexador = Lexador; //# sourceMappingURL=lexador.js.map