function readNumber(i, chars) {
let group = []
while(i < chars.length) {
const val = chars[i]
if(/(\d|\.)/.test(val)) {
group.push(val)
i += 1
} else {
break
}
}
return group.join('')
}
function readPlaceholder(i, chars) {
let group = []
while(i < chars.length) {
const val = chars[i]
if (val !== '}') {
group.push(val)
i += 1
} else {
group.push('}')
break
}
}
return group.join('')
}
function parse(exp) {
const chars = exp.split('')
const tokens = []
let i = 0;
while(i < chars.length) {
let char = chars[i]
if (/^\d$/.test(char)) {
const val = readNumber(i, chars)
i += val.length
tokens.push({
type: 'num',
value: Number(val)
})
} else if (char === '#') {
const val = readPlaceholder(i, chars)
i += val.length
tokens.push({
type: 'ph',
value: val
})
} else if (/[\+\-\*\/%\(\)]/.test(char)) {
i += 1
const priorityMap = {
'+': 1,
'-': 1,
'*': 2,
'/': 2,
'%': 2,
'(': 3,
')': 3
}
tokens.push({
type: 'op',
value: char,
priority: priorityMap[char]
})
} else {
i += 1
}
}
return tokens
}
function evalExp(exp) {
const tokens = parse(exp)
let results = []
const opStack = []
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i]
if (['ph', 'num'].includes(token.type)) {
results.push(token)
} else if (token.type === 'op') {
let topOp = opStack[opStack.length - 1]
if (!topOp || topOp.priority < token.priority) {
if (token.value !== ')') {
opStack.push(token)
} else {
while(topOp && topOp.value !== '(') {
results.push(topOp)
opStack.pop()
topOp = opStack[opStack.length - 1]
}
if (topOp) {
opStack.pop()
} else {
console.log('表达式不合法')
results = []
break
}
}
} else {
while(topOp && topOp.value !== '(' && topOp.priority >= token.priority) {
results.push(topOp)
opStack.pop()
topOp = opStack[opStack.length - 1]
}
opStack.push(token)
}
}
}
if (opStack.length) {
let topOp = opStack.pop()
while(topOp) {
results.push(topOp)
topOp = opStack.pop()
}
}
console.log('===results', results.map(i => i.value))
let numStack = []
for (let i = 0; i < results.length; i++) {
const token = results[i]
if (token.type === 'num') {
numStack.push(token.value)
} else {
const b = numStack.pop()
const a = numStack.pop()
if (a != null && b != null) {
if (token.value === '+') {
numStack.push(a + b)
} else if (token.value === '-') {
numStack.push(a - b)
} else if (token.value === '*') {
numStack.push(a * b)
} else if (token.value === '/') {
if (!b) {
numStack = []
break
} else {
numStack.push(a / b)
}
} else if (token.type === '%') {
number.push(a % b)
}
}
}
}
if (numStack.length !== 1) {
console.log('====numStack', numStack)
return ''
}
return numStack[0]
}
console.log(evalExp('107.5 * (3 * 4 + 3)'))
console