silegismg-interpretador-articulacao
Version:
Interpretador de Articulação
125 lines (124 loc) • 6.3 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const EscapeInterpretacao_1 = __importDefault(require("./EscapeInterpretacao"));
const EscapeSimboloEscape_1 = __importDefault(require("./impl/EscapeSimboloEscape"));
/**
* Processa um texto, omitindo trechos que não devem fazer parte do processamento.
*/
class Escapamento {
/**
* Prepara o processamento, escapando o texto.
*
* @param textoOriginal Texto a ser processado.
* @param escapesExtras Escapadores a serem utilizados.
*/
constructor(textoOriginal, ...escapesExtras) {
this.contexto = null;
this.escapes = [];
const escapadores = [new EscapeSimboloEscape_1.default(), ...escapesExtras];
/*
* Para cada citação, isto é, texto entre aspas, substitui-se o seu conteúdo
* por \0 e o conteúdo substituído é inserido na pilha de aspas, para evitar
* que o conteúdo seja também interpretado.
*
* Desta maneira, de forma transparente, por meio do método processar, é
* possível iterar por todas linhas sem o conteúdo escapado para realizar
* o devido processamento textual.
*/
this.textoEscapado = escapadores.reduce((prev, cur) => {
const escapesAnteriores = [...this.escapes];
/**
* Determina o índice em que deve inserir o escape de forma ordenada
* no contexto.
*/
let idxAdicaoVetorEscape = 0;
return cur.escapar(prev, (trecho, idx) => {
// Ajusta o índice à posição no texto original considerando os escapamentos anteriores.
for (let i = 0; i < escapesAnteriores.length && escapesAnteriores[i].idx <= idx; i++) {
idx += escapesAnteriores[i].trecho.length - EscapeInterpretacao_1.default.ESCAPE.length;
}
// Substitui todos os escapes contidos dentro deste novo escape pelo texto original.
let idxBaseRestauracao = idx;
trecho = trecho.replace(EscapeInterpretacao_1.default.ESCAPES_REGEXP, (escape, idxARestaurar) => {
const idxCorrigido = idxARestaurar + idxBaseRestauracao;
const aRemover = this.escapes.findIndex((item) => item.idx === idxCorrigido);
if (aRemover === -1) {
throw new Error('Falha durante escapamento.');
}
const [escapeAnterior] = this.escapes.splice(aRemover, 1);
idxBaseRestauracao += escapeAnterior.trecho.length - EscapeInterpretacao_1.default.ESCAPE.length;
return escapeAnterior.trecho;
});
while (idxAdicaoVetorEscape > 0 && this.escapes[idxAdicaoVetorEscape].idx > idx) {
idxAdicaoVetorEscape--;
}
while (this.escapes.length > idxAdicaoVetorEscape && this.escapes[idxAdicaoVetorEscape].idx < idx) {
idxAdicaoVetorEscape++;
}
this.escapes.splice(idxAdicaoVetorEscape, 0, { trecho: trecho, idx });
return EscapeInterpretacao_1.default.ESCAPE;
});
}, textoOriginal);
}
*processar() {
for (const trecho of this.textoEscapado.split('\n')) {
if (this.escapes.length === 0) {
this.contexto = {
trechoComEscapes: trecho,
escapou: false,
trechoSemEscapes: trecho
};
}
else {
const trechoSemEscapes = trecho.replace(EscapeInterpretacao_1.default.ESCAPES_REGEXP, '');
this.contexto = {
trechoComEscapes: trecho,
trechoSemEscapes,
escapou: trechoSemEscapes.length !== trecho.length
};
}
yield this.contexto.trechoSemEscapes;
}
}
desfazerEscapes(trecho) {
if (!this.contexto) {
throw new Error('Contexto de escapamento está nulo.');
}
try {
if (!this.contexto.escapou) {
return trecho !== null && trecho !== void 0 ? trecho : this.contexto.trechoComEscapes;
}
else if (trecho === undefined) {
return this.contexto.trechoComEscapes.replace(EscapeInterpretacao_1.default.ESCAPES_REGEXP, () => this.escapes.shift().trecho);
}
else {
let idxTrecho = this.contexto.trechoSemEscapes.indexOf(trecho);
let idxEscape;
let nEscapesAnteriores = 0;
// Ajusta o índice da descrição, para torná-la relativa à linha com escapes.
for (idxEscape = this.contexto.trechoComEscapes.indexOf(EscapeInterpretacao_1.default.ESCAPE); idxEscape !== -1 && idxEscape <= idxTrecho; idxEscape = this.contexto.trechoComEscapes.indexOf(EscapeInterpretacao_1.default.ESCAPE, idxEscape + EscapeInterpretacao_1.default.ESCAPE.length)) {
idxTrecho += EscapeInterpretacao_1.default.ESCAPE.length;
nEscapesAnteriores++;
}
// Ajusta o índice da descrição para escapes imediatamente anterior a ela.
while (nEscapesAnteriores > 0 && this.contexto.trechoComEscapes.lastIndexOf(EscapeInterpretacao_1.default.ESCAPE, idxTrecho - 1)
+ EscapeInterpretacao_1.default.ESCAPE.length === idxTrecho) {
idxTrecho -= EscapeInterpretacao_1.default.ESCAPE.length;
nEscapesAnteriores--;
}
// Remove os escapes do rótulo.
while (nEscapesAnteriores-- > 0) {
this.escapes.shift();
}
return this.contexto.trechoComEscapes.substring(idxTrecho).replace(EscapeInterpretacao_1.default.ESCAPES_REGEXP, () => this.escapes.shift().trecho);
}
}
finally {
this.contexto = null;
}
}
}
exports.default = Escapamento;