| 100 | } |
| 101 | |
| 102 | func evalMathStack(opStack, valueStack *mathTreeStack) error { |
| 103 | topOp, err := opStack.pop() |
| 104 | if err != nil { |
| 105 | return errors.Errorf("Invalid Math expression") |
| 106 | } |
| 107 | switch { |
| 108 | case isUnary(topOp.Fn): |
| 109 | // Since "not" is a unary operator, just pop one value. |
| 110 | topVal, err := valueStack.pop() |
| 111 | if err != nil { |
| 112 | return errors.Errorf("Invalid math statement. Expected 1 operands") |
| 113 | } |
| 114 | if opStack.size() > 1 { |
| 115 | peek := opStack.peek().Fn |
| 116 | if (peek == "/" || peek == "%") && isZero(topOp.Fn, topVal.Const) { |
| 117 | return errors.Errorf("Division by zero") |
| 118 | } |
| 119 | } |
| 120 | topOp.Child = []*MathTree{topVal} |
| 121 | |
| 122 | case isTernary(topOp.Fn): |
| 123 | if valueStack.size() < 3 { |
| 124 | return errors.Errorf("Invalid Math expression. Expected 3 operands") |
| 125 | } |
| 126 | topVal1 := valueStack.popAssert() |
| 127 | topVal2 := valueStack.popAssert() |
| 128 | topVal3 := valueStack.popAssert() |
| 129 | topOp.Child = []*MathTree{topVal3, topVal2, topVal1} |
| 130 | |
| 131 | default: |
| 132 | if valueStack.size() < 2 { |
| 133 | return errors.Errorf("Invalid Math expression. Expected 2 operands") |
| 134 | } |
| 135 | if isZero(topOp.Fn, valueStack.peek().Const) { |
| 136 | return errors.Errorf("Division by zero.") |
| 137 | } |
| 138 | topVal1 := valueStack.popAssert() |
| 139 | topVal2 := valueStack.popAssert() |
| 140 | topOp.Child = []*MathTree{topVal2, topVal1} |
| 141 | |
| 142 | } |
| 143 | // Push the new value (tree) into the valueStack. |
| 144 | valueStack.push(topOp) |
| 145 | return nil |
| 146 | } |
| 147 | |
| 148 | func isMathFunc(f string) bool { |
| 149 | // While adding an op, also add it to the corresponding function type. |