Parse attributes on expressions
diff --git a/src/expr.rs b/src/expr.rs
index a90470e..ebf3b5a 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1391,21 +1391,23 @@
     #[cfg(feature = "full")]
     named!(unary_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
         do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
             op: syn!(UnOp) >>
             expr: call!(unary_expr, allow_struct, true) >>
             (ExprUnary {
-                attrs: Vec::new(),
+                attrs: attrs,
                 op: op,
                 expr: Box::new(expr),
             }.into())
         )
         |
         do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
             and: punct!(&) >>
             mutability: option!(keyword!(mut)) >>
             expr: call!(unary_expr, allow_struct, true) >>
             (ExprReference {
-                attrs: Vec::new(),
+                attrs: attrs,
                 and_token: and,
                 mutability: mutability,
                 expr: Box::new(expr),
@@ -1413,10 +1415,11 @@
         )
         |
         do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
             box_: keyword!(box) >>
             expr: call!(unary_expr, allow_struct, true) >>
             (ExprBox {
-                attrs: Vec::new(),
+                attrs: attrs,
                 box_token: box_,
                 expr: Box::new(expr),
             }.into())
@@ -1441,6 +1444,19 @@
         call!(trailer_expr, allow_struct, allow_block)
     ));
 
+    fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
+        let mut outer = Vec::new();
+        let mut inner = Vec::new();
+        for attr in mem::replace(attrs, Vec::new()) {
+            match attr.style {
+                AttrStyle::Outer => outer.push(attr),
+                AttrStyle::Inner(_) => inner.push(attr),
+            }
+        }
+        *attrs = inner;
+        outer
+    }
+
     // <atom> (..<args>) ...
     // <atom> . <ident> (..<args>) ...
     // <atom> . <ident> ...
@@ -1450,6 +1466,12 @@
     #[cfg(feature = "full")]
     named!(trailer_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
         mut e: call!(atom_expr, allow_struct, allow_block) >>
+        outer_attrs: value!({
+            let mut attrs = e.replace_attrs(Vec::new());
+            let outer_attrs = take_outer(&mut attrs);
+            e.replace_attrs(attrs);
+            outer_attrs
+        }) >>
         many0!(alt!(
             tap!(args: and_call => {
                 let (paren, args) = args;
@@ -1495,7 +1517,12 @@
                 }.into();
             })
         )) >>
-        (e)
+        ({
+            let mut attrs = outer_attrs;
+            attrs.extend(e.replace_attrs(Vec::new()));
+            e.replace_attrs(attrs);
+            e
+        })
     ));
 
     // XXX: Duplication == ugly
@@ -1650,9 +1677,10 @@
     #[cfg(feature = "full")]
     impl Synom for ExprMacro {
         named!(parse -> Self, do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
             mac: syn!(Macro) >>
             (ExprMacro {
-                attrs: Vec::new(),
+                attrs: attrs,
                 mac: mac,
             })
         ));
@@ -1680,11 +1708,19 @@
 
     impl Synom for ExprParen {
         named!(parse -> Self, do_parse!(
-            e: parens!(syn!(Expr)) >>
+            outer_attrs: many0!(Attribute::parse_outer) >>
+            e: parens!(tuple!(
+                many0!(Attribute::parse_inner),
+                syn!(Expr)
+            )) >>
             (ExprParen {
-                attrs: Vec::new(),
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((e.1).0);
+                    attrs
+                },
                 paren_token: e.0,
-                expr: Box::new(e.1),
+                expr: Box::new((e.1).1),
             })
         ));
 
@@ -1696,11 +1732,19 @@
     #[cfg(feature = "full")]
     impl Synom for ExprArray {
         named!(parse -> Self, do_parse!(
-            elems: brackets!(Punctuated::parse_terminated) >>
+            outer_attrs: many0!(Attribute::parse_outer) >>
+            elems: brackets!(tuple!(
+                many0!(Attribute::parse_inner),
+                call!(Punctuated::parse_terminated)
+            )) >>
             (ExprArray {
-                attrs: Vec::new(),
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((elems.1).0);
+                    attrs
+                },
                 bracket_token: elems.0,
-                elems: elems.1,
+                elems: (elems.1).1,
             })
         ));
 
@@ -1758,10 +1802,18 @@
     #[cfg(feature = "full")]
     impl Synom for ExprTuple {
         named!(parse -> Self, do_parse!(
-            elems: parens!(Punctuated::parse_terminated) >>
+            outer_attrs: many0!(Attribute::parse_outer) >>
+            elems: parens!(tuple!(
+                many0!(Attribute::parse_inner),
+                call!(Punctuated::parse_terminated)
+            )) >>
             (ExprTuple {
-                attrs: Vec::new(),
-                elems: elems.1,
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((elems.1).0);
+                    attrs
+                },
+                elems: (elems.1).1,
                 paren_token: elems.0,
             })
         ));
