SOURCE

//词法解析部分
let token = [];
let tokens = []
const start = (char) => {
    if (char === '1' || char === '2' || char === '3' || char === '4' || char === '5' || char === '6' || char === '7' || char === '8' || char === '9' || char === '0' || char === ".") {
        token.push(char)
        return inNumner
    }
    if (char === '-' || char === '+') {
        if (tokens[tokens.length - 1].type === "+" || tokens[tokens.length - 1].type === "-" || tokens[tokens.length - 1].type === "*" || tokens[tokens.length - 1].type === "-") {
            token.push(char)
            return inNumner
        }

    }

    if (char === '+' || char === '-' || char === '*' || char === '/') {
        emmitToken(char, char);
        return start
    }
    if (char === '(' || char === ')') {
        emmitToken(char, char);
        return start
    }
    if (char === ' ') {
        return start;
    }
    if (char === '\r' || char === '\n') {
        return start;
    }
    return emmitToken(char, char)

}
const inNumner = (char) => {
    //引入负数,判断上一个是不是

    if (char === '1' || char === '2' || char === '3' || char === '4' || char === '5' || char === '6' || char === '7' || char === '8' || char === '9' || char === '0' || char === ".") {
        token.push(char)
        return inNumner
    } else if (char === '-' || char === '+') {
        if (tokens[tokens.length - 1].type === "+" || tokens[tokens.length - 1].type === "-" || tokens[tokens.length - 1].type === "*" || tokens[tokens.length - 1].type === "-") {
            token.push(char)
            return inNumner
        }

    } else {
        emmitToken("Number", token.join(""));
        token = [];
        return start(char);
    }
}
function emmitToken(type, value) {
    tokens.push({ type, value });
}

//语法解析部分
function Expression(source) {
    if (source[0].type === "AdditiveExpression" && source[1] && source[1].type === "EOF") {
        let node = {
            type: "Expression",
            children: [source.shift(), source.shift()]
        }
        source.unshift(node);
        return node;
    }
    AdditiveExpression(source);
    return Expression(source);
}
function AdditiveExpression(source) {

    if (source[0].type === "MultiplicativeExpression") {
        let node = {
            type: "AdditiveExpression",
            children: [source[0]]
        }
        source[0] = node;
        return AdditiveExpression(source);
    }


    if (source[0].type === "AdditiveExpression" && source[1] && source[1].type === "+") {
        let node = {
            type: "AdditiveExpression",
            operator: "+",
            children: []
        }
        node.children.push(source.shift());
        node.children.push(source.shift());
        MultiplicativeExpression(source);
        node.children.push(source.shift());
        source.unshift(node);
        return AdditiveExpression(source);
    }
    if (source[0].type === "AdditiveExpression" && source[1] && source[1].type === "-") {
        let node = {
            type: "AdditiveExpression",
            operator: "-",
            children: []
        }
        node.children.push(source.shift());
        node.children.push(source.shift());
        MultiplicativeExpression(source);
        node.children.push(source.shift());
        source.unshift(node);
        return AdditiveExpression(source);
    }
    if (source[0].type === "AdditiveExpression")
        return source[0];
    MultiplicativeExpression(source);
    return AdditiveExpression(source);
}





function MultiplicativeExpression(source) {
    if (source[0].type === "Number") {
        let node = {
            type: "MultiplicativeExpression",
            children: [source[0]]
        }
        source[0] = node;
        return MultiplicativeExpression(source);
    }
    if (source[0].type === "(") {
        let addExpr = [];
        let i = 0;
        while (i++ < source.length && source[i].type !== ")") {
            addExpr.push(source[i]);
        }

        source.splice(0, addExpr.length + 2, AdditiveExpression(addExpr));

        source[0].type = "AdditiveExpression";
        return AdditiveExpression(source);
    }
    if (source[2] && source[2].type === "(") {
        let addExpr = [];
        let i = 2;
        while (i++ < source.length && source[i].type !== ")") {
            addExpr.push(source[i]);
        }

        source.splice(2, addExpr.length + 2, AdditiveExpression([...addExpr]));
        source[2].type = "AdditiveExpression";

        return AdditiveExpression(source);
    }

    if (source[0].type === "MultiplicativeExpression" && source[1] && source[1].type === "*") {
        let node = {
            type: "MultiplicativeExpression",
            operator: "*",
            children: []
        }
        node.children.push(source.shift());
        node.children.push(source.shift());
        node.children.push(source.shift());
        source.unshift(node);
        return MultiplicativeExpression(source);
    }
    if (source[0].type === "MultiplicativeExpression" && source[1] && source[1].type === "/") {
        let node = {
            type: "MultiplicativeExpression",
            operator: "/",
            children: []
        }
        node.children.push(source.shift());
        node.children.push(source.shift());
        node.children.push(source.shift());
        source.unshift(node);
        return MultiplicativeExpression(source);
    }


    if (source[0].type === "MultiplicativeExpression")
        return;

    return MultiplicativeExpression(source);
};

function evaluate(node) {
    if (node.type === "Expression") {
        return evaluate(node.children[0])
    }
    if (node.type === "AdditiveExpression") {
        if (node.operator === '-') {
            return evaluate(node.children[0]) - evaluate(node.children[2]);
        }
        if (node.operator === '+') {
            return evaluate(node.children[0]) + evaluate(node.children[2]);
        }
        return evaluate(node.children[0])
    }
    if (node.type === "MultiplicativeExpression") {
        if (node.operator === '*') {
            return evaluate(node.children[0]) * evaluate(node.children[2]);
        }
        if (node.operator === '/') {
            return evaluate(node.children[0]) / evaluate(node.children[2]);
        }
        return evaluate(node.children[0])
    }
    if (node.type === "Number") {
        return Number(node.value);
    }
}

var input = "(4 - 1 * 4 -2) + (3 * 2) - 3";
var state = start;
for (var c of input.split('')) {
    state = state(c);
}

state('EOF');
var ast = Expression(tokens);
console.log(evaluate(ast))
console 命令行工具 X clear

                    
>
console