Skip to content
Snippets Groups Projects
calc.cpp 1.36 KiB
Newer Older
Jacek Galowicz's avatar
Jacek Galowicz committed
#include "calc.hpp"

#include <stack>
#include <stdexcept>
Malte Harms's avatar
Malte Harms committed
#include <cmath>
Jacek Galowicz's avatar
Jacek Galowicz committed

int plus(    int a, int b) { return a + b; }
int minus(   int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
Malte Harms's avatar
Malte Harms committed
int power(   int a, int b) { return std::pow(a, b); }
Christian Wunder's avatar
Christian Wunder committed
int modulo(  int a, int b) { 
  if(b == 0) {
    throw std::domain_error("Modulo by 0 not defined.");
  }
  return a % b;
}
int divide(  int a, int b) { 
  if(b == 0) {
    throw std::domain_error("Division by 0.");
  }
  return a / b;
}
Jacek Galowicz's avatar
Jacek Galowicz committed

int pop_stack(auto &stack) {
  const auto ret{stack.top()};
  stack.pop();
  return ret;
}

void change_stack_state(auto &operation, auto &stack) {
  const auto op_b{pop_stack(stack)};
  const auto op_a{pop_stack(stack)};
  stack.push(operation(op_a, op_b));
}

int evaluate(const std::string &s) {
  std::stack<int> stack;

  for (const char c : s) {
    switch (c) {
    case '+': change_stack_state(plus,     stack); break;
    case '-': change_stack_state(minus,    stack); break;
    case '*': change_stack_state(multiply, stack); break;
    case '/': change_stack_state(divide,   stack); break;
Malte Harms's avatar
Malte Harms committed
    case '^': change_stack_state(power,    stack); break;
    case '%': change_stack_state(modulo,   stack); break;
Jacek Galowicz's avatar
Jacek Galowicz committed
    case '0'...'9': stack.push(c - '0'); break;
Meik Selig's avatar
Meik Selig committed
      throw std::invalid_argument( "received unrecognized character" );
Jacek Galowicz's avatar
Jacek Galowicz committed
    }
  }

  return {stack.top()};
}