@designliquido/delegua 1.24.0 → 1.24.1
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 +6 -2
- package/avaliador-sintatico/avaliador-sintatico.d.ts.map +1 -1
- package/avaliador-sintatico/avaliador-sintatico.js +284 -307
- package/avaliador-sintatico/avaliador-sintatico.js.map +1 -1
- package/bin/package.json +1 -1
- package/package.json +1 -1
- package/umd/delegua.js +284 -307
package/bin/package.json
CHANGED
package/package.json
CHANGED
package/umd/delegua.js
CHANGED
|
@@ -4634,6 +4634,289 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
4634
4634
|
this.interfacesDeclaradas[simbolo.lexema] = declaracao;
|
|
4635
4635
|
return declaracao;
|
|
4636
4636
|
}
|
|
4637
|
+
async analisarMembroOperador(ehEstatico, modificadorAcesso, metodos, docAtual) {
|
|
4638
|
+
const simboloOperadorKeyword = this.avancarEDevolverAnterior();
|
|
4639
|
+
const simboloDoOperador = this.avancarEDevolverAnterior();
|
|
4640
|
+
const nomeMetodoOp = 'operador' + simboloDoOperador.lexema;
|
|
4641
|
+
const simboloNomeMetodo = {
|
|
4642
|
+
tipo: delegua_2.default.IDENTIFICADOR,
|
|
4643
|
+
lexema: nomeMetodoOp,
|
|
4644
|
+
literal: null,
|
|
4645
|
+
linha: simboloOperadorKeyword.linha,
|
|
4646
|
+
hashArquivo: this.hashArquivo,
|
|
4647
|
+
};
|
|
4648
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após operador sobrecarregado.");
|
|
4649
|
+
let paramsOp = [];
|
|
4650
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4651
|
+
paramsOp = await this.logicaComumParametros();
|
|
4652
|
+
}
|
|
4653
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do operador.");
|
|
4654
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do operador.");
|
|
4655
|
+
const indiceAberturaCorpoOp = this.atual - 1;
|
|
4656
|
+
const quantidadeErrosAntesCorpoOp = this.erros.length;
|
|
4657
|
+
let corpoOp = [];
|
|
4658
|
+
try {
|
|
4659
|
+
corpoOp = await this.blocoEscopo();
|
|
4660
|
+
}
|
|
4661
|
+
catch (erro) {
|
|
4662
|
+
this.erros.push(erro);
|
|
4663
|
+
}
|
|
4664
|
+
if (this.erros.length > quantidadeErrosAntesCorpoOp) {
|
|
4665
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoOp);
|
|
4666
|
+
corpoOp = [];
|
|
4667
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4668
|
+
}
|
|
4669
|
+
const corpoFuncaoOp = new construtos_1.FuncaoConstruto(this.hashArquivo, simboloNomeMetodo.linha, paramsOp, corpoOp);
|
|
4670
|
+
const metodoOp = new declaracoes_1.FuncaoDeclaracao(simboloNomeMetodo, corpoFuncaoOp);
|
|
4671
|
+
metodoOp.estatico = ehEstatico;
|
|
4672
|
+
metodoOp.acesso = modificadorAcesso;
|
|
4673
|
+
metodoOp.documentacao = docAtual;
|
|
4674
|
+
metodos.push(metodoOp);
|
|
4675
|
+
this.pilhaDecoradores = [];
|
|
4676
|
+
}
|
|
4677
|
+
async analisarMembroMetodo(ehEstatico, modificadorAcesso, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, docAtual) {
|
|
4678
|
+
const nomeMetodo = this.avancarEDevolverAnterior();
|
|
4679
|
+
// Pré-registrar para suportar chamadas recursivas (igual a funcao()).
|
|
4680
|
+
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, 'qualquer'));
|
|
4681
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
|
|
4682
|
+
let params = [];
|
|
4683
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4684
|
+
params = await this.logicaComumParametros();
|
|
4685
|
+
}
|
|
4686
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do método.");
|
|
4687
|
+
let tipoRetorno = 'qualquer';
|
|
4688
|
+
let definicaoExplicitaDeTipo = false;
|
|
4689
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
|
|
4690
|
+
tipoRetorno = this.verificarDefinicaoTipoAtual();
|
|
4691
|
+
this.avancarEDevolverAnterior();
|
|
4692
|
+
definicaoExplicitaDeTipo = true;
|
|
4693
|
+
}
|
|
4694
|
+
if (ehEstrangeira && this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
4695
|
+
throw this.erro(this.simbolos[this.atual], 'Métodos de classe estrangeira não podem ter corpo.');
|
|
4696
|
+
}
|
|
4697
|
+
// Método é abstrato quando: (a) está dentro de um bloco `abstrato {}`,
|
|
4698
|
+
// ou (b) a classe é abstrata/estrangeira e o próximo token não é `{`.
|
|
4699
|
+
const ehAbstrato = ehAbstratoPadrao ||
|
|
4700
|
+
ehEstrangeira ||
|
|
4701
|
+
(ehAbstrata && !this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA));
|
|
4702
|
+
if (ehAbstrato) {
|
|
4703
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4704
|
+
const corpoVazio = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, [], tipoRetorno, definicaoExplicitaDeTipo);
|
|
4705
|
+
const metodoAbstrato = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoVazio, tipoRetorno);
|
|
4706
|
+
metodoAbstrato.estatico = ehEstatico;
|
|
4707
|
+
metodoAbstrato.abstrato = true;
|
|
4708
|
+
metodoAbstrato.acesso = modificadorAcesso;
|
|
4709
|
+
metodoAbstrato.decoradores = Array.from(this.pilhaDecoradores);
|
|
4710
|
+
metodoAbstrato.documentacao = docAtual;
|
|
4711
|
+
metodos.push(metodoAbstrato);
|
|
4712
|
+
}
|
|
4713
|
+
else {
|
|
4714
|
+
// Método concreto: com corpo. Inferência de tipo de retorno igual a corpoDaFuncao().
|
|
4715
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do método.");
|
|
4716
|
+
const indiceAberturaCorpo = this.atual - 1;
|
|
4717
|
+
const quantidadeErrosAntesCorpo = this.erros.length;
|
|
4718
|
+
let corpo = [];
|
|
4719
|
+
try {
|
|
4720
|
+
corpo = await this.blocoEscopo();
|
|
4721
|
+
}
|
|
4722
|
+
catch (erro) {
|
|
4723
|
+
this.erros.push(erro);
|
|
4724
|
+
}
|
|
4725
|
+
if (this.erros.length > quantidadeErrosAntesCorpo) {
|
|
4726
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpo);
|
|
4727
|
+
corpo = [];
|
|
4728
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4729
|
+
}
|
|
4730
|
+
let expressoesRetorna = [];
|
|
4731
|
+
for (const declaracao of corpo) {
|
|
4732
|
+
expressoesRetorna = expressoesRetorna.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
4733
|
+
}
|
|
4734
|
+
const tiposRetornos = new Set(expressoesRetorna.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
|
|
4735
|
+
const retornaChamadoExplicitamente = tiposRetornos.size > 0;
|
|
4736
|
+
tiposRetornos.delete('qualquer');
|
|
4737
|
+
if (tipoRetorno === 'qualquer') {
|
|
4738
|
+
if (tiposRetornos.size > 0) {
|
|
4739
|
+
tipoRetorno = tiposRetornos.values().next().value;
|
|
4740
|
+
}
|
|
4741
|
+
else if (!retornaChamadoExplicitamente && !definicaoExplicitaDeTipo) {
|
|
4742
|
+
tipoRetorno = 'vazio';
|
|
4743
|
+
}
|
|
4744
|
+
}
|
|
4745
|
+
const corpoFuncao = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, corpo, tipoRetorno);
|
|
4746
|
+
const tipoDaFuncao = `função<${tipoRetorno}>`;
|
|
4747
|
+
const metodo = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoFuncao, tipoDaFuncao);
|
|
4748
|
+
metodo.estatico = ehEstatico;
|
|
4749
|
+
metodo.acesso = modificadorAcesso;
|
|
4750
|
+
metodo.decoradores = Array.from(this.pilhaDecoradores);
|
|
4751
|
+
metodo.documentacao = docAtual;
|
|
4752
|
+
metodos.push(metodo);
|
|
4753
|
+
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, tipoDaFuncao));
|
|
4754
|
+
this.pilhaEscopos.registrarReferenciaFuncao(nomeMetodo.lexema, metodo);
|
|
4755
|
+
}
|
|
4756
|
+
this.pilhaDecoradores = [];
|
|
4757
|
+
}
|
|
4758
|
+
async analisarMembroPropriedade(ehEstatico, modificadorAcesso, metodos, propriedades, docAtual) {
|
|
4759
|
+
const nomePropriedade = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado identificador para nome de propriedade.');
|
|
4760
|
+
this.consumir(delegua_2.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade.');
|
|
4761
|
+
const tipoPropriedade = this.avancarEDevolverAnterior();
|
|
4762
|
+
let nomeTipoPropriedade = tipoPropriedade.lexema;
|
|
4763
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.COLCHETE_ESQUERDO)) {
|
|
4764
|
+
this.avancarEDevolverAnterior();
|
|
4765
|
+
this.consumir(delegua_2.default.COLCHETE_DIREITO, "Esperado ']' após '[' na definição do tipo de propriedade.");
|
|
4766
|
+
nomeTipoPropriedade = `${nomeTipoPropriedade}[]`;
|
|
4767
|
+
}
|
|
4768
|
+
const prop = new declaracoes_1.PropriedadeClasse(nomePropriedade, nomeTipoPropriedade, Array.from(this.pilhaDecoradores), modificadorAcesso, ehEstatico);
|
|
4769
|
+
prop.documentacao = docAtual;
|
|
4770
|
+
// Auto-propriedade: `nome: tipo { obter; definir; }`
|
|
4771
|
+
// Ou corpo personalizado: `nome: tipo { obter() { ... } definir(valor) { ... } }`
|
|
4772
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
4773
|
+
this.avancarEDevolverAnterior();
|
|
4774
|
+
let temCorpoPersonalizado = false;
|
|
4775
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) && !this.estaNoFinal()) {
|
|
4776
|
+
const lexema = String(this.simbolos[this.atual].lexema || '').toLowerCase();
|
|
4777
|
+
if (lexema === 'obter' || lexema === 'definir') {
|
|
4778
|
+
const ehObter = lexema === 'obter';
|
|
4779
|
+
this.avancarEDevolverAnterior();
|
|
4780
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
|
|
4781
|
+
// Corpo personalizado: obter() { ... } / definir(valor) { ... }
|
|
4782
|
+
temCorpoPersonalizado = true;
|
|
4783
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após acessor.");
|
|
4784
|
+
let paramsAcessor = [];
|
|
4785
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4786
|
+
paramsAcessor = await this.logicaComumParametros();
|
|
4787
|
+
}
|
|
4788
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do acessor.");
|
|
4789
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do acessor.");
|
|
4790
|
+
const indiceAberturaCorpoAcessor = this.atual - 1;
|
|
4791
|
+
const quantidadeErrosAntesCorpoAcessor = this.erros.length;
|
|
4792
|
+
let corpoAcessor = [];
|
|
4793
|
+
try {
|
|
4794
|
+
corpoAcessor = await this.blocoEscopo();
|
|
4795
|
+
}
|
|
4796
|
+
catch (erro) {
|
|
4797
|
+
this.erros.push(erro);
|
|
4798
|
+
}
|
|
4799
|
+
if (this.erros.length > quantidadeErrosAntesCorpoAcessor) {
|
|
4800
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoAcessor);
|
|
4801
|
+
corpoAcessor = [];
|
|
4802
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4803
|
+
}
|
|
4804
|
+
let tipoAcessor = 'qualquer';
|
|
4805
|
+
let expressoesRetornaAcessor = [];
|
|
4806
|
+
for (const declaracao of corpoAcessor) {
|
|
4807
|
+
expressoesRetornaAcessor = expressoesRetornaAcessor.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
4808
|
+
}
|
|
4809
|
+
const tiposRetornosAcessor = new Set(expressoesRetornaAcessor.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
|
|
4810
|
+
const retornaExplicitamenteAcessor = tiposRetornosAcessor.size > 0;
|
|
4811
|
+
tiposRetornosAcessor.delete('qualquer');
|
|
4812
|
+
if (tiposRetornosAcessor.size > 0) {
|
|
4813
|
+
tipoAcessor = tiposRetornosAcessor.values().next().value;
|
|
4814
|
+
}
|
|
4815
|
+
else if (!retornaExplicitamenteAcessor) {
|
|
4816
|
+
tipoAcessor = 'vazio';
|
|
4817
|
+
}
|
|
4818
|
+
const corpoFuncaoAcessor = new construtos_1.FuncaoConstruto(this.hashArquivo, nomePropriedade.linha, paramsAcessor, corpoAcessor, tipoAcessor);
|
|
4819
|
+
const tipoDaFuncaoAcessor = `função<${tipoAcessor}>`;
|
|
4820
|
+
const metodoAcessor = new declaracoes_1.FuncaoDeclaracao(nomePropriedade, corpoFuncaoAcessor, tipoDaFuncaoAcessor);
|
|
4821
|
+
metodoAcessor.estatico = ehEstatico;
|
|
4822
|
+
metodoAcessor.acesso = modificadorAcesso;
|
|
4823
|
+
metodoAcessor.eObtenedor = ehObter;
|
|
4824
|
+
metodoAcessor.eDefinidor = !ehObter;
|
|
4825
|
+
metodos.push(metodoAcessor);
|
|
4826
|
+
}
|
|
4827
|
+
else {
|
|
4828
|
+
// Forma trivial: obter; / definir;
|
|
4829
|
+
if (ehObter) {
|
|
4830
|
+
prop.autoObter = true;
|
|
4831
|
+
}
|
|
4832
|
+
else {
|
|
4833
|
+
prop.autoDefinir = true;
|
|
4834
|
+
}
|
|
4835
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
else {
|
|
4839
|
+
break;
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após acessores da propriedade.");
|
|
4843
|
+
// Corpo personalizado: obtenedor/definidor são métodos — não há campos base a declarar.
|
|
4844
|
+
// Para auto-propriedades, o campo base iniciado por '_' é criado em tempo de execução com base
|
|
4845
|
+
// nos indicadores autoObter/autoDefinir. O avaliador sintático usa o nome original ('nome').
|
|
4846
|
+
if (!temCorpoPersonalizado) {
|
|
4847
|
+
propriedades.push(prop);
|
|
4848
|
+
}
|
|
4849
|
+
}
|
|
4850
|
+
else {
|
|
4851
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4852
|
+
propriedades.push(prop);
|
|
4853
|
+
}
|
|
4854
|
+
this.pilhaDecoradores = [];
|
|
4855
|
+
}
|
|
4856
|
+
async compreenderMembros(acessoPadrao, ehEstaticoPadrao, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades) {
|
|
4857
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
|
|
4858
|
+
!this.estaNoFinal()) {
|
|
4859
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.COMENTARIO ||
|
|
4860
|
+
this.simbolos[this.atual].tipo === delegua_2.default.LINHA_COMENTARIO) {
|
|
4861
|
+
this.avancarEDevolverAnterior();
|
|
4862
|
+
continue;
|
|
4863
|
+
}
|
|
4864
|
+
let docAtual = undefined;
|
|
4865
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.DOCUMENTARIO) {
|
|
4866
|
+
const simboloDoc = this.avancarEDevolverAnterior();
|
|
4867
|
+
docAtual = new construtos_1.ComentarioComoConstruto(simboloDoc);
|
|
4868
|
+
}
|
|
4869
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.ARROBA) {
|
|
4870
|
+
await this.resolverDecoradores();
|
|
4871
|
+
continue;
|
|
4872
|
+
}
|
|
4873
|
+
const tipoAtual = this.simbolos[this.atual].tipo;
|
|
4874
|
+
const tipoProximo = this.simbolos[this.atual + 1]?.tipo;
|
|
4875
|
+
const ehBlocoAcesso = [delegua_2.default.PRIVADO, delegua_2.default.PROTEGIDO].includes(tipoAtual) &&
|
|
4876
|
+
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4877
|
+
const ehBlocoEstatico = tipoAtual === delegua_2.default.ESTATICO && tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4878
|
+
const ehBlocoAbstrato = tipoAtual === delegua_2.default.ABSTRATO && tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4879
|
+
if (ehBlocoAcesso) {
|
|
4880
|
+
const novoAcesso = tipoAtual === delegua_2.default.PRIVADO ? 'privado' : 'protegido';
|
|
4881
|
+
this.avancarEDevolverAnterior();
|
|
4882
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após modificador de acesso de bloco.");
|
|
4883
|
+
await this.compreenderMembros(novoAcesso, ehEstaticoPadrao, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
4884
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco de modificador de acesso.");
|
|
4885
|
+
continue;
|
|
4886
|
+
}
|
|
4887
|
+
if (ehBlocoEstatico) {
|
|
4888
|
+
this.avancarEDevolverAnterior();
|
|
4889
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'estático'.");
|
|
4890
|
+
await this.compreenderMembros(acessoPadrao, true, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
4891
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco estático.");
|
|
4892
|
+
continue;
|
|
4893
|
+
}
|
|
4894
|
+
if (ehBlocoAbstrato) {
|
|
4895
|
+
this.avancarEDevolverAnterior();
|
|
4896
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'abstrato'.");
|
|
4897
|
+
await this.compreenderMembros(acessoPadrao, ehEstaticoPadrao, true, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
4898
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco abstrato.");
|
|
4899
|
+
continue;
|
|
4900
|
+
}
|
|
4901
|
+
const modificadorAcesso = acessoPadrao;
|
|
4902
|
+
const ehEstatico = ehEstaticoPadrao;
|
|
4903
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.OPERADOR) {
|
|
4904
|
+
await this.analisarMembroOperador(ehEstatico, modificadorAcesso, metodos, docAtual);
|
|
4905
|
+
continue;
|
|
4906
|
+
}
|
|
4907
|
+
const proximoSimbolo = this.simbolos[this.atual + 1];
|
|
4908
|
+
switch (proximoSimbolo?.tipo) {
|
|
4909
|
+
case delegua_2.default.PARENTESE_ESQUERDO:
|
|
4910
|
+
await this.analisarMembroMetodo(ehEstatico, modificadorAcesso, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, docAtual);
|
|
4911
|
+
break;
|
|
4912
|
+
case delegua_2.default.DOIS_PONTOS:
|
|
4913
|
+
await this.analisarMembroPropriedade(ehEstatico, modificadorAcesso, metodos, propriedades, docAtual);
|
|
4914
|
+
break;
|
|
4915
|
+
default:
|
|
4916
|
+
throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
|
|
4917
|
+
}
|
|
4918
|
+
}
|
|
4919
|
+
}
|
|
4637
4920
|
async declaracaoDeClasse() {
|
|
4638
4921
|
// Modificadores opcionais no nível da classe: `abstrata`, `estrangeira` e/ou `estática`.
|
|
4639
4922
|
// Sintaxe: `classe abstrata NomeDaClasse`, `classe estrangeira NomeDaClasse`, etc.
|
|
@@ -4685,314 +4968,8 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
4685
4968
|
this.pilhaDecoradores = [];
|
|
4686
4969
|
const metodos = [];
|
|
4687
4970
|
const propriedades = [];
|
|
4688
|
-
/**
|
|
4689
|
-
* Analisa membros do corpo da classe com um contexto de acesso e estático padrão.
|
|
4690
|
-
* Suporta blocos de contexto aninhados: `estático { }`, `abstrato { }`, `privado { }`, `protegido { }`, `publico { }`.
|
|
4691
|
-
*/
|
|
4692
|
-
const compreenderMembros = async (acessoPadrao, ehEstaticoPadrao, ehAbstratoPadrao = false) => {
|
|
4693
|
-
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
|
|
4694
|
-
!this.estaNoFinal()) {
|
|
4695
|
-
// Pular comentários normais dentro do corpo da classe.
|
|
4696
|
-
if (this.simbolos[this.atual].tipo === delegua_2.default.COMENTARIO ||
|
|
4697
|
-
this.simbolos[this.atual].tipo === delegua_2.default.LINHA_COMENTARIO) {
|
|
4698
|
-
this.avancarEDevolverAnterior();
|
|
4699
|
-
continue;
|
|
4700
|
-
}
|
|
4701
|
-
// Documentário (/** ... */)
|
|
4702
|
-
let docAtual = undefined;
|
|
4703
|
-
if (this.simbolos[this.atual].tipo === delegua_2.default.DOCUMENTARIO) {
|
|
4704
|
-
const simboloDoc = this.avancarEDevolverAnterior();
|
|
4705
|
-
docAtual = new construtos_1.ComentarioComoConstruto(simboloDoc);
|
|
4706
|
-
}
|
|
4707
|
-
// Decorador
|
|
4708
|
-
if (this.simbolos[this.atual].tipo === delegua_2.default.ARROBA) {
|
|
4709
|
-
await this.resolverDecoradores();
|
|
4710
|
-
continue;
|
|
4711
|
-
}
|
|
4712
|
-
// Detecção de bloco de contexto: modificador seguido de '{'
|
|
4713
|
-
const tipoAtual = this.simbolos[this.atual].tipo;
|
|
4714
|
-
const tipoProximo = this.simbolos[this.atual + 1]?.tipo;
|
|
4715
|
-
const ehBlocoAcesso = [delegua_2.default.PRIVADO, delegua_2.default.PROTEGIDO].includes(tipoAtual) &&
|
|
4716
|
-
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4717
|
-
const ehBlocoEstatico = tipoAtual === delegua_2.default.ESTATICO &&
|
|
4718
|
-
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4719
|
-
const ehBlocoAbstrato = tipoAtual === delegua_2.default.ABSTRATO &&
|
|
4720
|
-
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4721
|
-
if (ehBlocoAcesso) {
|
|
4722
|
-
const novoAcesso = tipoAtual === delegua_2.default.PRIVADO ? 'privado' : 'protegido';
|
|
4723
|
-
this.avancarEDevolverAnterior(); // consume modificador de acesso
|
|
4724
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após modificador de acesso de bloco.");
|
|
4725
|
-
await compreenderMembros(novoAcesso, ehEstaticoPadrao, ehAbstratoPadrao);
|
|
4726
|
-
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco de modificador de acesso.");
|
|
4727
|
-
continue;
|
|
4728
|
-
}
|
|
4729
|
-
if (ehBlocoEstatico) {
|
|
4730
|
-
this.avancarEDevolverAnterior(); // consume 'estático'
|
|
4731
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'estático'.");
|
|
4732
|
-
await compreenderMembros(acessoPadrao, true, ehAbstratoPadrao);
|
|
4733
|
-
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco estático.");
|
|
4734
|
-
continue;
|
|
4735
|
-
}
|
|
4736
|
-
if (ehBlocoAbstrato) {
|
|
4737
|
-
this.avancarEDevolverAnterior(); // consume 'abstrato'
|
|
4738
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'abstrato'.");
|
|
4739
|
-
await compreenderMembros(acessoPadrao, ehEstaticoPadrao, true);
|
|
4740
|
-
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco abstrato.");
|
|
4741
|
-
continue;
|
|
4742
|
-
}
|
|
4743
|
-
const modificadorAcesso = acessoPadrao;
|
|
4744
|
-
const ehEstatico = ehEstaticoPadrao;
|
|
4745
|
-
// Método operador sobrecarregado: `operador+ (outro) { ... }`
|
|
4746
|
-
if (this.simbolos[this.atual].tipo === delegua_2.default.OPERADOR) {
|
|
4747
|
-
const simboloOperadorKeyword = this.avancarEDevolverAnterior();
|
|
4748
|
-
const simboloDoOperador = this.avancarEDevolverAnterior();
|
|
4749
|
-
const nomeMetodoOp = 'operador' + simboloDoOperador.lexema;
|
|
4750
|
-
const simboloNomeMetodo = {
|
|
4751
|
-
tipo: delegua_2.default.IDENTIFICADOR,
|
|
4752
|
-
lexema: nomeMetodoOp,
|
|
4753
|
-
literal: null,
|
|
4754
|
-
linha: simboloOperadorKeyword.linha,
|
|
4755
|
-
hashArquivo: this.hashArquivo,
|
|
4756
|
-
};
|
|
4757
|
-
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após operador sobrecarregado.");
|
|
4758
|
-
let paramsOp = [];
|
|
4759
|
-
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4760
|
-
paramsOp = await this.logicaComumParametros();
|
|
4761
|
-
}
|
|
4762
|
-
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do operador.");
|
|
4763
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do operador.");
|
|
4764
|
-
const indiceAberturaCorpoOp = this.atual - 1;
|
|
4765
|
-
const quantidadeErrosAntesCorpoOp = this.erros.length;
|
|
4766
|
-
let corpoOp = [];
|
|
4767
|
-
try {
|
|
4768
|
-
corpoOp = await this.blocoEscopo();
|
|
4769
|
-
}
|
|
4770
|
-
catch (erro) {
|
|
4771
|
-
this.erros.push(erro);
|
|
4772
|
-
}
|
|
4773
|
-
if (this.erros.length > quantidadeErrosAntesCorpoOp) {
|
|
4774
|
-
this.atual =
|
|
4775
|
-
this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoOp);
|
|
4776
|
-
corpoOp = [];
|
|
4777
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4778
|
-
}
|
|
4779
|
-
const corpoFuncaoOp = new construtos_1.FuncaoConstruto(this.hashArquivo, simboloNomeMetodo.linha, paramsOp, corpoOp);
|
|
4780
|
-
const metodoOp = new declaracoes_1.FuncaoDeclaracao(simboloNomeMetodo, corpoFuncaoOp);
|
|
4781
|
-
metodoOp.estatico = ehEstatico;
|
|
4782
|
-
metodoOp.acesso = modificadorAcesso;
|
|
4783
|
-
metodoOp.documentacao = docAtual;
|
|
4784
|
-
metodos.push(metodoOp);
|
|
4785
|
-
this.pilhaDecoradores = [];
|
|
4786
|
-
continue;
|
|
4787
|
-
}
|
|
4788
|
-
// Método ou propriedade, determinado pelo token seguinte ao nome
|
|
4789
|
-
const proximoSimbolo = this.simbolos[this.atual + 1];
|
|
4790
|
-
switch (proximoSimbolo?.tipo) {
|
|
4791
|
-
case delegua_2.default.PARENTESE_ESQUERDO: {
|
|
4792
|
-
// Analisa: nome ( params ) [abstrato] [: tipoRetorno] { corpo }
|
|
4793
|
-
const nomeMetodo = this.avancarEDevolverAnterior();
|
|
4794
|
-
// Pré-registrar para suportar chamadas recursivas (igual a funcao()).
|
|
4795
|
-
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, 'qualquer'));
|
|
4796
|
-
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
|
|
4797
|
-
let params = [];
|
|
4798
|
-
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4799
|
-
params = await this.logicaComumParametros();
|
|
4800
|
-
}
|
|
4801
|
-
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do método.");
|
|
4802
|
-
// Tipo de retorno opcional (igual a corpoDaFuncao())
|
|
4803
|
-
let tipoRetorno = 'qualquer';
|
|
4804
|
-
let definicaoExplicitaDeTipo = false;
|
|
4805
|
-
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
|
|
4806
|
-
tipoRetorno = this.verificarDefinicaoTipoAtual();
|
|
4807
|
-
this.avancarEDevolverAnterior();
|
|
4808
|
-
definicaoExplicitaDeTipo = true;
|
|
4809
|
-
}
|
|
4810
|
-
// Método de classe estrangeira não pode ter corpo.
|
|
4811
|
-
if (ehEstrangeira &&
|
|
4812
|
-
this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
4813
|
-
throw this.erro(this.simbolos[this.atual], 'Métodos de classe estrangeira não podem ter corpo.');
|
|
4814
|
-
}
|
|
4815
|
-
// Método é abstrato quando: (a) está dentro de um bloco `abstrato {}`,
|
|
4816
|
-
// ou (b) a classe é abstrata/estrangeira e o próximo token não é `{`.
|
|
4817
|
-
const ehAbstrato = ehAbstratoPadrao ||
|
|
4818
|
-
ehEstrangeira ||
|
|
4819
|
-
(ehAbstrata &&
|
|
4820
|
-
!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA));
|
|
4821
|
-
if (ehAbstrato) {
|
|
4822
|
-
// Método abstrato/estrangeiro: sem corpo
|
|
4823
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4824
|
-
const corpoVazio = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, [], tipoRetorno, definicaoExplicitaDeTipo);
|
|
4825
|
-
const metodoAbstrato = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoVazio, tipoRetorno);
|
|
4826
|
-
metodoAbstrato.estatico = ehEstatico;
|
|
4827
|
-
metodoAbstrato.abstrato = true;
|
|
4828
|
-
metodoAbstrato.acesso = modificadorAcesso;
|
|
4829
|
-
metodoAbstrato.documentacao = docAtual;
|
|
4830
|
-
metodos.push(metodoAbstrato);
|
|
4831
|
-
}
|
|
4832
|
-
else {
|
|
4833
|
-
// Método concreto: com corpo.
|
|
4834
|
-
// Inferência de tipo de retorno igual a corpoDaFuncao().
|
|
4835
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do método.");
|
|
4836
|
-
const indiceAberturaCorpo = this.atual - 1;
|
|
4837
|
-
const quantidadeErrosAntesCorpo = this.erros.length;
|
|
4838
|
-
let corpo = [];
|
|
4839
|
-
try {
|
|
4840
|
-
corpo = await this.blocoEscopo();
|
|
4841
|
-
}
|
|
4842
|
-
catch (erro) {
|
|
4843
|
-
this.erros.push(erro);
|
|
4844
|
-
}
|
|
4845
|
-
if (this.erros.length > quantidadeErrosAntesCorpo) {
|
|
4846
|
-
this.atual =
|
|
4847
|
-
this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpo);
|
|
4848
|
-
corpo = [];
|
|
4849
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4850
|
-
}
|
|
4851
|
-
let expressoesRetorna = [];
|
|
4852
|
-
for (const declaracao of corpo) {
|
|
4853
|
-
expressoesRetorna = expressoesRetorna.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
4854
|
-
}
|
|
4855
|
-
const tiposRetornos = new Set(expressoesRetorna
|
|
4856
|
-
.filter((e) => e.tipo !== 'qualquer')
|
|
4857
|
-
.map((e) => e.tipo));
|
|
4858
|
-
const retornaChamadoExplicitamente = tiposRetornos.size > 0;
|
|
4859
|
-
tiposRetornos.delete('qualquer');
|
|
4860
|
-
if (tipoRetorno === 'qualquer') {
|
|
4861
|
-
if (tiposRetornos.size > 0) {
|
|
4862
|
-
tipoRetorno = tiposRetornos.values().next().value;
|
|
4863
|
-
}
|
|
4864
|
-
else if (!retornaChamadoExplicitamente &&
|
|
4865
|
-
!definicaoExplicitaDeTipo) {
|
|
4866
|
-
tipoRetorno = 'vazio';
|
|
4867
|
-
}
|
|
4868
|
-
}
|
|
4869
|
-
const corpoFuncao = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, corpo, tipoRetorno);
|
|
4870
|
-
const tipoDaFuncao = `função<${tipoRetorno}>`;
|
|
4871
|
-
const metodo = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoFuncao, tipoDaFuncao);
|
|
4872
|
-
metodo.estatico = ehEstatico;
|
|
4873
|
-
metodo.acesso = modificadorAcesso;
|
|
4874
|
-
metodo.decoradores = Array.from(this.pilhaDecoradores);
|
|
4875
|
-
metodo.documentacao = docAtual;
|
|
4876
|
-
metodos.push(metodo);
|
|
4877
|
-
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, tipoDaFuncao));
|
|
4878
|
-
this.pilhaEscopos.registrarReferenciaFuncao(nomeMetodo.lexema, metodo);
|
|
4879
|
-
}
|
|
4880
|
-
this.pilhaDecoradores = [];
|
|
4881
|
-
break;
|
|
4882
|
-
}
|
|
4883
|
-
case delegua_2.default.DOIS_PONTOS: {
|
|
4884
|
-
const nomePropriedade = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado identificador para nome de propriedade.');
|
|
4885
|
-
this.consumir(delegua_2.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade.');
|
|
4886
|
-
const tipoPropriedade = this.avancarEDevolverAnterior();
|
|
4887
|
-
let nomeTipoPropriedade = tipoPropriedade.lexema;
|
|
4888
|
-
if (this.verificarTipoSimboloAtual(delegua_2.default.COLCHETE_ESQUERDO)) {
|
|
4889
|
-
this.avancarEDevolverAnterior(); // consume '['
|
|
4890
|
-
this.consumir(delegua_2.default.COLCHETE_DIREITO, "Esperado ']' após '[' na definição do tipo de propriedade.");
|
|
4891
|
-
nomeTipoPropriedade = `${nomeTipoPropriedade}[]`;
|
|
4892
|
-
}
|
|
4893
|
-
const prop = new declaracoes_1.PropriedadeClasse(nomePropriedade, nomeTipoPropriedade, Array.from(this.pilhaDecoradores), modificadorAcesso, ehEstatico);
|
|
4894
|
-
prop.documentacao = docAtual;
|
|
4895
|
-
// Auto-propriedade: `nome: tipo { obter; definir; }`
|
|
4896
|
-
// Ou corpo personalizado: `nome: tipo { obter() { ... } definir(valor) { ... } }`
|
|
4897
|
-
if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
4898
|
-
this.avancarEDevolverAnterior(); // consume '{'
|
|
4899
|
-
let temCorpoPersonalizado = false;
|
|
4900
|
-
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
|
|
4901
|
-
!this.estaNoFinal()) {
|
|
4902
|
-
const lexema = String(this.simbolos[this.atual].lexema || '').toLowerCase();
|
|
4903
|
-
if (lexema === 'obter' || lexema === 'definir') {
|
|
4904
|
-
const ehObter = lexema === 'obter';
|
|
4905
|
-
this.avancarEDevolverAnterior(); // consume 'obter' / 'definir'
|
|
4906
|
-
if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
|
|
4907
|
-
// Corpo personalizado: obter() { ... } / definir(valor) { ... }
|
|
4908
|
-
temCorpoPersonalizado = true;
|
|
4909
|
-
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após acessor.");
|
|
4910
|
-
let paramsAcessor = [];
|
|
4911
|
-
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4912
|
-
paramsAcessor = await this.logicaComumParametros();
|
|
4913
|
-
}
|
|
4914
|
-
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do acessor.");
|
|
4915
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do acessor.");
|
|
4916
|
-
const indiceAberturaCorpoAcessor = this.atual - 1;
|
|
4917
|
-
const quantidadeErrosAntesCorpoAcessor = this.erros.length;
|
|
4918
|
-
let corpoAcessor = [];
|
|
4919
|
-
try {
|
|
4920
|
-
corpoAcessor = await this.blocoEscopo();
|
|
4921
|
-
}
|
|
4922
|
-
catch (erro) {
|
|
4923
|
-
this.erros.push(erro);
|
|
4924
|
-
}
|
|
4925
|
-
if (this.erros.length > quantidadeErrosAntesCorpoAcessor) {
|
|
4926
|
-
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoAcessor);
|
|
4927
|
-
corpoAcessor = [];
|
|
4928
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4929
|
-
}
|
|
4930
|
-
// Inferência de tipo de retorno
|
|
4931
|
-
let tipoAcessor = 'qualquer';
|
|
4932
|
-
let expressoesRetornaAcessor = [];
|
|
4933
|
-
for (const declaracao of corpoAcessor) {
|
|
4934
|
-
expressoesRetornaAcessor =
|
|
4935
|
-
expressoesRetornaAcessor.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
4936
|
-
}
|
|
4937
|
-
const tiposRetornosAcessor = new Set(expressoesRetornaAcessor
|
|
4938
|
-
.filter((e) => e.tipo !== 'qualquer')
|
|
4939
|
-
.map((e) => e.tipo));
|
|
4940
|
-
const retornaExplicitamenteAcessor = tiposRetornosAcessor.size > 0;
|
|
4941
|
-
tiposRetornosAcessor.delete('qualquer');
|
|
4942
|
-
if (tiposRetornosAcessor.size > 0) {
|
|
4943
|
-
tipoAcessor = tiposRetornosAcessor
|
|
4944
|
-
.values()
|
|
4945
|
-
.next().value;
|
|
4946
|
-
}
|
|
4947
|
-
else if (!retornaExplicitamenteAcessor) {
|
|
4948
|
-
tipoAcessor = 'vazio';
|
|
4949
|
-
}
|
|
4950
|
-
const corpoFuncaoAcessor = new construtos_1.FuncaoConstruto(this.hashArquivo, nomePropriedade.linha, paramsAcessor, corpoAcessor, tipoAcessor);
|
|
4951
|
-
const tipoDaFuncaoAcessor = `função<${tipoAcessor}>`;
|
|
4952
|
-
const metodoAcessor = new declaracoes_1.FuncaoDeclaracao(nomePropriedade, corpoFuncaoAcessor, tipoDaFuncaoAcessor);
|
|
4953
|
-
metodoAcessor.estatico = ehEstatico;
|
|
4954
|
-
metodoAcessor.acesso = modificadorAcesso;
|
|
4955
|
-
metodoAcessor.eObtenedor = ehObter;
|
|
4956
|
-
metodoAcessor.eDefinidor = !ehObter;
|
|
4957
|
-
metodos.push(metodoAcessor);
|
|
4958
|
-
}
|
|
4959
|
-
else {
|
|
4960
|
-
// Forma trivial: obter; / definir;
|
|
4961
|
-
if (ehObter) {
|
|
4962
|
-
prop.autoObter = true;
|
|
4963
|
-
}
|
|
4964
|
-
else {
|
|
4965
|
-
prop.autoDefinir = true;
|
|
4966
|
-
}
|
|
4967
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4968
|
-
}
|
|
4969
|
-
}
|
|
4970
|
-
else {
|
|
4971
|
-
break;
|
|
4972
|
-
}
|
|
4973
|
-
}
|
|
4974
|
-
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após acessores da propriedade.");
|
|
4975
|
-
// Corpo personalizado: obtenedor/definidor são métodos — não há campos base a declarar.
|
|
4976
|
-
// Para auto-propriedades, o campo base iniciado por '_' é criado em tempo de execução com base
|
|
4977
|
-
// nos indicadores autoObter/autoDefinir. O avaliador sintático usa o nome original ('nome').
|
|
4978
|
-
if (!temCorpoPersonalizado) {
|
|
4979
|
-
propriedades.push(prop);
|
|
4980
|
-
}
|
|
4981
|
-
}
|
|
4982
|
-
else {
|
|
4983
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4984
|
-
propriedades.push(prop);
|
|
4985
|
-
}
|
|
4986
|
-
this.pilhaDecoradores = [];
|
|
4987
|
-
break;
|
|
4988
|
-
}
|
|
4989
|
-
default:
|
|
4990
|
-
throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
|
|
4991
|
-
}
|
|
4992
|
-
}
|
|
4993
|
-
};
|
|
4994
4971
|
this.metodosClasseAtualEmAnalise = metodos;
|
|
4995
|
-
await compreenderMembros('publico', false);
|
|
4972
|
+
await this.compreenderMembros('publico', false, false, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
4996
4973
|
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após o escopo da classe.");
|
|
4997
4974
|
// Verificação em tempo de análise: classe deve implementar todos os contratos das interfaces.
|
|
4998
4975
|
const linhaFinalClasse = this.simbolos[this.atual - 1].linha;
|