diff --git a/libwccl/CMakeLists.txt b/libwccl/CMakeLists.txt
index 9a894000a7b744c5e82cd7660543be92ec95e8c1..1dced6862f2ced24fd7cfd35e64a6326a36430d4 100644
--- a/libwccl/CMakeLists.txt
+++ b/libwccl/CMakeLists.txt
@@ -72,7 +72,6 @@ SET(libwccl_STAT_SRC
 	ops/match/conditions/repeatedmatch.cpp
 	ops/match/conditions/tokencondition.cpp
 	ops/matchrule.cpp
-	ops/rulesequence.cpp
 	ops/tagaction.cpp
 	ops/tagactions/delete.cpp
 	ops/tagactions/mark.cpp
@@ -81,6 +80,7 @@ SET(libwccl_STAT_SRC
 	ops/tagactions/unify.cpp
 	ops/tagactions/unmark.cpp
 	ops/tagrule.cpp
+	ops/tagrulesequence.cpp
 	parser/grammar.g
 	parser/Parser.cpp
 	parser/ParserException.cpp
diff --git a/libwccl/ops/match/conditions/longest.cpp b/libwccl/ops/match/conditions/longest.cpp
index ce8b9aaa56b9f9c4708b167dafc507a09220aa68..82a3653d12cf43216d76ce2561cd98cf239adf90 100644
--- a/libwccl/ops/match/conditions/longest.cpp
+++ b/libwccl/ops/match/conditions/longest.cpp
@@ -5,7 +5,7 @@
 
 namespace Wccl {
 
-Longest::Longest(const boost::shared_ptr<std::vector<ConjConditions> >& variants)
+Longest::Longest(const boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > >& variants)
 	: _variants(variants)
 {
 	BOOST_ASSERT(_variants);
@@ -18,8 +18,8 @@ MatchResult Longest::apply(const ActionExecContext& context) const
 	int longest_pos = orig_pos;
 	MatchResult longest;
 
-	foreach(const ConjConditions& variant, *_variants) {
-		MatchResult res = variant.apply(context);
+	foreach(const boost::shared_ptr<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;
@@ -40,7 +40,7 @@ std::string Longest::to_string(const Corpus2::Tagset& tagset) const
 		if (i != 0) {
 			ostream << ", ";
 		}
-		ostream << "variant" << _variants->at(i).to_string(tagset);
+		ostream << "variant" << _variants->at(i)->to_string(tagset);
 	}
 	ostream << ")";
 	return ostream.str();
@@ -53,7 +53,7 @@ std::ostream& Longest::write_to(std::ostream& ostream) const
 		if (i != 0) {
 			ostream << ", ";
 		}
-		ostream << "variant" << _variants->at(i);
+		ostream << "variant" << *(_variants->at(i));
 	}
 	return ostream << ")";
 }
diff --git a/libwccl/ops/match/conditions/longest.h b/libwccl/ops/match/conditions/longest.h
index 2aed55ba7b4765a01784900e82fce96ed7b887b4..008b50767b811b3f7d0ef1a205755afd68fccdae 100644
--- a/libwccl/ops/match/conditions/longest.h
+++ b/libwccl/ops/match/conditions/longest.h
@@ -11,7 +11,7 @@ namespace Wccl {
 class Longest : public MatchCondition
 {
 public:
-	Longest(const boost::shared_ptr<std::vector<ConjConditions> >& variants);
+	Longest(const boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > >& variants);
 
 	/**
 	 * @returns Name of the condition.
@@ -45,7 +45,7 @@ protected:
 	 */
 	std::ostream& write_to(std::ostream& ostream) const;
 private:
-	const boost::shared_ptr<std::vector<ConjConditions> > _variants;
+	const boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > > _variants;
 };
 } /* end ns Wccl */
 
diff --git a/libwccl/ops/match/conditions/oneof.cpp b/libwccl/ops/match/conditions/oneof.cpp
index 78c3544c0656ddb6d828c3a6623a6943cbb66b4a..068b04af3df261586d6bf6b0c0e8cfeaeb586b78 100644
--- a/libwccl/ops/match/conditions/oneof.cpp
+++ b/libwccl/ops/match/conditions/oneof.cpp
@@ -5,7 +5,7 @@
 
 namespace Wccl {
 
-OneOf::OneOf(const boost::shared_ptr<std::vector<ConjConditions> >& variants)
+OneOf::OneOf(const boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > >& variants)
 	: _variants(variants)
 {
 	BOOST_ASSERT(_variants);
@@ -15,8 +15,8 @@ OneOf::OneOf(const boost::shared_ptr<std::vector<ConjConditions> >& variants)
 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);
+	foreach(const boost::shared_ptr<ConjConditions>& variant, *_variants) {
+		MatchResult res = variant->apply(context);
 		if (res.matched()) {
 			return res;
 		}
@@ -33,7 +33,7 @@ std::string OneOf::to_string(const Corpus2::Tagset& tagset) const
 		if (i != 0) {
 			ostream << ", ";
 		}
-		ostream << "variant" << _variants->at(i).to_string(tagset);
+		ostream << "variant" << _variants->at(i)->to_string(tagset);
 	}
 	ostream << ")";
 	return ostream.str();
@@ -46,7 +46,7 @@ std::ostream& OneOf::write_to(std::ostream& ostream) const
 		if (i != 0) {
 			ostream << ", ";
 		}
-		ostream << "variant" << _variants->at(i);
+		ostream << "variant" << *(_variants->at(i));
 	}
 	return ostream << ")";
 }
diff --git a/libwccl/ops/match/conditions/oneof.h b/libwccl/ops/match/conditions/oneof.h
index 0aba4762638cf33c594401be71a2adfbba19572a..a0d649a9d2d98c400569cd74abba4d98fa80d726 100644
--- a/libwccl/ops/match/conditions/oneof.h
+++ b/libwccl/ops/match/conditions/oneof.h
@@ -11,7 +11,7 @@ namespace Wccl {
 class OneOf : public MatchCondition
 {
 public:
-	OneOf(const boost::shared_ptr<std::vector<ConjConditions> >& variants);
+	OneOf(const boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > >& variants);
 
 	/**
 	 * @returns Name of the condition.
@@ -44,7 +44,7 @@ protected:
 	 */
 	std::ostream& write_to(std::ostream& ostream) const;
 private:
-	const boost::shared_ptr<std::vector<ConjConditions> > _variants;
+	const boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > > _variants;
 };
 } /* end ns Wccl */
 
diff --git a/libwccl/ops/rulesequence.cpp b/libwccl/ops/tagrulesequence.cpp
similarity index 75%
rename from libwccl/ops/rulesequence.cpp
rename to libwccl/ops/tagrulesequence.cpp
index b5c1f8ac681b7f4f6889019bece07e4df167bad2..ea2c3abf3dacfe345f6e5cdee46e8a1370564945 100644
--- a/libwccl/ops/rulesequence.cpp
+++ b/libwccl/ops/tagrulesequence.cpp
@@ -1,10 +1,10 @@
-#include <libwccl/ops/rulesequence.h>
+#include <libwccl/ops/tagrulesequence.h>
 #include <libpwrutils/foreach.h>
 
 
 namespace Wccl {
 
-Bool RuleSequence::execute_once(const boost::shared_ptr<Corpus2::Sentence>& sentence)
+Bool TagRuleSequence::execute_once(const boost::shared_ptr<Corpus2::Sentence>& sentence)
 {
 	if(!sentence || sentence->empty()) {
 		throw InvalidArgument(
@@ -24,7 +24,7 @@ Bool RuleSequence::execute_once(const boost::shared_ptr<Corpus2::Sentence>& sent
 	return changed;
 }
 
-int RuleSequence::execute_until_done(const boost::shared_ptr<Corpus2::Sentence>& sentence, int max_iter)
+int TagRuleSequence::execute_until_done(const boost::shared_ptr<Corpus2::Sentence>& sentence, int max_iter)
 {
 	if(max_iter < 0) {
 		throw InvalidArgument(
diff --git a/libwccl/ops/rulesequence.h b/libwccl/ops/tagrulesequence.h
similarity index 87%
rename from libwccl/ops/rulesequence.h
rename to libwccl/ops/tagrulesequence.h
index 1015a9bf25e6b776a2eaf2988de36485f7471b4b..e415098d38adda9992a660f8ba315b607ff69a62 100644
--- a/libwccl/ops/rulesequence.h
+++ b/libwccl/ops/tagrulesequence.h
@@ -1,5 +1,5 @@
-#ifndef LIBWCCL_OPS_RULESEQUENCE_H
-#define LIBWCCL_OPS_RULESEQUENCE_H
+#ifndef LIBWCCL_OPS_TAGRULESEQUENCE_H
+#define LIBWCCL_OPS_TAGRULESEQUENCE_H
 
 #include <libwccl/ops/tagrule.h>
 
@@ -11,12 +11,12 @@ namespace Wccl {
  * for all positions of a Sentence.
  * @note The class methods are not thread-safe
  */
-class RuleSequence : public std::vector<TagRule>
+class TagRuleSequence : public std::vector<TagRule>
 {
 public:
-	RuleSequence(std::vector<TagRule> rules);
+	TagRuleSequence(std::vector<TagRule> rules);
 
-	RuleSequence();
+	TagRuleSequence();
 
 	/**
 	 * Executes all contained Rules sequentially, once for each position
@@ -73,20 +73,20 @@ public:
 //--- implementation details ---
 //
 inline
-RuleSequence::RuleSequence(std::vector<TagRule> rules)
+TagRuleSequence::TagRuleSequence(std::vector<TagRule> rules)
 	: std::vector<TagRule>(rules) {
 }
 
 inline
-RuleSequence::RuleSequence()
+TagRuleSequence::TagRuleSequence()
 	: std::vector<TagRule>() {
 }
 
 inline
-Bool RuleSequence::operator()(const boost::shared_ptr<Corpus2::Sentence>& sentence) {
+Bool TagRuleSequence::operator()(const boost::shared_ptr<Corpus2::Sentence>& sentence) {
 	return execute_once(sentence);
 }
 
 } /* end ns Wccl */
 
-#endif // LIBWCCL_OPS_RULESEQUENCE_H
+#endif // LIBWCCL_OPS_TAGRULESEQUENCE_H
diff --git a/libwccl/parser/Parser.cpp b/libwccl/parser/Parser.cpp
index f78dec74c16f61a6715715de4d968d9eb4522fd1..54813edf5482b18d0079cb71347386819b8ae79a 100644
--- a/libwccl/parser/Parser.cpp
+++ b/libwccl/parser/Parser.cpp
@@ -392,18 +392,18 @@ boost::shared_ptr<FunctionalOperator> Parser::parseAnyOperator(
 
 /**
  * @desc Parse rule sequence contained in a std::string. Converts the string
- *       to a stream and calls parseRuleSequence with it
+ *       to a stream and calls parseTagRuleSequence with it
  * @arg str rules string
  * @return the parsed rule sequence via a shared pointer
  */
-boost::shared_ptr<RuleSequence> Parser::parseRuleSequence(
+boost::shared_ptr<TagRuleSequence> Parser::parseTagRuleSequence(
 		const std::string& str) const
 {
 	std::stringstream ss (std::stringstream::in | std::stringstream::out);
 	ss << str;
 
 	try {
-		return this->parseRuleSequence(ss);
+		return this->parseTagRuleSequence(ss);
 	}
 	catch (ParserException&) {
 		throw;
@@ -416,12 +416,12 @@ boost::shared_ptr<RuleSequence> Parser::parseRuleSequence(
  * @arg istr input stream with writed rules
  * @return the parsed rule sequence via a shared pointer
  */
-boost::shared_ptr<RuleSequence> Parser::parseRuleSequence(
+boost::shared_ptr<TagRuleSequence> Parser::parseTagRuleSequence(
 		std::istream& istr) const
 {
 	ANTLRLexer lexer(istr);
 	ANTLRParser parser(lexer);
-	boost::shared_ptr<RuleSequence> res;
+	boost::shared_ptr<TagRuleSequence> res;
 
 	try {
 		res = parser.parse_rule_sequence(tagset_);
diff --git a/libwccl/parser/Parser.h b/libwccl/parser/Parser.h
index 0d7e49cf4b4520d1a41f0a6111813ffa78629e88..cc362727e4b08a2727817753532896555edd4756 100644
--- a/libwccl/parser/Parser.h
+++ b/libwccl/parser/Parser.h
@@ -15,7 +15,7 @@
 #include <libwccl/ops/operator.h>
 
 // rules
-#include <libwccl/ops/rulesequence.h>
+#include <libwccl/ops/tagrulesequence.h>
 
 // match actions
 #include <libwccl/ops/matchrule.h>
@@ -69,10 +69,10 @@ public:
 
 	// ---------------------------------------------------------------------------
 	// Parsing rule sequence from input string
-	boost::shared_ptr<RuleSequence>
-			parseRuleSequence(const std::string& rule_string) const;
-	boost::shared_ptr<RuleSequence>
-			parseRuleSequence(std::istream& is) const;
+	boost::shared_ptr<TagRuleSequence>
+			parseTagRuleSequence(const std::string& rule_string) const;
+	boost::shared_ptr<TagRuleSequence>
+			parseTagRuleSequence(std::istream& is) const;
 
 	// ---------------------------------------------------------------------------
 	// Parsing single rule from input string
diff --git a/libwccl/parser/grammar.g b/libwccl/parser/grammar.g
index d8b78df8733e8602287cd8984b986b1e8db1630e..f534a84a5b77d37af24a017b4720ee90bb7ce792 100644
--- a/libwccl/parser/grammar.g
+++ b/libwccl/parser/grammar.g
@@ -69,7 +69,7 @@ header {
 	// Rules, actions
 	#include <libwccl/ops/tagrule.h>
 	#include <libwccl/ops/matchrule.h>
-	#include <libwccl/ops/rulesequence.h>
+	#include <libwccl/ops/tagrulesequence.h>
 	//
 	#include <libwccl/ops/tagactions/unify.h>
 	#include <libwccl/ops/tagactions/delete.h>
@@ -248,10 +248,10 @@ parse_single_rule
 ;
 
 // Rule for parsing rules section in the wccl file
-// Returns boost::shared_ptr<RuleSequence>
+// Returns boost::shared_ptr<TagRuleSequence>
 parse_rule_sequence
 	[const Corpus2::Tagset& tagset]
-	returns [boost::shared_ptr<RuleSequence> rule_seq]
+	returns [boost::shared_ptr<TagRuleSequence> rule_seq]
 {
 	ParsingScope scope(tagset);
 }
@@ -1855,12 +1855,12 @@ rule
 // Rule sequence
 rule_sequence
 	[ParsingScope& scope]
-	returns [boost::shared_ptr<RuleSequence> rule_seq]
+	returns [boost::shared_ptr<TagRuleSequence> rule_seq]
 {
 	// FIXME czy tutaj przypadkiem nie powinno byc shared_ptr?
 	boost::shared_ptr<TagRule> rle;
 
-	rule_seq.reset(new RuleSequence());
+	rule_seq.reset(new TagRuleSequence());
 }
 	: rle = rule [scope] {
 		rule_seq->push_back(*rle);
@@ -1876,7 +1876,7 @@ rule_sequence
 // This is wrapper for rule_sequence in rules section in the wccl file
 rules
 	[ParsingScope& scope]
-	returns [boost::shared_ptr<RuleSequence> rule_seq]
+	returns [boost::shared_ptr<TagRuleSequence> rule_seq]
 	: "rules" LPAREN rule_seq = rule_sequence [scope] RPAREN {
 		//
 	}
@@ -2111,20 +2111,18 @@ match_condition_in
 // Retutns boost::shared_ptr<std::vector<ConjConditions> >
 match_variants
 	[ParsingScope& scope]
-	returns [boost::shared_ptr<std::vector<ConjConditions> > variants]
+	returns [boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > > variants]
 {
-	variants.reset(new std::vector<ConjConditions>());
+	variants.reset(new std::vector<boost::shared_ptr<ConjConditions> >());
 
 	boost::shared_ptr<ConjConditions> variant;
 }
 	: "variant" LPAREN variant = match_condition [scope] RPAREN {
-		// TODO
-		// variants->push_back(variant);
+		variants->push_back(variant);
 	} 
 	(
 		COMMA "variant" LPAREN variant = match_condition [scope] RPAREN {
-			// TODO
-			// variants->push_back(variant);
+			variants->push_back(variant);
 		}
 	)*
 ;
@@ -2207,7 +2205,7 @@ match_cond_oneof
 	[ParsingScope& scope]
 	returns [boost::shared_ptr<OneOf> onf]
 {
-	boost::shared_ptr<std::vector<ConjConditions> > variants;
+	boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > > variants;
 }
 	: "oneof" LPAREN variants = match_variants [scope] RPAREN {
 		onf.reset(new OneOf(variants));
@@ -2220,7 +2218,7 @@ match_cond_longest
 	[ParsingScope& scope]
 	returns [boost::shared_ptr<Longest> lng]
 {
-	boost::shared_ptr<std::vector<ConjConditions> > variants;
+	boost::shared_ptr<std::vector<boost::shared_ptr<ConjConditions> > > variants;
 }
 	: "longest" LPAREN variants = match_variants [scope] RPAREN {
 		lng.reset(new Longest(variants));
diff --git a/tests/datarule.cpp b/tests/datarule.cpp
index 24d0d4fd267816f45e1a86ae19574c3891bea099..b85e858fec5051ac770d2119bf34ae049fb53acb 100644
--- a/tests/datarule.cpp
+++ b/tests/datarule.cpp
@@ -109,7 +109,7 @@ void test_one_rule_item_actual(const rule_compare_test& c)
 	std::string rf = c.rule_file.string();
 	std::ifstream is(rf.c_str());
 	BOOST_REQUIRE(is.good());
-	boost::shared_ptr<Wccl::RuleSequence> rules = parser.parseRuleSequence(is);
+	boost::shared_ptr<Wccl::TagRuleSequence> rules = parser.parseTagRuleSequence(is);
 	for (size_t i = 0; i < chunk->sentences().size(); ++i) {
 		Corpus2::Sentence::Ptr sentence = chunk->sentences()[i]->clone_shared();
 		Corpus2::Sentence::Ptr expected_sentence = expected->sentences()[i];
diff --git a/wccl-apps/CMakeLists.txt b/wccl-apps/CMakeLists.txt
index b8b95da6852fbd08e959ee63d8a9e98eae8fb9d5..e07a49df24685820ba8044b67b203b6f8e4e8325 100644
--- a/wccl-apps/CMakeLists.txt
+++ b/wccl-apps/CMakeLists.txt
@@ -12,6 +12,9 @@ include_directories(${LibXML++_INCLUDE_DIRS})
 link_directories(${LibXML++_LIBRARY_DIRS})
 set(LIBS ${LIBS} ${LibXML++_LIBRARIES})
 
+find_package(Loki REQUIRED QUIET)
+set(LIBS ${LIBS} loki)
+
 include_directories(${CMAKE_SOURCE_DIR})
 include_directories(${Boost_INCLUDE_DIR})
 link_directories(${Boost_LIBRARY_DIRS})
diff --git a/wccl-apps/wccl-rules.cpp b/wccl-apps/wccl-rules.cpp
index 4b8b664aeb7f0cffea6fff31a199251c266f649f..c8119c96b7f8bbec0a2c2fcb08a0d275870cbe72 100644
--- a/wccl-apps/wccl-rules.cpp
+++ b/wccl-apps/wccl-rules.cpp
@@ -5,7 +5,7 @@
 
 #include <libwccl/values/strset.h>
 #include <libwccl/parser/Parser.h>
-#include <libwccl/ops/rulesequence.h>
+#include <libwccl/ops/tagrulesequence.h>
 #include <libcorpus2/tagsetmanager.h>
 #include <libcorpus2/util/tokentimer.h>
 
@@ -31,16 +31,16 @@ namespace {
 	};
 }
 
-bool load_more_rules(Wccl::Parser& parser, const std::string& filename, Wccl::RuleSequence& rules)
+bool load_more_rules(Wccl::Parser& parser, const std::string& filename, Wccl::TagRuleSequence& rules)
 {
-	boost::shared_ptr<Wccl::RuleSequence> ret;
+	boost::shared_ptr<Wccl::TagRuleSequence> ret;
 	try {
 		std::ifstream is(filename.c_str());
 		if (!is.good()) {
 			throw Wccl::FileNotFound(filename, "", __FUNCTION__);
 		}
 
-		ret = parser.parseRuleSequence(is);
+		ret = parser.parseTagRuleSequence(is);
 		if (ret) {
 			if (!quiet) {
 				std::cerr << "Loaded " << ret->size() << " rule(s) from "
@@ -73,7 +73,7 @@ bool load_more_rules(Wccl::Parser& parser, const std::string& filename, Wccl::Ru
 }
 
 void apply_rules(boost::shared_ptr<Corpus2::TokenReader> reader,
-	boost::shared_ptr<Corpus2::TokenWriter> writer, Wccl::RuleSequence& rules,
+	boost::shared_ptr<Corpus2::TokenWriter> writer, Wccl::TagRuleSequence& rules,
 	const options& opts)
 {
 	Corpus2::TokenTimer& timer = Corpus2::global_timer();
@@ -197,7 +197,7 @@ int main(int argc, char** argv)
 	try {
 		const Corpus2::Tagset& tagset = Corpus2::get_named_tagset(tagset_load);
 		Wccl::Parser parser(tagset);
-		Wccl::RuleSequence rules;
+		Wccl::TagRuleSequence rules;
 		foreach (const std::string& f, ccl_files) {
 			size_t sz = rules.size();
 			if (!load_more_rules(parser, f, rules)) {