Repository: DesignLiquido/delegua
Pull request #585 (2024-01-20 11:31:57)

Analisador semantico visualg
## Descrição da Pull Request

### Funcionalidades Implementadas

1. **Constante/Variável Não Existente**
   - Implementada a verificação de existência de constantes/variáveis antes do acesso, lançando um erro caso uma constante/variável não declarada seja referenciada.

2. **Atribuição de Tipos Incompatíveis entre Variáveis**
   - Introduzida a verificação para garantir que apenas valores com tipos compatíveis sejam atribuídos a variáveis, lançando um erro caso a tentativa de atribuição envolva tipos incompatíveis.

3. **Chamada de Função Inexistente**
   - Implementada a verificação de existência de funções antes da chamada, lançando um erro caso uma função não declarada seja chamada.

54 **Chamada de Função com Número de Parâmetros Diferente do Esperado**
   - Adicionada a verificação do número correto de parâmetros durante a chamada de funções, lançando um erro se o número de argumentos fornecidos não corresponder ao número esperado pela função.

### Detalhes Técnicos
- Foram introduzidos novos métodos nas classes responsáveis pela manipulação de variáveis, constantes e funções.
- Testes unitários foram adicionados para garantir a integridade e funcionamento correto das novas funcionalidades.

leonelsanchesdasilva: Resolve https://github.com/DesignLiquido/delegua/issues/510