@@ -1850,20 +1902,31 @@
     #[cfg(feature = "full")]
     impl Synom for ExprForLoop {
         named!(parse -> Self, do_parse!(
+            outer_attrs: many0!(Attribute::parse_outer) >>
             label: option!(syn!(Label)) >>
             for_: keyword!(for) >>
             pat: syn!(Pat) >>
             in_: keyword!(in) >>
             expr: expr_no_struct >>
-            loop_block: syn!(Block) >>
+            block: braces!(tuple!(
+                many0!(Attribute::parse_inner),
+                call!(Block::parse_within)
+            )) >>
             (ExprForLoop {
-                attrs: Vec::new(),
-                for_token: for_,
-                in_token: in_,
-                pat: Box::new(pat),
-                expr: Box::new(expr),
-                body: loop_block,
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((block.1).0);
+                    attrs
+                },
                 label: label,
+                for_token: for_,
+                pat: Box::new(pat),
+                in_token: in_,
+                expr: Box::new(expr),
+                body: Block {
+                    brace_token: block.0,
+                    stmts: (block.1).1,
+                },
             })
         ));
 
@@ -1875,14 +1938,25 @@
     #[cfg(feature = "full")]
     impl Synom for ExprLoop {
         named!(parse -> Self, do_parse!(
+            outer_attrs: many0!(Attribute::parse_outer) >>
             label: option!(syn!(Label)) >>
             loop_: keyword!(loop) >>
-            loop_block: syn!(Block) >>
+            block: braces!(tuple!(
+                many0!(Attribute::parse_inner),
+                call!(Block::parse_within)
+            )) >>
             (ExprLoop {
-                attrs: Vec::new(),
-                loop_token: loop_,
-                body: loop_block,
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((block.1).0);
+                    attrs
+                },
                 label: label,
+                loop_token: loop_,
+                body: Block {
+                    brace_token: block.0,
+                    stmts: (block.1).1,
+                },
             })
         ));
 
@@ -1894,15 +1968,23 @@
     #[cfg(feature = "full")]
     impl Synom for ExprMatch {
         named!(parse -> Self, do_parse!(
+            outer_attrs: many0!(Attribute::parse_outer) >>
             match_: keyword!(match) >>
             obj: expr_no_struct >>
-            res: braces!(many0!(Arm::parse)) >>
+            braced_content: braces!(tuple!(
+                many0!(Attribute::parse_inner),
+                many0!(syn!(Arm))
+            )) >>
             (ExprMatch {
-                attrs: Vec::new(),
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((braced_content.1).0);
+                    attrs
+                },
                 expr: Box::new(obj),
                 match_token: match_,
-                brace_token: res.0,
-                arms: res.1,
+                brace_token: braced_content.0,
+                arms: (braced_content.1).1,
             })
         ));
 
@@ -2038,16 +2120,27 @@
     #[cfg(feature = "full")]
     impl Synom for ExprWhile {
         named!(parse -> Self, do_parse!(
+            outer_attrs: many0!(Attribute::parse_outer) >>
             label: option!(syn!(Label)) >>
             while_: keyword!(while) >>
             cond: expr_no_struct >>
-            while_block: syn!(Block) >>
+            block: braces!(tuple!(
+                many0!(Attribute::parse_inner),
+                call!(Block::parse_within)
+            )) >>
             (ExprWhile {
-                attrs: Vec::new(),
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((block.1).0);
+                    attrs
+                },
+                label: label,
                 while_token: while_,
                 cond: Box::new(cond),
-                body: while_block,
-                label: label,
+                body: Block {
+                    brace_token: block.0,
+                    stmts: (block.1).1,
+                },
             })
         ));
 
