rosetta-converters_dist_src_converter.js

/***************************************************
 * Licensed Materials - Property of HCL
 * (c)Copyright HCL America, Inc. 2023
 ***************************************************/

/**
 * @module rosetta-converter-api
 */

import antlr from 'antlr4';
import NotesFormulaLexer from './lib/NotesFormulaLexer.js';
import NotesFormulaParser from './lib/NotesFormulaParser.js';
import NotesFormulaToJs from './NotesFormulaToJs.js';
import OpenFormulaLexer from './lib/OpenFormulaLexer.js';
import OpenFormulaParser from './lib/OpenFormulaParser.js';
import OpenFormulaToJs from './OpenFormulaToJs.js';
import ErrorListener from './ErrorListener.js';

const NON_FORMULA = /<%=[\S\s]*%>/g; // detect formula type without non formula string
/**
 * Get javascript code converted from formula
 * @param {Object} rosettajs - rosetta API object
 * @param {String} input - formula string
 * @returns {String} - javascript code
 * @throws {Error} - if formula type is not supported
*/
export function getRosettaJSFromFormula(rosettajs, input) {
  if (isOpenFormula(input)) {
    return convertOpenFormula(rosettajs, input);
  } else if (isNotes(input)) {
    return convertNotesFormula(rosettajs, input);
  } else {
    throw new Error('Unsupported formula type');
  }
}

function convertOpenFormula(rosettajs, input) {
  const errorListener = new ErrorListener();
  const chars = new antlr.InputStream(input);
  const lexer = new OpenFormulaLexer(chars);
  lexer.removeErrorListeners();
  lexer.addErrorListener(errorListener);
  const tokens = new antlr.CommonTokenStream(lexer);
  const parser = new OpenFormulaParser(tokens);
  parser.removeErrorListeners();
  parser.addErrorListener(errorListener);

  const tree = parser.formulaInput();
  if(errorListener.getErrors().length > 0) {
    handleError(errorListener.getErrors());
    return;
  }

  const converter = new OpenFormulaToJs(rosettajs, input);
  const converted = converter.visit(tree);
  return converted;
}

export function convertNotesFormula(rosettajs, input) {
  if(!input.endsWith(';')) {
    input += ';';
  }
  const errorListener = new ErrorListener();
  const chars = new antlr.InputStream(input);
  const lexer = new NotesFormulaLexer(chars);
  lexer.removeErrorListeners();
  lexer.addErrorListener(errorListener);
  const tokens = new antlr.CommonTokenStream(lexer);
  const parser = new NotesFormulaParser(tokens);
  parser.removeErrorListeners();
  parser.addErrorListener(errorListener);

  const tree = parser.formulaInput();
  if(errorListener.getErrors().length > 0) {
    handleError(errorListener.getErrors());
    return;
  }

  const converter = new NotesFormulaToJs(rosettajs, input);
  const converted = converter.visit(tree);
  return converted;
}

export function isNotes(inputs) {
  return /@[a-zA-Z]|@|:=|=|REM|SELECT|DEFAULT|FIELD|ENVIRONMENT/g.test(inputs.replace(NON_FORMULA, '').trim());
}

export function isOpenFormula(inputs) {
  return inputs.replace(NON_FORMULA, '').trim().startsWith('=');
}

export const LANGUAGE = {
  ERROR: -1,
  UNKNOWN: 0,
  NOTES: 1,
  OPEN_FORMULA: 2
};

export function getFormulaLang(inputs) {
  try {
    if (isOpenFormula(inputs)) {
      return LANGUAGE.OPEN_FORMULA;
    } else if (isNotes(inputs)) {
      return LANGUAGE.NOTES;
    } else {
      return LANGUAGE.UNKNOWN;
    }
  } catch (e) {
    return LANGUAGE.ERROR;
  }
}

function handleError(error) {
  if(error !== null) {
    const msg = JSON.stringify(error);
    throw Error(msg);
  }
}