diff --git a/libwccl/CMakeLists.txt b/libwccl/CMakeLists.txt
index 75bcc153864b0b9d1ff8eb77983f5c1b12b39cf5..4e2017bf3e2316f3e40890c89829639ff78cd467 100644
--- a/libwccl/CMakeLists.txt
+++ b/libwccl/CMakeLists.txt
@@ -55,6 +55,8 @@ SET(libwccl_STAT_SRC
 	ops/functions/tset/getsymbols.cpp
 	ops/functions/tset/getsymbolsinrange.cpp
 	ops/match/conditions/conjconditions.cpp
+	ops/match/conditions/longest.cpp
+	ops/match/conditions/oneof.cpp
 	ops/match/conditions/optionalmatch.cpp
 	ops/match/conditions/repeatedmatch.cpp
 	ops/match/conditions/tokencondition.cpp
diff --git a/libwccl/ops/match/applyoperator.cpp b/libwccl/ops/match/applyoperator.cpp
index cfecd52112358e6187939b69044f51b65b7fd5e4..a24ce2646a08c644d5c8ae614b8bc6bce27ee3b1 100644
--- a/libwccl/ops/match/applyoperator.cpp
+++ b/libwccl/ops/match/applyoperator.cpp
@@ -20,14 +20,14 @@ ApplyOperator::ApplyOperator(
 
 void ApplyOperator::execute(const ActionExecContext &context) const
 {
-	boost::shared_ptr<Position> iter_pos(new Position(0));
 	boost::shared_ptr<MatchVector> matches =
 		boost::dynamic_pointer_cast<MatchVector>(context.variables()->get_fast(_matches));
+	context.sentence_context().goto_start();
 	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);
+		int orig_pos = context.sentence_context().get_position();
+		// Set initial value for $m:_M variable for this iteration and launch the match:
 		matches->clear();
-		boost::shared_ptr<Match> match = _match_op->apply(iter_pos, context);
+		boost::shared_ptr<Match> match = _match_op->apply(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) {
@@ -40,12 +40,8 @@ void ApplyOperator::execute(const ActionExecContext &context) const
 			}
 		}
 		// 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());
+		// advancing current sentence position.
+		BOOST_ASSERT(context.sentence_context().get_position() > orig_pos);
 	}
 }
 
diff --git a/libwccl/ops/match/conditions/conjconditions.cpp b/libwccl/ops/match/conditions/conjconditions.cpp
index 7dd80eb211107e65e8d026c832b77a6c6f98f66d..11b1c1481aa50e170c26735c2645e81cf2f6794c 100644
--- a/libwccl/ops/match/conditions/conjconditions.cpp
+++ b/libwccl/ops/match/conditions/conjconditions.cpp
@@ -11,17 +11,17 @@ ConjConditions::ConjConditions(const std::vector< boost::shared_ptr<const MatchC
 	BOOST_ASSERT(_conditions.size() > 0);
 }
 
-MatchResult ConjConditions::apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const
+MatchResult ConjConditions::apply(const ActionExecContext& context) const
 {
 	boost::shared_ptr<MatchVector> matches(new MatchVector());
-	int orig_iter_pos = iter_pos->get_value();
+	int orig_pos = context.sentence_context().get_position();
 
 	foreach (const boost::shared_ptr<const MatchCondition>& cond, _conditions) {
-		MatchResult res = cond->apply(iter_pos, context);
+		MatchResult res = cond->apply(context);
 		if(res.matched()) {
 			matches->append(res.get_match());
 		} else {
-			iter_pos->set_value(orig_iter_pos);
+			context.sentence_context().set_position(orig_pos);
 			return MatchResult();
 		}
 	}
diff --git a/libwccl/ops/match/conditions/conjconditions.h b/libwccl/ops/match/conditions/conjconditions.h
index 38d0a145aebcef6f9aa1682dddc46e83a1f9106e..d2df5c45d7e245992dce2a6d1b3c8d70597f2b3a 100644
--- a/libwccl/ops/match/conditions/conjconditions.h
+++ b/libwccl/ops/match/conditions/conjconditions.h
@@ -22,10 +22,10 @@ public:
 	}
 	/**
 	 * Applies the condition to the given execution context.
-	 * If match is found, the current iter Position "$_" is increased
+	 * If match is found, the current position in sentence is increased
 	 * by one (the size of token match, which is always one).
 	 */
