Repository: DesignLiquido/delegua
Pull request #310 (2023-04-04 16:49:32)

VisualG, operadores lógicos (não e xou)
- Algum redesenho da arquitetura do interpretador do dialeto;
- Melhora em alguns testes unitários.


Patch:
diff --git a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-visualg.ts b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-visualg.ts
index f77e4f3c..ac1cbc90 100644
--- a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-visualg.ts
+++ b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-visualg.ts
@@ -26,6 +26,7 @@ import {
     FormatacaoEscrita,
     FuncaoConstruto,
     Literal,
+    Logico,
     Variavel,
 } from '../../construtos';
 import { ParametroInterface, SimboloInterface } from '../../interfaces';
@@ -296,6 +297,18 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
         return expressao;
     }
 
+    ou(): Construto {
+        let expressao = this.e();
+
+        while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.OU, tiposDeSimbolos.XOU)) {
+            const operador = this.simbolos[this.atual - 1];
+            const direito = this.e();
+            expressao = new Logico(this.hashArquivo, expressao, operador, direito);
+        }
+
+        return expressao;
+    }
+
     /**
      * Método que resolve atribuições.
      * @returns Um construto do tipo `Atribuir`, `Conjunto` ou `AtribuicaoSobrescrita`.
diff --git a/fontes/interpretador/dialetos/visualg/comum.ts b/fontes/interpretador/dialetos/visualg/comum.ts
new file mode 100644
index 00000000..8e56d61c
--- /dev/null
+++ b/fontes/interpretador/dialetos/visualg/comum.ts
@@ -0,0 +1,165 @@
+import { Binario, Construto, Logico } from "../../../construtos";
+import { InterpretadorInterface, SimboloInterface, VariavelInterface } from "../../../interfaces";
+import { inferirTipoVariavel } from '../../inferenciador';
+
+import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
+import { ErroEmTempoDeExecucao } from "../../../excecoes";
+
+async function avaliar(interpretador: InterpretadorInterface, expressao: Construto): Promise<any> {
+    return await expressao.aceitar(interpretador);
+}
+
+function eIgual(esquerda: VariavelInterface | any, direita: VariavelInterface | any): boolean {
+    if (esquerda === null && direita === null) return true;
+    if (esquerda === null) return false;
+    return esquerda === direita;
+}
+
+function eVerdadeiro(objeto: any): boolean {
+    if (objeto === null) return false;
+    if (typeof objeto === 'boolean') return Boolean(objeto);
+    if (objeto.hasOwnProperty('valor')) {
+        return Boolean(objeto.valor);
+    }
+
+    return true;
+}
+
+function verificarOperandosNumeros(
+    operador: SimboloInterface,
+    direita: VariavelInterface | any,
+    esquerda: VariavelInterface | any
+): void {
+    const tipoDireita: string = direita.tipo ? direita.tipo : typeof direita === 'number' ? 'número' : String(NaN);
+    const tipoEsquerda: string = esquerda.tipo
+        ? esquerda.tipo
+        : typeof esquerda === 'number'
+        ? 'número'
+        : String(NaN);
+    if (tipoDireita === 'número' && tipoEsquerda === 'número') return;
+    throw new ErroEmTempoDeExecucao(operador, 'Operadores precisam ser números.', operador.linha);
+}
+
+/**
+ * Método de visita de expressão binária.
+ * Reintroduzido pelas particularidades do VisuAlg.
+ * @param expressao A expressão binária.
+ * @returns O resultado da resolução da expressão.
+ */
+export async function visitarExpressaoBinaria(interpretador: InterpretadorInterface, expressao: Binario | any): Promise<any> {
+    try {
+        const esquerda: VariavelInterface | any = await avaliar(interpretador, expressao.esquerda);
+        const direita: VariavelInterface | any = await avaliar(interpretador, expressao.direita);
+
+        let valorEsquerdo: any = esquerda?.hasOwnProperty('valor') ? esquerda.valor : esquerda;
+        let valorDireito: any = direita?.hasOwnProperty('valor') ? direita.valor : direita;
+
+        // No VisuAlg, uma variável pode resolver para função porque funções não precisam ter parênteses.
+        // Esta parte evita o problema.
+        if (valorEsquerdo && valorEsquerdo.hasOwnProperty('funcao')) {
+            valorEsquerdo = valorEsquerdo.funcao();
+        }
+
+        if (valorDireito && valorDireito.hasOwnProperty('funcao')) {
+            valorDireito = valorDireito.funcao();
+        }
+
+        const tipoEsquerdo: string = esquerda?.hasOwnProperty('tipo')
+            ? esquerda.tipo
+            : inferirTipoVariavel(esquerda);
+        const tipoDireito: string = direita?.hasOwnProperty('tipo') ? direita.tipo : inferirTipoVariavel(direita);
+
+        switch (expressao.operador.tipo) {
+            case tiposDeSimbolos.EXPONENCIACAO:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Math.pow(valorEsquerdo, valorDireito);
+
+            case tiposDeSimbolos.MAIOR:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Number(valorEsquerdo) > Number(valorDireito);
+
+            case tiposDeSimbolos.MAIOR_IGUAL:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Number(valorEsquerdo) >= Number(valorDireito);
+
+            case tiposDeSimbolos.MENOR:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Number(valorEsquerdo) < Number(valorDireito);
+
+            case tiposDeSimbolos.MENOR_IGUAL:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Number(valorEsquerdo) <= Number(valorDireito);
+
+            case tiposDeSimbolos.SUBTRACAO:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Number(valorEsquerdo) - Number(valorDireito);
+
+            case tiposDeSimbolos.ADICAO:
+                if (tipoEsquerdo === 'número' && tipoDireito === 'número') {
+                    return Number(valorEsquerdo) + Number(valorDireito);
+                } else {
+                    return String(valorEsquerdo) + String(valorDireito);
+                }
+
+            case tiposDeSimbolos.DIVISAO:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Number(valorEsquerdo) / Number(valorDireito);
+
+            case tiposDeSimbolos.DIVISAO_INTEIRA:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Math.floor(Number(valorEsquerdo) / Number(valorDireito));
+
+            case tiposDeSimbolos.MULTIPLICACAO:
+                if (tipoEsquerdo === 'texto' || tipoDireito === 'texto') {
+                    // Sem ambos os valores resolvem como texto, multiplica normal.
+                    // Se apenas um resolve como texto, o outro repete o 
+                    // texto n vezes, sendo n o valor do outro.
+                    if (tipoEsquerdo === 'texto' && tipoDireito === 'texto') {
+                        return Number(valorEsquerdo) * Number(valorDireito);    
+                    } 
+                    
+                    if (tipoEsquerdo === 'texto') {
+                        return valorEsquerdo.repeat(Number(valorDireito));
+                    }
+
+                    return valorDireito.repeat(Number(valorEsquerdo));
+                }
+                
+                return Number(valorEsquerdo) * Number(valorDireito);
+
+            case tiposDeSimbolos.MODULO:
+                verificarOperandosNumeros(expressao.operador, esquerda, direita);
+                return Number(valorEsquerdo) % Number(valorDireito);
+
+            case tiposDeSimbolos.DIFERENTE:
+                return !eIgual(valorEsquerdo, valorDireito);
+
+            case tiposDeSimbolos.IGUAL:
+                return eIgual(valorEsquerdo, valorDireito);
+        }
+    } catch (erro: any) {
+        return Promise.reject(erro);
+    }
+}
+
+export async function visitarExpressaoLogica(interpretador: InterpretadorInterface, expressao: Logico): Promise<any> {
+    const esquerda = await avaliar(interpretador, expressao.esquerda);
+
+    // se um estado for verdadeiro, retorna verdadeiro
+    if (expressao.operador.tipo === tiposDeSimbolos.OU) {
+        if (eVerdadeiro(esquerda)) return esquerda;
+    }
+
+    // se a primeira variável é verdadeiro, retorna a segunda invertida
+    if (expressao.operador.tipo === tiposDeSimbolos.XOU) {
+        const valorDireito = await avaliar(interpretador, expressao.direita);
+        return eVerdadeiro(esquerda) !== eVerdadeiro(valorDireito);
+    }
+
+    // se um estado for falso, retorna falso
+    if (expressao.operador.tipo === tiposDeSimbolos.E) {
+        if (!eVerdadeiro(esquerda)) return esquerda;
+    }
+
+    return await avaliar(interpretador, expressao.direita);
+}
\ No newline at end of file
diff --git a/fontes/interpretador/dialetos/visualg/interpretador-visualg-com-depuracao.ts b/fontes/interpretador/dialetos/visualg/interpretador-visualg-com-depuracao.ts
index 88e8b64d..76552fa2 100644
--- a/fontes/interpretador/dialetos/visualg/interpretador-visualg-com-depuracao.ts
+++ b/fontes/interpretador/dialetos/visualg/interpretador-visualg-com-depuracao.ts
@@ -2,14 +2,12 @@ import {
     registrarBibliotecaNumericaVisuAlg,
     registrarBibliotecaCaracteresVisuAlg,
 } from '../../../bibliotecas/dialetos/visualg';
