فهرست منبع

Implement the management required to deal with library_id

-Link the language defined languages to their localized name counter parts

-Refactor ivprogParser to handle LIB_ID lexer ruler

-Create error message for LIB_ID used as variable

-Create the langLibs.js file to so libvrary  names can be translated
Lucas de Souza 5 سال پیش
والد
کامیت
a82b8f9b7c

+ 3 - 1
grammar/en/ivprog.g4

@@ -164,7 +164,9 @@ ID
   : [a-zA-Z_] [a-zA-Z0-9_]*
   ;
 
-// ID_BIBLIOTECA     : ID '.' ID;
+LIB_ID
+  : ID '.' ID
+  ;
 
 INTEGER
   : [0-9]+

+ 27 - 1
grammar/en/langFunctions.js

@@ -3,5 +3,31 @@
 export default {
   main_function: "start",
   $read: "read",
-  $write: "write"
+  $write: "write",
+  $numElements: "numero_elementos",
+  $matrixLines: "matriz_linhas",
+  $matrixColumns: "matriz_colunas",
+  $substring: "subcadeia",
+  $length: "comprimento",
+  $uppercase: "caixa_alta",
+  $lowercase: "caixa_baixa",
+  $charAt: "char_at",
+  $isReal: "e_real",
+  $isInt: "e_inteiro",
+  $isBool: "e_logico",
+  $castReal: "como_real",
+  $castInt: "como_inteiro",
+  $castBool: "como_logico",
+  $castString: "como_cadeia",
+  $sin: "sen",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "raiz_quadrada",
+  $pow: "pot",
+  $log: "log",
+  $abs: "modulo",
+  $negate: "trocar_sinal",
+  $invert: "inverter_valor",
+  $max: "maximo",
+  $min: "minimo"
 }

+ 10 - 0
grammar/en/langLibs.js

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

+ 3 - 1
grammar/es/ivprog.g4

@@ -164,7 +164,9 @@ ID
   : [a-zA-Z_] [a-zA-Z0-9_]*
   ;
 
-// ID_BIBLIOTECA     : ID '.' ID;
+LIB_ID
+  : ID '.' ID
+  ;
 
 INTEGER
   : [0-9]+

+ 27 - 1
grammar/es/langFunctions.js

@@ -3,5 +3,31 @@
 export default {
   main_function: "inicio",
   $read: "leia",
-  $write: "escreva"
+  $write: "escreva",
+  $numElements: "numero_elementos",
+  $matrixLines: "matriz_linhas",
+  $matrixColumns: "matriz_colunas",
+  $substring: "subcadeia",
+  $length: "comprimento",
+  $uppercase: "caixa_alta",
+  $lowercase: "caixa_baixa",
+  $charAt: "char_at",
+  $isReal: "e_real",
+  $isInt: "e_inteiro",
+  $isBool: "e_logico",
+  $castReal: "como_real",
+  $castInt: "como_inteiro",
+  $castBool: "como_logico",
+  $castString: "como_cadeia",
+  $sin: "sen",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "raiz_quadrada",
+  $pow: "pot",
+  $log: "log",
+  $abs: "modulo",
+  $negate: "trocar_sinal",
+  $invert: "inverter_valor",
+  $max: "maximo",
+  $min: "minimo"
 }

+ 10 - 0
grammar/es/langLibs.js

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

+ 6 - 3
grammar/index.js

@@ -1,10 +1,13 @@
 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';
 
-exports.pt = {lexer: PT.ivprog, langFuncs: PTFuncs};
-exports.en = {lexer: EN.ivprog, langFuncs: ENFuncs};
-exports.es = {lexer: ES.ivprog, langFuncs: ESFuncs};
+exports.pt = {lexer: PT.ivprog, langFuncs: PTFuncs, langLibs: PTLibs};
+exports.en = {lexer: EN.ivprog, langFuncs: ENFuncs, langLibs: ENLibs};
+exports.es = {lexer: ES.ivprog, langFuncs: ESFuncs, langLibs: ESLibs};

