Skip to content
Snippets Groups Projects
applyoperator.cpp 3.1 KiB
Newer Older
#include <libwccl/ops/match/applyoperator.h>
#include <libwccl/values/matchvector.h>
#include <libpwrutils/foreach.h>

namespace Wccl {

ApplyOperator::ApplyOperator(
	const VariableAccessor<Position>& cur_iter_pos,
	const VariableAccessor<Match>& matches,
	const boost::shared_ptr<const MatchOperator>& match_op,
	const std::vector<boost::shared_ptr<const MatchAction> >& actions,
	const std::vector<boost::shared_ptr<const Function<Bool> > >& conditions)
		: _cur_iter_pos(cur_iter_pos),
		  _matches(matches),
		  _match_op(match_op),
		  _actions(actions),
		  _conditions(conditions)
{
	BOOST_ASSERT(_match_op);
	BOOST_ASSERT(actions.size() > 0);
}

void ApplyOperator::execute(const ActionExecContext &context) const
{
	boost::shared_ptr<Position> iter_pos = context.variables()->get_fast(_cur_iter_pos);
	boost::shared_ptr<MatchVector> matches =
			boost::dynamic_pointer_cast<MatchVector>(context.variables()->get_fast(_matches));
	while(context.sentence_context().is_current_inside()) {
		// Set initial values of $_ and $m:_M variables for this iteration and launch the match:
		iter_pos->set_value(0);
		matches->clear();
		boost::shared_ptr<Match> match = _match_op->apply(iter_pos, context);
		// Execute the actions only if match isn't empty and all post-conditions are met:
		bool should_act = !match->empty();
		for(size_t i = 0; should_act && i < _conditions.size(); ++i) {
			should_act = _conditions[i]->apply(context)->get_value();
		}
		if (should_act) {
			matches->append(match); // the match goes to $m:_M[0]
			foreach (const boost::shared_ptr<const MatchAction>& action, _actions) {
				action->execute(context);
			}
		}
		// Inner operators (match and its conditions) are responsible for properly
		// advancing $_ variable.
		// After an iteration, we increase current sentence position by the value of $_
		// and repeat until current sentence position goes outside.
		BOOST_ASSERT(iter_pos->get_value() > 0);
		context.sentence_context().set_position(
				context.sentence_context().get_position() + iter_pos->get_value());
	}
}

std::string ApplyOperator::to_string(const Corpus2::Tagset& tagset) const
{
	std::ostringstream ostream;
	ostream << name() << "(" << _match_op->to_string(tagset) << ", ";
	if (!_conditions.empty()) {
		ostream << "cond(";
		for(size_t i = 0; i < _conditions.size(); ++i) {
			if (i != 0) {
				ostream << ", ";
			}
			ostream << _conditions[i]->to_string(tagset);
		}
		ostream << "), ";
	}
	ostream << "actions(";
	for(size_t i = 0; i < _actions.size(); ++i) {
		if (i != 0) {
			ostream << ", ";
		}
		ostream << _actions[i]->to_string(tagset);
	}
	ostream << "))";
	return ostream.str();
}

std::ostream& ApplyOperator::write_to(std::ostream &ostream) const
{
	ostream << name() << "(" << *_match_op << ", ";
	if (!_conditions.empty()) {
		ostream << "cond(";
		for(size_t i = 0; i < _conditions.size(); ++i) {
			if (i != 0) {
				ostream << ", ";
			}
			ostream << *_conditions[i];
		}
		ostream << "), ";
	}
	ostream << "actions(";
	for(size_t i = 0; i < _actions.size(); ++i) {
		if (i != 0) {
			ostream << ", ";
		}
		ostream << *_actions[i];
	}
	ostream << "))";
	return ostream;
}

} /* end ns Wccl */