-import { Construto, Variavel } from '../../../construtos';
+import { Binario, Construto, Logico, Variavel } from '../../../construtos';
 import { EscrevaMesmaLinha, Escreva, Fazer, Leia } from '../../../declaracoes';
-import { VariavelInterface } from '../../../interfaces';
 import { ContinuarQuebra, Quebra } from '../../../quebras';
-import { inferirTipoVariavel } from '../../inferenciador';
 import { InterpretadorComDepuracao } from '../../interpretador-com-depuracao';
 
-import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
+import * as comum from './comum';
 
 /**
  * Interpretador com depuração para o dialeto VisuAlg.
@@ -120,105 +118,11 @@ export class InterpretadorVisuAlgComDepuracao extends InterpretadorComDepuracao
         }
     }
 
-    /**
-     * Método de visita de expressão binária.
-     * Reintroduzido pelas particularidades do VisuAlg.
-     * @param expressao A expressão binária.
-     * @returns O resultado da resolução da expressão.
-     */
-    async visitarExpressaoBinaria(expressao: any): Promise<any> {
-        try {
-            const esquerda: VariavelInterface | any = await this.avaliar(expressao.esquerda);
-            const direita: VariavelInterface | any = await this.avaliar(expressao.direita);
-
-            let valorEsquerdo: any = esquerda?.hasOwnProperty('valor') ? esquerda.valor : esquerda;
-            let valorDireito: any = direita?.hasOwnProperty('valor') ? direita.valor : direita;
-
-            // No VisuAlg, uma variável pode resolver para função porque funções não precisam ter parênteses.
-            // Esta parte evita o problema.
-            if (valorEsquerdo && valorEsquerdo.hasOwnProperty('funcao')) {
-                valorEsquerdo = valorEsquerdo.funcao();
-            }
-
-            if (valorDireito && valorDireito.hasOwnProperty('funcao')) {
-                valorDireito = valorDireito.funcao();
-            }
-
-            const tipoEsquerdo: string = esquerda?.hasOwnProperty('tipo')
-                ? esquerda.tipo
-                : inferirTipoVariavel(esquerda);
-            const tipoDireito: string = direita?.hasOwnProperty('tipo') ? direita.tipo : inferirTipoVariavel(direita);
-
-            switch (expressao.operador.tipo) {
-                case tiposDeSimbolos.EXPONENCIACAO:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Math.pow(valorEsquerdo, valorDireito);
-
-                case tiposDeSimbolos.MAIOR:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) > Number(valorDireito);
-
-                case tiposDeSimbolos.MAIOR_IGUAL:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) >= Number(valorDireito);
-
-                case tiposDeSimbolos.MENOR:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) < Number(valorDireito);
-
-                case tiposDeSimbolos.MENOR_IGUAL:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) <= Number(valorDireito);
-
-                case tiposDeSimbolos.SUBTRACAO:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) - Number(valorDireito);
-
-                case tiposDeSimbolos.ADICAO:
-                    if (tipoEsquerdo === 'número' && tipoDireito === 'número') {
-                        return Number(valorEsquerdo) + Number(valorDireito);
-                    } else {
-                        return String(valorEsquerdo) + String(valorDireito);
-                    }
-
-                case tiposDeSimbolos.DIVISAO:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) / Number(valorDireito);
-
-                case tiposDeSimbolos.DIVISAO_INTEIRA:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Math.floor(Number(valorEsquerdo) / Number(valorDireito));
-
-                case tiposDeSimbolos.MULTIPLICACAO:
-                    if (tipoEsquerdo === 'texto' || tipoDireito === 'texto') {
-                        // Sem ambos os valores resolvem como texto, multiplica normal.
-                        // Se apenas um resolve como texto, o outro repete o
-                        // texto n vezes, sendo n o valor do outro.
-                        if (tipoEsquerdo === 'texto' && tipoDireito === 'texto') {
-                            return Number(valorEsquerdo) * Number(valorDireito);
-                        }
-
-                        if (tipoEsquerdo === 'texto') {
-                            return valorEsquerdo.repeat(Number(valorDireito));
-                        }
-
-                        return valorDireito.repeat(Number(valorEsquerdo));
-                    }
-
-                    return Number(valorEsquerdo) * Number(valorDireito);
-
-                case tiposDeSimbolos.MODULO:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) % Number(valorDireito);
-
-                case tiposDeSimbolos.DIFERENTE:
-                    return !this.eIgual(valorEsquerdo, valorDireito);
+    async visitarExpressaoBinaria(expressao: Binario | any): Promise<any> {
+        return comum.visitarExpressaoBinaria(this, expressao);
+    }
 
