Browse Source

Fix duplicate variables declaration not throwing a Syntax error

Lucas de Souza 6 years ago
parent
commit
676ad2d964
3 changed files with 34 additions and 2 deletions
  1. 1 0
      i18n/pt/error.json
  2. 4 0
      js/ast/error/syntaxErrorFactory.js
  3. 29 2
      js/ast/ivprogParser.js

+ 1 - 0
i18n/pt/error.json

@@ -35,5 +35,6 @@
   "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",
   "duplicate_function": "A função $0 na linha: $1, coluna: $2 já foi definida anteriormente.",
+  "duplicate_variable": "A variável $0 na linha: $1, coluna: $2 já foi declarada anteriormente.",
   "main_parameters": "A função inicio não pode ter parâmetros."
 }

+ 4 - 0
js/ast/error/syntaxErrorFactory.js

@@ -62,5 +62,9 @@ export const SyntaxErrorFactory = Object.freeze({
   },
   main_parameters: () => {
     return new SyntaxError(LocalizedStrings.getError("main_parameters"));
+  },
+  duplicate_variable: (token) => {
+    const context = [token.text, token.line, token.column];
+    return new SyntaxError(LocalizedStrings.getError("duplicate_variable", context));
   }
 });

+ 29 - 2
js/ast/ivprogParser.js

@@ -47,7 +47,8 @@ export class IVProgParser {
     this.parsingArrayDimension = 0;
     this.scope = [];
     this.langFuncs = LanguageService.getCurrentLangFuncs();
-    this.definedFuncsNameList = []
+    this.definedFuncsNameList = [];
+    this.definedVariablesStack = [];
   }
 
   parseTree () {
@@ -72,10 +73,22 @@ export class IVProgParser {
     this.scope.push(scope);
   }
 
+  pushVariableStack () {
+    this.definedVariablesStack.push([]);
+  }
+
   popScope () {
     return this.scope.pop();
   }
 
+  popVariableStack () {
+    return this.definedVariablesStack.pop();
+  }
+
+  getCurrentVariableStack () {
+    return this.definedVariablesStack[this.definedVariablesStack.length - 1];
+  }
+
   isEOF () {
     this.getToken(this.pos);
     return this.tokenStream.fetchedEOF;
@@ -91,13 +104,16 @@ export class IVProgParser {
       this.consumeNewLines();
       this.checkOpenCurly();
       this.pos++;
+      this.pushVariableStack();
       while(true) {
         this.consumeNewLines();
         const token = this.getToken();
         if (token.type === this.lexerClass.RK_CONST || this.isVariableType(token)) {
           globalVars = globalVars.concat(this.parseGlobalVariables());
         } else if (token.type === this.lexerClass.RK_FUNCTION) {
+          this.pushVariableStack();
           functions = functions.concat(this.parseFunction());
+          this.popVariableStack();
         } else {
           break;
         }
@@ -109,6 +125,7 @@ export class IVProgParser {
       if(!this.isEOF()) {
         throw SyntaxErrorFactory.extra_lines();
       }
+      this.popVariableStack();
       return {global: globalVars, functions: functions};
     } else {
       throw SyntaxErrorFactory.token_missing_one(this.lexer.literalNames[this.lexerClass.RK_PROGRAM], token);
@@ -213,6 +230,14 @@ export class IVProgParser {
     this.definedFuncsNameList.push(id);
   }
 
+  checkVariableDuplicate (variableID, variableIDToken) {
+    const index = this.getCurrentVariableStack().indexOf(variableID);
+    if(index !== -1) {
+      throw SyntaxErrorFactory.duplicate_variable(variableIDToken);
+    }
+    this.getCurrentVariableStack().push(variableID);
+  }
+
   consumeForSemiColon () {
     const eosToken = this.getToken();
     if (eosToken.type === this.lexerClass.EOS && eosToken.text.match(';')) {
@@ -260,7 +285,7 @@ export class IVProgParser {
     let dim2 = null;
     const idToken = this.getToken();
     const idString = this.parseID();
-    
+    this.checkVariableDuplicate(idString,idToken);
     // Check for array or vector
     // ID[int/IDi][int/IDj]
     if (this.checkOpenBrace(true)) {
@@ -491,7 +516,9 @@ export class IVProgParser {
     while(true) {
       let dimensions = 0;
       const typeString = this.parseType();
+      const idToken = this.getToken();
       const idString = this.parseID();
+      this.checkVariableDuplicate(idString, idToken);
       if (this.checkOpenBrace(true)) {
         this.pos++;
         dimensions++;