Esempio n. 1
0
// Consume operators with precedence >= than op then add op
void rpnBuilder::handle_op(const std::string& op) {
  // "Convert" unary operators into binary, so they can
  // be treated as if they were the same:
  handle_unary(op);

  // Check if operator exists:
  if (!opp.exists(op)) {
    cleanRPN(&(rpn));
    throw std::domain_error("Undefined operator: `" + op + "`!");
  }

  // Let p(o) denote the precedence of an operator o.
  //
  // If the token is an operator, o1, then
  //   While there is an operator token, o2, at the top
  //       and p(o1) >= p(o2), then (`>` for Right to Left associativity)
  //     pop o2 off the stack onto the output queue.
  //   Push o1 on the stack.

  // If it associates from left to right:
  if (opp.assoc(op) == 0) {
    while (!opStack.empty() && opp.prec(op) >= opp.prec(opStack.top())) {
      rpn.push(new Token<std::string>(opStack.top(), OP));
      opStack.pop();
    }
  } else {
    while (!opStack.empty() && opp.prec(op) > opp.prec(opStack.top())) {
      rpn.push(new Token<std::string>(opStack.top(), OP));
      opStack.pop();
    }
  }
  opStack.push(op);

  lastTokenWasOp = op[0];
}
double calculator::calculate(const char* expr,
    std::map<std::string, double>* vars) {

  // Convert to RPN with Dijkstra's Shunting-yard algorithm.
  TokenQueue_t rpn = toRPN(expr, vars);

  double ret = calculate(rpn);

  cleanRPN(rpn);

  return ret;
}
Esempio n. 3
0
// Check for unary operators and "convert" them to binary:
void rpnBuilder::handle_unary(const std::string& op) {
  if (this->lastTokenWasOp) {
    // Convert unary operators to binary in the RPN.
    if (!op.compare("-") || !op.compare("+")) {
      this->rpn.push(new Token<int64_t>(0, INT));
      this->lastTokenWasUnary = true;
    } else {
      cleanRPN(&(this->rpn));
      throw std::domain_error("Unrecognized unary operator: '" + op + "'.");
    }
  } else {
    this->lastTokenWasUnary = false;
  }
}