Skip to content

Commit b175405

Browse files
- Avaliação sintática em colunas.
- Ajustes em testes unitários.
1 parent f074943 commit b175405

File tree

8 files changed

+157
-44
lines changed

8 files changed

+157
-44
lines changed

execucao.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import { Lexador } from "./fontes/lexador";
66
const lexador = new Lexador();
77
const avaliadorSintatico = new AvaliadorSintatico();
88
const sentencaSelecao = 'SELECIONAR NOME, EMAIL DE clientes ONDE IDADE = 18;';
9-
const resultadoLexador = lexador.mapear([sentencaSelecao]);
10-
const teste = avaliadorSintatico.analisar(resultadoLexador);
9+
let resultadoLexador = lexador.mapear([sentencaSelecao]);
10+
let teste = avaliadorSintatico.analisar(resultadoLexador);
1111
console.log(teste);
12+
13+
const sentencaCriacao = 'CRIAR TABELA clientes(ID INTEIRO NAO NULO CHAVE PRIMARIA AUTO INCREMENTO, NOME TEXTO(100) NAO NULO, IDADE INTEIRO NAO NULO, EMAIL TEXTO(255) NAO NULO, ATIVO LOGICO NAO NULO);';
14+
resultadoLexador = lexador.mapear([sentencaCriacao]);
15+
teste = avaliadorSintatico.analisar(resultadoLexador);
16+
console.log(teste);

fontes/avaliador-sintatico/avaliador-sintatico.ts

Lines changed: 116 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,132 @@ import {
66
} from '../interfaces/retornos';
77
import tiposDeSimbolos from '../tipos-de-simbolos';
88
import { AvaliadorSintaticoBase } from './avaliador-sintatico-base';
9-
import { InformacoesColuna } from './informacaoColuna';
9+
import { Coluna } from '../construtos/coluna';
1010

1111
export class AvaliadorSintatico extends AvaliadorSintaticoBase {
1212
private avancar(): void {
13-
this.atual++;
13+
if (!this.estaNoFinal()) {
14+
this.atual++;
15+
}
1416
}
1517

16-
private logicaColunas(): InformacoesColuna {
17-
return null;
18+
private declaracaoCriacaoColuna(): Coluna {
19+
// Nome
20+
const nomeDaColuna = this.consumir(tiposDeSimbolos.IDENTIFICADOR,
21+
'Esperado identificador de nome de coluna em comando de criação de tabela.');
22+
23+
// Tipo de dados
24+
let tipoColuna = null;
25+
let tamanhoColuna = null;
26+
switch (this.simbolos[this.atual].tipo) {
27+
case tiposDeSimbolos.INTEIRO:
28+
tipoColuna = tiposDeSimbolos.INTEIRO;
29+
this.avancar();
30+
break;
31+
case tiposDeSimbolos.LOGICO:
32+
tipoColuna = tiposDeSimbolos.LOGICO;
33+
this.avancar();
34+
break;
35+
case tiposDeSimbolos.TEXTO:
36+
tipoColuna = tiposDeSimbolos.TEXTO;
37+
this.avancar();
38+
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PARENTESE_ESQUERDO)) {
39+
tamanhoColuna = this.consumir(tiposDeSimbolos.NUMERO,
40+
'Esperado tamanho de texto de coluna em comando de criação de tabela.');
41+
this.consumir(tiposDeSimbolos.PARENTESE_DIREITO,
42+
'Esperado parêntese direito após declaração de tamanho de coluna em comando de criação de tabela.');
43+
}
44+
45+
break;
46+
default:
47+
throw this.erro(this.simbolos[this.atual],
48+
'Esperado tipo de dados válido na definição de coluna em comando de criação de tabela.');
49+
}
50+
51+
// Nulo/Não Nulo
52+
let nulo = true;
53+
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.NAO, tiposDeSimbolos.NULO)) {
54+
const simboloAnterior = this.simbolos[this.atual - 1];
55+
switch (simboloAnterior.tipo) {
56+
case tiposDeSimbolos.NAO:
57+
this.consumir(tiposDeSimbolos.NULO,
58+
'Esperado palavra reservada "NULO" após palavra reservada "NÃO" em declaração de coluna em comando de criação de tabela.');
59+
nulo = false;
60+
break;
61+
case tiposDeSimbolos.NULO:
62+
default:
63+
break;
64+
}
65+
}
66+
67+
// Chave primária?
68+
let chavePrimaria = false;
69+
let autoIncremento = false;
70+
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.CHAVE)) {
71+
switch (this.simbolos[this.atual].tipo) {
72+
case tiposDeSimbolos.PRIMARIA:
73+
chavePrimaria = true;
74+
this.avancar();
75+
if (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.AUTO)) {
76+
this.consumir(tiposDeSimbolos.INCREMENTO,
77+
'Esperado palavra reservada "INCREMENTO" após palavra reservada "AUTO" em declaração de coluna em comando de criação de tabela.');
78+
autoIncremento = true;
79+
}
80+
break;
81+
default:
82+
throw this.erro(this.simbolos[this.atual],
83+
'Esperado palavra reservada "PRIMARIA" após palavra reservada "CHAVE" na definição de coluna em comando de criação de tabela.');
84+
}
85+
}
86+
87+
return new Coluna(nomeDaColuna.lexema, tipoColuna, tamanhoColuna, nulo, chavePrimaria, false);
1888
}
1989

