在 Javascript 中我自己的类似函数的评估
Eval like function by my own in Javascript
我正在尝试在 Javascript 中创建类似 eval() 的函数(从字符串计算表达式)。
我在连续的“-”操作中遇到错误。
除了“-”之外,一切正常。
谁能帮我让“-”工作
用于实时预览代码笔 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
您应该考虑这是否按预期工作,因为任何负数都会破坏您的代码。 (例如:垫子(“1+-1”))。考虑正则表达式是否具有解析表达式所需的表达能力,因为它们非常有限。 (例如,您不能单独使用正则表达式检查平衡括号)
您可能想研究解析,网上有很多教程对此进行了描述。
你可能还想看看正则语言的局限性(这是正则表达式可以表达的/"parse")
下一步可能是研究所谓的 "context free grammars",它具有更强的表达能力。
对于完整的解析,一些有用的关键字是 "Tokenizing" 和 "Abstract syntax trees"。希望其中的一些可以帮助您研究您需要的东西。
问题是 4-5 产生 -1,所以在第一次替换后你得到
-1-1
,导致无限循环,或者,使用您的 abs()
hack
1-1
,导致错误的结果。
一个选择是删除 abs()
hack 并使用 ns.indexOf('-', 1)
,但这可能会导致负数出现问题——而且您的数字正则表达式似乎无法处理也有负数......所以你也需要解决这个问题。
解决此问题的一个选项可能是:
- 添加一个预处理步骤,用其他字符替换所有被数字包围的“-”,例如'%'
- 所有剩余的 '-' 都是一元的。相应地扩展您的正则表达式以包含一元减号
- 更改二进制负处理代码以改为使用“%”。
或者,您可以使用这样的递归方法代替术语重写方法:
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);
}
我正在尝试在 Javascript 中创建类似 eval() 的函数(从字符串计算表达式)。 我在连续的“-”操作中遇到错误。 除了“-”之外,一切正常。 谁能帮我让“-”工作 用于实时预览代码笔 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
您应该考虑这是否按预期工作,因为任何负数都会破坏您的代码。 (例如:垫子(“1+-1”))。考虑正则表达式是否具有解析表达式所需的表达能力,因为它们非常有限。 (例如,您不能单独使用正则表达式检查平衡括号)
您可能想研究解析,网上有很多教程对此进行了描述。
你可能还想看看正则语言的局限性(这是正则表达式可以表达的/"parse")
下一步可能是研究所谓的 "context free grammars",它具有更强的表达能力。
对于完整的解析,一些有用的关键字是 "Tokenizing" 和 "Abstract syntax trees"。希望其中的一些可以帮助您研究您需要的东西。
问题是 4-5 产生 -1,所以在第一次替换后你得到
-1-1
,导致无限循环,或者,使用您的 abs()
hack
1-1
,导致错误的结果。
一个选择是删除 abs()
hack 并使用 ns.indexOf('-', 1)
,但这可能会导致负数出现问题——而且您的数字正则表达式似乎无法处理也有负数......所以你也需要解决这个问题。
解决此问题的一个选项可能是:
- 添加一个预处理步骤,用其他字符替换所有被数字包围的“-”,例如'%'
- 所有剩余的 '-' 都是一元的。相应地扩展您的正则表达式以包含一元减号
- 更改二进制负处理代码以改为使用“%”。
或者,您可以使用这样的递归方法代替术语重写方法:
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);
}