Ver Fonte

Implement alternative keywords for for and while

Change semantic and syntax of do...while to do...until
Lucas de Souza há 5 anos atrás
pai
commit
bcd5323e8e

+ 12 - 0
grammar/pt/ivprog.g4

@@ -54,6 +54,10 @@ RK_RETURN
   ;  
 
 RK_FOR
+  : 'para'
+  ;
+
+RK_FOR_ALT
   : 'repita_para'
   ;
 
@@ -77,10 +81,18 @@ RK_DO
   : 'faca'
   ;
 
+RK_DO_UNTIL
+  : 'ate_que'
+  ;
+
 RK_WHILE
   : 'enquanto'
   ;
 
+RK_WHILE_ALT
+  : 'repita_enquanto'
+  ;
+
 RK_IF
   : 'se'
   ;

+ 5 - 2
i18n/pt/ui.json

@@ -47,9 +47,12 @@
   "text_break":"pare",
   "text_else":"senao",
   "text_for":"repita_para",
-  "text_code_while":"enquanto",
+  "text_code_while":"repita_enquanto",
   "text_code_do":"faca",
+  "text_code_do_until":"ate_que",
   "text_command_do":"faça",
+  "text_command_while":"repita enquanto",
+  "text_command_do_until":"até que",
   "text_code_switch": "escolha",
   "text_code_case": "caso",
   "text_config_programming":"Programação",
@@ -64,7 +67,7 @@
   "text_repeatNtimes": "Repita N vezes",
   "text_receives": "recebe",
   "text_whiletrue": "Enquanto verdadeiro",
-  "text_dowhiletrue": "Faça enquanto verdadeiro",
+  "text_dowhiletrue": "Faça até que verdadeiro",
   "text_switch": "Escolha",
   "text_functioncall": "Chamada de função",
   "text_value": "Valor",

+ 61 - 53
js/util/editorMode2.js

@@ -11,14 +11,16 @@ export function CodeEditorMode (CodeMirror) {
     this.align = align;
     this.prev = prev;
   }
+
   function pushContext(state, col, type, info) {
-    var indent = state.indented;
+    let indent = state.indented;
     if (state.context && state.context.type == "statement" && type != "statement")
       indent = state.context.indented;
     return state.context = new Context(indent, col, type, info, null, state.context);
   }
+  
   function popContext(state) {
-    var t = state.context.type;
+    const t = state.context.type;
     if (t == ")" || t == "]" || t == "}")
       state.indented = state.context.indented;
     return state.context = state.context.prev;
@@ -38,15 +40,35 @@ export function CodeEditorMode (CodeMirror) {
     }
   }
 
