//词法解析部分
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