From 9b64d560bee0d5c703b10d0ae28731516a480a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Wardy=C5=84ski?= <no@email> Date: Tue, 9 Nov 2010 16:16:06 +0100 Subject: [PATCH] Conditional operators realised as if..then..else expression and operator "? val ? pred" with some tests for StrSet specialization --- libwccl/ops/conditional.h | 148 +++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + tests/conditional.cpp | 151 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 libwccl/ops/conditional.h create mode 100644 tests/conditional.cpp diff --git a/libwccl/ops/conditional.h b/libwccl/ops/conditional.h new file mode 100644 index 0000000..e17a020 --- /dev/null +++ b/libwccl/ops/conditional.h @@ -0,0 +1,148 @@ +#ifndef CONDITIONAL_H +#define CONDITIONAL_H + +#include <boost/shared_ptr.hpp> +#include <boost/mpl/list.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/count.hpp> +#include <libwccl/ops/predicate.h> +#include <libwccl/ops/formatters.h> +#include <libwccl/ops/constant.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 = ArgFunctionPtr(new Constant<T>(T()))) + : 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 { + std::string s(this->operator_name(tagset)); + s.append(" "); + s.append(cond_expr_->to_string(tagset)); + s.append(" then "); + s.append(iftrue_expr_->to_string(tagset)); + s.append(" else "); + s.append(iffalse_expr_->to_string(tagset)); + return s; + } + + /** + * 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 { + std::string s(this->raw_operator_name()); + s.append(" "); + s.append(cond_expr_->to_raw_string()); + s.append(" then "); + s.append(iftrue_expr_->to_raw_string()); + s.append(" else "); + s.append(iffalse_expr_->to_raw_string()); + return s; + } + + virtual const std::string raw_operator_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. + */ + virtual BaseRetValPtr apply_internal(const SentenceContext& 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 { + std::string s(this->operator_name(tagset)); + s.append(" "); + s.append(this->iftrue_expr_->to_string(tagset)); + s.append(" ? "); + s.append(this->cond_expr_->to_string(tagset)); + return s; + } + + /** + * 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 { + std::string s(this->raw_operator_name()); + s.append(" "); + s.append(this->iftrue_expr_->to_raw_string()); + s.append(" ? "); + s.append(this->cond_expr_->to_raw_string()); + return s; + } + + virtual const std::string raw_operator_name() const { + return "?"; + } +}; + + +} /* end ns Wccl */ + +#endif // CONDITIONAL_H diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 58d9f29..abc70b5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories( ${CMAKE_SOURCE_DIR} ) add_definitions(-DLIBWCCL_TEST_DATA_DIR="${PROJECT_SOURCE_DIR}/") add_executable(tests + conditional.cpp constant_tests.cpp context.cpp logicalpredicates.cpp diff --git a/tests/conditional.cpp b/tests/conditional.cpp new file mode 100644 index 0000000..6693301 --- /dev/null +++ b/tests/conditional.cpp @@ -0,0 +1,151 @@ +#include <boost/test/unit_test.hpp> +#include <boost/bind.hpp> +#include <boost/shared_ptr.hpp> +#include <libcorpus2/sentence.h> + +#include <libwccl/ops/constant.h> +#include <libwccl/ops/conditional.h> + +#include <libwccl/values/bool.h> +#include <libwccl/values/tset.h> +#include <libwccl/values/strset.h> + +#include <libwccl/sentencecontext.h> + +using namespace Wccl; + +BOOST_AUTO_TEST_SUITE(logical_predicates) + +struct CondFix +{ + CondFix() + : sc(boost::make_shared<Corpus2::Sentence>()), + tagset(), + true_value(true), + false_value(false), + true_constant(new Constant<Bool>(true_value)), + false_constant(new Constant<Bool>(false_value)) + { + } + SentenceContext sc; + Corpus2::Tagset tagset; + + Bool true_value; + Bool false_value; + Conditional<StrSet>::BoolFunctionPtr true_constant; + Conditional<StrSet>::BoolFunctionPtr false_constant; +}; + +struct CondFixStrSet : public CondFix +{ + CondFixStrSet() + : CondFix(), + iftrue_strset(), + iffalse_strset(), + empty_strset(), + one_elem_strset() + { + iftrue_strset.insert("I"); + iftrue_strset.insert("am"); + iftrue_strset.insert("True"); + iftrue_strset_expr = Conditional<StrSet>::ArgFunctionPtr(new Constant<StrSet>(iftrue_strset)); + iffalse_strset.insert("I"); + iffalse_strset.insert("am"); + iffalse_strset.insert("so"); + iffalse_strset.insert("False"); + iffalse_strset_expr = Conditional<StrSet>::ArgFunctionPtr(new Constant<StrSet>(iffalse_strset)); + one_elem_strset.insert("oNe"); + one_elem_strset_expr = Conditional<StrSet>::ArgFunctionPtr(new Constant<StrSet>(one_elem_strset)); + empty_strset_expr = Conditional<StrSet>::ArgFunctionPtr(new Constant<StrSet>(empty_strset)); + } + + StrSet iftrue_strset; + StrSet iffalse_strset; + StrSet empty_strset; + StrSet one_elem_strset; + Conditional<StrSet>::ArgFunctionPtr iftrue_strset_expr; + Conditional<StrSet>::ArgFunctionPtr iffalse_strset_expr; + Conditional<StrSet>::ArgFunctionPtr empty_strset_expr; + Conditional<StrSet>::ArgFunctionPtr one_elem_strset_expr; +}; + +BOOST_FIXTURE_TEST_CASE(true_condition_strset, CondFixStrSet) +{ + BOOST_CHECK(!iftrue_strset.equals(iffalse_strset)); + + boost::shared_ptr<Conditional<StrSet> > cond(new Conditional<StrSet>( + true_constant, + iftrue_strset_expr, + iffalse_strset_expr)); + + BOOST_CHECK(iftrue_strset.equals(*(cond->apply(sc)))); +} + +BOOST_FIXTURE_TEST_CASE(false_condition_strset, CondFixStrSet) +{ + boost::shared_ptr<Conditional<StrSet> > cond(new Conditional<StrSet>( + false_constant, + iftrue_strset_expr, + iffalse_strset_expr)); + + BOOST_CHECK(iffalse_strset.equals(*(cond->apply(sc)))); +} + +BOOST_FIXTURE_TEST_CASE(true_condition_op_strset, CondFixStrSet) +{ + boost::shared_ptr<ConditionalOp<StrSet> > cond(new ConditionalOp<StrSet>( + true_constant, + iftrue_strset_expr)); + + BOOST_CHECK(iftrue_strset.equals(*(cond->apply(sc)))); +} + +BOOST_FIXTURE_TEST_CASE(false_condition_op_strset, CondFixStrSet) +{ + boost::shared_ptr<ConditionalOp<StrSet> > cond(new ConditionalOp<StrSet>( + false_constant, + iftrue_strset_expr)); + + BOOST_CHECK(empty_strset.equals(*(cond->apply(sc)))); +} + +//------ to_string test cases ------- + +BOOST_FIXTURE_TEST_CASE(cond_to_string, CondFixStrSet) +{ + boost::shared_ptr<Conditional<StrSet> > cond(new Conditional<StrSet>( + true_constant, + empty_strset_expr, + one_elem_strset_expr)); + std::string expected = "if True then [] else [\"oNe\"]"; + BOOST_CHECK_EQUAL(expected, cond->to_string(tagset)); +} + +BOOST_FIXTURE_TEST_CASE(cond_to_string_raw, CondFixStrSet) +{ + boost::shared_ptr<Conditional<StrSet> > cond(new Conditional<StrSet>( + true_constant, + one_elem_strset_expr)); + std::string expected = "if True then [\"oNe\"] else []"; + BOOST_CHECK_EQUAL(expected, cond->to_string(tagset)); +} + +BOOST_FIXTURE_TEST_CASE(cond_op_to_string, CondFixStrSet) +{ + boost::shared_ptr<ConditionalOp<StrSet> > cond(new ConditionalOp<StrSet>( + true_constant, + empty_strset_expr)); + std::string expected = "? [] ? True"; + BOOST_CHECK_EQUAL(expected, cond->to_string(tagset)); +} + +BOOST_FIXTURE_TEST_CASE(cond_op_to_string_raw, CondFixStrSet) +{ + boost::shared_ptr<ConditionalOp<StrSet> > cond(new ConditionalOp<StrSet>( + false_constant, + one_elem_strset_expr)); + std::string expected = "? [\"oNe\"] ? False"; + BOOST_CHECK_EQUAL(expected, cond->to_string(tagset)); +} + +BOOST_AUTO_TEST_SUITE_END() -- GitLab