Ver código fonte

Fix duplicate functions name not throwing an error

-Fix main function declared with parameters not throwing an error
Lucas de Souza 6 anos atrás
pai
commit
a2dcc689da
3 arquivos alterados com 25 adições e 7 exclusões
  1. 3 1
      i18n/pt/error.json
  2. 8 1
      js/ast/error/syntaxErrorFactory.js
  3. 14 5
      js/ast/ivprogParser.js

+ 3 - 1
i18n/pt/error.json

@@ -33,5 +33,7 @@
   "line_outbounds": "Número de linhas $0 é invaálido para a matriz $1 que possui $2 linhas",
   "invalid_infix_op": "Não é possível aplicar a operação $0 entre os tipos $1 e $2",
   "invalid_unary_op": "Não é possível aplicar a operação $0 ao tipo $1",
-  "unknown_op": "Erro interno crítico: Operação $0 desconhecida"
+  "unknown_op": "Erro interno crítico: Operação $0 desconhecida",
+  "duplicate_function": "A função $0 na linha: $1, coluna: $2 já foi definida anteriormente.",
+  "main_parameters": "A função inicio não pode ter parâmetros."
 }

+ 8 - 1
js/ast/error/syntaxErrorFactory.js

@@ -39,7 +39,7 @@ export const SyntaxErrorFactory = Object.freeze({
     const context = [token.line, cmdName];
     return new SyntaxError(LocalizedStrings.getError("invalid_break_command", context));
   },
-  invalid_terminal: () => {
+  invalid_terminal: (token) => {
     const context = [token.text, token.line, token.column];
     return new SyntaxError(LocalizedStrings.getError('invalid_terminal', context));
   },
@@ -55,5 +55,12 @@ export const SyntaxErrorFactory = Object.freeze({
   invalid_id_format: (token) => {
     const context = [token.text, token.line, token.column];
     return new SyntaxError(LocalizedStrings.getError("invalid_id_format", context));
+  },
+  duplicate_function: (token) => {
+    const context = [token.text, token.line, token.column];
+    return new SyntaxError(LocalizedStrings.getError("duplicate_function", context));
+  },
+  main_parameters: () => {
+    return new SyntaxError(LocalizedStrings.getError("main_parameters"));
   }
 });

+ 14 - 5
js/ast/ivprogParser.js

@@ -47,6 +47,7 @@ export class IVProgParser {
     this.parsingArrayDimension = 0;
     this.scope = [];
     this.langFuncs = LanguageService.getCurrentLangFuncs();
+    this.definedFuncsNameList = []
   }
 
   parseTree () {
@@ -203,6 +204,15 @@ export class IVProgParser {
     return true;
   }
 
+  checkFunctionDuplicate (functionID, funcIDToken) {
+    const id = functionID === null ? "$main" : functionID;
+    const index = this.definedFuncsNameList.indexOf(id);
+    if(index !== -1) {
+      throw SyntaxErrorFactory.duplicate_function(funcIDToken);
+    }
+    this.definedFuncsNameList.push(id);
+  }
+
   consumeForSemiColon () {
     const eosToken = this.getToken();
     if (eosToken.type === this.lexerClass.EOS && eosToken.text.match(';')) {
@@ -372,7 +382,6 @@ export class IVProgParser {
     this.checkOpenCurly();
     const beginArray = this.getToken();
     if (this.parsingArrayDimension >= 2) {
-      // TODO: better error message
       throw SyntaxErrorFactory.token_missing_list(`Array dimensions exceed maximum size of 2 at line ${beginArray.line}`);
     }
     this.pos++;
@@ -441,7 +450,9 @@ export class IVProgParser {
         dimensions++;
       }
     }
+    const funcIDToken = this.getToken();
     const functionID = this.parseID();
+    this.checkFunctionDuplicate(functionID, funcIDToken);
     this.checkOpenParenthesis();
     this.pos++;
     this.consumeNewLines();
@@ -461,10 +472,11 @@ export class IVProgParser {
     }
     const func = new Commands.Function(functionID, returnType, formalParams, commandsBlock);
     if (functionID === null && !func.isMain) {
-      // TODO: better error message
       throw SyntaxErrorFactory.invalid_main_return(LanguageDefinedFunction.getMainFunctionName(),
         this.lexer.literalNames[this.lexerClass.RK_VOID],
         token.line);
+    } else if (func.isMain && formalParams.length !== 0) {
+      throw SyntaxErrorFactory.main_parameters();
     }
     this.popScope();
     return func;
@@ -592,7 +604,6 @@ export class IVProgParser {
     const token = this.getToken();
     if (this.isVariableType(token)) {
       if(!this.insideScope(IVProgParser.FUNCTION)) {
-        // TODO better error message
         throw SyntaxErrorFactory.invalid_var_declaration(token.line);
       }
       this.pushScope(IVProgParser.BASE);
@@ -614,7 +625,6 @@ export class IVProgParser {
       return this.parseFor();
     } else if (token.type === this.lexerClass.RK_BREAK ) {
       if(!this.insideScope(IVProgParser.BREAKABLE)) {
-        // TODO better error message
         throw SyntaxErrorFactory.invalid_break_command(
           this.lexer.literalNames[this.lexerClass.RK_BREAK],
           token
@@ -710,7 +720,6 @@ export class IVProgParser {
       } else if(maybeIf.type === this.lexerClass.RK_IF) {
         elseBlock = this.parseIfThenElse();
       } else {
-        // TODO better error message
         throw SyntaxErrorFactory.token_missing_list([this.lexer.literalNames[this.lexerClass.RK_IF], '{'], maybeIf);
       }
       return new Commands.IfThenElse(logicalExpression, cmdBlocks, elseBlock);