@@ -2059,22 +2152,33 @@
     #[cfg(feature = "full")]
     impl Synom for ExprWhileLet {
         named!(parse -> Self, do_parse!(
+            outer_attrs: many0!(Attribute::parse_outer) >>
             label: option!(syn!(Label)) >>
             while_: keyword!(while) >>
             let_: keyword!(let) >>
             pats: call!(Punctuated::parse_separated_nonempty) >>
             eq: punct!(=) >>
             value: expr_no_struct >>
-            while_block: syn!(Block) >>
+            block: braces!(tuple!(
+                many0!(Attribute::parse_inner),
+                call!(Block::parse_within)
+            )) >>
             (ExprWhileLet {
-                attrs: Vec::new(),
-                eq_token: eq,
-                let_token: let_,
-                while_token: while_,
-                pats: pats,
-                expr: Box::new(value),
-                body: while_block,
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((block.1).0);
+                    attrs
+                },
                 label: label,
+                while_token: while_,
+                let_token: let_,
+                pats: pats,
+                eq_token: eq,
+                expr: Box::new(value),
+                body: Block {
+                    brace_token: block.0,
+                    stmts: (block.1).1,
+                },
             })
         ));
 
@@ -2102,10 +2206,11 @@
     #[cfg(feature = "full")]
     impl Synom for ExprContinue {
         named!(parse -> Self, do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
             cont: keyword!(continue) >>
             label: option!(syn!(Lifetime)) >>
             (ExprContinue {
-                attrs: Vec::new(),
+                attrs: attrs,
                 continue_token: cont,
                 label: label,
             })
@@ -2118,13 +2223,14 @@
 
     #[cfg(feature = "full")]
     named!(expr_break(allow_struct: bool) -> Expr, do_parse!(
+        attrs: many0!(Attribute::parse_outer) >>
         break_: keyword!(break) >>
         label: option!(syn!(Lifetime)) >>
         // We can't allow blocks after a `break` expression when we wouldn't
         // allow structs, as this expression is ambiguous.
         val: opt_ambiguous_expr!(allow_struct) >>
         (ExprBreak {
-            attrs: Vec::new(),
+            attrs: attrs,
             label: label,
             expr: val.map(Box::new),
             break_token: break_,
@@ -2133,6 +2239,7 @@
 
     #[cfg(feature = "full")]
     named!(expr_ret(allow_struct: bool) -> Expr, do_parse!(
+        attrs: many0!(Attribute::parse_outer) >>
         return_: keyword!(return) >>
         // NOTE: return is greedy and eats blocks after it even when in a
         // position where structs are not allowed, such as in if statement
@@ -2141,7 +2248,7 @@
         // if return { println!("A") } {} // Prints "A"
         ret_value: option!(ambiguous_expr!(allow_struct)) >>
         (ExprReturn {
-            attrs: Vec::new(),
+            attrs: attrs,
             expr: ret_value.map(Box::new),
             return_token: return_,
         }.into())
@@ -2150,24 +2257,30 @@
     #[cfg(feature = "full")]
     impl Synom for ExprStruct {
         named!(parse -> Self, do_parse!(
+            outer_attrs: many0!(Attribute::parse_outer) >>
             path: syn!(Path) >>
             data: braces!(do_parse!(
+                inner_attrs: many0!(Attribute::parse_inner) >>
                 fields: call!(Punctuated::parse_terminated) >>
                 base: option!(cond!(fields.empty_or_trailing(), do_parse!(
                     dots: punct!(..) >>
                     base: syn!(Expr) >>
                     (dots, base)
                 ))) >>
-                (fields, base)
+                (inner_attrs, fields, base)
             )) >>
             ({
-                let (brace, (fields, base)) = data;
+                let (brace, (inner_attrs, fields, base)) = data;
                 let (dots, rest) = match base.and_then(|b| b) {
                     Some((dots, base)) => (Some(dots), Some(base)),
                     None => (None, None),
                 };
                 ExprStruct {
-                    attrs: Vec::new(),
+                    attrs: {
+                        let mut attrs = outer_attrs;
+                        attrs.extend(inner_attrs);
+                        attrs
+                    },
                     brace_token: brace,
                     path: path,
                     fields: fields,
@@ -2215,18 +2328,23 @@
     #[cfg(feature = "full")]
     impl Synom for ExprRepeat {
         named!(parse -> Self, do_parse!(
-            data: brackets!(do_parse!(
-                value: syn!(Expr) >>
-                semi: punct!(;) >>
-                times: syn!(Expr) >>
-                (value, semi, times)
+            outer_attrs: many0!(Attribute::parse_outer) >>
+            data: brackets!(tuple!(
+                many0!(Attribute::parse_inner),
+                syn!(Expr),
+                punct!(;),
+                syn!(Expr)
             )) >>
             (ExprRepeat {
-                attrs: Vec::new(),
-                expr: Box::new((data.1).0),
-                len: Box::new((data.1).2),
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((data.1).0);
+                    attrs
+                },
+                expr: Box::new((data.1).1),
+                len: Box::new((data.1).3),
                 bracket_token: data.0,
-                semi_token: (data.1).1,
+                semi_token: (data.1).2,
             })
         ));
 
@@ -2255,10 +2373,21 @@
     #[cfg(feature = "full")]
     impl Synom for ExprBlock {
         named!(parse -> Self, do_parse!(
-            b: syn!(Block) >>
+            outer_attrs: many0!(Attribute::parse_outer) >>
+            block: braces!(tuple!(
+                many0!(Attribute::parse_inner),
+                call!(Block::parse_within)
+            )) >>
             (ExprBlock {
-                attrs: Vec::new(),
-                block: b,
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((block.1).0);
+                    attrs
+                },
+                block: Block {
+                    brace_token: block.0,
+                    stmts: (block.1).1,
+                },
             })
         ));
 
@@ -2422,10 +2551,11 @@
 
     #[cfg(feature = "full")]
     named!(stmt_blockexpr -> Stmt, do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
+        mut attrs: many0!(Attribute::parse_outer) >>
         mut e: expr_nosemi >>
         semi: option!(punct!(;)) >>
         ({
+            attrs.extend(e.replace_attrs(Vec::new()));
             e.replace_attrs(attrs);
             if let Some(semi) = semi {
                 Stmt::Semi(e, semi)
@@ -2437,10 +2567,11 @@
 
     #[cfg(feature = "full")]
     named!(stmt_expr -> Stmt, do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
+        mut attrs: many0!(Attribute::parse_outer) >>
         mut e: syn!(Expr) >>
         semi: punct!(;) >>
         ({
+            attrs.extend(e.replace_attrs(Vec::new()));
             e.replace_attrs(attrs);
             Stmt::Semi(e, semi)
         })
@@ -2879,6 +3010,7 @@
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(self.attrs.outer());
             self.bracket_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
                 self.elems.to_tokens(tokens);
             })
         }
@@ -2933,6 +3065,7 @@
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(self.attrs.outer());
             self.paren_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
                 self.elems.to_tokens(tokens);
                 // If we only have one argument, we need a trailing comma to
                 // distinguish ExprTuple from ExprParen.
@@ -3038,7 +3171,10 @@
             self.label.to_tokens(tokens);
             self.while_token.to_tokens(tokens);
             wrap_bare_struct(tokens, &self.cond);
-            self.body.to_tokens(tokens);
+            self.body.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.body.stmts);
+            });
         }
     }
 
@@ -3052,7 +3188,10 @@
             self.pats.to_tokens(tokens);
             self.eq_token.to_tokens(tokens);
             wrap_bare_struct(tokens, &self.expr);
-            self.body.to_tokens(tokens);
+            self.body.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.body.stmts);
+            });
         }
     }
 
@@ -3065,7 +3204,10 @@
             self.pat.to_tokens(tokens);
             self.in_token.to_tokens(tokens);
             wrap_bare_struct(tokens, &self.expr);
-            self.body.to_tokens(tokens);
+            self.body.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.body.stmts);
+            });
         }
     }
 
@@ -3075,7 +3217,10 @@
             tokens.append_all(self.attrs.outer());
             self.label.to_tokens(tokens);
             self.loop_token.to_tokens(tokens);
-            self.body.to_tokens(tokens);
+            self.body.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.body.stmts);
+            });
         }
     }
 
