Repository: DesignLiquido/delegua
Pull request #333 (2023-04-28 14:46:18)

Implementação da avaliação sintática para declaração de função, refatoração e testes

Nesta PR, foram realizadas as seguintes melhorias no projeto:

1. **Implementação da avaliação sintática para a declaração de função**: Esta atualização adiciona a funcionalidade de avaliar sintaticamente as declarações de função no código, permitindo uma análise mais precisa e melhorando a qualidade geral do projeto.

2. **Refatoração de algumas lógicas**: O código foi revisado e algumas lógicas foram refatoradas para aumentar a eficiência, a legibilidade e a manutenibilidade do projeto. Essas mudanças também facilitarão a implementação de novas funcionalidades no futuro.

3. **Testes abrangentes**: Foram criados testes para garantir a correta funcionalidade da avaliação sintática de declarações de função e das lógicas refatoradas. Esses testes irão assegurar que futuras mudanças no código não comprometam a integridade do projeto e ajudarão a identificar potenciais problemas antes de serem integrados ao código principal.

Esta PR é um passo importante para aumentar a qualidade e a robustez do projeto, e espera-se que essas melhorias beneficiem tanto os desenvolvedores quanto os usuários finais.


github-actions[bot]: <!-- jest coverage report action for options with hash 781087021f8e6c43aac1e668f4520603 -->

## Coverage report 



| <div title="Status of coverage:&#10; 🟢 - ok&#10; 🟡 - slightly more than threshold&#10; 🔴 - under the threshold">St.<sup>:grey_question:</sup></div> | Category   | Percentage                                                     | Covered / Total |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :--------- | :------------------------------------------------------------- | :-------------: |
|                                                                           🟡                                                                           | Statements | <div title="Base coverage is: 73.68%">73.94% (+0.25% 🔼)</div> |    5456/7379    |
|                                                                           🟡                                                                           | Branches   | <div title="Base coverage is: 62.16%">62.19% (+0.03% 🔼)</div> |    1696/2727    |
|                                                                           🟡                                                                           | Functions  | <div title="Base coverage is: 74.72%">75.09% (+0.38% 🔼)</div> |     805/1072    |
|                                                                           🟡                                                                           | Lines      | <div title="Base coverage is: 74.13%">74.39% (+0.26% 🔼)</div> |    5310/7138    |

<details><summary>Show new covered files 🐣</summary>
<br/>

| <div title="Status of coverage:&#10; 🟢 - ok&#10; 🟡 - slightly more than threshold&#10; 🔴 - under the threshold">St.<sup>:grey_question:</sup></div> | File                | Statements | Branches | Functions | Lines |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------ | :--------- | :------- | :-------- | :---- |
|                                                                           🟢                                                                           | utilidades/index.ts | 100%       | 100%     | 100%      | 100%  |

</details>


<details><summary>Show files with reduced coverage 🔻</summary>
<br/>

| <div title="Status of coverage:&#10; 🟢 - ok&#10; 🟡 - slightly more than threshold&#10; 🔴 - under the threshold">St.<sup>:grey_question:</sup></div> | File                                                                                                            | Statements                                                     | Branches                                                       | Functions                                                       | Lines                                                          |
| :----------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------- | :------------------------------------------------------------- | :-------------------------------------------------------------- | :------------------------------------------------------------- |
|                                                                           🟢                                                                           | <div title="avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts">`...` / avaliador-sintatico-birl.ts</div> | <div title="Base coverage is: 75.74%">81.02% (+5.27% 🔼)</div> | <div title="Base coverage is: 75.44%">73.08% (-2.36% 🔻)</div> | <div title="Base coverage is: 71.43%">82.35% (+10.92% 🔼)</div> | <div title="Base coverage is: 75.74%">81.02% (+5.27% 🔼)</div> |

</details>

## Test suite run success
392 tests passing in 35 suites.

<p align="right">Report generated by <a href="https://github.com/ArtiomTr/jest-coverage-report-action">🧪jest coverage report action</a> from c184e6f9fcbe3ddb8fb73ee685fb0a9ab30b7e5f</p>
<!-- Sticky Pull Request Comment -->

