Browse Source

feat: Implement moojs lexers for iVProg

Implement english and portuguese language lexers using the new system
Add type information for i18n string in the lexer context
Add a new type that represents lexer tokens, libs and functions of a given language
Lucas de Souza 2 years ago
parent
commit
99ac397b0f

+ 0 - 268
grammar/en/ivprog.g4

@@ -1,268 +0,0 @@
-lexer grammar ivprog;
-
-// BEGIN i18n Lexical rules
-RK_PROGRAM
-  : 'program'
-  ;
-
-RK_REAL
-  : 'real'
-  ;
-
-RK_VOID
-  : 'void'
-  ;
-
-RK_BOOLEAN
-  : 'bool'
-  ;
-
-RK_STRING
-  : 'string'
-  ;
-
-RK_INTEGER
-  : 'int'
-  ;
-
-RK_CHARACTER
-  : 'char'
-  ;
-
-RK_SWITCH
-  : 'switch'
-  ;
-
-RK_CASE
-  : 'case'
-  ;
-
-RK_DEFAULT
-  : 'otherwise'
-  ;
-
-RK_CONST
-  : 'const'
-  ;
-
-RK_FUNCTION
-  : 'function'
-  ;
-
-RK_RETURN
-  : 'return'
-  ;
-
-RK_FOR
-  : 'for'
-  ;
-
-RK_FOR_ALT
-  : 'repeat_for'
-  ;
-
-RK_FOR_FROM
-  : 'from'
-  ;
-
-RK_FOR_TO
-  : 'to'
-  ;
-
-RK_FOR_PASS
-  : 'pass'
-  ;
-
-RK_BREAK
-  : 'break'
-  ;
-
-RK_DO
-  : 'repeat'
-  ;
-
-RK_DO_UNTIL
-  : 'until'
-  ;
-
-RK_WHILE
-  : 'while'
-  ;
-
-RK_WHILE_ALT
-  : 'repeat_while'
-  ;
-
-RK_IF
-  : 'if'
-  ;
-
-RK_ELSE
-  : 'else'
-  ;
-
-RK_FALSE
-  : 'false'
-  ;
-
-RK_TRUE
-  : 'true'
-  ;
-
-fragment RK_LOGICAL_NOT
-  : 'not'
-  ;
-
-fragment RK_LOGICAL_AND
-  : 'AND'
-  ;
-
-fragment RK_LOGICAL_OR
-  : 'OR'
-  ;
-
-RK_REFERENCE
-  : '&'
-  ;
-// END i18n Lexical rules
-
-// GAMBIARRA   : '.' |'á'| 'à'| 'ã'|'â'|'é'|'ê'|'í'|'ó'|'ô'|'õ'|'ú'|'ü'|'ç'|'Ä'|'À'|'Ã'|'Â'|'É'|'Ê'|'Ë'|'Ó'|'Ô'|'Õ'|'Ú'|'Ü'|'Ç'|'#'|'$'|'"'|'§'|'?'|'¹'|'²'|'³'|'£'|'¢'|'¬'|'ª'|'º'|'~'|'\''|'`'|'\\'|'@';
-
-OPEN_PARENTHESIS
-  : '('
-  ;
-
-CLOSE_PARENTHESIS
-  : ')'
-  ;
-
-OPEN_BRACE
-  : '['
-  ;
-
-CLOSE_BRACE
-  : ']'
-  ;
-
-OPEN_CURLY
-  : '{'
-  ;
-
-CLOSE_CURLY
-  : '}'
-  ;
-
-COMMA
-  : ','
-  ;
-
-EQUAL
-  : '<-'
-  | '←'
-  ;
-
-SUM_OP
-  : ('+'|'-')
-  ;
-
-MULTI_OP
-  : ('*'|'/'|'%')
-  ;
-
-AND_OPERATOR
-  : RK_LOGICAL_AND
-  ;
-
-OR_OPERATOR
-  : RK_LOGICAL_OR
-  ;
-
-RELATIONAL_OPERATOR
-  : ('>='|'=='|'<='|'>'|'<'|'!=')
-  ;
-
-COLON
-  : ':'
-  ;
-
-NOT_OPERATOR
-  : RK_LOGICAL_NOT
-  ;
-
-ID
-  : [a-zA-Z_] [a-zA-Z0-9_]*
-  ;
-
-LIB_ID
-  : ID '.' ID
-  ;
-
-INTEGER
-  : [0-9]+
-  | ('0x'|'0X')(HEX_DIGIT)+
-  | ('0b'|'0B')[0-1]+
-  ;
-
-REAL
-  : [0-9]+ '.' [0-9]+
-  | [0-9]+ '.' [0-9]* ExponentPart
-  ;
-
-fragment ExponentPart
-  : [eE] [+-]? [0-9]+
-  ;
-
-STRING
-  : '"' STRING_CHARACTER* '"'
-  ;
-
-fragment STRING_CHARACTER //String as defined at https://github.com/antlr/grammars-v4/blob/master/java8/Java8.g4
-  : ~["\\\r\n]
-  | ESC_SEQ
-  ;
-
-CHARACTER //Character as defined at https://github.com/antlr/grammars-v4/blob/master/java8/Java8.g4
-  : '\'' ( ESC_SEQ | ~['\\\r\n]) '\''
-  ;
-
-WHITESPACE
-  : ( ' ' | '\t') -> skip
-  ;
-
-fragment SEMICOLON
-  : ';'
-  ;
-
-EOS
-  : [\r\n]+
-  | SEMICOLON
-  ;
-
-fragment HEX_DIGIT
-  : [0-9a-fA-F]
-  ;
-
-fragment OCTAL_DIGIT
-  : [0-7]
-  ;
-
-fragment ESC_SEQ
-  : '\\' ('b'|'t'|'n'|'f'|'r'|'"'|'\''|'\\')
-  | ESC_UNICODE
-  | ESC_OCTAL
-  ;
-
-fragment ESC_OCTAL
-  : '\\' [0-3] OCTAL_DIGIT OCTAL_DIGIT
-  | '\\' OCTAL_DIGIT OCTAL_DIGIT
-  | '\\' OCTAL_DIGIT
-  ;
-
-fragment ESC_UNICODE
-  : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
-  ;
-
-COMMENTS
-  : ('//' ~('\n'|'\r')* '\r'? '\n'
-    | '/*' .*? '*/') -> channel(HIDDEN)
-  ;

+ 104 - 0
grammar/en/ivprog.ts

@@ -0,0 +1,104 @@
+import {
+  I18N_LEXER_TYPES,
+  I18N_LEXER_COMMANDS,
+  I18N_LEXER_BOOLVAL,
+  I18N_LEXER_LOGICOP,
+  makeLexer,
+  I18N_LANG_LIBS,
+  I18N_LANG_FUNCS,
+} from "../lexer";
+
+// i18n lexer strings for the language.
+const types: I18N_LEXER_TYPES = {
+  // types
+  RK_REAL: "real",
+  RK_INTEGER: "int",
+  RK_BOOLEAN: "bool",
+  RK_CHARACTER: "char",
+  RK_STRING: "string",
+  RK_VOID: "void",
+};
+const commands: I18N_LEXER_COMMANDS = {
+  // commands
+  RK_PROGRAM: "program",
+  RK_SWITCH: "switch",
+  RK_CASE: "case",
+  RK_DEFAULT: "otherwise",
+  RK_CONST: "const",
+  RK_FUNCTION: "function",
+  RK_RETURN: "return",
+  RK_FOR: "for",
+  RK_FOR_ALT: "repeat_for",
+  RK_FOR_FROM: "from",
+  RK_FOR_TO: "to",
+  RK_FOR_PASS: "pass",
+  RK_BREAK: "break",
+  RK_DO: "repeat",
+  RK_DO_UNTIL: "until",
+  RK_WHILE: "while",
+  RK_WHILE_ALT: "repeat_while",
+  RK_IF: "if",
+  RK_ELSE: "else",
+  RK_REFERENCE: "&",
+};
+const boolVal: I18N_LEXER_BOOLVAL = {
+  RK_FALSE: "false",
+  RK_TRUE: "true",
+};
+
+const logicOp: I18N_LEXER_LOGICOP = {
+  RK_LOGICAL_NOT: "not",
+  RK_LOGICAL_AND: "AND",
+  RK_LOGICAL_OR: "OR",
+};
+
+const langLibs: I18N_LANG_LIBS = {
+  $mathLib: "Mathematics",
+  $ioLib: "IO",
+  $strLib: "Text",
+  $arrayLib: "Array",
+  $langLib: "Conversion",
+};
+
+const langFuncs: I18N_LANG_FUNCS = {
+  main_function: "main",
+  $read: "read",
+  $write: "write",
+  $numElements: "total_of_elements",
+  $matrixLines: "total_of_lines",
+  $matrixColumns: "total_of_columns",
+  $substring: "substring",
+  $length: "length",
+  $uppercase: "uppercase",
+  $lowercase: "lowercase",
+  $charAt: "char_at",
+  $isReal: "is_real",
+  $isInt: "is_integer",
+  $isBool: "is_logic",
+  $castReal: "to_real",
+  $castInt: "to_integer",
+  $castBool: "to_logic",
+  $castString: "to_string",
+  $castChar: "to_char",
+  $sin: "sin",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "sqrt",
+  $pow: "pow",
+  $log: "log",
+  $abs: "abs",
+  $negate: "negate",
+  $invert: "invert",
+  $max: "maximum",
+  $min: "minimum",
+  $rand: "random",
+};
+// END i18n lexer strings
+export const enLexer = makeLexer({
+  commands,
+  boolVal,
+  logicOp,
+  types,
+  langLibs,
+  langFuncs,
+});

+ 0 - 36
grammar/en/langFunctions.js

@@ -1,36 +0,0 @@
-/* This is a dictionary of the language defined functions
-**/
-export default {
-  main_function: "main",
-  $read: "read",
-  $write: "write",
-  $numElements: "total_of_elements",
-  $matrixLines: "total_of_lines",
-  $matrixColumns: "total_of_columns",
-  $substring: "substring",
-  $length: "length",
-  $uppercase: "uppercase",
-  $lowercase: "lowercase",
-  $charAt: "char_at",
-  $isReal: "is_real",
-  $isInt: "is_integer",
-  $isBool: "is_logic",
-  $castReal: "to_real",
-  $castInt: "to_integer",
-  $castBool: "to_logic",
-  $castString: "to_string",
-  $castChar: "to_char",
-  $sin: "sin",
-  $cos: "cos",
-  $tan: "tan",
-  $sqrt: "sqrt",
-  $pow: "pow",
-  $log: "log",
-  $abs: "abs",
-  $negate: "negate",
-  $invert: "invert",
-  $max: "maximum",
-  $min: "minimum",
-  $rand: "random"
-
-}

+ 0 - 10
grammar/en/langLibs.js

@@ -1,10 +0,0 @@
-/**
- * This is the dictionary of the language defined libraries
- */
-export default {
-  $mathLib: "Mathematic",
-  $ioLib: "IO",
-  $strLib: "Text",
-  $arrayLib: "Array",
-  $langLib: "Conversion"
-}

+ 10 - 0
grammar/helper.ts

@@ -0,0 +1,10 @@
+export function combineRegex(strings: TemplateStringsArray, ...pieces: any[]) {
+  return new RegExp(
+    strings.raw
+      .map(
+        (r, i) =>
+          r + (pieces[i] === undefined ? "" : "(?:" + pieces[i].source + ")")
+      )
+      .join("")
+  );
+}

+ 0 - 15
grammar/index.js

@@ -1,15 +0,0 @@
-import * as PT from "./pt/ivprog.g4";
-import PTFuncs from "./pt/langFunctions";
-import PTLibs from "./pt/langLibs";
-import * as EN from "./en/ivprog.g4";
-import ENFuncs from "./en/langFunctions";
-import ENLibs from "./en/langLibs";
-/*import * as ES from "./es/ivprog.g4";
-import ESFuncs from "./es/langFunctions";
-import ESLibs from "./es/langLibs";*/
-
-export default {
-  pt: { lexer: PT.ivprog, langFuncs: PTFuncs, langLibs: PTLibs },
-  en: { lexer: EN.ivprog, langFuncs: ENFuncs, langLibs: ENLibs },
-  //es: {lexer: ES.ivprog, langFuncs: ESFuncs, langLibs: ESLibs}
-};

+ 11 - 0
grammar/index.ts

@@ -0,0 +1,11 @@
+import { ptLexer as pt } from "./pt/ivprog";
+import { enLexer as en } from "./en/ivprog";
+import { IVProgLexer } from "./lexer";
+/*import * as ES from "./es/ivprog.g4";
+import ESFuncs from "./es/langFunctions";
+import ESLibs from "./es/langLibs";*/
+const lexers: Record<string, IVProgLexer> = {};
+lexers["pt"] = pt;
+lexers["en"] = en;
+
+export default lexers;

+ 173 - 0
grammar/lexer.ts

@@ -0,0 +1,173 @@
+import * as moo from "moo";
+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;
+}
+
+export interface I18N_LEXER_BOOLVAL {
+  RK_FALSE: string;
+  RK_TRUE: string;
+}
+
+export interface I18N_LEXER_LOGICOP {
+  RK_LOGICAL_NOT: string;
+  RK_LOGICAL_AND: string;
+  RK_LOGICAL_OR: string;
+}
+
+export interface I18N_LEXER_COMMANDS {
+  RK_PROGRAM: string;
+  RK_SWITCH: string;
+  RK_CASE: string;
+  RK_DEFAULT: string;
+  RK_CONST: string;
+  RK_FUNCTION: string;
+  RK_RETURN: string;
+  RK_FOR: string;
+  RK_FOR_ALT: string;
+  RK_FOR_FROM: string;
+  RK_FOR_TO: string;
+  RK_FOR_PASS: string;
+  RK_BREAK: string;
+  RK_DO: string;
+  RK_DO_UNTIL: string;
+  RK_WHILE: string;
+  RK_WHILE_ALT: string;
+  RK_IF: string;
+  RK_ELSE: string;
+  RK_REFERENCE: string;
+}
+
+export interface I18N_LANG_LIBS {
+  $ioLib: string;
+  $strLib: string;
+  $mathLib: string;
+  $langLib: string;
+  $arrayLib: string;
+}
+
+export interface I18N_LANG_FUNCS {
+  main_function: string;
+  $read: string;
+  $write: string;
+  $numElements: string;
+  $matrixLines: string;
+  $matrixColumns: string;
+  $substring: string;
+  $length: string;
+  $uppercase: string;
+  $lowercase: string;
+  $charAt: string;
+  $isReal: string;
+  $isInt: string;
+  $isBool: string;
+  $castReal: string;
+  $castInt: string;
+  $castBool: string;
+  $castString: string;
+  $castChar: string;
+  $sin: string;
+  $cos: string;
+  $tan: string;
+  $sqrt: string;
+  $pow: string;
+  $log: string;
+  $abs: string;
+  $negate: string;
+  $invert: string;
+  $max: string;
+  $min: string;
+  $rand: string;
+}
+
+export interface I18nLexer {
+  commands: I18N_LEXER_COMMANDS;
+  logicOp: I18N_LEXER_LOGICOP;
+  boolVal: I18N_LEXER_BOOLVAL;
+  types: I18N_LEXER_TYPES;
+  langLibs: I18N_LANG_LIBS;
+  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(
+    private RKs: Record<string, string>,
+    public lexer: moo.Lexer,
+    private i18nLexer: I18nLexer
+  ) {}
+
+  getReservedKeys(): Record<string, string> {
+    return this.RKs;
+  }
+
+  getTypeKeys() {
+    return this.i18nLexer.types;
+  }
+
+  getLangLibs() {
+    return this.i18nLexer.langLibs;
+  }
+
+  getLangFuncs() {
+    return this.i18nLexer.langFuncs;
+  }
+}
+
+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));
+  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({
+    OPEN_BRACE: /\[/,
+    CLOSE_BRACE: /\]/,
+    OPEN_PARENTHESIS: /\(/,
+    CLOSE_PARENTHESIS: /\)/,
+    OPEN_CURLY: /\{/,
+    CLOSE_CURLY: /\}/,
+    COMMA: /,/,
+    ASSIGNMENT: /<-|←/,
+    REAL: /[0-9]+\.[0-9]*[eE][+-]?[0-9]+|[0-9]+\.[0-9]+/,
+    INTEGER: RegExp(`(?:0x|0X)${HEX_DIGIT}+|(?:0b|0B)[0-1]+|[0-9]+`),
+    SUM_OP: /[+-]/,
+    MULTI_OP: /[*/%]/,
+    RELATIONAL_OPERATOR: />=|==|<=|>|<|!=/,
+    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: /&/,
+    ID: { match: RegExp(ID), type: RESERVED_KEYS },
+    DOT: /\./,
+  });
+  return new IVProgLexer(RKs, moolexer, lexer);
+}

