Browse Source

feat: Implement moo lexer at ast and processor modules

Replace antlr4 code with moo.Lexer equivalent at ivprogParser.js
Replace antlr4 code with moo.Lexer equivalent at semanticAnalyser.js
Fix a bug in the grammar structure regarding i18n rules
Lucas de Souza 2 years ago
parent
commit
7433dcdeaa

+ 2 - 1
.eslintrc.json

@@ -23,7 +23,8 @@
       { "argsIgnorePattern": "^_" }
     ],
     "@typescript-eslint/camelcase": "off",
-    "space-before-function-paren": ["error", "always"]
+    "space-before-function-paren": "off",
+    "@typescript-eslint/space-before-function-paren": ["error", "always"]
   },
   "overrides": [
     {

+ 2 - 2
changeScriptSourcePlugin.js

@@ -6,7 +6,7 @@ function ChangeScriptSourcePlugin () {}
 ChangeScriptSourcePlugin.prototype.apply = function (compiler) {
   compiler.hooks.compilation.tap('ChangeScriptSourcePlugin', function (compilation) {
     console.log('The compiler is starting a new compilation...')
-    // Staic Plugin interface |compilation |HOOK NAME | register listener 
+    // Staic Plugin interface |compilation |HOOK NAME | register listener
     HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync(
       'ChangeScriptSourcePlugin', // <-- Set a meaningful name here for stacktraces
       function (data, cb) {
@@ -26,4 +26,4 @@ ChangeScriptSourcePlugin.prototype.apply = function (compiler) {
   })
 }
 
-module.exports = ChangeScriptSourcePlugin
+module.exports = ChangeScriptSourcePlugin

+ 2 - 1
grammar/en/ivprog.ts

@@ -16,9 +16,10 @@ const types: I18N_LEXER_TYPES = {
   RK_BOOLEAN: "bool",
   RK_CHARACTER: "char",
   RK_STRING: "string",
-  RK_VOID: "void",
 };
 const commands: I18N_LEXER_COMMANDS = {
+  // RK_VOID is not formally part of Types since it doesn't have a valid value/instance
+  RK_VOID: "vazio",
   // commands
   RK_PROGRAM: "program",
   RK_SWITCH: "switch",

+ 77 - 30
grammar/lexer.ts

@@ -4,7 +4,6 @@ import { combineRegex } from "./helper";
 export interface I18N_LEXER_TYPES {
   RK_INTEGER: string;
   RK_REAL: string;
-  RK_VOID: string;
   RK_CHARACTER: string;
   RK_STRING: string;
   RK_BOOLEAN: string;
@@ -23,6 +22,7 @@ export interface I18N_LEXER_LOGICOP {
 
 export interface I18N_LEXER_COMMANDS {
   RK_PROGRAM: string;
+  RK_VOID: string;
   RK_SWITCH: string;
   RK_CASE: string;
   RK_DEFAULT: string;
@@ -95,56 +95,102 @@ export interface I18nLexer {
   langFuncs: I18N_LANG_FUNCS;
 }
 
-// General Regex Rules
-const ID = "[a-zA-Z_][a-zA-Z0-9_]*";
-const HEX_DIGIT = "[0-9a-fA-F]";
-const OCTAL_DIGIT = "[0-7]";
-const ESC_OCTAL = RegExp(
-  `\\\\[0-3]${OCTAL_DIGIT}${OCTAL_DIGIT}|\\\\${OCTAL_DIGIT}${OCTAL_DIGIT}|\\\\${OCTAL_DIGIT}`
-);
-const ESC_UNICODE = RegExp(
-  `\\\\u${HEX_DIGIT}${HEX_DIGIT}${HEX_DIGIT}${HEX_DIGIT}`
-);
-const ESC_SEQ_BASE = /\\[b,t,n,f,r,",',\\]|/;
-const ESC_SEQ = combineRegex`${ESC_SEQ_BASE}|${ESC_UNICODE}|${ESC_OCTAL}`;
-const STRING_CHARACTER = combineRegex`${ESC_SEQ}|[^"\\\\]`;
-
 export class IVProgLexer {
-  constructor(
+  constructor (
     private RKs: Record<string, string>,
     public lexer: moo.Lexer,
+    private rules: I18N_LEXER_RULES,
     private i18nLexer: I18nLexer
   ) {}
 
-  getReservedKeys(): Record<string, string> {
+  getReservedKeys (): Record<string, string> {
     return this.RKs;
   }
 
-  getTypeKeys() {
+  getRules (): I18N_LEXER_RULES {
+    return this.rules;
+  }
+
+  getTypeKeys (): I18N_LEXER_TYPES {
     return this.i18nLexer.types;
   }
 
-  getLangLibs() {
+  getLangLibs (): I18N_LANG_LIBS {
     return this.i18nLexer.langLibs;
   }
 
-  getLangFuncs() {
+  getLangFuncs (): I18N_LANG_FUNCS {
     return this.i18nLexer.langFuncs;
   }
 }
 
-export function makeLexer(lexer: I18nLexer): IVProgLexer {
+export interface I18N_LEXER_RULES
+  extends I18N_LEXER_TYPES,
+    I18N_LEXER_COMMANDS,
+    I18N_LEXER_BOOLVAL,
+    I18N_LEXER_LOGICOP {
+  OPEN_BRACE: string;
+  CLOSE_BRACE: string;
+  OPEN_PARENTHESIS: string;
+  CLOSE_PARENTHESIS: string;
+  OPEN_CURLY: string;
+  CLOSE_CURLY: string;
+  COMMA: string;
+  ASSIGNMENT: string;
+  REAL: string;
+  INTEGER: string;
+  SUM_OP: string;
+  MULTI_OP: string;
+  RELATIONAL_OPERATOR: string;
+  COLON: string;
+  STRING: string;
+  CHARACTER: string;
+  EOS: string;
+  WHITESPACE: string;
+  COMMENTS: string;
+  RK_REFERENCE: string;
+  ID: string;
+  DOT: string;
+  ERROR: string;
+}
+
+// General Regex Rules
+const ID = "[a-zA-Z_][a-zA-Z0-9_]*";
+const HEX_DIGIT = "[0-9a-fA-F]";
+const OCTAL_DIGIT = "[0-7]";
+const ESC_OCTAL = RegExp(
+  `\\\\[0-3]${OCTAL_DIGIT}${OCTAL_DIGIT}|\\\\${OCTAL_DIGIT}${OCTAL_DIGIT}|\\\\${OCTAL_DIGIT}`
+);
+const ESC_UNICODE = RegExp(
+  `\\\\u${HEX_DIGIT}${HEX_DIGIT}${HEX_DIGIT}${HEX_DIGIT}`
+);
+const ESC_SEQ_BASE = /\\[b,t,n,f,r,",',\\]|/;
+const ESC_SEQ = combineRegex`${ESC_SEQ_BASE}|${ESC_UNICODE}|${ESC_OCTAL}`;
+const STRING_CHARACTER = combineRegex`${ESC_SEQ}|[^"\\\\]`;
+
+export function makeLexer (lexer: I18nLexer): IVProgLexer {
   const RKs: Record<string, string> = {};
-  Object.entries(lexer.types).forEach(([key, value]) => (RKs[key] = value));
-  Object.entries(lexer.boolVal).forEach(([key, value]) => (RKs[key] = value));
-  Object.entries(lexer.commands).forEach(([key, value]) => (RKs[key] = value));
+  const rules: Record<string, string> = {};
+  Object.entries(lexer.types).forEach(([key, value]) => {
+    RKs[key] = value;
+    rules[key] = key;
+  });
+  Object.entries(lexer.boolVal).forEach(([key, value]) => {
+    RKs[key] = value;
+    rules[key] = key;
+  });
+  Object.entries(lexer.commands).forEach(([key, value]) => {
+    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;
 
   const RESERVED_KEYS = moo.keywords(RKs);
 
-  const moolexer = moo.compile({
+  const lexerRules: moo.Rules = {
+    COMMENTS: { match: /\/\/[^$]*?$|\/\*[^$]*?\*\//, lineBreaks: true },
     OPEN_BRACE: /\[/,
     CLOSE_BRACE: /\]/,
     OPEN_PARENTHESIS: /\(/,
@@ -161,13 +207,14 @@ export function makeLexer(lexer: I18nLexer): IVProgLexer {
     COLON: /:/,
     STRING: combineRegex`"(?:${STRING_CHARACTER})*?"`,
     CHARACTER: combineRegex`'(?:${ESC_SEQ}|[^'\\\\])'`,
-    // LIB_ID: RegExp(`${ID}\.${ID}`), cannot filter keywords here
     EOS: { match: /;\r?\n?|[\r\n]+/, lineBreaks: true },
     WHITESPACE: /(?: |\t)+/,
-    COMMENTS: { match: /\/\/[^$]*?$|\/\*[^$]*?\*\//, lineBreaks: true },
-    RK_REFERENCE: /&/,
+    RK_REFERENCE: RegExp(lexer.commands.RK_REFERENCE),
     ID: { match: RegExp(ID), type: RESERVED_KEYS },
     DOT: /\./,
-  });
-  return new IVProgLexer(RKs, moolexer, lexer);
+    ERROR: { match: /[\$?`]/, error: true },
+  };
+  Object.entries(lexerRules).forEach(([key, _]) => (rules[key] = key));
+  const moolexer = moo.compile(lexerRules);
+  return new IVProgLexer(RKs, moolexer, rules as unknown as I18N_LEXER_RULES, lexer);
 }

+ 2 - 1
grammar/pt/ivprog.ts

@@ -16,9 +16,10 @@ const types: I18N_LEXER_TYPES = {
   RK_BOOLEAN: "logico",
   RK_CHARACTER: "caractere",
   RK_STRING: "cadeia",
-  RK_VOID: "vazio",
 };
 const commands: I18N_LEXER_COMMANDS = {
+  // RK_VOID is not formally part of Types since it doesn't have a valid value/instance
+  RK_VOID: "vazio",
   // commands
   RK_PROGRAM: "programa",
   RK_SWITCH: "escolha",

File diff suppressed because it is too large
+ 1 - 0
i18n/error.csv


+ 32 - 26
js/ast/error/syntaxErrorFactory.js

@@ -13,97 +13,97 @@ function createError (message_id, context = []) {
 export const SyntaxErrorFactory = Object.freeze({
   extra_lines: () => new SyntaxError(LocalizedStrings.getError("extra_lines")),
   token_missing_one: (expected, token) => {
-    const context = [expected, token.text, token.line, token.column];
+    const context = [expected, token.text, token.line, token.col];
     const error = createError("token_missing_one", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   token_missing_list: (expectedList, token) => {
     const line = expectedList.join(LocalizedStrings.getOR());
     const error = SyntaxErrorFactory.token_missing_one(line, token);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   id_missing: (token) => {
-    const context = [token.text, token.line, token.column];
+    const context = [token.text, token.line, token.col];
     const error = createError("id_missing", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   eos_missing: (token) => {
-    const context = [token.line, token.column];
+    const context = [token.line, token.col];
     const error = createError("eos_missing", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_array_dimension: (typeName, token) => {
-    const context = [token.line, token.column, typeName];
+    const context = [token.line, token.col, typeName];
     const error = createError("invalid_array_dimension", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_array_size: (token) => {
     const context = [token.line];
     const error = createError("invalid_array_size", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_main_return: (name, typeName, token) => {
     const context = [name, typeName, token.line];
     const error = createError("invalid_main_return", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_var_declaration: (token) => {
     const context = [token.line];
     const error = createError("invalid_var_declaration", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_break_command: (cmdName, token) => {
     const context = [token.line, cmdName];
     const error = createError("invalid_break_command", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_terminal: (token) => {
-    const context = [token.text, token.line, token.column];
+    const context = [token.text, token.line, token.col];
     const error = createError("invalid_terminal", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_type: (list, token) => {
     const line = list.join(LocalizedStrings.getOR());
-    const context = [token.text, token.line, token.column, line];
+    const context = [token.text, token.line, token.col, line];
     const error = createError("invalid_type", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   const_not_init: (token) => {
-    const context = [token.line, token.column];
+    const context = [token.line, token.col];
     const error = createError("const_not_init", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_id_format: (token) => {
-    const context = [token.text, token.line, token.column];
+    const context = [token.text, token.line, token.col];
     const error = createError("invalid_id_format", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   duplicate_function: (token) => {
-    const context = [token.text, token.line, token.column];
+    const context = [token.text, token.line, token.col];
     const error = createError("duplicate_function", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   main_parameters: () => {
     return createError("main_parameters");
   },
   duplicate_variable: (token) => {
-    const context = [token.text, token.line, token.column];
+    const context = [token.text, token.line, token.col];
     const error = createError("duplicate_variable", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_character: (text, line, column) => {
@@ -115,7 +115,7 @@ export const SyntaxErrorFactory = Object.freeze({
   annonymous_array_literal: (token) => {
     const context = [token.line];
     const error = createError("annonymous_array_literal", context);
-    error.context = { line: token.line, column: token.column };
+    error.context = { line: token.line, column: token.col};
     return error;
   },
   invalid_matrix_literal_line: (exp, sourceInfo) => {
@@ -184,4 +184,10 @@ export const SyntaxErrorFactory = Object.freeze({
     error.context = { line: sourceInfo.line, column: sourceInfo.column };
     return error;
   },
+  invalid_syntax: (text, line, column) => {
+    const context = [text, line];
+    const error = createError("invalid_syntax", context);
+    error.context = { line: line, column: column };
+    return error;
+  }
 });

+ 197 - 148
js/ast/ivprogParser.js

@@ -1,7 +1,5 @@
-import { CommonTokenStream, InputStream } from "antlr4/index";
 import * as Expressions from "./expressions";
 import * as Commands from "./commands";
-import * as AstHelpers from "./ast_helpers";
 import * as Parsers from "../typeSystem/parsers";
 import { Types } from "../typeSystem/types";
 import { ArrayType } from "../typeSystem/array_type";
@@ -12,9 +10,13 @@ import { LanguageDefinedFunction } from "../processor/definedFunctions";
 import { LanguageService } from "../services/languageService";
 
 export class IVProgParser {
-  static createParser (input) {
-    const lexerClass = LanguageService.getCurrentLexer();
-    return new IVProgParser(input, lexerClass);
+  static createParser (input, fill = true) {
+    const lexer = LanguageService.getCurrentLexer();
+    const parser = new IVProgParser(input, lexer);
+    if (fill) {
+      parser.fill()
+    }
+    return parser
   }
 
   // <BEGIN scope consts>
@@ -32,37 +34,63 @@ export class IVProgParser {
   }
   // </ END scope consts>
 
-  constructor (input, lexerClass) {
-    this.lexerClass = lexerClass;
-    this.inputStream = new InputStream(input);
-    this.lexer = new lexerClass(this.inputStream);
-    this.lexer.recover = AstHelpers.recover.bind(this.lexer);
-    this.tokenStream = new CommonTokenStream(this.lexer);
-    this.tokenStream.fill();
-    this.pos = 1;
-    this.variableTypes = [
-      this.lexerClass.RK_INTEGER,
-      this.lexerClass.RK_REAL,
-      this.lexerClass.RK_BOOLEAN,
-      this.lexerClass.RK_STRING,
-      this.lexerClass.RK_CHARACTER,
-    ];
-    this.functionTypes = this.variableTypes.concat(this.lexerClass.RK_VOID);
+  /**
+   * @param {string} input
+   * @param {IVProgLexer} ivprogLexer
+   **/
+  constructor (input, ivprogLexer) {
+    this.ivprogLexer = ivprogLexer;
+    this.inputStream = input;
+    this.lexer = ivprogLexer.lexer;
+    this.tokenStream = [];
+    this.pos = 0;
+    this.ruleNames = ivprogLexer.getRules();
+    this.variableTypes = Object.entries(this.ivprogLexer.getTypeKeys()).map(
+      ([key, _]) => key
+    );
+    this.functionTypes = this.variableTypes.concat(this.ruleNames.RK_VOID);
+
     this.parsingArrayDimension = 0;
     this.scope = [];
-    this.langFuncs = LanguageService.getCurrentLangFuncs();
+    this.langFuncs = this.ivprogLexer.getLangFuncs();
     this.definedFuncsNameList = [];
     this.definedVariablesStack = [];
   }
 
+  fill (stream = null) {
+    if (stream) {
+      this.tokenStream = stream;
+      return;
+    }
+    this.tokenStream = Array.from(this.lexer.reset(this.inputStream));
+    this.tokenStream = this.tokenStream.filter((token) => {
+      // Throws an exception in case of invalid syntax
+      if (token.type === this.ruleNames.ERROR) {
+        let text = token.text;
+        const line = token.line;
+        const column = token.col;
+        throw SyntaxErrorFactory.invalid_syntax(text, line, column);
+      }
+      // remove all whitespaces token and comments
+      return (
+        token.type !== this.ruleNames.WHITESPACE &&
+        token.type !== this.ruleNames.COMMENTS
+      );
+    });
+  }
+
   parseTree () {
     return this.parseProgram();
   }
 
+  /**
+   * @param {number} index
+   * @return {moo.Token}
+   * */
   getToken (index = this.pos) {
     // if(index === null)
     //   index = this.pos;
-    return this.tokenStream.LT(index);
+    return this.tokenStream[index];
   }
 
   insideScope (scope) {
@@ -94,8 +122,7 @@ export class IVProgParser {
   }
 
   isEOF () {
-    this.getToken(this.pos);
-    return this.tokenStream.fetchedEOF;
+    return this.getToken(this.pos) == null;
   }
 
   parseProgram () {
@@ -104,7 +131,7 @@ export class IVProgParser {
     let globalVars = [];
     let functions = [];
 
-    if (this.lexerClass.RK_PROGRAM === token.type) {
+    if (this.ruleNames.RK_PROGRAM === token.type) {
       this.pos++;
       this.consumeNewLines();
       this.checkOpenCurly();
@@ -114,11 +141,11 @@ export class IVProgParser {
         this.consumeNewLines();
         const token = this.getToken();
         if (
-          token.type === this.lexerClass.RK_CONST ||
+          token.type === this.ruleNames.RK_CONST ||
           this.isVariableType(token)
         ) {
           globalVars = globalVars.concat(this.parseGlobalVariables());
-        } else if (token.type === this.lexerClass.RK_FUNCTION) {
+        } else if (token.type === this.ruleNames.RK_FUNCTION) {
           this.pushVariableStack();
           functions = functions.concat(this.parseFunction());
           this.popVariableStack();
@@ -137,7 +164,7 @@ export class IVProgParser {
       return { global: globalVars, functions: functions };
     } else {
       throw SyntaxErrorFactory.token_missing_one(
-        this.lexer.literalNames[this.lexerClass.RK_PROGRAM],
+        this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_PROGRAM],
         token
       );
     }
@@ -145,7 +172,7 @@ export class IVProgParser {
 
   checkOpenCurly (attempt = false) {
     const token = this.getToken();
-    if (this.lexerClass.OPEN_CURLY !== token.type) {
+    if (this.ruleNames.OPEN_CURLY !== token.type) {
       if (!attempt) throw SyntaxErrorFactory.token_missing_one("{", token);
       else return false;
     }
@@ -154,7 +181,7 @@ export class IVProgParser {
 
   checkCloseCurly (attempt = false) {
     const token = this.getToken();
-    if (this.lexerClass.CLOSE_CURLY !== token.type) {
+    if (this.ruleNames.CLOSE_CURLY !== token.type) {
       if (!attempt) throw SyntaxErrorFactory.token_missing_one("}", token);
       else return false;
     }
@@ -171,7 +198,7 @@ export class IVProgParser {
    **/
   checkOpenBrace (attempt = false) {
     const token = this.getToken();
-    if (this.lexerClass.OPEN_BRACE !== token.type) {
+    if (this.ruleNames.OPEN_BRACE !== token.type) {
       if (!attempt) {
         throw SyntaxErrorFactory.token_missing_one("[", token);
       } else {
@@ -183,7 +210,7 @@ export class IVProgParser {
 
   checkCloseBrace (attempt = false) {
     const token = this.getToken();
-    if (this.lexerClass.CLOSE_BRACE !== token.type) {
+    if (this.ruleNames.CLOSE_BRACE !== token.type) {
       if (!attempt) {
         throw SyntaxErrorFactory.token_missing_one("]", token);
       } else {
@@ -195,7 +222,7 @@ export class IVProgParser {
 
   checkOpenParenthesis (attempt = false) {
     const token = this.getToken();
-    if (this.lexerClass.OPEN_PARENTHESIS !== token.type) {
+    if (this.ruleNames.OPEN_PARENTHESIS !== token.type) {
       if (!attempt) {
         throw SyntaxErrorFactory.token_missing_one("(", token);
       } else {
@@ -207,7 +234,7 @@ export class IVProgParser {
 
   checkCloseParenthesis (attempt = false) {
     const token = this.getToken();
-    if (this.lexerClass.CLOSE_PARENTHESIS !== token.type) {
+    if (this.ruleNames.CLOSE_PARENTHESIS !== token.type) {
       if (!attempt) {
         throw SyntaxErrorFactory.token_missing_one(")", token);
       } else {
@@ -219,7 +246,7 @@ export class IVProgParser {
 
   checkEOS (attempt = false) {
     const eosToken = this.getToken();
-    if (eosToken.type !== this.lexerClass.EOS) {
+    if (eosToken.type !== this.ruleNames.EOS) {
       if (!attempt) throw SyntaxErrorFactory.eos_missing(eosToken);
       else return false;
     }
@@ -245,7 +272,7 @@ export class IVProgParser {
 
   consumeForSemiColon () {
     const eosToken = this.getToken();
-    if (eosToken.type === this.lexerClass.EOS && eosToken.text.match(";")) {
+    if (eosToken.type === this.ruleNames.EOS && eosToken.text.match("^;$")) {
       this.pos++;
       return;
     }
@@ -266,7 +293,7 @@ export class IVProgParser {
    **/
   parseMaybeConst () {
     const constToken = this.getToken();
-    if (constToken.type === this.lexerClass.RK_CONST) {
+    if (constToken.type === this.ruleNames.RK_CONST) {
       this.pos++;
       const typeString = this.parseType();
       return this.parseDeclaration(typeString, true);
@@ -275,7 +302,7 @@ export class IVProgParser {
       return this.parseDeclaration(typeString);
     } else {
       throw SyntaxErrorFactory.token_missing_list(
-        [this.lexer.literalNames[this.lexerClass.RK_CONST]].concat(
+        [this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_CONST]].concat(
           this.getTypeArray()
         ),
         constToken
@@ -283,9 +310,9 @@ export class IVProgParser {
     }
   }
 
-  /*
+  /**
    * Parses a declarion of the form: type --- id --- (= --- EAnd)?
-   * @returns a list of Declararion(const, type, id, initVal?)
+   * @return {Commands.Declartion[]} a list of Declararion(const, type, id, initVal?)
    **/
   parseDeclaration (typeString, isConst = false) {
     let initial = null;
@@ -324,11 +351,11 @@ export class IVProgParser {
         dim2
       );
     } else {
-      const equalsToken = this.getToken();
-      if (isConst && equalsToken.type !== this.lexerClass.EQUAL) {
+      const assignmentToken = this.getToken();
+      if (isConst && assignmentToken.type !== this.ruleNames.ASSIGNMENT) {
         throw SyntaxErrorFactory.const_not_init(sourceInfo);
       }
-      if (equalsToken.type === this.lexerClass.EQUAL) {
+      if (assignmentToken.type === this.ruleNames.ASSIGNMENT) {
         this.pos++;
         initial = this.parseExpressionOR();
       }
@@ -340,7 +367,7 @@ export class IVProgParser {
       );
       declaration.sourceInfo = sourceInfo;
       const commaToken = this.getToken();
-      if (commaToken.type === this.lexerClass.COMMA) {
+      if (commaToken.type === this.ruleNames.COMMA) {
         this.pos++;
         this.consumeNewLines();
         return [declaration].concat(this.parseDeclaration(typeString, isConst));
@@ -359,7 +386,7 @@ export class IVProgParser {
     dim1,
     dim2
   ) {
-    const equalsToken = this.getToken();
+    const assignmentToken = this.getToken();
     let n_lines = dim1;
     let n_columns = dim2;
     let initial = null;
@@ -371,22 +398,22 @@ export class IVProgParser {
       dim_is_id = true;
       if (dimensions > 1 && (dim1 == null || dim2 == null)) {
         throw SyntaxErrorFactory.invalid_matrix_id_dimension(
-          SourceInfo.createSourceInfo(equalsToken)
+          SourceInfo.createSourceInfo(assignmentToken)
         );
       }
     }
-    if (isConst && equalsToken.type !== this.lexerClass.EQUAL) {
+    if (isConst && assignmentToken.type !== this.ruleNames.ASSIGNMENT) {
       throw SyntaxErrorFactory.const_not_init(sourceInfo);
     }
-    if (equalsToken.type === this.lexerClass.EQUAL) {
+    if (assignmentToken.type === this.ruleNames.ASSIGNMENT) {
       if (dim_is_id) {
         if (dimensions == 1) {
           throw SyntaxErrorFactory.invalid_vector_init(
-            SourceInfo.createSourceInfo(equalsToken)
+            SourceInfo.createSourceInfo(assignmentToken)
           );
         } else {
           throw SyntaxErrorFactory.invalid_matrix_init(
-            SourceInfo.createSourceInfo(equalsToken)
+            SourceInfo.createSourceInfo(assignmentToken)
           );
         }
       }
@@ -445,7 +472,7 @@ export class IVProgParser {
     );
     declaration.sourceInfo = sourceInfo;
     const commaToken = this.getToken();
-    if (commaToken.type === this.lexerClass.COMMA) {
+    if (commaToken.type === this.ruleNames.COMMA) {
       this.pos++;
       this.consumeNewLines();
       return [declaration].concat(this.parseDeclaration(typeString, isConst));
@@ -456,7 +483,11 @@ export class IVProgParser {
 
   consumeNewLines () {
     let token = this.getToken();
-    while (token.type === this.lexerClass.EOS && token.text.match("[\r\n]+")) {
+    while (
+      token &&
+      token.type === this.ruleNames.EOS &&
+      token.text.match("^[\r\n]+$")
+    ) {
       this.pos++;
       token = this.getToken();
     }
@@ -466,34 +497,35 @@ export class IVProgParser {
     return this.variableTypes.find((v) => v === token.type);
   }
 
-  /*
+  /**
    * Reads the next token of the stream to check if it is a Integer or an ID.
    * @returns Integer | ID
    **/
   parseArrayDimension () {
     const dimToken = this.getToken();
-    if (dimToken.type === this.lexerClass.INTEGER) {
+    if (dimToken.type === this.ruleNames.INTEGER) {
       //parse as int literal
       this.pos++;
       return this.getIntLiteral(dimToken);
-    } else if (dimToken.type === this.lexerClass.ID) {
+    } else if (dimToken.type === this.ruleNames.ID) {
       //parse as variable
       this.pos++;
       return this.parseVariable(dimToken);
-    } else if (dimToken.type === this.lexerClass.CLOSE_BRACE) {
+    } else if (dimToken.type === this.ruleNames.CLOSE_BRACE) {
       return null;
     } else {
       throw SyntaxErrorFactory.invalid_array_dimension(
-        this.lexer.literalNames[this.lexerClass.RK_INTEGER],
+        this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_INTEGER],
         dimToken
       );
     }
   }
 
-  /*
+  /**
    * Returns an object {type: 'int', value: value}.
    * It checks for binary and hexadecimal integers.
-   * @returns object with fields type and value
+   * @param {moo.Token} token
+   * @return {Object} object with fields type and value
    **/
   getIntLiteral (token) {
     const text = token.text;
@@ -608,9 +640,9 @@ export class IVProgParser {
       if (lastSize == null) {
         lastSize = data.length;
       } else if (lastSize !== data.length) {
-        const expString = this.inputStream.getText(
-          beginArray.start,
-          endArray.stop
+        const expString = this.inputStream.substring(
+          beginArray.offset,
+          endArray.offset + endArray.text.length
         );
         throw SyntaxErrorFactory.invalid_matrix_literal_line(
           expString,
@@ -622,7 +654,7 @@ export class IVProgParser {
       exp.sourceInfo = sourceInfo;
       list.push(exp);
       const commaToken = this.getToken();
-      if (commaToken.type !== this.lexerClass.COMMA) {
+      if (commaToken.type !== this.ruleNames.COMMA) {
         break;
       }
       this.pos += 1;
@@ -654,7 +686,7 @@ export class IVProgParser {
     this.pushScope(IVProgParser.FUNCTION);
     let formalParams = [];
     const token = this.getToken();
-    if (token.type !== this.lexerClass.RK_FUNCTION) {
+    if (token.type !== this.ruleNames.RK_FUNCTION) {
       //throw SyntaxError.createError(this.lexer.literalNames[this.lexerClass.PR_FUNCAO], token);
       return null;
     }
@@ -702,7 +734,7 @@ export class IVProgParser {
     if (functionID === null && !func.isMain) {
       throw SyntaxErrorFactory.invalid_main_return(
         LanguageDefinedFunction.getMainFunctionName(),
-        this.lexer.literalNames[this.lexerClass.RK_VOID],
+        this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_VOID],
         token.line
       );
     } else if (func.isMain && formalParams.length !== 0) {
@@ -723,7 +755,7 @@ export class IVProgParser {
       let reference = false;
       const typeString = this.parseType();
       let maybeIDToken = this.getToken();
-      if (maybeIDToken.type === this.lexerClass.RK_REFERENCE) {
+      if (maybeIDToken.type === this.ruleNames.RK_REFERENCE) {
         reference = true;
         this.pos += 1;
         maybeIDToken = this.getToken();
@@ -752,7 +784,7 @@ export class IVProgParser {
       parameter.sourceInfo = SourceInfo.createSourceInfo(maybeIDToken);
       list.push(parameter);
       const commaToken = this.getToken();
-      if (commaToken.type !== this.lexerClass.COMMA) break;
+      if (commaToken.type !== this.ruleNames.COMMA) break;
       this.pos++;
       this.consumeNewLines();
     }
@@ -761,7 +793,7 @@ export class IVProgParser {
 
   parseID () {
     const token = this.getToken();
-    if (token.type !== this.lexerClass.ID) {
+    if (token.type !== this.ruleNames.ID) {
       throw SyntaxErrorFactory.id_missing(token);
     }
     this.pos++;
@@ -773,14 +805,24 @@ export class IVProgParser {
     return token.text;
   }
 
+  /**
+   * @return {string}
+   **/
   parseMaybeLibID () {
     const token = this.getToken();
-    if (
-      token.type !== this.lexerClass.ID &&
-      token.type !== this.lexerClass.LIB_ID
-    ) {
+    if (token.type !== this.ruleNames.ID) {
       throw SyntaxErrorFactory.id_missing(token);
     }
+    const maybeDOT = this.getToken(this.pos + 1);
+    if (maybeDOT.type === this.ruleNames.DOT) {
+      this.pos += 2;
+      const anotherID = this.getToken();
+      if (anotherID.type !== this.ruleNames.ID) {
+        throw SyntaxErrorFactory.id_missing(anotherID);
+      }
+      this.pos++;
+      return `${token.text}.${anotherID.text}`;
+    }
     this.pos++;
     return token.text;
   }
@@ -788,12 +830,12 @@ export class IVProgParser {
   parseType () {
     const token = this.getToken();
     if (
-      token.type === this.lexerClass.ID &&
+      token.type === this.ruleNames.ID &&
       this.insideScope(IVProgParser.FUNCTION)
     ) {
       return Types.VOID;
     } else if (
-      token.type === this.lexerClass.RK_VOID &&
+      token.type === this.ruleNames.RK_VOID &&
       this.insideScope(IVProgParser.FUNCTION)
     ) {
       this.pos++;
@@ -801,15 +843,15 @@ export class IVProgParser {
     } else if (this.isVariableType(token)) {
       this.pos++;
       switch (token.type) {
-        case this.lexerClass.RK_INTEGER:
+        case this.ruleNames.RK_INTEGER:
           return Types.INTEGER;
-        case this.lexerClass.RK_BOOLEAN:
+        case this.ruleNames.RK_BOOLEAN:
           return Types.BOOLEAN;
-        case this.lexerClass.RK_REAL:
+        case this.ruleNames.RK_REAL:
           return Types.REAL;
-        case this.lexerClass.RK_STRING:
+        case this.ruleNames.RK_STRING:
           return Types.STRING;
-        case this.lexerClass.RK_CHARACTER:
+        case this.ruleNames.RK_CHARACTER:
           return Types.CHAR;
         default:
           break;
@@ -867,35 +909,40 @@ export class IVProgParser {
       this.checkEOS();
       this.pos++;
       return cmd;
-    } else if (token.type === this.lexerClass.ID) {
-      return this.parseIDCommand();
-    } else if (token.type === this.lexerClass.LIB_ID) {
+    } else if (token.type === this.ruleNames.ID) {
       return this.parseIDCommand();
-    } else if (token.type === this.lexerClass.RK_RETURN) {
+    } else if (token.type === this.ruleNames.DOT) {
+      // TODO Check if this is relevant since DOT is a replacement for antlr4 LIB_ID :=> ID . ID
+      throw SyntaxErrorFactory.invalid_syntax(
+        token.text,
+        token.line,
+        token.col
+      );
+    } else if (token.type === this.ruleNames.RK_RETURN) {
       return this.parseReturn();
     } else if (
-      token.type === this.lexerClass.RK_WHILE ||
-      token.type === this.lexerClass.RK_WHILE_ALT
+      token.type === this.ruleNames.RK_WHILE ||
+      token.type === this.ruleNames.RK_WHILE_ALT
     ) {
       return this.parseWhile();
     } else if (
-      token.type === this.lexerClass.RK_FOR ||
-      token.type === this.lexerClass.RK_FOR_ALT
+      token.type === this.ruleNames.RK_FOR ||
+      token.type === this.ruleNames.RK_FOR_ALT
     ) {
       return this.parseFor();
-    } else if (token.type === this.lexerClass.RK_BREAK) {
+    } else if (token.type === this.ruleNames.RK_BREAK) {
       if (!this.insideScope(IVProgParser.BREAKABLE)) {
         throw SyntaxErrorFactory.invalid_break_command(
-          this.lexer.literalNames[this.lexerClass.RK_BREAK],
+          this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_BREAK],
           token
         );
       }
       return this.parseBreak();
-    } else if (token.type === this.lexerClass.RK_SWITCH) {
+    } else if (token.type === this.ruleNames.RK_SWITCH) {
       return this.parseSwitchCase();
-    } else if (token.type === this.lexerClass.RK_DO) {
+    } else if (token.type === this.ruleNames.RK_DO) {
       return this.parseRepeatUntil();
-    } else if (token.type === this.lexerClass.RK_IF) {
+    } else if (token.type === this.ruleNames.RK_IF) {
       return this.parseIfThenElse();
     } else if (this.checkEOS(true)) {
       this.pos++;
@@ -936,9 +983,9 @@ export class IVProgParser {
     const commandsBlock = this.parseCommandBlock();
     this.consumeNewLines(); //Maybe not...
     const whileToken = this.getToken();
-    if (whileToken.type !== this.lexerClass.RK_DO_UNTIL) {
+    if (whileToken.type !== this.ruleNames.RK_DO_UNTIL) {
       throw SyntaxErrorFactory.token_missing_one(
-        this.lexer.literalNames[this.lexerClass.RK_DO_UNTIL],
+        this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_DO_UNTIL],
         whileToken
       );
     }
@@ -974,18 +1021,18 @@ export class IVProgParser {
     const cmdBlocks = this.parseCommandBlock();
 
     const maybeElse = this.getToken();
-    if (maybeElse.type === this.lexerClass.RK_ELSE) {
+    if (maybeElse.type === this.ruleNames.RK_ELSE) {
       this.pos++;
       this.consumeNewLines();
       const maybeIf = this.getToken();
       let elseBlock = null;
       if (this.checkOpenCurly(true)) {
         elseBlock = this.parseCommandBlock();
-      } else if (maybeIf.type === this.lexerClass.RK_IF) {
+      } else if (maybeIf.type === this.ruleNames.RK_IF) {
         elseBlock = this.parseIfThenElse();
       } else {
         throw SyntaxErrorFactory.token_missing_list(
-          [this.lexer.literalNames[this.lexerClass.RK_IF], "{"],
+          [this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_IF], "{"],
           maybeIf
         );
       }
@@ -1015,9 +1062,9 @@ export class IVProgParser {
     const for_id = new Expressions.VariableLiteral(id);
     for_id.sourceInfo = SourceInfo.createSourceInfo(id_token);
     // END parse ID
-    const for_from = this.parseForParameters(this.lexerClass.RK_FOR_FROM);
-    const for_to = this.parseForParameters(this.lexerClass.RK_FOR_TO);
-    const maybePass = this.parseForParameters(this.lexerClass.RK_FOR_PASS);
+    const for_from = this.parseForParameters(this.ruleNames.RK_FOR_FROM);
+    const for_to = this.parseForParameters(this.ruleNames.RK_FOR_TO);
+    const maybePass = this.parseForParameters(this.ruleNames.RK_FOR_PASS);
     this.consumeNewLines();
     const commandsBlock = this.parseCommandBlock();
     this.popScope();
@@ -1074,8 +1121,8 @@ export class IVProgParser {
 
   parseIDCommand () {
     const refToken = this.getToken();
-    const isID = refToken.type === this.lexerClass.ID;
     const id = this.parseMaybeLibID();
+    const isID = id.indexOf(".") === -1;
     if (this.checkOpenBrace(true)) {
       this.pos++;
       let lineExpression = null;
@@ -1093,9 +1140,10 @@ export class IVProgParser {
         this.checkCloseBrace();
         this.pos++;
       }
-      const equalToken = this.getToken();
-      if (equalToken.type !== this.lexerClass.EQUAL) {
-        throw SyntaxErrorFactory.token_missing_one("=", equalToken);
+      const assignmentToken = this.getToken();
+      if (assignmentToken.type !== this.ruleNames.ASSIGNMENT) {
+        // TODO BETTER MESSAGE
+        throw SyntaxErrorFactory.token_missing_one("<-", assignmentToken);
       }
       this.pos++;
       const exp = this.parseExpressionOR();
@@ -1107,27 +1155,29 @@ export class IVProgParser {
         columnExpression,
         exp
       );
-      cmd.sourceInfo = SourceInfo.createSourceInfo(equalToken);
+      cmd.sourceInfo = SourceInfo.createSourceInfo(assignmentToken);
       return cmd;
     }
-    const equalOrParenthesis = this.getToken();
-    if (isID && equalOrParenthesis.type === this.lexerClass.EQUAL) {
+    const assignmentOrParenthesis = this.getToken();
+    if (isID && assignmentOrParenthesis.type === this.ruleNames.ASSIGNMENT) {
       this.pos++;
       const exp = this.parseExpressionOR();
       this.checkEOS();
       this.pos++;
       const cmd = new Commands.Assign(id, exp);
-      cmd.sourceInfo = SourceInfo.createSourceInfo(equalOrParenthesis);
+      cmd.sourceInfo = SourceInfo.createSourceInfo(assignmentOrParenthesis);
       return cmd;
-    } else if (equalOrParenthesis.type === this.lexerClass.OPEN_PARENTHESIS) {
+    } else if (
+      assignmentOrParenthesis.type === this.ruleNames.OPEN_PARENTHESIS
+    ) {
       const funcCall = this.parseFunctionCallCommand(id);
       this.checkEOS();
       this.pos++;
       return funcCall;
     } else if (isID) {
       throw SyntaxErrorFactory.token_missing_list(
-        ["=", "("],
-        equalOrParenthesis
+        ["<-", "("],
+        assignmentOrParenthesis
       );
     } else {
       throw SyntaxErrorFactory.invalid_id_format(refToken);
@@ -1135,7 +1185,7 @@ export class IVProgParser {
   }
 
   parseForParameters (keyword_code) {
-    if (keyword_code === this.lexerClass.RK_FOR_PASS) {
+    if (keyword_code === this.ruleNames.RK_FOR_PASS) {
       if (this.checkOpenCurly(true)) {
         return null;
       }
@@ -1143,7 +1193,7 @@ export class IVProgParser {
     const from_token = this.getToken();
     if (from_token.type !== keyword_code) {
       // TODO better error message
-      const keyword = this.lexer.literalNames[keyword_code];
+      const keyword = this.ivprogLexer.getReservedKeys()[keyword_code];
       throw new Error(
         "Error de sintaxe no comando repita_para: esperava-se " +
           keyword +
@@ -1155,23 +1205,23 @@ export class IVProgParser {
     let int_or_id = this.getToken();
     let is_unary_op = false;
     let op = null;
-    if (int_or_id.type === this.lexerClass.SUM_OP) {
+    if (int_or_id.type === this.ruleNames.SUM_OP) {
       is_unary_op = true;
       op = int_or_id.text;
       this.pos += 1;
       int_or_id = this.getToken();
     }
     let for_from = null;
-    if (int_or_id.type === this.lexerClass.ID) {
+    if (int_or_id.type === this.ruleNames.ID) {
       for_from = new Expressions.VariableLiteral(this.parseID());
       for_from.sourceInfo = SourceInfo.createSourceInfo(int_or_id);
-    } else if (int_or_id.type === this.lexerClass.INTEGER) {
+    } else if (int_or_id.type === this.ruleNames.INTEGER) {
       this.pos += 1;
       for_from = this.getIntLiteral(int_or_id);
     }
     if (for_from == null) {
       // TODO better error message
-      const keyword = this.lexer.literalNames[keyword_code];
+      const keyword = this.ivprogLexer.getReservedKeys()[keyword_code];
       throw new Error(
         "Error de sintaxe no comando repeita_para: " +
           int_or_id.text +
@@ -1188,18 +1238,18 @@ export class IVProgParser {
 
   parseCases () {
     const token = this.getToken();
-    if (token.type !== this.lexerClass.RK_CASE) {
+    if (token.type !== this.ruleNames.RK_CASE) {
       throw SyntaxErrorFactory.token_missing_one(
-        this.lexer.literalNames[this.lexerClass.RK_CASE],
+        this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_CASE],
         token
       );
     }
     this.pos++;
     const nextToken = this.getToken();
-    if (nextToken.type === this.lexerClass.RK_DEFAULT) {
+    if (nextToken.type === this.ruleNames.RK_DEFAULT) {
       this.pos++;
       const colonToken = this.getToken();
-      if (colonToken.type !== this.lexerClass.COLON) {
+      if (colonToken.type !== this.ruleNames.COLON) {
         throw SyntaxErrorFactory.token_missing_one(":", colonToken);
       }
       this.pos++;
@@ -1211,7 +1261,7 @@ export class IVProgParser {
     } else {
       const exp = this.parseExpressionOR();
       const colonToken = this.getToken();
-      if (colonToken.type !== this.lexerClass.COLON) {
+      if (colonToken.type !== this.ruleNames.COLON) {
         throw SyntaxErrorFactory.token_missing_one(":", colonToken);
       }
       this.pos++;
@@ -1220,7 +1270,7 @@ export class IVProgParser {
       const aCase = new Commands.Case(exp);
       aCase.setCommands(block.commands);
       const caseToken = this.getToken();
-      if (caseToken.type === this.lexerClass.RK_CASE) {
+      if (caseToken.type === this.ruleNames.RK_CASE) {
         return [aCase].concat(this.parseCases());
       } else {
         return [aCase];
@@ -1233,21 +1283,21 @@ export class IVProgParser {
    *
    * EOR  => EAnd ( 'or' EOR)? #expression and
    *
-   * EOR   => ENot ('and' EOR)? #expression or
+   * EAnd   => ENot ('and' EAnd)? #expression or
    *
    * ENot  => 'not'? ER #expression not
    *
-   * ER    => E ((>=, <=, ==, >, <) E)? #expression relational
+   * ER    => E ((>=, <=, ==, >, <) ER)? #expression relational
    *
    * E     => factor ((+, -) E)? #expression
    *
    * factor=> term ((*, /, %) factor)?
    *
-   * term  => literal || arrayAccess || FuncCall || ID || '('EAnd')'
+   * term  => literal || arrayAccess || FuncCall || ID || '('EOR')'
    **/
   parseExpressionOR () {
     let exp1 = this.parseExpressionAND();
-    while (this.getToken().type === this.lexerClass.OR_OPERATOR) {
+    while (this.getToken().type === this.ruleNames.OR_OPERATOR) {
       const opToken = this.getToken();
       this.pos++;
       const or = convertFromString("or");
@@ -1262,7 +1312,7 @@ export class IVProgParser {
 
   parseExpressionAND () {
     let exp1 = this.parseExpressionNot();
-    while (this.getToken().type === this.lexerClass.AND_OPERATOR) {
+    while (this.getToken().type === this.ruleNames.AND_OPERATOR) {
       const opToken = this.getToken();
       this.pos++;
       const and = convertFromString("and");
@@ -1277,7 +1327,7 @@ export class IVProgParser {
 
   parseExpressionNot () {
     const maybeNotToken = this.getToken();
-    if (maybeNotToken.type === this.lexerClass.NOT_OPERATOR) {
+    if (maybeNotToken.type === this.ruleNames.NOT_OPERATOR) {
       const opToken = this.getToken();
       this.pos++;
       const not = convertFromString("not");
@@ -1292,7 +1342,7 @@ export class IVProgParser {
 
   parseExpressionRel () {
     let exp1 = this.parseExpression();
-    while (this.getToken().type === this.lexerClass.RELATIONAL_OPERATOR) {
+    while (this.getToken().type === this.ruleNames.RELATIONAL_OPERATOR) {
       const relToken = this.getToken();
       this.pos++;
       const rel = convertFromString(relToken.text);
@@ -1306,7 +1356,7 @@ export class IVProgParser {
 
   parseExpression () {
     let factor = this.parseFactor();
-    while (this.getToken().type === this.lexerClass.SUM_OP) {
+    while (this.getToken().type === this.ruleNames.SUM_OP) {
       const sumOpToken = this.getToken();
       this.pos++;
       const op = convertFromString(sumOpToken.text);
@@ -1320,7 +1370,7 @@ export class IVProgParser {
 
   parseFactor () {
     let term = this.parseTerm();
-    while (this.getToken().type === this.lexerClass.MULTI_OP) {
+    while (this.getToken().type === this.ruleNames.MULTI_OP) {
       const multOpToken = this.getToken();
       this.pos++;
       const op = convertFromString(multOpToken.text);
@@ -1337,7 +1387,7 @@ export class IVProgParser {
     let sourceInfo = null;
     let exp = null;
     switch (token.type) {
-      case this.lexerClass.SUM_OP:
+      case this.ruleNames.SUM_OP:
         this.pos++;
         sourceInfo = SourceInfo.createSourceInfo(token);
         exp = new Expressions.UnaryApp(
@@ -1346,30 +1396,29 @@ export class IVProgParser {
         );
         exp.sourceInfo = sourceInfo;
         return exp;
-      case this.lexerClass.INTEGER:
+      case this.ruleNames.INTEGER:
         this.pos++;
         return this.getIntLiteral(token);
-      case this.lexerClass.REAL:
+      case this.ruleNames.REAL:
         this.pos++;
         return this.getRealLiteral(token);
-      case this.lexerClass.STRING:
+      case this.ruleNames.STRING:
         this.pos++;
         return this.getStringLiteral(token);
-      case this.lexerClass.CHARACTER:
+      case this.ruleNames.CHARACTER:
         this.pos++;
         return this.getCharLiteral(token);
-      case this.lexerClass.RK_TRUE:
-      case this.lexerClass.RK_FALSE:
+      case this.ruleNames.RK_TRUE:
+      case this.ruleNames.RK_FALSE:
         this.pos++;
         return this.getBoolLiteral(token);
-      case this.lexerClass.OPEN_CURLY:
+      case this.ruleNames.OPEN_CURLY:
         // No more annonymous array
         // return this.parseArrayLiteral();
         throw SyntaxErrorFactory.annonymous_array_literal(token);
-      case this.lexerClass.ID:
-      case this.lexerClass.LIB_ID:
+      case this.ruleNames.ID:
         return this.parseIDTerm();
-      case this.lexerClass.OPEN_PARENTHESIS:
+      case this.ruleNames.OPEN_PARENTHESIS:
         return this.parseParenthesisExp();
       default:
         throw SyntaxErrorFactory.invalid_terminal(token);
@@ -1379,7 +1428,7 @@ export class IVProgParser {
   parseIDTerm () {
     const tokenA = this.getToken();
     const id = this.parseMaybeLibID();
-    const isID = tokenA.type === this.lexerClass.ID;
+    const isID = id.indexOf(".") === -1;
     if (isID && this.checkOpenBrace(true)) {
       let tokenB = null;
       this.pos++;
@@ -1426,7 +1475,8 @@ export class IVProgParser {
   }
 
   parseFunctionCallExpression (id) {
-    const tokenA = this.getToken(this.pos - 1);
+    const stepBack = id.indexOf(".") === -1 ? 1 : 3;
+    const tokenA = this.getToken(this.pos - stepBack);
     const actualParameters = this.parseActualParameters();
     const tokenB = this.getToken(this.pos - 1);
     const funcName = this.getFunctionName(id);
@@ -1443,7 +1493,6 @@ export class IVProgParser {
   parseParenthesisExp () {
     this.checkOpenParenthesis();
     const tokenA = this.getToken();
-    this.pos += 1;
     this.consumeNewLines();
     const exp = this.parseExpressionOR();
     this.consumeNewLines();
@@ -1476,7 +1525,7 @@ export class IVProgParser {
       const exp = this.parseExpressionOR();
       list.push(exp);
       const maybeToken = this.getToken();
-      if (maybeToken.type !== this.lexerClass.COMMA) {
+      if (maybeToken.type !== this.ruleNames.COMMA) {
         break;
       } else {
         this.pos++;

+ 21 - 4
js/ast/sourceInfo.js

@@ -1,18 +1,35 @@
 export class SourceInfo {
 
+  /**
+    * @param {moo.Token} token
+    *
+    * @return {SourceInfo}
+    * **/
   static createSourceInfo (token) {
-    return new SourceInfo(token.line, token.column, token.text, token.text.length);
+    return new SourceInfo(token.line, token.col, token.text, token.text.length);
   }
 
+  /**
+    * @param {moo.Token} tokenA
+    * @param {moo.Token} tokenB
+    *
+    * @return {SourceInfo}
+    * **/
   static createSourceInfoFromList (tokenA, tokenB) {
     const line = tokenA.line;
-    const column = tokenA.column;
+    const column = tokenA.col;
     // adapted from https://github.com/UNIVALI-LITE/Portugol-Studio/blob/master/core/src/main/java/br/univali/portugol/nucleo/analise/sintatica/Portugol.g
     // No idea why...
-    const size = tokenB.tokenIndex + 1 - tokenA.tokenIndex
+    const size = tokenB.offset + 1 - tokenA.offset
     return new SourceInfo(line, column, "", size);
   }
 
+  /**
+   * @param {number} line
+   * @param {number} column
+   * @param {string} text
+   * @param {number} size
+    * **/
   constructor (line, column, text, size) {
     this.line = line;
     this.column = column;
@@ -20,4 +37,4 @@ export class SourceInfo {
     this.size = size;
   }
 
-}
+}

+ 2 - 1
js/main.js

@@ -24,7 +24,7 @@ import {
 import { openAssessmentDetail, levenshteinDistance } from "./util/utils";
 import { Config } from "./util/config";
 import { processData } from "./util/dataProcess";
-import { parseExpression } from "./util/parseFromVisual";
+import { parseExpression, parseCode } from "./util/parseFromVisual";
 import * as CodeEditorAll from "./visualUI/text_editor";
 import { autoGenerateTestCaseOutput } from "./util/auto_gen_output";
 import { generate } from "./visualUI/code_generator";
@@ -63,6 +63,7 @@ export {
   autoGenerateTestCaseOutput,
   Config,
   parseExpression,
+  parseCode,
   generate as generateCode,
   levenshteinDistance,
   processData,

+ 0 - 4
js/processor/semantic/semanticAnalyser.js

@@ -1,6 +1,5 @@
 import { ProcessorErrorFactory } from "./../error/processorErrorFactory";
 import { LanguageDefinedFunction } from "./../definedFunctions";
-import { LanguageService } from "./../../services/languageService";
 import {
   ArrayDeclaration,
   While,
@@ -47,9 +46,6 @@ export class SemanticAnalyser {
 
   constructor (ast) {
     this.ast = ast;
-    this.lexerClass = LanguageService.getCurrentLexer();
-    const lexer = new this.lexerClass(null);
-    this.literalNames = lexer.literalNames;
     this.symbolMap = null;
     this.currentFunction = null;
   }

+ 4 - 4
js/runner.js

@@ -1,12 +1,10 @@
 import { IVProgParser } from './ast/ivprogParser';
 import { IVProgProcessor } from './processor/ivprogProcessor';
 import {DOMConsole} from './io/domConsole';
-import { LanguageService } from './services/languageService';
 import { SemanticAnalyser } from './processor/semantic/semanticAnalyser';
 import { Location } from "./memory/location";
 
 export function runner () {
-const ivprogLexer = LanguageService.getCurrentLexer();
 
 
 // const lexer = new ivprogLexer(new InputStream(input));
@@ -29,8 +27,10 @@ domConsole.hide();
 try {
   window.$('#btn').click( () => {
     const input = window.$('#input').val();
-    const analiser = new IVProgParser(input, ivprogLexer);
+    const analiser = IVProgParser.createParser(input);
     try {
+      analiser.fill();
+      //console.debug(analiser.tokenStream)
       const data = analiser.parseTree();
       const semAna = new SemanticAnalyser(data);
       const proc = new IVProgProcessor(semAna.analyseTree());
@@ -51,7 +51,7 @@ try {
       console.log(error);
       console.log(Location.size());
     }
-    
+
   });
 } catch(a) {
   console.log(a);

+ 6 - 6
js/services/languageService.ts

@@ -1,4 +1,4 @@
-declare var iLMparameters: any; // Tell Typescript iLMparameters is a global
+declare const iLMparameters: any; // Tell Typescript iLMparameters is a global
 
 import Lexers from "./../../grammar/";
 import line_i18n from "line-i18n";
@@ -10,7 +10,7 @@ import {
 } from "../../grammar/lexer";
 
 class LanguageServiceExtended extends line_i18n.LanguageServiceNoLS {
-  constructor() {
+  constructor () {
     super(
       typeof iLMparameters === "undefined"
         ? Config.default_lang
@@ -18,11 +18,11 @@ class LanguageServiceExtended extends line_i18n.LanguageServiceNoLS {
     );
   }
 
-  getDefaultLang(): string {
+  getDefaultLang (): string {
     return "en";
   }
 
-  getCurrentLexer(): IVProgLexer {
+  getCurrentLexer (): IVProgLexer {
     const langLexer = Lexers[this.getLang()];
     if (langLexer === null || langLexer === undefined) {
       return Lexers[this.getDefaultLang()];
@@ -31,7 +31,7 @@ class LanguageServiceExtended extends line_i18n.LanguageServiceNoLS {
     }
   }
 
-  getCurrentLangFuncs(): I18N_LANG_FUNCS {
+  getCurrentLangFuncs (): I18N_LANG_FUNCS {
     const langInfo = Lexers[this.getLang()];
     if (langInfo === null || langInfo === undefined) {
       return Lexers[this.getDefaultLang()].getLangFuncs();
@@ -40,7 +40,7 @@ class LanguageServiceExtended extends line_i18n.LanguageServiceNoLS {
     }
   }
 
-  getCurrentLangLibs(): I18N_LANG_LIBS {
+  getCurrentLangLibs (): I18N_LANG_LIBS {
     const langInfo = Lexers[this.getLang()];
     if (langInfo === null || langInfo === undefined) {
       return Lexers[this.getDefaultLang()].getLangLibs();

+ 7 - 7
js/typeSystem/parsers.js

@@ -21,7 +21,7 @@ export function toString (str) {
 }
 
 export function toChar (str) {
-  console.debug(str, str.length);
+  //console.debug(str, str.length);
   let value = str.replace(/^'/, "");
   value = value.replace(/'$/, "");
   value = value.replace(/\\b/g, "\b");
@@ -41,10 +41,10 @@ export function toReal (value) {
 export function toBool (str) {
   const val = "'" + str + "'";
   const lexer = LanguageService.getCurrentLexer();
-  const instance = new lexer(null);
-  if (instance.literalNames[lexer.RK_TRUE] === val) {
+
+  if (lexer.getReservedKeys()[lexer.getRules().RK_TRUE] === val) {
     return true;
-  } else if (instance.literalNames[lexer.RK_FALSE] === val) {
+  } else if (lexer.getReservedKeys()[lexer.getRules().RK_FALSE] === val) {
     return false;
   } else {
     // TODO: better error message
@@ -54,13 +54,13 @@ export function toBool (str) {
 
 export function convertBoolToString (bool) {
   const lexer = LanguageService.getCurrentLexer();
-  const instance = new lexer(null);
   let result = null;
   if (bool) {
-    result = instance.literalNames[lexer.RK_TRUE];
+    result = lexer.getReservedKeys()[lexer.getRules().RK_TRUE];
   } else {
-    result = instance.literalNames[lexer.RK_FALSE];
+    result = lexer.getReservedKeys()[lexer.getRules().RK_FALSE];
   }
+  //console.debug(result)
   return result.replace(/'/g, "");
 }
 

+ 1 - 2
js/typeSystem/type.ts

@@ -1,11 +1,10 @@
 import { IType } from "./itype";
 
 export class Type implements IType {
-
   public value: string;
   public ord: number;
 
-  constructor(value: string, ord: number) {
+  constructor (value: string, ord: number) {
     this.value = value;
     this.ord = ord;
   }

+ 4 - 4
js/util/dataProcess.js

@@ -42,10 +42,10 @@ export function processData () {
     const files = Array.from(folderInput.files);
     const idx = files.find((f) => f.name == "index.csv");
     const folderName = idx.webkitRelativePath.replace(idx.name, "");
-    console.debug(idx);
-    console.debug(folderName);
+    //console.debug(idx);
+    //console.debug(folderName);
     const data = await idx.text();
-    console.debug(data);
+    //console.debug(data);
     const csvEntries = data
       .split("\n")
       .slice(1)
@@ -56,7 +56,7 @@ export function processData () {
         vec.forEach((val, i) => (obj[header[i]] = val));
         return obj;
       });
-    console.debug(csvEntries);
+    //console.debug(csvEntries);
     const blockExercMap = csvEntries.reduce(prepareData, new Map());
     //console.log(Array.from(blockExercMatrix.entries()));
     const getFilePath = async function (submission) {

+ 190 - 108
js/util/utils.js

@@ -2,63 +2,82 @@ import { LanguageService } from "./../services/languageService";
 import { LocalizedStrings } from "./../services/localizedStringsService";
 import { Operators } from "./../ast/operators";
 
-/** 
- * source: https://pawelgrzybek.com/page-scroll-in-vanilla-javascript/ 
- * 
-*/
-export function scrollIt (destination, duration = 200, easing = 'linear', callback = null) {
-
+/**
+ * source: https://pawelgrzybek.com/page-scroll-in-vanilla-javascript/
+ *
+ */
+export function scrollIt (
+  destination,
+  duration = 200,
+  easing = "linear",
+  callback = null
+) {
   const easings = {
-    linear(t) {
+    linear (t) {
       return t;
     },
-    easeInQuad(t) {
+    easeInQuad (t) {
       return t * t;
     },
-    easeOutQuad(t) {
+    easeOutQuad (t) {
       return t * (2 - t);
     },
-    easeInOutQuad(t) {
+    easeInOutQuad (t) {
       return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
     },
-    easeInCubic(t) {
+    easeInCubic (t) {
       return t * t * t;
     },
-    easeOutCubic(t) {
-      return (--t) * t * t + 1;
+    easeOutCubic (t) {
+      return --t * t * t + 1;
     },
-    easeInOutCubic(t) {
+    easeInOutCubic (t) {
       return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
     },
-    easeInQuart(t) {
+    easeInQuart (t) {
       return t * t * t * t;
     },
-    easeOutQuart(t) {
-      return 1 - (--t) * t * t * t;
+    easeOutQuart (t) {
+      return 1 - --t * t * t * t;
     },
-    easeInOutQuart(t) {
-      return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t;
+    easeInOutQuart (t) {
+      return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
     },
-    easeInQuint(t) {
+    easeInQuint (t) {
       return t * t * t * t * t;
     },
-    easeOutQuint(t) {
-      return 1 + (--t) * t * t * t * t;
+    easeOutQuint (t) {
+      return 1 + --t * t * t * t * t;
+    },
+    easeInOutQuint (t) {
+      return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
     },
-    easeInOutQuint(t) {
-      return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t;
-    }
   };
 
   const start = window.pageYOffset;
-  const startTime = 'now' in window.performance ? performance.now() : new Date().getTime();
+  const startTime =
+    "now" in window.performance ? performance.now() : new Date().getTime();
 
-  const documentHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
-  const windowHeight = window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight;
-  const destinationOffset = typeof destination === 'number' ? destination : destination.offsetTop;
-  const destinationOffsetToScroll = Math.round(documentHeight - destinationOffset < windowHeight ? documentHeight - windowHeight : destinationOffset);
+  const documentHeight = Math.max(
+    document.body.scrollHeight,
+    document.body.offsetHeight,
+    document.documentElement.clientHeight,
+    document.documentElement.scrollHeight,
+    document.documentElement.offsetHeight
+  );
+  const windowHeight =
+    window.innerHeight ||
+    document.documentElement.clientHeight ||
+    document.getElementsByTagName("body")[0].clientHeight;
+  const destinationOffset =
+    typeof destination === "number" ? destination : destination.offsetTop;
+  const destinationOffsetToScroll = Math.round(
+    documentHeight - destinationOffset < windowHeight
+      ? documentHeight - windowHeight
+      : destinationOffset
+  );
 
-  if ('requestAnimationFrame' in window === false) {
+  if ("requestAnimationFrame" in window === false) {
     window.scroll(0, destinationOffsetToScroll);
     if (callback) {
       callback();
@@ -66,11 +85,15 @@ export function scrollIt (destination, duration = 200, easing = 'linear', callba
     return;
   }
 
-  function scroll() {
-    const now = 'now' in window.performance ? performance.now() : new Date().getTime();
-    const time = Math.min(1, ((now - startTime) / duration));
+  function scroll () {
+    const now =
+      "now" in window.performance ? performance.now() : new Date().getTime();
+    const time = Math.min(1, (now - startTime) / duration);
     const timeFunction = easings[easing](time);
-    window.scroll(0, Math.ceil((timeFunction * (destinationOffsetToScroll - start)) + start));
+    window.scroll(
+      0,
+      Math.ceil(timeFunction * (destinationOffsetToScroll - start) + start)
+    );
 
     if (window.pageYOffset === destinationOffsetToScroll) {
       if (callback) {
@@ -86,42 +109,67 @@ export function scrollIt (destination, duration = 200, easing = 'linear', callba
 }
 
 /**
- * 
+ *
  * source: https://stackoverflow.com/a/16270434
  */
 export function isElementInViewport (el) {
   const rect = el.getBoundingClientRect();
 
-  return rect.bottom > 0 &&
+  return (
+    rect.bottom > 0 &&
     rect.right > 0 &&
     rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
-    rect.top < (window.innerHeight || document.documentElement.clientHeight);
+    rect.top < (window.innerHeight || document.documentElement.clientHeight)
+  );
 }
 
 let cacheMainList = null;
 let cacheOp = null;
 
 function fillCache () {
-  if(cacheMainList == null) {
+  if (cacheMainList == null) {
     cacheMainList = [];
-    const mainList = ["RK_PROGRAM","RK_REAL","RK_VOID","RK_BOOLEAN","RK_STRING",
-      "RK_INTEGER","RK_CHARACTER","RK_SWITCH","RK_CASE","RK_DEFAULT","RK_CONST",
-      "RK_FUNCTION","RK_RETURN","RK_FOR","RK_BREAK","RK_DO","RK_WHILE","RK_IF",
-      "RK_ELSE","RK_FALSE","RK_TRUE"];
-    const lexerClass = LanguageService.getCurrentLexer();
-    const nullLexer = new lexerClass();
+    const mainList = [
+      "RK_PROGRAM",
+      "RK_REAL",
+      "RK_VOID",
+      "RK_BOOLEAN",
+      "RK_STRING",
+      "RK_INTEGER",
+      "RK_CHARACTER",
+      "RK_SWITCH",
+      "RK_CASE",
+      "RK_DEFAULT",
+      "RK_CONST",
+      "RK_FUNCTION",
+      "RK_RETURN",
+      "RK_FOR",
+      "RK_BREAK",
+      "RK_DO",
+      "RK_WHILE",
+      "RK_IF",
+      "RK_ELSE",
+      "RK_FALSE",
+      "RK_TRUE",
+    ];
+    const lexer = LanguageService.getCurrentLexer();
+    const names = lexer.getReservedKeys();
     for (let key = 0; key < mainList.length; ++key) {
       const word = mainList[key];
-      const keyword = nullLexer.literalNames[lexerClass[word]];
-      cacheMainList.push(keyword.substring(1, keyword.length-1));
+      const keyword = names[word];
+      cacheMainList.push(keyword.substring(1, keyword.length - 1));
     }
   }
-  if(cacheOp == null) {
-    cacheOp = []
-    const logicOpList = [Operators.AND.value, Operators.OR.value, Operators.NOT.value];
+  if (cacheOp == null) {
+    cacheOp = [];
+    const logicOpList = [
+      Operators.AND.value,
+      Operators.OR.value,
+      Operators.NOT.value,
+    ];
     for (let op = 0; op < logicOpList.length; ++op) {
       const lOp = `logic_operator_${logicOpList[op]}`;
-      cacheOp.push(LocalizedStrings.getUI(lOp))
+      cacheOp.push(LocalizedStrings.getUI(lOp));
     }
   }
 }
@@ -130,14 +178,14 @@ export function isKeyword (text) {
   fillCache();
   for (let key = 0; key < cacheMainList.length; ++key) {
     const keyword = cacheMainList[key];
-    if(keyword == text) {
+    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) {
+    if (lOp == text) {
       return true;
     }
   }
@@ -146,122 +194,156 @@ export function isKeyword (text) {
 
 export function isValidIdentifier (identifier_str) {
   const validRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(identifier_str);
-  if(!validRegex) {
+  if (!validRegex) {
     return false;
   }
-	return !isKeyword(identifier_str);
+  return !isKeyword(identifier_str);
 }
 
 export function getCodeEditorModeConfig () {
-  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","RK_CHARACTER"];
+  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",
+    "RK_CHARACTER",
+  ];
   const atomList = ["RK_FALSE", "RK_TRUE"];
 
   const case_default = [];
   const blocks = [];
   const keywords = [];
   const types = [];
-  const atoms = []
+  const atoms = [];
   let switchString = "";
 
   cacheMainList = [];
-  const lexerClass = LanguageService.getCurrentLexer();
-  const nullLexer = new lexerClass();
-  blockList.forEach( v => {
-    const keyword = nullLexer.literalNames[lexerClass[v]];
-    const value = keyword.substring(1, keyword.length-1);
+  const lexer = LanguageService.getCurrentLexer();
+  const names = lexer.getReservedKeys();
+  //console.debug(names);
+  blockList.forEach((v) => {
+    const keyword = names[v];
+    const value = keyword.substring(1, keyword.length - 1);
     cacheMainList.push(value);
     keywords.push(value);
     blocks.push(value);
-    if(v == "RK_SWITCH") {
+    if (v == "RK_SWITCH") {
       switchString = value;
     } else if (v == "RK_CASE" || v == "RK_DEFAULT") {
       case_default.push(value);
     }
   });
-  keywordsList.forEach( v => {
-    const keyword = nullLexer.literalNames[lexerClass[v]];
-    const value = keyword.substring(1, keyword.length-1);
+  keywordsList.forEach((v) => {
+    const keyword = names[v];
+    const value = keyword.substring(1, keyword.length - 1);
     cacheMainList.push(value);
     keywords.push(value);
   });
-  typeList.forEach(v => {
-    const keyword = nullLexer.literalNames[lexerClass[v]];
-    const value = keyword.substring(1, keyword.length-1);
+  typeList.forEach((v) => {
+    const keyword = names[v];
+    const value = keyword.substring(1, keyword.length - 1);
     cacheMainList.push(value);
     types.push(value);
-  })
-  atomList.forEach( v => {
-    const keyword = nullLexer.literalNames[lexerClass[v]];
-    const value = keyword.substring(1, keyword.length-1);
+  });
+  atomList.forEach((v) => {
+    const keyword = names[v];
+    const value = keyword.substring(1, keyword.length - 1);
     cacheMainList.push(value);
     atoms.push(value);
-  })
-  
-  cacheOp = []
-  const logicOpList = [Operators.AND.value, Operators.OR.value, Operators.NOT.value];
-  for (let op = 0; op < logicOpList.length; ++op) {
-    const lOp = `logic_operator_${logicOpList[op]}`;
-    const value = LocalizedStrings.getUI(lOp);
-    cacheOp.push(value)
+  });
+
+  cacheOp = [];
+  const logicOpList = ["NOT_OPERATOR", "OR_OPERATOR", "AND_OPERATOR"];
+
+  logicOpList.forEach((v) => {
+    const keyword = names[v];
+    const value = keyword.substring(1, keyword.length - 1);
+    cacheOp.push(value);
     keywords.push(value);
-  }
+  });
+
   return {
     case_default: case_default,
     atoms: atoms,
     keywords: keywords,
     switchString: switchString,
     types: types,
-    blocks: blocks
-  }
+    blocks: blocks,
+  };
 }
 
 /**
  * Source: https://gist.github.com/andrei-m/982927
- * @param {string} a 
- * @param {string} b 
+ * @param {string} a
+ * @param {string} b
  */
 export function levenshteinDistance (a, b) {
-  if(a.length == 0) return b.length; 
-  if(b.length == 0) return a.length; 
+  if (a.length == 0) return b.length;
+  if (b.length == 0) return a.length;
 
   const matrix = [];
 
   // increment along the first column of each row
   let i;
-  for(i = 0; i <= b.length; i++){
+  for (i = 0; i <= b.length; i++) {
     matrix[i] = [i];
   }
 
   // increment each column in the first row
   let j;
-  for(j = 0; j <= a.length; j++){
+  for (j = 0; j <= a.length; j++) {
     matrix[0][j] = j;
   }
 
   // Fill in the rest of the matrix
-  for(i = 1; i <= b.length; i++){
-    for(j = 1; j <= a.length; j++){
-      if(b.charCodeAt(i-1) == a.charCodeAt(j-1)){
-        matrix[i][j] = matrix[i-1][j-1];
+  for (i = 1; i <= b.length; i++) {
+    for (j = 1; j <= a.length; j++) {
+      if (b.charCodeAt(i - 1) == a.charCodeAt(j - 1)) {
+        matrix[i][j] = matrix[i - 1][j - 1];
       } else {
-        matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
-                        Math.min(matrix[i][j-1] + 1, // insertion
-                          matrix[i-1][j] + 1)); // deletion
+        matrix[i][j] = Math.min(
+          matrix[i - 1][j - 1] + 1, // substitution
+          Math.min(
+            matrix[i][j - 1] + 1, // insertion
+            matrix[i - 1][j] + 1
+          )
+        ); // deletion
       }
     }
   }
   return matrix[b.length][a.length];
 }
 
-let win = null
+let win = null;
 export function openAssessmentDetail (event) {
   event.preventDefault();
   const page_code = event.currentTarget.dataset.page;
-  if(win != null) {
-    win.close()
+  if (win != null) {
+    win.close();
   }
   win = window.open("", "DetailWindow", "width=550,height=600");
   win.document.open();
@@ -270,13 +352,13 @@ export function openAssessmentDetail (event) {
 }
 
 export function range (size, startAt = 0) {
-  return [...Array(size).keys()].map(i => i + startAt);
+  return [...Array(size).keys()].map((i) => i + startAt);
 }
 
 /**
- * 
- * @param {number} ms 
+ *
+ * @param {number} ms
  */
 export async function sleep (ms) {
-    return new Promise( (res, _) => setTimeout(res, ms));
-  }
+  return new Promise((res, _) => setTimeout(res, ms));
+}

File diff suppressed because it is too large
+ 1001 - 766
package-lock.json


+ 2 - 1
package.json

@@ -37,7 +37,8 @@
     "copy-webpack-plugin": "10.x",
     "csv-parser": "^2.3.3",
     "eslint": "^8.5.0",
-    "html-webpack-plugin": "^4.3.0",
+    "html-webpack-plugin": "^5.5.0",
+    "http-server": "^14.0.0",
     "ts-loader": "^5.4.5",
     "typescript": "^3.9.5",
     "webpack": "^5",

+ 6 - 6
templates/runner.html

@@ -16,14 +16,14 @@
 <body>
     <div style="padding-top: 50px;content: ''"></div>
   <div class="ui container grid">
-    
+
     <div class="four wide column">
       <div class="row">
         <textarea class="ui form control" name="input" id="input" cols="100" rows="30">
             programa {
 
               const real C = 5.5
-             
+
               funcao inicio() {
 
                inteiro a = 8
@@ -50,12 +50,12 @@
         </div>
     </div>
   </div>
-  
-  
+
+
 </body>
 <script>
-  ( function () {
+  window.addEventListener('DOMContentLoaded', () => {
     ivprogCore.runner();
-  })();
+  });
 </script>
 </html>

+ 2 - 2
updateVersionPlugin.js

@@ -12,9 +12,9 @@ function writeVersionFile () {
 function UpdateVersionPlugin () { }
 
 UpdateVersionPlugin.prototype.apply  = function (compiler) {
-  compiler.hooks.beforeCompile.tap("UpdateVersionPlugin", function() {
+  compiler.hooks.beforeCompile.tap("UpdateVersionPlugin", function () {
     writeVersionFile();
   });
 }
 
-module.exports = UpdateVersionPlugin;
+module.exports = UpdateVersionPlugin;

+ 3 - 3
webpack.config.js

@@ -57,15 +57,15 @@ module.exports = {
     }),
     new UpdateVersionPlugin(),
     new HtmlWebpackPlugin({
-      template: "templates/index.html",
+      template: "./templates/index.html",
       filename: path.resolve(__dirname, "build", "index.html"),
     }),
     new HtmlWebpackPlugin({
-      template: "templates/runner.html",
+      template: "./templates/runner.html",
       filename: path.resolve(__dirname, "build", "runner.html"),
     }),
     new HtmlWebpackPlugin({
-      template: "templates/process.html",
+      template: "./templates/process.html",
       filename: path.resolve(__dirname, "build", "process.html"),
     }),
     /*new ChangeScriptSourcePlugin(),*/