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;
     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);
 

+ 3 - 3
js/ast/ivprogParser.js

@@ -1324,7 +1324,7 @@ export class IVProgParser {
    **/
   parseExpressionOR () {
     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();
       this.pos++;
       const or = convertFromString("or");
@@ -1339,7 +1339,7 @@ export class IVProgParser {
 
   parseExpressionAND () {
     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();
       this.pos++;
       const and = convertFromString("and");
@@ -1354,7 +1354,7 @@ export class IVProgParser {
 
   parseExpressionNot () {
     const maybeNotToken = this.getToken();
-    if (maybeNotToken.type === this.ruleNames.NOT_OPERATOR) {
+    if (maybeNotToken.type === this.ruleNames.RK_LOGICAL_NOT) {
       const opToken = this.getToken();
       this.pos++;
       const not = convertFromString("not");

+ 2 - 3
js/util/parseFromVisual.js

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

+ 42 - 41
js/visualUI/functions.js

@@ -142,7 +142,7 @@ function addFunctionHandler () {
 		var in_use = false;
 		do {
 			in_use = false;
-			
+
 			var temp_name = LocalizedStrings.getUI('new_function') + '_' + counter_new_functions;
 
 			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;
 		do {
 			in_use = false;
-			
+
 			var temp_name = LocalizedStrings.getUI('new_parameter') + '_' + counter_new_parameters;
 
 			function_obj.parameters_list.forEach(function(el) {
@@ -287,7 +287,7 @@ function addHandlers (function_obj, function_container) {
         function_container.find(".inline_add_command").toggle();
       });
     }
-    
+
   });
 }
 
@@ -295,7 +295,7 @@ function addHandlers (function_obj, function_container) {
 function renderFunctionReturn (function_obj, function_element) {
 
   var ret = '<div class="ui dropdown function_return">';
-    
+
     if (function_obj.return_dimensions == 1) {
       ret += '<div class="text">'+ LocalizedStrings.getUI("vector") +': '+ LocalizedStrings.getUI(`type_${function_obj.return_type.toLowerCase()}`);
       ret += ' [ ] </div>';
@@ -342,20 +342,20 @@ function renderFunctionReturn (function_obj, function_element) {
     ret += '</div></div>';
 
     ret = $(ret);
-    
+
     function_element.find('.function_return').append(ret);
 }
 
 var cont = 0;
 
 export function renderFunction (function_obj) {
-  
+
   var appender = '<div class="ui secondary segment function_div list-group-item function_cont_'+cont+'">';
 
   if (function_obj.function_comment) {
     //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 += (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 {
       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">';
   }
-    
+
   appender += '</div> <span class="parethesis_function"> ) </span> </div>'
     + (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);
 
-  // Rendering parameters: 
+  // Rendering parameters:
   for (var j = 0; j < function_obj.parameters_list.length; j++) {
     renderParameter(function_obj, function_obj.parameters_list[j], appender);
   }
@@ -458,7 +458,7 @@ export function renderFunction (function_obj) {
       hide: 0
     }
   });
-  
+
   appender.find('.add_var_button_function').popup({
     content : LocalizedStrings.getUI("btn_add_var"),
     delay: {
@@ -601,7 +601,7 @@ export function renderFunction (function_obj) {
       offset: 40,
       onStick: function (evt) {
         $(teste).css('top', '20px', 'important');
-      }, 
+      },
       onBottom: function (evt) {
         $(teste).css('top', '20px', 'important');
       },
@@ -622,7 +622,7 @@ export function renderFunction (function_obj) {
       }
     });
   }
-  
+
   cont ++;
 
   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);
 
   const is_in_case_switch = $(evento_drag.item).parent().hasClass('case_commands_block');
-  
+
   // encontrar o elemento na árvore:
 
   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:
   // (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:
     window.program_obj.functions[function_index].commands.splice(evento_drag.newIndex - 1, 0, command_in_drag);
   } else if (is_in_else)  {
@@ -756,7 +756,7 @@ function updateProgramObjDrag () {
 
   window.draging = false;
   renderAlgorithm();
-  
+
 
 }
 
@@ -800,7 +800,7 @@ function prepareDragHandler (evt) {
 var command_in_drag;
 
 function addSortableHandler (element, id_function) {
-  
+
   var n_group = 'commands_drag_' + id_function;
   Sortable.create(element, {
     handle: '.command_drag',
@@ -873,7 +873,7 @@ function addSortableHandler (element, id_function) {
       addSortableHandler($(this).find(".case_commands_block")[0], id_function);
     });
 
-  });  
+  });
 }
 
 export function initVisualUI () {
@@ -1048,7 +1048,7 @@ export function setTestCases (testCases) {
 
 export function getTestCases () {
   // 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));
 }
 
@@ -1075,7 +1075,7 @@ function runCodeAssessment () {
     // cannot run assessment or it's already running
     return -1;
   }
-  
+
   let strCode = null;
 
   is_iassign = false;
@@ -1138,7 +1138,7 @@ function runCode () {
   if (strCode == null) {
     return;
   }
-  
+
   toggleConsole(true);
 
   // if(domConsole == null)
@@ -1155,7 +1155,7 @@ function runCode () {
       scheduleCall(() => {
         if(domConsole.pending_writes.length == 0) {
           if(proc.mode === Modes.ABORT) {
-            domConsole.info(LocalizedStrings.getMessage("aborted_execution"));  
+            domConsole.info(LocalizedStrings.getMessage("aborted_execution"));
           } else {
             domConsole.info(LocalizedStrings.getMessage("success_execution"));
           }
@@ -1183,7 +1183,7 @@ function runCode () {
         }
         return false;
       },100);
-    }) 
+    })
   } catch (error) {
     scheduleCall(() => {
       if(domConsole.pending_writes.length == 0) {
@@ -1197,7 +1197,7 @@ function runCode () {
       return false;
     },100);
   }
-  
+
 }
 
 function toggleConsole (is_running) {
@@ -1300,7 +1300,7 @@ function renderParameter (function_obj, parameter_obj, function_container) {
 
   if (parameter_obj.reference)
     ret += '<input type="checkbox" checked class="by_reference">';
-  else 
+  else
     ret += '<input type="checkbox" class="by_copy">';
 
   ret += '<div class="ui dropdown parameter_type">';
@@ -1319,7 +1319,7 @@ function renderParameter (function_obj, parameter_obj, function_container) {
 
   ret += '<div class="menu">';
 
-  
+
   for (const tm in Types) {
       if (tm == Types.VOID.toUpperCase()) {
         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 = $(ret);
-  
+
   function_container.find('.container_parameters_list').append(ret);
 
   ret.find('.remove_parameter').on('click', function(e){
     removeParameter(function_obj, parameter_obj, ret);
   });
-  
+
   ret.find('.ui.dropdown.parameter_type').dropdown({
     onChange: function(_, __, $selectedItem) {
       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) {
-  
+
   if (parameter_var.name == new_name) {
     return;
   }
@@ -1448,11 +1448,11 @@ function variableNameAlreadyExists (name_var, function_obj) {
 }
 
 function updateFunctionName (function_var, new_name, function_obj_dom) {
-  
+
   if (function_var.name == new_name) {
     return;
   }
-  
+
   if (isValidIdentifier(new_name)) {
     if (functionNameAlreadyExists(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-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.insertBefore(parent_node.find('.span_name_function'));
 
@@ -1626,7 +1626,7 @@ function enableNameFunctionUpdate (function_obj, parent_node) {
     }
   });
   input_field.select();
-  
+
 }
 
 export function addFunctionChangeListener (callback) {
@@ -1678,38 +1678,39 @@ function stopExecution () {
 }
 
 function downloadFile() {
-  
+
   var contentToSend = '{}\n::algorithm::';
 
   contentToSend = generator();
 
-  var date = new Date(); 
+  var date = new Date();
   var temp = date.toISOString().split('T')[0] + "_" + date.toTimeString().split(' ')[0].replaceAll(':', '-');
   var blob = new Blob([contentToSend],
                 { type: "text/plain;charset=utf-8" });
-  
+
   saveAs(blob, "ivprog-exported_" + temp + ".ivph");
 }
 
 function uploadFile (evt) {
     var oFReader = new FileReader();
     oFReader.readAsText(document.getElementById("ivph_file").files[0]);
+
     oFReader.onload = function (oFREvent) {
       var txt = oFREvent.target.result;
 
       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);
-        }
-        else {
+          console.debug("code=" + txt.code):
+        } else {
           ivprogCore.setPreviousAlgorithm(txt);
           window.renderAlgorithm();
         }
-
       }
       catch (e) {
         console.log(e)
       }
     };
-  }
+  }