@designliquido/delegua 1.23.5 → 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/ffi/despachador-ffi-interface.d.ts +31 -0
- package/ffi/despachador-ffi-interface.d.ts.map +1 -0
- package/ffi/despachador-ffi-interface.js +3 -0
- package/ffi/despachador-ffi-interface.js.map +1 -0
- package/ffi/index.d.ts +3 -0
- package/ffi/index.d.ts.map +1 -0
- package/ffi/index.js +19 -0
- package/ffi/index.js.map +1 -0
- package/ffi/leitor-definicao.d.ts +23 -0
- package/ffi/leitor-definicao.d.ts.map +1 -0
- package/ffi/leitor-definicao.js +56 -0
- package/ffi/leitor-definicao.js.map +1 -0
- package/index.d.ts +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/interpretador/estruturas/descritor-tipo-classe.d.ts +1 -1
- package/interpretador/estruturas/descritor-tipo-classe.d.ts.map +1 -1
- package/interpretador/interpretador-base.d.ts +9 -0
- package/interpretador/interpretador-base.d.ts.map +1 -1
- package/interpretador/interpretador-base.js +14 -0
- package/interpretador/interpretador-base.js.map +1 -1
- package/interpretador/interpretador.d.ts.map +1 -1
- package/interpretador/interpretador.js +8 -0
- package/interpretador/interpretador.js.map +1 -1
- package/package.json +1 -1
- package/umd/delegua.js +785 -704
|
@@ -2241,6 +2241,289 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
2241
2241
|
this.interfacesDeclaradas[simbolo.lexema] = declaracao;
|
|
2242
2242
|
return declaracao;
|
|
2243
2243
|
}
|
|
2244
|
+
async analisarMembroOperador(ehEstatico, modificadorAcesso, metodos, docAtual) {
|
|
2245
|
+
const simboloOperadorKeyword = this.avancarEDevolverAnterior();
|
|
2246
|
+
const simboloDoOperador = this.avancarEDevolverAnterior();
|
|
2247
|
+
const nomeMetodoOp = 'operador' + simboloDoOperador.lexema;
|
|
2248
|
+
const simboloNomeMetodo = {
|
|
2249
|
+
tipo: delegua_2.default.IDENTIFICADOR,
|
|
2250
|
+
lexema: nomeMetodoOp,
|
|
2251
|
+
literal: null,
|
|
2252
|
+
linha: simboloOperadorKeyword.linha,
|
|
2253
|
+
hashArquivo: this.hashArquivo,
|
|
2254
|
+
};
|
|
2255
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após operador sobrecarregado.");
|
|
2256
|
+
let paramsOp = [];
|
|
2257
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2258
|
+
paramsOp = await this.logicaComumParametros();
|
|
2259
|
+
}
|
|
2260
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do operador.");
|
|
2261
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do operador.");
|
|
2262
|
+
const indiceAberturaCorpoOp = this.atual - 1;
|
|
2263
|
+
const quantidadeErrosAntesCorpoOp = this.erros.length;
|
|
2264
|
+
let corpoOp = [];
|
|
2265
|
+
try {
|
|
2266
|
+
corpoOp = await this.blocoEscopo();
|
|
2267
|
+
}
|
|
2268
|
+
catch (erro) {
|
|
2269
|
+
this.erros.push(erro);
|
|
2270
|
+
}
|
|
2271
|
+
if (this.erros.length > quantidadeErrosAntesCorpoOp) {
|
|
2272
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoOp);
|
|
2273
|
+
corpoOp = [];
|
|
2274
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2275
|
+
}
|
|
2276
|
+
const corpoFuncaoOp = new construtos_1.FuncaoConstruto(this.hashArquivo, simboloNomeMetodo.linha, paramsOp, corpoOp);
|
|
2277
|
+
const metodoOp = new declaracoes_1.FuncaoDeclaracao(simboloNomeMetodo, corpoFuncaoOp);
|
|
2278
|
+
metodoOp.estatico = ehEstatico;
|
|
2279
|
+
metodoOp.acesso = modificadorAcesso;
|
|
2280
|
+
metodoOp.documentacao = docAtual;
|
|
2281
|
+
metodos.push(metodoOp);
|
|
2282
|
+
this.pilhaDecoradores = [];
|
|
2283
|
+
}
|
|
2284
|
+
async analisarMembroMetodo(ehEstatico, modificadorAcesso, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, docAtual) {
|
|
2285
|
+
const nomeMetodo = this.avancarEDevolverAnterior();
|
|
2286
|
+
// Pré-registrar para suportar chamadas recursivas (igual a funcao()).
|
|
2287
|
+
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, 'qualquer'));
|
|
2288
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
|
|
2289
|
+
let params = [];
|
|
2290
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2291
|
+
params = await this.logicaComumParametros();
|
|
2292
|
+
}
|
|
2293
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do método.");
|
|
2294
|
+
let tipoRetorno = 'qualquer';
|
|
2295
|
+
let definicaoExplicitaDeTipo = false;
|
|
2296
|
+
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
|
|
2297
|
+
tipoRetorno = this.verificarDefinicaoTipoAtual();
|
|
2298
|
+
this.avancarEDevolverAnterior();
|
|
2299
|
+
definicaoExplicitaDeTipo = true;
|
|
2300
|
+
}
|
|
2301
|
+
if (ehEstrangeira && this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
2302
|
+
throw this.erro(this.simbolos[this.atual], 'Métodos de classe estrangeira não podem ter corpo.');
|
|
2303
|
+
}
|
|
2304
|
+
// Método é abstrato quando: (a) está dentro de um bloco `abstrato {}`,
|
|
2305
|
+
// ou (b) a classe é abstrata/estrangeira e o próximo token não é `{`.
|
|
2306
|
+
const ehAbstrato = ehAbstratoPadrao ||
|
|
2307
|
+
ehEstrangeira ||
|
|
2308
|
+
(ehAbstrata && !this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA));
|
|
2309
|
+
if (ehAbstrato) {
|
|
2310
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2311
|
+
const corpoVazio = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, [], tipoRetorno, definicaoExplicitaDeTipo);
|
|
2312
|
+
const metodoAbstrato = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoVazio, tipoRetorno);
|
|
2313
|
+
metodoAbstrato.estatico = ehEstatico;
|
|
2314
|
+
metodoAbstrato.abstrato = true;
|
|
2315
|
+
metodoAbstrato.acesso = modificadorAcesso;
|
|
2316
|
+
metodoAbstrato.decoradores = Array.from(this.pilhaDecoradores);
|
|
2317
|
+
metodoAbstrato.documentacao = docAtual;
|
|
2318
|
+
metodos.push(metodoAbstrato);
|
|
2319
|
+
}
|
|
2320
|
+
else {
|
|
2321
|
+
// Método concreto: com corpo. Inferência de tipo de retorno igual a corpoDaFuncao().
|
|
2322
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do método.");
|
|
2323
|
+
const indiceAberturaCorpo = this.atual - 1;
|
|
2324
|
+
const quantidadeErrosAntesCorpo = this.erros.length;
|
|
2325
|
+
let corpo = [];
|
|
2326
|
+
try {
|
|
2327
|
+
corpo = await this.blocoEscopo();
|
|
2328
|
+
}
|
|
2329
|
+
catch (erro) {
|
|
2330
|
+
this.erros.push(erro);
|
|
2331
|
+
}
|
|
2332
|
+
if (this.erros.length > quantidadeErrosAntesCorpo) {
|
|
2333
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpo);
|
|
2334
|
+
corpo = [];
|
|
2335
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2336
|
+
}
|
|
2337
|
+
let expressoesRetorna = [];
|
|
2338
|
+
for (const declaracao of corpo) {
|
|
2339
|
+
expressoesRetorna = expressoesRetorna.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
2340
|
+
}
|
|
2341
|
+
const tiposRetornos = new Set(expressoesRetorna.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
|
|
2342
|
+
const retornaChamadoExplicitamente = tiposRetornos.size > 0;
|
|
2343
|
+
tiposRetornos.delete('qualquer');
|
|
2344
|
+
if (tipoRetorno === 'qualquer') {
|
|
2345
|
+
if (tiposRetornos.size > 0) {
|
|
2346
|
+
tipoRetorno = tiposRetornos.values().next().value;
|
|
2347
|
+
}
|
|
2348
|
+
else if (!retornaChamadoExplicitamente && !definicaoExplicitaDeTipo) {
|
|
2349
|
+
tipoRetorno = 'vazio';
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
const corpoFuncao = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, corpo, tipoRetorno);
|
|
2353
|
+
const tipoDaFuncao = `função<${tipoRetorno}>`;
|
|
2354
|
+
const metodo = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoFuncao, tipoDaFuncao);
|
|
2355
|
+
metodo.estatico = ehEstatico;
|
|
2356
|
+
metodo.acesso = modificadorAcesso;
|
|
2357
|
+
metodo.decoradores = Array.from(this.pilhaDecoradores);
|
|
2358
|
+
metodo.documentacao = docAtual;
|
|
2359
|
+
metodos.push(metodo);
|
|
2360
|
+
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, tipoDaFuncao));
|
|
2361
|
+
this.pilhaEscopos.registrarReferenciaFuncao(nomeMetodo.lexema, metodo);
|
|
2362
|
+
}
|
|
2363
|
+
this.pilhaDecoradores = [];
|
|
2364
|
+
}
|
|
2365
|
+
async analisarMembroPropriedade(ehEstatico, modificadorAcesso, metodos, propriedades, docAtual) {
|
|
2366
|
+
const nomePropriedade = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado identificador para nome de propriedade.');
|
|
2367
|
+
this.consumir(delegua_2.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade.');
|
|
2368
|
+
const tipoPropriedade = this.avancarEDevolverAnterior();
|
|
2369
|
+
let nomeTipoPropriedade = tipoPropriedade.lexema;
|
|
2370
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.COLCHETE_ESQUERDO)) {
|
|
2371
|
+
this.avancarEDevolverAnterior();
|
|
2372
|
+
this.consumir(delegua_2.default.COLCHETE_DIREITO, "Esperado ']' após '[' na definição do tipo de propriedade.");
|
|
2373
|
+
nomeTipoPropriedade = `${nomeTipoPropriedade}[]`;
|
|
2374
|
+
}
|
|
2375
|
+
const prop = new declaracoes_1.PropriedadeClasse(nomePropriedade, nomeTipoPropriedade, Array.from(this.pilhaDecoradores), modificadorAcesso, ehEstatico);
|
|
2376
|
+
prop.documentacao = docAtual;
|
|
2377
|
+
// Auto-propriedade: `nome: tipo { obter; definir; }`
|
|
2378
|
+
// Ou corpo personalizado: `nome: tipo { obter() { ... } definir(valor) { ... } }`
|
|
2379
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
2380
|
+
this.avancarEDevolverAnterior();
|
|
2381
|
+
let temCorpoPersonalizado = false;
|
|
2382
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) && !this.estaNoFinal()) {
|
|
2383
|
+
const lexema = String(this.simbolos[this.atual].lexema || '').toLowerCase();
|
|
2384
|
+
if (lexema === 'obter' || lexema === 'definir') {
|
|
2385
|
+
const ehObter = lexema === 'obter';
|
|
2386
|
+
this.avancarEDevolverAnterior();
|
|
2387
|
+
if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
|
|
2388
|
+
// Corpo personalizado: obter() { ... } / definir(valor) { ... }
|
|
2389
|
+
temCorpoPersonalizado = true;
|
|
2390
|
+
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após acessor.");
|
|
2391
|
+
let paramsAcessor = [];
|
|
2392
|
+
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2393
|
+
paramsAcessor = await this.logicaComumParametros();
|
|
2394
|
+
}
|
|
2395
|
+
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do acessor.");
|
|
2396
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do acessor.");
|
|
2397
|
+
const indiceAberturaCorpoAcessor = this.atual - 1;
|
|
2398
|
+
const quantidadeErrosAntesCorpoAcessor = this.erros.length;
|
|
2399
|
+
let corpoAcessor = [];
|
|
2400
|
+
try {
|
|
2401
|
+
corpoAcessor = await this.blocoEscopo();
|
|
2402
|
+
}
|
|
2403
|
+
catch (erro) {
|
|
2404
|
+
this.erros.push(erro);
|
|
2405
|
+
}
|
|
2406
|
+
if (this.erros.length > quantidadeErrosAntesCorpoAcessor) {
|
|
2407
|
+
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoAcessor);
|
|
2408
|
+
corpoAcessor = [];
|
|
2409
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2410
|
+
}
|
|
2411
|
+
let tipoAcessor = 'qualquer';
|
|
2412
|
+
let expressoesRetornaAcessor = [];
|
|
2413
|
+
for (const declaracao of corpoAcessor) {
|
|
2414
|
+
expressoesRetornaAcessor = expressoesRetornaAcessor.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
2415
|
+
}
|
|
2416
|
+
const tiposRetornosAcessor = new Set(expressoesRetornaAcessor.filter((e) => e.tipo !== 'qualquer').map((e) => e.tipo));
|
|
2417
|
+
const retornaExplicitamenteAcessor = tiposRetornosAcessor.size > 0;
|
|
2418
|
+
tiposRetornosAcessor.delete('qualquer');
|
|
2419
|
+
if (tiposRetornosAcessor.size > 0) {
|
|
2420
|
+
tipoAcessor = tiposRetornosAcessor.values().next().value;
|
|
2421
|
+
}
|
|
2422
|
+
else if (!retornaExplicitamenteAcessor) {
|
|
2423
|
+
tipoAcessor = 'vazio';
|
|
2424
|
+
}
|
|
2425
|
+
const corpoFuncaoAcessor = new construtos_1.FuncaoConstruto(this.hashArquivo, nomePropriedade.linha, paramsAcessor, corpoAcessor, tipoAcessor);
|
|
2426
|
+
const tipoDaFuncaoAcessor = `função<${tipoAcessor}>`;
|
|
2427
|
+
const metodoAcessor = new declaracoes_1.FuncaoDeclaracao(nomePropriedade, corpoFuncaoAcessor, tipoDaFuncaoAcessor);
|
|
2428
|
+
metodoAcessor.estatico = ehEstatico;
|
|
2429
|
+
metodoAcessor.acesso = modificadorAcesso;
|
|
2430
|
+
metodoAcessor.eObtenedor = ehObter;
|
|
2431
|
+
metodoAcessor.eDefinidor = !ehObter;
|
|
2432
|
+
metodos.push(metodoAcessor);
|
|
2433
|
+
}
|
|
2434
|
+
else {
|
|
2435
|
+
// Forma trivial: obter; / definir;
|
|
2436
|
+
if (ehObter) {
|
|
2437
|
+
prop.autoObter = true;
|
|
2438
|
+
}
|
|
2439
|
+
else {
|
|
2440
|
+
prop.autoDefinir = true;
|
|
2441
|
+
}
|
|
2442
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
else {
|
|
2446
|
+
break;
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após acessores da propriedade.");
|
|
2450
|
+
// Corpo personalizado: obtenedor/definidor são métodos — não há campos base a declarar.
|
|
2451
|
+
// Para auto-propriedades, o campo base iniciado por '_' é criado em tempo de execução com base
|
|
2452
|
+
// nos indicadores autoObter/autoDefinir. O avaliador sintático usa o nome original ('nome').
|
|
2453
|
+
if (!temCorpoPersonalizado) {
|
|
2454
|
+
propriedades.push(prop);
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
else {
|
|
2458
|
+
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2459
|
+
propriedades.push(prop);
|
|
2460
|
+
}
|
|
2461
|
+
this.pilhaDecoradores = [];
|
|
2462
|
+
}
|
|
2463
|
+
async compreenderMembros(acessoPadrao, ehEstaticoPadrao, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades) {
|
|
2464
|
+
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
|
|
2465
|
+
!this.estaNoFinal()) {
|
|
2466
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.COMENTARIO ||
|
|
2467
|
+
this.simbolos[this.atual].tipo === delegua_2.default.LINHA_COMENTARIO) {
|
|
2468
|
+
this.avancarEDevolverAnterior();
|
|
2469
|
+
continue;
|
|
2470
|
+
}
|
|
2471
|
+
let docAtual = undefined;
|
|
2472
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.DOCUMENTARIO) {
|
|
2473
|
+
const simboloDoc = this.avancarEDevolverAnterior();
|
|
2474
|
+
docAtual = new construtos_1.ComentarioComoConstruto(simboloDoc);
|
|
2475
|
+
}
|
|
2476
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.ARROBA) {
|
|
2477
|
+
await this.resolverDecoradores();
|
|
2478
|
+
continue;
|
|
2479
|
+
}
|
|
2480
|
+
const tipoAtual = this.simbolos[this.atual].tipo;
|
|
2481
|
+
const tipoProximo = this.simbolos[this.atual + 1]?.tipo;
|
|
2482
|
+
const ehBlocoAcesso = [delegua_2.default.PRIVADO, delegua_2.default.PROTEGIDO].includes(tipoAtual) &&
|
|
2483
|
+
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
2484
|
+
const ehBlocoEstatico = tipoAtual === delegua_2.default.ESTATICO && tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
2485
|
+
const ehBlocoAbstrato = tipoAtual === delegua_2.default.ABSTRATO && tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
2486
|
+
if (ehBlocoAcesso) {
|
|
2487
|
+
const novoAcesso = tipoAtual === delegua_2.default.PRIVADO ? 'privado' : 'protegido';
|
|
2488
|
+
this.avancarEDevolverAnterior();
|
|
2489
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após modificador de acesso de bloco.");
|
|
2490
|
+
await this.compreenderMembros(novoAcesso, ehEstaticoPadrao, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
2491
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco de modificador de acesso.");
|
|
2492
|
+
continue;
|
|
2493
|
+
}
|
|
2494
|
+
if (ehBlocoEstatico) {
|
|
2495
|
+
this.avancarEDevolverAnterior();
|
|
2496
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'estático'.");
|
|
2497
|
+
await this.compreenderMembros(acessoPadrao, true, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
2498
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco estático.");
|
|
2499
|
+
continue;
|
|
2500
|
+
}
|
|
2501
|
+
if (ehBlocoAbstrato) {
|
|
2502
|
+
this.avancarEDevolverAnterior();
|
|
2503
|
+
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'abstrato'.");
|
|
2504
|
+
await this.compreenderMembros(acessoPadrao, ehEstaticoPadrao, true, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
2505
|
+
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco abstrato.");
|
|
2506
|
+
continue;
|
|
2507
|
+
}
|
|
2508
|
+
const modificadorAcesso = acessoPadrao;
|
|
2509
|
+
const ehEstatico = ehEstaticoPadrao;
|
|
2510
|
+
if (this.simbolos[this.atual].tipo === delegua_2.default.OPERADOR) {
|
|
2511
|
+
await this.analisarMembroOperador(ehEstatico, modificadorAcesso, metodos, docAtual);
|
|
2512
|
+
continue;
|
|
2513
|
+
}
|
|
2514
|
+
const proximoSimbolo = this.simbolos[this.atual + 1];
|
|
2515
|
+
switch (proximoSimbolo?.tipo) {
|
|
2516
|
+
case delegua_2.default.PARENTESE_ESQUERDO:
|
|
2517
|
+
await this.analisarMembroMetodo(ehEstatico, modificadorAcesso, ehAbstratoPadrao, ehAbstrata, ehEstrangeira, metodos, docAtual);
|
|
2518
|
+
break;
|
|
2519
|
+
case delegua_2.default.DOIS_PONTOS:
|
|
2520
|
+
await this.analisarMembroPropriedade(ehEstatico, modificadorAcesso, metodos, propriedades, docAtual);
|
|
2521
|
+
break;
|
|
2522
|
+
default:
|
|
2523
|
+
throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2244
2527
|
async declaracaoDeClasse() {
|
|
2245
2528
|
// Modificadores opcionais no nível da classe: `abstrata`, `estrangeira` e/ou `estática`.
|
|
2246
2529
|
// Sintaxe: `classe abstrata NomeDaClasse`, `classe estrangeira NomeDaClasse`, etc.
|
|
@@ -2292,314 +2575,8 @@ class AvaliadorSintatico extends avaliador_sintatico_base_1.AvaliadorSintaticoBa
|
|
|
2292
2575
|
this.pilhaDecoradores = [];
|
|
2293
2576
|
const metodos = [];
|
|
2294
2577
|
const propriedades = [];
|
|
2295
|
-
/**
|
|
2296
|
-
* Analisa membros do corpo da classe com um contexto de acesso e estático padrão.
|
|
2297
|
-
* Suporta blocos de contexto aninhados: `estático { }`, `abstrato { }`, `privado { }`, `protegido { }`, `publico { }`.
|
|
2298
|
-
*/
|
|
2299
|
-
const compreenderMembros = async (acessoPadrao, ehEstaticoPadrao, ehAbstratoPadrao = false) => {
|
|
2300
|
-
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
|
|
2301
|
-
!this.estaNoFinal()) {
|
|
2302
|
-
// Pular comentários normais dentro do corpo da classe.
|
|
2303
|
-
if (this.simbolos[this.atual].tipo === delegua_2.default.COMENTARIO ||
|
|
2304
|
-
this.simbolos[this.atual].tipo === delegua_2.default.LINHA_COMENTARIO) {
|
|
2305
|
-
this.avancarEDevolverAnterior();
|
|
2306
|
-
continue;
|
|
2307
|
-
}
|
|
2308
|
-
// Documentário (/** ... */)
|
|
2309
|
-
let docAtual = undefined;
|
|
2310
|
-
if (this.simbolos[this.atual].tipo === delegua_2.default.DOCUMENTARIO) {
|
|
2311
|
-
const simboloDoc = this.avancarEDevolverAnterior();
|
|
2312
|
-
docAtual = new construtos_1.ComentarioComoConstruto(simboloDoc);
|
|
2313
|
-
}
|
|
2314
|
-
// Decorador
|
|
2315
|
-
if (this.simbolos[this.atual].tipo === delegua_2.default.ARROBA) {
|
|
2316
|
-
await this.resolverDecoradores();
|
|
2317
|
-
continue;
|
|
2318
|
-
}
|
|
2319
|
-
// Detecção de bloco de contexto: modificador seguido de '{'
|
|
2320
|
-
const tipoAtual = this.simbolos[this.atual].tipo;
|
|
2321
|
-
const tipoProximo = this.simbolos[this.atual + 1]?.tipo;
|
|
2322
|
-
const ehBlocoAcesso = [delegua_2.default.PRIVADO, delegua_2.default.PROTEGIDO].includes(tipoAtual) &&
|
|
2323
|
-
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
2324
|
-
const ehBlocoEstatico = tipoAtual === delegua_2.default.ESTATICO &&
|
|
2325
|
-
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
2326
|
-
const ehBlocoAbstrato = tipoAtual === delegua_2.default.ABSTRATO &&
|
|
2327
|
-
tipoProximo === delegua_2.default.CHAVE_ESQUERDA;
|
|
2328
|
-
if (ehBlocoAcesso) {
|
|
2329
|
-
const novoAcesso = tipoAtual === delegua_2.default.PRIVADO ? 'privado' : 'protegido';
|
|
2330
|
-
this.avancarEDevolverAnterior(); // consume modificador de acesso
|
|
2331
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após modificador de acesso de bloco.");
|
|
2332
|
-
await compreenderMembros(novoAcesso, ehEstaticoPadrao, ehAbstratoPadrao);
|
|
2333
|
-
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco de modificador de acesso.");
|
|
2334
|
-
continue;
|
|
2335
|
-
}
|
|
2336
|
-
if (ehBlocoEstatico) {
|
|
2337
|
-
this.avancarEDevolverAnterior(); // consume 'estático'
|
|
2338
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'estático'.");
|
|
2339
|
-
await compreenderMembros(acessoPadrao, true, ehAbstratoPadrao);
|
|
2340
|
-
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco estático.");
|
|
2341
|
-
continue;
|
|
2342
|
-
}
|
|
2343
|
-
if (ehBlocoAbstrato) {
|
|
2344
|
-
this.avancarEDevolverAnterior(); // consume 'abstrato'
|
|
2345
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' após 'abstrato'.");
|
|
2346
|
-
await compreenderMembros(acessoPadrao, ehEstaticoPadrao, true);
|
|
2347
|
-
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' para fechar bloco abstrato.");
|
|
2348
|
-
continue;
|
|
2349
|
-
}
|
|
2350
|
-
const modificadorAcesso = acessoPadrao;
|
|
2351
|
-
const ehEstatico = ehEstaticoPadrao;
|
|
2352
|
-
// Método operador sobrecarregado: `operador+ (outro) { ... }`
|
|
2353
|
-
if (this.simbolos[this.atual].tipo === delegua_2.default.OPERADOR) {
|
|
2354
|
-
const simboloOperadorKeyword = this.avancarEDevolverAnterior();
|
|
2355
|
-
const simboloDoOperador = this.avancarEDevolverAnterior();
|
|
2356
|
-
const nomeMetodoOp = 'operador' + simboloDoOperador.lexema;
|
|
2357
|
-
const simboloNomeMetodo = {
|
|
2358
|
-
tipo: delegua_2.default.IDENTIFICADOR,
|
|
2359
|
-
lexema: nomeMetodoOp,
|
|
2360
|
-
literal: null,
|
|
2361
|
-
linha: simboloOperadorKeyword.linha,
|
|
2362
|
-
hashArquivo: this.hashArquivo,
|
|
2363
|
-
};
|
|
2364
|
-
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após operador sobrecarregado.");
|
|
2365
|
-
let paramsOp = [];
|
|
2366
|
-
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2367
|
-
paramsOp = await this.logicaComumParametros();
|
|
2368
|
-
}
|
|
2369
|
-
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do operador.");
|
|
2370
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do operador.");
|
|
2371
|
-
const indiceAberturaCorpoOp = this.atual - 1;
|
|
2372
|
-
const quantidadeErrosAntesCorpoOp = this.erros.length;
|
|
2373
|
-
let corpoOp = [];
|
|
2374
|
-
try {
|
|
2375
|
-
corpoOp = await this.blocoEscopo();
|
|
2376
|
-
}
|
|
2377
|
-
catch (erro) {
|
|
2378
|
-
this.erros.push(erro);
|
|
2379
|
-
}
|
|
2380
|
-
if (this.erros.length > quantidadeErrosAntesCorpoOp) {
|
|
2381
|
-
this.atual =
|
|
2382
|
-
this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoOp);
|
|
2383
|
-
corpoOp = [];
|
|
2384
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2385
|
-
}
|
|
2386
|
-
const corpoFuncaoOp = new construtos_1.FuncaoConstruto(this.hashArquivo, simboloNomeMetodo.linha, paramsOp, corpoOp);
|
|
2387
|
-
const metodoOp = new declaracoes_1.FuncaoDeclaracao(simboloNomeMetodo, corpoFuncaoOp);
|
|
2388
|
-
metodoOp.estatico = ehEstatico;
|
|
2389
|
-
metodoOp.acesso = modificadorAcesso;
|
|
2390
|
-
metodoOp.documentacao = docAtual;
|
|
2391
|
-
metodos.push(metodoOp);
|
|
2392
|
-
this.pilhaDecoradores = [];
|
|
2393
|
-
continue;
|
|
2394
|
-
}
|
|
2395
|
-
// Método ou propriedade, determinado pelo token seguinte ao nome
|
|
2396
|
-
const proximoSimbolo = this.simbolos[this.atual + 1];
|
|
2397
|
-
switch (proximoSimbolo?.tipo) {
|
|
2398
|
-
case delegua_2.default.PARENTESE_ESQUERDO: {
|
|
2399
|
-
// Analisa: nome ( params ) [abstrato] [: tipoRetorno] { corpo }
|
|
2400
|
-
const nomeMetodo = this.avancarEDevolverAnterior();
|
|
2401
|
-
// Pré-registrar para suportar chamadas recursivas (igual a funcao()).
|
|
2402
|
-
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, 'qualquer'));
|
|
2403
|
-
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após nome do método.");
|
|
2404
|
-
let params = [];
|
|
2405
|
-
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2406
|
-
params = await this.logicaComumParametros();
|
|
2407
|
-
}
|
|
2408
|
-
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do método.");
|
|
2409
|
-
// Tipo de retorno opcional (igual a corpoDaFuncao())
|
|
2410
|
-
let tipoRetorno = 'qualquer';
|
|
2411
|
-
let definicaoExplicitaDeTipo = false;
|
|
2412
|
-
if (this.verificarSeSimboloAtualEIgualA(delegua_2.default.DOIS_PONTOS)) {
|
|
2413
|
-
tipoRetorno = this.verificarDefinicaoTipoAtual();
|
|
2414
|
-
this.avancarEDevolverAnterior();
|
|
2415
|
-
definicaoExplicitaDeTipo = true;
|
|
2416
|
-
}
|
|
2417
|
-
// Método de classe estrangeira não pode ter corpo.
|
|
2418
|
-
if (ehEstrangeira &&
|
|
2419
|
-
this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
2420
|
-
throw this.erro(this.simbolos[this.atual], 'Métodos de classe estrangeira não podem ter corpo.');
|
|
2421
|
-
}
|
|
2422
|
-
// Método é abstrato quando: (a) está dentro de um bloco `abstrato {}`,
|
|
2423
|
-
// ou (b) a classe é abstrata/estrangeira e o próximo token não é `{`.
|
|
2424
|
-
const ehAbstrato = ehAbstratoPadrao ||
|
|
2425
|
-
ehEstrangeira ||
|
|
2426
|
-
(ehAbstrata &&
|
|
2427
|
-
!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA));
|
|
2428
|
-
if (ehAbstrato) {
|
|
2429
|
-
// Método abstrato/estrangeiro: sem corpo
|
|
2430
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2431
|
-
const corpoVazio = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, [], tipoRetorno, definicaoExplicitaDeTipo);
|
|
2432
|
-
const metodoAbstrato = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoVazio, tipoRetorno);
|
|
2433
|
-
metodoAbstrato.estatico = ehEstatico;
|
|
2434
|
-
metodoAbstrato.abstrato = true;
|
|
2435
|
-
metodoAbstrato.acesso = modificadorAcesso;
|
|
2436
|
-
metodoAbstrato.documentacao = docAtual;
|
|
2437
|
-
metodos.push(metodoAbstrato);
|
|
2438
|
-
}
|
|
2439
|
-
else {
|
|
2440
|
-
// Método concreto: com corpo.
|
|
2441
|
-
// Inferência de tipo de retorno igual a corpoDaFuncao().
|
|
2442
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do método.");
|
|
2443
|
-
const indiceAberturaCorpo = this.atual - 1;
|
|
2444
|
-
const quantidadeErrosAntesCorpo = this.erros.length;
|
|
2445
|
-
let corpo = [];
|
|
2446
|
-
try {
|
|
2447
|
-
corpo = await this.blocoEscopo();
|
|
2448
|
-
}
|
|
2449
|
-
catch (erro) {
|
|
2450
|
-
this.erros.push(erro);
|
|
2451
|
-
}
|
|
2452
|
-
if (this.erros.length > quantidadeErrosAntesCorpo) {
|
|
2453
|
-
this.atual =
|
|
2454
|
-
this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpo);
|
|
2455
|
-
corpo = [];
|
|
2456
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2457
|
-
}
|
|
2458
|
-
let expressoesRetorna = [];
|
|
2459
|
-
for (const declaracao of corpo) {
|
|
2460
|
-
expressoesRetorna = expressoesRetorna.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
2461
|
-
}
|
|
2462
|
-
const tiposRetornos = new Set(expressoesRetorna
|
|
2463
|
-
.filter((e) => e.tipo !== 'qualquer')
|
|
2464
|
-
.map((e) => e.tipo));
|
|
2465
|
-
const retornaChamadoExplicitamente = tiposRetornos.size > 0;
|
|
2466
|
-
tiposRetornos.delete('qualquer');
|
|
2467
|
-
if (tipoRetorno === 'qualquer') {
|
|
2468
|
-
if (tiposRetornos.size > 0) {
|
|
2469
|
-
tipoRetorno = tiposRetornos.values().next().value;
|
|
2470
|
-
}
|
|
2471
|
-
else if (!retornaChamadoExplicitamente &&
|
|
2472
|
-
!definicaoExplicitaDeTipo) {
|
|
2473
|
-
tipoRetorno = 'vazio';
|
|
2474
|
-
}
|
|
2475
|
-
}
|
|
2476
|
-
const corpoFuncao = new construtos_1.FuncaoConstruto(this.hashArquivo, nomeMetodo.linha, params, corpo, tipoRetorno);
|
|
2477
|
-
const tipoDaFuncao = `função<${tipoRetorno}>`;
|
|
2478
|
-
const metodo = new declaracoes_1.FuncaoDeclaracao(nomeMetodo, corpoFuncao, tipoDaFuncao);
|
|
2479
|
-
metodo.estatico = ehEstatico;
|
|
2480
|
-
metodo.acesso = modificadorAcesso;
|
|
2481
|
-
metodo.decoradores = Array.from(this.pilhaDecoradores);
|
|
2482
|
-
metodo.documentacao = docAtual;
|
|
2483
|
-
metodos.push(metodo);
|
|
2484
|
-
this.pilhaEscopos.definirInformacoesVariavel(nomeMetodo.lexema, new informacao_elemento_sintatico_1.InformacaoElementoSintatico(nomeMetodo.lexema, tipoDaFuncao));
|
|
2485
|
-
this.pilhaEscopos.registrarReferenciaFuncao(nomeMetodo.lexema, metodo);
|
|
2486
|
-
}
|
|
2487
|
-
this.pilhaDecoradores = [];
|
|
2488
|
-
break;
|
|
2489
|
-
}
|
|
2490
|
-
case delegua_2.default.DOIS_PONTOS: {
|
|
2491
|
-
const nomePropriedade = this.consumir(delegua_2.default.IDENTIFICADOR, 'Esperado identificador para nome de propriedade.');
|
|
2492
|
-
this.consumir(delegua_2.default.DOIS_PONTOS, 'Esperado dois-pontos após nome de propriedade.');
|
|
2493
|
-
const tipoPropriedade = this.avancarEDevolverAnterior();
|
|
2494
|
-
let nomeTipoPropriedade = tipoPropriedade.lexema;
|
|
2495
|
-
if (this.verificarTipoSimboloAtual(delegua_2.default.COLCHETE_ESQUERDO)) {
|
|
2496
|
-
this.avancarEDevolverAnterior(); // consume '['
|
|
2497
|
-
this.consumir(delegua_2.default.COLCHETE_DIREITO, "Esperado ']' após '[' na definição do tipo de propriedade.");
|
|
2498
|
-
nomeTipoPropriedade = `${nomeTipoPropriedade}[]`;
|
|
2499
|
-
}
|
|
2500
|
-
const prop = new declaracoes_1.PropriedadeClasse(nomePropriedade, nomeTipoPropriedade, Array.from(this.pilhaDecoradores), modificadorAcesso, ehEstatico);
|
|
2501
|
-
prop.documentacao = docAtual;
|
|
2502
|
-
// Auto-propriedade: `nome: tipo { obter; definir; }`
|
|
2503
|
-
// Ou corpo personalizado: `nome: tipo { obter() { ... } definir(valor) { ... } }`
|
|
2504
|
-
if (this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_ESQUERDA)) {
|
|
2505
|
-
this.avancarEDevolverAnterior(); // consume '{'
|
|
2506
|
-
let temCorpoPersonalizado = false;
|
|
2507
|
-
while (!this.verificarTipoSimboloAtual(delegua_2.default.CHAVE_DIREITA) &&
|
|
2508
|
-
!this.estaNoFinal()) {
|
|
2509
|
-
const lexema = String(this.simbolos[this.atual].lexema || '').toLowerCase();
|
|
2510
|
-
if (lexema === 'obter' || lexema === 'definir') {
|
|
2511
|
-
const ehObter = lexema === 'obter';
|
|
2512
|
-
this.avancarEDevolverAnterior(); // consume 'obter' / 'definir'
|
|
2513
|
-
if (this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_ESQUERDO)) {
|
|
2514
|
-
// Corpo personalizado: obter() { ... } / definir(valor) { ... }
|
|
2515
|
-
temCorpoPersonalizado = true;
|
|
2516
|
-
this.consumir(delegua_2.default.PARENTESE_ESQUERDO, "Esperado '(' após acessor.");
|
|
2517
|
-
let paramsAcessor = [];
|
|
2518
|
-
if (!this.verificarTipoSimboloAtual(delegua_2.default.PARENTESE_DIREITO)) {
|
|
2519
|
-
paramsAcessor = await this.logicaComumParametros();
|
|
2520
|
-
}
|
|
2521
|
-
this.consumir(delegua_2.default.PARENTESE_DIREITO, "Esperado ')' após parâmetros do acessor.");
|
|
2522
|
-
this.consumir(delegua_2.default.CHAVE_ESQUERDA, "Esperado '{' antes do corpo do acessor.");
|
|
2523
|
-
const indiceAberturaCorpoAcessor = this.atual - 1;
|
|
2524
|
-
const quantidadeErrosAntesCorpoAcessor = this.erros.length;
|
|
2525
|
-
let corpoAcessor = [];
|
|
2526
|
-
try {
|
|
2527
|
-
corpoAcessor = await this.blocoEscopo();
|
|
2528
|
-
}
|
|
2529
|
-
catch (erro) {
|
|
2530
|
-
this.erros.push(erro);
|
|
2531
|
-
}
|
|
2532
|
-
if (this.erros.length > quantidadeErrosAntesCorpoAcessor) {
|
|
2533
|
-
this.atual = this.encontrarIndiceAposFechamentoDeBloco(indiceAberturaCorpoAcessor);
|
|
2534
|
-
corpoAcessor = [];
|
|
2535
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2536
|
-
}
|
|
2537
|
-
// Inferência de tipo de retorno
|
|
2538
|
-
let tipoAcessor = 'qualquer';
|
|
2539
|
-
let expressoesRetornaAcessor = [];
|
|
2540
|
-
for (const declaracao of corpoAcessor) {
|
|
2541
|
-
expressoesRetornaAcessor =
|
|
2542
|
-
expressoesRetornaAcessor.concat((0, comum_1.buscarRetornos)(declaracao));
|
|
2543
|
-
}
|
|
2544
|
-
const tiposRetornosAcessor = new Set(expressoesRetornaAcessor
|
|
2545
|
-
.filter((e) => e.tipo !== 'qualquer')
|
|
2546
|
-
.map((e) => e.tipo));
|
|
2547
|
-
const retornaExplicitamenteAcessor = tiposRetornosAcessor.size > 0;
|
|
2548
|
-
tiposRetornosAcessor.delete('qualquer');
|
|
2549
|
-
if (tiposRetornosAcessor.size > 0) {
|
|
2550
|
-
tipoAcessor = tiposRetornosAcessor
|
|
2551
|
-
.values()
|
|
2552
|
-
.next().value;
|
|
2553
|
-
}
|
|
2554
|
-
else if (!retornaExplicitamenteAcessor) {
|
|
2555
|
-
tipoAcessor = 'vazio';
|
|
2556
|
-
}
|
|
2557
|
-
const corpoFuncaoAcessor = new construtos_1.FuncaoConstruto(this.hashArquivo, nomePropriedade.linha, paramsAcessor, corpoAcessor, tipoAcessor);
|
|
2558
|
-
const tipoDaFuncaoAcessor = `função<${tipoAcessor}>`;
|
|
2559
|
-
const metodoAcessor = new declaracoes_1.FuncaoDeclaracao(nomePropriedade, corpoFuncaoAcessor, tipoDaFuncaoAcessor);
|
|
2560
|
-
metodoAcessor.estatico = ehEstatico;
|
|
2561
|
-
metodoAcessor.acesso = modificadorAcesso;
|
|
2562
|
-
metodoAcessor.eObtenedor = ehObter;
|
|
2563
|
-
metodoAcessor.eDefinidor = !ehObter;
|
|
2564
|
-
metodos.push(metodoAcessor);
|
|
2565
|
-
}
|
|
2566
|
-
else {
|
|
2567
|
-
// Forma trivial: obter; / definir;
|
|
2568
|
-
if (ehObter) {
|
|
2569
|
-
prop.autoObter = true;
|
|
2570
|
-
}
|
|
2571
|
-
else {
|
|
2572
|
-
prop.autoDefinir = true;
|
|
2573
|
-
}
|
|
2574
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2575
|
-
}
|
|
2576
|
-
}
|
|
2577
|
-
else {
|
|
2578
|
-
break;
|
|
2579
|
-
}
|
|
2580
|
-
}
|
|
2581
|
-
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após acessores da propriedade.");
|
|
2582
|
-
// Corpo personalizado: obtenedor/definidor são métodos — não há campos base a declarar.
|
|
2583
|
-
// Para auto-propriedades, o campo base iniciado por '_' é criado em tempo de execução com base
|
|
2584
|
-
// nos indicadores autoObter/autoDefinir. O avaliador sintático usa o nome original ('nome').
|
|
2585
|
-
if (!temCorpoPersonalizado) {
|
|
2586
|
-
propriedades.push(prop);
|
|
2587
|
-
}
|
|
2588
|
-
}
|
|
2589
|
-
else {
|
|
2590
|
-
this.verificarSeSimboloAtualEIgualA(delegua_2.default.PONTO_E_VIRGULA);
|
|
2591
|
-
propriedades.push(prop);
|
|
2592
|
-
}
|
|
2593
|
-
this.pilhaDecoradores = [];
|
|
2594
|
-
break;
|
|
2595
|
-
}
|
|
2596
|
-
default:
|
|
2597
|
-
throw this.erro(this.simbolos[this.atual], 'Esperado definição de método ou propriedade.');
|
|
2598
|
-
}
|
|
2599
|
-
}
|
|
2600
|
-
};
|
|
2601
2578
|
this.metodosClasseAtualEmAnalise = metodos;
|
|
2602
|
-
await compreenderMembros('publico', false);
|
|
2579
|
+
await this.compreenderMembros('publico', false, false, ehAbstrata, ehEstrangeira, metodos, propriedades);
|
|
2603
2580
|
this.consumir(delegua_2.default.CHAVE_DIREITA, "Esperado '}' após o escopo da classe.");
|
|
2604
2581
|
// Verificação em tempo de análise: classe deve implementar todos os contratos das interfaces.
|
|
2605
2582
|
const linhaFinalClasse = this.simbolos[this.atual - 1].linha;
|