+ 0 - 268
grammar/pt/ivprog.g4

@@ -1,268 +0,0 @@
-lexer grammar ivprog;
-
-// BEGIN i18n Lexical rules
-RK_PROGRAM
-  : 'programa'
-  ;
-
-RK_REAL
-  : 'real'
-  ;
-
-RK_VOID
-  : 'vazio'
-  ;
-
-RK_BOOLEAN
-  : 'logico'
-  ;
-
-RK_STRING
-  : 'cadeia'
-  ;
-
-RK_INTEGER
-  : 'inteiro'
-  ;
-
-RK_CHARACTER
-  : 'caractere'
-  ;
-
-RK_SWITCH
-  : 'escolha'
-  ;
-
-RK_CASE
-  : 'caso'
-  ;
-
-RK_DEFAULT
-  : 'contrario'
-  ;
-
-RK_CONST
-  : 'const'
-  ;
-
-RK_FUNCTION
-  : 'funcao'
-  ;
-
-RK_RETURN
-  : 'devolva'
-  ;
-
-RK_FOR
-  : 'para'
-  ;
-
-RK_FOR_ALT
-  : 'repita_para'
-  ;
-
-RK_FOR_FROM
-  : 'de'
-  ;
-
-RK_FOR_TO
-  : 'ate'
-  ;
-
-RK_FOR_PASS
-  : 'passo'
-  ;
-
-RK_BREAK
-  : 'pare'
-  ;
-
-RK_DO
-  : 'repita'
-  ;
-
-RK_DO_UNTIL
-  : 'ate_que'
-  ;
-
-RK_WHILE
-  : 'enquanto'
-  ;
-
-RK_WHILE_ALT
-  : 'repita_enquanto'
-  ;
-
-RK_IF
-  : 'se'
-  ;
-
-RK_ELSE
-  : 'senao'
-  ;
-
-RK_FALSE
-  : 'falso'
-  ;
-
-RK_TRUE
-  : 'verdadeiro'
-  ;
-
-fragment RK_LOGICAL_NOT
-  : 'nao'
-  ;
-
-fragment RK_LOGICAL_AND
-  : 'E'
-  ;
-
-fragment RK_LOGICAL_OR
-  : 'OU'
-  ;
-
-RK_REFERENCE
-  : '&'
-  ;
-// END i18n Lexical rules
-
-// GAMBIARRA   : '.' |'á'| 'à'| 'ã'|'â'|'é'|'ê'|'í'|'ó'|'ô'|'õ'|'ú'|'ü'|'ç'|'Ä'|'À'|'Ã'|'Â'|'É'|'Ê'|'Ë'|'Ó'|'Ô'|'Õ'|'Ú'|'Ü'|'Ç'|'#'|'$'|'"'|'§'|'?'|'¹'|'²'|'³'|'£'|'¢'|'¬'|'ª'|'º'|'~'|'\''|'`'|'\\'|'@';
-
-OPEN_PARENTHESIS
-  : '('
-  ;
-
-CLOSE_PARENTHESIS
-  : ')'
-  ;
-
-OPEN_BRACE
-  : '['
-  ;
-
-CLOSE_BRACE
-  : ']'
-  ;
-
-OPEN_CURLY
-  : '{'
-  ;
-
-CLOSE_CURLY
-  : '}'
-  ;
-
-COMMA
-  : ','
-  ;
-
-EQUAL
-  : '<-'
-  | '←'
-  ;
-
-SUM_OP
-  : ('+'|'-')
-  ;
-
-MULTI_OP
-  : ('*'|'/'|'%')
-  ;
-
-AND_OPERATOR
-  : RK_LOGICAL_AND
-  ;
-
-OR_OPERATOR
-  : RK_LOGICAL_OR
-  ;
-
-RELATIONAL_OPERATOR
-  : ('>='|'=='|'<='|'>'|'<'|'!=')
-  ;
-
-COLON
-  : ':'
-  ;
-
-NOT_OPERATOR
-  : RK_LOGICAL_NOT
-  ;
-
-ID
-  : [a-zA-Z_] [a-zA-Z0-9_]*
-  ;
-
-LIB_ID
-  : ID '.' ID
-  ;
-
-INTEGER
-  : [0-9]+
-  | ('0x'|'0X')(HEX_DIGIT)+
-  | ('0b'|'0B')[0-1]+
-  ;
-
-REAL
-  : [0-9]+ '.' [0-9]+
-  | [0-9]+ '.' [0-9]* ExponentPart
-  ;
-
-fragment ExponentPart
-  : [eE] [+-]? [0-9]+
-  ;
-
-STRING
-  : '"' STRING_CHARACTER* '"'
-  ;
-
-fragment STRING_CHARACTER //String as defined at https://github.com/antlr/grammars-v4/blob/master/java8/Java8.g4
-  : ~["\\\r\n]
-  | ESC_SEQ
-  ;
-
-CHARACTER //Character as defined at https://github.com/antlr/grammars-v4/blob/master/java8/Java8.g4
-  : '\'' ( ESC_SEQ | ~['\\\r\n]) '\''
-  ;
-
-WHITESPACE
-  : ( ' ' | '\t') -> skip
-  ;
-
-fragment SEMICOLON
-  : ';'
-  ;
-
-EOS
-  : [\r\n]+
-  | SEMICOLON
-  ;
-
-fragment HEX_DIGIT
-  : [0-9a-fA-F]
-  ;
-
-fragment OCTAL_DIGIT
-  : [0-7]
-  ;
-
-fragment ESC_SEQ
-  : '\\' ('b'|'t'|'n'|'f'|'r'|'"'|'\''|'\\')
-  | ESC_UNICODE
-  | ESC_OCTAL
-  ;
-
-fragment ESC_OCTAL
-  : '\\' [0-3] OCTAL_DIGIT OCTAL_DIGIT
-  | '\\' OCTAL_DIGIT OCTAL_DIGIT
-  | '\\' OCTAL_DIGIT
-  ;
-
-fragment ESC_UNICODE
-  : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
-  ;
-
-COMMENTS
-  : ('//' ~('\n'|'\r')* '\r'? '\n'
-    | '/*' .*? '*/') -> channel(HIDDEN)
-  ;

+ 104 - 0
grammar/pt/ivprog.ts

@@ -0,0 +1,104 @@
+import {
+  I18N_LEXER_TYPES,
+  I18N_LEXER_COMMANDS,
+  I18N_LEXER_BOOLVAL,
+  I18N_LEXER_LOGICOP,
+  makeLexer,
+  I18N_LANG_LIBS,
+  I18N_LANG_FUNCS,
+} from "../lexer";
+
+// i18n lexer strings for the language.
+const types: I18N_LEXER_TYPES = {
+  // types
+  RK_REAL: "real",
+  RK_INTEGER: "inteiro",
+  RK_BOOLEAN: "logico",
+  RK_CHARACTER: "caractere",
+  RK_STRING: "cadeia",
+  RK_VOID: "vazio",
+};
+const commands: I18N_LEXER_COMMANDS = {
+  // commands
+  RK_PROGRAM: "programa",
+  RK_SWITCH: "escolha",
+  RK_CASE: "caso",
+  RK_DEFAULT: "contrario",
+  RK_CONST: "const",
+  RK_FUNCTION: "funcao",
+  RK_RETURN: "devolva",
+  RK_FOR: "para",
+  RK_FOR_ALT: "repita_para",
+  RK_FOR_FROM: "de",
+  RK_FOR_TO: "ate",
+  RK_FOR_PASS: "passo",
+  RK_BREAK: "pare",
+  RK_DO: "repita",
+  RK_DO_UNTIL: "ate_que",
+  RK_WHILE: "enquanto",
+  RK_WHILE_ALT: "repita_enquanto",
+  RK_IF: "se",
+  RK_ELSE: "senao",
+  RK_REFERENCE: "&",
+};
+const boolVal: I18N_LEXER_BOOLVAL = {
+  RK_FALSE: "falso",
+  RK_TRUE: "verdadeiro",
+};
+
+const logicOp: I18N_LEXER_LOGICOP = {
+  RK_LOGICAL_NOT: "nao",
+  RK_LOGICAL_AND: "E",
+  RK_LOGICAL_OR: "OU",
+};
+
+const langLibs: I18N_LANG_LIBS = {
+  $mathLib: "Matematica",
+  $ioLib: "ES",
+  $strLib: "Texto",
+  $arrayLib: "Arranjo",
+  $langLib: "Conversao",
+};
+
+const langFuncs: I18N_LANG_FUNCS = {
+  main_function: "inicio",
+  $read: "leia",
+  $write: "escreva",
+  $numElements: "total_de_elementos",
+  $matrixLines: "total_de_linhas",
+  $matrixColumns: "total_de_colunas",
+  $substring: "subcadeia",
+  $length: "comprimento",
+  $uppercase: "caixa_alta",
+  $lowercase: "caixa_baixa",
+  $charAt: "caractere_na_posicao",
+  $isReal: "e_real",
+  $isInt: "e_inteiro",
+  $isBool: "e_logico",
+  $castReal: "como_real",
+  $castInt: "como_inteiro",
+  $castBool: "como_logico",
+  $castString: "como_cadeia",
+  $castChar: "como_caractere",
+  $sin: "seno",
+  $cos: "cosseno",
+  $tan: "tangente",
+  $sqrt: "raiz_quadrada",
+  $pow: "potencia",
+  $log: "logaritmo",
+  $abs: "modulo",
+  $negate: "trocar_sinal",
+  $invert: "inverter_valor",
+  $max: "maximo",
+  $min: "minimo",
+  $rand: "numero_aleatorio",
+};
+// END i18n lexer strings
+export const ptLexer = makeLexer({
+  commands,
+  boolVal,
+  logicOp,
+  types,
+  langLibs,
+  langFuncs,
+});

+ 0 - 35
grammar/pt/langFunctions.js

@@ -1,35 +0,0 @@
-/* This is a dictionary of the language defined functions
-**/
-export default {
-  main_function: "inicio",
-  $read: "leia",
-  $write: "escreva",
-  $numElements: "total_de_elementos",
-  $matrixLines: "total_de_linhas",
-  $matrixColumns: "total_de_colunas",
-  $substring: "subcadeia",
-  $length: "comprimento",
-  $uppercase: "caixa_alta",
-  $lowercase: "caixa_baixa",
-  $charAt: "caractere_na_posicao",
-  $isReal: "e_real",
-  $isInt: "e_inteiro",
-  $isBool: "e_logico",
-  $castReal: "como_real",
-  $castInt: "como_inteiro",
-  $castBool: "como_logico",
-  $castString: "como_cadeia",
-  $castChar: "como_caractere",
-  $sin: "seno",
-  $cos: "cosseno",
-  $tan: "tangente",
-  $sqrt: "raiz_quadrada",
-  $pow: "potencia",
-  $log: "logaritmo",
-  $abs: "modulo",
-  $negate: "trocar_sinal",
-  $invert: "inverter_valor",
-  $max: "maximo",
-  $min: "minimo",
-  $rand: "numero_aleatorio"
-}

+ 0 - 10
grammar/pt/langLibs.js

@@ -1,10 +0,0 @@
-/**
- * This is the dictionary of the language defined libraries
- */
-export default {
-  $mathLib: "Matematica",
-  $ioLib: "ES",
-  $strLib: "Texto",
-  $arrayLib: "Arranjo",
-  $langLib: "Conversao"
-}

+ 52 - 0
js/services/languageService.ts

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

+ 13 - 0
package-lock.json

@@ -20,6 +20,7 @@
         "@babel/core": "^7.10.2",
         "@babel/plugin-transform-runtime": "^7.10.1",
         "@babel/preset-env": "^7.10.2",
+        "@types/moo": "^0.5.5",
         "@typescript-eslint/eslint-plugin": "^5.7.0",
         "@typescript-eslint/parser": "^5.0.0",
         "babel-loader": "^8.0.6",
@@ -1535,6 +1536,12 @@
       "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
       "dev": true
     },
+    "node_modules/@types/moo": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/@types/moo/-/moo-0.5.5.tgz",
+      "integrity": "sha512-eXQpwnkI4Ntw5uJg6i2PINdRFWLr55dqjuYQaLHNjvqTzF14QdNWbCbml9sza0byyXNA0hZlHtcdN+VNDcgVHA==",
+      "dev": true
+    },
     "node_modules/@types/node": {
       "version": "13.11.1",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz",
@@ -8173,6 +8180,12 @@
       "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
       "dev": true
     },
+    "@types/moo": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/@types/moo/-/moo-0.5.5.tgz",
+      "integrity": "sha512-eXQpwnkI4Ntw5uJg6i2PINdRFWLr55dqjuYQaLHNjvqTzF14QdNWbCbml9sza0byyXNA0hZlHtcdN+VNDcgVHA==",
+      "dev": true
+    },
     "@types/node": {
       "version": "13.11.1",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz",

+ 1 - 0
package.json

@@ -29,6 +29,7 @@
     "@babel/core": "^7.10.2",
     "@babel/plugin-transform-runtime": "^7.10.1",
     "@babel/preset-env": "^7.10.2",
+    "@types/moo": "^0.5.5",
     "@typescript-eslint/eslint-plugin": "^5.7.0",
     "@typescript-eslint/parser": "^5.0.0",
     "babel-loader": "^8.0.6",

+ 0 - 7
webpack.config.js

@@ -28,13 +28,6 @@ module.exports = {
           },
         },
       },
-      {
-        test: /\.g4$/,
-        exclude: /(node_modules)/,
-        use: {
-          loader: "antlr4-webpack-loader",
-        },
-      },
       {
         test: /\.tsx?$/,
         use: "ts-loader",