diff --git a/libwccl/CMakeLists.txt b/libwccl/CMakeLists.txt
index c3e53ec55e352ce4c0f8bad5cfa9ffadcf075284..2b63e4b476862ad188009f6ab6c2eff759b9122d 100644
--- a/libwccl/CMakeLists.txt
+++ b/libwccl/CMakeLists.txt
@@ -54,6 +54,7 @@ SET(libwccl_STAT_SRC
 	ops/functions/tset/catfilter.cpp
 	ops/functions/tset/getsymbols.cpp
 	ops/functions/tset/getsymbolsinrange.cpp
+	ops/match/conditions/conjconditions.cpp
 	ops/match/conditions/tokencondition.cpp
 	ops/match/applyoperator.cpp
 	ops/match/matchoperator.cpp
diff --git a/libwccl/ops/match/conditions/conjconditions.cpp b/libwccl/ops/match/conditions/conjconditions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7dd80eb211107e65e8d026c832b77a6c6f98f66d
--- /dev/null
+++ b/libwccl/ops/match/conditions/conjconditions.cpp
@@ -0,0 +1,58 @@
+#include <libwccl/ops/match/conditions/conjconditions.h>
+#include <libwccl/values/matchvector.h>
+#include <libpwrutils/foreach.h>
+#include <sstream>
+
+namespace Wccl {
+
+ConjConditions::ConjConditions(const std::vector< boost::shared_ptr<const MatchCondition> >& conditions)
+	: _conditions(conditions)
+{
+	BOOST_ASSERT(_conditions.size() > 0);
+}
+
+MatchResult ConjConditions::apply(boost::shared_ptr<Position> iter_pos, const FunExecContext& context) const
+{
+	boost::shared_ptr<MatchVector> matches(new MatchVector());
+	int orig_iter_pos = iter_pos->get_value();
+
+	foreach (const boost::shared_ptr<const MatchCondition>& cond, _conditions) {
+		MatchResult res = cond->apply(iter_pos, context);
+		if(res.matched()) {
+			matches->append(res.get_match());
+		} else {
+			iter_pos->set_value(orig_iter_pos);
+			return MatchResult();
+		}
+	}
+	return MatchResult(matches);
+}
+
+std::string ConjConditions::to_string(const Corpus2::Tagset& tagset) const
+{
+	std::ostringstream ostream;
+	ostream << "(";
+	for(size_t i = 0; i < _conditions.size(); ++i) {
+		if (i != 0) {
+			ostream << ", ";
+		}
+		ostream << _conditions[i]->to_string(tagset);
+	}
+	ostream << ")";
+	return ostream.str();
+}
+
+std::ostream& ConjConditions::write_to(std::ostream &ostream) const
+{
+	ostream << "(";
+	for(size_t i = 0; i < _conditions.size(); ++i) {
+		if (i != 0) {
+			ostream << ", ";
+		}
+		ostream << *_conditions[i];
+	}
+	ostream << ")";
+	return ostream;
+}
+
+} /* end ns Wccl */
diff --git a/libwccl/ops/match/conditions/conjconditions.h b/libwccl/ops/match/conditions/conjconditions.h
new file mode 100644
index 0000000000000000000000000000000000000000..38d0a145aebcef6f9aa1682dddc46e83a1f9106e
--- /dev/null
+++ b/libwccl/ops/match/conditions/conjconditions.h
@@ -0,0 +1,49 @@
+#ifndef LIBWCCL_OPS_MATCH_CONDITIONS_CONJCONDITIONS_H
+#define LIBWCCL_OPS_MATCH_CONDITIONS_CONJCONDITIONS_H
+
+#include <libwccl/ops/match/matchcondition.h>
+
+namespace Wccl {
+
+/**
+ * Class that wraps a vector of match conditions to act as
+ * single condition that matches if all inner conditions match.
+ */
+class ConjConditions : public MatchCondition
+{
+public:
+	ConjConditions(const std::vector< boost::shared_ptr<const MatchCondition> >& conditions);
+
+	/**
+	 * @returns Name of the condition.
+	 */
+	std::string name() const {
+		return "and"; // string repr actually doesn't include this
+	}
+	/**
+	 * Applies the condition to the given execution context.
+	 * If match is found, the current iter 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;
+
+	/**
+	 * @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 std::vector<boost::shared_ptr<const MatchCondition> > _conditions;
+};
+
+} /* end ns Wccl */
+
+#endif // LIBWCCL_OPS_MATCH_CONDITIONS_CONJCONDITIONS_H