瀏覽代碼

Improve if and general loops condition type error message

Implement some ast command source info data
Lucas de Souza 5 年之前
父節點
當前提交
e4034c17d0

+ 6 - 6
i18n/pt/error.json

@@ -26,14 +26,14 @@
   "invalid_parameter_type": "A expressão $0 fornecida como parâmetro para a função $1 não é compatível com o tipo esperado.",
   "unknown_command_full": "Erro interno crítico: comando desconhecido encontrado na linha $0",
   "unknown_command": "Erro interno crítico: comando desconhecido encontrado!",
-  "loop_condition_type_full": "Erro na linha: $0, coluna $1: a condição dos laços de repetição deve ser do tipo lógico",
-  "loop_condition_type": "A condição dos laços de repetição deve ser do tipo lógico",
+  "loop_condition_type_full": "Erro na linha: $0, coluna $1: a condição $2 do laço de repetição deve ser do tipo lógico",
+  "loop_condition_type": "A condição $0 do laço de repetição deve ser do tipo lógico",
   "endless_loop_full": "Possível laço infinito detectado no seu código. Verifique a linha $0",
   "endless_loop": "Possível laço infinito detectado no seu código.",
-  "for_condition_type_full": "Erro na linha: $0, coluna $1: a condição de parada do comando para(...) deve ser do tipo lógico",
-  "for_condition_type": "A condição de parada do comando para(...) deve ser do tipo lógico",
-  "if_condition_type_full": "Erro na linha: $0, coluna $1: a condição de um comando se...senao deve ser do tipo lógico",
-  "if_condition_type": "A condição de um comando se...senao deve ser do tipo lógico",
+  "for_condition_type_full": "Erro na linha: $0, coluna $1: a condição de parada $2 do comando para(...) deve ser do tipo lógico",
+  "for_condition_type": "A condição de parada $0 do comando para(...) deve ser do tipo lógico",
+  "if_condition_type_full": "Erro na linha: $0, coluna $1: a condição $2 do comando se...senao deve ser do tipo lógico",
+  "if_condition_type": "A condição $0 do comando se...senao deve ser do tipo lógico",
   "invalid_return_type_full": "Erro na linha $0: a expressão não produz um tipo compatível com a função $1. Tipo esperado: $2.",
   "invalid_return_type": "A expressão não produz um tipo compatível com a função $0. Tipo esperado: $1.",
   "invalid_void_return_full": "Erro na linha $0: a função $1 não pode retornar uma expressão vazia, use uma espressão do tipo $2",

+ 1 - 1
js/ast/expressions/stringLiteral.js

@@ -9,6 +9,6 @@ export class StringLiteral extends Literal {
   }
 
   toString() {
-    return this.value;
+    return '"' + this.value + '"';
   }
 }

+ 12 - 3
js/ast/ivprogParser.js

@@ -725,6 +725,7 @@ export class IVProgParser {
     } else {
       this.pushScope(IVProgParser.COMMAND);
     }
+    const token = this.getToken();
     this.pos++;
     this.checkOpenParenthesis();
     this.pos++;
@@ -749,11 +750,16 @@ export class IVProgParser {
       } else {
         throw SyntaxErrorFactory.token_missing_list([this.lexer.literalNames[this.lexerClass.RK_IF], '{'], maybeIf);
       }
-      return new Commands.IfThenElse(logicalExpression, cmdBlocks, elseBlock);
+      this.popScope();
+      const cmd = new Commands.IfThenElse(logicalExpression, cmdBlocks, elseBlock);
+      cmd.sourceInfo = SourceInfo.createSourceInfo(token);
+      return cmd;
     }
     this.popScope();
 