@@ -3086,6 +3231,7 @@
             self.match_token.to_tokens(tokens);
             wrap_bare_struct(tokens, &self.expr);
             self.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
                 for (i, arm) in self.arms.iter().enumerate() {
                     arm.to_tokens(tokens);
                     // Ensure that we have a comma after a non-block arm, except
@@ -3157,7 +3303,10 @@
     impl ToTokens for ExprBlock {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(self.attrs.outer());
-            self.block.to_tokens(tokens);
+            self.block.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.block.stmts);
+            });
         }
     }
 
@@ -3290,6 +3439,7 @@
             tokens.append_all(self.attrs.outer());
             self.path.to_tokens(tokens);
             self.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
                 self.fields.to_tokens(tokens);
                 if self.rest.is_some() {
                     TokensOrDefault(&self.dot2_token).to_tokens(tokens);
@@ -3304,6 +3454,7 @@
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(self.attrs.outer());
             self.bracket_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
                 self.expr.to_tokens(tokens);
                 self.semi_token.to_tokens(tokens);
                 self.len.to_tokens(tokens);
@@ -3325,6 +3476,7 @@
         fn to_tokens(&self, tokens: &mut TokenStream) {
             attrs_to_tokens(&self.attrs, tokens);
             self.paren_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
                 self.expr.to_tokens(tokens);
             });
         }