+ 3 - 1
grammar/pt/ivprog.g4

@@ -164,7 +164,9 @@ ID
   : [a-zA-Z_] [a-zA-Z0-9_]*
   ;
 
-// ID_BIBLIOTECA     : ID '.' ID;
+LIB_ID
+  : ID '.' ID
+  ;
 
 INTEGER
   : [0-9]+

+ 27 - 1
grammar/pt/langFunctions.js

@@ -3,5 +3,31 @@
 export default {
   main_function: "inicio",
   $read: "leia",
-  $write: "escreva"
+  $write: "escreva",
+  $numElements: "numero_elementos",
+  $matrixLines: "matriz_linhas",
+  $matrixColumns: "matriz_colunas",
+  $substring: "subcadeia",
+  $length: "comprimento",
+  $uppercase: "caixa_alta",
+  $lowercase: "caixa_baixa",
+  $charAt: "char_at",
+  $isReal: "e_real",
+  $isInt: "e_inteiro",
+  $isBool: "e_logico",
+  $castReal: "como_real",
+  $castInt: "como_inteiro",
+  $castBool: "como_logico",
+  $castString: "como_cadeia",
+  $sin: "sen",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "raiz_quadrada",
+  $pow: "pot",
+  $log: "log",
+  $abs: "modulo",
+  $negate: "trocar_sinal",
+  $invert: "inverter_valor",
+  $max: "maximo",
+  $min: "minimo"
 }

+ 10 - 0
grammar/pt/langLibs.js

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

+ 1 - 0
i18n/pt/error.json

@@ -12,6 +12,7 @@
   "invalid_terminal": "Não é possível utilizar $0 na expressão da linha: $1, coluna: $2. Tente um valor númerico, variável ou chamada de função.",
   "const_not_init": "Erro na linha: $0, coluna: $1. Uma variável declarada como const deve ser inicializada",
   "id_missing": "Esperava-se um identificador, mas encontrou-se $0 na linha: $1, coluna: $2",
+  "invalid_id_format": "$0 na linha: $1, coluna: $2 não é um identificador válido. O símbolo '.' não é permitido neste contexto.",
   "main_missing": "A função principal não foi encontrada",
   "invalid_global_var": "Erro crítico: Chamada inválida da função initGlobal fora do contexto BASE",
   "not_implemented": "Erro interno crítico: A função definida pelo sistema $0 não foi implementada.",

+ 4 - 0
js/ast/error/syntaxErrorFactory.js

@@ -51,5 +51,9 @@ export const SyntaxErrorFactory = Object.freeze({
   const_not_init: (token) => {
     const context = [token.line, token.column];
     return new SyntaxError(LocalizedStrings.getError("const_not_init", context));
+  },
+  invalid_id_format: (token) => {
+    const context = [token.text, token.line, token.column];
+    return new SyntaxError(LocalizedStrings.getError("invalid_id_format", context));
   }
 });

+ 27 - 8
js/ast/ivprogParser.js

