UNPKG

@designliquido/delegua

Version:

Linguagem de programação simples e moderna usando português estruturado.

400 lines 14.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LexadorPrisma = void 0; const browser_process_hrtime_1 = __importDefault(require("browser-process-hrtime")); const simbolo_1 = require("../simbolo"); const prisma_1 = require("./palavras-reservadas/prisma"); const prisma_2 = __importDefault(require("../../tipos-de-simbolos/prisma")); /** * O Lexador é responsável por transformar o código em uma coleção de tokens de linguagem. * Cada token de linguagem é representado por um tipo, um lexema e informações da linha de código em que foi expresso. * Também é responsável por mapear as palavras reservadas da linguagem, que não podem ser usadas por outras * estruturas, tais como nomes de variáveis, funções, literais, classes e assim por diante. * * Este lexador é específico para o dialeto Prisma da linguagem Delégua. */ class LexadorPrisma { constructor(performance = false) { this.performance = performance; this.simbolos = []; this.erros = []; this.inicioSimbolo = 0; this.atual = 0; this.linha = 0; } eDigito(caractere) { return caractere >= '0' && caractere <= '9'; } eAlfabeto(caractere) { const acentuacoes = [ 'á', 'Á', 'ã', 'Ã', 'â', 'Â', 'à', 'À', 'é', 'É', 'ê', 'Ê', 'í', 'Í', 'ó', 'Ó', 'õ', 'Õ', 'ô', 'Ô', 'ú', 'Ú', 'ç', 'Ç', '_', ]; return ((caractere >= 'a' && caractere <= 'z') || (caractere >= 'A' && caractere <= 'Z') || acentuacoes.includes(caractere)); } eAlfabetoOuDigito(caractere) { return this.eDigito(caractere) || this.eAlfabeto(caractere); } /** * 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; } eFinalDaLinha() { return this.atual >= this.codigo[this.linha].length; } eFinalDoCodigo() { return this.eUltimaLinha() && this.eFinalDaLinha(); } simboloAtual() { if (this.eFinalDaLinha()) { if (this.eUltimaLinha()) { return '\0'; } return '\n'; } return this.codigo[this.linha].charAt(this.atual); } proximoSimbolo() { if (this.atual + 1 >= this.codigo[this.linha].length) return '\n'; return this.codigo[this.linha].charAt(this.atual + 1); } simboloAnterior() { if (this.atual === 0) return '\0'; return this.codigo[this.linha].charAt(this.atual - 1); } avancar() { if (this.eFinalDaLinha() && !this.eUltimaLinha()) { this.linha++; this.atual = 0; } else { this.atual++; } } adicionarSimbolo(tipo, literal = null) { const texto = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual); const comprimento = Math.max(texto.length, 1); const colunaInicio = this.inicioSimbolo + 1; const colunaFim = this.inicioSimbolo + comprimento; this.simbolos.push(new simbolo_1.Simbolo(tipo, texto, literal, this.linha + 1, this.hashArquivo, colunaInicio, colunaFim)); } analisarTexto(delimitador = '"') { const inicioTexto = this.linha; while (this.simboloAtual() !== delimitador && !this.eFinalDoCodigo()) { this.avancar(); } if (this.eFinalDoCodigo()) { this.erros.push({ linha: inicioTexto + 1, caractere: delimitador, mensagem: 'Texto não finalizado.', }); return; } const valor = this.codigo[this.linha].substring(this.inicioSimbolo + 1, this.atual); this.adicionarSimbolo(prisma_2.default.TEXTO, valor); this.avancar(); } lerTexto() { this.analisarTexto('"'); } analisarNumero() { while (this.eDigito(this.simboloAtual())) { this.avancar(); } if (this.simboloAtual() === '.' && this.eDigito(this.proximoSimbolo())) { this.avancar(); while (this.eDigito(this.simboloAtual())) { this.avancar(); } } const numero = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual); this.adicionarSimbolo(prisma_2.default.NUMERO, Number(numero)); } lerNumero() { this.analisarNumero(); } identificarPalavraChave() { while (this.eAlfabetoOuDigito(this.simboloAtual())) { this.avancar(); } const textoPalavraChave = this.codigo[this.linha].substring(this.inicioSimbolo, this.atual); const tipo = textoPalavraChave in prisma_1.palavrasReservadas ? prisma_1.palavrasReservadas[textoPalavraChave] : prisma_2.default.IDENTIFICADOR; this.simbolos.push(new simbolo_1.Simbolo(tipo, textoPalavraChave, null, this.linha + 1, this.hashArquivo)); } analisarToken() { const caractere = this.simboloAtual(); switch (caractere) { case ' ': case '\t': case '\r': case '\n': this.avancar(); break; case '(': this.adicionarSimbolo(prisma_2.default.PARENTESE_ESQUERDO); this.avancar(); break; case ')': this.adicionarSimbolo(prisma_2.default.PARENTESE_DIREITO); this.avancar(); break; case '{': this.adicionarSimbolo(prisma_2.default.CHAVE_ESQUERDA); this.avancar(); break; case '}': this.adicionarSimbolo(prisma_2.default.CHAVE_DIREITA); this.avancar(); break; case '[': this.adicionarSimbolo(prisma_2.default.COLCHETE_ESQUERDO); this.avancar(); break; case ']': this.adicionarSimbolo(prisma_2.default.COLCHETE_DIREITO); this.avancar(); break; case ',': this.adicionarSimbolo(prisma_2.default.VIRGULA); this.avancar(); break; case '.': this.avancar(); if (this.simboloAtual() === '.') { this.avancar(); this.adicionarSimbolo(prisma_2.default.CONCATENACAO); } else { this.adicionarSimbolo(prisma_2.default.PONTO); } break; case '#': this.adicionarSimbolo(prisma_2.default.COMPRIMENTO); this.avancar(); break; case ';': this.adicionarSimbolo(prisma_2.default.PONTO_E_VIRGULA); this.avancar(); break; case ':': this.adicionarSimbolo(prisma_2.default.DOIS_PONTOS); this.avancar(); break; case '?': this.adicionarSimbolo(prisma_2.default.INTERROGACAO); this.avancar(); break; case '=': this.avancar(); if (this.simboloAtual() === '=') { this.adicionarSimbolo(prisma_2.default.IGUAL_IGUAL); this.avancar(); } else { this.adicionarSimbolo(prisma_2.default.IGUAL); } break; case '!': this.avancar(); if (this.simboloAtual() === '=') { this.adicionarSimbolo(prisma_2.default.DIFERENTE); this.avancar(); } else { this.adicionarSimbolo(prisma_2.default.NEGACAO); } break; case '<': this.avancar(); if (this.simboloAtual() === '=') { this.adicionarSimbolo(prisma_2.default.MENOR_IGUAL); this.avancar(); } else if (this.simboloAtual() === '<') { this.adicionarSimbolo(prisma_2.default.MENOR_MENOR); this.avancar(); } else { this.adicionarSimbolo(prisma_2.default.MENOR); } break; case '>': this.avancar(); if (this.simboloAtual() === '=') { this.adicionarSimbolo(prisma_2.default.MAIOR_IGUAL); this.avancar(); } else if (this.simboloAtual() === '>') { this.adicionarSimbolo(prisma_2.default.MAIOR_MAIOR); this.avancar(); } else { this.adicionarSimbolo(prisma_2.default.MAIOR); } break; case '+': this.avancar(); if (this.simboloAtual() === '=') { this.adicionarSimbolo(prisma_2.default.MAIS_IGUAL); this.avancar(); } else { this.adicionarSimbolo(prisma_2.default.ADICAO); } break; case '-': this.avancar(); if (this.simboloAtual() === '>') { this.adicionarSimbolo(prisma_2.default.SETA); this.avancar(); } else { this.adicionarSimbolo(prisma_2.default.SUBTRACAO); } break; case '*': this.avancar(); if (this.simboloAtual() === '*') { this.adicionarSimbolo(prisma_2.default.EXPONENCIACAO); this.avancar(); } else { this.adicionarSimbolo(prisma_2.default.MULTIPLICACAO); } break; case '/': this.avancar(); if (this.simboloAtual() === '/') { // Comentário de linha — ignorar até o final da linha this.atual = this.codigo[this.linha].length; } else if (this.simboloAtual() === '*') { // Comentário de bloco this.avancar(); while (!this.eFinalDoCodigo()) { if (this.simboloAtual() === '*' && this.proximoSimbolo() === '/') { this.avancar(); this.avancar(); break; } this.avancar(); } } else { this.adicionarSimbolo(prisma_2.default.DIVISAO); } break; case '%': this.adicionarSimbolo(prisma_2.default.MODULO); this.avancar(); break; case '&': this.adicionarSimbolo(prisma_2.default.BIT_AND); this.avancar(); break; case '|': this.adicionarSimbolo(prisma_2.default.BIT_OR); this.avancar(); break; case '^': this.adicionarSimbolo(prisma_2.default.BIT_XOR); this.avancar(); break; case '~': this.avancar(); if (this.simboloAtual() === '=') { this.adicionarSimbolo(prisma_2.default.DIFERENTE); this.avancar(); } else { this.adicionarSimbolo(prisma_2.default.BIT_XOR); } break; case '"': this.avancar(); this.analisarTexto('"'); break; case "'": this.avancar(); this.analisarTexto("'"); 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(); } break; } } mapear(codigo, hashArquivo) { const inicioMapeamento = (0, browser_process_hrtime_1.default)(); this.erros = []; this.simbolos = []; this.inicioSimbolo = 0; this.atual = 0; this.linha = 0; this.codigo = codigo || ['']; this.hashArquivo = hashArquivo; while (!this.eFinalDoCodigo()) { this.inicioSimbolo = this.atual; this.analisarToken(); } if (this.performance) { const deltaMapeamento = (0, browser_process_hrtime_1.default)(inicioMapeamento); console.log(`[Lexador] Tempo para mapeamento: ${deltaMapeamento[0] * 1e9 + deltaMapeamento[1]}ns`); } return { simbolos: this.simbolos, erros: this.erros, }; } } exports.LexadorPrisma = LexadorPrisma; //# sourceMappingURL=lexador-prisma.js.map