-                case tiposDeSimbolos.IGUAL:
-                    return this.eIgual(valorEsquerdo, valorDireito);
-            }
-        } catch (erro: any) {
-            return Promise.reject(erro);
-        }
+    async visitarExpressaoLogica(expressao: Logico): Promise<any> {
+        return comum.visitarExpressaoLogica(this, expressao);
     }
 }
diff --git a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
index 01af6290..073a423a 100644
--- a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
+++ b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
@@ -1,14 +1,12 @@
-import { Construto, Variavel } from '../../../construtos';
+import { Binario, Construto, Logico, Variavel } from '../../../construtos';
 import { Escreva, EscrevaMesmaLinha, Fazer, Leia } from '../../../declaracoes';
 import { InterpretadorBase } from '../..';
 import { ContinuarQuebra, Quebra } from '../../../quebras';
 import { registrarBibliotecaNumericaVisuAlg } from '../../../bibliotecas/dialetos/visualg/numerica';
-import { VariavelInterface } from '../../../interfaces';
-import { inferirTipoVariavel } from '../../inferenciador';
-
-import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
 import { registrarBibliotecaCaracteresVisuAlg } from '../../../bibliotecas/dialetos/visualg';
 
+import * as comum from './comum';
+
 /**
  * O Interpretador VisuAlg possui algumas diferenças em relação ao
  * Interpretador Delégua quanto à escrita na saída.
@@ -125,105 +123,11 @@ export class InterpretadorVisuAlg extends InterpretadorBase {
         }
     }
 
-    /**
-     * Método de visita de expressão binária.
-     * Reintroduzido pelas particularidades do VisuAlg.
-     * @param expressao A expressão binária.
-     * @returns O resultado da resolução da expressão.
-     */
-    async visitarExpressaoBinaria(expressao: any): Promise<any> {
-        try {
-            const esquerda: VariavelInterface | any = await this.avaliar(expressao.esquerda);
-            const direita: VariavelInterface | any = await this.avaliar(expressao.direita);
-
-            let valorEsquerdo: any = esquerda?.hasOwnProperty('valor') ? esquerda.valor : esquerda;
-            let valorDireito: any = direita?.hasOwnProperty('valor') ? direita.valor : direita;
-
-            // No VisuAlg, uma variável pode resolver para função porque funções não precisam ter parênteses.
-            // Esta parte evita o problema.
-            if (valorEsquerdo && valorEsquerdo.hasOwnProperty('funcao')) {
-                valorEsquerdo = valorEsquerdo.funcao();
-            }
-
-            if (valorDireito && valorDireito.hasOwnProperty('funcao')) {
-                valorDireito = valorDireito.funcao();
-            }
-
-            const tipoEsquerdo: string = esquerda?.hasOwnProperty('tipo')
-                ? esquerda.tipo
-                : inferirTipoVariavel(esquerda);
-            const tipoDireito: string = direita?.hasOwnProperty('tipo') ? direita.tipo : inferirTipoVariavel(direita);
-
-            switch (expressao.operador.tipo) {
-                case tiposDeSimbolos.EXPONENCIACAO:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Math.pow(valorEsquerdo, valorDireito);
-
-                case tiposDeSimbolos.MAIOR:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) > Number(valorDireito);
-
-                case tiposDeSimbolos.MAIOR_IGUAL:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) >= Number(valorDireito);
-
-                case tiposDeSimbolos.MENOR:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) < Number(valorDireito);
-
-                case tiposDeSimbolos.MENOR_IGUAL:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) <= Number(valorDireito);
-
-                case tiposDeSimbolos.SUBTRACAO:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) - Number(valorDireito);
-
-                case tiposDeSimbolos.ADICAO:
-                    if (tipoEsquerdo === 'número' && tipoDireito === 'número') {
-                        return Number(valorEsquerdo) + Number(valorDireito);
-                    } else {
-                        return String(valorEsquerdo) + String(valorDireito);
-                    }
-
-                case tiposDeSimbolos.DIVISAO:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) / Number(valorDireito);
-
-                case tiposDeSimbolos.DIVISAO_INTEIRA:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Math.floor(Number(valorEsquerdo) / Number(valorDireito));
-
-                case tiposDeSimbolos.MULTIPLICACAO:
-                    if (tipoEsquerdo === 'texto' || tipoDireito === 'texto') {
-                        // Sem ambos os valores resolvem como texto, multiplica normal.
-                        // Se apenas um resolve como texto, o outro repete o 
-                        // texto n vezes, sendo n o valor do outro.
-                        if (tipoEsquerdo === 'texto' && tipoDireito === 'texto') {
-                            return Number(valorEsquerdo) * Number(valorDireito);    
-                        } 
-                        
-                        if (tipoEsquerdo === 'texto') {
-                            return valorEsquerdo.repeat(Number(valorDireito));
-                        }
-
-                        return valorDireito.repeat(Number(valorEsquerdo));
-                    }
-                    
-                    return Number(valorEsquerdo) * Number(valorDireito);
-
-                case tiposDeSimbolos.MODULO:
-                    this.verificarOperandosNumeros(expressao.operador, esquerda, direita);
-                    return Number(valorEsquerdo) % Number(valorDireito);
-
-                case tiposDeSimbolos.DIFERENTE:
-                    return !this.eIgual(valorEsquerdo, valorDireito);
+    async visitarExpressaoBinaria(expressao: Binario | any): Promise<any> {
+        return comum.visitarExpressaoBinaria(this, expressao);
+    }
 
