浏览代码

Implement new language defined functions structure

-Refactor ivprogParser and ivprogProcessor to use LanguageDefinedFunction object
-Refactor the definedFunctions.js file
-Refactor the lexer grammar file removing the defined functions name constants
-Create the langFunctions.js file as a dictionary with the languaged defined functions
Lucas de Souza 6 年之前
父节点
当前提交
904bb845ba

+ 0 - 7
grammar/en/ivprog.g4

@@ -1,12 +1,5 @@
 lexer grammar ivprog;
 
-@lexer::members{
-  //Translate to fit your language
-  ivprog.MAIN_FUNCTION_NAME = "start";
-  ivprog.READ_FUNCTION_NAME = "read";
-  ivprog.WRITE_FUNCTION_NAME = "write";
-}
-
 // BEGIN i18n Lexical rules
 RK_PROGRAM
   : 'program'

+ 7 - 0
grammar/en/langFunctions.js

@@ -0,0 +1,7 @@
+/* This is a dictionary of the language defined functions
+**/
+export default {
+  main_function: "start",
+  $read: "read",
+  $write: "write"
+}

+ 0 - 7
grammar/es/ivprog.g4

@@ -1,12 +1,5 @@
 lexer grammar ivprog;
 
-@lexer::members{
-  //Translate to fit your language
-  ivprog.MAIN_FUNCTION_NAME = "inicio";
-  ivprog.READ_FUNCTION_NAME = "leia";
-  ivprog.WRITE_FUNCTION_NAME = "escreva";
-}
-
 // BEGIN i18n Lexical rules
 RK_PROGRAM
   : 'programa'

+ 7 - 0
grammar/es/langFunctions.js

@@ -0,0 +1,7 @@
+/* This is a dictionary of the language defined functions
+**/
+export default {
+  main_function: "inicio",
+  $read: "leia",
+  $write: "escreva"
+}

+ 6 - 3
grammar/index.js

@@ -1,7 +1,10 @@
 import * as PT from './pt/ivprog.g4';
+import PTFuncs from './pt/langFunctions';
 import * as EN from './en/ivprog.g4';
+import ENFuncs from './en/langFunctions';
 import * as ES from './es/ivprog.g4';
+import ESFuncs from './es/langFunctions';
 
-exports.pt = PT.ivprog;
-exports.en = EN.ivprog;
-exports.es = ES.ivprog;
+exports.pt = {lexer: PT.ivprog, langFuncs: PTFuncs};
+exports.en = {lexer: EN.ivprog, langFuncs: ENFuncs};
+exports.es = {lexer: ES.ivprog, langFuncs: ESFuncs};

+ 0 - 7
grammar/pt/ivprog.g4

@@ -1,12 +1,5 @@
 lexer grammar ivprog;
 
-@lexer::members{
-  //Translate to fit your language
-  ivprog.MAIN_FUNCTION_NAME = "inicio";
-  ivprog.READ_FUNCTION_NAME = "leia";
-  ivprog.WRITE_FUNCTION_NAME = "escreva";
-}
-
 // BEGIN i18n Lexical rules
 RK_PROGRAM
   : 'programa'

+ 7 - 0
grammar/pt/langFunctions.js

@@ -0,0 +1,7 @@
+/* This is a dictionary of the language defined functions
+**/
+export default {
+  main_function: "inicio",
+  $read: "leia",
+  $write: "escreva"
+}

+ 13 - 9
js/ast/ivprogParser.js

@@ -4,7 +4,8 @@ import * as Commands from './commands/';
 import { Types, toInt, toString } from './types';
 import { convertFromString } from './operators';
 import { SyntaxErrorFactory } from './error/syntaxErrorFactory';