-    return new Commands.IfThenElse(logicalExpression, cmdBlocks, null);
+    const cmd = new Commands.IfThenElse(logicalExpression, cmdBlocks, null);
+    cmd.sourceInfo = SourceInfo.createSourceInfo(token);
+    return cmd;
   }
 
   parseFor () {
@@ -777,6 +783,7 @@ export class IVProgParser {
 
   parseWhile () {
     this.pushScope(IVProgParser.BREAKABLE);
+    const token = this.getToken();
     this.pos++;
     this.checkOpenParenthesis();
     this.pos++;
@@ -788,7 +795,9 @@ export class IVProgParser {
     this.consumeNewLines();
     const cmdBlocks = this.parseCommandBlock();
     this.popScope();
-    return new Commands.While(logicalExpression, cmdBlocks);
+    const cmd = new Commands.While(logicalExpression, cmdBlocks);
+    cmd.sourceInfo = SourceInfo.createSourceInfo(token);
+    return cmd;
   }
 
   parseBreak () {

+ 18 - 15
js/processor/error/processorErrorFactory.js

@@ -102,16 +102,17 @@ export const ProcessorErrorFactory  = Object.freeze({
     const context = [exp, translateType(type, dim)];
     return new SemanticError(LocalizedStrings.getError("incompatible_types_array", context));
   },
-  loop_condition_type_full: (sourceInfo) => {
+  loop_condition_type_full: (exp, sourceInfo) => {
     if(sourceInfo) {
-      const context = [sourceInfo.line, sourceInfo.column];
+      const context = [sourceInfo.line, sourceInfo.column, exp];
       return new SemanticError(LocalizedStrings.getError("loop_condition_type_full", context));
     } else {
-      return ProcessorErrorFactory.loop_condition_type();
+      return ProcessorErrorFactory.loop_condition_type(exp);
     }
   },
-  loop_condition_type: () => {
-    return new SemanticError(LocalizedStrings.getError("loop_condition_type"));
+  loop_condition_type: (exp) => {
+    const context = [exp];
+    return new SemanticError(LocalizedStrings.getError("loop_condition_type", context));
   },
   endless_loop_full: (sourceInfo) => {
     if(sourceInfo) {
@@ -124,27 +125,29 @@ export const ProcessorErrorFactory  = Object.freeze({
   endless_loop: () => {
     return new SemanticError(LocalizedStrings.getError("endless_loop"));
   },
-  for_condition_type_full: (sourceInfo) => {
+  for_condition_type_full: (exp, sourceInfo) => {
     if(sourceInfo) {
-      const context = [sourceInfo.line, sourceInfo.column];
+      const context = [sourceInfo.line, sourceInfo.column, exp];
       return new SemanticError(LocalizedStrings.getError("for_condition_type_full", context));
     } else {
-      return ProcessorErrorFactory.for_condition_type();
+      return ProcessorErrorFactory.for_condition_type(exp);
     }
   },
-  for_condition_type: () => {
-    return new SemanticError(LocalizedStrings.getError("for_condition_type"));
+  for_condition_type: (exp) => {
+    const context = [exp];
+    return new SemanticError(LocalizedStrings.getError("for_condition_type", context));
   },
-  if_condition_type_full: (sourceInfo) => {
+  if_condition_type_full: (exp, sourceInfo) => {
     if(sourceInfo) {
-      const context = [sourceInfo.line, sourceInfo.column];
+      const context = [sourceInfo.line, sourceInfo.column, exp];
       return new SemanticError(LocalizedStrings.getError("if_condition_type_full", context));
     } else {
-      return ProcessorErrorFactory.if_condition_type();
+      return ProcessorErrorFactory.if_condition_type(exp);
     }
   },
-  if_condition_type: () => {
-    return new SemanticError(LocalizedStrings.getError("if_condition_type"));
+  if_condition_type: (exp) => {
+    const context = [exp];
+    return new SemanticError(LocalizedStrings.getError("if_condition_type", context));
   },
   invalid_global_var: () => {
     return new RuntimeError(LocalizedStrings.getError("invalid_global_var"))

+ 2 - 2
js/processor/ivprogProcessor.js

@@ -413,7 +413,7 @@ export class IVProgProcessor {
             return store;
           }
         } else {
-          return Promise.reject(ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo));
+          return Promise.reject(ProcessorErrorFactory.loop_condition_type_full(cmd.expression.toString(), cmd.sourceInfo));
         }
       })
       
@@ -439,7 +439,7 @@ export class IVProgProcessor {
             return Promise.resolve(store);
           }
         } else {
-          return Promise.reject(ProcessorErrorFactory.if_condition_type_full(cmd.sourceInfo));
+          return Promise.reject(ProcessorErrorFactory.if_condition_type_full(cmd.condition.toString(), cmd.sourceInfo));
         }
       });
     } catch (error) {

+ 3 - 3
js/processor/semantic/semanticAnalyser.js

@@ -347,7 +347,7 @@ export class SemanticAnalyser {
     if (cmd instanceof While) {
       const resultType = this.evaluateExpressionType(cmd.expression);
       if (!resultType.isCompatible(Types.BOOLEAN)) {
-        throw ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo);
+        throw ProcessorErrorFactory.loop_condition_type_full(cmd.expression.toString(), cmd.sourceInfo);
       }
       this.checkCommands(type, cmd.commands, optional);
       return false;
@@ -355,7 +355,7 @@ export class SemanticAnalyser {
       this.checkCommand(type, cmd.assignment, optional);
       const resultType = this.evaluateExpressionType(cmd.condition);
       if (!resultType.isCompatible(Types.BOOLEAN)) {
-        throw ProcessorErrorFactory.for_condition_type_full(cmd.sourceInfo);
+        throw ProcessorErrorFactory.for_condition_type_full(cmd.condition.toString(), cmd.sourceInfo);
       }
       this.checkCommand(type, cmd.increment, optional);
       this.checkCommands(type, cmd.commands, optional);
@@ -440,7 +440,7 @@ export class SemanticAnalyser {
     } else if (cmd instanceof IfThenElse) {
       const resultType = this.evaluateExpressionType(cmd.condition);
       if (!resultType.isCompatible(Types.BOOLEAN)) {
-        throw ProcessorErrorFactory.if_condition_type_full(cmd.sourceInfo);
+        throw ProcessorErrorFactory.if_condition_type_full(cmd.condition.toString(), cmd.sourceInfo);
       }
       if(cmd.ifFalse instanceof IfThenElse) {
         return this.checkCommands(type, cmd.ifTrue.commands, optional) && this.checkCommand(type, cmd.ifFalse, optional);