+  function contains(words, word) {
+    if (typeof words === "function") {
+      return words(word);
+    } else {
+      return Object.propertyIsEnumerable.call(words, word);
+    }
+  }
+
+  function tokenComment(stream, state) {
+    let maybeEnd = false, ch;
+    while ((ch = stream.next())) {
+      if (ch == "/" && maybeEnd) {
+        state.tokenize = null;
+        break;
+      }
+      maybeEnd = (ch == "*");
+    }
+    return "comment";
+  }
+
   CodeMirror.defineMode("ivprog", function (config, parserConfig) {
-    var indentUnit = config.indentUnit,
+    const indentUnit = config.indentUnit,
       statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
       dontAlignCalls = parserConfig.dontAlignCalls,
       keywords = parserConfig.keywords || {},
       switchKeyword = parserConfig.switchKeyword,
       caseKeyword = parserConfig.caseKeyword,
       defaultKeyword = parserConfig.defaultKeyword,
-      caseRegex = new RegExp(`^\s*(?:${caseKeyword} .*?:|${defaultKeyword}:|\{\}?|\})$`),////,
+      caseRegex = new RegExp(`^\\s*(?:${caseKeyword} .*?:|${defaultKeyword}:|\\{\\}?|\\})$`),////,
       types = parserConfig.types || {},
       builtin = parserConfig.builtin || {},
       blockKeywords = parserConfig.blockKeywords || {},
@@ -56,21 +78,21 @@ export function CodeEditorMode (CodeMirror) {
       multiLineStrings = parserConfig.multiLineStrings,
       indentStatements = false,
       namespaceSeparator = null,
-      isPunctuationChar = /[\[\]{}\(\),;\:\n]/,
-      numberStart = /[\d\.]/,
-      number = /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)/i,
-      isOperatorChar = /[+\-*%=<>!\/]/,
+      isPunctuationChar = /[[\]{}(),;:\n]/,
+      numberStart = /[\d.]/,
+      number = /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)$/i,
+      isOperatorChar = /[+\-*%=<>!/&]/,
       isIdentifierChar = /[a-zA-Z0-9_]/,
       // An optional function that takes a {string} token and returns true if it
       // should be treated as a builtin.
       isReservedIdentifier = parserConfig.isReservedIdentifier || false;
 
-    var curPunc, isDefKeyword;
-
+    let curPunc, isDefKeyword;
+    let tokenString = function () { /*SKIP*/};
     function tokenBase(stream, state) {
-      var ch = stream.next();
+      const ch = stream.next();
       if (hooks[ch]) {
-        var result = hooks[ch](stream, state);
+        const result = hooks[ch](stream, state);
         if (result !== false) return result;
       }
       if (ch == '"') {
@@ -97,14 +119,14 @@ export function CodeEditorMode (CodeMirror) {
         }
       }
       if (isOperatorChar.test(ch)) {
-        while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) { }
+        while (!stream.match(/^\/[/*]/, false) && stream.eat(isOperatorChar)) { /* SKIP */}
         return "operator";
       }
       stream.eatWhile(isIdentifierChar);
       if (namespaceSeparator) while (stream.match(namespaceSeparator))
         stream.eatWhile(isIdentifierChar);
 
-      var cur = stream.current();
+      const cur = stream.current();
       if (contains(keywords, cur)) {
         if (contains(blockKeywords, cur)) curPunc = "newstatement";
         if (contains(defKeywords, cur)) isDefKeyword = true;
@@ -120,9 +142,9 @@ export function CodeEditorMode (CodeMirror) {
       return "variable";
     }
 
-    function tokenString(quote) {
+     tokenString = function (quote) {
       return function (stream, state) {
-        var escaped = false, next, end = false;
+        let escaped = false, next, end = false;
         while ((next = stream.next()) != null) {
           if (next == quote && !escaped) { end = true; break; }
           escaped = !escaped && next == "\\";
@@ -133,18 +155,6 @@ export function CodeEditorMode (CodeMirror) {
       };
     }
 
-    function tokenComment(stream, state) {
-      var maybeEnd = false, ch;
-      while (ch = stream.next()) {
-        if (ch == "/" && maybeEnd) {
-          state.tokenize = null;
-          break;
-        }
-        maybeEnd = (ch == "*");
-      }
-      return "comment";
-    }
-
     function maybeEOL(stream, state) {
       if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
         state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
@@ -164,7 +174,7 @@ export function CodeEditorMode (CodeMirror) {
       },
 
       token: function (stream, state) {
-        var ctx = state.context;
+        let ctx = state.context;
         if (stream.sol()) {
           if (ctx.align == null) ctx.align = false;
           state.indented = stream.indentation();
@@ -172,7 +182,7 @@ export function CodeEditorMode (CodeMirror) {
         }
         if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
         curPunc = isDefKeyword = null;
-        var style = (state.tokenize || tokenBase)(stream, state);
+        let style = (state.tokenize || tokenBase)(stream, state);
         if (style == "comment" || style == "meta") return style;
         if (ctx.align == null) ctx.align = true;
 
@@ -200,7 +210,7 @@ export function CodeEditorMode (CodeMirror) {
           style = "def";
 
         if (hooks.token) {
-          var result = hooks.token(stream, state, style);
+          const result = hooks.token(stream, state, style);
           if (result !== undefined) style = result;
         }
 
@@ -214,17 +224,18 @@ export function CodeEditorMode (CodeMirror) {
 
       indent: function (state, textAfter) {
         if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
-        var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
-        var closing = firstChar == ctx.type;
+        let ctx = state.context;
+        const firstChar = textAfter && textAfter.charAt(0)
+        const closing = firstChar == ctx.type;
         if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
         if (parserConfig.dontIndentStatements)
           while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
             ctx = ctx.prev
         if (hooks.indent) {
-          var hook = hooks.indent(state, ctx, textAfter, indentUnit);
+          const hook = hooks.indent(state, ctx, textAfter, indentUnit);
           if (typeof hook == "number") return hook
         }
-        var switchBlock = ctx.prev && ctx.prev.info == switchKeyword;
+        const switchBlock = ctx.prev && ctx.prev.info == switchKeyword;
         if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
           while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
           return ctx.indented
@@ -235,7 +246,7 @@ export function CodeEditorMode (CodeMirror) {
           return ctx.column + (closing ? 0 : 1);
         if (ctx.type == ")" && !closing)
           return ctx.indented + statementIndentUnit;
-        var caseTestRegex = new RegExp(`^(?:${caseKeyword}|${defaultKeyword})\b`)
+        const caseTestRegex = new RegExp(`^(?:${caseKeyword}|${defaultKeyword})\b`)
         return ctx.indented + (closing ? 0 : indentUnit) +
           (!closing && switchBlock && !caseTestRegex.test(textAfter) ? indentUnit : 0);
       },
@@ -250,24 +261,18 @@ export function CodeEditorMode (CodeMirror) {
   });
 
   function words(str) {
-    var obj = {}, words = str.split(" ");
-    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
+    const obj = {}, words = str.split(" ");
+    for (let i = 0; i < words.length; ++i) obj[words[i]] = true;
     return obj;
   }
-  function contains(words, word) {
-    if (typeof words === "function") {
-      return words(word);
-    } else {
-      return Object.propertyIsEnumerable.call(words, word);
-    }
-  }
+  
   const codeConfig = getCodeEditorModeConfig();
 
-  var ivprogKeywords =  codeConfig.keywords.join(" ");
+  const ivprogKeywords =  codeConfig.keywords.join(" ");
 
   // Do not use this. Use the cTypes function below. This is global just to avoid
   // excessive calls when cTypes is being called multiple times during a parse.
-  var basicTypes = words(codeConfig.types.join(" "));
+  const basicTypes = words(codeConfig.types.join(" "));
 
   // Returns true if identifier is a "C" type.
   // C type is defined as those that are reserved by the compiler (basicTypes),
@@ -277,15 +282,18 @@ export function CodeEditorMode (CodeMirror) {
     return contains(basicTypes, identifier);
   }
 
-  var ivprogBlockKeywords = codeConfig.blocks.join(" ");
-  var ivprogDefKeywords = "funcao const";
+  const ivprogBlockKeywords = codeConfig.blocks.join(" ");
+  const ivprogDefKeywords = "funcao const";
 
   function def(mimes, mode) {
     if (typeof mimes == "string") mimes = [mimes];
-    var words = [];
+    const words = [];
     function add(obj) {
-      if (obj) for (var prop in obj) if (Object.hasOwnProperty.call(obj, prop))
-        words.push(prop);
+      if (obj) {
+        for (const prop in obj) if (Object.hasOwnProperty.call(obj, prop)) {
+          words.push(prop);
+        }
+      }
     }
     add(mode.keywords);
     add(mode.types);
@@ -296,7 +304,7 @@ export function CodeEditorMode (CodeMirror) {
       CodeMirror.registerHelper("hintWords", mimes[0], words);
     }
 
-    for (var i = 0; i < mimes.length; ++i)
+    for (let i = 0; i < mimes.length; ++i)
       CodeMirror.defineMIME(mimes[i], mode);
   }
   

+ 30 - 28
js/util/utils.js

@@ -97,33 +97,9 @@ export function isElementInViewport (el) {
     rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
     rect.top < (window.innerHeight || document.documentElement.clientHeight);
 }
+
 let cacheMainList = null;
 let cacheOp = null;
-export function isKeyword (text) {
-  fillCache();
-  for (let key = 0; key < cacheMainList.length; ++key) {
-    const keyword = cacheMainList[key];
-    if(keyword == text) {
-      return true;
-    }
-  }
-  // not in main list, check op
-  for (let op = 0; op < cacheOp.length; op++) {
-    const lOp = cacheOp[op];
-    if(lOp == text) {
-      return true;
-    }
-  }
-  return false;
-}
-
-export function isValidIdentifier (identifier_str) {
-  const validRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(identifier_str);
-  if(!validRegex) {
-    return false;
-  }
-	return !isKeyword(identifier_str);
-}
 
 function fillCache () {
   if(cacheMainList == null) {
@@ -150,10 +126,36 @@ function fillCache () {
   }
 }
 
+export function isKeyword (text) {
+  fillCache();
+  for (let key = 0; key < cacheMainList.length; ++key) {
+    const keyword = cacheMainList[key];
+    if(keyword == text) {
+      return true;
+    }
+  }
+  // not in main list, check op
+  for (let op = 0; op < cacheOp.length; op++) {
+    const lOp = cacheOp[op];
+    if(lOp == text) {
+      return true;
+    }
+  }
+  return false;
+}
+
+export function isValidIdentifier (identifier_str) {
+  const validRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(identifier_str);
+  if(!validRegex) {
+    return false;
+  }
+	return !isKeyword(identifier_str);
+}
+
 export function getCodeEditorModeConfig () {
-  const blockList = ["RK_SWITCH", "RK_PROGRAM","RK_CASE","RK_DEFAULT","RK_FOR",
-    "RK_FUNCTION","RK_DO","RK_WHILE","RK_IF","RK_ELSE"]
-  const keywordsList = ["RK_CONST","RK_RETURN","RK_BREAK","RK_FOR_FROM","RK_FOR_TO","RK_FOR_PASS"];
+  const blockList = ["RK_SWITCH", "RK_PROGRAM","RK_CASE","RK_DEFAULT","RK_FOR","RK_FOR_ALT",
+    "RK_FUNCTION","RK_DO","RK_WHILE","RK_WHILE_ALT","RK_IF","RK_ELSE"]
+  const keywordsList = ["RK_CONST","RK_RETURN","RK_BREAK","RK_FOR_FROM","RK_FOR_TO","RK_FOR_PASS","RK_DO_UNTIL"];
   const typeList = ["RK_REAL","RK_VOID","RK_BOOLEAN","RK_STRING","RK_INTEGER"];
   const atomList = ["RK_FALSE", "RK_TRUE"];
 

+ 1 - 1
js/visualUI/code_generator.js

@@ -384,7 +384,7 @@ function doWhilesCode (command_obj, indentation) {
 		ret += '\t';
 	}
 
-	ret += '} ' + LocalizedStrings.getUI('text_code_while');
+	ret += '} ' + LocalizedStrings.getUI('text_code_do_until');
 
 	if (!command_obj.expression) {
 		Utils.renderErrorMessage(command_obj.expression.dom_object, LocalizedStrings.getUI('inform_valid_expression'));

+ 2 - 2
js/visualUI/commands/dowhiletrue.js

@@ -5,7 +5,7 @@ import * as ContextualizedMenu from './contextualized_menu';
 import * as GenericExpressionManagement from './generic_expression';
 
 export function createFloatingCommand () {
-	return $('<div class="ui dowhiletrue created_element"> <i class="ui icon small sync"></i> <span> '+ LocalizedStrings.getUI('text_command_do') +' <br> ' + LocalizedStrings.getUI('text_code_while') +'(x < 10) </span></div>');
+	return $('<div class="ui dowhiletrue created_element"> <i class="ui icon small sync"></i> <span> '+ LocalizedStrings.getUI('text_command_do') +' <br> ' + LocalizedStrings.getUI('text_command_do_until') +'(x < 10) </span></div>');
 }
 
 export function renderCommand (command, function_obj) {
@@ -13,7 +13,7 @@ export function renderCommand (command, function_obj) {
 	ret += '<div class="ui dowhiletrue command_container"> <i class="ui icon small sync command_drag"></i> <i class="ui icon times red button_remove_command"></i> <div class="ui context_menu"></div>  <span class="span_command_spec"> ' + LocalizedStrings.getUI('text_command_do') + ' </span>';
 	ret += '<div class="ui block_commands" data-subblock="" data-idcommand="">';
 	ret += '</div>';
-	ret += ' <span class="span_command_spec"> ' + LocalizedStrings.getUI('text_code_while') + ' </span> <span class="span_command_spec"> ( </span> <div class="conditional_expression"></div> <span class="span_command_spec"> ) </span>';
+	ret += ' <span class="span_command_spec"> ' + LocalizedStrings.getUI('text_command_do_until') + ' </span> <span class="span_command_spec"> ( </span> <div class="conditional_expression"></div> <span class="span_command_spec"> ) </span>';
 	ret += '</div>';
 
 	var el = $(ret);

+ 2 - 2
js/visualUI/commands/whiletrue.js

@@ -5,12 +5,12 @@ import * as ContextualizedMenu from './contextualized_menu';
 import * as GenericExpressionManagement from './generic_expression';
 
 export function createFloatingCommand () {
-	return $('<div class="ui whiletrue created_element"> <i class="ui icon small sync"></i> <span> ' + LocalizedStrings.getUI('text_code_while') + ' ( x < 10 ) <br> </span></div>');
+	return $('<div class="ui whiletrue created_element"> <i class="ui icon small sync"></i> <span> ' + LocalizedStrings.getUI('text_command_while') + ' ( x < 10 ) <br> </span></div>');
 }
 
 export function renderCommand (command, function_obj) {
 	var ret = '';
-	ret += '<div class="ui whiletrue command_container"> <i class="ui icon small sync command_drag"></i> <i class="ui icon times red button_remove_command"></i> <div class="ui context_menu"></div>  <span class="span_command_spec"> ' + LocalizedStrings.getUI('text_code_while') + ' </span>';
+	ret += '<div class="ui whiletrue command_container"> <i class="ui icon small sync command_drag"></i> <i class="ui icon times red button_remove_command"></i> <div class="ui context_menu"></div>  <span class="span_command_spec"> ' + LocalizedStrings.getUI('text_command_while') + ' </span>';
 	ret += '<span class="span_command_spec"> ( </span> <div class="conditional_expression"></div> <span class="span_command_spec"> ) </span>';
 	ret += ' </span>';
 	ret += '<div class="ui block_commands">';