@designliquido/delegua 1.24.0 → 1.24.2
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/analisador-semantico/analisador-semantico.d.ts.map +1 -1
- package/analisador-semantico/analisador-semantico.js +4 -0
- package/analisador-semantico/analisador-semantico.js.map +1 -1
- package/analisador-semantico/dialetos/analisador-semantico-pitugues.d.ts.map +1 -1
- package/analisador-semantico/dialetos/analisador-semantico-pitugues.js +10 -0
- package/analisador-semantico/dialetos/analisador-semantico-pitugues.js.map +1 -1
- package/avaliador-sintatico/avaliador-sintatico-base.js +1 -1
- package/avaliador-sintatico/avaliador-sintatico-base.js.map +1 -1
- 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 +285 -308
- package/avaliador-sintatico/avaliador-sintatico.js.map +1 -1
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.d.ts.map +1 -1
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.js +2 -2
- package/avaliador-sintatico/dialetos/avaliador-sintatico-pitugues.js.map +1 -1
- package/bin/package.json +1 -1
- package/interpretador/interpretador-base.d.ts.map +1 -1
- package/interpretador/interpretador-base.js +31 -0
- package/interpretador/interpretador-base.js.map +1 -1
- package/interpretador/interpretador.d.ts.map +1 -1
- package/interpretador/interpretador.js +9 -1
- package/interpretador/interpretador.js.map +1 -1
- package/package.json +1 -1
- package/umd/delegua.js +332 -312
package/umd/delegua.js
CHANGED
|
@@ -553,6 +553,10 @@ class AnalisadorSemantico extends analisador_semantico_base_1.AnalisadorSemantic
|
|
|
553
553
|
// Chamadas de método/função podem retornar vetores.
|
|
554
554
|
// A validação detalhada é feita em tempo de execução.
|
|
555
555
|
}
|
|
556
|
+
else if (declaracao.inicializador instanceof construtos_1.Binario) {
|
|
557
|
+
// Expressões binárias podem produzir vetores em tempo de execução
|
|
558
|
+
// (ex: vetor1 + vetor2 concatena dois vetores), então não geramos erro
|
|
559
|
+
}
|
|
556
560
|
else {
|
|
557
561
|
this.erro(declaracao.simbolo, `Atribuição inválida para '${declaracao.simbolo.lexema}': é esperado um vetor de elementos.`);
|
|
558
562
|
}
|
|
@@ -2201,7 +2205,7 @@ class AvaliadorSintaticoBase {
|
|
|
2201
2205
|
async unario() {
|
|
2202
2206
|
if (this.verificarSeSimboloAtualEIgualA(comum_1.default.NEGACAO, comum_1.default.SUBTRACAO)) {
|
|
2203
2207
|
const operador = this.simbolos[this.atual - 1];
|
|
2204
|
-
const direito = await this.
|
|
2208
|
+
const direito = await this.exponenciacao();
|
|
2205
2209
|
return Promise.resolve(new construtos_1.Unario(this.hashArquivo, operador, direito, 'ANTES'));
|
|
2206
2210
|
}
|
|
2207
2211
|
return await this.chamar();
|
|
@@ -3374,7 +3378,7 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
3374
3378
|
}
|
|
3375
3379
|
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.NAO, delegua_2.default.NEGACAO, delegua_2.default.ADICAO, delegua_2.default.SUBTRACAO, delegua_2.default.BIT_NOT, delegua_2.default.INCREMENTAR, delegua_2.default.DECREMENTAR)) {
|
|
3376
3380
|
const operador = this.simbolos[this.atual - 1];
|
|
3377
|
-
const direito = await this.
|
|
3381
|
+
const direito = await this.exponenciacao();
|
|
3378
3382
|
if (operador.tipo === delegua_2.default.NEGACAO ||
|
|
3379
3383
|
operador.tipo === delegua_2.default.NAO) {
|
|
3380
3384
|
this.verificarOperandoNegacao(operador, direito);
|
|
@@ -4634,6 +4638,289 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
4634
4638
|
this.interfacesDeclaradas[simbolo.lexema] = declaracao;
|
|
4635
4639
|
return declaracao;
|
|
4636
4640
|
}
|
|
4641
|
+
async analisarMembroOperador(ehEstatico, modificadorAcesso, metodos, docAtual) {
|
|
4642
|
+
const simboloOperadorKeyword = this.avancarEDevolverAnterior();
|
|
4643
|
+
const simboloDoOperador = this.avancarEDevolverAnterior();
|
|
4644
|
+
const nomeMetodoOp = 'operador' + simboloDoOperador.lexema;
|
|
4645
|
+
const simboloNomeMetodo = {
|
|
4646
|
+
tipo: delegua_2.default.IDENTIFICADOR,
|
|
4647
|
+
lexema: nomeMetodoOp,
|
|
4648
|
+
literal: null,
|
|
4649
|
+
linha: simboloOperadorKeyword.linha,
|
|
4650
|
+
hashArquivo: this.hashArquivo,
|
|
4651
|
+
};
|
|
4652
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após operador sobrecarregado.");
|
|
4653
|
+
let paramsOp = [];
|
|
4654
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4655
|
+
paramsOp = await this.logicaComumParametros();
|
|
4656
|
+
}
|
|
4657
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do operador.");
|
|
4658
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do operador.");
|
|
4659
|
+
const indiceAberturaCorpoOp = this.atual - 1;
|
|
4660
|
+
const quantidadeErrosAntesCorpoOp = this.erros.length;
|
|
4661
|
+
let corpoOp = [];
|
|
4662
|
+
try {
|
|
4663
|
+
corpoOp = await this.blocoEscopo();
|
|
4664
|
+
}
|
|
4665
|
+
catch (erro) {
|
|
4666
|
+
this.erros.push(erro);
|
|
4667
|
+
}
|
|
4668
|
+
if (this.erros.length > quantidadeErrosAntesCorpoOp) {
|
|
4669
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoOp);
|
|
4670
|
+
corpoOp = [];
|
|
4671
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4672
|
+
}
|
|
4673
|
+
const corpoFuncaoOp = new construtos_1.FuncaoConstruto(this.hashArquivo, simboloNomeMetodo.linha, paramsOp, corpoOp);
|
|
4674
|
+
const metodoOp = new declaracoes_1.FuncaoDeclaracao(simboloNomeMetodo, corpoFuncaoOp);
|
|
4675
|
+
metodoOp.estatico = ehEstatico;
|
|
4676
|
+
metodoOp.acesso = modificadorAcesso;
|
|
4677
|
+
metodoOp.documentacao = docAtual;
|
|
4678
|
+
metodos.push(metodoOp);
|
|
4679
|
+
this.pilhaDecoradores = [];
|
|
4680
|
+
}
|
|
4681
|
+
async analisarMembroMetodo(ehEstatico, modificadorAcesso, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, docAtual) {
|
|
4682
|
+
const nomeMetodo = this.avancarEDevolverAnterior();
|
|
4683
|
+
// Pré-registrar para suportar chamadas recursivas (igual a funcao()).
|
|
4684
|
+
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, 'qualquer'));
|
|
4685
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
|
|
4686
|
+
let params = [];
|
|
4687
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4688
|
+
params = await this.logicaComumParametros();
|
|
4689
|
+
}
|
|
4690
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do método.");
|
|
4691
|
+
let tipoRetorno = 'qualquer';
|
|
4692
|
+
let definicaoExplicitaDeTipo = false;
|
|
4693
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
|
|
4694
|
+
tipoRetorno = this.verificarDefinicaoTipoAtual();
|
|
4695
|
+
this.avancarEDevolverAnterior();
|
|
4696
|
+
definicaoExplicitaDeTipo = true;
|
|
4697
|
+
}
|
|
4698
|
+
if (ehEstrangeira && this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
4699
|
+
throw this.erro(this.simbolos[this.atual], 'Métodos de classe estrangeira não podem ter corpo.');
|
|
4700
|
+
}
|
|
4701
|
+
// Método é abstrato quando: (a) está dentro de um bloco `abstrato {}`,
|
|
4702
|
+
// ou (b) a classe é abstrata/estrangeira e o próximo token não é `{`.
|
|
4703
|
+
const ehAbstrato = ehAbstratoPadrao ||
|
|
4704
|
+
ehEstrangeira ||
|
|
4705
|
+
(ehAbstrata && !this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA));
|
|
4706
|
+
if (ehAbstrato) {
|
|
4707
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4708
|
+
const corpoVazio = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, [], tipoRetorno, definicaoExplicitaDeTipo);
|
|
4709
|
+
const metodoAbstrato = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoVazio, tipoRetorno);
|
|
4710
|
+
metodoAbstrato.estatico = ehEstatico;
|
|
4711
|
+
metodoAbstrato.abstrato = true;
|
|
4712
|
+
metodoAbstrato.acesso = modificadorAcesso;
|
|
4713
|
+
metodoAbstrato.decoradores = Array.from(this.pilhaDecoradores);
|
|
4714
|
+
metodoAbstrato.documentacao = docAtual;
|
|
4715
|
+
metodos.push(metodoAbstrato);
|
|
4716
|
+
}
|
|
4717
|
+
else {
|
|
4718
|
+
// Método concreto: com corpo. Inferência de tipo de retorno igual a corpoDaFuncao().
|
|
4719
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do método.");
|
|
4720
|
+
const indiceAberturaCorpo = this.atual - 1;
|
|
4721
|
+
const quantidadeErrosAntesCorpo = this.erros.length;
|
|
4722
|
+
let corpo = [];
|
|
4723
|
+
try {
|
|
4724
|
+
corpo = await this.blocoEscopo();
|
|
4725
|
+
}
|
|
4726
|
+
catch (erro) {
|
|
4727
|
+
this.erros.push(erro);
|
|
4728
|
+
}
|
|
4729
|
+
if (this.erros.length > quantidadeErrosAntesCorpo) {
|
|
4730
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpo);
|
|
4731
|
+
corpo = [];
|
|
4732
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4733
|
+
}
|
|
4734
|
+
let expressoesRetorna = [];
|
|
4735
|
+
for (const declaracao of corpo) {
|
|
4736
|
+
expressoesRetorna = expressoesRetorna.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
4737
|
+
}
|
|
4738
|
+
const tiposRetornos = new Set(expressoesRetorna.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
|
|
4739
|
+
const retornaChamadoExplicitamente = tiposRetornos.size > 0;
|
|
4740
|
+
tiposRetornos.delete('qualquer');
|
|
4741
|
+
if (tipoRetorno === 'qualquer') {
|
|
4742
|
+
if (tiposRetornos.size > 0) {
|
|
4743
|
+
tipoRetorno = tiposRetornos.values().next().value;
|
|
4744
|
+
}
|
|
4745
|
+
else if (!retornaChamadoExplicitamente && !definicaoExplicitaDeTipo) {
|
|
4746
|
+
tipoRetorno = 'vazio';
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4749
|
+
const corpoFuncao = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, corpo, tipoRetorno);
|
|
4750
|
+
const tipoDaFuncao = `função<${tipoRetorno}>`;
|
|
4751
|
+
const metodo = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoFuncao, tipoDaFuncao);
|
|
4752
|
+
metodo.estatico = ehEstatico;
|
|
4753
|
+
metodo.acesso = modificadorAcesso;
|
|
4754
|
+
metodo.decoradores = Array.from(this.pilhaDecoradores);
|
|
4755
|
+
metodo.documentacao = docAtual;
|
|
4756
|
+
metodos.push(metodo);
|
|
4757
|
+
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, tipoDaFuncao));
|
|
4758
|
+
this.pilhaEscopos.registrarReferenciaFuncao(nomeMetodo.lexema, metodo);
|
|
4759
|
+
}
|
|
4760
|
+
this.pilhaDecoradores = [];
|
|
4761
|
+
}
|
|
4762
|
+
async analisarMembroPropriedade(ehEstatico, modificadorAcesso, metodos, propriedades, docAtual) {
|
|
4763
|
+
const nomePropriedade = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado identificador para nome de propriedade.');
|
|
4764
|
+
this.consumir(delegua_2.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade.');
|
|
4765
|
+
const tipoPropriedade = this.avancarEDevolverAnterior();
|
|
4766
|
+
let nomeTipoPropriedade = tipoPropriedade.lexema;
|
|
4767
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.COLCHETE_ESQUERDO)) {
|
|
4768
|
+
this.avancarEDevolverAnterior();
|
|
4769
|
+
this.consumir(delegua_2.default.COLCHETE_DIREITO, "Esperado ']' após '[' na definição do tipo de propriedade.");
|
|
4770
|
+
nomeTipoPropriedade = `${nomeTipoPropriedade}[]`;
|
|
4771
|
+
}
|
|
4772
|
+
const prop = new declaracoes_1.PropriedadeClasse(nomePropriedade, nomeTipoPropriedade, Array.from(this.pilhaDecoradores), modificadorAcesso, ehEstatico);
|
|
4773
|
+
prop.documentacao = docAtual;
|
|
4774
|
+
// Auto-propriedade: `nome: tipo { obter; definir; }`
|
|
4775
|
+
// Ou corpo personalizado: `nome: tipo { obter() { ... } definir(valor) { ... } }`
|
|
4776
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
4777
|
+
this.avancarEDevolverAnterior();
|
|
4778
|
+
let temCorpoPersonalizado = false;
|
|
4779
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) && !this.estaNoFinal()) {
|
|
4780
|
+
const lexema = String(this.simbolos[this.atual].lexema || '').toLowerCase();
|
|
4781
|
+
if (lexema === 'obter' || lexema === 'definir') {
|
|
4782
|
+
const ehObter = lexema === 'obter';
|
|
4783
|
+
this.avancarEDevolverAnterior();
|
|
4784
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
|
|
4785
|
+
// Corpo personalizado: obter() { ... } / definir(valor) { ... }
|
|
4786
|
+
temCorpoPersonalizado = true;
|
|
4787
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após acessor.");
|
|
4788
|
+
let paramsAcessor = [];
|
|
4789
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
4790
|
+
paramsAcessor = await this.logicaComumParametros();
|
|
4791
|
+
}
|
|
4792
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do acessor.");
|
|
4793
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do acessor.");
|
|
4794
|
+
const indiceAberturaCorpoAcessor = this.atual - 1;
|
|
4795
|
+
const quantidadeErrosAntesCorpoAcessor = this.erros.length;
|
|
4796
|
+
let corpoAcessor = [];
|
|
4797
|
+
try {
|
|
4798
|
+
corpoAcessor = await this.blocoEscopo();
|
|
4799
|
+
}
|
|
4800
|
+
catch (erro) {
|
|
4801
|
+
this.erros.push(erro);
|
|
4802
|
+
}
|
|
4803
|
+
if (this.erros.length > quantidadeErrosAntesCorpoAcessor) {
|
|
4804
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoAcessor);
|
|
4805
|
+
corpoAcessor = [];
|
|
4806
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4807
|
+
}
|
|
4808
|
+
let tipoAcessor = 'qualquer';
|
|
4809
|
+
let expressoesRetornaAcessor = [];
|
|
4810
|
+
for (const declaracao of corpoAcessor) {
|
|
4811
|
+
expressoesRetornaAcessor = expressoesRetornaAcessor.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
4812
|
+
}
|
|
4813
|
+
const tiposRetornosAcessor = new Set(expressoesRetornaAcessor.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
|
|
4814
|
+
const retornaExplicitamenteAcessor = tiposRetornosAcessor.size > 0;
|
|
4815
|
+
tiposRetornosAcessor.delete('qualquer');
|
|
4816
|
+
if (tiposRetornosAcessor.size > 0) {
|
|
4817
|
+
tipoAcessor = tiposRetornosAcessor.values().next().value;
|
|
4818
|
+
}
|
|
4819
|
+
else if (!retornaExplicitamenteAcessor) {
|
|
4820
|
+
tipoAcessor = 'vazio';
|
|
4821
|
+
}
|
|
4822
|
+
const corpoFuncaoAcessor = new construtos_1.FuncaoConstruto(this.hashArquivo, nomePropriedade.linha, paramsAcessor, corpoAcessor, tipoAcessor);
|
|
4823
|
+
const tipoDaFuncaoAcessor = `função<${tipoAcessor}>`;
|
|
4824
|
+
const metodoAcessor = new declaracoes_1.FuncaoDeclaracao(nomePropriedade, corpoFuncaoAcessor, tipoDaFuncaoAcessor);
|
|
4825
|
+
metodoAcessor.estatico = ehEstatico;
|
|
4826
|
+
metodoAcessor.acesso = modificadorAcesso;
|
|
4827
|
+
metodoAcessor.eObtenedor = ehObter;
|
|
4828
|
+
metodoAcessor.eDefinidor = !ehObter;
|
|
4829
|
+
metodos.push(metodoAcessor);
|
|
4830
|
+
}
|
|
4831
|
+
else {
|
|
4832
|
+
// Forma trivial: obter; / definir;
|
|
4833
|
+
if (ehObter) {
|
|
4834
|
+
prop.autoObter = true;
|
|
4835
|
+
}
|
|
4836
|
+
else {
|
|
4837
|
+
prop.autoDefinir = true;
|
|
4838
|
+
}
|
|
4839
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
else {
|
|
4843
|
+
break;
|
|
4844
|
+
}
|
|
4845
|
+
}
|
|
4846
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após acessores da propriedade.");
|
|
4847
|
+
// Corpo personalizado: obtenedor/definidor são métodos — não há campos base a declarar.
|
|
4848
|
+
// Para auto-propriedades, o campo base iniciado por '_' é criado em tempo de execução com base
|
|
4849
|
+
// nos indicadores autoObter/autoDefinir. O avaliador sintático usa o nome original ('nome').
|
|
4850
|
+
if (!temCorpoPersonalizado) {
|
|
4851
|
+
propriedades.push(prop);
|
|
4852
|
+
}
|
|
4853
|
+
}
|
|
4854
|
+
else {
|
|
4855
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
4856
|
+
propriedades.push(prop);
|
|
4857
|
+
}
|
|
4858
|
+
this.pilhaDecoradores = [];
|
|
4859
|
+
}
|
|
4860
|
+
async compreenderMembros(acessoPadrao, ehEstaticoPadrao, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades) {
|
|
4861
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
|
|
4862
|
+
!this.estaNoFinal()) {
|
|
4863
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.COMENTARIO ||
|
|
4864
|
+
this.simbolos[this.atual].tipo === delegua_2.default.LINHA_COMENTARIO) {
|
|
4865
|
+
this.avancarEDevolverAnterior();
|
|
4866
|
+
continue;
|
|
4867
|
+
}
|
|
4868
|
+
let docAtual = undefined;
|
|
4869
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.DOCUMENTARIO) {
|
|
4870
|
+
const simboloDoc = this.avancarEDevolverAnterior();
|
|
4871
|
+
docAtual = new construtos_1.ComentarioComoConstruto(simboloDoc);
|
|
4872
|
+
}
|
|
4873
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.ARROBA) {
|
|
4874
|
+
await this.resolverDecoradores();
|
|
4875
|
+
continue;
|
|
4876
|
+
}
|
|
4877
|
+
const tipoAtual = this.simbolos[this.atual].tipo;
|
|
4878
|
+
const tipoProximo = this.simbolos[this.atual + 1]?.tipo;
|
|
4879
|
+
const ehBlocoAcesso = [delegua_2.default.PRIVADO, delegua_2.default.PROTEGIDO].includes(tipoAtual) &&
|
|
4880
|
+
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4881
|
+
const ehBlocoEstatico = tipoAtual === delegua_2.default.ESTATICO && tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4882
|
+
const ehBlocoAbstrato = tipoAtual === delegua_2.default.ABSTRATO && tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
4883
|
+
if (ehBlocoAcesso) {
|
|
4884
|
+
const novoAcesso = tipoAtual === delegua_2.default.PRIVADO ? 'privado' : 'protegido';
|
|
4885
|
+
this.avancarEDevolverAnterior();
|
|
4886
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após modificador de acesso de bloco.");
|
|
4887
|
+
await this.compreenderMembros(novoAcesso, ehEstaticoPadrao, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
4888
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco de modificador de acesso.");
|
|
4889
|
+
continue;
|
|
4890
|
+
}
|
|
4891
|
+
if (ehBlocoEstatico) {
|
|
4892
|
+
this.avancarEDevolverAnterior();
|
|
4893
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'estático'.");
|
|
4894
|
+
await this.compreenderMembros(acessoPadrao, true, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
4895
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco estático.");
|
|
4896
|
+
continue;
|
|
4897
|
+
}
|
|
4898
|
+
if (ehBlocoAbstrato) {
|
|
4899
|
+
this.avancarEDevolverAnterior();
|
|
4900
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'abstrato'.");
|
|
4901
|
+
await this.compreenderMembros(acessoPadrao, ehEstaticoPadrao, true, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
4902
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco abstrato.");
|
|
4903
|
+
continue;
|
|
4904
|
+
}
|
|
4905
|
+
const modificadorAcesso = acessoPadrao;
|
|
4906
|
+
const ehEstatico = ehEstaticoPadrao;
|
|
4907
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.OPERADOR) {
|
|
4908
|
+
await this.analisarMembroOperador(ehEstatico, modificadorAcesso, metodos, docAtual);
|
|
4909
|
+
continue;
|
|
4910
|
+
}
|
|
4911
|
+
const proximoSimbolo = this.simbolos[this.atual + 1];
|
|
4912
|
+
switch (proximoSimbolo?.tipo) {
|
|
4913
|
+
case delegua_2.default.PARENTESE_ESQUERDO:
|
|
4914
|
+
await this.analisarMembroMetodo(ehEstatico, modificadorAcesso, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, docAtual);
|
|
4915
|
+
break;
|
|
4916
|
+
case delegua_2.default.DOIS_PONTOS:
|
|
4917
|
+
await this.analisarMembroPropriedade(ehEstatico, modificadorAcesso, metodos, propriedades, docAtual);
|
|
4918
|
+
break;
|
|
4919
|
+
default:
|
|
4920
|
+
throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
|
|
4921
|
+
}
|
|
4922
|
+
}
|
|
4923
|
+
}
|
|
4637
4924
|
async declaracaoDeClasse() {
|
|
4638
4925
|
// Modificadores opcionais no nível da classe: `abstrata`, `estrangeira` e/ou `estática`.
|
|
4639
4926
|
// Sintaxe: `classe abstrata NomeDaClasse`, `classe estrangeira NomeDaClasse`, etc.
|
|
@@ -4685,314 +4972,8 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
4685
4972
|
this.pilhaDecoradores = [];
|
|
4686
4973
|
const metodos = [];
|
|
4687
4974
|
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
4975
|
this.metodosClasseAtualEmAnalise = metodos;
|
|
4995
|
-
await compreenderMembros('publico', false);
|
|
4976
|
+
await this.compreenderMembros('publico', false, false, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
4996
4977
|
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após o escopo da classe.");
|
|
4997
4978
|
// Verificação em tempo de análise: classe deve implementar todos os contratos das interfaces.
|
|
4998
4979
|
const linhaFinalClasse = this.simbolos[this.atual - 1].linha;
|
|
@@ -7060,7 +7041,7 @@ class AvaliadorSintaticoPitugues extends avaliador_sintatico_base_1.AvaliadorSin
|
|
|
7060
7041
|
}
|
|
7061
7042
|
if (this.verificarSeSimboloAtualEIgualA(pitugues_2.default.NEGACAO, pitugues_2.default.SUBTRACAO, pitugues_2.default.BIT_NOT)) {
|
|
7062
7043
|
const operador = this.simboloAnterior();
|
|
7063
|
-
const direito = await this.
|
|
7044
|
+
const direito = await this.exponenciacao();
|
|
7064
7045
|
return new construtos_1.Unario(this.hashArquivo, operador, direito);
|
|
7065
7046
|
}
|
|
7066
7047
|
return await this.chamar();
|
|
@@ -7285,7 +7266,7 @@ class AvaliadorSintaticoPitugues extends avaliador_sintatico_base_1.AvaliadorSin
|
|
|
7285
7266
|
const simboloOperador = new lexador_1.Simbolo(tipoOperadorMatematico, operadorAtribuicao.lexema.charAt(0), null, operadorAtribuicao.linha, operadorAtribuicao.hashArquivo);
|
|
7286
7267
|
const operacaoBinaria = new construtos_1.Binario(this.hashArquivo, expressao, simboloOperador, valor);
|
|
7287
7268
|
if (expressao instanceof construtos_1.Variavel) {
|
|
7288
|
-
return new construtos_1.Atribuir(this.hashArquivo, expressao, operacaoBinaria);
|
|
7269
|
+
return new construtos_1.Atribuir(this.hashArquivo, expressao, operacaoBinaria, undefined, operadorAtribuicao);
|
|
7289
7270
|
}
|
|
7290
7271
|
if (expressao instanceof construtos_1.AcessoMetodoOuPropriedade) {
|
|
7291
7272
|
return new construtos_1.DefinirValor(this.hashArquivo, 0, expressao.objeto, expressao.simbolo, operacaoBinaria);
|
|
@@ -22334,6 +22315,9 @@ class InterpretadorBase {
|
|
|
22334
22315
|
// Se veio antes e o operando é uma variável, precisamos incrementar/decrementar,
|
|
22335
22316
|
// armazenar o valor da variável pra só então devolver o valor.
|
|
22336
22317
|
case delegua_1.default.INCREMENTAR:
|
|
22318
|
+
if (typeof valor === 'string') {
|
|
22319
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.operador, `Operador '${expressao.operador.lexema}' não pode ser aplicado a um texto.`, expressao.linha);
|
|
22320
|
+
}
|
|
22337
22321
|
if (expressao.incidenciaOperador === 'ANTES') {
|
|
22338
22322
|
valor++;
|
|
22339
22323
|
if (expressao.operando instanceof construtos_1.Variavel) {
|
|
@@ -22347,6 +22331,9 @@ class InterpretadorBase {
|
|
|
22347
22331
|
}
|
|
22348
22332
|
return valorAnteriorIncremento;
|
|
22349
22333
|
case delegua_1.default.DECREMENTAR:
|
|
22334
|
+
if (typeof valor === 'string') {
|
|
22335
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.operador, `Operador '${expressao.operador.lexema}' não pode ser aplicado a um texto.`, expressao.linha);
|
|
22336
|
+
}
|
|
22350
22337
|
if (expressao.incidenciaOperador === 'ANTES') {
|
|
22351
22338
|
valor--;
|
|
22352
22339
|
if (expressao.operando instanceof construtos_1.Variavel) {
|
|
@@ -22886,6 +22873,31 @@ class InterpretadorBase {
|
|
|
22886
22873
|
break;
|
|
22887
22874
|
case construtos_1.Variavel:
|
|
22888
22875
|
const alvoVariavel = expressao.alvo;
|
|
22876
|
+
if (expressao.simboloOperador) {
|
|
22877
|
+
let valorAtual;
|
|
22878
|
+
valorAtual = this.resolverValor(this.pilhaEscoposExecucao.obterValorVariavel(alvoVariavel.simbolo));
|
|
22879
|
+
if (typeof valorAtual === 'string') {
|
|
22880
|
+
let valorDireito;
|
|
22881
|
+
if (expressao.valor instanceof construtos_1.Binario) {
|
|
22882
|
+
valorDireito = this.resolverValor(await this.avaliar(expressao.valor.direita));
|
|
22883
|
+
}
|
|
22884
|
+
else {
|
|
22885
|
+
valorDireito = valorResolvido;
|
|
22886
|
+
}
|
|
22887
|
+
if (expressao.simboloOperador.tipo === delegua_1.default.MAIS_IGUAL) {
|
|
22888
|
+
if (typeof valorDireito !== 'string') {
|
|
22889
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloOperador, `Operador '+=' não pode concatenar texto com ${typeof valorDireito}. Use conversão explícita.`, expressao.linha);
|
|
22890
|
+
}
|
|
22891
|
+
}
|
|
22892
|
+
else if ([delegua_1.default.MENOS_IGUAL,
|
|
22893
|
+
delegua_1.default.MULTIPLICACAO_IGUAL,
|
|
22894
|
+
delegua_1.default.DIVISAO_IGUAL,
|
|
22895
|
+
delegua_1.default.MODULO_IGUAL]
|
|
22896
|
+
.includes(expressao.simboloOperador.tipo)) {
|
|
22897
|
+
throw new excecoes_1.ErroEmTempoDeExecucao(expressao.simboloOperador, `Operador '${expressao.simboloOperador.lexema}' não pode ser aplicado a um texto.`, expressao.linha);
|
|
22898
|
+
}
|
|
22899
|
+
}
|
|
22900
|
+
}
|
|
22889
22901
|
this.atribuirVariavel(alvoVariavel, valorResolvido, indice);
|
|
22890
22902
|
break;
|
|
22891
22903
|
default:
|
|
@@ -25563,7 +25575,15 @@ class Interpretador extends interpretador_base_1.InterpretadorBase {
|
|
|
25563
25575
|
const alvoTipoDe = await this.avaliar(valorTipoDe);
|
|
25564
25576
|
return `tipo de<${alvoTipoDe}>`;
|
|
25565
25577
|
case construtos_1.Variavel:
|
|
25566
|
-
|
|
25578
|
+
const tipoEstatico = valorTipoDe.tipo;
|
|
25579
|
+
if (tipoEstatico !== 'qualquer')
|
|
25580
|
+
return tipoEstatico;
|
|
25581
|
+
const valorAvaliado = await this.avaliar(valorTipoDe);
|
|
25582
|
+
const valorResolvido = this.resolverValor(valorAvaliado);
|
|
25583
|
+
if (valorResolvido === undefined || valorResolvido === null) {
|
|
25584
|
+
return 'qualquer';
|
|
25585
|
+
}
|
|
25586
|
+
return (0, inferenciador_1.inferirTipoVariavel)(valorResolvido);
|
|
25567
25587
|
case construtos_1.Vetor:
|
|
25568
25588
|
const vetor = valorTipoDe;
|
|
25569
25589
|
const apenasValores = vetor.valores.filter((v) => !['ComentarioComoConstruto', 'Separador'].includes(v.constructor.name));
|