@designliquido/foles
Version:
Linguagem de folhas de estilo para documentos em geral em português
314 lines • 10.7 kB
JavaScript
"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