eguatech / egua

Linguagem de programação em português, simples e moderna
https://egua.dev/idegua/
MIT License
817 stars 40 forks source link

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

Closed Andre0n closed 1 year ago

Andre0n commented 1 year ago

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;
        }
    }
lucaspompeun commented 1 year ago

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.

lucaspompeun commented 1 year ago

Possível local da correção: https://github.com/eguatech/egua/blob/7b3bb09559b5dd68164ee5e5c98f7b7d99edb8e0/src/parser.js#L702

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.

Andre0n commented 1 year ago

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;
        }
    }
``
Andre0n commented 1 year ago

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));
}
lucaspompeun commented 1 year ago

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

Andre0n commented 1 year ago

Beleza!