diff --git a/fontes/analisador-semantico/analisador-semantico.ts b/fontes/analisador-semantico/analisador-semantico.ts index f821fbf1..1a0bfe8a 100644 --- a/fontes/analisador-semantico/analisador-semantico.ts +++ b/fontes/analisador-semantico/analisador-semantico.ts @@ -63,16 +63,26 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface { return Promise.resolve(); } - erro(simbolo: SimboloInterface, mensagemDeErro: string): void { + erro(simbolo: SimboloInterface, mensagem: string): void { this.diagnosticos.push({ simbolo: simbolo, - mensagem: mensagemDeErro, + 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 + }); + } + verificarTipoAtribuido(declaracao: Var | Const) { if (declaracao.tipo) { if (['vetor', 'qualquer[]', 'inteiro[]', 'texto[]'].includes(declaracao.tipo)) { @@ -483,13 +493,7 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface { this.verificarTipoAtribuido(declaracao); if (this.variaveis.hasOwnProperty(declaracao.simbolo.lexema)) { - this.diagnosticos.push({ - simbolo: declaracao.simbolo, - mensagem: 'Declaração de constante já feita.', - hashArquivo: declaracao.hashArquivo, - linha: declaracao.linha, - severidade: DiagnosticoSeveridade.ERRO, - }); + this.erro(declaracao.simbolo, 'Declaração de constante já feita.'); } else { this.variaveis[declaracao.simbolo.lexema] = { imutavel: true, @@ -498,6 +502,28 @@ export class AnalisadorSemantico implements AnalisadorSemanticoInterface { }; } + this.virificarTipoDeclaracaoConst(declaracao); + + + return Promise.resolve(); + } + + virificarTipoDeclaracaoConst(declaracao: Const): Promise { + + if (declaracao.inicializador instanceof Binario) { + // verificar tipos iguais no lado esquerdo e direito + const binario = declaracao.inicializador as Binario; + this.verificarLadoBinario(binario.direita); + this.verificarLadoBinario(binario.esquerda); + + const tipoDireita = typeof binario.direita.valor; + const tipoEsquerda = typeof binario.esquerda.valor; + + if (tipoDireita !== tipoEsquerda) { + this.aviso(declaracao.simbolo, 'Declaração de constante com tipos diferentes.'); + } + } + return Promise.resolve(); } diff --git a/testes/analisador-semantico.test.ts b/testes/analisador-semantico.test.ts index 97f52f9e..3dcf4ba6 100644 --- a/testes/analisador-semantico.test.ts +++ b/testes/analisador-semantico.test.ts @@ -1,6 +1,7 @@ import { Lexador } from '../fontes/lexador'; import { AvaliadorSintatico } from '../fontes/avaliador-sintatico'; import { AnalisadorSemantico } from '../fontes/analisador-semantico'; +import { DiagnosticoSeveridade } from '../fontes/interfaces/erros'; describe('Analisador semântico', () => { let lexador: Lexador; @@ -505,13 +506,13 @@ describe('Analisador semântico', () => { it('sucesso - verificar função declarada', () => { const retornoLexador = lexador.mapear([ - "funcao funcaoExistente() { ", - " retorna verdadeiro; ", - "} ", - "enquanto (funcaoExistente()) { ", - " escreva('teste'); ", - " sustar; ", - "} ", + "funcao funcaoExistente() { ", + " retorna verdadeiro; ", + "} ", + "enquanto (funcaoExistente()) { ", + " escreva('teste'); ", + " sustar; ", + "} ", ], -1); const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes); @@ -651,7 +652,7 @@ describe('Analisador semântico', () => { const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes); expect(retornoAnalisadorSemantico).toBeTruthy(); expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(2); - }); + }); }); }); @@ -763,8 +764,33 @@ describe('Analisador semântico', () => { expect(retornoAnalisadorSemantico).toBeTruthy(); expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1); }); - }); + }); + }); + describe('Cenários conversão implicita', () => { + describe('Cenários de sucesso', () => { + it('Sucesso - conversão implicita com variável definida com valor válido', () => { + const retornoLexador = lexador.mapear([ + "const valor = 2 + 2", + ], -1); + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes); + expect(retornoAnalisadorSemantico).toBeTruthy(); + expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(0); + }); + }); + describe('Cenários de aviso', () => { + it('Aviso - conversão implicita com variável definida com valor válido', () => { + const retornoLexador = lexador.mapear([ + "const valor = 2 + '2'", + ], -1); + const retornoAvaliadorSintatico = avaliadorSintatico.analisar(retornoLexador, -1); + const retornoAnalisadorSemantico = analisadorSemantico.analisar(retornoAvaliadorSintatico.declaracoes); + expect(retornoAnalisadorSemantico).toBeTruthy(); + expect(retornoAnalisadorSemantico.diagnosticos.filter(item=> item.severidade === DiagnosticoSeveridade.AVISO)).toHaveLength(1); + expect(retornoAnalisadorSemantico.diagnosticos).toHaveLength(1); + }); + }); }); }); });