评估以字符串表示的嵌套函数调用

时间:2019-05-09 12:14:09

标签: javascript

如何解决JavaScript中以字符串表示的嵌套函数调用 作为“ PRODUCT(SUM(PRODUCT(2,2),2),3)” => 18 为“ SUM(12,PRODUCT(1,2))” => 14

使用eval()会很容易。但是需要使用eval()而无需

const SUM = (...args) => args.reduce((a, b) => a + b);
const PRODUCT = (...args) => args.reduce((a, b) => a * b);
const evaluateString = str => {
    //code to evaluate "PRODUCT(SUM(PRODUCT(2,2),2),3)"
}

1 个答案:

答案 0 :(得分:0)

就像Yeldar所说的那样,最干净的方法是创建语法树并对其进行求值,但是对于您给出的示例,由于您的函数仅实现了平凡的运算符,因此您似乎总是只能得到2个args。有了这些信息,为这种基本用途编写代码将很痛苦,因此我建议在这种情况下创建自己的评估程序。

好吧,这显然不是一个很干净的方法,它们可能有很多可能的升级,但这是完成工作的一段代码:

const SUM = (...args) => args.reduce((a, b) => a + b);
const PRODUCT = (...args) => args.reduce((a, b) => a * b);
const strToEvaluate = "PRODUCT(SUM(PRODUCT(2,2),PRODUCT(SUM(1,1),2)),3);";

function myEval(str) {
    if(!isNaN(str)) {
        return Number(str);
    }
    if(str.includes('(')) {
        let fn = str.split('(')[0];
        let pos = getParenthesisAndComaPos(str.substring(str.indexOf('(')+1));
        let arg1 = myEval(str.substring(str.indexOf('(')+1).substring(0, pos[0]));
        let arg2 = myEval(str.substring(str.indexOf('(')+1).substring(pos[0]+1, pos[1]));
        switch(fn) {
    	    case 'PRODUCT':
      	        return PRODUCT(arg1, arg2);
            case 'SUM':
      	        return SUM(arg1, arg2);
        }
    }
}

//Will return a tab with position of the coma between arg0 and arg1 and position of the end parenthesis
function getParenthesisAndComaPos(str) {
    let counter = 1;
    let i=0;
    let c=0;
    while (counter>0 && i<=str.length) {
  	if(counter==1 && str.charAt(i)==',') {
    	    c = i;
        }
  	if(str.charAt(i)==')') {
    	    counter--;
        } else if(str.charAt(i)=='(') {
          counter++;
        }
        i++;
    }
    return [c, i-1];
}

console.log(myEval(strToEvaluate));