Skip to content
Snippets Groups Projects
conditional.h 4.47 KiB
Newer Older
#ifndef LIBWCCL_OPS_FUNCTIONS_CONDITIONAL_H
#define LIBWCCL_OPS_FUNCTIONS_CONDITIONAL_H
#include <sstream>
#include <boost/format.hpp>

#include <libwccl/ops/functions/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<const Function<T> > ArgFunctionPtr;
	typedef boost::shared_ptr<const 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, iftrue_expr_string, iffalse_expr_string)"
	std::string to_string(const Corpus2::Tagset& tagset) const;

	/**
	 * String representation of conditional operator in form of:
	 * "if(cond_expr_raw_s, iftrue_expr_raw_s, iffalse_expr_raw_s)"
	 * This version does not require tagset, but may be inclomplete
	 * and/or contain internal info.
	 */
	std::string to_raw_string() const;
	/**
	 * @returns Name of the function: "if"
	 */
	std::string raw_name() const {
		return "if";
	}

protected:
	const BoolFunctionPtr cond_expr_;
	const ArgFunctionPtr iftrue_expr_;
	const ArgFunctionPtr iffalse_expr_;

	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.
	 */
	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);
	}
private:
	static const ArgFunctionPtr Default() {
		return detail::DefaultFunction<T>();
	}
};

/**
 * 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 typename Conditional<T>::BoolFunctionPtr BoolFunctionPtr;

	ConditionalOp(
		const BoolFunctionPtr& cond_expr,
		const ArgFunctionPtr& iftrue_expr)
		: Conditional<T>(cond_expr, iftrue_expr)
	{
	}

	/**
	 * @returns String representation of conditional operator in form of:
	 * "? if_true_expr_string ? cond_expr_string"
	 */
	std::string to_string(const Corpus2::Tagset& tagset) const;
	 * @returns String representation of conditional operator in form of:
	 * "? if_true_expr_raw_string ? cond_expr_raw_string"
	 * @note This version does not require tagset, but may be inclomplete
	std::string to_raw_string() const;
	/**
	 * @returns Name of the function: "?".
	 */
	std::string raw_name() const {
template<class T>
std::string Conditional<T>::to_raw_string() const
{
	std::stringstream ss;
	ss << boost::format("%1%(%2%, %3%, %4%)")
			% 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->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->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->iftrue_expr_->to_string(tagset)
			% this->cond_expr_->to_string(tagset);
	return ss.str();
}
#endif // LIBWCCL_OPS_FUNCTIONS_CONDITIONAL_H