瀏覽代碼

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 年之前
父節點
當前提交
ec02855f07
共有 4 個文件被更改,包括 54 次插入50 次删除
  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)
       }
     };
-  }
+  }