ExprValue Expression::getPropertyValue(const std::string& propertyName) { auto callback = properties_.find(propertyName); if (callback == properties_.end()) { throw EvaluateException(str(boost::format("Property callback not set for property '%s'") % propertyName)); } return callback->second(); }
void OpApply::Apply(Expression *expression, Calculator *calculator, int32 recursions) { if(expression->LeafCount() != 2) throw EvaluateException("Apply expects 2 operands."); // If second operand is Atom, return that Atom. Otherwise replace head of second operand // by first operand. if(!expression->Leaf(1)->IsAtom()) { delete expression->Leaf(1)->Head(); expression->Leaf(1)->Head(expression->Leaf(0)); } expression->Leaves().erase(expression->Leaves().begin()); expression->AssignLeaf(0); expression->Evaluate(calculator, recursions); }
void OpMap::Apply(Expression *expression, Calculator *calculator, int32 recursions) { if(expression->LeafCount() != 2) throw EvaluateException("Map expects 2 operands."); Expression *head = expression->Leaf(0); Expression *list = expression->Leaf(1); for(ExprVector::iterator leaf = list->Leaves().begin(); leaf != list->Leaves().end(); ++leaf) { ExprPtr operation(new Expression()); operation->Head(head->Clone()); operation->AppendLeaf(*leaf); *leaf = operation.release(); } expression->AssignLeaf(1); expression->Evaluate(calculator, recursions); }
ExprValue Expression::calcTree(const ExprNodePtr& tree) { switch (tree->operationType) { case OP_VARIABLE: return getPropertyValue(boost::get<std::string>(tree->value)); case OP_VALUE: return tree->value; case OP_PLUS: try { return boost::get<ExprInteger>(calcTree(tree->left)) + boost::get<ExprInteger>(calcTree(tree->right)); } catch (boost::bad_get&) { throw EvaluateException("Invalid argument for operator '+'"); } case OP_MINUS: try { return boost::get<ExprInteger>(calcTree(tree->left)) - boost::get<ExprInteger>(calcTree(tree->right)); } catch (boost::bad_get&) { throw EvaluateException("Invalid argument for operator '-'"); } case OP_MULTIPLY: try { return boost::get<ExprInteger>(calcTree(tree->left)) * boost::get<ExprInteger>(calcTree(tree->right)); } catch (boost::bad_get&) { throw EvaluateException("Invalid argument for operator '*'"); } case OP_DIVIDE: try { return boost::get<ExprInteger>(calcTree(tree->left)) * boost::get<ExprInteger>(calcTree(tree->right)); } catch (boost::bad_get&) { throw EvaluateException("Invalid argument for operator '*'"); } case OP_CONTAINS: return operationContains(tree); case OP_LESS: case OP_LESSOREQUAL: case OP_GREATER: case OP_GREATEROREQUAL: return operationCompare(tree); case OP_EQUAL: return operationEquals(tree); case OP_NOTEQUAL: return operationNotEquals(tree); case OP_UMINUS: try { return -boost::get<ExprInteger>(calcTree(tree->left)); } catch (boost::bad_get&) { throw EvaluateException("Invalid argument for unary minus operator"); } case OP_NOT: return operationIsNot(tree); /*try { return !boost::get<bool>(calcTree(tree->left)); } catch (boost::bad_get&) { throw EvaluateException("Invalid argument for 'not' operator"); }*/ case OP_OR: case OP_AND: return operationLogical(tree); case OP_IS: return operationIs(tree); case OP_FUNCTIONCALL: { ExprValue left = calcTree(tree->left); return runtimeInfo_->callFunction(tree, left); } default: throw ParserException(str(boost::format("Unknown operation %d") % static_cast<int>(tree->operationType)), 0); } }
bool operator()(const T &, const U &) const { throw EvaluateException("Cannot compare different types"); }