Match parsing
diff --git a/src/expr.rs b/src/expr.rs
index ed33b3e..1824922 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -337,10 +337,11 @@
 pub mod parsing {
     use super::*;
     use {Ident, Lifetime, Ty};
+    use attr::parsing::outer_attr;
     use generics::parsing::lifetime;
     use ident::parsing::ident;
     use lit::parsing::lit;
-    use ty::parsing::ty;
+    use ty::parsing::{mutability, ty};
 
     named!(pub expr -> Expr, do_parse!(
         mut e: alt!(
@@ -364,7 +365,8 @@
             // TODO: ForLoop
             |
             expr_loop
-            // TODO: Match
+            |
+            expr_match
             // TODO: Closure
             |
             expr_block
@@ -561,6 +563,31 @@
         ))
     ));
 
+    named!(expr_match -> Expr, do_parse!(
+        keyword!("match") >>
+        obj: expr >>
+        punct!("{") >>
+        arms: many0!(do_parse!(
+            attrs: many0!(outer_attr) >>
+            pats: separated_nonempty_list!(punct!("|"), pat) >>
+            guard: option!(preceded!(keyword!("if"), expr)) >>
+            punct!("=>") >>
+            body: alt!(
+                terminated!(expr, punct!(","))
+                |
+                map!(block, |blk| Expr::Block(Box::new(blk)))
+            ) >>
+            (Arm {
+                attrs: attrs,
+                pats: pats,
+                guard: guard.map(Box::new),
+                body: Box::new(body),
+            })
+        )) >>
+        punct!("}") >>
+        (Expr::Match(Box::new(obj), arms))
+    ));
+
     named!(expr_while -> Expr, do_parse!(
         lbl: option!(terminated!(label, punct!(":"))) >>
         keyword!("while") >>
@@ -642,12 +669,47 @@
         (Stmt::Semi(Box::new(e)))
     ));
 
+    named!(pat -> Pat, alt!(
+        pat_wild
+        |
+        pat_ident
+        // TODO: Struct
+        // TODO: TupleStruct
+        // TODO: Path
+        // TODO: Tuple
+        // TODO: Box
+        // TODO: Ref
+        // TODO: Lit
+        // TODO: Range
+        // TODO: Vec
+        // TODO: Mac
+    ));
+
+    named!(pat_wild -> Pat, map!(keyword!("_"), |_| Pat::Wild));
+
+    named!(pat_ident -> Pat, do_parse!(
+        mode: option!(keyword!("ref")) >>
+        mutability: mutability >>
+        name: ident >>
+        subpat: option!(preceded!(punct!("@"), pat)) >>
+        (Pat::Ident(
+            if mode.is_some() {
+                BindingMode::ByRef(mutability)
+            } else {
+                BindingMode::ByValue(mutability)
+            },
+            name,
+            subpat.map(Box::new),
+        ))
+    ));
+
     named!(label -> Ident, map!(lifetime, |lt: Lifetime| lt.ident));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
+    use Mutability;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Expr {
@@ -676,7 +738,13 @@
                 Expr::WhileLet(ref _pat, ref _expr, ref _body, ref _label) => unimplemented!(),
                 Expr::ForLoop(ref _pat, ref _expr, ref _body, ref _label) => unimplemented!(),
                 Expr::Loop(ref _body, ref _label) => unimplemented!(),
-                Expr::Match(ref _expr, ref _arms) => unimplemented!(),
+                Expr::Match(ref expr, ref arms) => {
+                    tokens.append("match");
+                    expr.to_tokens(tokens);
+                    tokens.append("{");
+                    tokens.append_separated(arms, ",");
+                    tokens.append("}");
+                }
                 Expr::Closure(_capture, ref _decl, ref _body) => unimplemented!(),
                 Expr::Block(ref _block) => unimplemented!(),
                 Expr::Assign(ref _var, ref _expr) => unimplemented!(),
@@ -698,4 +766,67 @@
             }
         }
     }
+
+    impl ToTokens for Arm {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            for attr in &self.attrs {
+                attr.to_tokens(tokens);
+            }
+            tokens.append_separated(&self.pats, "|");
+            if let Some(ref guard) = self.guard {
+                tokens.append("if");
+                guard.to_tokens(tokens);
+            }
+            tokens.append("=>");
+            self.body.to_tokens(tokens);
+            match *self.body {
+                Expr::Block(_) => { /* no comma */ }
+                _ => tokens.append(","),
+            }
+        }
+    }
+
+    impl ToTokens for Pat {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                Pat::Wild => tokens.append("_"),
+                Pat::Ident(mode, ref ident, ref subpat) => {
+                    mode.to_tokens(tokens);
+                    ident.to_tokens(tokens);
+                    if let Some(ref subpat) = *subpat {
+                        tokens.append("@");
+                        subpat.to_tokens(tokens);
+                    }
+                }
+                Pat::Struct(ref _path, ref _fields, _dots) => unimplemented!(),
+                Pat::TupleStruct(ref _path, ref _pats, _dotpos) => unimplemented!(),
+                Pat::Path(ref _qself, ref _path) => unimplemented!(),
+                Pat::Tuple(ref _pats, _dotpos) => unimplemented!(),
+                Pat::Box(ref _inner) => unimplemented!(),
+                Pat::Ref(ref _target, _mutability) => unimplemented!(),
+                Pat::Lit(ref _expr) => unimplemented!(),
+                Pat::Range(ref _lower, ref _upper) => unimplemented!(),
+                Pat::Vec(ref _before, ref _dots, ref _after) => unimplemented!(),
+                Pat::Mac(ref _mac) => unimplemented!(),
+            }
+        }
+    }
+
+    impl ToTokens for BindingMode {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                BindingMode::ByRef(Mutability::Immutable) => {
+                    tokens.append("ref");
+                }
+                BindingMode::ByRef(Mutability::Mutable) => {
+                    tokens.append("ref");
+                    tokens.append("mut");
+                }
+                BindingMode::ByValue(Mutability::Immutable) => {}
+                BindingMode::ByValue(Mutability::Mutable) => {
+                    tokens.append("mut");
+                }
+            }
+        }
+    }
 }