Patch:
diff --git a/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts b/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts
new file mode 100644
index 00000000..b4c6540a
--- /dev/null
+++ b/fontes/analisador-semantico/dialetos/analisador-semantico-visualg.ts
@@ -0,0 +1,394 @@
+import { Atribuir, Chamada, ExpressaoRegular, FimPara, FormatacaoEscrita, FuncaoConstruto, Literal, Super, TipoDe, Variavel, Vetor } from "../../construtos";
+import {
+    Bloco,
+    Classe,
+    Const,
+    ConstMultiplo,
+    Continua,
+    Declaracao,
+    Enquanto,
+    Escolha,
+    Escreva,
+    EscrevaMesmaLinha,
+    Expressao,
+    Fazer,
+    FuncaoDeclaracao,
+    Importar,
+    Leia,
+    LeiaMultiplo,
+    Para,
+    ParaCada,
+    Retorna,
+    Se,
+    Sustar,
+    Tente,
+    Var,
+    VarMultiplo
+} from "../../declaracoes";
+import { SimboloInterface } from "../../interfaces";
+import { AnalisadorSemanticoInterface } from "../../interfaces/analisador-semantico-interface";
+import { DiagnosticoAnalisadorSemantico, DiagnosticoSeveridade } from "../../interfaces/erros";
+import { RetornoAnalisadorSemantico } from "../../interfaces/retornos/retorno-analisador-semantico";
+import { TiposDadosInterface } from "../../interfaces/tipos-dados-interface";
+import { ContinuarQuebra, RetornoQuebra, SustarQuebra } from "../../quebras";
+import { PilhaVariaveis } from "../pilha-variaveis";
+
+interface VariavelHipoteticaInterface {
+    tipo: TiposDadosInterface;
+    subtipo?: 'texto' | 'número' | 'inteiro' | 'longo' | 'lógico';
+    imutavel: boolean;
+    valor?: any
+}
+
+interface FuncaoHipoteticaInterface {
+    valor: any
+}
+
+export class AnalisadorSemanticoVisualg implements AnalisadorSemanticoInterface {
+    pilhaVariaveis: PilhaVariaveis;
+    variaveis: { [nomeVariavel: string]: VariavelHipoteticaInterface };
+    funcoes: { [nomeFuncao: string]: FuncaoHipoteticaInterface }
+    atual: number;
+    diagnosticos: DiagnosticoAnalisadorSemantico[];
+
+    constructor() {
+        this.pilhaVariaveis = new PilhaVariaveis();
+        this.variaveis = {};
+        this.funcoes = {};
+        this.atual = 0;
+        this.diagnosticos = [];
+    }
+
+    erro(simbolo: SimboloInterface, mensagem: string): void {
+        this.diagnosticos.push({
+            simbolo: simbolo,
+            mensagem: mensagem,
+            hashArquivo: simbolo.hashArquivo,
+            linha: simbolo.linha,
+            severidade: DiagnosticoSeveridade.ERRO
+        });
+    }
+
+    aviso(simbolo: SimboloInterface, mensagem: string): void {
+        this.diagnosticos.push({
+            simbolo: simbolo,
+            mensagem: mensagem,
+            hashArquivo: simbolo.hashArquivo,
+            linha: simbolo.linha,
+            severidade: DiagnosticoSeveridade.AVISO
+        });
+    }
+
+    visitarDeclaracaoDeAtribuicao(expressao: Atribuir) {
+        const { simbolo, valor } = expressao;
+        let variavel = this.variaveis[simbolo.lexema];
+        if (!variavel) {
+            this.erro(
+                simbolo,
+                `Variável ${simbolo.lexema} ainda não foi declarada.`
+            );
+            return Promise.resolve();
+        }
+
+
+        if (variavel.tipo) {
+            if (valor instanceof Literal && variavel.tipo.includes('[]')) {
+                this.erro(simbolo, `Atribuição inválida, esperado tipo '${variavel.tipo}' na atribuição.`);
+                return Promise.resolve();
+            }
+            if (valor instanceof Vetor && !variavel.tipo.includes('[]')) {
+                this.erro(simbolo, `Atribuição inválida, esperado tipo '${variavel.tipo}' na atribuição.`);
+                return Promise.resolve();
+            }
+
+            if (valor instanceof Literal) {
+                let valorLiteral = typeof (valor as Literal).valor;
+                if (!['qualquer'].includes(variavel.tipo)) {
+                    if (valorLiteral === 'string') {
+                        if (variavel.tipo != 'texto') {
+                            this.erro(simbolo, `Esperado tipo '${variavel.tipo}' na atribuição.`);
+                            return Promise.resolve();
+                        }
+                    }
+                    if (valorLiteral === 'number') {
+                        if (!['inteiro', 'real'].includes(variavel.tipo)) {
+                            this.erro(simbolo, `Esperado tipo '${variavel.tipo}' na atribuição.`);
+                            return Promise.resolve();
+                        }
+                    }
+                }
+            }
+        }
+
+        if (variavel) {
+            this.variaveis[simbolo.lexema].valor = valor;
+        }
+    }
+
+    visitarDeclaracaoVar(declaracao: Var): Promise<any> {
+        this.variaveis[declaracao.simbolo.lexema] = {
+            imutavel: false,
+            tipo: declaracao.tipo,
+            valor: declaracao.inicializador !== null ? declaracao.inicializador.valor !== undefined ? declaracao.inicializador.valor : declaracao.inicializador : undefined
+        }
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoClasse(declaracao: Classe) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoConst(declaracao: Const): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoConstMultiplo(declaracao: ConstMultiplo): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoDeExpressao(declaracao: Expressao) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoDefinicaoFuncao(declaracao: FuncaoDeclaracao) {
+        for (let parametro of declaracao.funcao.parametros) {
+            if (parametro.hasOwnProperty('tipoDado') && !parametro.tipoDado.tipo) {
+                this.erro(declaracao.simbolo, `O tipo '${parametro.tipoDado.tipoInvalido}' não é valido`);
+            }
+        }
+
+        if (declaracao.funcao.tipoRetorno === undefined) {
+            this.erro(declaracao.simbolo, `Declaração de retorno da função é inválida`);
+        }
+
+        if (declaracao.funcao.parametros.length >= 255) {
+            this.erro(declaracao.simbolo, 'Não pode haver mais de 255 parâmetros');
+        }
+
+        this.funcoes[declaracao.simbolo.lexema] = {
+            valor: declaracao.funcao
+        }
+
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoEnquanto(declaracao: Enquanto) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoEscolha(declaracao: Escolha) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoEscreva(declaracao: Escreva) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoEscrevaMesmaLinha(declaracao: EscrevaMesmaLinha) {
+        declaracao.argumentos.forEach((argumento: FormatacaoEscrita) => {
+            if (argumento.expressao instanceof Variavel) {
+                if (!this.variaveis[argumento.expressao.simbolo.lexema]) {
+                    this.erro(argumento.expressao.simbolo, `Variável '${argumento.expressao.simbolo.lexema}' não existe.`)
+                    return Promise.resolve();
+                }
+                if (this.variaveis[argumento.expressao.simbolo.lexema]?.valor === undefined) {
+                    this.aviso(argumento.expressao.simbolo, `Variável '${argumento.expressao.simbolo.lexema}' não foi inicializada.`)
+                    return Promise.resolve();
+                }
+            }
+        })
+
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoFazer(declaracao: Fazer) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoImportar(declaracao: Importar) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoPara(declaracao: Para): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoParaCada(declaracao: ParaCada): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoSe(declaracao: Se) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoTente(declaracao: Tente) {
+        return Promise.resolve();
+    }
+
+    visitarDeclaracaoVarMultiplo(declaracao: VarMultiplo): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoAcessoIndiceVariavel(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoVetor(expressao: any) {
+        return Promise.resolve();
+    }
+    visitarExpressaoAcessoMetodo(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoAgrupamento(expressao: any): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoAtribuicaoPorIndice(expressao: any): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoBinaria(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoBloco(declaracao: Bloco): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoContinua(declaracao?: Continua): ContinuarQuebra {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoDeChamada(expressao: Chamada) {
+        if (expressao.entidadeChamada instanceof Variavel) {
+            const variavel = expressao.entidadeChamada as Variavel;
+            const funcaoChamada = this.variaveis[variavel.simbolo.lexema] || this.funcoes[variavel.simbolo.lexema]
+            if (!funcaoChamada) {
+                this.erro(
+                    variavel.simbolo,
+                    `Função '${variavel.simbolo.lexema} não foi declarada.'`
+                )
+                return Promise.resolve();
+            }
+            const funcao = funcaoChamada.valor as FuncaoConstruto;
+            if (funcao.parametros.length != expressao.argumentos.length) {
+                this.erro(
+                    variavel.simbolo,
+                    `Esperava ${funcao.parametros.length} ${funcao.parametros.length > 1 ? "argumentos" : "argumento"}, mas obteve ${expressao.argumentos.length}.`
+                )
+            }
+
+            for (let [indice, arg0] of funcao.parametros.entries()) {
+                const arg1 = expressao.argumentos[indice];
+                if (arg1) {
+                    if (arg0.tipoDado?.tipo.toLowerCase() === 'caracter' && typeof arg1.valor !== 'string') {
+                        this.erro(
+                            variavel.simbolo,
+                            `O valor passado para o parâmetro '${arg0.tipoDado.nome}' é diferente do esperado pela função.`
+                        );
+                    }
+                    else if (['inteiro', 'real'].includes(arg0.tipoDado?.tipo.toLowerCase())
+                        && typeof arg1.valor !== 'number') {
+                        this.erro(
+                            variavel.simbolo,
+                            `O valor passado para o parâmetro '${arg0.tipoDado.nome}' é diferente do esperado pela função.`
+                        );
+                    }
+                }
+            }
+        }
+        return Promise.resolve()
+    }
+
+    visitarExpressaoDeVariavel(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoDefinirValor(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoDeleguaFuncao(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoDicionario(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoExpressaoRegular(expressao: ExpressaoRegular): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoFalhar(expressao: any): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoFimPara(declaracao: FimPara) {
+        return Promise.resolve();
+    }
+    visitarExpressaoFormatacaoEscrita(declaracao: FormatacaoEscrita) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoIsto(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoLeia(expressao: Leia): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoLeiaMultiplo(expressao: LeiaMultiplo): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoLiteral(expressao: Literal): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoLogica(expressao: any) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoRetornar(declaracao: Retorna): Promise<RetornoQuebra> {
+        return Promise.resolve(null);
+    }
+
+    visitarExpressaoSuper(expressao: Super) {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoSustar(declaracao?: Sustar): SustarQuebra {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoTipoDe(expressao: TipoDe): Promise<any> {
+        return Promise.resolve();
+    }
+
+    visitarExpressaoUnaria(expressao: any) {
+        return Promise.resolve();
+    }
+    visitarExpressaoAcessoElementoMatriz(expressao: any) {
+        return Promise.resolve()
+    }
+
+    visitarExpressaoAtribuicaoPorIndicesMatriz(expressao: any): Promise<any> {
+        return Promise.resolve()
+    }
+    analisar(declaracoes: Declaracao[]): RetornoAnalisadorSemantico {
+        this.variaveis = {};
+        this.atual = 0;
+        this.diagnosticos = [];
+        while (this.atual < declaracoes.length) {
+            declaracoes[this.atual].aceitar(this);
+            this.atual++;
+        }
+
+        return {
+            diagnosticos: this.diagnosticos
+        } as RetornoAnalisadorSemantico
+    }
+}
diff --git a/fontes/analisador-semantico/dialetos/index.ts b/fontes/analisador-semantico/dialetos/index.ts
index 6df675a9..2bead003 100644
--- a/fontes/analisador-semantico/dialetos/index.ts
+++ b/fontes/analisador-semantico/dialetos/index.ts
@@ -1,2 +1,3 @@
 export * from './analisador-semantico-birl';
 export * from './analisador-semantico-mapler';
+export * from './analisador-semantico-visualg';
diff --git a/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts b/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts
index d0baa3ef..525054e0 100644
--- a/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts
+++ b/fontes/avaliador-sintatico/dialetos/visualg/avaliador-sintatico-visualg.ts
@@ -40,6 +40,7 @@ import { Simbolo } from '../../../lexador';
 
 import tiposDeSimbolos from '../../../tipos-de-simbolos/visualg';
 import { ParametroVisuAlg } from './parametro-visualg';
+import { TiposDadosInterface } from '../../../interfaces/tipos-dados-interface';
 
 export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
     blocoPrincipalIniciado: boolean;
@@ -226,13 +227,15 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
                         this.atual++;
                     } else {
                         for (let identificador of dadosVariaveis.identificadores) {
+                            const tipo = dadosVariaveis.tipo as TiposDadosInterface
                             switch (dadosVariaveis.tipo) {
                                 case tiposDeSimbolos.CARACTER:
                                 case tiposDeSimbolos.CARACTERE:
                                     inicializacoes.push(
                                         new Var(
                                             identificador,
-                                            new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), '')
+                                            new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), ''),
+                                            tipo
                                         )
                                     );
                                     break;
@@ -241,7 +244,8 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
                                     inicializacoes.push(
                                         new Var(
                                             identificador,
-                                            new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), 0)
+                                            new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), 0),
+                                            tipo
                                         )
                                     );
                                     break;
@@ -249,7 +253,8 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
                                     inicializacoes.push(
                                         new Var(
                                             identificador,
-                                            new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), false)
+                                            new Literal(this.hashArquivo, Number(dadosVariaveis.simbolo.linha), false),
+                                            tipo
                                         )
                                     );
                                     break;
@@ -455,6 +460,35 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
         return expressao;
     }
 
+    simboloAtual(): SimboloInterface {
+        return this.simbolos[this.atual - 2];
+    }
+
+    verificarDefinicaoTipoAtual(): TiposDadosInterface {
+        const tipos = ['inteiro', 'qualquer', 'real', 'texto', 'vazio', 'vetor', 'caracter'];
+
+        const lexema = this.simboloAtual().lexema.toLowerCase();
+
+        const contemTipo = tipos.find((tipo) => tipo === lexema);
+
+        if (contemTipo && this.verificarTipoProximoSimbolo(tiposDeSimbolos.COLCHETE_ESQUERDO)) {
+            const tiposVetores = ['inteiro[]', 'qualquer[]', 'real[]', 'texto[]', 'caracter[]'];
+            this.avancarEDevolverAnterior();
+
+            if (!this.verificarTipoProximoSimbolo(tiposDeSimbolos.COLCHETE_DIREITO)) {
+                throw this.erro(this.simbolos[this.atual - 1], "Esperado símbolo de fechamento do vetor ']'.");
+            }
+
+            const contemTipoVetor = tiposVetores.find((tipo) => tipo === `${lexema}[]`);
+
+            this.avancarEDevolverAnterior();
+
+            return contemTipoVetor as TiposDadosInterface;
+        }
+
+        return contemTipo as TiposDadosInterface;
+    }
+
     corpoDaFuncao(tipo: any): FuncaoConstruto {
         const simboloAnterior = this.simbolos[this.atual - 1];
 
@@ -463,6 +497,7 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
         this.consumir(tiposDeSimbolos.DOIS_PONTOS, 'Esperado dois-pontos após nome de função.');
 
         // Tipo retornado pela função.
+        let tipoRetorno = null
         if (
             !this.verificarSeSimboloAtualEIgualA(
                 tiposDeSimbolos.INTEIRO,
@@ -476,7 +511,7 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
         }
 
         this.consumir(tiposDeSimbolos.QUEBRA_LINHA, "Esperado quebra de linha após tipo retornado por 'funcao'.");
-
+        tipoRetorno = this.verificarDefinicaoTipoAtual();
         const inicializacoes = this.validarSegmentoVar();
         this.validarSegmentoInicio('função');
 
@@ -486,7 +521,8 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
             this.hashArquivo,
             Number(simboloAnterior.linha),
             parametros,
-            corpo.filter((d) => d)
+            corpo.filter((d) => d),
+            tipoRetorno
         );
     }
 
@@ -944,11 +980,18 @@ export class AvaliadorSintaticoVisuAlg extends AvaliadorSintaticoBase {
         if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO)) {
             while (!this.verificarTipoSimboloAtual(tiposDeSimbolos.PARENTESE_DIREITO)) {
                 const dadosParametros = this.logicaComumParametroVisuAlg();
+                const tipoDadoParametro = {
+                    nome: dadosParametros.simbolo.lexema,
+                    tipo: dadosParametros.tipo as TiposDadosInterface,
+                    tipoInvalido: !dadosParametros.tipo ? this.simboloAtual().lexema : null
+                }
+
                 for (let parametro of dadosParametros.identificadores) {
                     parametros.push({
                         abrangencia: 'padrao',
                         nome: parametro,
                         referencia: dadosParametros.referencia,
+                        tipoDado: tipoDadoParametro,
                     });
                 }
             }
diff --git a/fontes/interfaces/tipos-dados-interface.ts b/fontes/interfaces/tipos-dados-interface.ts
index a95581e2..a1161011 100644
--- a/fontes/interfaces/tipos-dados-interface.ts
+++ b/fontes/interfaces/tipos-dados-interface.ts
@@ -15,5 +15,7 @@ export type TiposDadosInterface =
     | 'símbolo'
     | 'texto'
     | 'texto[]'
+    | 'caracter'
+    | 'caracter[]'
     | 'vetor'
     | undefined;


Test patch:
diff --git a/testes/visualg/analisador-semantico.test.ts b/testes/visualg/analisador-semantico.test.ts
new file mode 100644
index 00000000..88961e4c
--- /dev/null
+++ b/testes/visualg/analisador-semantico.test.ts
@@ -0,0 +1,102 @@
+import { AnalisadorSemanticoVisualg } from '../../fontes/analisador-semantico/dialetos/analisador-semantico-visualg'
+import { AvaliadorSintaticoVisuAlg } from "../../fontes/avaliador-sintatico/dialetos";
+import { LexadorVisuAlg } from "../../fontes/lexador/dialetos";
+
+describe('Analisador sêmantico (Visualg)', () => {
+    describe('analisar()', () => {
+        let lexador: LexadorVisuAlg;
+        let avaliadorSintaticoVisuAlg: AvaliadorSintaticoVisuAlg;
+        let analisadorSemanticoVisualg: AnalisadorSemanticoVisualg
+
+        beforeEach(() => {
+            lexador = new LexadorVisuAlg();
+            avaliadorSintaticoVisuAlg = new AvaliadorSintaticoVisuAlg();
+            analisadorSemanticoVisualg = new AnalisadorSemanticoVisualg();
+        });
+
+
+        describe('Cenários de falha', () => {
+            it('Variável indefinida, não declarada(escreva)', () => {
+                const retornoLexador = lexador.mapear([
+                    'algoritmo "Declaração de variável"',
+                    'var',
+                    'inicio',
+                    'escreva(idade, "teste");',
+                    'fimalgoritmo'
+                ], -1);
+                const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1);
+                const retornoAnalisadorSemantico = analisadorSemanticoVisualg.analisar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
+            });
+
+            it('Variável indefinida, não declarada(atribuição)', () => {
+                const retornoLexador = lexador.mapear([
+                    'algoritmo "Atribuição de valor"',
+                    'var',
+                    'inicio',
+                    'idade <- 2',
+                    'fimalgoritmo'
+                ], -1);
+
+                const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1);
+                const retornoAnalisadorSemantico = analisadorSemanticoVisualg.analisar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
+            });
+
+            it('Atribuição inválida', () => {
+                const retornoLexador = lexador.mapear([
+                    'algoritmo "Atribuição de valor"',
+                    'var',
+                    'idade: real',
+                    'inicio',
+                    'idade <- "2"',
+                    'fimalgoritmo'
+                ], -1);
+
+                const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1);
+                const retornoAnalisadorSemantico = analisadorSemanticoVisualg.analisar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
+            });
+
+            it("Chamada de função inexistente", () => {
+                const retornoLexador = lexador.mapear([
+                    'algoritmo "definindo função"',
+                    'var',
+                    'resultado: caracter',
+                    'inicio',
+                    'saudacao(4);',
+                    'fimalgoritmo'
+                ], -1)
+
+                const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1);
+                const retornoAnalisadorSemantico = analisadorSemanticoVisualg.analisar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
+            })
+
+            it("Chamada de função com número de parametro diferentes", () => {
+                const retornoLexador = lexador.mapear([
+                    'algoritmo "definindo função"',
+                    'var',
+                    'resultado: caracter',
+                    'função saudacao(nome: caracter): caracter',
+                    'var',
+                    'inicio',
+                    'retorna "Bem vindo " + nome',
+                    'fimfunção',
+                    'inicio',
+                    'saudacao(4);',
+                    'fimalgoritmo'
+                ], -1)
+
+                const retornoAvaliadorSintatico = avaliadorSintaticoVisuAlg.analisar(retornoLexador, -1);
+                const retornoAnalisadorSemantico = analisadorSemanticoVisualg.analisar(retornoAvaliadorSintatico.declaracoes);
+                expect(retornoAnalisadorSemantico).toBeTruthy();
+                expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1);
+            })
+        })
+    })
+})
\ No newline at end of file