表达式解析

发布时间 2023-12-28 09:05:53作者: 名字不好起啊

本来可以很简单的事情,放到了  OpenHarmony  上实现,就变得不简单了。。。

实现表达式解析,我们可以用 eval,可以用 new Function,但是! OpenHarmony  都不让用

 

先写个四则运算解析:

1、加入表达式为(每一个 @ 代表一个变量的引用):@num1+@num2-@num3*@num4/@num5

2、使用正则将变量替换成: 1+2-3*4/5

3、然后根据符号分割表达式(operators数组每个符号下标都对应着 nums 对应 sub  和 sub+1 的运算):

  nums: [ 1, 2, 3, 4, 5]

  operators: [ '+', '-', '*', '/' ]

4、循环符号数组(注意优先 * / 的计算),每执行1次,移除一个符号,并将结果压入 nums,当符号数组为空,则 nums 最后的一个元素即为结果~

 

代码:

function analyseArithmeticExpression(expression) {
    let operators = /[\+\-\*\/]/g;
    let matchArr = expression.match(operators);
    console.log(expression.match(operators));
    let nums = [];
    operators = [];
    let str = expression;
    matchArr.forEach((item, index) => {
        let sub = str.indexOf(item);
        let temp = str.substr(0, sub);
        nums.push(Number(temp[0]));
        operators.push(item);
        str = str.substr(sub + 1, str.length);
        if (index === matchArr.length - 1) {
            nums.push(Number(str));
        }
    });
    let currentOperatorsLength = operators.length;
    while (operators.length) {
        let sub = 0;
        // 优先执行 * /
        let rideSub = operators.indexOf('*');
        let divisionSub = operators.indexOf('/');
        if (rideSub > -1 && divisionSub > -1) {
            sub = Math.min(rideSub, divisionSub);
        } else if (rideSub > -1) {
            sub = rideSub;
        } else if (divisionSub > -1) {
            sub = divisionSub;
        }
        // 记录长度
        currentOperatorsLength = operators.length;
        // 执行运算
        doArithmetic(nums, operators, sub);
        if (currentOperatorsLength === operators.length) {
           // 必 -1,如果没操作,则跳出
           break;
        }
    }
    return nums[0];
}


function doArithmetic(nums, operators, sub) {
    let operator = operators[sub];
    // 当前 数 与 下一个数 运算
    let num = 0;
    switch (operator) {
        case '+':
            num = nums[sub] + nums[sub + 1];
            break;
        case '-':
            num = nums[sub] - nums[sub + 1];
            break;
        case '*':
            num = nums[sub] * nums[sub + 1];
            break;
        case '/':
            num = nums[sub] / nums[sub + 1];
            break;
    }
    // 更新当前数,移除运算后的数,移除运算后的符号
    nums[sub] = num;
    nums.splice(sub + 1, 1);
    operators.splice(sub, 1);
}