eguatech/egua

Bug: É possível declarar funções sem identificador no escopo global.

Closed this issue · 6 comments

No parse.js o método declaration() faz o parse de um função sem nome como um expressionStatementnão entendi a verificação no primeiro if

declaration() {
        try {
            if (
                this.check(tokenTypes.FUNÇÃO) &&
                this.checkNext(tokenTypes.IDENTIFIER)
            ) {
                this.consume(tokenTypes.FUNÇÃO, null);
                return this.function("função");
            }
            if (this.match(tokenTypes.VAR)) return this.varDeclaration();
            if (this.match(tokenTypes.CLASSE)) return this.classDeclaration();

            return this.statement();
        } catch (error) {
            this.synchronize();
            return null;
        }
    }

De fato, com isso o erro sai bem genérico como apenas "[Linha: 3] Erro no fim: Esperado ';' após expressão.".
Isso acontece por falta de uma verificação do identifier, o que leva o parser a não identificar um estado específico e leva para um genérico.

Possível local da correção:

statement() {

Há também a possibilidade da criação de um functionStatement que irá verificar isso. Ou corrigir de maneira mais direta, fazendo a verificação direto no método 'declaration' e trazendo a mensagem de erro mais clara.

Fiz o seguinte, apenas removi a verificação do next token ser um INDENTIFIER

   declaration() {
        try {
            if (this.check(tokenTypes.FUNÇÃO)) {
                this.consume(tokenTypes.FUNÇÃO, null);
                return this.function("função");
            }
            if (this.match(tokenTypes.VAR)) return this.varDeclaration();
            if (this.match(tokenTypes.CLASSE)) return this.classDeclaration();

            return this.statement();
        } catch (error) {
            this.synchronize();
            return null;
        }
    }
``

No function já garante o próximo token ser IDENTIFIER

function(kind) {
   let name = this.consume(tokenTypes.IDENTIFIER, `Esperado nome ${kind}.`);
   return new Stmt.Função(name, this.functionBody(kind));
}

Show, a solução aparenta ser boa e funcional, se quiser fazer um PR, eu já avalio e testo

Beleza!