diff --git a/libwccl/CMakeLists.txt b/libwccl/CMakeLists.txt index 8bbf14623039956534e0c130c0c9b1c4a24eeded..5ed26c712a614d56ed3d13ad962a7d64019c1adf 100644 --- a/libwccl/CMakeLists.txt +++ b/libwccl/CMakeLists.txt @@ -16,6 +16,7 @@ SET(libwccl_STAT_SRC sentencecontext.cpp values/bool.cpp values/position.cpp + values/positionref.cpp values/value.cpp variables.cpp ) diff --git a/libwccl/sentencecontext.cpp b/libwccl/sentencecontext.cpp index 591d89c5bb376c5aabd9ea458313aca2422bcfe5..68f9c6dad53fa4761f78109a76524161c50b590d 100644 --- a/libwccl/sentencecontext.cpp +++ b/libwccl/sentencecontext.cpp @@ -19,4 +19,25 @@ SentenceContext* SentenceContext::clone() const return new SentenceContext(duplicate()); } +int SentenceContext::get_abs_position(const Position &position) const +{ + return translate_special_position(position.get_value()); +} + +int SentenceContext::get_abs_position(const PositionRef &position) const +{ + int p = translate_special_position(position.get_base()->get_value()); + return p + position.get_offset(); +} + +int SentenceContext::get_rel_position(const Position &position) const +{ + return get_abs_position(position) - position_; +} + +int SentenceContext::get_rel_position(const PositionRef &position) const +{ + return get_abs_position(position) - position_; +} + } /* end ns Wccl */ diff --git a/libwccl/sentencecontext.h b/libwccl/sentencecontext.h index 1994db44f49401615bc439513b5eff11188941fd..3604c54a27a0de6a3cd92b17b8ae29b8e046b21e 100644 --- a/libwccl/sentencecontext.h +++ b/libwccl/sentencecontext.h @@ -2,6 +2,7 @@ #define LIBWCCL_SENTENCECONTEXT_H #include <libcorpus2/sentence.h> +#include <libwccl/values/positionref.h> #include <boost/shared_ptr.hpp> namespace Wccl { @@ -18,7 +19,7 @@ class SentenceContext { public: /// Constructor, wraps the Sentence and sets position to 0 - SentenceContext(const boost::shared_ptr<Corpus2::Sentence>& s); + explicit SentenceContext(const boost::shared_ptr<Corpus2::Sentence>& s); /// Returns a copy of this with a cloned underlyiong sentence SentenceContext duplicate() const; @@ -47,8 +48,13 @@ public: } /// Checks if the current position is valid (within the sentence bounds) - bool is_inside() const { - return position_ >= 0 && position_ < size(); + bool is_current_inside() const { + return is_inside(position_); + } + + /// Checks if the the given absolute position is valid (in sentence bounds) + bool is_inside(int abs_pos) const { + return abs_pos >= 0 && abs_pos < size(); } /// Position setter @@ -57,7 +63,7 @@ public: } /// Position advance shorthand - void position() { + void advance() { ++position_; } @@ -69,7 +75,7 @@ public: /// Token access convenience function - const. /// Will return NULL if the passed position is not valid in this Sentence const Corpus2::Token* at(int position) const { - if (is_inside()) { + if (is_current_inside()) { return get_sentence()[position]; } else { return NULL; @@ -79,7 +85,7 @@ public: /// Token access convenience function. /// Will return NULL if the passed position is not valid in this Sentence Corpus2::Token* at(int position) { - if (is_inside()) { + if (is_current_inside()) { return get_sentence()[position]; } else { return NULL; @@ -96,7 +102,28 @@ public: return at(position_); } + int get_abs_position(const Position& position) const; + + int get_abs_position(const PositionRef& position) const; + + int get_rel_position(const Position& position) const; + + int get_rel_position(const PositionRef& position) const; + + int translate_special_position(int pos) const { + switch (pos) { + case Position::Begin: + return 0; + case Position::End: + return sentence_->size() - 1; + case Position::Nowhere: + return Position::Nowhere; + default: + return position_ + pos; + } + } private: + /// The wrapped sentence boost::shared_ptr<Corpus2::Sentence> sentence_; diff --git a/libwccl/values/position.cpp b/libwccl/values/position.cpp index d422ccb4b0bbe81ce27d5e82593e8948b46ed4c5..329c65a8770132125d3b4be1335ded35ad6bee35 100644 --- a/libwccl/values/position.cpp +++ b/libwccl/values/position.cpp @@ -6,7 +6,16 @@ const char* Position::type_name = "Position"; std::string Position::to_raw_string() const { - return boost::lexical_cast<std::string>(val_); + switch (val_) { + case Nowhere: + return "nowhere"; + case Begin: + return "begin"; + case End: + return "end"; + default: + return boost::lexical_cast<std::string>(val_); + } } } /* end ns Wccl */ diff --git a/libwccl/values/position.h b/libwccl/values/position.h index ee7b05941c3e31adde3607c1cdb2e64c1e330d13..0b2148b436e01e4018b955a101d6dc5cb8cb3376 100644 --- a/libwccl/values/position.h +++ b/libwccl/values/position.h @@ -3,6 +3,7 @@ #include <libwccl/values/value.h> #include <cstdlib> +#include <boost/integer_traits.hpp> namespace Wccl { @@ -16,6 +17,10 @@ public: { } + static const int Nowhere = boost::integer_traits<int>::const_min; + static const int Begin = boost::integer_traits<int>::const_min + 1; + static const int End = boost::integer_traits<int>::const_max; + int get_value() const { return val_; } diff --git a/libwccl/values/positionref.cpp b/libwccl/values/positionref.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b790885ed3e8215d0cbbc366dc3c79830059a9c --- /dev/null +++ b/libwccl/values/positionref.cpp @@ -0,0 +1,19 @@ +#include <libwccl/values/positionref.h> +#include <sstream> + +namespace Wccl { + +const char* PositionRef::type_name = "PositionRef"; + +std::string PositionRef::to_raw_string() const +{ + std::stringstream ss; + ss << base_->get_value(); + if (offset_ >=0) { + ss << "+"; + } + ss << offset_; + return ss.str(); +} + +} /* end ns Wccl */ diff --git a/libwccl/values/positionref.h b/libwccl/values/positionref.h new file mode 100644 index 0000000000000000000000000000000000000000..dcb8667025e9bf558462c6a45a10adec8c821484 --- /dev/null +++ b/libwccl/values/positionref.h @@ -0,0 +1,48 @@ +#ifndef LIBWCCL_VALUES_POSITIONREF_H +#define LIBWCCL_VALUES_POSITIONREF_H + +#include <libwccl/values/position.h> +#include <boost/make_shared.hpp> + +namespace Wccl { + +class PositionRef : public Value +{ +public: + WCCL_VALUE_PREAMBLE + + explicit PositionRef(const boost::shared_ptr<Position>& base, + int offset = 0) + : base_(base), offset_(offset) + { + assert(base_); + } + + explicit PositionRef(int base, int offset = 0) + : base_(boost::make_shared<Position>(base)), offset_(offset) + { + } + + std::string to_raw_string() const; + + const boost::shared_ptr<Position>& get_base() const { + return base_; + } + + int get_offset() const { + return offset_; + } + + void set_offset(int offset) { + offset_ = offset; + } + +private: + boost::shared_ptr<Position> base_; + + int offset_; +}; + +} /* end ns Wccl */ + +#endif // LIBWCCL_VALUES_POSITIONREF_H diff --git a/libwccl/variables.h b/libwccl/variables.h index 8cc21277272cc43813eef5c7791d0fe6e0c278ee..ea77194746658e8dc06fadd7782bcb2e2399a9f4 100644 --- a/libwccl/variables.h +++ b/libwccl/variables.h @@ -4,6 +4,7 @@ #include <libwccl/values/bool.h> #include <libwccl/exception.h> #include <libwccl/values/position.h> +#include <libwccl/values/positionref.h> #include <iostream> #include <map> #include <string> @@ -82,11 +83,12 @@ public: class Variables : detail::Vmap<Value> , detail::Vmap<Bool> , detail::Vmap<Position> + , detail::Vmap<PositionRef> { public: /// Valid value types, should match the inheritance. /// the type Value must be first, order of other items is not important - typedef boost::mpl::list<Value, Bool, Position> types; + typedef boost::mpl::list<Value, Bool, Position, PositionRef> types; /// Constructor, creates an empty instance. Variables(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5d575c52ec1ba0d9f178691ed3ec447b18583e57..e56b4db7f09580c88cfcda1df87b93d1236aeff1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,6 +7,7 @@ add_definitions(-DLIBWCCL_TEST_DATA_DIR="${PROJECT_SOURCE_DIR}/") add_executable(tests main.cpp variables.cpp + position.cpp context.cpp ) diff --git a/tests/context.cpp b/tests/context.cpp index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9c15a817405cae7189d5ae17452ed47c8f86f156 100644 --- a/tests/context.cpp +++ b/tests/context.cpp @@ -0,0 +1,226 @@ +#include <boost/test/unit_test.hpp> +#include <boost/bind.hpp> + +#include <libwccl/variables.h> +#include <libwccl/sentencecontext.h> + +#include <iostream> + +using namespace Wccl; + +BOOST_AUTO_TEST_SUITE(context_position) + +BOOST_AUTO_TEST_CASE(contex_init) +{ + SentenceContext sc(boost::make_shared<Corpus2::Sentence>()); + BOOST_CHECK_EQUAL(sc.size(), 0); + BOOST_CHECK_EQUAL(sc.get_position(), 0); +} + +struct Fpos +{ + Fpos() + : sc(boost::make_shared<Corpus2::Sentence>()) + { + using namespace Corpus2; + using namespace PwrNlp::Whitespace; + sc.get_sentence().append( + new Token(UnicodeString::fromUTF8("t1"), Space)); + sc.get_sentence().append( + new Token(UnicodeString::fromUTF8("t2"), Space)); + sc.get_sentence().append( + new Token(UnicodeString::fromUTF8("t3"), Space)); + } + + SentenceContext sc; +}; + +BOOST_FIXTURE_TEST_CASE(scadvance, Fpos) +{ + BOOST_CHECK(sc.is_current_inside()); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_position(), 1); + BOOST_CHECK(sc.is_current_inside()); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_position(), 2); + BOOST_CHECK(sc.is_current_inside()); + sc.advance(); + BOOST_CHECK(!sc.is_current_inside()); + sc.goto_start(); + BOOST_CHECK(sc.is_current_inside()); + BOOST_CHECK_EQUAL(sc.get_position(), 0); +} + +BOOST_FIXTURE_TEST_CASE(pos0, Fpos) +{ + Position p(0); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 0); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); +} + +BOOST_FIXTURE_TEST_CASE(pos1, Fpos) +{ + Position p(1); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 1); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); +} + +BOOST_FIXTURE_TEST_CASE(posneg1, Fpos) +{ + Position p(-1); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 0); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -1); + sc.advance(); BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); +} + +BOOST_FIXTURE_TEST_CASE(pos_begin, Fpos) +{ + Position p(Position::Begin); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 0); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 0); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 0); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -2); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 0); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -3); +} + +BOOST_FIXTURE_TEST_CASE(pos_end, Fpos) +{ + Position p(Position::End); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 2); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -1); +} + +BOOST_FIXTURE_TEST_CASE(pos_no, Fpos) +{ + Position p(Position::Nowhere); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); +} + + +BOOST_FIXTURE_TEST_CASE(posref0, Fpos) +{ + PositionRef p(0, 1); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 1); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); +} + +BOOST_FIXTURE_TEST_CASE(posref1m1, Fpos) +{ + PositionRef p(1, -1); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 0); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); +} + +BOOST_FIXTURE_TEST_CASE(posref1_1, Fpos) +{ + PositionRef p(-1, 1); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 0); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 2); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); +} + +BOOST_FIXTURE_TEST_CASE(posref_begin, Fpos) +{ + PositionRef p(Position::Begin, 1); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -2); +} + +BOOST_FIXTURE_TEST_CASE(posref_end, Fpos) +{ + PositionRef p(Position::End, -1); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), 0); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -1); + sc.advance(); + BOOST_CHECK_EQUAL(sc.get_abs_position(p), 1); + BOOST_CHECK_EQUAL(sc.get_rel_position(p), -2); +} + +BOOST_FIXTURE_TEST_CASE(posref_no, Fpos) +{ + PositionRef p(Position::Nowhere, 1); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); + sc.advance(); + BOOST_CHECK(!sc.is_inside(sc.get_abs_position(p))); +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/tests/position.cpp b/tests/position.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391