-                case tiposDeSimbolos.IGUAL:
-                    return this.eIgual(valorEsquerdo, valorDireito);
-            }
-        } catch (erro: any) {
-            return Promise.reject(erro);
-        }
+    async visitarExpressaoLogica(expressao: Logico): Promise<any> {
+        return comum.visitarExpressaoLogica(this, expressao);
     }
 }
diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts
index 59cb29d8..7e400979 100644
--- a/fontes/interpretador/interpretador-base.ts
+++ b/fontes/interpretador/interpretador-base.ts
@@ -1,4 +1,3 @@
-// import * as readline from 'readline';
 import hrtime from 'browser-process-hrtime';
 
 import { EspacoVariaveis } from '../espaco-variaveis';
@@ -92,7 +91,7 @@ export class InterpretadorBase implements InterpretadorInterface {
         this.performance = performance;
 
         this.funcaoDeRetorno = funcaoDeRetorno || console.log;
-        this.funcaoDeRetornoMesmaLinha = funcaoDeRetornoMesmaLinha || process.stdout.write;
+        this.funcaoDeRetornoMesmaLinha = funcaoDeRetornoMesmaLinha || process.stdout.write.bind(process.stdout);
 
         this.erros = [];
         this.declaracoes = [];
diff --git a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
index 216038e2..f995e374 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
@@ -40,6 +40,7 @@ export default {
     log: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
     logn: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
     logico: tiposDeSimbolos.LOGICO,
+    nao: tiposDeSimbolos.NEGACAO, // Exceção
     ou: tiposDeSimbolos.OU,
     outrocaso: tiposDeSimbolos.OUTRO_CASO,
     para: tiposDeSimbolos.PARA,
@@ -59,4 +60,5 @@ export default {
     var: tiposDeSimbolos.VAR,
     verdadeiro: tiposDeSimbolos.VERDADEIRO,
     vetor: tiposDeSimbolos.VETOR,
+    xou: tiposDeSimbolos.XOU
 };
diff --git a/fontes/tipos-de-simbolos/visualg.ts b/fontes/tipos-de-simbolos/visualg.ts
index af62b3ba..f28e84f3 100644
--- a/fontes/tipos-de-simbolos/visualg.ts
+++ b/fontes/tipos-de-simbolos/visualg.ts
@@ -65,4 +65,5 @@ export default {
     VERDADEIRO: 'VERDADEIRO',
     VETOR: 'VETOR',
     VIRGULA: 'VIRGULA',
+    XOU: 'XOU'
 };


Test patch:
diff --git a/testes/visualg/avaliador-sintatico.test.ts b/testes/visualg/avaliador-sintatico.test.ts
index e2ce763b..2d038f44 100644
--- a/testes/visualg/avaliador-sintatico.test.ts
+++ b/testes/visualg/avaliador-sintatico.test.ts
@@ -194,5 +194,35 @@ describe('Avaliador sintático (VisuAlg)', () => {
             expect(retornoAvaliadorSintatico).toBeTruthy();
             expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3);
         });
+
+        it('Sucesso - Xou', () => {
+            const retornoLexador = lexador.mapear([
+                'algoritmo "Exemplo Xou"',
+                'var A, B, C, resultA, resultB, resultC: logico',
+                'inicio',
+                'A <- verdadeiro',
+                'B <- verdadeiro',
+                'C <- falso',
+                'resultA <- A ou B',
+                'escreval("A ", resultA)',
+                'resultA <- A xou B',
+                'escreval("A ", resultA)',
+                'resultA <- nao B',
+                'escreval("A ", resultA)',
+                'resultB <- B',
+                'resultA <- (A e B) ou (A xou B)',
+                'resultB <- (A ou B) e (A e C)',
+                'resultC <- A ou C e B xou A e nao B',
+                'escreval("A ", resultA)',
+                'escreval("B ", resultB)',
+                'escreval("C ", resultC)',
+                'fimalgoritmo'
+            ], -1);
+            
+            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador);
+
+            expect(retornoAvaliadorSintatico).toBeTruthy();
+            expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(22);
+        })
     });
 });
