#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 */