UNPKG

math-expression-evaluator

Version:
99 lines (97 loc) 3.01 kB
import { toPostfix } from './postfix' import { tokenTypes, ParsedToken } from './token' export type Constants = Record<string, number> export function postfixEval(arr: ReturnType<typeof toPostfix>, Constants?: Constants) { Constants = Constants || {} Constants.PI = Math.PI Constants.E = Math.E type Item = { value: any type: tokenTypes } var stack: (Item | ParsedToken[])[] = [], pop1: Item | undefined | ParsedToken[], pop2: Item | undefined | ParsedToken[], pop3: Item | undefined | ParsedToken[] var isRunningUnderSigmaOrPi = typeof Constants.n !== 'undefined' for (var i = 0; i < arr.length; i++) { if (arr[i].type === 1) { stack.push({ value: arr[i].value, type: 1 }) } else if (arr[i].type === 3) { stack.push({ value: Constants[arr[i].value], type: 1 }) } else if (arr[i].type === 0) { const top = stack[stack.length - 1] if (Array.isArray(top)) { top.push(arr[i]) } else top.value = arr[i].value(top.value) } else if (arr[i].type === 7) { const top = stack[stack.length - 1] if (Array.isArray(top)) { top.push(arr[i]) } else top.value = arr[i].value(top.value) } else if (arr[i].type === 8) { var popped = [] // @ts-ignore for (var x = 0; x < arr[i].numberOfArguments; x++) { const p = stack.pop() // @ts-ignore if (p) popped.push(p.value) } stack.push({ type: 1, value: arr[i].value.apply(arr[i], popped.reverse()) }) } else if (arr[i].type === 10) { pop1 = stack.pop() pop2 = stack.pop() if (Array.isArray(pop2)) { // @ts-ignore pop2 = pop2.concat(pop1) pop2.push(arr[i]) stack.push(pop2) } else if (Array.isArray(pop1)) { // @ts-ignore pop1.unshift(pop2) pop1.push(arr[i]) stack.push(pop1) } else { // @ts-ignore stack.push({ type: 1, value: arr[i].value(pop2.value, pop1.value) }) } } else if (arr[i].type === 2 || arr[i].type === 9) { pop1 = stack.pop() pop2 = stack.pop() if (Array.isArray(pop2)) { //@ts-ignore pop2 = pop2.concat(pop1) pop2.push(arr[i]) stack.push(pop2) } else if (Array.isArray(pop1)) { //@ts-ignore pop1.unshift(pop2) pop1.push(arr[i]) stack.push(pop1) } else { // @ts-ignore stack.push({ type: 1, value: arr[i].value(pop2.value, pop1.value) }) } } else if (arr[i].type === 12) { pop1 = stack.pop() let pop: Item[] if (!Array.isArray(pop1) && pop1) { pop = [pop1] } else if (pop1) pop = pop1 else pop = [] pop2 = stack.pop() pop3 = stack.pop() // @ts-ignore stack.push({ type: 1, value: arr[i].value(pop3.value, pop2.value, pop) }) } else if (arr[i].type === 13) { if (isRunningUnderSigmaOrPi) { stack.push({ value: Constants[arr[i].value], type: 3 }) } else stack.push([arr[i]]) } } if (stack.length > 1) { throw new Error('Uncaught Syntax error') } // @ts-ignore return parseFloat(stack[0].value.toFixed(15)) }