@@ -477,7 +477,7 @@ export class IVProgParser {
     const token = this.getToken();
     if(token.type !== this.lexerClass.ID) {
       throw SyntaxErrorFactory.id_missing(token);
-    } 
+    }
     this.pos++;
     if (this.insideScope(IVProgParser.FUNCTION)) {
       if (token.text === LanguageDefinedFunction.getMainFunctionName()){
@@ -487,6 +487,15 @@ export class IVProgParser {
     return token.text;
   }
 
+  parseMaybeLibID () {
+    const token = this.getToken();
+    if(token.type !== this.lexerClass.ID && token.type !== this.lexerClass.LIB_ID) {
+      throw SyntaxErrorFactory.id_missing(token);
+    } 
+    this.pos++;
+    return token.text;
+  }
+
   parseType () {
     const token = this.getToken();
     if(token.type === this.lexerClass.ID && this.insideScope(IVProgParser.FUNCTION)) {
@@ -560,6 +569,8 @@ export class IVProgParser {
       return cmd;
     } else if (token.type === this.lexerClass.ID) {
       return this.parseIDCommand();
+    } else if (token.type === this.lexerClass.LIB_ID) {
+      return this.parseIDCommand();
     } else if (token.type === this.lexerClass.RK_RETURN) {
       return this.parseReturn();
     } else if (token.type === this.lexerClass.RK_WHILE) {
@@ -728,9 +739,11 @@ export class IVProgParser {
   }
 
   parseIDCommand () {
-    const id = this.parseID();
+    const refToken = this.getToken();
+    const isID = refToken.type === this.lexerClass.ID;
+    const id = this.parseMaybeLibID();
     const equalOrParenthesis = this.getToken();
-    if (equalOrParenthesis.type === this.lexerClass.EQUAL) {
+    if (isID && equalOrParenthesis.type === this.lexerClass.EQUAL) {
       const sourceInfo = SourceInfo.createSourceInfo(this.getToken());
       this.pos++
       const exp = this.parseExpressionOR();
@@ -744,8 +757,10 @@ export class IVProgParser {
       this.checkEOS();
       this.pos++;
       return funcCall;
-    } else {
+    } else if (isID) {
       throw SyntaxErrorFactory.token_missing_list(['=','('], equalOrParenthesis);
+    } else {
+      throw SyntaxErrorFactory.invalid_id_format(refToken);
     }
   }
 
@@ -941,6 +956,7 @@ export class IVProgParser {
       case this.lexerClass.OPEN_CURLY:
         return this.parseArrayLiteral();
       case this.lexerClass.ID:
+      case this.lexerClass.LIB_ID:
         return this.parseIDTerm();
       case this.lexerClass.OPEN_PARENTHESIS:
         return this.parseParenthesisExp();
@@ -950,9 +966,10 @@ export class IVProgParser {
   }
 
   parseIDTerm () {
-    const id = this.parseID();
-    const tokenA = this.getToken(this.pos - 1);
-    if(this.checkOpenBrace(true)) {
+    const tokenA = this.getToken();
+    const id = this.parseMaybeLibID();
+    const isID = tokenA.type === this.lexerClass.ID;
+    if(isID && this.checkOpenBrace(true)) {
       let tokenB = null;
       this.pos++;
       const firstIndex = this.parseExpression();
@@ -976,11 +993,13 @@ export class IVProgParser {
 
     } else if (this.checkOpenParenthesis(true)) {
       return this.parseFunctionCallExpression(id);
-    } else {
+    } else if (isID) {
       const sourceInfo = SourceInfo.createSourceInfo(tokenA);
       const exp = new Expressions.VariableLiteral(id);
       exp.sourceInfo = sourceInfo;
       return exp;
+    } else {
+      throw SyntaxErrorFactory.invalid_id_format(tokenA);
     }
   }
 

+ 91 - 5
js/processor/definedFunctions.js

@@ -1,5 +1,20 @@
 import { LanguageService } from '../services/languageService';
 import {createInputFun, createOutputFun} from './lib/io';
+import {createLengthFun, createLowercaseFun,
+  createrCharAtFun, createSubstringFun,
+  createUppercaseFun} from './lib/strings';
+import {createMatrixColumnsFun, createMatrixLinesFun,
+  createNumElementsFun} from './lib/arrays';
+import {createCastBoolFun, createCastIntFun,
+  createCastRealFun, createCastStringFun,
+  createIsBoolFun, createIsIntFun,
+  createIsRealFun} from './lib/lang';
+import {createAbsFun, createCosFun,
+  createInvertFun, createLogFun,
+  createMaxFun, createMinFun,
+  createNegateFun, createPowFun,
+  createSinFun, createSqrtFun,
+  createTanFun} from './lib/math';
 
 function valueToKey (value, object) {
   for (const key in object) {
@@ -12,13 +27,84 @@ function valueToKey (value, object) {
   return null;
 }
 
-const funcsObject = {
-  $read: createInputFun(),
-  $write: createOutputFun()
+function concatObjects (...objs) {
+  let result = {};
+  for (let i = 0; i < objs.length; i++) {
+    const obj = objs[i];
+    for(const key in obj) {
+      if(obj.hasOwnProperty(key)) {
+        result[key] = obj[key];
+      }
+    }
+  }
+  return result;
+}
+
+const libsObject = {
+  $mathLib: {
+    $sin: createSinFun(),
+    $cos: createCosFun(),
+    $tan: createTanFun(),
+    $sqrt: createSqrtFun(),
+    $pow: createPowFun(),
+    $log: createLogFun(),
+    $abs: createAbsFun(),
+    $negate: createNegateFun(),
+    $invert: createInvertFun(),
+    $max: createMaxFun(),
+    $min: createMinFun()
+  },
+  $ioLib: {
+    $read: createInputFun(),
+    $write: createOutputFun()
+  },
+  $strLib: {
+    $substring: createSubstringFun(),
+    $length: createLengthFun(),
+    $uppercase: createUppercaseFun(),
+    $lowercase: createLowercaseFun(),
+    $charAt: createrCharAtFun(),
+  },
+  $arrayLib: {
+    $numElements: createNumElementsFun(),
+    $matrixLines: createMatrixLinesFun(),
+    $matrixColumns: createMatrixColumnsFun()
+  },
+  $langLib: {
+    $isReal: createIsRealFun(),
+    $isInt: createIsIntFun(),
+    $isBool: createIsBoolFun(),
+    $castReal: createCastRealFun(),
+    $castInt: createCastIntFun(),
+    $castBool: createCastBoolFun(),
+    $castString: createCastStringFun()
+  }
 }
 
+const funcsObject = concatObjects(libsObject.$ioLib, libsObject.$langLib,
+  libsObject.$strLib, libsObject.$arrayLib);
+
 export const LanguageDefinedFunction = Object.freeze({
   getMainFunctionName: () => LanguageService.getCurrentLangFuncs().main_function,
-  getInternalName: (localName) => valueToKey(localName, LanguageService.getCurrentLangFuncs()),
-  getFunction: (internalName) => funcsObject[internalName],
+  getInternalName: (localName) => {
+    if (localName.indexOf(".") !== -1) {
+      const names = localName.split(".");
+      const lib = valueToKey(names[0], LanguageService.getCurrentLangLibs());
+      const internalName = valueToKey(names[1], LanguageService.getCurrentLangFuncs());
+      if (lib === null || internalName === null) {
+        return null;
+      }
+      return lib + "." + internalName;
+    }
+    return valueToKey(localName, LanguageService.getCurrentLangFuncs());
+  },
+  getFunction: (internalName) => {
+    if (internalName.indexOf(".") !== -1) {
+      const names = internalName.split(".");
+      const libName = names[0];
+      const funName = names[1];
+      return libsObject[libName][funName];
+    }
+    return funcsObject[internalName];
+  },
 });

+ 1 - 1
js/processor/lib/math.js

@@ -97,7 +97,7 @@ export function createPowFun () {
 export function createLogFun () {
   const logFun = (sto, _) => {
     const x = sto.applyStore('x');
-    if (x.isNegative()) {
+    if (x.value.isNegative()) {
       return Promise.reject("the value passed to log function cannot be negative");
     }
     const result = toReal(Math.log10(x.number));

+ 1 - 1
js/processor/lib/strings.js

@@ -8,7 +8,7 @@ import { Types, toInt } from './../../ast/types';
 *  length
 *  uppercase
 *  lowercase
-*  letterAt
+*  charAt
 **/
 
 export function createSubstringFun () {

+ 8 - 0
js/services/languageService.js

@@ -33,6 +33,14 @@ export const LanguageService  = Object.freeze({
     } else {
       return langInfo.langFuncs;
     }
+  },
+
+  getCurrentLangLibs: () => {
+    const langInfo = Lexers[LanguageService.getLang()];
+    if(langInfo === null || langInfo === undefined) {
+      return Lexers[DEFAULT_LANG].langLibs;
+    }
+    return langInfo.langLibs;
   }
 
 });