2090
private declaracaoCriar(): Criar {
21-
this.avancar();
22-
if (this.verificaSeLexemaSimboloAtual('TABELA')) {
23-
this.avancar();
24-
const nomeDaTabela = this.simbolos[this.atual].lexema;
25-
this.avancar();
26-
if (this.verificaSeLexemaSimboloAtual('(')) {
27-
this.consumir(
28-
'(',
29-
'Esperado abrir parenteses após nome da tabela'
30-
);
31-
32-
const colunas: InformacoesColuna[] = [];
33-
34-
while (!this.verificaSeLexemaSimboloAtual(')')) {
35-
this.logicaColunas();
36-
this.avancar();
37-
}
91+
// Essa linha nunca deve retornar erro.
92+
this.consumir(tiposDeSimbolos.CRIAR, 'Esperado palavra reservada "CRIAR".');
3893

39-
return new Criar(
40-
this.simbolos[this.atual].linha,
41-
nomeDaTabela,
42-
colunas
43-
);
44-
}
94+
switch (this.simbolos[this.atual].tipo) {
95+
case 'TABELA':
96+
default:
97+
return this.declaracaoCriarTabela();
98+
}
99+
}
100+
101+
private declaracaoCriarTabela() {
102+
// Essa linha nunca deve retornar erro.
103+
this.consumir(tiposDeSimbolos.TABELA, 'Esperado palavra reservada "TABELA".');
104+
105+
const nomeDaTabela = this.consumir(tiposDeSimbolos.IDENTIFICADOR,
106+
'Esperado identificador de nome de tabela após palavra reservada "TABELA".');
107+
108+
this.consumir(tiposDeSimbolos.PARENTESE_ESQUERDO,
109+
'Esperado abertura de parênteses após nome da tabela');
110+
111+
const colunas: Coluna[] = [];
112+
113+
do {
114+
colunas.push(this.declaracaoCriacaoColuna());
45115
}
116+
while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.VIRGULA));
117+
118+
this.consumir(tiposDeSimbolos.PARENTESE_DIREITO,
119+
'Esperado fechamento de parênteses após nome da tabela');
120+
121+
// Ponto-e-vírgula opcional.
122+
// TODO: trazer isso mais tarde.
123+
// this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PONTO_VIRGULA);
124+
125+
return new Criar(
126+
this.simbolos[this.atual].linha,
127+
nomeDaTabela.lexema,
128+
colunas
129+
);
46130
}
47131

48132
private declaracaoSelecionar() {
49133
// Essa linha nunca deve retornar erro.
50-
this.consumir(tiposDeSimbolos.SELECIONAR, 'Esperado palavra reservada "SELECIONAR".')
134+
this.consumir(tiposDeSimbolos.SELECIONAR, 'Esperado palavra reservada "SELECIONAR".');
51135

52136
// Colunas
53137
let tudo = false;
@@ -93,11 +177,14 @@ export class AvaliadorSintatico extends AvaliadorSintaticoBase {
93177

94178
const direita = this.simbolos[this.atual];
95179
this.avancar();
96-
180+
97181
condicoes.push(new Condicao(esquerda, operador, direita.literal || direita.lexema));
98182
} while (this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.E));
99183
}
100184

185+
// Ponto-e-vírgula opcional.
186+
this.verificarSeSimboloAtualEIgualA(tiposDeSimbolos.PONTO_VIRGULA);
187+
101188
return new Selecionar(-1, nomeTabela.lexema, colunas, condicoes, tudo);
102189
}
103190

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export { AvaliadorSintatico } from './avaliador-sintatico';
22
export { ErroAvaliadorSintatico } from './erro-avaliador-sintatico';
3-
export * from './informacaoColuna';
3+
export * from '../construtos/coluna';

fontes/comandos/criar.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { InformacoesColuna } from '../avaliador-sintatico';
1+
import { Coluna } from '../avaliador-sintatico';
22
import { Comando } from './comando';
33

