diff --git a/libwccl/parser/grammar.g b/libwccl/parser/grammar.g
index 486bc79f3962ff278b20b16c21ea77d2635179da..41d52380bce3c44a8a3aaa2b542f38bcb4746f8d 100644
--- a/libwccl/parser/grammar.g
+++ b/libwccl/parser/grammar.g
@@ -249,7 +249,6 @@ parse_match_rule
 {
 	Variables vars;
 	vars.get_put<Match>("$m_M");
-	vars.get_put<Position>("$_");
 }
 	: ret_match = match_rule_operator[tagset, vars] 
 ;
@@ -1708,27 +1707,39 @@ match_rule_operator
 {
 	//
 }
-	: ret_op = match_operator [tagset, vars]
+	: ret_op = match_apply_operator [tagset, vars]
 ;
 
 // Match apply operator:
-// 	apply(match(), conditions, actions) 
-// 	apply(match(), actions)
+// 	apply(match(), cond(conditions), actions(actions)) 
+// 	apply(match(), actions(actions))
 // Returns boost::shared_ptr<ApplyOperator>
 match_apply_operator
 	[const Corpus2::Tagset& tagset, Variables& vars]
 	returns [boost::shared_ptr<ApplyOperator> ret_op]
 {
-	// VariableAccessor<Match> matches;
-	// VariableAccessor<Position> cur_iter_pos;
-	// boost::shared_ptr<const MatchOperator> match_op;
-	// std::vector<boost::shared_ptr<const MatchAction> > actions;
-	// std::vector<boost::shared_ptr<const Function<Bool> > > conditions;
-	// TODO
+	VariableAccessor<Match> matches = vars.create_accessor<Match>("$m_M");;
+	boost::shared_ptr<const MatchOperator> match_op;
+	boost::shared_ptr<std::vector<boost::shared_ptr<MatchAction> > > actions;
+	boost::shared_ptr<std::vector<boost::shared_ptr<Function<Bool> > > > conditions;
+
 }
-	: "apply" LPAREN RPAREN {
-		// TODO
-	}
+	: "apply" LPAREN 
+		match_op = match_operator[tagset, vars] COMMA
+		("cond"   LPAREN conditions = bool_operator_comma_sep [tagset, vars] RPAREN COMMA)?
+		"actions" LPAREN actions    =  match_action_comma_sep [tagset, vars] RPAREN
+		RPAREN {
+			if (conditions) {
+				ret_op.reset(
+					new ApplyOperator(matches, match_op, actions, conditions)
+				);
+			}
+			else {
+				ret_op.reset(
+					new ApplyOperator(matches, match_op, actions)
+				);
+			}
+		}
 ;
 
 // Match operator: match(match_conditions)
@@ -1784,7 +1795,7 @@ match_cond_all
 	| ret = match_cond_repeate  [tagset, vars]
 ;
 
-// Match condition - optional
+ // Match condition - optional
 // Returns boost::shared_ptr<OptionalMatch>
 match_cond_optional
 	[const Corpus2::Tagset& tagset, Variables& vars]
@@ -1812,6 +1823,53 @@ match_cond_repeate
 
 // ----------------------------------------------------------------------------
 
+// Match actions. Match action can be mark or unmark
+// Returns boost::shared_ptr<MatchAction>
+match_action
+	[const Corpus2::Tagset& tagset, Variables& vars]
+	returns [boost::shared_ptr<MatchAction> m_act]
+	: m_act = match_mark_action   [tagset, vars]
+	| m_act = match_unmark_action [tagset, vars]
+;
+
+// Match mark action
+// Returns ???
+match_mark_action
+	[const Corpus2::Tagset& tagset, Variables& vars]
+	returns [boost::shared_ptr<MatchAction> m_act]
+	: "mark" LPAREN /* TODO */ RPAREN
+;
+
+// Match unmark action
+// Returns ???
+match_unmark_action
+	[const Corpus2::Tagset& tagset, Variables& vars]
+	returns [boost::shared_ptr<MatchAction> m_act]
+	: "unmark" LPAREN /* TODO */ RPAREN
+;
+
+// Match action separated by comma
+// Returns boost::shared_ptr<std::vector<boost::shared_ptr<MatchAction> > >
+match_action_comma_sep
+	[const Corpus2::Tagset& tagset, Variables& vars]
+	returns [boost::shared_ptr<std::vector<boost::shared_ptr<MatchAction> > > r_vec]
+{
+	boost::shared_ptr<MatchAction> act;
+
+	r_vec.reset(
+		new std::vector<boost::shared_ptr<MatchAction> >
+	);
+}
+	: act = match_action [tagset, vars] {
+			r_vec->push_back(act);
+	}
+	(
+		COMMA act = match_action [tagset, vars] {
+			r_vec->push_back(act);
+		}
+	)*
+;
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 // ANTLR LEXER