#ifndef LIBWCCL_SENTENCECONTEXT_H #define LIBWCCL_SENTENCECONTEXT_H #include <libcorpus2/sentence.h> #include <libwccl/values/position.h> #include <boost/shared_ptr.hpp> namespace Wccl { /** * A wrapper for a Corpus2 Sentence that adds a "current position" * and several convenience functions. * * Copying contexts is cheap and safe since the sentence is kept through * a shared pointer, use duplicate() or clone() to get a copy with a separate * underlying sentence (which is slower). */ class SentenceContext { public: /// Constructor, wraps the Sentence and sets position to 0 explicit SentenceContext(const boost::shared_ptr<Corpus2::Sentence>& s); /// Returns a copy of this with a cloned underlyiong sentence SentenceContext duplicate() const; /// Cloning -- clones the underlying sentence as well SentenceContext* clone() const; /// Underlying sentence accessor Corpus2::Sentence& get_sentence() { return *sentence_; } /// Underlying sentence accessor, const const Corpus2::Sentence& get_sentence() const { return *sentence_; } /// Shorthand to get_sentence().size() int size() const { return sentence_->size(); } /// Position accessor int get_position() const { return position_; } /// Checks if the current position is valid (within the sentence bounds) 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 void set_position(int new_position) { position_ = new_position; } /// Position advance shorthand void advance() { ++position_; } /// Reste position to point to the first token void goto_start() { position_ = 0; } /// Token access convenience function - const. /// Will return NULL if the passed position is not valid in this Sentence const Corpus2::Token* at(int abs_pos) const { if (is_current_inside()) { return get_sentence()[abs_pos]; } else { return NULL; } } /// Token access const function overload that takes a Position object const Corpus2::Token* at(const Position& position) const { return at(get_abs_position(position)); } /// Token access convenience function. /// Will return NULL if the passed position is not valid in this Sentence Corpus2::Token* at(int abs_pos) { if (is_current_inside()) { return get_sentence()[abs_pos]; } else { return NULL; } } /// Token access function overload that takes a Position object Corpus2::Token* at(const Position& position) { return at(get_abs_position(position)); } /// Current token access shorthand, const. @see at const Corpus2::Token* current() const { return at(position_); } /// Current token access shorthand. @see at Corpus2::Token* current() { return at(position_); } int get_abs_position(const Position& position) const; int get_rel_position(const Position& 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_; /// Current position in the sentence int position_; }; // TODO ConstSentenceContext ? } /* end ns Wccl */ #endif // LIBWCCL_SENTENCECONTEXT_H