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
No related branches found
No related tags found
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% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment