diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h
index 1bf5f3bae5..4f032bce58 100644
--- a/Zend/zend_ast.h
+++ b/Zend/zend_ast.h
@@ -47,6 +47,7 @@ enum _zend_ast_kind {
 	ZEND_AST_EXPR_LIST,
 	ZEND_AST_STMT_LIST,
 	ZEND_AST_IF,
+	ZEND_AST_MATCH_LIST,
 	ZEND_AST_SWITCH_LIST,
 	ZEND_AST_CATCH_LIST,
 	ZEND_AST_PARAM_LIST,
@@ -57,6 +58,7 @@ enum _zend_ast_kind {
 	ZEND_AST_NAME_LIST,
 	ZEND_AST_TRAIT_ADAPTATIONS,
 	ZEND_AST_USE,
+        ZEND_AST_PATTERN_ARRAY,
 
 	/* 0 child nodes */
 	ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT,
@@ -120,6 +122,8 @@ enum _zend_ast_kind {
 	ZEND_AST_WHILE,
 	ZEND_AST_DO_WHILE,
 	ZEND_AST_IF_ELEM,
+        ZEND_AST_MATCH,
+        ZEND_AST_MATCH_CASE,
 	ZEND_AST_SWITCH,
 	ZEND_AST_SWITCH_CASE,
 	ZEND_AST_DECLARE,
@@ -131,6 +135,10 @@ enum _zend_ast_kind {
 	ZEND_AST_TRAIT_ALIAS,
 	ZEND_AST_GROUP_USE,
 
+        ZEND_AST_PATTERN_SCALAR,
+        ZEND_AST_PATTERN_TYPE,
+	ZEND_AST_PATTERN_ARRAY_ELEM,
+        
 	/* 3 child nodes */
 	ZEND_AST_METHOD_CALL = 3 << ZEND_AST_NUM_CHILDREN_SHIFT,
 	ZEND_AST_STATIC_CALL,
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 63359dfa39..b4111b43a5 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -4590,6 +4590,81 @@ void zend_compile_if(zend_ast *ast) /* {{{ */
 }
 /* }}} */
 
+static zend_ast* ast_create_empty_array(uint32_t lineno)
+{
+	zend_ast *array = zend_ast_create_list(0, ZEND_AST_ARRAY);
+	array->lineno = lineno;
+	return array;
+}
+
+static zend_ast* ast_create_true(uint32_t lineno)
+{
+	zend_ast_zval *val = malloc(sizeof(zend_ast_zval));
+	val->kind = ZEND_AST_ZVAL;
+	val->attr = 0;
+	val->val.u2.lineno = lineno;
+	ZVAL_TRUE(&val->val);
+
+	return (zend_ast*) val;
+}
+
+static zend_ast* ast_create_assign(uint32_t lineno, zend_ast* right, const char* var_name, unsigned int var_length)
+{
+	zend_ast *assign = malloc(sizeof(zend_ast) + sizeof(zend_ast*));
+	assign->kind = ZEND_AST_ASSIGN;
+	assign->attr = 0;
+	assign->lineno = lineno;
+	assign->child[1] = right;
+
+	zend_ast *var = malloc(sizeof(zend_ast));
+	var->kind = ZEND_AST_VAR;
+	var->attr = 0;
+	var->lineno = lineno;
+	zend_ast_zval *val = malloc(sizeof(zend_ast_zval));
+	val->kind = ZEND_AST_ZVAL;
+	val->attr = 0;
+	val->val.u2.lineno = lineno;
+	ZVAL_NEW_STR(&val->val, zend_string_init(var_name, var_length, 0));
+	var->child[0] = (zend_ast*) val;
+	assign->child[0] = var;
+
+	return assign;
+}
+
+static zend_ast* ast_create_if(uint32_t lineno, zend_ast* test, zend_ast* then)
+{
+	zend_ast* _if = zend_ast_create_list(1, ZEND_AST_IF,
+										 zend_ast_create(ZEND_AST_IF_ELEM, test, then)
+										 );
+	_if->lineno = lineno;
+
+	return _if;
+}
+
+static zend_ast* ast_create_if_else(uint32_t lineno, zend_ast* test, zend_ast* then, zend_ast* _else)
+{
+	zend_ast* _if = zend_ast_create_list(2, ZEND_AST_IF,
+										 zend_ast_create(ZEND_AST_IF_ELEM, test, then),
+										 zend_ast_create(ZEND_AST_IF_ELEM, NULL, _else)
+										 );
+	_if->lineno = lineno;
+
+	return _if;
+}
+
+void zend_compile_match(zend_ast *ast) /* {{{ */
+{
+	zend_ast *match_expr = ast_create_assign(ast->lineno, ast->child[0], "__MATCH__expr", 13);
+	zend_compile_stmt(match_expr);
+
+	zend_ast *match_variables = ast_create_assign(ast->lineno, ast_create_empty_array(ast->lineno), "__MATCH__variables", 18);
+	zend_compile_stmt(match_variables);
+
+	zend_ast *match_result = ast_create_assign(ast->lineno, ast_create_true(ast->lineno), "__MATCH__result", 15);
+	zend_compile_stmt(match_result);
+}
+/* }}} */
+
 void zend_compile_switch(zend_ast *ast) /* {{{ */
 {
 	zend_ast *expr_ast = ast->child[0];
@@ -7793,6 +7868,9 @@ void zend_compile_stmt(zend_ast *ast) /* {{{ */
 		case ZEND_AST_IF:
 			zend_compile_if(ast);
 			break;
+		case ZEND_AST_MATCH:
+			zend_compile_match(ast);
+			break;
 		case ZEND_AST_SWITCH:
 			zend_compile_switch(ast);
 			break;
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 3c7117930e..07876bae15 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -158,6 +158,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
 %token T_DECLARE    "declare (T_DECLARE)"
 %token T_ENDDECLARE "enddeclare (T_ENDDECLARE)"
 %token T_AS         "as (T_AS)"
+%token T_MATCH      "match (T_MATCH)"
 %token T_SWITCH     "switch (T_SWITCH)"
 %token T_ENDSWITCH  "endswitch (T_ENDSWITCH)"
 %token T_CASE       "case (T_CASE)"
@@ -253,6 +254,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
 %type <ast> array_pair non_empty_array_pair_list array_pair_list possible_array_pair
 %type <ast> isset_variable type return_type type_expr
 %type <ast> identifier
+%type <ast> match_case_list match_pattern as_pattern scalar_pattern array_pair_list_pattern array_pair_pattern
 
 %type <num> returns_ref function is_reference is_variadic variable_modifiers
 %type <num> method_modifiers non_empty_member_modifiers member_modifier
@@ -273,7 +275,7 @@ reserved_non_modifiers:
 	| T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
 	| T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK
 	| T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
-	| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C
+	| T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_MATCH
 ;
 
 semi_reserved:
@@ -426,6 +428,8 @@ statement:
 			{ $$ = zend_ast_create(ZEND_AST_FOR, $3, $5, $7, $9); }
 	|	T_SWITCH '(' expr ')' switch_case_list
 			{ $$ = zend_ast_create(ZEND_AST_SWITCH, $3, $5); }
+	|	T_MATCH '(' expr ')' '{' match_case_list '}'
+			{ $$ = zend_ast_create(ZEND_AST_MATCH, $3, $6); }
 	|	T_BREAK optional_expr ';'		{ $$ = zend_ast_create(ZEND_AST_BREAK, $2); }
 	|	T_CONTINUE optional_expr ';'	{ $$ = zend_ast_create(ZEND_AST_CONTINUE, $2); }
 	|	T_RETURN optional_expr ';'		{ $$ = zend_ast_create(ZEND_AST_RETURN, $2); }
@@ -578,6 +582,59 @@ case_list:
 			{ $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_SWITCH_CASE, NULL, $4)); }
 ;
 
+as_pattern:
+				/* empty */ { $$ = NULL; }
+		|		T_AS T_VARIABLE { $$ = $2; }
+				;
+
+array_pair_list_pattern:
+				array_pair_list_pattern ',' array_pair_pattern
+				{ $$ = zend_ast_list_add($1, $3); }
+		|		array_pair_pattern
+				{ $$ = zend_ast_create_list(1, ZEND_AST_PATTERN_ARRAY, $1); }
+				;
+
+array_pair_pattern:
+				T_LNUMBER T_DOUBLE_ARROW match_pattern
+				{ $$ = zend_ast_create(ZEND_AST_PATTERN_ARRAY_ELEM, $3, $1); }
+		|		T_CONSTANT_ENCAPSED_STRING T_DOUBLE_ARROW match_pattern
+				{ $$ = zend_ast_create(ZEND_AST_PATTERN_ARRAY_ELEM, $3, $1); }
+		|	match_pattern
+				{ $$ = zend_ast_create(ZEND_AST_PATTERN_ARRAY_ELEM, $1, NULL); }
+				;
+
+scalar_pattern:
+				T_LNUMBER { $$ = $1; }
+		|		T_DNUMBER { $$ = $1; }
+		|		T_CONSTANT_ENCAPSED_STRING { $$ = $1; }
+				/* for true, false, null */
+		|		T_STRING { $$ = $1; }
+				;
+
+match_pattern:
+                scalar_pattern as_pattern
+                { $$ = zend_ast_create(ZEND_AST_PATTERN_SCALAR, $1, $2); }
+		|		T_ARRAY '(' ')' as_pattern
+				{ $$ = zend_ast_create_list(1, ZEND_AST_PATTERN_ARRAY, $4); $$->attr = ZEND_ARRAY_SYNTAX_LONG; }
+		|		T_ARRAY '(' array_pair_list_pattern ')' as_pattern
+				{ $$ = $3; zend_ast_list_add($$, $5); $$->attr = ZEND_ARRAY_SYNTAX_LONG; }
+        |       T_STRING '(' ')' as_pattern
+                { $$ = zend_ast_create(ZEND_AST_PATTERN_TYPE, $1, $4); }
+		|		'[' ']' as_pattern
+				{ $$ = zend_ast_create_list(1, ZEND_AST_PATTERN_ARRAY, $3); $$->attr = ZEND_ARRAY_SYNTAX_SHORT; }
+		|		'['array_pair_list_pattern ']' as_pattern
+				{ $$ = $2; zend_ast_list_add($$, $4); $$->attr = ZEND_ARRAY_SYNTAX_SHORT; }
+				;
+
+match_case_list:
+				/* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_MATCH_LIST); }
+		|		match_case_list T_CASE match_pattern case_separator inner_statement_list
+				{ $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_MATCH_CASE, $3, $5)); }
+		|		match_case_list T_DEFAULT case_separator inner_statement_list
+				{ $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_MATCH_CASE, NULL, $4)); }
+				;
+
+
 case_separator:
 		':'
 	|	';'
