(expression: string)
| 5 | // |
| 6 | // Then it evaluates the RPN stack and returns the output. |
| 7 | export function evalMath(expression: string): number { |
| 8 | // Stack where operators & numbers are stored in RPN. |
| 9 | const rpnStack: string[] = []; |
| 10 | // The working stack where new tokens are pushed. |
| 11 | const workingStack: string[] = []; |
| 12 | |
| 13 | let lastToken: string | undefined; |
| 14 | // Iterate over the expression. |
| 15 | for (let i = 0, len = expression.length; i < len; i++) { |
| 16 | const token = expression[i]; |
| 17 | |
| 18 | // Skip if the token is empty or a whitespace. |
| 19 | if (!token || token === ' ') { |
| 20 | continue; |
| 21 | } |
| 22 | |
| 23 | // Is the token a operator? |
| 24 | if (operators.has(token)) { |
| 25 | const op = operators.get(token); |
| 26 | |
| 27 | // Go trough the workingstack and determine it's place in the workingStack |
| 28 | while (workingStack.length) { |
| 29 | const currentOp = operators.get(workingStack[0]); |
| 30 | if (!currentOp) { |
| 31 | break; |
| 32 | } |
| 33 | |
| 34 | // Is the current operation equal or less than the current operation? |
| 35 | // Then move that operation to the rpnStack. |
| 36 | if (op!.lessOrEqualThan(currentOp)) { |
| 37 | rpnStack.push(workingStack.shift()!); |
| 38 | } else { |
| 39 | break; |
| 40 | } |
| 41 | } |
| 42 | // Add the operation to the workingStack. |
| 43 | workingStack.unshift(token); |
| 44 | // Otherwise was the last token a operator? |
| 45 | } else if (!lastToken || operators.has(lastToken)) { |
| 46 | rpnStack.push(token); |
| 47 | // Otherwise just append the result to the last token(e.g. multiple digits numbers). |
| 48 | } else { |
| 49 | rpnStack[rpnStack.length - 1] += token; |
| 50 | } |
| 51 | // Set the last token. |
| 52 | lastToken = token; |
| 53 | } |
| 54 | |
| 55 | // Push the working stack on top of the rpnStack. |
| 56 | rpnStack.push(...workingStack); |
| 57 | |
| 58 | // Now evaluate the rpnStack. |
| 59 | const stack: number[] = []; |
| 60 | for (let i = 0, len = rpnStack.length; i < len; i++) { |
| 61 | const op = operators.get(rpnStack[i]); |
| 62 | if (op) { |
| 63 | // Get the arguments of for the operation(first two in the stack). |
| 64 | const args = stack.splice(0, 2); |
no test coverage detected