Patch:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index c8938edc..e8c9c929 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,6 +4,20 @@
     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
     "version": "0.2.0",
     "configurations": [
+        {
+            "name": "Teste",
+            "type": "node",
+            "request": "launch",
+            "runtimeArgs": [
+                "--inspect-brk",
+                "${workspaceRoot}/node_modules/jest/bin/jest.js",
+                // "interpretador.test.ts",
+                "avaliador-sintatico.test.ts",
+                "--runInBand"
+            ],
+            "console": "integratedTerminal",
+            "internalConsoleOptions": "neverOpen"
+        },
         {
             "name": "BIRL > Testes Lexador",
             "type": "node",
diff --git a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts
index f567733a..8c28d1d3 100644
--- a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts
+++ b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-birl.ts
@@ -11,24 +11,29 @@ import {
 } from '../../construtos';
 import {
     Bloco,
+    Continua,
     Declaracao,
     Enquanto,
     Escolha,
     Escreva,
     Expressao,
     Fazer,
+    FuncaoDeclaracao,
     Leia,
     Para,
     Retorna,
     Se,
+    Sustar,
     Var,
 } from '../../declaracoes';
 import { RetornoAvaliadorSintatico, RetornoLexador } from '../../interfaces/retornos';
 import { AvaliadorSintaticoBase } from '../avaliador-sintatico-base';
 
-import { InterpretadorInterface, SimboloInterface } from '../../interfaces';
+import { ParametroInterface, SimboloInterface } from '../../interfaces';
 import tiposDeSimbolos from '../../tipos-de-simbolos/birl';
 import { Construto } from '../../construtos/construto';
+import { TiposDadosInterface } from '../../interfaces/tipos-dados-interface';
+import { limpaItensNull } from '../../utilidades';
 
 export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
     tratarSimbolos(simbolos: Array<SimboloInterface>): string | void {
@@ -351,11 +356,15 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
             );
             let valorInicializacao = 0x00;
             if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
-                const literalInicializacao = this.consumir(
-                    tiposDeSimbolos.NUMERO,
-                    `Esperado literal de ${simboloInteiro.lexema} após símbolo de igual em declaração de variável.`
-                );
-                valorInicializacao = Number(literalInicializacao.literal);
+                if (this.verificarTipoSimboloAtual(tiposDeSimbolos.IDENTIFICADOR)) {
+                    valorInicializacao = this.declaracao();
+                } else if (this.verificarTipoSimboloAtual(tiposDeSimbolos.NUMERO)) {
+                    const literalInicializacao = this.consumir(
+                        tiposDeSimbolos.NUMERO,
+                        `Esperado literal de ${simboloInteiro.lexema} após símbolo de igual em declaração de variável.`
+                    );
+                    valorInicializacao = Number(literalInicializacao.literal);
+                }
                 inicializacoes.push(
                     new Var(
                         identificador,
@@ -459,9 +468,14 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
         this.consumir(tiposDeSimbolos.GENTE, 'Esperado expressão `GENTE` após `A` para condição.');
         this.consumir(tiposDeSimbolos.QUER, 'Esperado expressão `QUER` após `GENTE` para condição.');
         this.consumir(tiposDeSimbolos.INTERROGACAO, 'Esperado interrogação após `QUER` para condição.');
+        this.consumir(
+            tiposDeSimbolos.PARENTESE_ESQUERDO,
+            'Esperado parêntese esquerdo após interrogação para condição.'
+        );
 
         const condicao = this.declaracao();
 
+        this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, 'Esperado parêntese direito após condição.');
         this.consumir(
             tiposDeSimbolos.QUEBRA_LINHA,
             'Esperado quebra de linha após expressão de condição para condição.'
@@ -470,33 +484,33 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
         while (this.verificarTipoSimboloAtual(tiposDeSimbolos.QUEBRA_LINHA)) {
             this.consumir(tiposDeSimbolos.QUEBRA_LINHA, '');
         }
+        let caminhoSenao = null;
         do {
             declaracoes.push(this.declaracao());
-            this.avancarEDevolverAnterior();
-        } while (![tiposDeSimbolos.BIRL].includes(this.simbolos[this.atual].tipo));
 
-        let caminhoSenao = null;
-        if (this.verificarTipoSimboloAtual(tiposDeSimbolos.NAO)) {
-            const simboloSenao: SimboloInterface = this.consumir(
-                tiposDeSimbolos.NAO,
-                'Esperado expressão `NAO` após expressão de condição.'
-            );
-            this.consumir(tiposDeSimbolos.VAI, 'Esperado expressão `VAI` após `NAO`.');
-            this.consumir(tiposDeSimbolos.DAR, 'Esperado expressão `DAR` após `VAI`.');
-            this.consumir(tiposDeSimbolos.NAO, 'Esperado expressão `NAO` após `DAR`.');
+            if (this.verificarTipoSimboloAtual(tiposDeSimbolos.NAO)) {
+                const simboloSenao: SimboloInterface = this.consumir(
+                    tiposDeSimbolos.NAO,
+                    'Esperado expressão `NAO` após expressão de condição.'
+                );
+                this.consumir(tiposDeSimbolos.VAI, 'Esperado expressão `VAI` após `NAO`.');
+                this.consumir(tiposDeSimbolos.DAR, 'Esperado expressão `DAR` após `VAI`.');
+                this.consumir(tiposDeSimbolos.NAO, 'Esperado expressão `NAO` após `DAR`.');
 
-            const declaracaoSenao = [];
+                const declaracaoSenao = [];
 
-            do {
-                declaracaoSenao.push(this.declaracao());
-            } while (![tiposDeSimbolos.BIRL].includes(this.simbolos[this.atual].tipo));
+                do {
+                    declaracaoSenao.push(this.declaracao());
+                } while (![tiposDeSimbolos.BIRL].includes(this.simbolos[this.atual].tipo));
 
-            caminhoSenao = new Bloco(
-                this.hashArquivo,
-                Number(simboloSe.linha),
-                declaracaoSenao.filter((d) => d)
-            );
-        }
+                caminhoSenao = new Bloco(
+                    this.hashArquivo,
+                    Number(simboloSe.linha),
+                    declaracaoSenao.filter((d) => d)
+                );
+                break;
+            }
+        } while (![tiposDeSimbolos.BIRL].includes(this.simbolos[this.atual].tipo));
 
         this.consumir(tiposDeSimbolos.BIRL, 'Esperado expressão `BIRL` após expressão de condição.');
 
@@ -512,8 +526,70 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
         );
     }
 
+    resolveSimboloInterfaceParaTiposDadosInterface(simbolo: SimboloInterface): TiposDadosInterface {
+        switch (simbolo.tipo) {
+            case tiposDeSimbolos.TRAPEZIO:
+                this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DESCENDENTE);
+            case tiposDeSimbolos.MONSTRO:
+            case tiposDeSimbolos.MONSTRINHO:
+            case tiposDeSimbolos.MONSTRAO:
+                return 'numero';
+            case tiposDeSimbolos.FRANGO:
+                return 'texto';
+            default:
+                throw new Error('Tipo desconhecido');
+        }
+    }
+
+    protected logicaComumParamentros(): ParametroInterface[] {
+        const parametros: ParametroInterface[] = [];
+
+        do {
+            if (parametros.length >= 255) {
+                this.erro(this.simbolos[this.atual], 'Não pode haver mais de 255 parâmetros');
+            }
+
+            const parametro: Partial<ParametroInterface> = {
+                abrangencia: 'padrao',
+            };
+
+            const tipo = this.resolveTipo(this.simbolos[this.atual].tipo);
+
+            parametro.tipo = this.resolveSimboloInterfaceParaTiposDadosInterface(tipo);
+            this.avancarEDevolverAnterior();
+            parametro.nome = this.simbolos[this.atual];
+
+            parametros.push(parametro as ParametroInterface);
+            this.avancarEDevolverAnterior();
+
+            if (this.simbolos[this.atual].tipo === tiposDeSimbolos.VIRGULA) {
+                this.avancarEDevolverAnterior();
+            }
+        } while (![tiposDeSimbolos.PARENTESE_DIREITO].includes(this.simbolos[this.atual].tipo));
+        return parametros;
+    }
+
     corpoDaFuncao(tipo: string): FuncaoConstruto {
-        throw new Error('Método não implementado.');
+        const parenteseEsquerdo = this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, `Esperado '(' após o nome ${tipo}`);
+
+        let paramentros = [];
+        if (!this.verificarTipoSimboloAtual(tiposDeSimbolos.PARENTESE_DIREITO)) {
+            paramentros.push(this.logicaComumParamentros());
+        }
+        this.consumir(tiposDeSimbolos.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
+
+        let corpo = [];
+
+        do {
+            corpo.push(this.declaracao());
+        } while (![tiposDeSimbolos.BIRL].includes(this.simbolos[this.atual].tipo));
+
+        return new FuncaoConstruto(
+            this.hashArquivo,
+            Number(parenteseEsquerdo.linha),
+            paramentros,
+            limpaItensNull(corpo)
+        );
     }
 
     declacacaoEnquanto(): Enquanto {
@@ -540,11 +616,65 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
         );
     }
 
+    declaracaoSustar(): Sustar {
+        this.consumir(tiposDeSimbolos.SAI, 'Esperado expressão `SAI`.');
+        this.consumir(tiposDeSimbolos.FILHO, 'Esperado expressão `FILHO` após `SAI`.');
+        this.consumir(tiposDeSimbolos.DA, 'Esperado expressão `DA` após `FILHO`.');
+        this.consumir(tiposDeSimbolos.PUTA, 'Esperado expressão `PUTA` após `DA`.');
+        this.consumir(tiposDeSimbolos.PONTO_E_VIRGULA, 'Esperado expressão `PONTO_E_VIRGULA` após `PUTA`.');
+        return new Sustar(this.simbolos[this.atual - 1]);
+    }
+
+    declaracaoContinua(): Continua {
+        this.consumir(tiposDeSimbolos.VAMO, 'Esperado expressão `VAMO`.');
+        this.consumir(tiposDeSimbolos.MONSTRO, 'Esperado expressão `MONSTRO` após `VAMO`.');
+        this.consumir(tiposDeSimbolos.PONTO_E_VIRGULA, 'Esperado expressão `PONTO_E_VIRGULA` após `MONSTRO`.');
+
+        return new Continua(this.simbolos[this.atual - 1]);
+    }
+
+    resolveTipo(tipo: string): SimboloInterface {
+        switch (tipo) {
+            case tiposDeSimbolos.TRAPEZIO:
+                this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.DESCENDENTE);
+            case tiposDeSimbolos.MONSTRAO:
+            case tiposDeSimbolos.MONSTRINHO:
+            case tiposDeSimbolos.MONSTRO:
+            case tiposDeSimbolos.FRANGO:
+            case tiposDeSimbolos.BICEPS:
+                return this.simbolos[this.atual];
+            default:
+                throw new Error('Esperado tipo da função');
+        }
+    }
+
+    funcao(tipo: string): FuncaoDeclaracao {
+        this.consumir(tiposDeSimbolos.OH, 'Esperado expressão `OH`.');
+        this.consumir(tiposDeSimbolos.O, 'Esperado expressão `O` após `OH`.');
+        this.consumir(tiposDeSimbolos.HOME, 'Esperado expressão `HOME` após `O`.');
+        this.consumir(tiposDeSimbolos.AI, 'Esperado expressão `AI` após `HOME`.');
+        this.consumir(tiposDeSimbolos.PO, 'Esperado expressão `PO` após `AI`.');
+        this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO, 'Esperado parêntese esquerdo após `PO`.');
+
+        let tipoRetorno: SimboloInterface = this.resolveTipo(this.simbolos[this.atual].tipo);
+        this.avancarEDevolverAnterior();
+        const nomeFuncao: SimboloInterface = this.consumir(
+            tiposDeSimbolos.IDENTIFICADOR,
+            'Esperado nome da função apos a declaração do tipo.'
+        );
+
+        return new FuncaoDeclaracao(nomeFuncao, this.corpoDaFuncao(tipo), tipoRetorno);
+    }
+
     declaracao(): any {
         const simboloAtual = this.simbolos[this.atual];
         switch (simboloAtual.tipo) {
             case tiposDeSimbolos.BORA:
                 return this.declaracaoRetorna();
+            case tiposDeSimbolos.SAI:
+                return this.declaracaoSustar();
+            case tiposDeSimbolos.VAMO:
+                return this.declaracaoContinua();
             case tiposDeSimbolos.QUE:
                 return this.declaracaoLeia();
             case tiposDeSimbolos.ELE:
@@ -553,7 +683,6 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
                 return this.declacacaoEnquanto();
             case tiposDeSimbolos.MAIS:
                 return this.declaracaoPara();
-            // Declaração de inteiros
             case tiposDeSimbolos.MONSTRO:
             case tiposDeSimbolos.MONSTRINHO:
             case tiposDeSimbolos.MONSTRAO:
@@ -564,10 +693,10 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
             case tiposDeSimbolos.TRAPEZIO:
                 return this.declaracaoPontoFlutuante();
             case tiposDeSimbolos.OH:
-            // Retornar uma declaração de funcao
+                return this.funcao('funcao');
             case tiposDeSimbolos.AJUDA:
             // Retornar uma declaração de chamar funcao
-            case tiposDeSimbolos.CE: // "CE QUER VER ESSA PORRA?"
+            case tiposDeSimbolos.CE:
                 return this.declaracaoEscreva();
             case tiposDeSimbolos.PONTO_E_VIRGULA:
             case tiposDeSimbolos.QUEBRA_LINHA:
@@ -583,14 +712,6 @@ export class AvaliadorSintaticoBirl extends AvaliadorSintaticoBase {
         this.blocos = 0;
         this.atual = 0;
 
-        // 1 validação
-        /* if (this.blocos > 0) {
-            throw new ErroAvaliadorSintatico(
-                null,
-                'Quantidade de blocos abertos não corresponde com a quantidade de blocos fechados'
-            );
-        } */
-
         this.simbolos = retornoLexador.simbolos;
         const declaracoes = [];
 
diff --git a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts
index 1014eb76..896e1c0b 100644
--- a/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts
+++ b/fontes/avaliador-sintatico/dialetos/avaliador-sintatico-portugol-studio.ts
@@ -79,9 +79,9 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
                 if (this.simbolos[this.atual] && [tiposDeSimbolos.INCREMENTAR, tiposDeSimbolos.DECREMENTAR].includes(this.simbolos[this.atual].tipo)) {
                     const simboloIncrementoDecremento: SimboloInterface = this.avancarEDevolverAnterior();
                     return new Unario(
-                        this.hashArquivo, 
-                        simboloIncrementoDecremento, 
-                        new Variavel(this.hashArquivo, simboloIdentificador), 
+                        this.hashArquivo,
+                        simboloIncrementoDecremento,
+                        new Variavel(this.hashArquivo, simboloIdentificador),
                         'DEPOIS'
                     );
                 }
@@ -253,7 +253,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
                 abrangencia: 'padrao'
             };
 
-            if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CADEIA, tiposDeSimbolos.REAL, tiposDeSimbolos.REAL)) {
+            if (!this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CADEIA, tiposDeSimbolos.REAL, tiposDeSimbolos.INTEIRO)) {
                 throw this.erro(this.simbolos[this.atual], 'Esperado tipo de parâmetro válido para declaração de função.');
             }
 
