Struct patterns
diff --git a/src/expr.rs b/src/expr.rs
index 9e45a64..9c3d2b4 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -881,12 +881,13 @@
         |
         pat_tuple_struct // must be before pat_ident
         |
+        pat_struct // must be before pat_ident
+        |
         pat_mac // must be before pat_ident
         |
         pat_ident // must be before pat_path
         |
         pat_path
-    // TODO: Struct
         |
         pat_tuple
         |
@@ -930,6 +931,50 @@
         (Pat::TupleStruct(path, tuple.0, tuple.1))
     ));
 
+    named!(pat_struct -> Pat, do_parse!(
+        path: path >>
+        punct!("{") >>
+        fields: separated_list!(punct!(","), field_pat) >>
+        more: option!(preceded!(
+            cond!(!fields.is_empty(), punct!(",")),
+            punct!("..")
+        )) >>
+        punct!("}") >>
+        (Pat::Struct(path, fields, more.is_some()))
+    ));
+
+    named!(field_pat -> FieldPat, alt!(
+        do_parse!(
+            ident: ident >>
+            punct!(":") >>
+            pat: pat >>
+            (FieldPat {
+                ident: ident,
+                pat: Box::new(pat),
+                is_shorthand: false,
+            })
+        )
+        |
+        do_parse!(
+            mode: option!(keyword!("ref")) >>
+            mutability: mutability >>
+            ident: ident >>
+            (FieldPat {
+                ident: ident.clone(),
+                pat: Box::new(Pat::Ident(
+                    if mode.is_some() {
+                        BindingMode::ByRef(mutability)
+                    } else {
+                        BindingMode::ByValue(mutability)
+                    },
+                    ident,
+                    None,
+                )),
+                is_shorthand: true,
+            })
+        )
+    ));
+
     named!(pat_path -> Pat, map!(qpath, |(qself, path)| Pat::Path(qself, path)));
 
     named!(pat_tuple -> Pat, map!(
@@ -1372,7 +1417,18 @@
                         subpat.to_tokens(tokens);
                     }
                 }
-                Pat::Struct(ref _path, ref _fields, _dots) => unimplemented!(),
+                Pat::Struct(ref path, ref fields, dots) => {
+                    path.to_tokens(tokens);
+                    tokens.append("{");
+                    tokens.append_separated(fields, ",");
+                    if dots {
+                        if !fields.is_empty() {
+                            tokens.append(",");
+                        }
+                        tokens.append("..");
+                    }
+                    tokens.append("}");
+                }
                 Pat::TupleStruct(ref path, ref pats, dotpos) => {
                     path.to_tokens(tokens);
                     tokens.append("(");
@@ -1453,6 +1509,16 @@
         }
     }
 
+    impl ToTokens for FieldPat {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            if !self.is_shorthand {
+                self.ident.to_tokens(tokens);
+                tokens.append(":");
+            }
+            self.pat.to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for BindingMode {
         fn to_tokens(&self, tokens: &mut Tokens) {
             match *self {