44
export class Criar extends Comando {
55
public tabela: string;
6-
public colunas: InformacoesColuna[];
7-
constructor(linha: number, tabela: string, colunas: InformacoesColuna[]) {
6+
public colunas: Coluna[];
7+
constructor(linha: number, tabela: string, colunas: Coluna[]) {
88
super(linha);
99
this.tabela = tabela;
1010
this.colunas = colunas;
Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
1-
export class InformacoesColuna {
1+
export class Coluna {
22
public nomeColuna: string;
3+
public tipo: 'INTEIRO' | 'LOGICO' | 'NUMERO' | 'TEXTO';
4+
public tamanho: number;
35
public nulo: boolean;
46
public chavePrimaria: boolean;
57
public chaveEstrangeira: boolean;
6-
public tipo: string;
7-
public tamanho: number;
8+
89
constructor(
910
nomeColuna: string,
10-
tipo: string,
11-
tamanho: number,
11+
tipo: 'INTEIRO' | 'LOGICO' | 'NUMERO' | 'TEXTO',
12+
tamanho?: number,
1213
nulo?: boolean,
1314
chavePrimaria?: boolean,
1415
chaveEstrangeira?: boolean
1516
) {
1617
this.nomeColuna = nomeColuna;
18+
this.tipo = tipo;
19+
this.tamanho = tamanho || -1;
20+
1721
this.nulo = nulo || false;
1822
this.chavePrimaria = chavePrimaria || false;
19-
this.chaveEstrangeira = chavePrimaria ? false : chaveEstrangeira;
20-
this.tipo = tipo;
21-
this.tamanho = tamanho;
23+
this.chaveEstrangeira = chaveEstrangeira || false;
2224
}
2325
}

fontes/palavras-reservadas.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,24 @@ import tiposDeSimbolos from './tipos-de-simbolos';
22

33
export default {
44
atualizar: tiposDeSimbolos.ATUALIZAR,
5+
auto: tiposDeSimbolos.AUTO,
6+
chave: tiposDeSimbolos.CHAVE,
57
criar: tiposDeSimbolos.CRIAR,
68
de: tiposDeSimbolos.DE,
79
definir: tiposDeSimbolos.DEFINIR,
810
e: tiposDeSimbolos.E,
911
em: tiposDeSimbolos.EM,
1012
excluir: tiposDeSimbolos.EXCLUIR,
13+
incremento: tiposDeSimbolos.INCREMENTO,
1114
inserir: tiposDeSimbolos.INSERIR,
15+
inteiro: tiposDeSimbolos.INTEIRO,
16+
logico: tiposDeSimbolos.LOGICO,
17+
nao: tiposDeSimbolos.NAO,
18+
nulo: tiposDeSimbolos.NULO,
1219
onde: tiposDeSimbolos.ONDE,
20+
primaria: tiposDeSimbolos.PRIMARIA,
1321
selecionar: tiposDeSimbolos.SELECIONAR,
22+
tabela: tiposDeSimbolos.TABELA,
23+
texto: tiposDeSimbolos.TEXTO,
1424
valores: tiposDeSimbolos.VALORES
1525
};

fontes/tipos-de-simbolos.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
export default {
22
ATUALIZAR: 'ATUALIZAR',
3+
AUTO: 'AUTO',
4+
CHAVE: 'CHAVE',
35
CRIAR: 'CRIAR',
46
DE: 'DE',
57
DEFINIR: 'DEFINIR',
@@ -8,17 +10,24 @@ export default {
810
EXCLUIR: 'EXCLUIR',
911
IDENTIFICADOR: 'IDENTIFICADOR',
1012
IGUAL: 'IGUAL',
13+
INCREMENTO: 'INCREMENTO',
1114
INSERIR: 'INSERIR',
15+
INTEIRO: 'INTEIRO',
16+
LOGICO: 'LOGICO',
1217
MAIOR: 'MAIOR',
1318
MAIOR_IGUAL: 'MAIOR_IGUAL',
1419
MENOR: 'MENOR',
1520
MENOR_IGUAL: 'MENOR_IGUAL',
21+
NAO: 'NAO',
22+
NULO: 'NULO',
1623
NUMERO: 'NUMERO',
1724
PARENTESE_DIREITO: 'PARENTESE_DIREITO',
1825
PARENTESE_ESQUERDO: 'PARENTESE_ESQUERDO',
1926
PONTO_VIRGULA: 'PONTO_VIRGULA',
27+
PRIMARIA: 'PRIMARIA',
2028
ONDE: 'ONDE',
2129
SELECIONAR: 'SELECIONAR',
30+
TABELA: 'TABELA',
2231
TEXTO: 'TEXTO',
2332
TUDO: 'TUDO',
2433
VALORES: 'VALORES',

testes/avaliador-sintatico.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('Avaliador Sintático', () => {
3232
const retornoAvaliadorSintatico =
3333
avaliadorSintatico.analisar(retornoLexador);
3434
expect(retornoAvaliadorSintatico).toBeTruthy();
35-
expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(2);
35+
expect(retornoAvaliadorSintatico.declaracoes).toHaveLength(1);
3636
expect(retornoAvaliadorSintatico.erros).toHaveLength(0);
3737
});
3838
});

0 commit comments

Comments
 (0)