Browse Source

Fix bug in logic operator syntatic parsing
Fix bug in textual to visual conversion for real numbers
Add logic to read .ivph file with test cases

Lucas de Souza 1 year ago
parent
commit
ec02855f07
4 changed files with 54 additions and 50 deletions
  1. 7 3
      grammar/lexer.ts
  2. 3 3
      js/ast/ivprogParser.js
  3. 2 3
      js/util/parseFromVisual.js
  4. 42 41
      js/visualUI/functions.js

+ 7 - 3
grammar/lexer.ts

@@ -183,9 +183,13 @@ export function makeLexer (lexer: I18nLexer): IVProgLexer {
     RKs[key] = value;
     RKs[key] = value;
     rules[key] = key;
     rules[key] = key;
   });
   });
-  RKs["AND_OPERATOR"] = lexer.logicOp.RK_LOGICAL_AND;
-  RKs["OR_OPERATOR"] = lexer.logicOp.RK_LOGICAL_OR;
-  RKs["NOT_OPERATOR"] = lexer.logicOp.RK_LOGICAL_NOT;
+  RKs["RK_LOGICAL_AND"] = lexer.logicOp.RK_LOGICAL_AND;
+  RKs["RK_LOGICAL_OR"] = lexer.logicOp.RK_LOGICAL_OR;
+  RKs["RK_LOGICAL_NOT"] = lexer.logicOp.RK_LOGICAL_NOT;
+
+  rules["RK_LOGICAL_AND"] = "RK_LOGICAL_AND";
+  rules["RK_LOGICAL_OR"] = "RK_LOGICAL_OR";
+  rules["RK_LOGICAL_NOT"] = "RK_LOGICAL_NOT";
 
 
   const RESERVED_KEYS = moo.keywords(RKs);
   const RESERVED_KEYS = moo.keywords(RKs);
 
 

+ 3 - 3
js/ast/ivprogParser.js

@@ -1324,7 +1324,7 @@ export class IVProgParser {
    **/
    **/
   parseExpressionOR () {
   parseExpressionOR () {
     let exp1 = this.parseExpressionAND();
     let exp1 = this.parseExpressionAND();
-    while (this.getToken().type === this.ruleNames.OR_OPERATOR) {
+    while (this.getToken().type === this.ruleNames.RK_LOGICAL_OR) {
       const opToken = this.getToken();
       const opToken = this.getToken();
       this.pos++;
       this.pos++;
       const or = convertFromString("or");
       const or = convertFromString("or");
@@ -1339,7 +1339,7 @@ export class IVProgParser {
 
 
   parseExpressionAND () {
   parseExpressionAND () {
     let exp1 = this.parseExpressionNot();
     let exp1 = this.parseExpressionNot();
-    while (this.getToken().type === this.ruleNames.AND_OPERATOR) {
+    while (this.getToken().type === this.ruleNames.RK_LOGICAL_AND) {
       const opToken = this.getToken();
       const opToken = this.getToken();
       this.pos++;
       this.pos++;
       const and = convertFromString("and");
       const and = convertFromString("and");
@@ -1354,7 +1354,7 @@ export class IVProgParser {
 
 
   parseExpressionNot () {
   parseExpressionNot () {
     const maybeNotToken = this.getToken();
     const maybeNotToken = this.getToken();
-    if (maybeNotToken.type === this.ruleNames.NOT_OPERATOR) {
+    if (maybeNotToken.type === this.ruleNames.RK_LOGICAL_NOT) {
       const opToken = this.getToken();
       const opToken = this.getToken();
       this.pos++;
       this.pos++;
       const not = convertFromString("not");
       const not = convertFromString("not");

+ 2 - 3
js/util/parseFromVisual.js

@@ -374,7 +374,7 @@ function variableInitialWalker (expression) {
         Types.REAL.isCompatible(expression.type) &&
         Types.REAL.isCompatible(expression.type) &&
         expression.value.decimalPlaces() == 0
         expression.value.decimalPlaces() == 0
       ) {
       ) {
-        value = expression.value.toFixed(2);
+        value = Number(expression.value.toFixed(2));
       } else {
       } else {
         value = expression.value.toNumber();
         value = expression.value.toNumber();
       }
       }
@@ -407,7 +407,6 @@ function expressionWalker (expression) {
     funcObj.params = paramsList;
     funcObj.params = paramsList;
     result = [funcObj];
     result = [funcObj];
   } else if (expression instanceof Expressions.UnaryApp) {
   } else if (expression instanceof Expressions.UnaryApp) {
-    console.log(expression);
     const left = expressionWalker(expression.left);
     const left = expressionWalker(expression.left);
     const opType = getOpType(expression.op);
     const opType = getOpType(expression.op);
     const opValue = translateOp(opType, expression.op);
     const opValue = translateOp(opType, expression.op);
@@ -457,7 +456,7 @@ function expressionWalker (expression) {
         Types.REAL.isCompatible(expression.type) &&
         Types.REAL.isCompatible(expression.type) &&
         expression.value.decimalPlaces() == 0
         expression.value.decimalPlaces() == 0
       ) {
       ) {
-        value = expression.value.toFixed(2);
+        value = Number(expression.value.toFixed(2));
       } else {
       } else {
         value = expression.value.toNumber();
         value = expression.value.toNumber();
       }
       }

+ 42 - 41
js/visualUI/functions.js

@@ -142,7 +142,7 @@ function addFunctionHandler () {
 		var in_use = false;
 		var in_use = false;
 		do {
 		do {
 			in_use = false;
 			in_use = false;
-			
+
 			var temp_name = LocalizedStrings.getUI('new_function') + '_' + counter_new_functions;
 			var temp_name = LocalizedStrings.getUI('new_function') + '_' + counter_new_functions;
 
 
 			window.program_obj.functions.forEach(function(el) {
 			window.program_obj.functions.forEach(function(el) {
@@ -180,7 +180,7 @@ function addParameter (function_obj, function_container/*, is_from_click = false
 		var in_use = false;
 		var in_use = false;
 		do {
 		do {
 			in_use = false;
 			in_use = false;
-			
+
 			var temp_name = LocalizedStrings.getUI('new_parameter') + '_' + counter_new_parameters;
 			var temp_name = LocalizedStrings.getUI('new_parameter') + '_' + counter_new_parameters;
 
 
 			function_obj.parameters_list.forEach(function(el) {
 			function_obj.parameters_list.forEach(function(el) {
@@ -287,7 +287,7 @@ function addHandlers (function_obj, function_container) {
         function_container.find(".inline_add_command").toggle();
         function_container.find(".inline_add_command").toggle();
       });
       });
     }
     }
-    
+
   });
   });
 }
 }
 
 
@@ -295,7 +295,7 @@ function addHandlers (function_obj, function_container) {
 function renderFunctionReturn (function_obj, function_element) {
 function renderFunctionReturn (function_obj, function_element) {
 
 
   var ret = '<div class="ui dropdown function_return">';
   var ret = '<div class="ui dropdown function_return">';
-    
+
     if (function_obj.return_dimensions == 1) {
     if (function_obj.return_dimensions == 1) {
       ret += '<div class="text">'+ LocalizedStrings.getUI("vector") +': '+ LocalizedStrings.getUI(`type_${function_obj.return_type.toLowerCase()}`);
       ret += '<div class="text">'+ LocalizedStrings.getUI("vector") +': '+ LocalizedStrings.getUI(`type_${function_obj.return_type.toLowerCase()}`);
       ret += ' [ ] </div>';
       ret += ' [ ] </div>';
@@ -342,20 +342,20 @@ function renderFunctionReturn (function_obj, function_element) {
     ret += '</div></div>';
     ret += '</div></div>';
 
 
     ret = $(ret);
     ret = $(ret);
-    
+
     function_element.find('.function_return').append(ret);
     function_element.find('.function_return').append(ret);
 }
 }
 
 
 var cont = 0;
 var cont = 0;
 
 
 export function renderFunction (function_obj) {
 export function renderFunction (function_obj) {
-  
+
   var appender = '<div class="ui secondary segment function_div list-group-item function_cont_'+cont+'">';
   var appender = '<div class="ui secondary segment function_div list-group-item function_cont_'+cont+'">';
 
 
   if (function_obj.function_comment) {
   if (function_obj.function_comment) {
     //appender += renderComment(function_obj.function_comment, sequence, true, -1);
     //appender += renderComment(function_obj.function_comment, sequence, true, -1);
   }
   }
-    
+
   appender += '<span class="glyphicon glyphicon-move move_function" aria-hidden="true"><i class="icon sort alternate vertical"></i></span>';
   appender += '<span class="glyphicon glyphicon-move move_function" aria-hidden="true"><i class="icon sort alternate vertical"></i></span>';
 
 
   appender += (function_obj.is_main ? '<div class="div_start_minimize_v"> </div>' : '<button class="ui icon button large remove_function_button"><i class="red icon times"></i></button>')
   appender += (function_obj.is_main ? '<div class="div_start_minimize_v"> </div>' : '<button class="ui icon button large remove_function_button"><i class="red icon times"></i></button>')
@@ -369,10 +369,10 @@ export function renderFunction (function_obj) {
   } else {
   } else {
       appender += '<div class="ui function_return"></div>';
       appender += '<div class="ui function_return"></div>';
 
 
-      appender += '<div class="function_name_div function_name_div_updated"><span class="span_name_function name_function_updated">'+function_obj.name+'</span> </div> ' 
+      appender += '<div class="function_name_div function_name_div_updated"><span class="span_name_function name_function_updated">'+function_obj.name+'</span> </div> '
         + ' <span class="parethesis_function"> ( </span> <i class="ui icon plus square outline add_parameter_button"></i> <div class="ui large labels parameters_list container_parameters_list">';
         + ' <span class="parethesis_function"> ( </span> <i class="ui icon plus square outline add_parameter_button"></i> <div class="ui large labels parameters_list container_parameters_list">';
   }
   }
-    
+
   appender += '</div> <span class="parethesis_function"> ) </span> </div>'
   appender += '</div> <span class="parethesis_function"> ) </span> </div>'
     + (function_obj.is_hidden ? ' <div class="function_area" style="display: none;"> ' : ' <div class="function_area"> ');
     + (function_obj.is_hidden ? ' <div class="function_area" style="display: none;"> ' : ' <div class="function_area"> ');
 
 
@@ -421,7 +421,7 @@ export function renderFunction (function_obj) {
 
 
   addHandlers(function_obj, appender);
   addHandlers(function_obj, appender);
 
 
-  // Rendering parameters: 
+  // Rendering parameters:
   for (var j = 0; j < function_obj.parameters_list.length; j++) {
   for (var j = 0; j < function_obj.parameters_list.length; j++) {
     renderParameter(function_obj, function_obj.parameters_list[j], appender);
     renderParameter(function_obj, function_obj.parameters_list[j], appender);
   }
   }
@@ -458,7 +458,7 @@ export function renderFunction (function_obj) {
       hide: 0
       hide: 0
     }
     }
   });
   });
-  
+
   appender.find('.add_var_button_function').popup({
   appender.find('.add_var_button_function').popup({
     content : LocalizedStrings.getUI("btn_add_var"),
     content : LocalizedStrings.getUI("btn_add_var"),
     delay: {
     delay: {
@@ -601,7 +601,7 @@ export function renderFunction (function_obj) {
       offset: 40,
       offset: 40,
       onStick: function (evt) {
       onStick: function (evt) {
         $(teste).css('top', '20px', 'important');
         $(teste).css('top', '20px', 'important');
-      }, 
+      },
       onBottom: function (evt) {
       onBottom: function (evt) {
         $(teste).css('top', '20px', 'important');
         $(teste).css('top', '20px', 'important');
       },
       },
@@ -622,7 +622,7 @@ export function renderFunction (function_obj) {
       }
       }
     });
     });
   }
   }
-  
+
   cont ++;
   cont ++;
 
 
   appender.find('.add_parameter_button').popup({
   appender.find('.add_parameter_button').popup({
@@ -712,7 +712,7 @@ function updateProgramObjDrag () {
   // index_in_block = $(evento_drag.item).parent().find('.command_container').index(evento_drag.item);
   // index_in_block = $(evento_drag.item).parent().find('.command_container').index(evento_drag.item);
 
 
   const is_in_case_switch = $(evento_drag.item).parent().hasClass('case_commands_block');
   const is_in_case_switch = $(evento_drag.item).parent().hasClass('case_commands_block');
-  
+
   // encontrar o elemento na árvore:
   // encontrar o elemento na árvore:
 
 
   var command_start_point = window.program_obj.functions[function_index].commands[indice_na_raiz];
   var command_start_point = window.program_obj.functions[function_index].commands[indice_na_raiz];
@@ -732,7 +732,7 @@ function updateProgramObjDrag () {
 
 
   // agora tem que alocar o comando na árvore, mas considerar as quatro situações:
   // agora tem que alocar o comando na árvore, mas considerar as quatro situações:
   // (1) se está em um else ou (2) se está em switch ou (3) será um caso padrão ou (4) se será na raiz.
   // (1) se está em um else ou (2) se está em switch ou (3) será um caso padrão ou (4) se será na raiz.
-  
+
   if (path_target.length == 0) { // soltou na raiz:
   if (path_target.length == 0) { // soltou na raiz:
     window.program_obj.functions[function_index].commands.splice(evento_drag.newIndex - 1, 0, command_in_drag);
     window.program_obj.functions[function_index].commands.splice(evento_drag.newIndex - 1, 0, command_in_drag);
   } else if (is_in_else)  {
   } else if (is_in_else)  {
@@ -756,7 +756,7 @@ function updateProgramObjDrag () {
 
 
   window.draging = false;
   window.draging = false;
   renderAlgorithm();
   renderAlgorithm();
-  
+
 
 
 }
 }
 
 
@@ -800,7 +800,7 @@ function prepareDragHandler (evt) {
 var command_in_drag;
 var command_in_drag;
 
 
 function addSortableHandler (element, id_function) {
 function addSortableHandler (element, id_function) {
-  
+
   var n_group = 'commands_drag_' + id_function;
   var n_group = 'commands_drag_' + id_function;
   Sortable.create(element, {
   Sortable.create(element, {
     handle: '.command_drag',
     handle: '.command_drag',
@@ -873,7 +873,7 @@ function addSortableHandler (element, id_function) {
       addSortableHandler($(this).find(".case_commands_block")[0], id_function);
       addSortableHandler($(this).find(".case_commands_block")[0], id_function);
     });
     });
 
 
-  });  
+  });
 }
 }
 
 
 export function initVisualUI () {
 export function initVisualUI () {
@@ -1048,7 +1048,7 @@ export function setTestCases (testCases) {
 
 
 export function getTestCases () {
 export function getTestCases () {
   // Deep clone of test cases to avoid unauthorized modification
   // Deep clone of test cases to avoid unauthorized modification
-  // TODO: It may be not possible to use this once custom test are fully implemented 
+  // TODO: It may be not possible to use this once custom test are fully implemented
   return JSON.parse(JSON.stringify(_testCases));
   return JSON.parse(JSON.stringify(_testCases));
 }
 }
 
 
@@ -1075,7 +1075,7 @@ function runCodeAssessment () {
     // cannot run assessment or it's already running
     // cannot run assessment or it's already running
     return -1;
     return -1;
   }
   }
-  
+
   let strCode = null;
   let strCode = null;
 
 
   is_iassign = false;
   is_iassign = false;
@@ -1138,7 +1138,7 @@ function runCode () {
   if (strCode == null) {
   if (strCode == null) {
     return;
     return;
   }
   }
-  
+
   toggleConsole(true);
   toggleConsole(true);
 
 
   // if(domConsole == null)
   // if(domConsole == null)
@@ -1155,7 +1155,7 @@ function runCode () {
       scheduleCall(() => {
       scheduleCall(() => {
         if(domConsole.pending_writes.length == 0) {
         if(domConsole.pending_writes.length == 0) {
           if(proc.mode === Modes.ABORT) {
           if(proc.mode === Modes.ABORT) {
-            domConsole.info(LocalizedStrings.getMessage("aborted_execution"));  
+            domConsole.info(LocalizedStrings.getMessage("aborted_execution"));
           } else {
           } else {
             domConsole.info(LocalizedStrings.getMessage("success_execution"));
             domConsole.info(LocalizedStrings.getMessage("success_execution"));
           }
           }
@@ -1183,7 +1183,7 @@ function runCode () {
         }
         }
         return false;
         return false;
       },100);
       },100);
-    }) 
+    })
   } catch (error) {
   } catch (error) {
     scheduleCall(() => {
     scheduleCall(() => {
       if(domConsole.pending_writes.length == 0) {
       if(domConsole.pending_writes.length == 0) {
@@ -1197,7 +1197,7 @@ function runCode () {
       return false;
       return false;
     },100);
     },100);
   }
   }
-  
+
 }
 }
 
 
 function toggleConsole (is_running) {
 function toggleConsole (is_running) {
@@ -1300,7 +1300,7 @@ function renderParameter (function_obj, parameter_obj, function_container) {
 
 
   if (parameter_obj.reference)
   if (parameter_obj.reference)
     ret += '<input type="checkbox" checked class="by_reference">';
     ret += '<input type="checkbox" checked class="by_reference">';
-  else 
+  else
     ret += '<input type="checkbox" class="by_copy">';
     ret += '<input type="checkbox" class="by_copy">';
 
 
   ret += '<div class="ui dropdown parameter_type">';
   ret += '<div class="ui dropdown parameter_type">';
@@ -1319,7 +1319,7 @@ function renderParameter (function_obj, parameter_obj, function_container) {
 
 
   ret += '<div class="menu">';
   ret += '<div class="menu">';
 
 
-  
+
   for (const tm in Types) {
   for (const tm in Types) {
       if (tm == Types.VOID.toUpperCase()) {
       if (tm == Types.VOID.toUpperCase()) {
         continue;
         continue;
@@ -1361,13 +1361,13 @@ function renderParameter (function_obj, parameter_obj, function_container) {
   ret += ' <i class="yellow inverted icon times remove_parameter"></i></div>';
   ret += ' <i class="yellow inverted icon times remove_parameter"></i></div>';
 
 
   ret = $(ret);
   ret = $(ret);
-  
+
   function_container.find('.container_parameters_list').append(ret);
   function_container.find('.container_parameters_list').append(ret);
 
 
   ret.find('.remove_parameter').on('click', function(e){
   ret.find('.remove_parameter').on('click', function(e){
     removeParameter(function_obj, parameter_obj, ret);
     removeParameter(function_obj, parameter_obj, ret);
   });
   });
-  
+
   ret.find('.ui.dropdown.parameter_type').dropdown({
   ret.find('.ui.dropdown.parameter_type').dropdown({
     onChange: function(_, __, $selectedItem) {
     onChange: function(_, __, $selectedItem) {
       if ($selectedItem.data('dimensions')) {
       if ($selectedItem.data('dimensions')) {
@@ -1409,7 +1409,7 @@ function renderParameter (function_obj, parameter_obj, function_container) {
 }
 }
 
 
 function updateParameterName (parameter_var, new_name, parameter_obj_dom, function_obj) {
 function updateParameterName (parameter_var, new_name, parameter_obj_dom, function_obj) {
-  
+
   if (parameter_var.name == new_name) {
   if (parameter_var.name == new_name) {
     return;
     return;
   }
   }
@@ -1448,11 +1448,11 @@ function variableNameAlreadyExists (name_var, function_obj) {
 }
 }
 
 
 function updateFunctionName (function_var, new_name, function_obj_dom) {
 function updateFunctionName (function_var, new_name, function_obj_dom) {
-  
+
   if (function_var.name == new_name) {
   if (function_var.name == new_name) {
     return;
     return;
   }
   }
-  
+
   if (isValidIdentifier(new_name)) {
   if (isValidIdentifier(new_name)) {
     if (functionNameAlreadyExists(new_name)) {
     if (functionNameAlreadyExists(new_name)) {
       Utils.renderErrorMessage(function_obj_dom.find('.function_name_div'), LocalizedStrings.getError('inform_valid_function_duplicated', [new_name]));
       Utils.renderErrorMessage(function_obj_dom.find('.function_name_div'), LocalizedStrings.getError('inform_valid_function_duplicated', [new_name]));
@@ -1562,7 +1562,7 @@ function enableNameFunctionUpdate (function_obj, parent_node) {
   }
   }
   parent_node.find('.span_name_function').css('padding-left', '0');
   parent_node.find('.span_name_function').css('padding-left', '0');
   parent_node.find('.span_name_function').css('padding-right', '0');
   parent_node.find('.span_name_function').css('padding-right', '0');
-  
+
   input_field = $( "<input type='text' class='width-dynamic input_name_function' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' value='"+function_obj.name+"' />" );
   input_field = $( "<input type='text' class='width-dynamic input_name_function' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' value='"+function_obj.name+"' />" );
   input_field.insertBefore(parent_node.find('.span_name_function'));
   input_field.insertBefore(parent_node.find('.span_name_function'));
 
 
@@ -1626,7 +1626,7 @@ function enableNameFunctionUpdate (function_obj, parent_node) {
     }
     }
   });
   });
   input_field.select();
   input_field.select();
-  
+
 }
 }
 
 
 export function addFunctionChangeListener (callback) {
 export function addFunctionChangeListener (callback) {
@@ -1678,38 +1678,39 @@ function stopExecution () {
 }
 }
 
 
 function downloadFile() {
 function downloadFile() {
-  
+
   var contentToSend = '{}\n::algorithm::';
   var contentToSend = '{}\n::algorithm::';
 
 
   contentToSend = generator();
   contentToSend = generator();
 
 
-  var date = new Date(); 
+  var date = new Date();
   var temp = date.toISOString().split('T')[0] + "_" + date.toTimeString().split(' ')[0].replaceAll(':', '-');
   var temp = date.toISOString().split('T')[0] + "_" + date.toTimeString().split(' ')[0].replaceAll(':', '-');
   var blob = new Blob([contentToSend],
   var blob = new Blob([contentToSend],
                 { type: "text/plain;charset=utf-8" });
                 { type: "text/plain;charset=utf-8" });
-  
+
   saveAs(blob, "ivprog-exported_" + temp + ".ivph");
   saveAs(blob, "ivprog-exported_" + temp + ".ivph");
 }
 }
 
 
 function uploadFile (evt) {
 function uploadFile (evt) {
     var oFReader = new FileReader();
     var oFReader = new FileReader();
     oFReader.readAsText(document.getElementById("ivph_file").files[0]);
     oFReader.readAsText(document.getElementById("ivph_file").files[0]);
+
     oFReader.onload = function (oFREvent) {
     oFReader.onload = function (oFREvent) {
       var txt = oFREvent.target.result;
       var txt = oFREvent.target.result;
 
 
       try {
       try {
 
 
-        if (txt.indexOf("::algorithm::") >= 0) {
+        if (txt.indexOf("::algorithm::") >= 0 || txt.indexOf("\"test_cases\"") >= 0) {
+          //leo/lucas Version with "test-cases": { "version": "x.y",\n "code": ... \n "test_cases":...
           prepareActivityToStudent(txt, true);
           prepareActivityToStudent(txt, true);
-        }
-        else {
+          console.debug("code=" + txt.code):
+        } else {
           ivprogCore.setPreviousAlgorithm(txt);
           ivprogCore.setPreviousAlgorithm(txt);
           window.renderAlgorithm();
           window.renderAlgorithm();
         }
         }
-
       }
       }
       catch (e) {
       catch (e) {
         console.log(e)
         console.log(e)
       }
       }
     };
     };
-  }
+  }