-import { NAMES } from './../processor/definedFunctions';
+import { LanguageDefinedFunction } from './../processor/definedFunctions';
+import { LanguageService } from '../services/languageService';
 
 export class IVProgParser {
 
@@ -37,6 +38,7 @@ export class IVProgParser {
     this.functionTypes = this.variableTypes.concat(this.lexerClass.RK_VOID);
     this.parsingArrayDimension = 0;
     this.scope = [];
+    this.langFuncs = LanguageService.getCurrentLangFuncs();
   }
 
   parseTree () {
@@ -204,7 +206,6 @@ export class IVProgParser {
 
   parseGlobalVariables () {
     const decl = this.parseMaybeConst();
-    const eosToken = this.getToken();
     this.checkEOS();
     this.pos++;
     return decl;
@@ -402,7 +403,7 @@ export class IVProgParser {
     const func = new Commands.Function(functionID, returnType, formalParams, commandsBlock);
     if (functionID === null && !func.isMain) {
       // TODO: better error message
-      throw SyntaxErrorFactory.invalid_main_return(this.lexerClass.MAIN_FUNCTION_NAME,
+      throw SyntaxErrorFactory.invalid_main_return(LanguageDefinedFunction.getMainFunctionName(),
         this.lexer.literalNames[this.lexerClass.RK_VOID],
         token.line);
     }
@@ -449,7 +450,7 @@ export class IVProgParser {
     } 
     this.pos++;
     if (this.insideScope(IVProgParser.FUNCTION)) {
-      if (token.text === this.lexerClass.MAIN_FUNCTION_NAME){
+      if (token.text === LanguageDefinedFunction.getMainFunctionName()){
         return null;
       }
     }
@@ -926,12 +927,15 @@ export class IVProgParser {
   }
 
   getFunctionName (id) {
-    if (id === this.lexerClass.READ_FUNCTION_NAME) {
-      return NAMES.READ;
-    } else if (id === this.lexerClass.WRITE_FUNCTION_NAME) {
-      return NAMES.WRITE;
-    } else {
+    const name = LanguageDefinedFunction.getInternalName(id);
+    console.log('###');
+    console.log(id);
+    console.log(name);
+    console.log('###');
+    if (name === null) {
       return id;
+    } else {
+      return name;
     }
   }
 

+ 20 - 7
js/processor/definedFunctions.js

@@ -1,5 +1,6 @@
 import * as Commands from './../ast/commands';
 import {Types} from './../ast/types';
+import { LanguageService } from '../services/languageService';
 
 function createOutputFun () {
   const block = new Commands.CommandBlock([], [new Commands.SysCall('$write')]);
@@ -17,12 +18,24 @@ function createInputFun () {
   return func;
 }
 
-export const LanguageDefinedFunction = Object.freeze({
-  $write: createOutputFun(),
-  $read: createInputFun()
-});
+function valueToKey (value, object) {
+  for (const key in object) {
+    if(object.hasOwnProperty(key)){
+      if (object[key] === value) {
+        return key;
+      }
+    }
+  }
+  return null;
+}
 
-export const NAMES = Object.freeze({
-  WRITE: '$write',
-  READ: '$read'
+const funcsObject = {
+  $read: createInputFun(),
+  $write: createOutputFun()
+}
+
+export const LanguageDefinedFunction = Object.freeze({
+  getMainFunctionName: () => LanguageService.getCurrentLangFuncs().main_function,
+  getInternalName: (localName) => valueToKey(localName, LanguageService.getCurrentLangFuncs()),
+  getFunction: (internalName) => funcsObject[internalName],
 });

+ 4 - 4
js/processor/ivprogProcessor.js

@@ -6,7 +6,7 @@ import { Modes } from './modes';
 import { Context } from './context';
 import { Types, toInt } from './../ast/types';
 import { Operators } from './../ast/operators';
-import { NAMES, LanguageDefinedFunction } from './definedFunctions';
+import { LanguageDefinedFunction } from './definedFunctions';
 import { resultTypeAfterInfixOp, resultTypeAfterUnaryOp } from './compatibilityTable';
 import * as Commands from './../ast/commands/';
 import * as Expressions from './../ast/expressions/';
@@ -69,7 +69,7 @@ export class IVProgProcessor {
 
   findFunction (name) {
     if(name.match(/^\$.+$/)) {
-      const fun = LanguageDefinedFunction[name];
+      const fun = LanguageDefinedFunction.getFunction(name);
       if(!!!fun) {
         throw new Error("!!!Internal Error. Language defined function not implemented -> " + name + "!!!");
       }
@@ -232,9 +232,9 @@ export class IVProgProcessor {
   }
 
   executeSysCall (store, cmd) {
-    if (cmd.id === NAMES.WRITE) {
+    if (cmd.id === "$write") {
       return this.runWriteFunction(store)
-    } else if (cmd.id === NAMES.READ) {
+    } else if (cmd.id === "$read") {
       return this.runReadFunction(store);
     }
   }

+ 13 - 4
js/services/languageService.js

@@ -18,11 +18,20 @@ export const LanguageService  = Object.freeze({
   },
 
   getCurrentLexer: () => {
-    const lexer = Lexers[LanguageService.getLang()];
-    if(lexer === null || lexer === undefined) {
-      return Lexers[DEFAULT_LANG];
+    const langInfo = Lexers[LanguageService.getLang()];
+    if(langInfo === null || langInfo === undefined) {
+      return Lexers[DEFAULT_LANG].lexer;
     } else {
-      return lexer;
+      return langInfo.lexer;
+    }
+  },
+
+  getCurrentLangFuncs: () => {
+    const langInfo = Lexers[LanguageService.getLang()];
+    if(langInfo === null || langInfo === undefined) {
+      return Lexers[DEFAULT_LANG].langFuncs;
+    } else {
+      return langInfo.langFuncs;
     }
   }
 

+ 4 - 0
tests/test40.spec.js

@@ -5,6 +5,10 @@ import { LanguageService } from '../js/services/languageService';
 
 describe('The LanguageService', function () {
 
+  beforeEach( () => {
+    localStorage.setItem('ivprog.lang', 'en');  
+  });
+
   const code = `program {
 
     function start() {