Exemple #1
0
packToken calculator::eval(TokenMap vars, bool keep_refs) const {
  TokenBase* value = calculate(this->RPN, vars, opMap());
  packToken p = packToken(value->clone());
  if (keep_refs) {
    return packToken(value);
  } else {
    return packToken(resolve_reference(value));
  }
}
Exemple #2
0
void TokenMap::assign(std::string key, TokenBase* value) {
  if (value) {
    value = value->clone();
  } else {
    throw std::invalid_argument("TokenMap assignment expected a non NULL argument as value!");
  }

  packToken* variable = find(key);

  if (variable) {
    (*variable) = packToken(value);
  } else {
    map()[key] = packToken(value);
  }
}
packToken lazy_class_init(packMap scope) {
  packMap _this = scope->find("this")->asMap();
  (*_this)["func"] = packToken(scope->find("func")->asFunc()->clone());
  (*_this)["args"] = scope->find("arglist")->asList();

  return packToken::None;
}
Exemple #4
0
packToken calculator::calculate(const char* expr, TokenMap vars,
                                const char* delim, const char** rest) {
  // Convert to RPN with Dijkstra's Shunting-yard algorithm.
  RAII_TokenQueue_t rpn = calculator::toRPN(expr, vars, delim, rest);

  TokenBase* ret = calculator::calculate(rpn, vars);

  return packToken(resolve_reference(ret));
}
Exemple #5
0
packToken* TokenMap::MapIterator::next() {
  if (it != map.end()) {
    last = packToken(it->first);
    ++it;
    return &last;
  } else {
    it = map.begin();
    return NULL;
  }
}
Exemple #6
0
std::string calculator::str(TokenQueue_t rpn) {
  std::stringstream ss;

  ss << "calculator { RPN: [ ";
  while (rpn.size()) {
    ss << packToken(resolve_reference(rpn.front()->clone())).str();
    rpn.pop();

    ss << (rpn.size() ? ", ":"");
  }
  ss << " ] }";
  return ss.str();
}
Exemple #7
0
void TokenMap::insert(std::string key, TokenBase* value) {
  (*this)[key] = packToken(value->clone());
}
Exemple #8
0
TokenBase* calculator::calculate(const TokenQueue_t& rpn, TokenMap scope,
                                 const opMap_t& opMap) {
  evaluationData data(rpn, scope, opMap);

  // Evaluate the expression in RPN form.
  std::stack<TokenBase*> evaluation;
  while (!data.rpn.empty()) {
    TokenBase* base = data.rpn.front()->clone();
    data.rpn.pop();

    // Operator:
    if (base->type == OP) {
      data.op = static_cast<Token<std::string>*>(base)->val;
      delete base;

      /* * * * * Resolve operands Values and References: * * * * */

      if (evaluation.size() < 2) {
        cleanStack(evaluation);
        throw std::domain_error("Invalid equation.");
      }
      TokenBase* b_right = evaluation.top(); evaluation.pop();
      TokenBase* b_left  = evaluation.top(); evaluation.pop();

      if (b_right->type == VAR) {
        std::string var_name = static_cast<Token<std::string>*>(b_right)->val;
        delete b_right;
        delete resolve_reference(b_left);
        cleanStack(evaluation);
        throw std::domain_error("Unable to find the variable '" + var_name + "'.");
      } else {
        b_right = resolve_reference(b_right, &data.scope);
      }

      packToken r_left;
      packToken m_left;
      if (b_left->type & REF) {
        RefToken* left = static_cast<RefToken*>(b_left);
        r_left = left->key;
        m_left = left->source;
        b_left = resolve_reference(left, &data.scope);
      } else if (b_left->type == VAR) {
        r_left = static_cast<Token<std::string>*>(b_left)->val;
      }

      /* * * * * Resolve Asign Operation * * * * */

      if (!data.op.compare("=")) {
        delete b_left;

        // If the left operand has a variable name:
        if (r_left->type == STR) {
          if (m_left->type == MAP) {
            TokenMap& map = m_left.asMap();
            std::string& key = r_left.asString();
            map[key] = packToken(b_right->clone());
          } else {
            TokenMap* map = data.scope.findMap(r_left.asString());
            if (!map || *map == TokenMap::default_global()) {
              // Assign on the local scope.
              // The user should not be able to implicitly overwrite
              // variables he did not declare, since it's error prone.
              data.scope[r_left.asString()] = packToken(b_right->clone());
            } else {
              (*map)[r_left.asString()] = packToken(b_right->clone());
            }
          }

          evaluation.push(b_right);
        // If the left operand has an index number:
        } else if (r_left->type & NUM) {
          if (m_left->type == LIST) {
            TokenList& list = m_left.asList();
            size_t index = r_left.asInt();
            list[index] = packToken(b_right->clone());
          } else {
            delete b_right;
            cleanStack(evaluation);
            throw std::domain_error("Left operand of assignment is not a list!");
          }

          evaluation.push(b_right);
        } else {
          packToken p_right(b_right->clone());
          delete b_right;

          cleanStack(evaluation);
          throw undefined_operation(data.op, r_left, p_right);
        }
      } else if (b_left->type == FUNC && data.op == "()") {
        Function* f_left = static_cast<Function*>(b_left);

        if (!data.op.compare("()")) {
          // Collect the parameter tuple:
          Tuple right;
          if (b_right->type == TUPLE) {
            right = *static_cast<Tuple*>(b_right);
          } else {
            right = Tuple(b_right);
          }
          delete b_right;

          packToken _this;
          if (m_left->type != NONE) {
            _this = m_left;
          } else {
            _this = data.scope;
          }

          // Execute the function:
          packToken ret;
          try {
            ret = Function::call(_this, f_left, &right, data.scope);
          } catch (...) {
            cleanStack(evaluation);
            delete f_left;
            throw;
          }

          delete f_left;

          evaluation.push(ret->clone());
        } else {
          packToken p_right(b_right->clone());
          packToken p_left(b_left->clone());
          delete b_right;

          cleanStack(evaluation);
          throw undefined_operation(data.op, p_left, p_right);
        }
      } else {
        data.opID = Operation::build_mask(b_left->type, b_right->type);
        packToken p_left(b_left);
        packToken p_right(b_right);
        TokenBase* result = 0;

        try {
          // Resolve the operation:
          result = exec_operation(p_left, p_right, &data, data.op);
          if (!result) {
            result = exec_operation(p_left, p_right, &data, ANY_OP);
          }
        } catch (...) {
          cleanStack(evaluation);
          throw;
        }

        if (result) {
          evaluation.push(result);
        } else {
          cleanStack(evaluation);
          throw undefined_operation(data.op, p_left, p_right);
        }
      }
    } else if (base->type == VAR) {  // Variable
      packToken* value = NULL;
      std::string key = static_cast<Token<std::string>*>(base)->val;

      value = data.scope.find(key);

      if (value) {
        TokenBase* copy = (*value)->clone();
        evaluation.push(new RefToken(key, copy));
        delete base;
      } else {
        evaluation.push(base);
      }
    } else {
      evaluation.push(base);
    }
  }

  return evaluation.top();
}