diff --git a/testes/visualg/interpretador.test.ts b/testes/visualg/interpretador.test.ts
index 030e6a6c..c5017977 100644
--- a/testes/visualg/interpretador.test.ts
+++ b/testes/visualg/interpretador.test.ts
@@ -214,6 +214,36 @@ describe('Interpretador', () => {
 
                 expect(retornoInterpretador.erros).toHaveLength(0);
             });
+
+            it('Sucesso - Operadores Lógicos', async () => {
+                const retornoLexador = lexador.mapear([
+                    'algoritmo "Exemplo Xou"',
+                    'var A, B, C, resultA, resultB, resultC: logico',
+                    'inicio',
+                    'A <- verdadeiro',
+                    'B <- verdadeiro',
+                    'C <- falso',
+                    'resultA <- A ou B',
+                    'escreval("A ", resultA)',
+                    'resultA <- A xou B',
+                    'escreval("A ", resultA)',
+                    'resultA <- nao B',
+                    'escreval("A ", resultA)',
+                    'resultB <- B',
+                    'resultA <- (A e B) ou (A xou B)',
+                    'resultB <- (A ou B) e (A e C)',
+                    'resultC <- A ou C e B xou A e nao B',
+                    'escreval("A ", resultA)',
+                    'escreval("B ", resultB)',
+                    'escreval("C ", resultC)',
+                    'fimalgoritmo'
+                ], -1);
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador);
+    
+                const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                expect(retornoInterpretador.erros).toHaveLength(0);
+            });
         });
     });
 });