@@ -261,7 +261,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
 
             // Em Portugol Studio, um parâmetro múltiplo é terminado por abre e fecha colchetes.
             if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.COLCHETE_ESQUERDO)) {
-                this.consumir(tiposDeSimbolos.COLCHETE_DIREITO, 
+                this.consumir(tiposDeSimbolos.COLCHETE_DIREITO,
                     'Esperado colchete direito após colchete esquerdo ao definir parâmetro múltiplo em função.');
                 parametro.abrangencia = 'multiplo';
             }
@@ -298,8 +298,8 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
     }
 
     /**
-     * Declaração de apenas uma variável. 
-     * Neste caso, o símbolo que determina o tipo da variável já foi consumido, 
+     * Declaração de apenas uma variável.
+     * Neste caso, o símbolo que determina o tipo da variável já foi consumido,
      * e o retorno conta com apenas uma variável retornada.
      */
     declaracaoDeVariavel(): Var {
@@ -310,13 +310,13 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
                     "Esperado identificador após palavra reservada 'inteiro'."
                 );
                 this.consumir(tiposDeSimbolos.IGUAL, "Esperado símbolo igual para inicialização de variável.");
-                const literalInicializacao = this.consumir(tiposDeSimbolos.INTEIRO, 
+                const literalInicializacao = this.consumir(tiposDeSimbolos.INTEIRO,
                     'Esperado literal inteiro após símbolo de igual em declaração de variável.');
                 const valorInicializacao = Number(literalInicializacao.literal);
                 return new Var(
-                    identificador, 
-                    new Literal(this.hashArquivo, 
-                        Number(literalInicializacao.linha), 
+                    identificador,
+                    new Literal(this.hashArquivo,
+                        Number(literalInicializacao.linha),
                         valorInicializacao
                     )
                 );
@@ -336,7 +336,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
             // Inicializações de variáveis podem ter valores definidos.
             let valorInicializacao = 0;
             if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
-                const literalInicializacao = this.consumir(tiposDeSimbolos.CADEIA, 
+                const literalInicializacao = this.consumir(tiposDeSimbolos.CADEIA,
                     'Esperado literal de cadeia de caracteres após símbolo de igual em declaração de variável.');
                 valorInicializacao = Number(literalInicializacao.literal);
             }
@@ -360,7 +360,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
             // Inicializações de variáveis podem ter valores definidos.
             let valorInicializacao = 0;
             if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
-                const literalInicializacao = this.consumir(tiposDeSimbolos.CARACTER, 
+                const literalInicializacao = this.consumir(tiposDeSimbolos.CARACTER,
                     'Esperado literal de caracter após símbolo de igual em declaração de variável.');
                 valorInicializacao = Number(literalInicializacao.literal);
             }
@@ -391,7 +391,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
             // Inicializações de variáveis podem ter valores definidos.
             let valorInicializacao = 0;
             if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
-                const literalInicializacao = this.consumir(tiposDeSimbolos.INTEIRO, 
+                const literalInicializacao = this.consumir(tiposDeSimbolos.INTEIRO,
                     'Esperado literal inteiro após símbolo de igual em declaração de variável.');
                 valorInicializacao = Number(literalInicializacao.literal);
             }
@@ -496,7 +496,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
             // Inicializações de variáveis podem ter valores definidos.
             let valorInicializacao = 0;
             if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.IGUAL)) {
-                const literalInicializacao = this.consumir(tiposDeSimbolos.REAL, 
+                const literalInicializacao = this.consumir(tiposDeSimbolos.REAL,
                     'Esperado literal real após símbolo de igual em declaração de variável.');
                 valorInicializacao = Number(literalInicializacao.literal);
             }
@@ -515,12 +515,12 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
     funcao(tipo: string): FuncaoDeclaracao {
         const simboloFuncao: SimboloInterface = this.avancarEDevolverAnterior();
 
-        // No Portugol Studio, se temos um símbolo de tipo após `função`, 
+        // No Portugol Studio, se temos um símbolo de tipo após `função`,
         // teremos um retorno no corpo da função.
         if (
             [
-                tiposDeSimbolos.REAL, 
-                tiposDeSimbolos.INTEIRO, 
+                tiposDeSimbolos.REAL,
+                tiposDeSimbolos.INTEIRO,
                 tiposDeSimbolos.CADEIA,
                 tiposDeSimbolos.CARACTER,
                 tiposDeSimbolos.LOGICO
@@ -559,7 +559,7 @@ export class AvaliadorSintaticoPortugolStudio extends AvaliadorSintaticoBase {
             case tiposDeSimbolos.LOGICO:
                 return this.declaracaoLogicos();
             case tiposDeSimbolos.PARA:
-                return this.declaracaoPara();        
+                return this.declaracaoPara();
             case tiposDeSimbolos.PROGRAMA:
             case tiposDeSimbolos.CHAVE_DIREITA:
                 this.avancarEDevolverAnterior();
diff --git a/fontes/declaracoes/const.ts b/fontes/declaracoes/const.ts
index a9ff0429..4c52eabc 100644
--- a/fontes/declaracoes/const.ts
+++ b/fontes/declaracoes/const.ts
@@ -1,5 +1,6 @@
 import { Construto } from '../construtos';
 import { InterpretadorInterface, SimboloInterface } from '../interfaces';
+import { TiposDadosInterface } from '../interfaces/tipos-dados-interface';
 import { Declaracao } from './declaracao';
 
 /**
@@ -8,12 +9,12 @@ import { Declaracao } from './declaracao';
 export class Const extends Declaracao {
     simbolo: SimboloInterface;
     inicializador: Construto;
-    tipo: 'texto' | 'numero' | 'longo' | 'lógico' | 'nulo' | 'vetor' | 'módulo' | 'dicionário' | 'função' | 'símbolo' | undefined
+    tipo: TiposDadosInterface
 
     constructor(
         simbolo: SimboloInterface,
         inicializador: Construto,
-        tipo: 'texto' | 'numero' | 'longo' | 'lógico' | 'nulo' | 'vetor' | 'módulo' | 'dicionário' | 'função' | 'símbolo' | undefined = undefined
+        tipo: TiposDadosInterface = undefined
     ) {
         super(Number(simbolo.linha), simbolo.hashArquivo);
         this.simbolo = simbolo;
diff --git a/fontes/declaracoes/funcao.ts b/fontes/declaracoes/funcao.ts
index 40238b9d..6cf2bec2 100644
--- a/fontes/declaracoes/funcao.ts
+++ b/fontes/declaracoes/funcao.ts
@@ -5,11 +5,13 @@ import { FuncaoConstruto } from '../construtos';
 export class FuncaoDeclaracao extends Declaracao {
     simbolo: SimboloInterface;
     funcao: FuncaoConstruto;
+    tipoRetorno?: SimboloInterface;
 
-    constructor(simbolo: SimboloInterface, funcao: FuncaoConstruto) {
+    constructor(simbolo: SimboloInterface, funcao: FuncaoConstruto, tipoRetorno?: SimboloInterface) {
         super(Number(simbolo.linha), simbolo.hashArquivo);
         this.simbolo = simbolo;
         this.funcao = funcao;
+        this.tipoRetorno = tipoRetorno;
     }
 
     async aceitar(visitante: InterpretadorInterface): Promise<any> {
diff --git a/fontes/declaracoes/var.ts b/fontes/declaracoes/var.ts
index 49e76e52..b996830b 100644
--- a/fontes/declaracoes/var.ts
+++ b/fontes/declaracoes/var.ts
@@ -1,5 +1,6 @@
 import { Construto } from '../construtos';
 import { InterpretadorInterface, SimboloInterface } from '../interfaces';
+import { TiposDadosInterface } from '../interfaces/tipos-dados-interface';
 import { Declaracao } from './declaracao';
 
 /**
@@ -8,13 +9,9 @@ import { Declaracao } from './declaracao';
 export class Var extends Declaracao {
     simbolo: SimboloInterface;
     inicializador: Construto;
-    tipo: 'texto' | 'numero' | 'longo' | 'lógico' | 'nulo' | 'vetor' | 'módulo' | 'dicionário' | 'função' | 'símbolo' | undefined
+    tipo: TiposDadosInterface;
 
-    constructor(
-        simbolo: SimboloInterface,
-        inicializador: Construto,
-        tipo: 'texto' | 'numero' | 'longo' | 'lógico' | 'nulo' | 'vetor' | 'módulo' | 'dicionário' | 'função' | 'símbolo' | undefined = undefined
-    ) {
+    constructor(simbolo: SimboloInterface, inicializador: Construto, tipo: TiposDadosInterface = undefined) {
         super(Number(simbolo.linha), simbolo.hashArquivo);
         this.simbolo = simbolo;
         this.inicializador = inicializador;
diff --git a/fontes/interfaces/parametro-interface.ts b/fontes/interfaces/parametro-interface.ts
index b67927a4..795818e2 100644
--- a/fontes/interfaces/parametro-interface.ts
+++ b/fontes/interfaces/parametro-interface.ts
@@ -1,7 +1,9 @@
 import { SimboloInterface } from './simbolo-interface';
+import { TiposDadosInterface } from './tipos-dados-interface';
 
 export interface ParametroInterface {
     abrangencia: 'padrao' | 'multiplo';
     nome: SimboloInterface;
+    tipo?: TiposDadosInterface;
     valorPadrao?: any;
 }
diff --git a/fontes/interfaces/tipos-dados-interface.ts b/fontes/interfaces/tipos-dados-interface.ts
new file mode 100644
index 00000000..150b7979
--- /dev/null
+++ b/fontes/interfaces/tipos-dados-interface.ts
@@ -0,0 +1,12 @@
+export type TiposDadosInterface =
+    | 'texto'
+    | 'numero'
+    | 'longo'
+    | 'lógico'
+    | 'nulo'
+    | 'vetor'
+    | 'módulo'
+    | 'dicionário'
+    | 'função'
+    | 'símbolo'
+    | undefined;
diff --git a/fontes/utilidades/index.ts b/fontes/utilidades/index.ts
new file mode 100644
index 00000000..407be4ad
--- /dev/null
+++ b/fontes/utilidades/index.ts
@@ -0,0 +1,3 @@
+export function limpaItensNull<T>(arr: Array<T | null>): Array<T> {
+    return arr.filter((item) => item !== null);
+}


Test patch:
diff --git a/testes/birl/avaliador-sintatico.test.ts b/testes/birl/avaliador-sintatico.test.ts
index 04a250be..7c2ae06d 100644
--- a/testes/birl/avaliador-sintatico.test.ts
+++ b/testes/birl/avaliador-sintatico.test.ts
@@ -1,7 +1,20 @@
 import { AvaliadorSintaticoBirl } from '../../fontes/avaliador-sintatico/dialetos';
-import { Enquanto, Para, Se } from '../../fontes/declaracoes';
+import {
+    Bloco,
+    Continua,
+    Enquanto,
+    Escreva,
+    FuncaoDeclaracao,
+    Para,
+    Retorna,
+    Se,
+    Sustar,
+    Var,
+} from '../../fontes/declaracoes';
 import { LexadorBirl } from '../../fontes/lexador/dialetos';
 import { RetornoLexador } from '../../fontes/interfaces/retornos/retorno-lexador';
+import { Simbolo } from '../../fontes/lexador';
+import { FuncaoConstruto, Variavel } from '../../fontes/construtos';
 
 describe('Avaliador Sintático Birl', () => {
     describe('analisar()', () => {
@@ -13,70 +26,74 @@ describe('Avaliador Sintático Birl', () => {
             avaliadorSintatico = new AvaliadorSintaticoBirl();
         });
 
-        it('Sucesso - Hello, World! Porra!', () => {
-            const retornoLexador = lexador.mapear(
-                ['HORA DO SHOW', '  CE QUER VER ESSA PORRA? ("Hello, World! Porra!\n");', '  BORA CUMPADE 0;', 'BIRL'],
-                -1
-            );
+        describe('Cenários de sucesso', () => {
+            it('Sucesso - Hello, World! Porra!', () => {
+                const retornoLexador = lexador.mapear(
+                    [
+                        'HORA DO SHOW',
+                        '  CE QUER VER ESSA PORRA? ("Hello, World! Porra!\n");',
+                        '  BORA CUMPADE 0;',
+                        'BIRL',
+                    ],
+                    -1
+                );
 
-            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
-
-            expect(retornoAvaliadorSintatico).toBeTruthy();
-            expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2);
-        });
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
 
-        it('Sucesso - Variavel - Numero', () => {
-            const retornoLexador = lexador.mapear(
-                [
-                    'HORA DO SHOW \n',
-                    '  MONSTRO M1 = 1; \n',
-                    '  CE QUER VER ESSA PORRA? (M1); \n',
-                    '  BORA CUMPADE 0; \n',
-                    'BIRL \n',
-                ],
-                -1
-            );
+                expect(retornoAvaliadorSintatico).toBeTruthy();
+                expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2);
+            });
 
-            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+            it('Sucesso - Variavel - Numero', () => {
+                const retornoLexador = lexador.mapear(
+                    [
+                        'HORA DO SHOW \n',
+                        '  MONSTRO M1 = 1; \n',
+                        '  CE QUER VER ESSA PORRA? (M1); \n',
+                        '  BORA CUMPADE 0; \n',
+                        'BIRL \n',
+                    ],
+                    -1
+                );
 
-            expect(retornoAvaliadorSintatico).toBeTruthy();
-            expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3);
-        });
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
 
-        it('Sucesso - Variavel - String', () => {
-            const retornoLexador = lexador.mapear([
-                'HORA DO SHOW \n',
-                "   FRANGO FR = 'testes';\n",
-                '   CE QUER VER ESSA PORRA? (FR); \n',
-                '   BORA CUMPADE 0; \n',
-                'BIRL \n',
-            ]);
-            //  FRANGO esta vindo como um indentificador
-            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
-
-            expect(retornoAvaliadorSintatico).toBeTruthy();
-            expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3);
-        });
+                expect(retornoAvaliadorSintatico).toBeTruthy();
+                expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3);
+            });
 
-        it('Sucesso - Variavel - Float', () => {
-            const retornoLexador = lexador.mapear(
-                [
+            it('Sucesso - Variavel - String', () => {
+                const retornoLexador = lexador.mapear([
                     'HORA DO SHOW \n',
-                    '  TRAPEZIO M1 = 1.03; \n',
-                    '  CE QUER VER ESSA PORRA? (M1); \n',
-                    '  BORA CUMPADE 0; \n',
+                    "   FRANGO FR = 'testes';\n",
+                    '   CE QUER VER ESSA PORRA? (FR); \n',
+                    '   BORA CUMPADE 0; \n',
                     'BIRL \n',
-                ],
-                -1
-            );
+                ]);
+                //  FRANGO esta vindo como um indentificador
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
 
-            const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                expect(retornoAvaliadorSintatico).toBeTruthy();
+                expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3);
+            });
 
-            expect(retornoAvaliadorSintatico).toBeTruthy();
-            expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3);
-        });
+            it('Sucesso - Variavel - Float', () => {
+                const retornoLexador = lexador.mapear(
+                    [
+                        'HORA DO SHOW \n',
+                        '  TRAPEZIO M1 = 1.03; \n',
+                        '  CE QUER VER ESSA PORRA? (M1); \n',
+                        '  BORA CUMPADE 0; \n',
+                        'BIRL \n',
+                    ],
+                    -1
+                );
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
 
-        describe('Sucesso - Variavel de tipagem não utilizada', () => {
+                expect(retornoAvaliadorSintatico).toBeTruthy();
+                expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(3);
+            });
             it('Sucesso - Variavel - short int', () => {
                 const retornoLexador = lexador.mapear([
                     'HORA DO SHOW \n',
@@ -167,8 +184,6 @@ describe('Avaliador Sintático Birl', () => {
                 expect(retornoAvaliadorSintatico.declaracoes[0].assinaturaMetodo).toBe('<principal>');
                 expect(retornoAvaliadorSintatico.declaracoes[0]).toBeInstanceOf(Se);
             });
-        });
-        describe('Sucesso - Loops', () => {
             it('Sucesso - declaração - for - incremento', () => {
                 const retornoLexador = lexador.mapear([
                     'HORA DO SHOW \n',
@@ -216,6 +231,10 @@ describe('Avaliador Sintático Birl', () => {
                 expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2);
                 expect(retornoAvaliadorSintatico.declaracoes[1].assinaturaMetodo).toBe('<principal>');
                 expect(retornoAvaliadorSintatico.declaracoes[1]).toBeInstanceOf(Para);
+                const declaracao1 = retornoAvaliadorSintatico.declaracoes[0][0] as Var;
+                expect(declaracao1.inicializador.valor).toBe(0);
+                expect(declaracao1.simbolo.lexema).toBe('M');
+                expect((retornoAvaliadorSintatico.declaracoes[1] as Para).corpo.declaracoes[0]).toBeInstanceOf(Escreva);
             });
             it('Sucesso - declaração - while', () => {
                 const RetornoLexador = lexador.mapear([
@@ -233,7 +252,80 @@ describe('Avaliador Sintático Birl', () => {
                 expect(RetornoAvaliadorSintatico.declaracoes).toHaveLength(2);
                 expect(RetornoAvaliadorSintatico.declaracoes[1].assinaturaMetodo).toBe('<principal>');
                 expect(RetornoAvaliadorSintatico.declaracoes[1]).toBeInstanceOf(Enquanto);
-            })
+            });
+            it('Sucesso - declaração - break', () => {
+                const retornoLexador = lexador.mapear([
+                    'HORA DO SHOW \n',
+                    '   MONSTRO M;\n',
+                    '   MAIS QUERO MAIS (M = 0; M < 5; M++)\n',
+                    '       CE QUER VER ESSA PORRA? ("teste");\n',
+                    '       SAI FILHO DA PUTA;\n',
+                    '   BIRL\n',
+                    'BIRL\n',
+                ]);
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                expect(retornoAvaliadorSintatico).toBeTruthy();
+                expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2);
+                expect(retornoAvaliadorSintatico.declaracoes[1].assinaturaMetodo).toBe('<principal>');
+                expect(retornoAvaliadorSintatico.declaracoes[1]).toBeInstanceOf(Para);
+                const declaracao1 = retornoAvaliadorSintatico.declaracoes[1] as Para;
+                expect(declaracao1.corpo.declaracoes[0]).toBeInstanceOf(Escreva);
+                expect(declaracao1.corpo.declaracoes[1]).toBeInstanceOf(Sustar);
+            });
+            it('Sucesso - declaração - continue', () => {
+                const retornoLexador = lexador.mapear([
+                    'HORA DO SHOW \n',
+                    '   MONSTRO M;\n',
+                    '   MAIS QUERO MAIS (M = 0; M < 5; M++)\n',
+                    '       CE QUER VER ESSA PORRA? ("teste");\n',
+                    '       ELE QUE A GENTE QUER? (M > 2)\n',
+                    '           SAI FILHO DA PUTA;\n',
+                    '       NAO VAI DAR NAO\n',
+                    '           VAMO MONSTRO;\n',
+                    '       BIRL\n',
+                    '   BIRL\n',
+                    'BIRL\n',
+                ]);
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                expect(retornoAvaliadorSintatico).toBeTruthy();
+                expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2);
+                expect(retornoAvaliadorSintatico.declaracoes[1].assinaturaMetodo).toBe('<principal>');
+                expect(retornoAvaliadorSintatico.declaracoes[1]).toBeInstanceOf(Para);
+                const declaracao1 = retornoAvaliadorSintatico.declaracoes[1] as Para;
+                expect(declaracao1.corpo.declaracoes[0]).toBeInstanceOf(Escreva);
+                expect(declaracao1.corpo.declaracoes[1]).toBeInstanceOf(Se);
+                const declaracaoSe = declaracao1.corpo.declaracoes[1] as Se;
+                expect((declaracaoSe.caminhoEntao as Bloco).declaracoes[0]).toBeInstanceOf(Sustar);
+                expect((declaracaoSe.caminhoSenao as Bloco).declaracoes[0]).toBeInstanceOf(Continua);
+            });
+            it('Sucesso - declaração - declaracaoFuncao', () => {
+                const retornoLexador = lexador.mapear([
+                    'HORA DO SHOW \n',
+                    '   OH O HOME AI PO(MONSTRO NOMEFUNCAO(MONSTRO primeiro, MONSTRO segundo)\n',
+                    '       MONSTRO C = primeiro + segundo;\n',
+                    '       BORA CUMPADE C;\n',
+                    '   BIRL\n',
+                    'BIRL\n',
+                ]);
+
+                const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1);
+                expect(retornoAvaliadorSintatico).toBeTruthy();
+                expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1);
+                expect(retornoAvaliadorSintatico.declaracoes[0].assinaturaMetodo).toBe('<principal>');
+                expect(retornoAvaliadorSintatico.declaracoes[0]).toBeInstanceOf(FuncaoDeclaracao);
+                const declaracoes = retornoAvaliadorSintatico.declaracoes[0] as FuncaoDeclaracao;
+                expect(declaracoes.tipoRetorno?.tipo).toBe('MONSTRO');
+                const funcao = declaracoes.funcao as FuncaoConstruto;
+                expect(funcao.parametros[0]).toHaveLength(2);
+                expect(funcao.corpo).toHaveLength(2);
+                expect(funcao.corpo[1]).toBeInstanceOf(Retorna);
+                expect(funcao.corpo[0]).toBeInstanceOf(Array<Var>);
+            });
         });
+        // describe('Cenários de erro', () => {
+        //     it('Falha - ')
+        // })
     });
 });