#ifndef LIBWCCL_OPS_CONDITIONAL_H #define LIBWCCL_OPS_CONDITIONAL_H #include <boost/mpl/list.hpp> #include <boost/mpl/count.hpp> #include <sstream> #include <boost/format.hpp> #include <libwccl/ops/predicate.h> #include <libwccl/ops/constant.h> #include <libwccl/ops/formatters.h> namespace Wccl { /** * Template class for conditional operators, returning value * depending on evaluation of some predicate. * This class is targeted towards if..then..else expression */ template<class T> class Conditional : public Function<T> { public: typedef boost::shared_ptr<Function<T> > ArgFunctionPtr; typedef boost::shared_ptr<Function<Bool> > BoolFunctionPtr; Conditional( const BoolFunctionPtr& cond_expr, const ArgFunctionPtr& iftrue_expr, const ArgFunctionPtr& iffalse_expr = Default()) : cond_expr_(cond_expr), iftrue_expr_(iftrue_expr), iffalse_expr_(iffalse_expr) { BOOST_ASSERT(cond_expr_); BOOST_ASSERT(iftrue_expr_); BOOST_ASSERT(iffalse_expr_); } /** * String representation of conditional operator in form of: * "if cond_expr_string then iftrue_expr_string else iffalse_expr_string" */ virtual std::string to_string(const Corpus2::Tagset& tagset) const; /** * String representation of conditional operator in form of: * "if cond_expr_raw_s then iftrue_expr_raw_s else iffalse_expr_raw_s" * This version does not require tagset, but may be inclomplete * and/or contain internal info. */ virtual std::string to_raw_string() const; virtual const std::string raw_operator_name() const { return "if"; } protected: const BoolFunctionPtr cond_expr_; const ArgFunctionPtr iftrue_expr_; const ArgFunctionPtr iffalse_expr_; static const ArgFunctionPtr& Default() { static ArgFunctionPtr x(new Constant<T>(T())); return x; } typedef FunctionBase::BaseRetValPtr BaseRetValPtr; /** * Evaluate the predicate. If it is true, evaluate and return value of * iftrue_expression. If predicate is false, evalute and return value * of iffalse_expression. */ virtual BaseRetValPtr apply_internal(const FunExecContext& context) const { if(this->cond_expr_->apply(context)->get_value()) { return iftrue_expr_->apply(context); } return iffalse_expr_->apply(context); } }; /** * Template class for conditional operator targeted * towards the operator "? if_true_value ? predicate" * Difference between base Conditional<T> is that * the if_false_value is always default, * and string representation is different. */ template<class T> class ConditionalOp : public Conditional<T> { public: typedef typename Conditional<T>::ArgFunctionPtr ArgFunctionPtr; typedef boost::shared_ptr<Function<Bool> > BoolFunctionPtr; ConditionalOp( const BoolFunctionPtr& cond_expr, const ArgFunctionPtr& iftrue_expr) : Conditional<T>(cond_expr, iftrue_expr) { } /** * String representation of conditional operator in form of: * "? if_true_expr_string ? cond_expr_string" */ virtual std::string to_string(const Corpus2::Tagset& tagset) const; /** * String representation of conditional operator in form of: * "? if_true_expr_raw_string ? cond_expr_raw_string" * This version does not require tagset, but may be inclomplete * and/or contain internal info. */ virtual std::string to_raw_string() const; virtual const std::string raw_operator_name() const { return "?"; } }; template<class T> std::string Conditional<T>::to_raw_string() const { std::stringstream ss; ss << boost::format("%1%(%2%, %3%, %4%)") % this->raw_operator_name() % this->cond_expr_->to_raw_string() % this->iftrue_expr_->to_raw_string() % this->iffalse_expr_->to_raw_string(); return ss.str(); } template<class T> std::string Conditional<T>::to_string(const Corpus2::Tagset &tagset) const { std::stringstream ss; ss << boost::format("%1%(%2%, %3%, %4%)") % this->operator_name(tagset) % this->cond_expr_->to_string(tagset) % this->iftrue_expr_->to_string(tagset) % this->iffalse_expr_->to_string(tagset); return ss.str(); } template<class T> std::string ConditionalOp<T>::to_raw_string() const { std::stringstream ss; ss << boost::format("%1% %2% ? %3%") % this->raw_operator_name() % this->iftrue_expr_->to_raw_string() % this->cond_expr_->to_raw_string(); return ss.str(); } template<class T> std::string ConditionalOp<T>::to_string(const Corpus2::Tagset &tagset) const { std::stringstream ss; ss << boost::format("%1% %2% ? %3%") % this->operator_name(tagset) % this->iftrue_expr_->to_string(tagset) % this->cond_expr_->to_string(tagset); return ss.str(); } } /* end ns Wccl */ #endif // LIBWCCL_OPS_CONDITIONAL_H