From 17c6528932d553cb51cdc582bc654b2f098f205c Mon Sep 17 00:00:00 2001
From: Adam Wardynski <award@.(B-4.4.46a)>
Date: Fri, 11 Mar 2011 19:52:04 +0100
Subject: [PATCH] ApplyOperator, the main operator behind match rules.

---
 libwccl/CMakeLists.txt              |   1 +
 libwccl/ops/match/applyoperator.cpp | 102 ++++++++++++++++++++++++++++
 libwccl/ops/match/applyoperator.h   |  70 +++++++++++++++++++
 3 files changed, 173 insertions(+)
 create mode 100644 libwccl/ops/match/applyoperator.cpp
 create mode 100644 libwccl/ops/match/applyoperator.h

diff --git a/libwccl/CMakeLists.txt b/libwccl/CMakeLists.txt
index f868a40..c3e53ec 100644
--- a/libwccl/CMakeLists.txt
+++ b/libwccl/CMakeLists.txt
@@ -55,6 +55,7 @@ SET(libwccl_STAT_SRC
 	ops/functions/tset/getsymbols.cpp
 	ops/functions/tset/getsymbolsinrange.cpp
 	ops/match/conditions/tokencondition.cpp
+	ops/match/applyoperator.cpp
 	ops/match/matchoperator.cpp
 	ops/rulesequence.cpp
 	ops/tagaction.cpp
diff --git a/libwccl/ops/match/applyoperator.cpp b/libwccl/ops/match/applyoperator.cpp
new file mode 100644
index 0000000..cdac967
--- /dev/null
+++ b/libwccl/ops/match/applyoperator.cpp
@@ -0,0 +1,102 @@
+#include <libwccl/ops/match/applyoperator.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);
+			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 */
diff --git a/libwccl/ops/match/applyoperator.h b/libwccl/ops/match/applyoperator.h
new file mode 100644
index 0000000..e160a40
--- /dev/null
+++ b/libwccl/ops/match/applyoperator.h
@@ -0,0 +1,70 @@
+#ifndef LIBWCCL_OPS_MATCH_APPLYOPERATOR_H
+#define LIBWCCL_OPS_MATCH_APPLYOPERATOR_H
+
+#include <libwccl/ops/function.h>
+
+#include <libwccl/ops/match/matchoperator.h>
+#include <libwccl/ops/match/matchaction.h>
+
+namespace Wccl {
+
+/**
+ * Operator that realizes "apply" functionality for match rules
+ */
+class ApplyOperator : public Expression
+{
+public:
+
+	/**
+	  * @param cur_iter_pos Accessor to the "$_" variable
+	  * @param matches Accessor to the "$m:_M" variable
+	  * @param match_op "match" operator for apply
+	  * @param actions "actions" section of apply, should not be empty
+	  * @param conditions "cond" section of apply, empty by default
+	  */
+	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 = (std::vector<boost::shared_ptr<const Function<Bool> > >()));
+
+	/**
+	 * @returns Name of the operator.
+	 */
+	std::string name() const {
+		return "apply";
+	}
+
+	/**
+	 * @returns String representation of the Action
+	 */
+	std::string to_string(const Corpus2::Tagset& tagset) const;
+
+protected:
+	/**
+	 * Writes string representation of the operator to
+	 * an output stream.
+	 * @returns Stream written to.
+	 * @note May be incomplete and/or containt internal info.
+	 */
+	std::ostream& write_to(std::ostream& ostream) const;
+
+	/**
+	 * Executes the apply operator on given context.
+	 * It iterates current sentence position applying match operator
+	 * and if match is found and conditions are met, executes actions.
+	 */
+	virtual void execute(const ActionExecContext &context) const;
+
+private:
+	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;
+};
+
+} /* end ns Wccl */
+
+#endif // LIBWCCL_OPS_MATCH_APPLYOPERATOR_H
-- 
GitLab