@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/bin/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designliquido/delegua",
3
- "version": "1.23.5",
3
+ "version": "1.24.0",
4
4
  "description": "Linguagem de programação simples e moderna usando português estruturado.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designliquido/delegua",
3
- "version": "1.24.0",
3
+ "version": "1.24.1",
4
4
  "description": "Linguagem de programação simples e moderna usando português estruturado.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
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;