Repository: DesignLiquido/delegua
Pull request #592 (2024-01-24 10:56:11)

Formas de uso funcao aleatorio
Esta Pull Request está conectado com a issu #507 

Agora é possível ter o seguinte código funcionando:

```
algoritmo "aleatorio"
var
   mes1, mes2 :inteiro

inicio
   escreval("Digite o mes do ano")

   aleatorio 1, 12
       leia(mes1)
       leia(mes2)
   aleatorio off

   escreval("")
   escreval("Mes 1:", mes1)
   escreval("Mes 2:", mes2)
fimAlgoritmo
```


Patch:
diff --git a/fontes/analisador-semantico/analisador-semantico.ts b/fontes/analisador-semantico/analisador-semantico.ts
index 0bf13bf3..244a402c 100644
--- a/fontes/analisador-semantico/analisador-semantico.ts
+++ b/fontes/analisador-semantico/analisador-semantico.ts
@@ -1,5 +1,6 @@
 import { Agrupamento, Atribuir, Binario, Chamada, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Literal, Logico, Super, TipoDe, Variavel, Vetor } from '../construtos';
 import {
+    Aleatorio,
     Bloco,
     Classe,
     Const,
@@ -59,6 +60,11 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface {
         this.atual = 0;
         this.diagnosticos = [];
     }
+
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any> {
+        return Promise.resolve();
+    }
+
     visitarExpressaoAcessoElementoMatriz(expressao: any) {
         return Promise.resolve();
     }
diff --git a/fontes/analisador-semantico/dialetos/analisador-semantico-birl.ts b/fontes/analisador-semantico/dialetos/analisador-semantico-birl.ts
index ee688aff..d70ad274 100644
--- a/fontes/analisador-semantico/dialetos/analisador-semantico-birl.ts
+++ b/fontes/analisador-semantico/dialetos/analisador-semantico-birl.ts
@@ -1,5 +1,6 @@
 import { Atribuir, ExpressaoRegular, FimPara, FormatacaoEscrita, Literal, Super, TipoDe, Variavel } from '../../construtos';
 import {
+    Aleatorio,
     Bloco,
     Classe,
     Const,
@@ -86,6 +87,10 @@ export class AnalisadorSemanticoBirl implements AnalisadorSemanticoInterface {
         return Promise.resolve();
     }
 
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any>{
+        return Promise.resolve();
+    }
+
     visitarDeclaracaoDeAtribuicao(expressao: Atribuir) {
         if (!this.variaveis.hasOwnProperty(expressao.simbolo.lexema)) {
             this.diagnosticos.push({
diff --git a/fontes/analisador-semantico/dialetos/analisador-semantico-mapler.ts b/fontes/analisador-semantico/dialetos/analisador-semantico-mapler.ts
index 73df8399..04812aa0 100644
--- a/fontes/analisador-semantico/dialetos/analisador-semantico-mapler.ts
+++ b/fontes/analisador-semantico/dialetos/analisador-semantico-mapler.ts
@@ -1,5 +1,6 @@
 import { Atribuir, Binario, Chamada, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, Literal, Super, TipoDe, Vetor } from '../../construtos';
 import {
+    Aleatorio,
     Bloco,
     Classe,
     Const,
@@ -59,6 +60,10 @@ export class AnalisadorSemanticoMapler implements AnalisadorSemanticoInterface {
         return Promise.resolve();
     }
 
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any>{
+        return Promise.resolve();
+    }
+
     erro(simbolo: SimboloInterface, mensagem: string): void {
         this.diagnosticos.push({
             simbolo: simbolo,
diff --git a/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts b/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts
index aed06c59..ba9263b6 100644
--- a/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts
+++ b/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts
@@ -1,5 +1,6 @@
 import { Atribuir, Chamada, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Literal, Super, TipoDe, Variavel, Vetor } from "../../construtos";
 import {
+    Aleatorio,
     Bloco,
     Classe,
     Const,
@@ -96,13 +97,13 @@ export class AnalisadorSemanticoVisuAlg implements AnalisadorSemanticoInterface
                 let valorLiteral = typeof (valor as Literal).valor;
                 if (!['qualquer'].includes(variavel.tipo)) {
                     if (valorLiteral === 'string') {
-                        if (variavel.tipo != 'texto') {
+                        if (variavel.tipo.toLowerCase() != 'caractere') {
                             this.erro(simbolo, `Esperado tipo '${variavel.tipo}' na atribuição.`);
                             return Promise.resolve();
                         }
                     }
                     if (valorLiteral === 'number') {
-                        if (!['inteiro', 'real'].includes(variavel.tipo)) {
+                        if (!['inteiro', 'real'].includes(variavel.tipo.toLowerCase())) {
                             this.erro(simbolo, `Esperado tipo '${variavel.tipo}' na atribuição.`);
                             return Promise.resolve();
                         }
@@ -116,6 +117,65 @@ export class AnalisadorSemanticoVisuAlg implements AnalisadorSemanticoInterface
         }
     }
 
+
+    private gerarNumeroAleatorio(min: number, max: number) {
+        return Math.floor(Math.random() * (max - min) + min);
+    }
+
+    private encontrarLeiaNoAleatorio(declaracao: Declaracao, menorNumero: number, maiorNumero: number) {
+        if ('declaracoes' in declaracao) {
+            // Se a declaração tiver um campo 'declaracoes', ela é um Bloco
+            const declaracoes = declaracao.declaracoes as Declaracao[]
+            for (const subDeclaracao of declaracoes) {
+                this.encontrarLeiaNoAleatorio(subDeclaracao, menorNumero, maiorNumero);
+            }
+        } else if (declaracao instanceof Leia) {
+            // Se encontrarmos um Leia, podemos efetuar as operações imediatamente
+            for (const argumento of declaracao.argumentos) {
+                this.atualizarVariavelComValorAleatorio(argumento as Variavel, menorNumero, maiorNumero);
+            }
+        }
+    }
+
+    private atualizarVariavelComValorAleatorio(variavel: Variavel, menorNumero: number, maiorNumero: number) {
+        if (this.variaveis[variavel.simbolo.lexema]) {
+            let valor: number | string = 0;
+            if(this.variaveis[variavel.simbolo.lexema].tipo === "inteiro" || this.variaveis[variavel.simbolo.lexema].tipo === "real") valor = this.gerarNumeroAleatorio(menorNumero, maiorNumero);
+            else if(this.variaveis[variavel.simbolo.lexema].tipo === "caracter" ) valor = this.palavraAleatoriaCom5Digitos()
+
+            this.variaveis[variavel.simbolo.lexema].valor = valor;
+        }
+    }
+
+    private palavraAleatoriaCom5Digitos(): string {
+        const caracteres = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+        let palavra = "";
+
+        for (let i = 0; i < 5; i++) {
+            const indiceAleatorio = Math.floor(Math.random() * caracteres.length);
+            palavra += caracteres.charAt(indiceAleatorio);
+        }
+        return palavra;
+    }
+
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any> {
+        //Isso acontece quando não é informado os número máximos e mínimos
+        let menorNumero = 0;
+        let maiorNumero = 100
+
+        if (declaracao.argumentos) {
+            menorNumero = Math.min(declaracao.argumentos.min, declaracao.argumentos.max);
+            maiorNumero = Math.max(declaracao.argumentos.min, declaracao.argumentos.max);
+
+        }
+
+        for (let corpoDeclaracao of declaracao.corpo.declaracoes) {
+            this.encontrarLeiaNoAleatorio(corpoDeclaracao, menorNumero, maiorNumero);
+        }
+
+        return Promise.resolve();
+    }
+
     visitarDeclaracaoVar(declaracao: Var): Promise<any> {
         this.variaveis[declaracao.simbolo.lexema] = {
             imutavel: false,
diff --git a/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts b/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts
index 525054e0..6c57edc8 100644
--- a/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts
+++ b/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts
@@ -41,6 +41,7 @@ import { Simbolo } from '../../../lexador';
 import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
 import { ParametroVisuAlg } from './parametro-visualg';
 import { TiposDadosInterface } from '../../../interfaces/tipos-dados-interface';
+import { Aleatorio } from '../../../declaracoes/aleatorio';
 
 export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
     blocoPrincipalIniciado: boolean;
@@ -342,7 +343,7 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
             return new Agrupamento(this.hashArquivo, Number(simboloAtual.linha), expressao);
         }
 
-        throw this.erro(this.simbolos[this.atual], 'Esperado expressão.');
+        throw this.erro(this.simbolos[this.atual], "Esperado expressão.");
     }
 
     comparacaoIgualdade(): Construto {
@@ -1115,9 +1116,56 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
         );
     }
 
+    declaracaoAleatorio(): Aleatorio {
+        const simboloAleatorio: SimboloInterface = this.avancarEDevolverAnterior();
+
+        let argumentos: { min: number, max: number } | null = {
+            min: 0,
+            max: 0
+        };
+
+        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.NUMERO)) {
+
+            this.consumir(tiposDeSimbolos.VIRGULA, "Esperado ',' após declaração do primeiro número.");
+
+            argumentos.min = Number(this.simboloAtual().literal);
+
+            this.consumir(tiposDeSimbolos.NUMERO, "Esperado um número após ','.");
+
+            argumentos.max = Number(this.simbolos[this.atual - 1].literal);
+
+        } else if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.ON)) {
+            this.consumir(
+                simboloAleatorio.tipo,
+                "Esperado palavra reservada 'ON'ou 'on' ou combinação de número'(min, max)' após declaração 'aleatorio'"
+            )
+            argumentos = null
+        }
+
+        this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após declaração do último número.");
+
+        const decoracoes = [];
+
+        do {
+            const decoracao = this.resolverDeclaracaoForaDeBloco()
+            if(decoracao instanceof Leia) decoracao.eParaInterromper = true;
+            decoracoes.push(decoracao);
+        } while (![tiposDeSimbolos.ALEATORIO, tiposDeSimbolos.FIM_ALGORITMO].includes(this.simbolos[this.atual].tipo))
+
+        if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.ALEATORIO)) {
+            this.consumir(tiposDeSimbolos.OFF, "Esperado palavra reservada 'off' ou 'OFF' após declaração 'aleatorio'.");
+        }
+
+        return new Aleatorio(simboloAleatorio.linha, simboloAleatorio.hashArquivo, new Bloco(simboloAleatorio.hashArquivo, Number(simboloAleatorio.linha), decoracoes.filter((d) => d)), argumentos)
+
+    }
+
     resolverDeclaracaoForaDeBloco(): Declaracao | Declaracao[] | Construto | Construto[] | any {
         const simboloAtual = this.simbolos[this.atual];
+
         switch (simboloAtual.tipo) {
+            case tiposDeSimbolos.ALEATORIO:
+                return this.declaracaoAleatorio();
             case tiposDeSimbolos.ENQUANTO:
                 return this.declaracaoEnquanto();
             case tiposDeSimbolos.ESCOLHA:
diff --git a/fontes/declaracoes/aleatorio.ts b/fontes/declaracoes/aleatorio.ts
new file mode 100644
index 00000000..eb11da15
--- /dev/null
+++ b/fontes/declaracoes/aleatorio.ts
@@ -0,0 +1,19 @@
+import { VisitanteComumInterface } from "../interfaces";
+import { Declaracao } from "./declaracao";
+import { Bloco } from "./bloco";
+
+export class Aleatorio extends Declaracao {
+    corpo: Bloco;
+    argumentos: { min: number, max: number } | null
+
+    constructor(linha: number, hashArquivo: number, corpo: Bloco, argumentos: { min: number, max: number } | null) {
+        super(linha, hashArquivo);
+
+        this.corpo = corpo
+        this.argumentos = argumentos;
+    }
+
+    async aceitar(visitante: VisitanteComumInterface): Promise<any> {
+        return await visitante.visitarDeclaracaoAleatorio(this);
+    }
+}
\ No newline at end of file
diff --git a/fontes/declaracoes/index.ts b/fontes/declaracoes/index.ts
index f49ddc92..a401933e 100644
--- a/fontes/declaracoes/index.ts
+++ b/fontes/declaracoes/index.ts
@@ -24,3 +24,4 @@ export * from './se';
 export * from './tente';
 export * from './var';
 export * from './var-multiplo';
+export * from './aleatorio';
\ No newline at end of file
diff --git a/fontes/declaracoes/leia.ts b/fontes/declaracoes/leia.ts
index c57401a0..3a5ccf56 100644
--- a/fontes/declaracoes/leia.ts
+++ b/fontes/declaracoes/leia.ts
@@ -13,6 +13,7 @@ export class Leia extends Declaracao {
     argumentos: Construto[];
     tipo?: string;
     numeroArgumentosEsperados?: number;
+    eParaInterromper?: boolean;
 
     constructor(simbolo: SimboloInterface, argumentos: Construto[]) {
         super(simbolo.linha, simbolo.hashArquivo);
diff --git a/fontes/formatadores/formatador-delegua.ts b/fontes/formatadores/formatador-delegua.ts
index 4e987f03..ff91120f 100644
--- a/fontes/formatadores/formatador-delegua.ts
+++ b/fontes/formatadores/formatador-delegua.ts
@@ -48,6 +48,7 @@ import {
     Sustar,
     Declaracao,
     Falhar,
+    Aleatorio,
 } from '../declaracoes';
 import { VisitanteComumInterface } from '../interfaces';
 
@@ -89,7 +90,7 @@ export class FormatadorDelegua implements VisitanteComumInterface {
             this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}${metodo.simbolo.lexema}`;
             this.visitarExpressaoFuncaoConstruto(metodo.funcao);
         }
-        
+
         this.indentacaoAtual -= this.tamanhoIndentacao;
 
         this.codigoFormatado += `${' '.repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
@@ -465,6 +466,10 @@ export class FormatadorDelegua implements VisitanteComumInterface {
         this.codigoFormatado += ')';
     }
 
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any> {
+        throw new Error('Método não implementado.');
+    }
+
     visitarExpressaoDefinirValor(expressao: DefinirValor) {
         this.formatarDeclaracaoOuConstruto(expressao.objeto);
         this.codigoFormatado += `.${expressao.nome.lexema} = `;
@@ -552,7 +557,7 @@ export class FormatadorDelegua implements VisitanteComumInterface {
         if (expressao.argumentos.length > 0) {
             this.codigoFormatado = this.codigoFormatado.slice(0, -2);
         }
-        
+
         this.codigoFormatado += `)`;
     }
 
@@ -582,7 +587,7 @@ export class FormatadorDelegua implements VisitanteComumInterface {
                 this.codigoFormatado += ` ou `;
                 break;
         }
-        
+
         this.formatarDeclaracaoOuConstruto(expressao.direita);
     }
 
@@ -597,7 +602,7 @@ export class FormatadorDelegua implements VisitanteComumInterface {
     }
 
     visitarExpressaoSuper(expressao: Super) {
-        // TODO: `expressao.metodo` deveria ser um `Construto`, não um `Simbolo` aqui. 
+        // TODO: `expressao.metodo` deveria ser um `Construto`, não um `Simbolo` aqui.
         this.codigoFormatado += `super.${expressao.metodo.lexema}()`;
         console.log(expressao);
     }
@@ -719,7 +724,7 @@ export class FormatadorDelegua implements VisitanteComumInterface {
                 break;
             case 'Importar':
                 this.visitarDeclaracaoImportar(declaracaoOuConstruto as Importar);
-                break;                
+                break;
             case 'Isto':
                 this.visitarExpressaoIsto(declaracaoOuConstruto as Isto);
                 break;
diff --git a/fontes/formatadores/formatador-portugol-studio.ts b/fontes/formatadores/formatador-portugol-studio.ts
index 2ee586c4..893d4079 100644
--- a/fontes/formatadores/formatador-portugol-studio.ts
+++ b/fontes/formatadores/formatador-portugol-studio.ts
@@ -1,5 +1,5 @@
 import { AcessoIndiceVariavel, AcessoMetodoOuPropriedade, Agrupamento, AtribuicaoPorIndice, Atribuir, Binario, Chamada, Construto, DefinirValor, Dicionario, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Isto, Literal, Logico, Super, TipoDe, Unario, Variavel, Vetor } from "../construtos";
-import { Classe, Const, ConstMultiplo, Expressao, FuncaoDeclaracao, Enquanto, Escolha, Escreva, Fazer, Importar, Para, ParaCada, Se, Tente, Var, VarMultiplo, Bloco, Continua, EscrevaMesmaLinha, Leia, LeiaMultiplo, Retorna, Sustar, Declaracao, Falhar } from "../declaracoes";
+import { Classe, Const, ConstMultiplo, Expressao, FuncaoDeclaracao, Enquanto, Escolha, Escreva, Fazer, Importar, Para, ParaCada, Se, Tente, Var, VarMultiplo, Bloco, Continua, EscrevaMesmaLinha, Leia, LeiaMultiplo, Retorna, Sustar, Declaracao, Falhar, Aleatorio } from "../declaracoes";
 import { VisitanteComumInterface } from "../interfaces";
 import { ContinuarQuebra, RetornoQuebra, SustarQuebra } from "../quebras";
 
@@ -38,9 +38,13 @@ export class FormatadorPortugolStudio implements VisitanteComumInterface {
         // throw new Error("Método não implementado");
     }
 
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any> {
+        throw new Error('Método não implementado.');
+    }
+
     visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) {
         this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}funcao ${declaracao.simbolo.lexema}()${this.quebraLinha}`;
-        
+
         this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}{${this.quebraLinha}`;
         this.visitarExpressaoFuncaoConstruto(declaracao.funcao);
         this.codigoFormatado += `${" ".repeat(this.indentacaoAtual)}}${this.quebraLinha}`;
@@ -260,7 +264,7 @@ export class FormatadorPortugolStudio implements VisitanteComumInterface {
                 break;
             case 'Importar':
                 this.visitarDeclaracaoImportar(declaracaoOuConstruto as Importar);
-                break;                
+                break;
             case 'Isto':
                 this.visitarExpressaoIsto(declaracaoOuConstruto as Isto);
                 break;
@@ -317,8 +321,8 @@ export class FormatadorPortugolStudio implements VisitanteComumInterface {
                 break;
         }
     }
-    
-    
+
+
     formatar(declaracoes: Declaracao[]): string {
         this.indentacaoAtual = 0;
         this.codigoFormatado = `programa${this.quebraLinha}{${this.quebraLinha}`;
diff --git a/fontes/interfaces/visitante-comum-interface.ts b/fontes/interfaces/visitante-comum-interface.ts
index 2a475509..da336147 100644
--- a/fontes/interfaces/visitante-comum-interface.ts
+++ b/fontes/interfaces/visitante-comum-interface.ts
@@ -1,5 +1,6 @@
 import { Atribuir, ExpressaoRegular, FimPara, Literal, Super, TipoDe } from '../construtos';
 import {
+    Aleatorio,
     Bloco,
     Classe,
     Const,
@@ -29,6 +30,7 @@ import { ConstMultiplo } from '../declaracoes/const-multiplo';
 import { VarMultiplo } from '../declaracoes/var-multiplo';
 
 export interface VisitanteComumInterface {
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any>
     visitarDeclaracaoClasse(declaracao: Classe): any;
     visitarDeclaracaoConst(declaracao: Const): Promise<any>;
     visitarDeclaracaoConstMultiplo(declaracao: ConstMultiplo): Promise<any>;
diff --git a/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts b/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
index 36211ac0..c07c942f 100644
--- a/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
+++ b/fontes/interpretador/dialetos/egua-classico/interpretador-egua-classico.ts
@@ -21,6 +21,7 @@ import {
     Variavel,
 } from '../../../construtos';
 import {
+    Aleatorio,
     Classe,
     Const,
     ConstMultiplo,
@@ -163,6 +164,10 @@ export class InterpretadorEguaClassico implements InterpretadorInterface {
         return this.avaliar(expressao.expressao);
     }
 
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any> {
+        throw new Error('Método não implementado')
+    }
+
     eVerdadeiro(objeto: any): boolean {
         if (objeto === null) return false;
         if (typeof objeto === 'boolean') return Boolean(objeto);
diff --git a/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts b/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
index c8216a25..4991ec04 100644
--- a/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
+++ b/fontes/interpretador/dialetos/egua-classico/resolvedor/resolvedor.ts
@@ -1,5 +1,6 @@
 import { AcessoMetodoOuPropriedade, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, QualTipo, Super, TipoDe, Variavel } from '../../../../construtos';
 import {
+    Aleatorio,
     Bloco,
     Const,
     ConstMultiplo,
@@ -85,7 +86,7 @@ export class ResolvedorEguaClassico implements ResolvedorInterface, Interpretado
     visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
         throw new Error('Método não implementado.');
     }
-    
+
     visitarExpressaoTipoDe(expressao: TipoDe): Promise<any> {
         throw new Error('Método não implementado.');
     }
@@ -529,6 +530,10 @@ export class ResolvedorEguaClassico implements ResolvedorInterface, Interpretado
         return null;
     }
 
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any> {
+        throw new Error('Método não implementado.');
+    }
+
     resolver(declaracoes: Construto | Declaracao | Declaracao[]): RetornoResolvedor {
         if (Array.isArray(declaracoes)) {
             for (let i = 0; i < declaracoes.length; i++) {
diff --git a/fontes/interpretador/dialetos/mapler/interpretador-mapler.ts b/fontes/interpretador/dialetos/mapler/interpretador-mapler.ts
index 998855a6..dff5a1ef 100644
--- a/fontes/interpretador/dialetos/mapler/interpretador-mapler.ts
+++ b/fontes/interpretador/dialetos/mapler/interpretador-mapler.ts
@@ -1,5 +1,5 @@
 import { Binario, Construto, ExpressaoRegular, Logico, Variavel } from '../../../construtos';
-import { Const, Escreva, EscrevaMesmaLinha, Fazer, Leia } from '../../../declaracoes';
+import { Aleatorio, Const, Escreva, EscrevaMesmaLinha, Fazer, Leia } from '../../../declaracoes';
 import { InterpretadorBase } from '../..';
 import { ContinuarQuebra, Quebra } from '../../../quebras';
 
@@ -21,7 +21,11 @@ export class InterpretadorMapler extends InterpretadorBase {
     visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
         throw new Error('Método não implementado.');
     }
-    
+
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any>{
+        throw new Error('Método não implementado.');
+    }
+
     visitarDeclaracaoConst(declaracao: Const): Promise<any> {
         throw new Error('Método não implementado.');
     }
@@ -99,7 +103,6 @@ export class InterpretadorMapler extends InterpretadorBase {
             this.erros.push(erro);
         }
     }
-
     /**
      * Execução da leitura de valores da entrada configurada no
      * início da aplicação.
diff --git a/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts b/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
index 61e36978..35e1848f 100644
--- a/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
+++ b/fontes/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.ts
@@ -1,5 +1,6 @@
 import { Atribuir, Construto, ExpressaoRegular, FimPara, FormatacaoEscrita, Literal, QualTipo, Super, TipoDe, Variavel } from '../../../construtos';
 import {
+    Aleatorio,
     Bloco,
     Classe,
     Const,
@@ -544,7 +545,9 @@ export class InterpretadorPortugolIpt implements InterpretadorInterface {
         }
         return resultado;
     }
-
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any>{
+        throw new Error('Método não implementado.');
+    }
     /**
      * Executa o último escopo empilhado no topo na pilha de escopos do interpretador.
      * Esse método pega exceções, mas apenas as devolve.
diff --git a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
index c06fdfed..b5035231 100644
--- a/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
+++ b/fontes/interpretador/dialetos/visualg/interpretador-visualg.ts
@@ -1,5 +1,5 @@
 import { AcessoElementoMatriz, AtribuicaoPorIndicesMatriz, Binario, Construto, FimPara, Logico, Variavel } from '../../../construtos';
-import { Const, Escreva, EscrevaMesmaLinha, Fazer, Leia, Para } from '../../../declaracoes';
+import { Aleatorio, Const, Escreva, EscrevaMesmaLinha, Fazer, Leia, Para } from '../../../declaracoes';
 import { InterpretadorBase } from '../..';
 import { ContinuarQuebra, Quebra, SustarQuebra } from '../../../quebras';
 import { registrarBibliotecaNumericaVisuAlg } from '../../../bibliotecas/dialetos/visualg/numerica';
@@ -137,17 +137,22 @@ export class InterpretadorVisuAlg extends InterpretadorBase {
      * @returns Promise com o resultado da leitura.
      */
     async visitarExpressaoLeia(expressao: Leia): Promise<any> {
-        for (let argumento of expressao.argumentos) {
-            const promessaLeitura: Function = () =>
-                new Promise((resolucao) =>
-                    this.interfaceEntradaSaida.question(this.mensagemPrompt, (resposta: any) => {
-                        this.mensagemPrompt = '> ';
-                        resolucao(resposta);
-                    })
-                );
-
-            const valorLido = await promessaLeitura();
-            await comum.atribuirVariavel(this, argumento, valorLido);
+
+        // Verifica se a leitura deve ser interrompida antes de prosseguir
+
+        if (!expressao.eParaInterromper) {
+            for (let argumento of expressao.argumentos) {
+                const promessaLeitura: Function = () =>
+                    new Promise((resolucao) =>
+                        this.interfaceEntradaSaida.question(this.mensagemPrompt, (resposta: any) => {
+                            this.mensagemPrompt = '> ';
+                            resolucao(resposta);
+                        })
+                    );
+
+                const valorLido = await promessaLeitura();
+                await comum.atribuirVariavel(this, argumento, valorLido);
+            }
         }
     }
 
@@ -197,4 +202,22 @@ export class InterpretadorVisuAlg extends InterpretadorBase {
     async visitarExpressaoLogica(expressao: Logico): Promise<any> {
         return comum.visitarExpressaoLogica(this, expressao);
     }
+
+    async visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any> {
+
+        let retornoExecucao: any;
+        try {
+            retornoExecucao = await this.executar(declaracao.corpo);
+
+        } catch (error) {
+            this.erros.push({
+                erroInterno: error,
+                linha: declaracao.linha,
+                hashArquivo: declaracao.hashArquivo,
+            });
+            return Promise.reject(error)
+        }
+
+        return retornoExecucao;
+    }
 }
diff --git a/fontes/interpretador/interpretador-base.ts b/fontes/interpretador/interpretador-base.ts
index 2db4648d..0914692b 100644
--- a/fontes/interpretador/interpretador-base.ts
+++ b/fontes/interpretador/interpretador-base.ts
@@ -9,6 +9,7 @@ import { MicroAvaliadorSintatico } from './../../fontes/avaliador-sintatico/micr
 import { ErroEmTempoDeExecucao } from '../excecoes';
 import { InterpretadorInterface, ParametroInterface, SimboloInterface, VariavelInterface } from '../interfaces';
 import {
+    Aleatorio,
     Bloco,
     Classe,
     Const,
@@ -92,14 +93,14 @@ export class InterpretadorBase implements InterpretadorInterface {
     resultadoInterpretador: Array<string> = [];
 
     // Esta variável indica que uma propriedade de um objeto
-    // não precisa da palavra `isto` para ser acessada, ou seja, 
+    // não precisa da palavra `isto` para ser acessada, ou seja,
     // `minhaPropriedade` e `isto.minhaPropriedade` são a mesma coisa.
     // Potigol, por exemplo, é um dialeto que tem essa característica.
     expandirPropriedadesDeObjetosEmEspacoVariaveis: boolean;
 
     // Esta variável indica que propriedades de classes precisam ser
     // declaradas para serem válidas.
-    // Delégua e Pituguês são dialetos que requerem a declaração 
+    // Delégua e Pituguês são dialetos que requerem a declaração
     // de propriedades de classes.
     requerDeclaracaoPropriedades: boolean;
 
@@ -643,8 +644,8 @@ export class InterpretadorBase implements InterpretadorInterface {
                     argumentos.push(null);
                 }
             } else {
-                // TODO: Aparentemente isso aqui nunca funcionou. 
-                // Avaliar de simplesmente apagar este código, e usar o que foi 
+                // TODO: Aparentemente isso aqui nunca funcionou.
+                // Avaliar de simplesmente apagar este código, e usar o que foi
                 // implementado em `DeleguaFuncao.chamar`.
                 if (
                     parametros &&
@@ -1433,6 +1434,11 @@ export class InterpretadorBase implements InterpretadorInterface {
         return this.procurarVariavel(expressao.palavraChave);
     }
 
+
+    visitarDeclaracaoAleatorio(declaracao: Aleatorio): Promise<any>{
+        throw new Error('Método não implementado.');
+    }
+
     async visitarExpressaoDicionario(expressao: any): Promise<any> {
         const dicionario = {};
         for (let i = 0; i < expressao.chaves.length; i++) {
@@ -1534,7 +1540,9 @@ export class InterpretadorBase implements InterpretadorInterface {
      *                         pelo modo LAIR.
      */
     async executar(declaracao: Declaracao, mostrarResultado = false): Promise<any> {
+
         const resultado: any = await declaracao.aceitar(this);
+        /* console.log("Resultado aceitar: " + resultado, this); */
         if (mostrarResultado) {
             this.funcaoDeRetorno(this.paraTexto(resultado));
         }
diff --git a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
index df218c64..f2223c7e 100644
--- a/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
+++ b/fontes/lexador/dialetos/palavras-reservadas/visualg.ts
@@ -3,6 +3,7 @@ import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
 export const palavrasReservadas = {
     abs: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
     algoritmo: tiposDeSimbolos.ALGORITMO,
+    aleatorio: tiposDeSimbolos.ALEATORIO,
     arccos: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
     arcsen: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
     arctan: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
@@ -47,6 +48,8 @@ export const palavrasReservadas = {
     logn: tiposDeSimbolos.METODO_BIBLIOTECA_GLOBAL,
     logico: tiposDeSimbolos.LOGICO,
     nao: tiposDeSimbolos.NEGACAO, // Exceção
+    on: tiposDeSimbolos.ON,
+    off: tiposDeSimbolos.OFF,
     ou: tiposDeSimbolos.OU,
     outrocaso: tiposDeSimbolos.OUTRO_CASO,
     para: tiposDeSimbolos.PARA,
diff --git a/fontes/tipos-de-simbolos/visualg.ts b/fontes/tipos-de-simbolos/visualg.ts
index 14bb7f02..4a959719 100644
--- a/fontes/tipos-de-simbolos/visualg.ts
+++ b/fontes/tipos-de-simbolos/visualg.ts
@@ -1,6 +1,7 @@
 export default {
     ADICAO: 'ADICAO',
     ALGORITMO: 'ALGORITMO',
+    ALEATORIO: 'ALEATORIO',
     ATE: 'ATE',
     ATÉ: 'ATÉ',
     CARACTER: 'CARACTER',
@@ -51,6 +52,8 @@ export default {
     MULTIPLICACAO: 'MULTIPLICACAO',
     NEGACAO: 'NEGACAO',
     NUMERO: 'NUMERO',
+    ON: 'ON',
+    OFF: 'OFF',
     OU: 'OU',
     OUTRO_CASO: 'OUTRO_CASO',
     PARA: 'PARA',


Test patch:
diff --git a/testes/visualg/analisador-semantico.test.ts b/testes/visualg/analisador-semantico.test.ts
index b534a6a8..23240520 100644
--- a/testes/visualg/analisador-semantico.test.ts
+++ b/testes/visualg/analisador-semantico.test.ts
@@ -61,6 +61,27 @@ describe('Analisador sêmantico (Visualg)', () => {
                 expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
             });
 
+            it('Atribuição inválida de variáveis', () => {
+                const retornoLexador = lexador.mapear([
+                    'algoritmo "Atribuição inválida de variáveis"',
+                    'var x: real',
+                    'y: inteiro',
+                    'a: caractere',
+                    'l: logico',
+                    'inicio',
+                    'x <- "25"',
+                    'y <- "6x"',
+                    'a <- 0',
+                    'l <- "verdadeiro e falso"',
+                    'fimalgoritmo'
+                ], -1);
+
+                const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1);
+                const retornoAnalisadorSemantico = analisadorSemanticoVisualg.analisar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(4);
+            });
+
             it("Chamada de função inexistente", () => {
                 const retornoLexador = lexador.mapear([
                     'algoritmo "definindo função"',
diff --git a/testes/visualg/avaliador-sintatico.test.ts b/testes/visualg/avaliador-sintatico.test.ts
index d9a6a53a..48100db0 100644
--- a/testes/visualg/avaliador-sintatico.test.ts
+++ b/testes/visualg/avaliador-sintatico.test.ts
@@ -284,6 +284,26 @@ describe('Avaliador sintático (VisuAlg)', () => {
                 expect(retornoAvaliadorSintatico).toBeTruthy();
                 expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(22);
             });
+
+            it('Sucesso - Aleatorio - Números', () => {
+                const retornoLexador = lexador.mapear(
+                    [
+                        'algoritmo "Exemplo Xou"',
+                        'var',
+                        'numero: inteiro',
+                        'inicio',
+                        'aleatorio 1, 5',
+                        'leia(numero)',
+                        'fimalgoritmo',
+                    ],
+                    -1
+                );
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                expect(retornoAvaliadorSintatico).toBeTruthy();
+                expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2);
+            });
         });
 
         describe('Cenário de falha', () => {
@@ -406,6 +426,29 @@ describe('Avaliador sintático (VisuAlg)', () => {
 
                 expect(() => avaliadorSintatico.analisar(retornoLexador, 1)).toThrowError();
             });
+
+            it('Falha - Aleatorio', () => {
+                const retornoLexador = lexador.mapear(
+                    [
+                        'algoritmo "Exemplo Xou"',
+                        'var',
+                        'numero: inteiro',
+                        'inicio',
+                        'aleatorio 1, ',
+                        'leia(numero)',
+                        'fimalgoritmo',
+                    ],
+                    -1
+                );
+
+                expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrowError();
+                expect(() => avaliadorSintatico.analisar(retornoLexador, -1)).toThrow(
+                    expect.objectContaining({
+                        name: 'Error',
+                        message: "Esperado um número após ','.",
+                    })
+                );
+            });
         });
     });
 });
diff --git a/testes/visualg/interpretador.test.ts b/testes/visualg/interpretador.test.ts
index 85e518d6..7787ad97 100644
--- a/testes/visualg/interpretador.test.ts
+++ b/testes/visualg/interpretador.test.ts
@@ -602,6 +602,23 @@ describe('Interpretador', () => {
 
                 expect(retornoInterpretador.erros).toHaveLength(0);
             });
+
+            it('Sucesso - Aleatorio', async () => {
+                const retornoLexador = lexador.mapear([
+                    'algoritmo "declaração aleatorio on"',
+                    'var',
+                    'numero: inteiro',
+                    'inicio',
+                    'aleatorio on',
+                    'leia(numero)',
+                    'fimalgoritmo'
+                ], -1);
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+
+                const retornoInterpretador = await interpretador.interpretar(retornoAvaliadorSintatico.declaracoes);
+
+                expect(retornoInterpretador.erros).toHaveLength(0);
+            });
         });
     });
 });