Eval喜欢我自己在Javascript中的功能

时间:2018-02-11 16:49:15

标签: javascript eval clone

我正在尝试在Javascript中创建类似eval()的函数(从字符串计算表达式)。 我在连续' - '操作中遇到错误。 除了' - '一切都很好。 任何人都可以帮助我让' - '工作 用于实时预览codepen link- https://codepen.io/raj1998211/pen/yvVXLd

function mat(str){
  // var sum = 0;
  ns = str;
  while(ns.indexOf('/') > 0){
    var regex = /(\d+|(\d+\.\d+))(\/)((\d+\.\d+)|\d+)/g;
     var ns = ns.replace(regex, function(a){
      arr = a.split("/");    
      ans = Number(arr[0]) / Number(arr[1]);
      return ans;
    });
    // console.log(ns);
  }
  while(ns.indexOf('*') > 0){
    var regex = /(\d+|(\d+\.\d+))(\*)((\d+\.\d+)|\d+)/g;
    var ns = ns.replace(regex, function(a){
      arr = a.split("*");    
      ans = Number(arr[0]) * Number(arr[1]);
      return ans;
    });
    // str = ns;
    // console.log(ns);
  }

  while(ns.indexOf('-') > 0){
    var regex = /(\-\d+|\d+|(\d+\.\d+))(\-)((\d+\.\d+)|\d+)/g;
    var ns = ns.replace(regex, function(a){
      arr = a.split("-");    
      ans = Number(arr[0]) - Number(arr[1]);
      return Math.abs(ans);
      // return ans;
    });
    // console.log(ns);
  }
//   if(ns.indexOf('-') === 0){

//   }

  if(ns.indexOf('+') > 0){
    arr = ns.split("+");
    sum = 0;
    for(i = 0; i < arr.length; i++){
      sum += Number(arr[i]);
    }
    ns = sum;
  }
  // return "sum";
  return ns;
}

console.log(mat("4-5-1")); //infinite loop if '-' comes on first char of str

2 个答案:

答案 0 :(得分:0)

您应该考虑这是否按预期工作,因为任何负数都会破坏您的代码。 (例如:mat(&#34; 1 + -1&#34;))。考虑正则表达式是否具有解析表达式所需的表达能力,因为它们非常有限。 (例如,您不能仅使用正则表达式检查平衡括号)

你可能想要研究解析,网上有很多教程描述这个。

您可能还想查找常规语言的限制(正则表达式可以表达/&#34;解析&#34;)

下一步可能是研究所谓的&#34;无上下文语法&#34;,它具有更强的表达能力。

对于完整的解析,一些有用的关键字是&#34; Tokenizing&#34;和#34;抽象语法树&#34;。希望其中一些可以帮助您研究您的需求。

答案 1 :(得分:0)

问题是4-5产生-1,所以在第一次替换后你得到

-1-1,导致infinte循环,或者,abs() hack

1-1,导致错误的结果。

一种选择是删除abs()黑客并使用ns.indexOf('-', 1),但这可能会导致数字出现负数问题 - 并且您的数字正则表达式似乎无法解决负数也是......所以你也需要解决这个问题。

解决此问题的一个选择可能是:

  • 添加预处理步骤,替换所有&#39; - &#39;由具有一些其他字符的数字包围,例如&#39;%&#39;
  • 所有剩余的&#39; - &#39;是一元的。扩展正则表达式以相应地包含一元减号
  • 更改二进制减去处理代码以使用&#39;%&#39;代替。

或者,你可以使用像这样的递归方法而不是你的术语重写方法:

function mat(str) {
  var operators = "/*-+"; 
  for (var i = 0; i < 4; i++) {
    var op = operators.charAt(i);
    var pos = str.indexOf(op);
    if (pos > 0 && operators.indexOf(str.charAt(pos - 1)) == -1) {
      var left = mat(str.substr(0, pos));
      var right = mat(str.substr(pos + 1));
      switch (op) {
        case "/": return left / right;
        case "*": return left * right;
        case "-": return left - right;
        case "+": return left + right; 
      }
    }
  }
  return Number(str);
}