Skip to content
Snippets Groups Projects
Commit 0e5a316a authored by Adam Wardynski's avatar Adam Wardynski
Browse files

Operator returning Position relative to given position.

RelativePosition operator, represented by "+" in WCCL (at least initially). Returns Nowhere for Nowhere, or a Position shifted by given offset to the position given (Begin and End are first translated into normal Positions).
parent 2b838d4b
Branches
No related merge requests found
......@@ -35,6 +35,7 @@ SET(libwccl_STAT_SRC
ops/or.cpp
ops/predicate.cpp
ops/regex.cpp
ops/relativeposition.cpp
ops/tolower.cpp
ops/toupper.cpp
parser/Parser.cpp
......
#include <libwccl/ops/relativeposition.h>
#include <sstream>
#include <libwccl/ops/constant.h>
namespace Wccl {
RelativePosition::BaseRetValPtr RelativePosition::apply_internal(
const FunExecContext &context) const
{
static const Constant<Position> nowhere((Position(Position::Nowhere)));
const RetValPtr& orig_pos = pos_expr_->apply(context);
if(orig_pos->get_value() == Position::Nowhere) {
return nowhere.apply(context);
}
const SentenceContext& sc = context.sentence_context();
return RetValPtr(new Position(offset_ + sc.get_rel_position(*orig_pos)));
}
std::string RelativePosition::to_string(const Corpus2::Tagset &tagset) const
{
std::stringstream ss;
ss << pos_expr_->to_string(tagset);
if(offset_ >= 0) {
ss << " + " << offset_;
} else {
ss << " - " << -offset_;
}
return ss.str();
}
std::string RelativePosition::to_raw_string() const
{
std::stringstream ss;
ss << pos_expr_->to_raw_string();
if(offset_ >= 0) {
ss << " + " << offset_;
} else {
ss << " - " << -offset_;
}
return ss.str();
}
} /* end ns Wccl */
#ifndef LIBWCCL_OPS_RELATIVEPOSITION_H
#define LIBWCCL_OPS_RELATIVEPOSITION_H
#include <libwccl/ops/functions.h>
#include <libwccl/ops/formatters.h>
#include <libwccl/values/position.h>
namespace Wccl {
/**
* Operator that takes a Position and an offset and returns relative
* Position, shifted by the offset from the original one.
*/
class RelativePosition : public Function<Position> {
public:
typedef boost::shared_ptr<Function<Position> > PosFunctionPtr;
RelativePosition(const PosFunctionPtr& pos_expr, int offset)
: pos_expr_(pos_expr),
offset_(offset)
{
BOOST_ASSERT(pos_expr_);
}
virtual std::string to_string(const Corpus2::Tagset& tagset) const;
virtual std::string to_raw_string() const;
virtual const std::string raw_operator_name() const {
return "+";
}
protected:
const PosFunctionPtr pos_expr_;
const int offset_;
/**
* Takes the value of a Position from argument expression, and returns
* a Position relative to it, shifted by the offset that this
* RelativePosition object is representing.
* The result is not being trimmed to boundaries of the current
* sentence (a Position pointing outside of a sentence is still
* a valid Position).
* If "nowhere" is given, "nowhere" is returned (shifted "nowhere"
* still points to "nowhere").
* If "begin" or "end" are given, they are first represented as a normal
* Position Value (i.e. a Position relative to the current Position
* in the SentenceContext acted upon) which is then shifted normally.
* @returns Position that is shifted by the represented offset relative
* to the Position being passed as argument to Operator.
*/
virtual BaseRetValPtr apply_internal(const FunExecContext& context) const;
};
} /* end ns Wccl */
#endif // LIBWCCL_OPS_RELATIVEPOSITION_H
......@@ -13,6 +13,7 @@ add_executable(tests
position.cpp
positionpredicates.cpp
regex.cpp
relativeposition.cpp
strsetfunctions.cpp
values.cpp
varaccess.cpp
......
#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/relativeposition.h>
using namespace Wccl;
BOOST_AUTO_TEST_SUITE(relative_position)
struct PosPredFix
{
PosPredFix()
: s(boost::make_shared<Corpus2::Sentence>()),
sc(s),
tagset(),
cx(sc, boost::make_shared<Variables>()),
pos_one(1),
pos_minus_one(-1),
nowhere(Position::Nowhere),
begin(Position::Begin),
end(Position::End),
pos_one_constant(new Constant<Position>(pos_one)),
pos_minus_one_constant(new Constant<Position>(pos_minus_one)),
nowhere_constant(new Constant<Position>(nowhere)),
begin_constant(new Constant<Position>(begin)),
end_constant(new Constant<Position>(end))
{
Corpus2::Token* the_token = new Corpus2::Token("ZZ", PwrNlp::Whitespace::ManySpaces);
Corpus2::Tag t1(Corpus2::mask_t(0));
Corpus2::Lexeme l1("aaa", t1);
Corpus2::Lexeme l2("bbb", t1);
the_token->add_lexeme(l1);
the_token->add_lexeme(l2);
s->append(the_token);
s->append(the_token->clone());
}
boost::shared_ptr<Corpus2::Sentence> s;
SentenceContext sc;
Corpus2::Tagset tagset;
FunExecContext cx;
Position pos_one;
Position pos_minus_one;
Position nowhere;
Position begin;
Position end;
boost::shared_ptr<Function<Position> > pos_one_constant;
boost::shared_ptr<Function<Position> > pos_minus_one_constant;
boost::shared_ptr<Function<Position> > nowhere_constant;
boost::shared_ptr<Function<Position> > begin_constant;
boost::shared_ptr<Function<Position> > end_constant;
};
BOOST_FIXTURE_TEST_CASE(rel_nowhere, PosPredFix)
{
for(int offset = -2; offset < 3; offset++)
{
RelativePosition relpos(nowhere_constant, offset);
BOOST_CHECK_EQUAL(
Position::Nowhere,
relpos.apply(cx)->get_value());
sc.advance();
BOOST_CHECK_EQUAL(
Position::Nowhere,
relpos.apply(cx)->get_value());
sc.advance();
BOOST_CHECK_EQUAL(
Position::Nowhere,
relpos.apply(cx)->get_value());
sc.goto_start();
}
}
BOOST_FIXTURE_TEST_CASE(rel_begin, PosPredFix)
{
for(int offset = -2; offset < 3; offset++)
{
RelativePosition relpos(begin_constant, offset);
BOOST_CHECK_EQUAL(
offset,
cx.sentence_context().get_abs_position(*relpos.apply(cx)));
sc.advance();
BOOST_CHECK_EQUAL(
offset,
cx.sentence_context().get_abs_position(*relpos.apply(cx)));
sc.advance();
BOOST_CHECK_EQUAL(
offset,
cx.sentence_context().get_abs_position(*relpos.apply(cx)));
sc.goto_start();
}
}
BOOST_FIXTURE_TEST_CASE(rel_end, PosPredFix)
{
for(int i = -2; i < 3; i++)
{
RelativePosition relpos(end_constant, i);
BOOST_CHECK_EQUAL(
sc.size() - 1 + i,
cx.sentence_context().get_abs_position(*relpos.apply(cx)));
sc.advance();
BOOST_CHECK_EQUAL(
sc.size() - 1 + i,
cx.sentence_context().get_abs_position(*relpos.apply(cx)));
sc.advance();
BOOST_CHECK_EQUAL(
sc.size() - 1 + i,
cx.sentence_context().get_abs_position(*relpos.apply(cx)));
sc.goto_start();
}
}
BOOST_FIXTURE_TEST_CASE(rel_normal_pos, PosPredFix)
{
for(int offset = -2; offset < 3; offset++)
{
for(int pos = -2; pos < 3; pos++)
{
boost::shared_ptr<Constant<Position> > position(new Constant<Position>(Position(pos)));
RelativePosition relpos(position, offset);
BOOST_CHECK_EQUAL(
offset + pos,
relpos.apply(cx)->get_value());
sc.advance();
BOOST_CHECK_EQUAL(
offset + pos,
relpos.apply(cx)->get_value());
sc.advance();
BOOST_CHECK_EQUAL(
offset + pos,
relpos.apply(cx)->get_value());
sc.goto_start();
}
}
}
//------ to_string test cases -------
BOOST_FIXTURE_TEST_CASE(relpos_to_string, PosPredFix)
{
RelativePosition relpos(begin_constant, 4);
BOOST_CHECK_EQUAL("begin + 4", relpos.to_string(tagset));
RelativePosition relpos_min1(pos_minus_one_constant, -1);
BOOST_CHECK_EQUAL("-1 - 1", relpos_min1.to_string(tagset));
RelativePosition relpos_zero(end_constant, 0);
BOOST_CHECK_EQUAL("end + 0", relpos_zero.to_string(tagset));
}
BOOST_FIXTURE_TEST_CASE(relpos_to_raw_string, PosPredFix)
{
RelativePosition relpos(nowhere_constant, 42);
BOOST_CHECK_EQUAL("nowhere + 42", relpos.to_raw_string());
RelativePosition relpos_min1(pos_one_constant, -1);
BOOST_CHECK_EQUAL("1 - 1", relpos_min1.to_raw_string());
RelativePosition relpos_zero(end_constant, 0);
BOOST_CHECK_EQUAL("end + 0", relpos_zero.to_raw_string());
}
BOOST_AUTO_TEST_SUITE_END()
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment