@designliquido/delegua 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/avaliador-sintatico/avaliador-sintatico.d.ts +11 -1
- package/avaliador-sintatico/avaliador-sintatico.d.ts.map +1 -1
- package/avaliador-sintatico/avaliador-sintatico.js +433 -66
- package/avaliador-sintatico/avaliador-sintatico.js.map +1 -1
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.d.ts +9 -2
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.d.ts.map +1 -1
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.js +84 -14
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.js.map +1 -1
- package/bin/package.json +1 -1
- package/construtos/acesso-intervalo-variavel.js +3 -3
- package/construtos/acesso-intervalo-variavel.js.map +1 -1
- package/construtos/chamada.d.ts.map +1 -1
- package/construtos/chamada.js +5 -2
- package/construtos/chamada.js.map +1 -1
- package/construtos/comentario-como-construto.js +1 -1
- package/construtos/comentario-como-construto.js.map +1 -1
- package/construtos/decorador.d.ts.map +1 -1
- package/construtos/decorador.js +12 -1
- package/construtos/decorador.js.map +1 -1
- package/construtos/funcao.d.ts.map +1 -1
- package/construtos/funcao.js +13 -2
- package/construtos/funcao.js.map +1 -1
- package/declaracoes/classe.d.ts +4 -1
- package/declaracoes/classe.d.ts.map +1 -1
- package/declaracoes/classe.js +4 -1
- package/declaracoes/classe.js.map +1 -1
- package/declaracoes/funcao.d.ts +8 -2
- package/declaracoes/funcao.d.ts.map +1 -1
- package/declaracoes/funcao.js +6 -1
- package/declaracoes/funcao.js.map +1 -1
- package/declaracoes/index.d.ts +1 -0
- package/declaracoes/index.d.ts.map +1 -1
- package/declaracoes/index.js +1 -0
- package/declaracoes/index.js.map +1 -1
- package/declaracoes/interface.d.ts +27 -0
- package/declaracoes/interface.d.ts.map +1 -0
- package/declaracoes/interface.js +45 -0
- package/declaracoes/interface.js.map +1 -0
- package/declaracoes/propriedade-classe.d.ts +7 -2
- package/declaracoes/propriedade-classe.d.ts.map +1 -1
- package/declaracoes/propriedade-classe.js +5 -1
- package/declaracoes/propriedade-classe.js.map +1 -1
- package/interfaces/interpretador-interface.d.ts +2 -0
- package/interfaces/interpretador-interface.d.ts.map +1 -1
- package/interfaces/visitante-delegua-interface.d.ts +2 -1
- package/interfaces/visitante-delegua-interface.d.ts.map +1 -1
- package/interpretador/comum.d.ts.map +1 -1
- package/interpretador/comum.js +45 -0
- package/interpretador/comum.js.map +1 -1
- package/interpretador/dialetos/egua-classico/interpretador-egua-classico.d.ts +1 -0
- package/interpretador/dialetos/egua-classico/interpretador-egua-classico.d.ts.map +1 -1
- package/interpretador/dialetos/egua-classico/interpretador-egua-classico.js +3 -2
- package/interpretador/dialetos/egua-classico/interpretador-egua-classico.js.map +1 -1
- package/interpretador/dialetos/egua-classico/resolvedor/resolvedor.d.ts +1 -0
- package/interpretador/dialetos/egua-classico/resolvedor/resolvedor.d.ts.map +1 -1
- package/interpretador/dialetos/egua-classico/resolvedor/resolvedor.js +1 -0
- package/interpretador/dialetos/egua-classico/resolvedor/resolvedor.js.map +1 -1
- package/interpretador/dialetos/pitugues/comum.js +1 -1
- package/interpretador/dialetos/pitugues/comum.js.map +1 -1
- package/interpretador/dialetos/pitugues/interpretador-pitugues.d.ts.map +1 -1
- package/interpretador/dialetos/pitugues/interpretador-pitugues.js +16 -0
- package/interpretador/dialetos/pitugues/interpretador-pitugues.js.map +1 -1
- package/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.d.ts +1 -0
- package/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.d.ts.map +1 -1
- package/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.js +1 -0
- package/interpretador/dialetos/portugol-ipt/interpretador-portugol-ipt.js.map +1 -1
- package/interpretador/estruturas/delegua-funcao-nativa.d.ts +18 -0
- package/interpretador/estruturas/delegua-funcao-nativa.d.ts.map +1 -0
- package/interpretador/estruturas/delegua-funcao-nativa.js +43 -0
- package/interpretador/estruturas/delegua-funcao-nativa.js.map +1 -0
- package/interpretador/estruturas/delegua-funcao.d.ts +2 -1
- package/interpretador/estruturas/delegua-funcao.d.ts.map +1 -1
- package/interpretador/estruturas/delegua-funcao.js +15 -2
- package/interpretador/estruturas/delegua-funcao.js.map +1 -1
- package/interpretador/estruturas/descritor-tipo-classe.d.ts +36 -0
- package/interpretador/estruturas/descritor-tipo-classe.d.ts.map +1 -1
- package/interpretador/estruturas/descritor-tipo-classe.js +85 -10
- package/interpretador/estruturas/descritor-tipo-classe.js.map +1 -1
- package/interpretador/estruturas/index.d.ts +2 -0
- package/interpretador/estruturas/index.d.ts.map +1 -1
- package/interpretador/estruturas/index.js +2 -0
- package/interpretador/estruturas/index.js.map +1 -1
- package/interpretador/estruturas/objeto-base.d.ts +3 -0
- package/interpretador/estruturas/objeto-base.d.ts.map +1 -0
- package/interpretador/estruturas/objeto-base.js +71 -0
- package/interpretador/estruturas/objeto-base.js.map +1 -0
- package/interpretador/estruturas/objeto-delegua-classe.d.ts +4 -3
- package/interpretador/estruturas/objeto-delegua-classe.d.ts.map +1 -1
- package/interpretador/estruturas/objeto-delegua-classe.js +98 -6
- package/interpretador/estruturas/objeto-delegua-classe.js.map +1 -1
- package/interpretador/interpretador-base.d.ts +8 -1
- package/interpretador/interpretador-base.d.ts.map +1 -1
- package/interpretador/interpretador-base.js +115 -10
- package/interpretador/interpretador-base.js.map +1 -1
- package/interpretador/interpretador.d.ts +2 -1
- package/interpretador/interpretador.d.ts.map +1 -1
- package/interpretador/interpretador.js +64 -4
- package/interpretador/interpretador.js.map +1 -1
- package/interpretador/pilha-escopos-execucao.d.ts.map +1 -1
- package/interpretador/pilha-escopos-execucao.js +5 -0
- package/interpretador/pilha-escopos-execucao.js.map +1 -1
- package/lexador/lexador.d.ts +6 -0
- package/lexador/lexador.d.ts.map +1 -1
- package/lexador/lexador.js +36 -1
- package/lexador/lexador.js.map +1 -1
- package/lexador/palavras-reservadas.d.ts +13 -0
- package/lexador/palavras-reservadas.d.ts.map +1 -1
- package/lexador/palavras-reservadas.js +13 -0
- package/lexador/palavras-reservadas.js.map +1 -1
- package/package.json +1 -1
- package/tipos-de-simbolos/delegua.d.ts +9 -0
- package/tipos-de-simbolos/delegua.d.ts.map +1 -1
- package/tipos-de-simbolos/delegua.js +9 -0
- package/tipos-de-simbolos/delegua.js.map +1 -1
- package/umd/delegua.js +1588 -497
|
@@ -51,6 +51,7 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
51
51
|
this.erros = [];
|
|
52
52
|
this.performance = performance;
|
|
53
53
|
this.tiposDefinidosEmCodigo = {};
|
|
54
|
+
this.interfacesDeclaradas = {};
|
|
54
55
|
this.tiposDeFerramentasExternas = {};
|
|
55
56
|
this.primitivasConhecidas = {};
|
|
56
57
|
this.pilhaEscopos = new pilha_escopos_1.PilhaEscopos();
|
|
@@ -257,8 +258,7 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
257
258
|
new declaracoes_1.Se(condicao, new declaracoes_1.Bloco(retornoExpressao.hashArquivo, retornoExpressao.linha, [
|
|
258
259
|
new declaracoes_1.Retorna(simboloVariavelIteracao, retornoExpressao),
|
|
259
260
|
]), [], null),
|
|
260
|
-
])), 'qualquer[]'
|
|
261
|
-
);
|
|
261
|
+
])), retornoExpressao.tipo ? `${retornoExpressao.tipo}[]` : 'qualquer[]');
|
|
262
262
|
}
|
|
263
263
|
async primario() {
|
|
264
264
|
const simboloAtual = this.simbolos[this.atual];
|
|
@@ -1056,7 +1056,7 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
1056
1056
|
if (Array.isArray(retornoDeclaracao)) {
|
|
1057
1057
|
declaracoes = declaracoes.concat(retornoDeclaracao);
|
|
1058
1058
|
}
|
|
1059
|
-
else {
|
|
1059
|
+
else if (retornoDeclaracao !== null) {
|
|
1060
1060
|
declaracoes.push(retornoDeclaracao);
|
|
1061
1061
|
}
|
|
1062
1062
|
}
|
|
@@ -1541,6 +1541,41 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
1541
1541
|
this.pilhaDecoradores = [];
|
|
1542
1542
|
return retornos;
|
|
1543
1543
|
}
|
|
1544
|
+
logicaComumInferenciaTiposAcessoMetodoOuPropriedade(entidadeChamada) {
|
|
1545
|
+
// Algumas coisas podem acontecer aqui.
|
|
1546
|
+
// Uma delas é a variável/constante ser uma classe padrão.
|
|
1547
|
+
// Isso ocorre quando a importação é feita de uma biblioteca Node.js.
|
|
1548
|
+
// Nesse caso, o tipo de `entidadeChamada.objeto` começa com uma letra maiúscula.
|
|
1549
|
+
if (entidadeChamada.objeto.tipo &&
|
|
1550
|
+
entidadeChamada.objeto.tipo.match(/^[A-Z]/)) {
|
|
1551
|
+
const tipoCorrespondente = this.tiposDefinidosPorBibliotecas[entidadeChamada.objeto.tipo];
|
|
1552
|
+
if (!tipoCorrespondente) {
|
|
1553
|
+
throw new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(entidadeChamada.simbolo, `Tipo '${entidadeChamada.objeto.tipo}' não foi encontrado entre os tipos definidos por bibliotecas.`);
|
|
1554
|
+
}
|
|
1555
|
+
if (!(entidadeChamada.simbolo.lexema in
|
|
1556
|
+
tipoCorrespondente.metodos) &&
|
|
1557
|
+
!(entidadeChamada.simbolo.lexema in
|
|
1558
|
+
tipoCorrespondente.propriedades)) {
|
|
1559
|
+
throw new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(entidadeChamada.simbolo, `Membro '${entidadeChamada.simbolo.lexema}' não existe no tipo '${entidadeChamada.objeto.tipo}'.`);
|
|
1560
|
+
}
|
|
1561
|
+
if (entidadeChamada.simbolo.lexema in
|
|
1562
|
+
tipoCorrespondente.metodos) {
|
|
1563
|
+
const metodoCorrespondente = tipoCorrespondente.metodos[entidadeChamada.simbolo.lexema];
|
|
1564
|
+
return metodoCorrespondente.tipoRetorno || 'qualquer';
|
|
1565
|
+
}
|
|
1566
|
+
const propriedadeCorrespondente = tipoCorrespondente.propriedades[entidadeChamada.simbolo.lexema];
|
|
1567
|
+
return propriedadeCorrespondente.tipo;
|
|
1568
|
+
}
|
|
1569
|
+
// Este caso ocorre quando a variável/constante é do tipo 'qualquer',
|
|
1570
|
+
// e a chamada normalmente é feita para uma primitiva.
|
|
1571
|
+
// A inferência, portanto, ocorre pelo uso da primitiva.
|
|
1572
|
+
for (const primitiva in this.primitivasConhecidas) {
|
|
1573
|
+
if (this.primitivasConhecidas[primitiva].hasOwnProperty(entidadeChamada.simbolo.lexema)) {
|
|
1574
|
+
return this.primitivasConhecidas[primitiva][entidadeChamada.simbolo.lexema].tipo;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
throw new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(entidadeChamada.simbolo, `Primitiva '${entidadeChamada.simbolo.lexema}' não existe.`);
|
|
1578
|
+
}
|
|
1544
1579
|
logicaComumInferenciaTiposVariaveisEConstantes(inicializador, tipo) {
|
|
1545
1580
|
if (tipo !== 'qualquer') {
|
|
1546
1581
|
return tipo;
|
|
@@ -1566,40 +1601,7 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
1566
1601
|
const tipoRetornoAcessoMetodoResolvido = entidadeChamadaAcessoMetodo.tipoRetornoMetodo.replace('<T>', entidadeChamadaAcessoMetodo.objeto.tipo);
|
|
1567
1602
|
return tipoRetornoAcessoMetodoResolvido;
|
|
1568
1603
|
case construtos_1.AcessoMetodoOuPropriedade:
|
|
1569
|
-
|
|
1570
|
-
// Algumas coisas podem acontecer aqui.
|
|
1571
|
-
// Uma delas é a variável/constante ser uma classe padrão.
|
|
1572
|
-
// Isso ocorre quando a importação é feita de uma biblioteca Node.js.
|
|
1573
|
-
// Nesse caso, o tipo de `entidadeChamadaAcessoMetodoOuPropriedade.objeto` começa com uma letra maiúscula.
|
|
1574
|
-
if (entidadeChamadaAcessoMetodoOuPropriedade.objeto.tipo &&
|
|
1575
|
-
entidadeChamadaAcessoMetodoOuPropriedade.objeto.tipo.match(/^[A-Z]/)) {
|
|
1576
|
-
const tipoCorrespondente = this.tiposDefinidosPorBibliotecas[entidadeChamadaAcessoMetodoOuPropriedade.objeto.tipo];
|
|
1577
|
-
if (!tipoCorrespondente) {
|
|
1578
|
-
throw new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(entidadeChamadaAcessoMetodoOuPropriedade.simbolo, `Tipo '${entidadeChamadaAcessoMetodoOuPropriedade.objeto.tipo}' não foi encontrado entre os tipos definidos por bibliotecas.`);
|
|
1579
|
-
}
|
|
1580
|
-
if (!(entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema in
|
|
1581
|
-
tipoCorrespondente.metodos) &&
|
|
1582
|
-
!(entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema in
|
|
1583
|
-
tipoCorrespondente.propriedades)) {
|
|
1584
|
-
throw new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(entidadeChamadaAcessoMetodoOuPropriedade.simbolo, `Membro '${entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema}' não existe no tipo '${entidadeChamadaAcessoMetodoOuPropriedade.objeto.tipo}'.`);
|
|
1585
|
-
}
|
|
1586
|
-
if (entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema in
|
|
1587
|
-
tipoCorrespondente.metodos) {
|
|
1588
|
-
const metodoCorrespondente = tipoCorrespondente.metodos[entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema];
|
|
1589
|
-
return metodoCorrespondente.tipoRetorno || 'qualquer';
|
|
1590
|
-
}
|
|
1591
|
-
const propriedadeCorrespondente = tipoCorrespondente.propriedades[entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema];
|
|
1592
|
-
return propriedadeCorrespondente.tipo;
|
|
1593
|
-
}
|
|
1594
|
-
// Este caso ocorre quando a variável/constante é do tipo 'qualquer',
|
|
1595
|
-
// e a chamada normalmente é feita para uma primitiva.
|
|
1596
|
-
// A inferência, portanto, ocorre pelo uso da primitiva.
|
|
1597
|
-
for (const primitiva in this.primitivasConhecidas) {
|
|
1598
|
-
if (this.primitivasConhecidas[primitiva].hasOwnProperty(entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema)) {
|
|
1599
|
-
return this.primitivasConhecidas[primitiva][entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema].tipo;
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
throw new erro_avaliador_sintatico_1.ErroAvaliadorSintatico(entidadeChamadaAcessoMetodoOuPropriedade.simbolo, `Primitiva '${entidadeChamadaAcessoMetodoOuPropriedade.simbolo.lexema}' não existe.`);
|
|
1604
|
+
return this.logicaComumInferenciaTiposAcessoMetodoOuPropriedade(entidadeChamadaChamada);
|
|
1603
1605
|
case construtos_1.AcessoPropriedade:
|
|
1604
1606
|
const entidadeChamadaAcessoPropriedade = entidadeChamadaChamada;
|
|
1605
1607
|
return entidadeChamadaAcessoPropriedade.tipoRetornoPropriedade;
|
|
@@ -1900,8 +1902,68 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
1900
1902
|
}
|
|
1901
1903
|
return new construtos_1.FuncaoConstruto(this.hashArquivo, Number(parenteseEsquerdo.linha), parametros, corpo, tipoRetorno, definicaoExplicitaDeTipo);
|
|
1902
1904
|
}
|
|
1905
|
+
/**
|
|
1906
|
+
* Analisa uma declaração de interface.
|
|
1907
|
+
* Interfaces definem contratos de métodos e propriedades que as classes devem implementar.
|
|
1908
|
+
* A verificação é feita em tempo de análise (parse-time).
|
|
1909
|
+
*/
|
|
1910
|
+
async declaracaoDeInterface() {
|
|
1911
|
+
const simbolo = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado nome da interface.');
|
|
1912
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo da interface.");
|
|
1913
|
+
const metodos = [];
|
|
1914
|
+
const propriedades = [];
|
|
1915
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) && !this.estaNoFinal()) {
|
|
1916
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
1917
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA))
|
|
1918
|
+
break;
|
|
1919
|
+
const nomeMembro = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado nome de método ou propriedade na interface.');
|
|
1920
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
|
|
1921
|
+
// Assinatura de método: nome(params): tipoRetorno
|
|
1922
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
|
|
1923
|
+
let params = [];
|
|
1924
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
1925
|
+
params = await this.logicaComumParametros();
|
|
1926
|
+
}
|
|
1927
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros.");
|
|
1928
|
+
let tipoRetorno = 'qualquer';
|
|
1929
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
|
|
1930
|
+
tipoRetorno = this.verificarDefinicaoTipoAtual();
|
|
1931
|
+
this.avancarEDevolverAnterior();
|
|
1932
|
+
}
|
|
1933
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
1934
|
+
metodos.push(new declaracoes_1.AssinaturaMetodo(nomeMembro, params, tipoRetorno));
|
|
1935
|
+
}
|
|
1936
|
+
else {
|
|
1937
|
+
// Assinatura de propriedade: nome: tipo
|
|
1938
|
+
this.consumir(delegua_2.default.DOIS_PONTOS, "Esperado ':' após nome de propriedade na interface.");
|
|
1939
|
+
const tipo = this.verificarDefinicaoTipoAtual();
|
|
1940
|
+
this.avancarEDevolverAnterior();
|
|
1941
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
1942
|
+
propriedades.push(new declaracoes_1.PropriedadeClasse(nomeMembro, tipo));
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após o corpo da interface.");
|
|
1946
|
+
const declaracao = new declaracoes_1.InterfaceDeclaracao(simbolo, metodos, propriedades);
|
|
1947
|
+
this.interfacesDeclaradas[simbolo.lexema] = declaracao;
|
|
1948
|
+
return declaracao;
|
|
1949
|
+
}
|
|
1903
1950
|
async declaracaoDeClasse() {
|
|
1951
|
+
var _a;
|
|
1952
|
+
// Modificadores opcionais no nível da classe: `abstrata` e/ou `estática`.
|
|
1953
|
+
// Sintaxe: `classe abstrata NomeDaClasse` ou `classe estática NomeDaClasse`.
|
|
1954
|
+
let ehAbstrata = false;
|
|
1955
|
+
let ehEstatica = false;
|
|
1956
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.ABSTRATO))
|
|
1957
|
+
ehAbstrata = true;
|
|
1958
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.ESTATICO))
|
|
1959
|
+
ehEstatica = true;
|
|
1960
|
+
// Também permite a ordem invertida: `classe estática abstrata`
|
|
1961
|
+
if (!ehAbstrata && this.verificarSeSimboloAtualEIgualA(delegua_2.default.ABSTRATO))
|
|
1962
|
+
ehAbstrata = true;
|
|
1904
1963
|
const simbolo = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado nome da classe.');
|
|
1964
|
+
// Pré-registro para permitir auto-referência no corpo da própria classe,
|
|
1965
|
+
// como em `MinhaClasse.propriedadeEstatica` dentro de métodos.
|
|
1966
|
+
this.tiposDefinidosEmCodigo[simbolo.lexema] = (_a = this.tiposDefinidosEmCodigo[simbolo.lexema]) !== null && _a !== void 0 ? _a : {};
|
|
1905
1967
|
const pilhaDecoradoresClasse = Array.from(this.pilhaDecoradores);
|
|
1906
1968
|
let superClasse = null;
|
|
1907
1969
|
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.HERDA)) {
|
|
@@ -1909,39 +1971,311 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
1909
1971
|
this.superclasseAtual = simboloSuperclasse.lexema;
|
|
1910
1972
|
superClasse = new construtos_1.Variavel(this.hashArquivo, this.simbolos[this.atual - 1], simboloSuperclasse.lexema);
|
|
1911
1973
|
}
|
|
1974
|
+
// Verificar `implementa InterfaceA, InterfaceB`
|
|
1975
|
+
const implementaInterfaces = [];
|
|
1976
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.IMPLEMENTA)) {
|
|
1977
|
+
do {
|
|
1978
|
+
implementaInterfaces.push(this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado nome de interface após "implementa".'));
|
|
1979
|
+
} while (this.verificarSeSimboloAtualEIgualA(delegua_2.default.VIRGULA));
|
|
1980
|
+
}
|
|
1912
1981
|
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do escopo da classe.");
|
|
1913
1982
|
this.pilhaDecoradores = [];
|
|
1914
1983
|
const metodos = [];
|
|
1915
1984
|
const propriedades = [];
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1985
|
+
/**
|
|
1986
|
+
* Analisa membros do corpo da classe com um contexto de acesso e estático padrão.
|
|
1987
|
+
* Suporta blocos de contexto aninhados: `estático { }`, `privado { }`, `protegido { }`, `publico { }`.
|
|
1988
|
+
*/
|
|
1989
|
+
const compreenderMembros = async (acessoPadrao, ehEstaticoPadrao) => {
|
|
1990
|
+
var _a, _b;
|
|
1991
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) && !this.estaNoFinal()) {
|
|
1992
|
+
// Pular comentários normais dentro do corpo da classe.
|
|
1993
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.COMENTARIO ||
|
|
1994
|
+
this.simbolos[this.atual].tipo === delegua_2.default.LINHA_COMENTARIO) {
|
|
1995
|
+
this.avancarEDevolverAnterior();
|
|
1996
|
+
continue;
|
|
1997
|
+
}
|
|
1998
|
+
// Documentário (/** ... */)
|
|
1999
|
+
let docAtual = null;
|
|
2000
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.DOCUMENTARIO) {
|
|
2001
|
+
const simboloDoc = this.avancarEDevolverAnterior();
|
|
2002
|
+
docAtual = new construtos_1.ComentarioComoConstruto(simboloDoc);
|
|
2003
|
+
}
|
|
2004
|
+
// Decorador
|
|
2005
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.ARROBA) {
|
|
2006
|
+
await this.resolverDecoradores();
|
|
2007
|
+
continue;
|
|
2008
|
+
}
|
|
2009
|
+
// Detecção de bloco de contexto: modificador seguido de '{'
|
|
2010
|
+
const tipoAtual = this.simbolos[this.atual].tipo;
|
|
2011
|
+
const tipoProximo = (_a = this.simbolos[this.atual + 1]) === null || _a === void 0 ? void 0 : _a.tipo;
|
|
2012
|
+
const ehBlocoAcesso = [delegua_2.default.PRIVADO, delegua_2.default.PROTEGIDO, delegua_2.default.PUBLICO].includes(tipoAtual)
|
|
2013
|
+
&& tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
2014
|
+
const ehBlocoEstatico = tipoAtual === delegua_2.default.ESTATICO
|
|
2015
|
+
&& tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
2016
|
+
if (ehBlocoAcesso) {
|
|
2017
|
+
const novoAcesso = tipoAtual === delegua_2.default.PRIVADO ? 'privado' :
|
|
2018
|
+
tipoAtual === delegua_2.default.PROTEGIDO ? 'protegido' : 'publico';
|
|
2019
|
+
this.avancarEDevolverAnterior(); // consume modificador de acesso
|
|
2020
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após modificador de acesso de bloco.");
|
|
2021
|
+
await compreenderMembros(novoAcesso, ehEstaticoPadrao);
|
|
2022
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco de modificador de acesso.");
|
|
2023
|
+
continue;
|
|
2024
|
+
}
|
|
2025
|
+
if (ehBlocoEstatico) {
|
|
2026
|
+
this.avancarEDevolverAnterior(); // consume 'estático'
|
|
2027
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'estático'.");
|
|
2028
|
+
await compreenderMembros(acessoPadrao, true);
|
|
2029
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco estático.");
|
|
2030
|
+
continue;
|
|
2031
|
+
}
|
|
2032
|
+
// Modificador de acesso por membro (somente quando NÃO seguido de '{')
|
|
2033
|
+
let modificadorAcesso = acessoPadrao;
|
|
2034
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.PRIVADO) {
|
|
2035
|
+
this.avancarEDevolverAnterior();
|
|
2036
|
+
modificadorAcesso = 'privado';
|
|
2037
|
+
}
|
|
2038
|
+
else if (this.simbolos[this.atual].tipo === delegua_2.default.PROTEGIDO) {
|
|
2039
|
+
this.avancarEDevolverAnterior();
|
|
2040
|
+
modificadorAcesso = 'protegido';
|
|
2041
|
+
}
|
|
2042
|
+
else if (this.simbolos[this.atual].tipo === delegua_2.default.PUBLICO) {
|
|
2043
|
+
this.avancarEDevolverAnterior();
|
|
2044
|
+
modificadorAcesso = 'publico';
|
|
2045
|
+
}
|
|
2046
|
+
// Modificador estático por membro (somente quando NÃO seguido de '{')
|
|
2047
|
+
let ehEstatico = ehEstaticoPadrao;
|
|
2048
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.ESTATICO &&
|
|
2049
|
+
((_b = this.simbolos[this.atual + 1]) === null || _b === void 0 ? void 0 : _b.tipo) !== delegua_2.default.CHAVE_ESQUERDA) {
|
|
2050
|
+
this.avancarEDevolverAnterior();
|
|
2051
|
+
ehEstatico = true;
|
|
2052
|
+
}
|
|
2053
|
+
// Palavras-chave de acessor (obter/definir)
|
|
2054
|
+
let eObtenedor = false;
|
|
2055
|
+
let eDefinidor = false;
|
|
2056
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.IDENTIFICADOR &&
|
|
2057
|
+
['obter', 'definir', 'obtenedor', 'definidor', 'get', 'set'].includes(String(this.simbolos[this.atual].lexema || '').toLowerCase())) {
|
|
2058
|
+
const palavraAcessor = String(this.simbolos[this.atual].lexema || '').toLowerCase();
|
|
2059
|
+
this.avancarEDevolverAnterior();
|
|
2060
|
+
eObtenedor = palavraAcessor === 'obter' || palavraAcessor === 'obtenedor' || palavraAcessor === 'get';
|
|
2061
|
+
eDefinidor = palavraAcessor === 'definir' || palavraAcessor === 'definidor' || palavraAcessor === 'set';
|
|
2062
|
+
}
|
|
2063
|
+
// Método operador sobrecarregado: `operador+ (outro) { ... }`
|
|
2064
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.OPERADOR) {
|
|
2065
|
+
const simboloOperadorKeyword = this.avancarEDevolverAnterior();
|
|
2066
|
+
const simboloDoOperador = this.avancarEDevolverAnterior();
|
|
2067
|
+
const nomeMetodoOp = 'operador' + simboloDoOperador.lexema;
|
|
2068
|
+
const simboloNomeMetodo = {
|
|
2069
|
+
tipo: delegua_2.default.IDENTIFICADOR,
|
|
2070
|
+
lexema: nomeMetodoOp,
|
|
2071
|
+
literal: null,
|
|
2072
|
+
linha: simboloOperadorKeyword.linha,
|
|
2073
|
+
hashArquivo: this.hashArquivo,
|
|
2074
|
+
};
|
|
2075
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após operador sobrecarregado.");
|
|
2076
|
+
let paramsOp = [];
|
|
2077
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2078
|
+
paramsOp = await this.logicaComumParametros();
|
|
2079
|
+
}
|
|
2080
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do operador.");
|
|
2081
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do operador.");
|
|
2082
|
+
const corpoOp = await this.blocoEscopo();
|
|
2083
|
+
const corpoFuncaoOp = new construtos_1.FuncaoConstruto(this.hashArquivo, simboloNomeMetodo.linha, paramsOp, corpoOp);
|
|
2084
|
+
const metodoOp = new declaracoes_1.FuncaoDeclaracao(simboloNomeMetodo, corpoFuncaoOp);
|
|
2085
|
+
metodoOp.estatico = ehEstatico;
|
|
2086
|
+
metodoOp.acesso = modificadorAcesso;
|
|
2087
|
+
metodoOp.documentacao = docAtual;
|
|
2088
|
+
metodos.push(metodoOp);
|
|
2089
|
+
this.pilhaDecoradores = [];
|
|
2090
|
+
continue;
|
|
2091
|
+
}
|
|
2092
|
+
// Método ou propriedade, determinado pelo token seguinte ao nome
|
|
2093
|
+
const proximoSimbolo = this.simbolos[this.atual + 1];
|
|
2094
|
+
switch (proximoSimbolo === null || proximoSimbolo === void 0 ? void 0 : proximoSimbolo.tipo) {
|
|
2095
|
+
case delegua_2.default.PARENTESE_ESQUERDO: {
|
|
2096
|
+
// Analisa: nome ( params ) [abstrato] [: tipoRetorno] { corpo }
|
|
2097
|
+
const nomeMetodo = this.avancarEDevolverAnterior();
|
|
2098
|
+
// Pré-registrar para suportar chamadas recursivas (igual a funcao()).
|
|
2099
|
+
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, 'qualquer'));
|
|
2100
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
|
|
2101
|
+
let params = [];
|
|
2102
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2103
|
+
params = await this.logicaComumParametros();
|
|
2104
|
+
}
|
|
2105
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do método.");
|
|
2106
|
+
// O modificador `abstrato` vem APÓS o fechamento dos parâmetros.
|
|
2107
|
+
// Sintaxe: `area() abstrato: numero`
|
|
2108
|
+
let ehAbstrato = false;
|
|
2109
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.ABSTRATO)) {
|
|
2110
|
+
ehAbstrato = true;
|
|
2111
|
+
}
|
|
2112
|
+
// Tipo de retorno opcional (igual a corpoDaFuncao())
|
|
2113
|
+
let tipoRetorno = 'qualquer';
|
|
2114
|
+
let definicaoExplicitaDeTipo = false;
|
|
2115
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
|
|
2116
|
+
tipoRetorno = this.verificarDefinicaoTipoAtual();
|
|
2117
|
+
this.avancarEDevolverAnterior();
|
|
2118
|
+
definicaoExplicitaDeTipo = true;
|
|
2119
|
+
}
|
|
2120
|
+
if (ehAbstrato) {
|
|
2121
|
+
// Método abstrato: sem corpo
|
|
2122
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2123
|
+
const corpoVazio = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, [], tipoRetorno);
|
|
2124
|
+
const metodoAbstrato = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoVazio, tipoRetorno);
|
|
2125
|
+
metodoAbstrato.estatico = ehEstatico;
|
|
2126
|
+
metodoAbstrato.abstrato = true;
|
|
2127
|
+
metodoAbstrato.acesso = modificadorAcesso;
|
|
2128
|
+
metodoAbstrato.documentacao = docAtual;
|
|
2129
|
+
metodos.push(metodoAbstrato);
|
|
2130
|
+
}
|
|
2131
|
+
else {
|
|
2132
|
+
// Método concreto: com corpo.
|
|
2133
|
+
// Inferência de tipo de retorno igual a corpoDaFuncao().
|
|
2134
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do método.");
|
|
2135
|
+
const corpo = await this.blocoEscopo();
|
|
2136
|
+
let expressoesRetorna = [];
|
|
2137
|
+
for (const declaracao of corpo) {
|
|
2138
|
+
expressoesRetorna = expressoesRetorna.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
2139
|
+
}
|
|
2140
|
+
const tiposRetornos = new Set(expressoesRetorna.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
|
|
2141
|
+
const retornaChamadoExplicitamente = tiposRetornos.size > 0;
|
|
2142
|
+
tiposRetornos.delete('qualquer');
|
|
2143
|
+
if (tipoRetorno === 'qualquer') {
|
|
2144
|
+
if (tiposRetornos.size > 0) {
|
|
2145
|
+
tipoRetorno = tiposRetornos.values().next().value;
|
|
2146
|
+
}
|
|
2147
|
+
else if (!retornaChamadoExplicitamente && !definicaoExplicitaDeTipo) {
|
|
2148
|
+
tipoRetorno = 'vazio';
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
const corpoFuncao = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, corpo, tipoRetorno);
|
|
2152
|
+
const tipoDaFuncao = `função<${tipoRetorno}>`;
|
|
2153
|
+
const metodo = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoFuncao, tipoDaFuncao);
|
|
2154
|
+
metodo.estatico = ehEstatico;
|
|
2155
|
+
metodo.eObtenedor = eObtenedor;
|
|
2156
|
+
metodo.eDefinidor = eDefinidor;
|
|
2157
|
+
metodo.acesso = modificadorAcesso;
|
|
2158
|
+
metodo.decoradores = Array.from(this.pilhaDecoradores);
|
|
2159
|
+
metodo.documentacao = docAtual;
|
|
2160
|
+
metodos.push(metodo);
|
|
2161
|
+
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, tipoDaFuncao));
|
|
2162
|
+
this.pilhaEscopos.registrarReferenciaFuncao(nomeMetodo.lexema, metodo);
|
|
2163
|
+
}
|
|
2164
|
+
this.pilhaDecoradores = [];
|
|
2165
|
+
break;
|
|
2166
|
+
}
|
|
2167
|
+
case delegua_2.default.DOIS_PONTOS: {
|
|
2168
|
+
const nomePropriedade = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado identificador para nome de propriedade.');
|
|
2169
|
+
this.consumir(delegua_2.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade.');
|
|
2170
|
+
const tipoPropriedade = this.avancarEDevolverAnterior();
|
|
2171
|
+
const prop = new declaracoes_1.PropriedadeClasse(nomePropriedade, tipoPropriedade.lexema, Array.from(this.pilhaDecoradores), modificadorAcesso, ehEstatico);
|
|
2172
|
+
prop.documentacao = docAtual;
|
|
2173
|
+
// Auto-propriedade: `nome: tipo { obter; definir; }`
|
|
2174
|
+
// Ou corpo personalizado: `nome: tipo { obter() { ... } definir(valor) { ... } }`
|
|
2175
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
2176
|
+
this.avancarEDevolverAnterior(); // consume '{'
|
|
2177
|
+
let temCorpoPersonalizado = false;
|
|
2178
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
|
|
2179
|
+
!this.estaNoFinal()) {
|
|
2180
|
+
const lexema = String(this.simbolos[this.atual].lexema || '').toLowerCase();
|
|
2181
|
+
if (lexema === 'obter' || lexema === 'definir') {
|
|
2182
|
+
const ehObter = lexema === 'obter';
|
|
2183
|
+
this.avancarEDevolverAnterior(); // consume 'obter' / 'definir'
|
|
2184
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
|
|
2185
|
+
// Corpo personalizado: obter() { ... } / definir(valor) { ... }
|
|
2186
|
+
temCorpoPersonalizado = true;
|
|
2187
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após acessor.");
|
|
2188
|
+
let paramsAcessor = [];
|
|
2189
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2190
|
+
paramsAcessor = await this.logicaComumParametros();
|
|
2191
|
+
}
|
|
2192
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do acessor.");
|
|
2193
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do acessor.");
|
|
2194
|
+
const corpoAcessor = await this.blocoEscopo();
|
|
2195
|
+
// Inferência de tipo de retorno
|
|
2196
|
+
let tipoAcessor = 'qualquer';
|
|
2197
|
+
let expressoesRetornaAcessor = [];
|
|
2198
|
+
for (const declaracao of corpoAcessor) {
|
|
2199
|
+
expressoesRetornaAcessor = expressoesRetornaAcessor.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
2200
|
+
}
|
|
2201
|
+
const tiposRetornosAcessor = new Set(expressoesRetornaAcessor.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
|
|
2202
|
+
const retornaExplicitamenteAcessor = tiposRetornosAcessor.size > 0;
|
|
2203
|
+
tiposRetornosAcessor.delete('qualquer');
|
|
2204
|
+
if (tiposRetornosAcessor.size > 0) {
|
|
2205
|
+
tipoAcessor = tiposRetornosAcessor.values().next().value;
|
|
2206
|
+
}
|
|
2207
|
+
else if (!retornaExplicitamenteAcessor) {
|
|
2208
|
+
tipoAcessor = 'vazio';
|
|
2209
|
+
}
|
|
2210
|
+
const corpoFuncaoAcessor = new construtos_1.FuncaoConstruto(this.hashArquivo, nomePropriedade.linha, paramsAcessor, corpoAcessor, tipoAcessor);
|
|
2211
|
+
const tipoDaFuncaoAcessor = `função<${tipoAcessor}>`;
|
|
2212
|
+
const metodoAcessor = new declaracoes_1.FuncaoDeclaracao(nomePropriedade, corpoFuncaoAcessor, tipoDaFuncaoAcessor);
|
|
2213
|
+
metodoAcessor.estatico = ehEstatico;
|
|
2214
|
+
metodoAcessor.acesso = modificadorAcesso;
|
|
2215
|
+
metodoAcessor.eObtenedor = ehObter;
|
|
2216
|
+
metodoAcessor.eDefinidor = !ehObter;
|
|
2217
|
+
metodos.push(metodoAcessor);
|
|
2218
|
+
}
|
|
2219
|
+
else {
|
|
2220
|
+
// Forma trivial: obter; / definir;
|
|
2221
|
+
if (ehObter) {
|
|
2222
|
+
prop.autoObter = true;
|
|
2223
|
+
}
|
|
2224
|
+
else {
|
|
2225
|
+
prop.autoDefinir = true;
|
|
2226
|
+
}
|
|
2227
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
else {
|
|
2231
|
+
break;
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após acessores da propriedade.");
|
|
2235
|
+
// Corpo personalizado: obtenedor/definidor são métodos — não há campos base a declarar.
|
|
2236
|
+
// Para auto-propriedades, o campo base iniciado por '_' é criado em tempo de execução com base
|
|
2237
|
+
// nos indicadores autoObter/autoDefinir. O avaliador sintático usa o nome original ('nome').
|
|
2238
|
+
if (!temCorpoPersonalizado) {
|
|
2239
|
+
propriedades.push(prop);
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
else {
|
|
2243
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2244
|
+
propriedades.push(prop);
|
|
2245
|
+
}
|
|
2246
|
+
this.pilhaDecoradores = [];
|
|
2247
|
+
break;
|
|
2248
|
+
}
|
|
2249
|
+
default:
|
|
2250
|
+
throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
};
|
|
2254
|
+
await compreenderMembros('publico', false);
|
|
2255
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após o escopo da classe.");
|
|
2256
|
+
// Verificação em tempo de análise: classe deve implementar todos os contratos das interfaces.
|
|
2257
|
+
for (const nomeInterface of implementaInterfaces) {
|
|
2258
|
+
const interfaceDecl = this.interfacesDeclaradas[nomeInterface.lexema];
|
|
2259
|
+
if (!interfaceDecl) {
|
|
2260
|
+
this.erros.push(this.erro(nomeInterface, `Interface '${nomeInterface.lexema}' não foi declarada antes da classe '${simbolo.lexema}'.`));
|
|
1922
2261
|
continue;
|
|
1923
2262
|
}
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
this.
|
|
1936
|
-
|
|
1937
|
-
this.pilhaDecoradores = [];
|
|
1938
|
-
break;
|
|
1939
|
-
default:
|
|
1940
|
-
throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
|
|
2263
|
+
for (const assinatura of interfaceDecl.metodos) {
|
|
2264
|
+
const nomeMetodo = assinatura.nome.lexema;
|
|
2265
|
+
const implementado = metodos.some((m) => m.simbolo.lexema === nomeMetodo);
|
|
2266
|
+
if (!implementado) {
|
|
2267
|
+
this.erros.push(this.erro(simbolo, `Classe '${simbolo.lexema}' não implementa o método '${nomeMetodo}' exigido pela interface '${nomeInterface.lexema}'.`));
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
for (const prop of interfaceDecl.propriedades) {
|
|
2271
|
+
const nomeProp = prop.nome.lexema;
|
|
2272
|
+
const implementada = propriedades.some((p) => p.nome.lexema === nomeProp);
|
|
2273
|
+
if (!implementada) {
|
|
2274
|
+
this.erros.push(this.erro(simbolo, `Classe '${simbolo.lexema}' não declara a propriedade '${nomeProp}' exigida pela interface '${nomeInterface.lexema}'.`));
|
|
2275
|
+
}
|
|
1941
2276
|
}
|
|
1942
2277
|
}
|
|
1943
|
-
|
|
1944
|
-
const definicaoClasse = new declaracoes_1.Classe(simbolo, superClasse, metodos, propriedades, pilhaDecoradoresClasse);
|
|
2278
|
+
const definicaoClasse = new declaracoes_1.Classe(simbolo, superClasse, metodos, propriedades, pilhaDecoradoresClasse, ehAbstrata, ehEstatica, implementaInterfaces);
|
|
1945
2279
|
this.tiposDefinidosEmCodigo[definicaoClasse.simbolo.lexema] = definicaoClasse;
|
|
1946
2280
|
this.superclasseAtual = undefined;
|
|
1947
2281
|
return definicaoClasse;
|
|
@@ -1963,15 +2297,26 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
1963
2297
|
while (this.verificarTipoSimboloAtual(delegua_2.default.ARROBA)) {
|
|
1964
2298
|
await this.resolverDecoradores();
|
|
1965
2299
|
}
|
|
2300
|
+
// Documentário (/** ... */) antes de uma declaração de função.
|
|
2301
|
+
let docTopLevel = null;
|
|
2302
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.DOCUMENTARIO)) {
|
|
2303
|
+
const simboloDoc = this.avancarEDevolverAnterior();
|
|
2304
|
+
docTopLevel = new construtos_1.ComentarioComoConstruto(simboloDoc);
|
|
2305
|
+
}
|
|
1966
2306
|
if ((this.verificarTipoSimboloAtual(delegua_2.default.FUNCAO) ||
|
|
1967
2307
|
this.verificarTipoSimboloAtual(delegua_2.default.FUNÇÃO)) &&
|
|
1968
2308
|
this.verificarTipoProximoSimbolo(delegua_2.default.IDENTIFICADOR)) {
|
|
1969
2309
|
this.avancarEDevolverAnterior();
|
|
1970
|
-
|
|
2310
|
+
const declaracaoFuncao = await this.funcao('funcao');
|
|
2311
|
+
declaracaoFuncao.documentacao = docTopLevel;
|
|
2312
|
+
return declaracaoFuncao;
|
|
1971
2313
|
}
|
|
1972
2314
|
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.CLASSE)) {
|
|
1973
2315
|
return await this.declaracaoDeClasse();
|
|
1974
2316
|
}
|
|
2317
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.INTERFACE)) {
|
|
2318
|
+
return await this.declaracaoDeInterface();
|
|
2319
|
+
}
|
|
1975
2320
|
return await this.resolverDeclaracao();
|
|
1976
2321
|
}
|
|
1977
2322
|
catch (erro) {
|
|
@@ -1986,10 +2331,15 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
1986
2331
|
* @returns Sempre retorna `void`.
|
|
1987
2332
|
*/
|
|
1988
2333
|
sincronizar() {
|
|
1989
|
-
this.avancarEDevolverAnterior();
|
|
2334
|
+
this.avancarEDevolverAnterior(); // avança além do token com erro
|
|
1990
2335
|
while (!this.estaNoFinal()) {
|
|
1991
|
-
|
|
1992
|
-
|
|
2336
|
+
// Um ponto-e-vírgula já consumido indica fronteira limpa entre declarações.
|
|
2337
|
+
if (this.simbolos[this.atual - 1].tipo === delegua_2.default.PONTO_E_VIRGULA)
|
|
2338
|
+
return;
|
|
2339
|
+
// Uma palavra-chave de início de declaração ou fecha-chave à frente:
|
|
2340
|
+
// retorna SEM consumir o token, para que o chamador o analise normalmente.
|
|
2341
|
+
switch (this.simbolos[this.atual].tipo) {
|
|
2342
|
+
case delegua_2.default.CHAVE_DIREITA:
|
|
1993
2343
|
case delegua_2.default.CLASSE:
|
|
1994
2344
|
case delegua_2.default.FUNCAO:
|
|
1995
2345
|
case delegua_2.default.FUNÇÃO:
|
|
@@ -2020,6 +2370,20 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
2020
2370
|
return await this.declaracaoBloco();
|
|
2021
2371
|
case delegua_2.default.COMENTARIO:
|
|
2022
2372
|
return this.declaracaoComentarioUmaLinha();
|
|
2373
|
+
case delegua_2.default.DOCUMENTARIO: {
|
|
2374
|
+
const simboloDoc = this.avancarEDevolverAnterior();
|
|
2375
|
+
// Se o próximo token for uma declaração de função com identificador,
|
|
2376
|
+
// anexa o documentário como documentação da função.
|
|
2377
|
+
if ((this.verificarTipoSimboloAtual(delegua_2.default.FUNCAO) ||
|
|
2378
|
+
this.verificarTipoSimboloAtual(delegua_2.default.FUNÇÃO)) &&
|
|
2379
|
+
this.verificarTipoProximoSimbolo(delegua_2.default.IDENTIFICADOR)) {
|
|
2380
|
+
this.avancarEDevolverAnterior();
|
|
2381
|
+
const declaracaoFuncao = await this.funcao('funcao');
|
|
2382
|
+
declaracaoFuncao.documentacao = new construtos_1.ComentarioComoConstruto(simboloDoc);
|
|
2383
|
+
return declaracaoFuncao;
|
|
2384
|
+
}
|
|
2385
|
+
return new declaracoes_1.Comentario(simboloDoc.hashArquivo, simboloDoc.linha, simboloDoc.literal, false);
|
|
2386
|
+
}
|
|
2023
2387
|
case delegua_2.default.CONSTANTE:
|
|
2024
2388
|
this.avancarEDevolverAnterior();
|
|
2025
2389
|
return await this.declaracaoDeConstantes();
|
|
@@ -2198,6 +2562,8 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
2198
2562
|
this.pilhaEscopos.definirInformacoesVariavel('tupla', new informacao_elemento_sintatico_1.InformacaoElementoSintatico('tupla', 'tupla', true, [
|
|
2199
2563
|
new informacao_elemento_sintatico_1.InformacaoElementoSintatico('vetor', 'qualquer[]'),
|
|
2200
2564
|
]));
|
|
2565
|
+
// Classe base global `Objeto`, registrada pelo interpretador em tempo de execução.
|
|
2566
|
+
this.pilhaEscopos.definirInformacoesVariavel('Objeto', new informacao_elemento_sintatico_1.InformacaoElementoSintatico('Objeto', 'qualquer'));
|
|
2201
2567
|
// TODO: Escrever algum tipo de validação aqui.
|
|
2202
2568
|
for (const tipos of Object.values(this.tiposDeFerramentasExternas)) {
|
|
2203
2569
|
for (const [nomeTipo, tipo] of Object.entries(tipos)) {
|
|
@@ -2214,6 +2580,7 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
2214
2580
|
this.simbolos = (retornoLexador === null || retornoLexador === void 0 ? void 0 : retornoLexador.simbolos) || [];
|
|
2215
2581
|
this.pilhaDecoradores = [];
|
|
2216
2582
|
this.tiposDefinidosEmCodigo = {};
|
|
2583
|
+
this.interfacesDeclaradas = {};
|
|
2217
2584
|
this.montaoTipos = new montao_tipos_1.MontaoTipos();
|
|
2218
2585
|
this.inicializarPilhaEscopos();
|
|
2219
2586
|
let declaracoes = [];
|