-	MatchResult apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const;
+	MatchResult apply(const ActionExecContext& context) const;
 
 	/**
 	 * @returns String representation of the MatchCondition
diff --git a/libwccl/ops/match/conditions/longest.cpp b/libwccl/ops/match/conditions/longest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ce8b9aaa56b9f9c4708b167dafc507a09220aa68
--- /dev/null
+++ b/libwccl/ops/match/conditions/longest.cpp
@@ -0,0 +1,61 @@
+#include <libwccl/ops/match/conditions/longest.h>
+#include <libwccl/values/matchvector.h>
+#include <sstream>
+#include <libpwrutils/foreach.h>
+
+namespace Wccl {
+
+Longest::Longest(const boost::shared_ptr<std::vector<ConjConditions> >& variants)
+	: _variants(variants)
+{
+	BOOST_ASSERT(_variants);
+	BOOST_ASSERT(!_variants->empty());
+}
+
+MatchResult Longest::apply(const ActionExecContext& context) const
+{
+	int orig_pos = context.sentence_context().get_position();
+	int longest_pos = orig_pos;
+	MatchResult longest;
+
+	foreach(const ConjConditions& variant, *_variants) {
+		MatchResult res = variant.apply(context);
+		int cur_pos = context.sentence_context().get_position();
+		if (res.matched() && longest_pos < cur_pos) {
+			longest_pos = cur_pos;
+			longest = res;
+		}
+		context.sentence_context().set_position(orig_pos);
+	}
+
+	context.sentence_context().set_position(longest_pos);
+	return longest;
+}
+
+std::string Longest::to_string(const Corpus2::Tagset& tagset) const
+{
+	std::ostringstream ostream;
+	ostream << name() << "(";
+	for (size_t i = 0; i < _variants->size(); ++i) {
+		if (i != 0) {
+			ostream << ", ";
+		}
+		ostream << "variant" << _variants->at(i).to_string(tagset);
+	}
+	ostream << ")";
+	return ostream.str();
+}
+
+std::ostream& Longest::write_to(std::ostream& ostream) const
+{
+	ostream << name() << "(";
+	for (size_t i = 0; i < _variants->size(); ++i) {
+		if (i != 0) {
+			ostream << ", ";
+		}
+		ostream << "variant" << _variants->at(i);
+	}
+	return ostream << ")";
+}
+
+} /* end ns Wccl */
diff --git a/libwccl/ops/match/conditions/longest.h b/libwccl/ops/match/conditions/longest.h
new file mode 100644
index 0000000000000000000000000000000000000000..2aed55ba7b4765a01784900e82fce96ed7b887b4
--- /dev/null
+++ b/libwccl/ops/match/conditions/longest.h
@@ -0,0 +1,52 @@
+#ifndef LIBWCCL_OPS_MATCH_CONDITIONS_LONGEST_H
+#define LIBWCCL_OPS_MATCH_CONDITIONS_LONGEST_H
+
+#include <libwccl/ops/match/conditions/conjconditions.h>
+
+namespace Wccl {
+
+/**
+ * Class for "longest" condition of match
+ */
+class Longest : public MatchCondition
+{
+public:
+	Longest(const boost::shared_ptr<std::vector<ConjConditions> >& variants);
+
+	/**
+	 * @returns Name of the condition.
+	 */
+	std::string name() const {
+		return "longest";
+	}
+	/**
+	 * Applies the condition to the given execution context.
+	 * Inner match variants are executed one by one to check which
+	 * one is the longest one. If any match variants were found to be "true",
+	 * the one that produced the longest match is returned with "true".
+	 * If there was no "true" match variant, "false" is returned instead.
+	 * If a match is found, the current sentence Position is increased
+	 * as to point one token after all the matched tokens, otherwise
+	 * it stays unchanged.
+	 */
+	MatchResult apply(const ActionExecContext& context) const;
+
+	/**
+	 * @returns String representation of the MatchCondition
+	 */
+	std::string to_string(const Corpus2::Tagset& tagset) const;
+
+protected:
+	/**
+	 * Writes string representation of the MatchCondition 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;
+private:
+	const boost::shared_ptr<std::vector<ConjConditions> > _variants;
+};
+} /* end ns Wccl */
+
+#endif // LIBWCCL_OPS_MATCH_CONDITIONS_LONGEST_H
diff --git a/libwccl/ops/match/conditions/oneof.cpp b/libwccl/ops/match/conditions/oneof.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78c3544c0656ddb6d828c3a6623a6943cbb66b4a
--- /dev/null
+++ b/libwccl/ops/match/conditions/oneof.cpp
@@ -0,0 +1,54 @@
+#include <libwccl/ops/match/conditions/oneof.h>
+#include <libwccl/values/matchvector.h>
+#include <sstream>
+#include <libpwrutils/foreach.h>
+
+namespace Wccl {
+
+OneOf::OneOf(const boost::shared_ptr<std::vector<ConjConditions> >& variants)
+	: _variants(variants)
+{
+	BOOST_ASSERT(_variants);
+	BOOST_ASSERT(!_variants->empty());
+}
+
+MatchResult OneOf::apply(const ActionExecContext& context) const
+{
+	int orig_pos = context.sentence_context().get_position();
+	foreach(const ConjConditions& variant, *_variants) {
+		MatchResult res = variant.apply(context);
+		if (res.matched()) {
+			return res;
+		}
+		context.sentence_context().set_position(orig_pos);
+	}
+	return MatchResult();
+}
+
+std::string OneOf::to_string(const Corpus2::Tagset& tagset) const
+{
+	std::ostringstream ostream;
+	ostream << name() << "(";
+	for (size_t i = 0; i < _variants->size(); ++i) {
+		if (i != 0) {
+			ostream << ", ";
+		}
+		ostream << "variant" << _variants->at(i).to_string(tagset);
+	}
+	ostream << ")";
+	return ostream.str();
+}
+
+std::ostream& OneOf::write_to(std::ostream& ostream) const
+{
+	ostream << name() << "(";
+	for (size_t i = 0; i < _variants->size(); ++i) {
+		if (i != 0) {
+			ostream << ", ";
+		}
+		ostream << "variant" << _variants->at(i);
+	}
+	return ostream << ")";
+}
+
+} /* end ns Wccl */
diff --git a/libwccl/ops/match/conditions/oneof.h b/libwccl/ops/match/conditions/oneof.h
new file mode 100644
index 0000000000000000000000000000000000000000..0aba4762638cf33c594401be71a2adfbba19572a
--- /dev/null
+++ b/libwccl/ops/match/conditions/oneof.h
@@ -0,0 +1,51 @@
+#ifndef LIBWCCL_OPS_MATCH_CONDITIONS_ONEOF_H
+#define LIBWCCL_OPS_MATCH_CONDITIONS_ONEOF_H
+
+#include <libwccl/ops/match/conditions/conjconditions.h>
+
+namespace Wccl {
+
+/**
+ * Class for "oneof" condition of match
+ */
+class OneOf : public MatchCondition
+{
+public:
+	OneOf(const boost::shared_ptr<std::vector<ConjConditions> >& variants);
+
+	/**
+	 * @returns Name of the condition.
+	 */
+	std::string name() const {
+		return "oneof";
+	}
+	/**
+	 * Applies the condition to the given execution context.
+	 * Inner match variants are executed one by one until a "true" one is found.
+	 * Once a "true" variant is found, it is returned with "true" MatchResult.
+	 * If there was no "true" match variant, "false" is returned instead.
+	 * If a match is found, the current sentence Position is increased
+	 * as to point one token after all the matched tokens, otherwise
+	 * it stays unchanged.
+	 */
+	MatchResult apply(const ActionExecContext& context) const;
+
+	/**
+	 * @returns String representation of the MatchCondition
+	 */
+	std::string to_string(const Corpus2::Tagset& tagset) const;
+
+protected:
+	/**
+	 * Writes string representation of the MatchCondition 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;
+private:
+	const boost::shared_ptr<std::vector<ConjConditions> > _variants;
+};
+} /* end ns Wccl */
+
+#endif // LIBWCCL_OPS_MATCH_CONDITIONS_ONEOF_H
diff --git a/libwccl/ops/match/conditions/optionalmatch.cpp b/libwccl/ops/match/conditions/optionalmatch.cpp
index bbc99ae00338dab56e788126af16545e2e04e26e..03116898c8236a6b9ff851e3dfcb82916c0fb816 100644
--- a/libwccl/ops/match/conditions/optionalmatch.cpp
+++ b/libwccl/ops/match/conditions/optionalmatch.cpp
@@ -10,14 +10,14 @@ OptionalMatch::OptionalMatch(const boost::shared_ptr<ConjConditions>& conditions
 	BOOST_ASSERT(_conditions);
 }
 
-MatchResult OptionalMatch::apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const
+MatchResult OptionalMatch::apply(const ActionExecContext& context) const
 {
-	int orig_pos = iter_pos->get_value();
-	MatchResult res = _conditions->apply(iter_pos, context);
+	int orig_pos = context.sentence_context().get_position();
+	MatchResult res = _conditions->apply(context);
 	if (res.matched()) {
 		return res;
 	}
-	iter_pos->set_value(orig_pos);
+	context.sentence_context().set_position(orig_pos);
 	return MatchResult(boost::make_shared<Match>());
 }
 
diff --git a/libwccl/ops/match/conditions/optionalmatch.h b/libwccl/ops/match/conditions/optionalmatch.h
index d9f3c1d66d914a95c83df7dde1a217d7cdbf088d..97dfb07622a094bf03b40554d8789866ecc1b9df 100644
--- a/libwccl/ops/match/conditions/optionalmatch.h
+++ b/libwccl/ops/match/conditions/optionalmatch.h
@@ -25,11 +25,11 @@ public:
 	 * If the match, was successfull the result consists of "true"
 	 * and the match.
 	 * If there was no match, "true" is returned anyway, but with a default Match.
-	 * If match is found, the current iter Position "$_" is increased
+	 * If match is found, the current sentence Position is increased
 	 * as to point one token after all the matched tokens, otherwise
 	 * it stays unchanged.
 	 */
-	MatchResult apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const;
+	MatchResult apply(const ActionExecContext& context) const;
 
 	/**
 	 * @returns String representation of the MatchCondition
diff --git a/libwccl/ops/match/conditions/repeatedmatch.cpp b/libwccl/ops/match/conditions/repeatedmatch.cpp
index a43fb47617e06d3e379a2576f6caf0aaf731dadb..f2fad5b6cc0653ac0df842f96c821c3f0a37d138 100644
--- a/libwccl/ops/match/conditions/repeatedmatch.cpp
+++ b/libwccl/ops/match/conditions/repeatedmatch.cpp
@@ -10,20 +10,20 @@ RepeatedMatch::RepeatedMatch(const boost::shared_ptr<ConjConditions>& conditions
 	BOOST_ASSERT(_conditions);
 }
 
-MatchResult RepeatedMatch::apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const
+MatchResult RepeatedMatch::apply(const ActionExecContext& context) const
 {
 	boost::shared_ptr<MatchVector> match(new MatchVector());
-	int orig_pos = iter_pos->get_value();
-	MatchResult res = _conditions->apply(iter_pos, context);
+	int orig_pos = context.sentence_context().get_position();
+	MatchResult res = _conditions->apply(context);
 	if (res.matched()) {
 		do {
 			match->append(res.get_match());
-			res = _conditions->apply(iter_pos, context);
+			res = _conditions->apply(context);
 		} while (res.matched());
 		return MatchResult(match);
 	}
 	else {
-		iter_pos->set_value(orig_pos);
+		context.sentence_context().set_position(orig_pos);
 		return MatchResult();
 	}
 }
diff --git a/libwccl/ops/match/conditions/repeatedmatch.h b/libwccl/ops/match/conditions/repeatedmatch.h
index 0454373b91f8761eeb73f0c76d6c8e3785285224..1d8764e151994848fb8cba744df390924e1e56bf 100644
--- a/libwccl/ops/match/conditions/repeatedmatch.h
+++ b/libwccl/ops/match/conditions/repeatedmatch.h
@@ -26,11 +26,11 @@ public:
 	 * and the MatchVector constructed out of individual match vectors coming
 	 * from each successful repetition.
 	 * If there was no match, "false" is returned along with a default Match.
-	 * If match is found, the current iter Position "$_" is increased
+	 * If match is found, the current sentence Position is increased
 	 * as to point one token after all the matched tokens, otherwise
 	 * it stays unchanged.
 	 */
-	MatchResult apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const;
+	MatchResult apply(const ActionExecContext& context) const;
 
 	/**
 	 * @returns String representation of the MatchCondition
diff --git a/libwccl/ops/match/conditions/tokencondition.cpp b/libwccl/ops/match/conditions/tokencondition.cpp
index 51604e69fc20d8d7e8530b6999a94d9acdefd392..e7f670f60b719b0295cb9b4965e001da9d77e263 100644
--- a/libwccl/ops/match/conditions/tokencondition.cpp
+++ b/libwccl/ops/match/conditions/tokencondition.cpp
@@ -19,17 +19,17 @@ std::string TokenCondition::to_string(const Corpus2::Tagset& tagset) const
 	return _predicate->to_string(tagset);
 }
 
-MatchResult TokenCondition::apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const
+MatchResult TokenCondition::apply(const ActionExecContext& context) const
 {
-	int orig_iter = iter_pos->get_value();
+	int orig_iter = context.sentence_context().get_position();
 	if (_predicate->apply(context)->get_value()) {
-		boost::shared_ptr<Match> match(new TokenMatch(context.sentence_context().get_abs_position(*iter_pos)));
-		// increase the $_ variable by one after successful token match
-		iter_pos->set_value(orig_iter + 1);
+		boost::shared_ptr<Match> match(new TokenMatch(context.sentence_context().get_position()));
+		// increase current sentence position by one after successful token match
+		context.sentence_context().set_position(orig_iter + 1);
 		return MatchResult(match);
 	}
 	else {
-		iter_pos->set_value(orig_iter);
+		context.sentence_context().set_position(orig_iter);
 		return MatchResult();
 	}
 }
diff --git a/libwccl/ops/match/conditions/tokencondition.h b/libwccl/ops/match/conditions/tokencondition.h
index 94f0bf2ddcbaf8fde817f96c848b65905e8d4742..cc86a277ee6ae7552f601596bc149b6ab31edfaa 100644
--- a/libwccl/ops/match/conditions/tokencondition.h
+++ b/libwccl/ops/match/conditions/tokencondition.h
@@ -20,10 +20,10 @@ public:
 	std::string name() const;
 	/**
 	 * Applies the condition to the given execution context.
-	 * If match is found, the current iter Position "$_" is increased
+	 * If match is found, the current sentence Position is increased
 	 * by one (the size of token match, which is always one).
 	 */
-	MatchResult apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const;
+	MatchResult apply(const ActionExecContext& context) const;
 
 	/**
 	 * @returns String representation of the Action
diff --git a/libwccl/ops/match/matchcondition.h b/libwccl/ops/match/matchcondition.h
index 6e8fddfa31587bead22629c71a109693e709d016..3b485065861242a2b5e2481e14e5ab7169641054 100644
--- a/libwccl/ops/match/matchcondition.h
+++ b/libwccl/ops/match/matchcondition.h
@@ -1,7 +1,7 @@
 #ifndef LIBWCCL_OPS_MATCH_MATCHCONDITION_H
 #define LIBWCCL_OPS_MATCH_MATCHCONDITION_H
 
-#include <libwccl/ops/funexeccontext.h>
+#include <libwccl/ops/actionexeccontext.h>
 #include <libwccl/ops/expression.h>
 #include <libwccl/ops/match/matchresult.h>
 
@@ -19,10 +19,10 @@ public:
 	virtual std::string name() const = 0;
 	/**
 	 * Applies the condition to the given execution context.
-	 * If match is found, the current iter position "$_" is
+	 * If match is found, the current sentence position is
 	 * set to position right after the match.
 	 */
-	virtual MatchResult apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const = 0;
+	virtual MatchResult apply(const ActionExecContext& context) const = 0;
 };
 
 } /* end ns Wccl */
diff --git a/libwccl/ops/match/matchoperator.cpp b/libwccl/ops/match/matchoperator.cpp
index 4cb8ec90581d689e9b47903e9f67147d6eb2f2a3..26a46e047f40563008818d31d37cc786887d0c94 100644
--- a/libwccl/ops/match/matchoperator.cpp
+++ b/libwccl/ops/match/matchoperator.cpp
@@ -3,16 +3,14 @@
 
 namespace Wccl {
 
-boost::shared_ptr<Match> MatchOperator::apply(
-		boost::shared_ptr<Position> iter_pos,
-		const FunExecContext& context) const
+boost::shared_ptr<Match> MatchOperator::apply(const ActionExecContext& context) const
 {
-	int orig_iter_pos = iter_pos->get_value();
-	MatchResult res = _conditions->apply(iter_pos, context);
+	int orig_pos = context.sentence_context().get_position();
+	MatchResult res = _conditions->apply(context);
 	if(res.matched()) {
 		return res.get_match();
 	}
-	iter_pos->set_value(orig_iter_pos + 1);
+	context.sentence_context().set_position(orig_pos + 1);
 	return boost::make_shared<Match>();
 }
 
diff --git a/libwccl/ops/match/matchoperator.h b/libwccl/ops/match/matchoperator.h
index dd6745b050a70210d760aa7069abca8a30653d87..000c38c89c81447378d204c461ec3b08c95bce23 100644
--- a/libwccl/ops/match/matchoperator.h
+++ b/libwccl/ops/match/matchoperator.h
@@ -31,16 +31,13 @@ public:
 	/**
 	 * Applies the operator to the given context.
 	 * @returns Vector of matches corresponding to match conditions,
-	 * if all conditions were met. In such case position $_ points one position
-	 * ahead of matched tokens.
+	 * if all conditions were met. In such case current sentence position
+	 * points to one position ahead of matched tokens.
 	 * Empty MatchVector is returned if any of the conditions was not met.
-	 * In such case Position $_ is advanced by 1.
-	 * @param iter_pos Pointer to the variable $_ from context's Variables
+	 * In such case current Position in sentence is advanced by 1.
 	 * @param context Execution context - current sentence and Variables to operate on
 	 */
-	boost::shared_ptr<Match> apply(
-			boost::shared_ptr<Position> iter_pos,
-			const FunExecContext& context) const;
+	boost::shared_ptr<Match> apply(const ActionExecContext& context) const;
 
 protected:
 	/**