我正在尝试在JavaScript中创建一个允许嵌套函数的自定义公式求值器。我已经能够创建基本的计算函数,如平均值,总和和最小值(以及许多其他函数),但我在嵌套函数方面遇到了麻烦,我可以使用一些帮助。
所需的行为如下所示:
用户使用语法funcName在文本输入中输入公式(arg1,arg2,...),其中funcName是计算函数的名称,arg1,arg2,...是函数的参数。参数可以是数字或其他函数(即平均(1,2)或平均(SUM(1,2),2)。我希望公式具有任意复杂的形式,只要它们以适当的语法编码。
用户按下一个按钮来计算公式。计算结果显示在屏幕上。下面是公式的另一个示例:AVERAGE(SUM(1,2),4)。此公式应按如下方式计算:
SUM(1,2)函数首先求值,返回值为3。AVERAGE(3,4)函数(也就是最终输出)接着求值,返回值为3.5。到目前为止,我已经能够创建基本的计算函数,如sum和min,但我在使用嵌套函数时遇到了麻烦。我将非常感谢任何人提供的帮助或指导。
先谢谢你!
以下是我所做的几种不同尝试之一;
function sum(...args) {
return args.reduce((acc, arg) => {
if (isNaN(arg)) {
return acc;
}
return acc + arg;
}, 0);
}
function min(...args) {
return Math.min(...args);
}
function avg(...args) {
if (args.length === 1 && typeof args[0] === 'number') {
return args[0];
}
return sum(...args) / args.length;
}
function evaluate(formula) {
let match = /^(\w+)\((.*)\)$/.exec(formula);
if (!match) {
return parseFloat(formula);
}
let [, func, argsStr] = match;
let args = argsStr.split(',').map(arg => evaluate(arg.trim()));
switch (func) {
case 'SUM':
return sum(...args);
case 'MIN':
return min(...args);
case 'AVERAGE':
return avg(...args);
default:
return NaN;
}
}
let formulaInput = document.getElementById('formula');
let evalButton = document.getElementById('eval-btn');
let result = document.getElementById('result');
evalButton.addEventListener('click', () => {
let formula = formulaInput.value;
result.innerHTML = evaluate(formula);
});
我已经尝试了各种方法,到目前为止,我已经发现这种方法取得了一些成功,但我不认为这是最好的方法,例如,如果我不包括"if(isNaN(arg))"或其他一些变体,在控制台中我会得到:{Array(3):0:NaN 1:3 2:3}作为第一个参数,当尝试创建类似以下的复杂公式时:SUM(平均值(1,3),3),输出为NaN。
2条答案
按热度按时间avwztpqn1#
正如在评论中指出的,你需要一个合适的语言解析器,好消息是,你可以使用解析器生成器,而不是手工编写解析器,一个好的解析器生成器是PEG.js,它的语法可以是这样的:
您可以在https://pegjs.org/online上试用它,然后只需单击“download parser”,您就准备好了。
此语法将输入转换为所谓的s表达式,即
[operator-or-function arg1 arg2 etc]
之类的嵌套数组。将被解析为:
评估这个应该不是问题。
fjaof16o2#
您可以用最嵌套函数中的值从里到外替换字符串。