diff --git a/testes/visualg/lexador.test.ts b/testes/visualg/lexador.test.ts
index 66b724e2..fe3ed9a2 100644
--- a/testes/visualg/lexador.test.ts
+++ b/testes/visualg/lexador.test.ts
@@ -44,7 +44,6 @@ describe('Lexador (VisuAlg)', () => {
                         expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA }),
                         expect.objectContaining({ tipo: tiposDeSimbolos.INICIO }),
                         expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA }),
-                        // expect.objectContaining({ tipo: tiposDeSimbolos.ESCREVA }),
                         expect.objectContaining({ tipo: tiposDeSimbolos.FIM_ALGORITMO })
                     ])
                 );
@@ -60,15 +59,21 @@ describe('Lexador (VisuAlg)', () => {
                     ], -1);
     
                 expect(resultado).toBeTruthy();
-                /* expect(resultado.simbolos).toHaveLength(4);
+                expect(resultado.simbolos).toHaveLength(10);
                 expect(resultado.simbolos).toEqual(
                     expect.arrayContaining([
-                        expect.objectContaining({ tipo: tiposDeSimbolos.ESCREVA }),
-                        expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_ESQUERDO }),
-                        expect.objectContaining({ tipo: tiposDeSimbolos.TEXTO }),
-                        expect.objectContaining({ tipo: tiposDeSimbolos.PARENTESE_DIREITO }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.ALGORITMO }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.CARACTERE }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.VAR }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.IDENTIFICADOR }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.DOIS_PONTOS }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.INTEIRO }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.INICIO }),
+                        expect.objectContaining({ tipo: tiposDeSimbolos.QUEBRA_LINHA })
                     ])
-                ); */
+                );
             });
         });
     });