unrest_tmp_syn/
expr.rs

1use super::*;
2use delimited::Delimited;
3
4ast_struct! {
5    /// An expression.
6    pub struct Expr {
7        /// Type of the expression.
8        pub node: ExprKind,
9
10        /// Attributes tagged on the expression.
11        pub attrs: Vec<Attribute>,
12    }
13}
14
15impl From<ExprKind> for Expr {
16    fn from(node: ExprKind) -> Expr {
17        Expr {
18            node: node,
19            attrs: Vec::new(),
20        }
21    }
22}
23
24ast_enum_of_structs! {
25    pub enum ExprKind {
26        /// A `box x` expression.
27        pub Box(ExprBox #full {
28            pub expr: Box<Expr>,
29            pub box_token: tokens::Box_,
30        }),
31
32        /// E.g. 'place <- val' or `in place { val }`.
33        pub InPlace(ExprInPlace #full {
34            pub place: Box<Expr>,
35            pub kind: InPlaceKind,
36            pub value: Box<Expr>,
37        }),
38
39        /// An array, e.g. `[a, b, c, d]`.
40        pub Array(ExprArray #full {
41            pub exprs: Delimited<Expr, tokens::Comma>,
42            pub bracket_token: tokens::Bracket,
43        }),
44
45        /// A function call.
46        pub Call(ExprCall {
47            pub func: Box<Expr>,
48            pub args: Delimited<Expr, tokens::Comma>,
49            pub paren_token: tokens::Paren,
50        }),
51
52        /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
53        ///
54        /// The `Ident` is the identifier for the method name.
55        /// The vector of `Ty`s are the ascripted type parameters for the method
56        /// (within the angle brackets).
57        ///
58        /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
59        /// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
60        pub MethodCall(ExprMethodCall #full {
61            pub expr: Box<Expr>,
62            pub method: Ident,
63            pub typarams: Delimited<Ty, tokens::Comma>,
64            pub args: Delimited<Expr, tokens::Comma>,
65            pub paren_token: tokens::Paren,
66            pub dot_token: tokens::Dot,
67            pub lt_token: Option<tokens::Lt>,
68            pub colon2_token: Option<tokens::Colon2>,
69            pub gt_token: Option<tokens::Gt>,
70        }),
71
72        /// A tuple, e.g. `(a, b, c, d)`.
73        pub Tup(ExprTup #full {
74            pub args: Delimited<Expr, tokens::Comma>,
75            pub paren_token: tokens::Paren,
76            pub lone_comma: Option<tokens::Comma>,
77        }),
78
79        /// A binary operation, e.g. `a + b`, `a * b`.
80        pub Binary(ExprBinary {
81            pub op: BinOp,
82            pub left: Box<Expr>,
83            pub right: Box<Expr>,
84        }),
85
86        /// A unary operation, e.g. `!x`, `*x`.
87        pub Unary(ExprUnary {
88            pub op: UnOp,
89            pub expr: Box<Expr>,
90        }),
91
92        /// A literal, e.g. `1`, `"foo"`.
93        pub Lit(Lit),
94
95        /// A cast, e.g. `foo as f64`.
96        pub Cast(ExprCast {
97            pub expr: Box<Expr>,
98            pub as_token: tokens::As,
99            pub ty: Box<Ty>,
100        }),
101
102        /// A type ascription, e.g. `foo: f64`.
103        pub Type(ExprType {
104            pub expr: Box<Expr>,
105            pub colon_token: tokens::Colon,
106            pub ty: Box<Ty>,
107        }),
108
109        /// An `if` block, with an optional else block
110        ///
111        /// E.g., `if expr { block } else { expr }`
112        pub If(ExprIf #full {
113            pub cond: Box<Expr>,
114            pub if_true: Block,
115            pub if_false: Option<Box<Expr>>,
116            pub if_token: tokens::If,
117            pub else_token: Option<tokens::Else>,
118        }),
119
120        /// An `if let` expression with an optional else block
121        ///
122        /// E.g., `if let pat = expr { block } else { expr }`
123        ///
124        /// This is desugared to a `match` expression.
125        pub IfLet(ExprIfLet #full {
126            pub pat: Box<Pat>,
127            pub expr: Box<Expr>,
128            pub if_true: Block,
129            pub if_false: Option<Box<Expr>>,
130            pub if_token: tokens::If,
131            pub let_token: tokens::Let,
132            pub eq_token: tokens::Eq,
133            pub else_token: Option<tokens::Else>,
134        }),
135
136        /// A while loop, with an optional label
137        ///
138        /// E.g., `'label: while expr { block }`
139        pub While(ExprWhile #full {
140            pub cond: Box<Expr>,
141            pub body: Block,
142            pub label: Option<Lifetime>,
143            pub colon_token: Option<tokens::Colon>,
144            pub while_token: tokens::While,
145        }),
146
147        /// A while-let loop, with an optional label.
148        ///
149        /// E.g., `'label: while let pat = expr { block }`
150        ///
151        /// This is desugared to a combination of `loop` and `match` expressions.
152        pub WhileLet(ExprWhileLet #full {
153            pub pat: Box<Pat>,
154            pub expr: Box<Expr>,
155            pub body: Block,
156            pub label: Option<Lifetime>,
157            pub colon_token: Option<tokens::Colon>,
158            pub while_token: tokens::While,
159            pub let_token: tokens::Let,
160            pub eq_token: tokens::Eq,
161        }),
162
163        /// A for loop, with an optional label.
164        ///
165        /// E.g., `'label: for pat in expr { block }`
166        ///
167        /// This is desugared to a combination of `loop` and `match` expressions.
168        pub ForLoop(ExprForLoop #full {
169            pub pat: Box<Pat>,
170            pub expr: Box<Expr>,
171            pub body: Block,
172            pub label: Option<Lifetime>,
173            pub for_token: tokens::For,
174            pub colon_token: Option<tokens::Colon>,
175            pub in_token: tokens::In,
176        }),
177
178        /// Conditionless loop with an optional label.
179        ///
180        /// E.g. `'label: loop { block }`
181        pub Loop(ExprLoop #full {
182            pub body: Block,
183            pub label: Option<Lifetime>,
184            pub loop_token: tokens::Loop,
185            pub colon_token: Option<tokens::Colon>,
186        }),
187
188        /// A `match` block.
189        pub Match(ExprMatch #full {
190            pub match_token: tokens::Match,
191            pub brace_token: tokens::Brace,
192            pub expr: Box<Expr>,
193            pub arms: Vec<Arm>,
194        }),
195
196        /// A closure (for example, `move |a, b, c| a + b + c`)
197        pub Closure(ExprClosure #full {
198            pub capture: CaptureBy,
199            pub decl: Box<FnDecl>,
200            pub body: Box<Expr>,
201            pub or1_token: tokens::Or,
202            pub or2_token: tokens::Or,
203        }),
204
205        /// A block (`{ ... }` or `unsafe { ... }`)
206        pub Block(ExprBlock #full {
207            pub unsafety: Unsafety,
208            pub block: Block,
209        }),
210
211        /// An assignment (`a = foo()`)
212        pub Assign(ExprAssign #full {
213            pub left: Box<Expr>,
214            pub right: Box<Expr>,
215            pub eq_token: tokens::Eq,
216        }),
217
218        /// An assignment with an operator
219        ///
220        /// For example, `a += 1`.
221        pub AssignOp(ExprAssignOp #full {
222            pub op: BinOp,
223            pub left: Box<Expr>,
224            pub right: Box<Expr>,
225        }),
226
227        /// Access of a named struct field (`obj.foo`)
228        pub Field(ExprField #full {
229            pub expr: Box<Expr>,
230            pub field: Ident,
231            pub dot_token: tokens::Dot,
232        }),
233
234        /// Access of an unnamed field of a struct or tuple-struct
235        ///
236        /// For example, `foo.0`.
237        pub TupField(ExprTupField #full {
238            pub expr: Box<Expr>,
239            pub field: Lit,
240            pub dot_token: tokens::Dot,
241        }),
242
243        /// An indexing operation (`foo[2]`)
244        pub Index(ExprIndex {
245            pub expr: Box<Expr>,
246            pub index: Box<Expr>,
247            pub bracket_token: tokens::Bracket,
248        }),
249
250        /// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`)
251        pub Range(ExprRange #full {
252            pub from: Option<Box<Expr>>,
253            pub to: Option<Box<Expr>>,
254            pub limits: RangeLimits,
255        }),
256
257        /// Variable reference, possibly containing `::` and/or type
258        /// parameters, e.g. foo::bar::<baz>.
259        ///
260        /// Optionally "qualified",
261        /// E.g. `<Vec<T> as SomeTrait>::SomeType`.
262        pub Path(ExprPath {
263            pub qself: Option<QSelf>,
264            pub path: Path,
265        }),
266
267        /// A referencing operation (`&a` or `&mut a`)
268        pub AddrOf(ExprAddrOf #full {
269            pub and_token: tokens::And,
270            pub mutbl: Mutability,
271            pub expr: Box<Expr>,
272        }),
273
274        /// A `break`, with an optional label to break, and an optional expression
275        pub Break(ExprBreak #full {
276            pub label: Option<Lifetime>,
277            pub expr: Option<Box<Expr>>,
278            pub break_token: tokens::Break,
279        }),
280
281        /// A `continue`, with an optional label
282        pub Continue(ExprContinue #full {
283            pub label: Option<Lifetime>,
284            pub continue_token: tokens::Continue,
285        }),
286
287        /// A `return`, with an optional value to be returned
288        pub Ret(ExprRet #full {
289            pub expr: Option<Box<Expr>>,
290            pub return_token: tokens::Return,
291        }),
292
293        /// A macro invocation; pre-expansion
294        pub Mac(Mac),
295
296        /// A struct literal expression.
297        ///
298        /// For example, `Foo {x: 1, y: 2}`, or
299        /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
300        pub Struct(ExprStruct #full {
301            pub path: Path,
302            pub fields: Delimited<FieldValue, tokens::Comma>,
303            pub rest: Option<Box<Expr>>,
304            pub dot2_token: Option<tokens::Dot2>,
305            pub brace_token: tokens::Brace,
306        }),
307
308        /// An array literal constructed from one repeated element.
309        ///
310        /// For example, `[1; 5]`. The first expression is the element
311        /// to be repeated; the second is the number of times to repeat it.
312        pub Repeat(ExprRepeat #full {
313            pub bracket_token: tokens::Bracket,
314            pub semi_token: tokens::Semi,
315            pub expr: Box<Expr>,
316            pub amt: Box<Expr>,
317        }),
318
319        /// No-op: used solely so we can pretty-print faithfully
320        pub Paren(ExprParen {
321            pub expr: Box<Expr>,
322            pub paren_token: tokens::Paren,
323        }),
324
325        /// No-op: used solely so we can pretty-print faithfully
326        ///
327        /// A `group` represents a `None`-delimited span in the input
328        /// `TokenStream` which affects the precidence of the resulting
329        /// expression. They are used for macro hygiene.
330        pub Group(ExprGroup {
331            pub expr: Box<Expr>,
332            pub group_token: tokens::Group,
333        }),
334
335        /// `expr?`
336        pub Try(ExprTry #full {
337            pub expr: Box<Expr>,
338            pub question_token: tokens::Question,
339        }),
340
341        /// A catch expression.
342        ///
343        /// E.g. `do catch { block }`
344        pub Catch(ExprCatch #full {
345            pub do_token: tokens::Do,
346            pub catch_token: tokens::Catch,
347            pub block: Block,
348        }),
349
350        /// A yield expression.
351        ///
352        /// E.g. `yield expr`
353        pub Yield(ExprYield #full {
354            pub yield_token: tokens::Yield,
355            pub expr: Option<Box<Expr>>,
356        }),
357    }
358}
359
360#[cfg(feature = "full")]
361ast_struct! {
362    /// A field-value pair in a struct literal.
363    pub struct FieldValue {
364        /// Name of the field.
365        pub ident: Ident,
366
367        /// Value of the field.
368        pub expr: Expr,
369
370        /// Whether this is a shorthand field, e.g. `Struct { x }`
371        /// instead of `Struct { x: x }`.
372        pub is_shorthand: bool,
373
374        /// Attributes tagged on the field.
375        pub attrs: Vec<Attribute>,
376
377        pub colon_token: Option<tokens::Colon>,
378    }
379}
380
381#[cfg(feature = "full")]
382ast_struct! {
383    /// A Block (`{ .. }`).
384    ///
385    /// E.g. `{ .. }` as in `fn foo() { .. }`
386    pub struct Block {
387        pub brace_token: tokens::Brace,
388        /// Statements in a block
389        pub stmts: Vec<Stmt>,
390    }
391}
392
393#[cfg(feature = "full")]
394ast_enum! {
395    /// A statement, usually ending in a semicolon.
396    pub enum Stmt {
397        /// A local (let) binding.
398        Local(Box<Local>),
399
400        /// An item definition.
401        Item(Box<Item>),
402
403        /// Expr without trailing semicolon.
404        Expr(Box<Expr>),
405
406        /// Expression with trailing semicolon;
407        Semi(Box<Expr>, tokens::Semi),
408
409        /// Macro invocation.
410        Mac(Box<(Mac, MacStmtStyle, Vec<Attribute>)>),
411    }
412}
413
414#[cfg(feature = "full")]
415ast_enum! {
416    /// How a macro was invoked.
417    #[cfg_attr(feature = "clone-impls", derive(Copy))]
418    pub enum MacStmtStyle {
419        /// The macro statement had a trailing semicolon, e.g. `foo! { ... };`
420        /// `foo!(...);`, `foo![...];`
421        Semicolon(tokens::Semi),
422
423        /// The macro statement had braces; e.g. foo! { ... }
424        Braces,
425
426        /// The macro statement had parentheses or brackets and no semicolon; e.g.
427        /// `foo!(...)`. All of these will end up being converted into macro
428        /// expressions.
429        NoBraces,
430    }
431}
432
433#[cfg(feature = "full")]
434ast_struct! {
435    /// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`
436    pub struct Local {
437        pub let_token: tokens::Let,
438        pub colon_token: Option<tokens::Colon>,
439        pub eq_token: Option<tokens::Eq>,
440        pub semi_token: tokens::Semi,
441
442        pub pat: Box<Pat>,
443        pub ty: Option<Box<Ty>>,
444
445        /// Initializer expression to set the value, if any
446        pub init: Option<Box<Expr>>,
447        pub attrs: Vec<Attribute>,
448    }
449}
450
451#[cfg(feature = "full")]
452ast_enum_of_structs! {
453    // Clippy false positive
454    // https://github.com/Manishearth/rust-clippy/issues/1241
455    #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
456    pub enum Pat {
457        /// Represents a wildcard pattern (`_`)
458        pub Wild(PatWild {
459            pub underscore_token: tokens::Underscore,
460        }),
461
462        /// A `Pat::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`),
463        /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
464        /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
465        /// during name resolution.
466        pub Ident(PatIdent {
467            pub mode: BindingMode,
468            pub ident: Ident,
469            pub subpat: Option<Box<Pat>>,
470            pub at_token: Option<tokens::At>,
471        }),
472
473        /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
474        /// The `bool` is `true` in the presence of a `..`.
475        pub Struct(PatStruct {
476            pub path: Path,
477            pub fields: Delimited<FieldPat, tokens::Comma>,
478            pub brace_token: tokens::Brace,
479            pub dot2_token: Option<tokens::Dot2>,
480        }),
481
482        /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
483        /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
484        /// 0 <= position <= subpats.len()
485        pub TupleStruct(PatTupleStruct {
486            pub path: Path,
487            pub pat: PatTuple,
488        }),
489
490        /// A possibly qualified path pattern.
491        /// Unquailfied path patterns `A::B::C` can legally refer to variants, structs, constants
492        /// or associated constants. Quailfied path patterns `<A>::B::C`/`<A as Trait>::B::C` can
493        /// only legally refer to associated constants.
494        pub Path(PatPath {
495            pub qself: Option<QSelf>,
496            pub path: Path,
497        }),
498
499        /// A tuple pattern `(a, b)`.
500        /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
501        /// 0 <= position <= subpats.len()
502        pub Tuple(PatTuple {
503            pub pats: Delimited<Pat, tokens::Comma>,
504            pub dots_pos: Option<usize>,
505            pub paren_token: tokens::Paren,
506            pub dot2_token: Option<tokens::Dot2>,
507            pub comma_token: Option<tokens::Comma>,
508        }),
509        /// A `box` pattern
510        pub Box(PatBox {
511            pub pat: Box<Pat>,
512            pub box_token: tokens::Box_,
513        }),
514        /// A reference pattern, e.g. `&mut (a, b)`
515        pub Ref(PatRef {
516            pub pat: Box<Pat>,
517            pub mutbl: Mutability,
518            pub and_token: tokens::And,
519        }),
520        /// A literal
521        pub Lit(PatLit {
522            pub expr: Box<Expr>,
523        }),
524        /// A range pattern, e.g. `1...2`
525        pub Range(PatRange {
526            pub lo: Box<Expr>,
527            pub hi: Box<Expr>,
528            pub limits: RangeLimits,
529        }),
530        /// `[a, b, i.., y, z]` is represented as:
531        pub Slice(PatSlice {
532            pub front: Delimited<Pat, tokens::Comma>,
533            pub middle: Option<Box<Pat>>,
534            pub back: Delimited<Pat, tokens::Comma>,
535            pub dot2_token: Option<tokens::Dot2>,
536            pub comma_token: Option<tokens::Comma>,
537            pub bracket_token: tokens::Bracket,
538        }),
539        /// A macro pattern; pre-expansion
540        pub Mac(Mac),
541    }
542}
543
544#[cfg(feature = "full")]
545ast_struct! {
546    /// An arm of a 'match'.
547    ///
548    /// E.g. `0...10 => { println!("match!") }` as in
549    ///
550    /// ```rust,ignore
551    /// match n {
552    ///     0...10 => { println!("match!") },
553    ///     // ..
554    /// }
555    /// ```
556    pub struct Arm {
557        pub attrs: Vec<Attribute>,
558        pub pats: Delimited<Pat, tokens::Or>,
559        pub if_token: Option<tokens::If>,
560        pub guard: Option<Box<Expr>>,
561        pub rocket_token: tokens::Rocket,
562        pub body: Box<Expr>,
563        pub comma: Option<tokens::Comma>,
564    }
565}
566
567#[cfg(feature = "full")]
568ast_enum! {
569    /// A capture clause
570    #[cfg_attr(feature = "clone-impls", derive(Copy))]
571    pub enum CaptureBy {
572        Value(tokens::Move),
573        Ref,
574    }
575}
576
577#[cfg(feature = "full")]
578ast_enum! {
579    /// Limit types of a range (inclusive or exclusive)
580    #[cfg_attr(feature = "clone-impls", derive(Copy))]
581    pub enum RangeLimits {
582        /// Inclusive at the beginning, exclusive at the end
583        HalfOpen(tokens::Dot2),
584        /// Inclusive at the beginning and end
585        Closed(tokens::Dot3),
586    }
587}
588
589#[cfg(feature = "full")]
590ast_struct! {
591    /// A single field in a struct pattern
592    ///
593    /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
594    /// are treated the same as `x: x, y: ref y, z: ref mut z`,
595    /// except `is_shorthand` is true
596    pub struct FieldPat {
597        /// The identifier for the field
598        pub ident: Ident,
599        /// The pattern the field is destructured to
600        pub pat: Box<Pat>,
601        pub is_shorthand: bool,
602        pub colon_token: Option<tokens::Colon>,
603        pub attrs: Vec<Attribute>,
604    }
605}
606
607#[cfg(feature = "full")]
608ast_enum! {
609    #[cfg_attr(feature = "clone-impls", derive(Copy))]
610    pub enum BindingMode {
611        ByRef(tokens::Ref, Mutability),
612        ByValue(Mutability),
613    }
614}
615
616#[cfg(feature = "full")]
617ast_enum! {
618    #[cfg_attr(feature = "clone-impls", derive(Copy))]
619    pub enum InPlaceKind {
620        Arrow(tokens::LArrow),
621        In(tokens::In),
622    }
623}
624
625#[cfg(any(feature = "parsing", feature = "printing"))]
626#[cfg(feature = "full")]
627fn arm_requires_comma(arm: &Arm) -> bool {
628    if let ExprKind::Block(ExprBlock { unsafety: Unsafety::Normal, .. }) = arm.body.node {
629        false
630    } else {
631        true
632    }
633}
634
635#[cfg(feature = "parsing")]
636pub mod parsing {
637    use super::*;
638    use ty::parsing::qpath;
639
640    #[cfg(feature = "full")]
641    use proc_macro2::{TokenStream, TokenNode, Delimiter, Term};
642    use synom::{PResult, Cursor, Synom};
643    #[cfg(feature = "full")]
644    use synom::parse_error;
645    use synom::tokens::*;
646
647    /// When we're parsing expressions which occur before blocks, like in
648    /// an if statement's condition, we cannot parse a struct literal.
649    ///
650    /// Struct literals are ambiguous in certain positions
651    /// https://github.com/rust-lang/rfcs/pull/92
652    macro_rules! ambiguous_expr {
653        ($i:expr, $allow_struct:ident) => {
654            ambiguous_expr($i, $allow_struct, true)
655        };
656    }
657
658    /// When we are parsing an optional suffix expression, we cannot allow
659    /// blocks if structs are not allowed.
660    ///
661    /// Example:
662    /// ```ignore
663    /// if break { } { }
664    /// // is ambiguous between:
665    /// if (break { }) { }
666    /// // - or -
667    /// if (break) { } { }
668    /// ```
669    #[cfg(feature = "full")]
670    macro_rules! opt_ambiguous_expr {
671        ($i:expr, $allow_struct:ident) => {
672            option!($i, call!(ambiguous_expr, $allow_struct, $allow_struct))
673        };
674    }
675
676    impl Synom for Expr {
677        named!(parse -> Self, ambiguous_expr!(true));
678
679        fn description() -> Option<&'static str> {
680            Some("expression")
681        }
682    }
683
684    #[cfg(feature = "full")]
685    named!(expr_no_struct -> Expr, ambiguous_expr!(false));
686
687    /// Parse an arbitrary expression.
688    #[cfg(feature = "full")]
689    fn ambiguous_expr(i: Cursor,
690                      allow_struct: bool,
691                      allow_block: bool)
692                      -> PResult<Expr> {
693        map!(
694            i,
695            call!(assign_expr, allow_struct, allow_block),
696            ExprKind::into
697        )
698    }
699
700    #[cfg(not(feature = "full"))]
701    fn ambiguous_expr(i: Cursor,
702                      allow_struct: bool,
703                      allow_block: bool)
704                      -> PResult<Expr> {
705        map!(
706            i,
707            // NOTE: We intentionally skip assign_expr, placement_expr, and
708            // range_expr, as they are not parsed in non-full mode.
709            call!(or_expr, allow_struct, allow_block),
710            ExprKind::into
711        )
712    }
713
714    /// Parse a left-associative binary operator.
715    macro_rules! binop {
716        (
717            $name: ident,
718            $next: ident,
719            $submac: ident!( $($args:tt)* )
720        ) => {
721            named!($name(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
722                mut e: call!($next, allow_struct, allow_block) >>
723                many0!(do_parse!(
724                    op: $submac!($($args)*) >>
725                    rhs: call!($next, allow_struct, true) >>
726                    ({
727                        e = ExprBinary {
728                            left: Box::new(e.into()),
729                            op: op,
730                            right: Box::new(rhs.into()),
731                        }.into();
732                    })
733                )) >>
734                (e)
735            ));
736        }
737    }
738
739    /// ```ignore
740    /// <placement> = <placement> ..
741    /// <placement> += <placement> ..
742    /// <placement> -= <placement> ..
743    /// <placement> *= <placement> ..
744    /// <placement> /= <placement> ..
745    /// <placement> %= <placement> ..
746    /// <placement> ^= <placement> ..
747    /// <placement> &= <placement> ..
748    /// <placement> |= <placement> ..
749    /// <placement> <<= <placement> ..
750    /// <placement> >>= <placement> ..
751    /// ```
752    ///
753    /// NOTE: This operator is right-associative.
754    #[cfg(feature = "full")]
755    named!(assign_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
756        mut e: call!(placement_expr, allow_struct, allow_block) >>
757        alt!(
758            do_parse!(
759                eq: syn!(Eq) >>
760                // Recurse into self to parse right-associative operator.
761                rhs: call!(assign_expr, allow_struct, true) >>
762                ({
763                    e = ExprAssign {
764                        left: Box::new(e.into()),
765                        eq_token: eq,
766                        right: Box::new(rhs.into()),
767                    }.into();
768                })
769            )
770            |
771            do_parse!(
772                op: call!(BinOp::parse_assign_op) >>
773                // Recurse into self to parse right-associative operator.
774                rhs: call!(assign_expr, allow_struct, true) >>
775                ({
776                    e = ExprAssignOp {
777                        left: Box::new(e.into()),
778                        op: op,
779                        right: Box::new(rhs.into()),
780                    }.into();
781                })
782            )
783            |
784            epsilon!()
785        ) >>
786        (e)
787    ));
788
789    /// ```ignore
790    /// <range> <- <range> ..
791    /// ```
792    ///
793    /// NOTE: The `in place { expr }` version of this syntax is parsed in
794    /// `atom_expr`, not here.
795    ///
796    /// NOTE: This operator is right-associative.
797    #[cfg(feature = "full")]
798    named!(placement_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
799        mut e: call!(range_expr, allow_struct, allow_block) >>
800        alt!(
801            do_parse!(
802                arrow: syn!(LArrow) >>
803                // Recurse into self to parse right-associative operator.
804                rhs: call!(placement_expr, allow_struct, true) >>
805                ({
806                    e = ExprInPlace {
807                        // op: BinOp::Place(larrow),
808                        place: Box::new(e.into()),
809                        kind: InPlaceKind::Arrow(arrow),
810                        value: Box::new(rhs.into()),
811                    }.into();
812                })
813            )
814            |
815            epsilon!()
816        ) >>
817        (e)
818    ));
819
820    /// ```ignore
821    /// <or> ... <or> ..
822    /// <or> .. <or> ..
823    /// <or> ..
824    /// ```
825    ///
826    /// NOTE: This is currently parsed oddly - I'm not sure of what the exact
827    /// rules are for parsing these expressions are, but this is not correct.
828    /// For example, `a .. b .. c` is not a legal expression. It should not
829    /// be parsed as either `(a .. b) .. c` or `a .. (b .. c)` apparently.
830    ///
831    /// NOTE: The form of ranges which don't include a preceding expression are
832    /// parsed by `atom_expr`, rather than by this function.
833    #[cfg(feature = "full")]
834    named!(range_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
835        mut e: call!(or_expr, allow_struct, allow_block) >>
836        many0!(do_parse!(
837            limits: syn!(RangeLimits) >>
838            // We don't want to allow blocks here if we don't allow structs. See
839            // the reasoning for `opt_ambiguous_expr!` above.
840            hi: option!(call!(or_expr, allow_struct, allow_struct)) >>
841            ({
842                e = ExprRange {
843                    from: Some(Box::new(e.into())),
844                    limits: limits,
845                    to: hi.map(|e| Box::new(e.into())),
846                }.into();
847            })
848        )) >>
849        (e)
850    ));
851
852    /// ```ignore
853    /// <and> || <and> ...
854    /// ```
855    binop!(or_expr, and_expr, map!(syn!(OrOr), BinOp::Or));
856
857    /// ```ignore
858    /// <compare> && <compare> ...
859    /// ```
860    binop!(and_expr, compare_expr, map!(syn!(AndAnd), BinOp::And));
861
862    /// ```ignore
863    /// <bitor> == <bitor> ...
864    /// <bitor> != <bitor> ...
865    /// <bitor> >= <bitor> ...
866    /// <bitor> <= <bitor> ...
867    /// <bitor> > <bitor> ...
868    /// <bitor> < <bitor> ...
869    /// ```
870    ///
871    /// NOTE: This operator appears to be parsed as left-associative, but errors
872    /// if it is used in a non-associative manner.
873    binop!(compare_expr, bitor_expr, alt!(
874        syn!(EqEq) => { BinOp::Eq }
875        |
876        syn!(Ne) => { BinOp::Ne }
877        |
878        // must be above Lt
879        syn!(Le) => { BinOp::Le }
880        |
881        // must be above Gt
882        syn!(Ge) => { BinOp::Ge }
883        |
884        do_parse!(
885            // Make sure that we don't eat the < part of a <- operator
886            not!(syn!(LArrow)) >>
887            t: syn!(Lt) >>
888            (BinOp::Lt(t))
889        )
890        |
891        syn!(Gt) => { BinOp::Gt }
892    ));
893
894    /// ```ignore
895    /// <bitxor> | <bitxor> ...
896    /// ```
897    binop!(bitor_expr, bitxor_expr, do_parse!(
898        not!(syn!(OrOr)) >>
899        not!(syn!(OrEq)) >>
900        t: syn!(Or) >>
901        (BinOp::BitOr(t))
902    ));
903
904    /// ```ignore
905    /// <bitand> ^ <bitand> ...
906    /// ```
907    binop!(bitxor_expr, bitand_expr, do_parse!(
908        // NOTE: Make sure we aren't looking at ^=.
909        not!(syn!(CaretEq)) >>
910        t: syn!(Caret) >>
911        (BinOp::BitXor(t))
912    ));
913
914    /// ```ignore
915    /// <shift> & <shift> ...
916    /// ```
917    binop!(bitand_expr, shift_expr, do_parse!(
918        // NOTE: Make sure we aren't looking at && or &=.
919        not!(syn!(AndAnd)) >>
920        not!(syn!(AndEq)) >>
921        t: syn!(And) >>
922        (BinOp::BitAnd(t))
923    ));
924
925    /// ```ignore
926    /// <arith> << <arith> ...
927    /// <arith> >> <arith> ...
928    /// ```
929    binop!(shift_expr, arith_expr, alt!(
930        syn!(Shl) => { BinOp::Shl }
931        |
932        syn!(Shr) => { BinOp::Shr }
933    ));
934
935    /// ```ignore
936    /// <term> + <term> ...
937    /// <term> - <term> ...
938    /// ```
939    binop!(arith_expr, term_expr, alt!(
940        syn!(Add) => { BinOp::Add }
941        |
942        syn!(Sub) => { BinOp::Sub }
943    ));
944
945    /// ```ignore
946    /// <cast> * <cast> ...
947    /// <cast> / <cast> ...
948    /// <cast> % <cast> ...
949    /// ```
950    binop!(term_expr, cast_expr, alt!(
951        syn!(Star) => { BinOp::Mul }
952        |
953        syn!(Div) => { BinOp::Div }
954        |
955        syn!(Rem) => { BinOp::Rem }
956    ));
957
958    /// ```ignore
959    /// <unary> as <ty>
960    /// <unary> : <ty>
961    /// ```
962    named!(cast_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
963        mut e: call!(unary_expr, allow_struct, allow_block) >>
964        many0!(alt!(
965            do_parse!(
966                as_: syn!(As) >>
967                // We can't accept `A + B` in cast expressions, as it's
968                // ambiguous with the + expression.
969                ty: call!(Ty::without_plus) >>
970                ({
971                    e = ExprCast {
972                        expr: Box::new(e.into()),
973                        as_token: as_,
974                        ty: Box::new(ty),
975                    }.into();
976                })
977            )
978            |
979            do_parse!(
980                colon: syn!(Colon) >>
981                // We can't accept `A + B` in cast expressions, as it's
982                // ambiguous with the + expression.
983                ty: call!(Ty::without_plus) >>
984                ({
985                    e = ExprType {
986                        expr: Box::new(e.into()),
987                        colon_token: colon,
988                        ty: Box::new(ty),
989                    }.into();
990                })
991            )
992        )) >>
993        (e)
994    ));
995
996    /// ```
997    /// <UnOp> <trailer>
998    /// & <trailer>
999    /// &mut <trailer>
1000    /// box <trailer>
1001    /// ```
1002    #[cfg(feature = "full")]
1003    named!(unary_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
1004        do_parse!(
1005            op: syn!(UnOp) >>
1006            expr: call!(unary_expr, allow_struct, true) >>
1007            (ExprUnary {
1008                op: op,
1009                expr: Box::new(expr.into()),
1010            }.into())
1011        )
1012        |
1013        do_parse!(
1014            and: syn!(And) >>
1015            mutability: syn!(Mutability) >>
1016            expr: call!(unary_expr, allow_struct, true) >>
1017            (ExprAddrOf {
1018                and_token: and,
1019                mutbl: mutability,
1020                expr: Box::new(expr.into()),
1021            }.into())
1022        )
1023        |
1024        do_parse!(
1025            box_: syn!(Box_) >>
1026            expr: call!(unary_expr, allow_struct, true) >>
1027            (ExprBox {
1028                box_token: box_,
1029                expr: Box::new(expr.into()),
1030            }.into())
1031        )
1032        |
1033        call!(trailer_expr, allow_struct, allow_block)
1034    ));
1035
1036    // XXX: This duplication is ugly
1037    #[cfg(not(feature = "full"))]
1038    named!(unary_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
1039        do_parse!(
1040            op: syn!(UnOp) >>
1041            expr: call!(unary_expr, allow_struct, true) >>
1042            (ExprUnary {
1043                op: op,
1044                expr: Box::new(expr.into()),
1045            }.into())
1046        )
1047        |
1048        call!(trailer_expr, allow_struct, allow_block)
1049    ));
1050
1051    /// ```ignore
1052    /// <atom> (..<args>) ...
1053    /// <atom> . <ident> (..<args>) ...
1054    /// <atom> . <ident> ...
1055    /// <atom> . <lit> ...
1056    /// <atom> [ <expr> ] ...
1057    /// <atom> ? ...
1058    /// ```
1059    #[cfg(feature = "full")]
1060    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
1061        mut e: call!(atom_expr, allow_struct, allow_block) >>
1062        many0!(alt!(
1063            tap!(args: and_call => {
1064                let (args, paren) = args;
1065                e = ExprCall {
1066                    func: Box::new(e.into()),
1067                    args: args,
1068                    paren_token: paren,
1069                }.into();
1070            })
1071            |
1072            tap!(more: and_method_call => {
1073                let mut call = more;
1074                call.expr = Box::new(e.into());
1075                e = call.into();
1076            })
1077            |
1078            tap!(field: and_field => {
1079                let (field, token) = field;
1080                e = ExprField {
1081                    expr: Box::new(e.into()),
1082                    field: field,
1083                    dot_token: token,
1084                }.into();
1085            })
1086            |
1087            tap!(field: and_tup_field => {
1088                let (field, token) = field;
1089                e = ExprTupField {
1090                    expr: Box::new(e.into()),
1091                    field: field,
1092                    dot_token: token,
1093                }.into();
1094            })
1095            |
1096            tap!(i: and_index => {
1097                let (i, token) = i;
1098                e = ExprIndex {
1099                    expr: Box::new(e.into()),
1100                    bracket_token: token,
1101                    index: Box::new(i),
1102                }.into();
1103            })
1104            |
1105            tap!(question: syn!(Question) => {
1106                e = ExprTry {
1107                    expr: Box::new(e.into()),
1108                    question_token: question,
1109                }.into();
1110            })
1111        )) >>
1112        (e)
1113    ));
1114
1115    // XXX: Duplication == ugly
1116    #[cfg(not(feature = "full"))]
1117    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
1118        mut e: call!(atom_expr, allow_struct, allow_block) >>
1119        many0!(alt!(
1120            tap!(args: and_call => {
1121                let (args, paren) = args;
1122                e = ExprCall {
1123                    func: Box::new(e.into()),
1124                    args: args,
1125                    paren_token: paren,
1126                }.into();
1127            })
1128            |
1129            tap!(i: and_index => {
1130                let (i, token) = i;
1131                e = ExprIndex {
1132                    expr: Box::new(e.into()),
1133                    bracket_token: token,
1134                    index: Box::new(i),
1135                }.into();
1136            })
1137        )) >>
1138        (e)
1139    ));
1140
1141    /// Parse all atomic expressions which don't have to worry about precidence
1142    /// interactions, as they are fully contained.
1143    #[cfg(feature = "full")]
1144    named!(atom_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
1145        syn!(ExprGroup) => { ExprKind::Group } // must be placed first
1146        |
1147        syn!(Lit) => { ExprKind::Lit } // must be before expr_struct
1148        |
1149        // must be before expr_path
1150        cond_reduce!(allow_struct, map!(syn!(ExprStruct), ExprKind::Struct))
1151        |
1152        syn!(ExprParen) => { ExprKind::Paren } // must be before expr_tup
1153        |
1154        syn!(Mac) => { ExprKind::Mac } // must be before expr_path
1155        |
1156        call!(expr_break, allow_struct) // must be before expr_path
1157        |
1158        syn!(ExprContinue) => { ExprKind::Continue } // must be before expr_path
1159        |
1160        call!(expr_ret, allow_struct) // must be before expr_path
1161        |
1162        // NOTE: The `in place { expr }` form. `place <- expr` is parsed above.
1163        syn!(ExprInPlace) => { ExprKind::InPlace }
1164        |
1165        syn!(ExprArray) => { ExprKind::Array }
1166        |
1167        syn!(ExprTup) => { ExprKind::Tup }
1168        |
1169        syn!(ExprIf) => { ExprKind::If }
1170        |
1171        syn!(ExprIfLet) => { ExprKind::IfLet }
1172        |
1173        syn!(ExprWhile) => { ExprKind::While }
1174        |
1175        syn!(ExprWhileLet) => { ExprKind::WhileLet }
1176        |
1177        syn!(ExprForLoop) => { ExprKind::ForLoop }
1178        |
1179        syn!(ExprLoop) => { ExprKind::Loop }
1180        |
1181        syn!(ExprMatch) => { ExprKind::Match }
1182        |
1183        syn!(ExprCatch) => { ExprKind::Catch }
1184        |
1185        syn!(ExprYield) => { ExprKind::Yield }
1186        |
1187        call!(expr_closure, allow_struct)
1188        |
1189        cond_reduce!(allow_block, map!(syn!(ExprBlock), ExprKind::Block))
1190        |
1191        // NOTE: This is the prefix-form of range
1192        call!(expr_range, allow_struct)
1193        |
1194        syn!(ExprPath) => { ExprKind::Path }
1195        |
1196        syn!(ExprRepeat) => { ExprKind::Repeat }
1197    ));
1198
1199    #[cfg(not(feature = "full"))]
1200    named!(atom_expr(_allow_struct: bool, _allow_block: bool) -> ExprKind, alt!(
1201        syn!(ExprGroup) => { ExprKind::Group } // must be placed first
1202        |
1203        syn!(Lit) => { ExprKind::Lit } // must be before expr_struct
1204        |
1205        syn!(ExprParen) => { ExprKind::Paren } // must be before expr_tup
1206        |
1207        syn!(Mac) => { ExprKind::Mac } // must be before expr_path
1208        |
1209        syn!(ExprPath) => { ExprKind::Path }
1210    ));
1211
1212
1213    #[cfg(feature = "full")]
1214    named!(expr_nosemi -> Expr, map!(alt!(
1215        syn!(ExprIf) => { ExprKind::If }
1216        |
1217        syn!(ExprIfLet) => { ExprKind::IfLet }
1218        |
1219        syn!(ExprWhile) => { ExprKind::While }
1220        |
1221        syn!(ExprWhileLet) => { ExprKind::WhileLet }
1222        |
1223        syn!(ExprForLoop) => { ExprKind::ForLoop }
1224        |
1225        syn!(ExprLoop) => { ExprKind::Loop }
1226        |
1227        syn!(ExprMatch) => { ExprKind::Match }
1228        |
1229        syn!(ExprCatch) => { ExprKind::Catch }
1230        |
1231        syn!(ExprYield) => { ExprKind::Yield }
1232        |
1233        syn!(ExprBlock) => { ExprKind::Block }
1234    ), Expr::from));
1235
1236    impl Synom for ExprGroup {
1237        named!(parse -> Self, do_parse!(
1238            e: grouped!(syn!(Expr)) >>
1239            (ExprGroup {
1240                expr: Box::new(e.0),
1241                group_token: e.1,
1242            }.into())
1243        ));
1244    }
1245
1246    impl Synom for ExprParen {
1247        named!(parse -> Self, do_parse!(
1248            e: parens!(syn!(Expr)) >>
1249            (ExprParen {
1250                expr: Box::new(e.0),
1251                paren_token: e.1,
1252            }.into())
1253        ));
1254    }
1255
1256    #[cfg(feature = "full")]
1257    impl Synom for ExprInPlace {
1258        named!(parse -> Self, do_parse!(
1259            in_: syn!(In) >>
1260            place: expr_no_struct >>
1261            value: braces!(call!(Block::parse_within)) >>
1262            (ExprInPlace {
1263                place: Box::new(place),
1264                kind: InPlaceKind::In(in_),
1265                value: Box::new(Expr {
1266                    node: ExprBlock {
1267                        unsafety: Unsafety::Normal,
1268                        block: Block {
1269                            stmts: value.0,
1270                            brace_token: value.1,
1271                        },
1272                    }.into(),
1273                    attrs: Vec::new(),
1274                }),
1275            })
1276        ));
1277    }
1278
1279    #[cfg(feature = "full")]
1280    impl Synom for ExprArray {
1281        named!(parse -> Self, do_parse!(
1282            elems: brackets!(call!(Delimited::parse_terminated)) >>
1283            (ExprArray {
1284                exprs: elems.0,
1285                bracket_token: elems.1,
1286            })
1287        ));
1288    }
1289
1290    named!(and_call -> (Delimited<Expr, tokens::Comma>, tokens::Paren),
1291           parens!(call!(Delimited::parse_terminated)));
1292
1293    #[cfg(feature = "full")]
1294    named!(and_method_call -> ExprMethodCall, do_parse!(
1295        dot: syn!(Dot) >>
1296        method: syn!(Ident) >>
1297        typarams: option!(do_parse!(
1298            colon2: syn!(Colon2) >>
1299            lt: syn!(Lt) >>
1300            tys: call!(Delimited::parse_terminated) >>
1301            gt: syn!(Gt) >>
1302            (colon2, lt, tys, gt)
1303        )) >>
1304        args: parens!(call!(Delimited::parse_terminated)) >>
1305        ({
1306            let (colon2, lt, tys, gt) = match typarams {
1307                Some((a, b, c, d)) => (Some(a), Some(b), Some(c), Some(d)),
1308                None => (None, None, None, None),
1309            };
1310            ExprMethodCall {
1311                // this expr will get overwritten after being returned
1312                expr: Box::new(ExprKind::Lit(Lit {
1313                    span: Span::default(),
1314                    value: LitKind::Bool(false),
1315                }).into()),
1316
1317                method: method,
1318                args: args.0,
1319                paren_token: args.1,
1320                dot_token: dot,
1321                lt_token: lt,
1322                gt_token: gt,
1323                colon2_token: colon2,
1324                typarams: tys.unwrap_or_default(),
1325            }
1326        })
1327    ));
1328
1329    #[cfg(feature = "full")]
1330    impl Synom for ExprTup {
1331        named!(parse -> Self, do_parse!(
1332            elems: parens!(call!(Delimited::parse_terminated)) >>
1333            (ExprTup {
1334                args: elems.0,
1335                paren_token: elems.1,
1336                lone_comma: None, // TODO: parse this
1337            })
1338        ));
1339    }
1340
1341    #[cfg(feature = "full")]
1342    impl Synom for ExprIfLet {
1343        named!(parse -> Self, do_parse!(
1344            if_: syn!(If) >>
1345            let_: syn!(Let) >>
1346            pat: syn!(Pat) >>
1347            eq: syn!(Eq) >>
1348            cond: expr_no_struct >>
1349            then_block: braces!(call!(Block::parse_within)) >>
1350            else_block: option!(else_block) >>
1351            (ExprIfLet {
1352                pat: Box::new(pat),
1353                let_token: let_,
1354                eq_token: eq,
1355                expr: Box::new(cond),
1356                if_true: Block {
1357                    stmts: then_block.0,
1358                    brace_token: then_block.1,
1359                },
1360                if_token: if_,
1361                else_token: else_block.as_ref().map(|p| Else((p.0).0)),
1362                if_false: else_block.map(|p| Box::new(p.1.into())),
1363            })
1364        ));
1365    }
1366
1367    #[cfg(feature = "full")]
1368    impl Synom for ExprIf {
1369        named!(parse -> Self, do_parse!(
1370            if_: syn!(If) >>
1371            cond: expr_no_struct >>
1372            then_block: braces!(call!(Block::parse_within)) >>
1373            else_block: option!(else_block) >>
1374            (ExprIf {
1375                cond: Box::new(cond),
1376                if_true: Block {
1377                    stmts: then_block.0,
1378                    brace_token: then_block.1,
1379                },
1380                if_token: if_,
1381                else_token: else_block.as_ref().map(|p| Else((p.0).0)),
1382                if_false: else_block.map(|p| Box::new(p.1.into())),
1383            })
1384        ));
1385    }
1386
1387    #[cfg(feature = "full")]
1388    named!(else_block -> (Else, ExprKind), do_parse!(
1389        else_: syn!(Else) >>
1390        expr: alt!(
1391            syn!(ExprIf) => { ExprKind::If }
1392            |
1393            syn!(ExprIfLet) => { ExprKind::IfLet }
1394            |
1395            do_parse!(
1396                else_block: braces!(call!(Block::parse_within)) >>
1397                (ExprKind::Block(ExprBlock {
1398                    unsafety: Unsafety::Normal,
1399                    block: Block {
1400                        stmts: else_block.0,
1401                        brace_token: else_block.1,
1402                    },
1403                }))
1404            )
1405        ) >>
1406        (else_, expr)
1407    ));
1408
1409
1410    #[cfg(feature = "full")]
1411    impl Synom for ExprForLoop {
1412        named!(parse -> Self, do_parse!(
1413            lbl: option!(tuple!(syn!(Lifetime), syn!(Colon))) >>
1414            for_: syn!(For) >>
1415            pat: syn!(Pat) >>
1416            in_: syn!(In) >>
1417            expr: expr_no_struct >>
1418            loop_block: syn!(Block) >>
1419            (ExprForLoop {
1420                for_token: for_,
1421                in_token: in_,
1422                pat: Box::new(pat),
1423                expr: Box::new(expr),
1424                body: loop_block,
1425                colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
1426                label: lbl.map(|p| p.0),
1427            })
1428        ));
1429    }
1430
1431    #[cfg(feature = "full")]
1432    impl Synom for ExprLoop {
1433        named!(parse -> Self, do_parse!(
1434            lbl: option!(tuple!(syn!(Lifetime), syn!(Colon))) >>
1435            loop_: syn!(Loop) >>
1436            loop_block: syn!(Block) >>
1437            (ExprLoop {
1438                loop_token: loop_,
1439                body: loop_block,
1440                colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
1441                label: lbl.map(|p| p.0),
1442            })
1443        ));
1444    }
1445
1446    #[cfg(feature = "full")]
1447    impl Synom for ExprMatch {
1448        named!(parse -> Self, do_parse!(
1449            match_: syn!(Match) >>
1450            obj: expr_no_struct >>
1451            res: braces!(do_parse!(
1452                mut arms: many0!(do_parse!(
1453                    arm: syn!(Arm) >>
1454                        cond!(arm_requires_comma(&arm), syn!(Comma)) >>
1455                        cond!(!arm_requires_comma(&arm), option!(syn!(Comma))) >>
1456                        (arm)
1457                )) >>
1458                last_arm: option!(syn!(Arm)) >>
1459                ({
1460                    arms.extend(last_arm);
1461                    arms
1462                })
1463            )) >>
1464            ({
1465                let (mut arms, brace) = res;
1466                ExprMatch {
1467                    expr: Box::new(obj),
1468                    match_token: match_,
1469                    brace_token: brace,
1470                    arms: {
1471                        for arm in &mut arms {
1472                            if arm_requires_comma(arm) {
1473                                arm.comma = Some(tokens::Comma::default());
1474                            }
1475                        }
1476                        arms
1477                    },
1478                }
1479            })
1480        ));
1481    }
1482
1483    #[cfg(feature = "full")]
1484    impl Synom for ExprCatch {
1485        named!(parse -> Self, do_parse!(
1486            do_: syn!(Do) >>
1487            catch_: syn!(Catch) >>
1488            catch_block: syn!(Block) >>
1489            (ExprCatch {
1490                block: catch_block,
1491                do_token: do_,
1492                catch_token: catch_,
1493            }.into())
1494        ));
1495    }
1496
1497    #[cfg(feature = "full")]
1498    impl Synom for ExprYield {
1499        named!(parse -> Self, do_parse!(
1500            yield_: syn!(Yield) >>
1501            expr: option!(syn!(Expr)) >>
1502            (ExprYield {
1503                yield_token: yield_,
1504                expr: expr.map(Box::new),
1505            })
1506        ));
1507    }
1508
1509    #[cfg(feature = "full")]
1510    impl Synom for Arm {
1511        named!(parse -> Self, do_parse!(
1512            attrs: many0!(call!(Attribute::parse_outer)) >>
1513            pats: call!(Delimited::parse_separated_nonempty) >>
1514            guard: option!(tuple!(syn!(If), syn!(Expr))) >>
1515            rocket: syn!(Rocket) >>
1516            body: alt!(
1517                map!(syn!(Block), |blk| {
1518                    ExprKind::Block(ExprBlock {
1519                        unsafety: Unsafety::Normal,
1520                        block: blk,
1521                    }).into()
1522                })
1523                |
1524                syn!(Expr)
1525            ) >>
1526            (Arm {
1527                rocket_token: rocket,
1528                if_token: guard.as_ref().map(|p| If((p.0).0)),
1529                attrs: attrs,
1530                pats: pats,
1531                guard: guard.map(|p| Box::new(p.1)),
1532                body: Box::new(body),
1533                comma: None,
1534            })
1535        ));
1536    }
1537
1538    #[cfg(feature = "full")]
1539    named!(expr_closure(allow_struct: bool) -> ExprKind, do_parse!(
1540        capture: syn!(CaptureBy) >>
1541        or1: syn!(Or) >>
1542        inputs: call!(Delimited::parse_terminated_with, fn_arg) >>
1543        or2: syn!(Or) >>
1544        ret_and_body: alt!(
1545            do_parse!(
1546                arrow: syn!(RArrow) >>
1547                ty: syn!(Ty) >>
1548                body: syn!(Block) >>
1549                (FunctionRetTy::Ty(ty, arrow),
1550                 ExprKind::Block(ExprBlock {
1551                    unsafety: Unsafety::Normal,
1552                    block: body,
1553                }).into())
1554            )
1555            |
1556            map!(ambiguous_expr!(allow_struct), |e| (FunctionRetTy::Default, e))
1557        ) >>
1558        (ExprClosure {
1559            capture: capture,
1560            or1_token: or1,
1561            or2_token: or2,
1562            decl: Box::new(FnDecl {
1563                inputs: inputs,
1564                output: ret_and_body.0,
1565                variadic: false,
1566                dot_tokens: None,
1567                fn_token: tokens::Fn_::default(),
1568                generics: Generics::default(),
1569                paren_token: tokens::Paren::default(),
1570            }),
1571            body: Box::new(ret_and_body.1),
1572        }.into())
1573    ));
1574
1575    #[cfg(feature = "full")]
1576    named!(fn_arg -> FnArg, do_parse!(
1577        pat: syn!(Pat) >>
1578        ty: option!(tuple!(syn!(Colon), syn!(Ty))) >>
1579        ({
1580            let (colon, ty) = ty.unwrap_or_else(|| {
1581                (Colon::default(), TyInfer {
1582                    underscore_token: Underscore::default(),
1583                }.into())
1584            });
1585            ArgCaptured {
1586                pat: pat,
1587                colon_token: colon,
1588                ty: ty,
1589            }.into()
1590        })
1591    ));
1592
1593    #[cfg(feature = "full")]
1594    impl Synom for ExprWhile {
1595        named!(parse -> Self, do_parse!(
1596            lbl: option!(tuple!(syn!(Lifetime), syn!(Colon))) >>
1597            while_: syn!(While) >>
1598            cond: expr_no_struct >>
1599            while_block: syn!(Block) >>
1600            (ExprWhile {
1601                while_token: while_,
1602                colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
1603                cond: Box::new(cond),
1604                body: while_block,
1605                label: lbl.map(|p| p.0),
1606            })
1607        ));
1608    }
1609
1610    #[cfg(feature = "full")]
1611    impl Synom for ExprWhileLet {
1612        named!(parse -> Self, do_parse!(
1613            lbl: option!(tuple!(syn!(Lifetime), syn!(Colon))) >>
1614            while_: syn!(While) >>
1615            let_: syn!(Let) >>
1616            pat: syn!(Pat) >>
1617            eq: syn!(Eq) >>
1618            value: expr_no_struct >>
1619            while_block: syn!(Block) >>
1620            (ExprWhileLet {
1621                eq_token: eq,
1622                let_token: let_,
1623                while_token: while_,
1624                colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
1625                pat: Box::new(pat),
1626                expr: Box::new(value),
1627                body: while_block,
1628                label: lbl.map(|p| p.0),
1629            })
1630        ));
1631    }
1632
1633    #[cfg(feature = "full")]
1634    impl Synom for ExprContinue {
1635        named!(parse -> Self, do_parse!(
1636            cont: syn!(Continue) >>
1637            lbl: option!(syn!(Lifetime)) >>
1638            (ExprContinue {
1639                continue_token: cont,
1640                label: lbl,
1641            })
1642        ));
1643    }
1644
1645    #[cfg(feature = "full")]
1646    named!(expr_break(allow_struct: bool) -> ExprKind, do_parse!(
1647        break_: syn!(Break) >>
1648        lbl: option!(syn!(Lifetime)) >>
1649        // We can't allow blocks after a `break` expression when we wouldn't
1650        // allow structs, as this expression is ambiguous.
1651        val: opt_ambiguous_expr!(allow_struct) >>
1652        (ExprBreak {
1653            label: lbl,
1654            expr: val.map(Box::new),
1655            break_token: break_,
1656        }.into())
1657    ));
1658
1659    #[cfg(feature = "full")]
1660    named!(expr_ret(allow_struct: bool) -> ExprKind, do_parse!(
1661        return_: syn!(Return) >>
1662        // NOTE: return is greedy and eats blocks after it even when in a
1663        // position where structs are not allowed, such as in if statement
1664        // conditions. For example:
1665        //
1666        // if return { println!("A") } { } // Prints "A"
1667        ret_value: option!(ambiguous_expr!(allow_struct)) >>
1668        (ExprRet {
1669            expr: ret_value.map(Box::new),
1670            return_token: return_,
1671        }.into())
1672    ));
1673
1674    #[cfg(feature = "full")]
1675    impl Synom for ExprStruct {
1676        named!(parse -> Self, do_parse!(
1677            path: syn!(Path) >>
1678            data: braces!(do_parse!(
1679                fields: call!(Delimited::parse_terminated) >>
1680                base: option!(
1681                    cond!(fields.is_empty() || fields.trailing_delim(),
1682                        do_parse!(
1683                            dots: syn!(Dot2) >>
1684                            base: syn!(Expr) >>
1685                            (dots, base)
1686                        )
1687                    )
1688                ) >>
1689                (fields, base)
1690            )) >>
1691            ({
1692                let ((fields, base), brace) = data;
1693                let (dots, rest) = match base.and_then(|b| b) {
1694                    Some((dots, base)) => (Some(dots), Some(base)),
1695                    None => (None, None),
1696                };
1697                ExprStruct {
1698                    brace_token: brace,
1699                    path: path,
1700                    fields: fields,
1701                    dot2_token: dots,
1702                    rest: rest.map(Box::new),
1703                }
1704            })
1705        ));
1706    }
1707
1708    #[cfg(feature = "full")]
1709    impl Synom for FieldValue {
1710        named!(parse -> Self, alt!(
1711            do_parse!(
1712                ident: field_ident >>
1713                colon: syn!(Colon) >>
1714                value: syn!(Expr) >>
1715                (FieldValue {
1716                    ident: ident,
1717                    expr: value,
1718                    is_shorthand: false,
1719                    attrs: Vec::new(),
1720                    colon_token: Some(colon),
1721                })
1722            )
1723            |
1724            map!(syn!(Ident), |name| FieldValue {
1725                ident: name.clone(),
1726                expr: ExprKind::Path(ExprPath { qself: None, path: name.into() }).into(),
1727                is_shorthand: true,
1728                attrs: Vec::new(),
1729                colon_token: None,
1730            })
1731        ));
1732    }
1733
1734    #[cfg(feature = "full")]
1735    impl Synom for ExprRepeat {
1736        named!(parse -> Self, do_parse!(
1737            data: brackets!(do_parse!(
1738                value: syn!(Expr) >>
1739                semi: syn!(Semi) >>
1740                times: syn!(Expr) >>
1741                (value, semi, times)
1742            )) >>
1743            (ExprRepeat {
1744                expr: Box::new((data.0).0),
1745                amt: Box::new((data.0).2),
1746                bracket_token: data.1,
1747                semi_token: (data.0).1,
1748            })
1749        ));
1750    }
1751
1752    #[cfg(feature = "full")]
1753    impl Synom for ExprBlock {
1754        named!(parse -> Self, do_parse!(
1755            rules: syn!(Unsafety) >>
1756            b: syn!(Block) >>
1757            (ExprBlock {
1758                unsafety: rules,
1759                block: b,
1760            })
1761        ));
1762    }
1763
1764    #[cfg(feature = "full")]
1765    named!(expr_range(allow_struct: bool) -> ExprKind, do_parse!(
1766        limits: syn!(RangeLimits) >>
1767        hi: opt_ambiguous_expr!(allow_struct) >>
1768        (ExprRange { from: None, to: hi.map(Box::new), limits: limits }.into())
1769    ));
1770
1771    #[cfg(feature = "full")]
1772    impl Synom for RangeLimits {
1773        named!(parse -> Self, alt!(
1774            // Must come before Dot2
1775            syn!(Dot3) => { RangeLimits::Closed }
1776            |
1777            syn!(Dot2) => { RangeLimits::HalfOpen }
1778        ));
1779    }
1780
1781    impl Synom for ExprPath {
1782        named!(parse -> Self, do_parse!(
1783            pair: qpath >>
1784            (ExprPath {
1785                qself: pair.0,
1786                path: pair.1,
1787            })
1788        ));
1789    }
1790
1791    #[cfg(feature = "full")]
1792    named!(and_field -> (Ident, Dot),
1793           map!(tuple!(syn!(Dot), syn!(Ident)), |(a, b)| (b, a)));
1794
1795    #[cfg(feature = "full")]
1796    named!(and_tup_field -> (Lit, Dot),
1797           map!(tuple!(syn!(Dot), syn!(Lit)), |(a, b)| (b, a)));
1798
1799    named!(and_index -> (Expr, tokens::Bracket), brackets!(syn!(Expr)));
1800
1801    #[cfg(feature = "full")]
1802    impl Synom for Block {
1803        named!(parse -> Self, do_parse!(
1804            stmts: braces!(call!(Block::parse_within)) >>
1805            (Block {
1806                stmts: stmts.0,
1807                brace_token: stmts.1,
1808            })
1809        ));
1810    }
1811
1812    #[cfg(feature = "full")]
1813    impl Block {
1814        named!(pub parse_within -> Vec<Stmt>, do_parse!(
1815            many0!(syn!(Semi)) >>
1816            mut standalone: many0!(terminated!(syn!(Stmt), many0!(syn!(Semi)))) >>
1817            last: option!(syn!(Expr)) >>
1818            (match last {
1819                None => standalone,
1820                Some(last) => {
1821                    standalone.push(Stmt::Expr(Box::new(last)));
1822                    standalone
1823                }
1824            })
1825        ));
1826    }
1827
1828    #[cfg(feature = "full")]
1829    impl Synom for Stmt {
1830        named!(parse -> Self, alt!(
1831            stmt_mac
1832            |
1833            stmt_local
1834            |
1835            stmt_item
1836            |
1837            stmt_blockexpr
1838            |
1839            stmt_expr
1840        ));
1841    }
1842
1843    #[cfg(feature = "full")]
1844    named!(stmt_mac -> Stmt, do_parse!(
1845        attrs: many0!(call!(Attribute::parse_outer)) >>
1846        what: syn!(Path) >>
1847        bang: syn!(Bang) >>
1848    // Only parse braces here; paren and bracket will get parsed as
1849    // expression statements
1850        data: braces!(syn!(TokenStream)) >>
1851        semi: option!(syn!(Semi)) >>
1852        (Stmt::Mac(Box::new((
1853            Mac {
1854                path: what,
1855                bang_token: bang,
1856                ident: None,
1857                tokens: vec![TokenTree(proc_macro2::TokenTree {
1858                    span: ((data.1).0).0,
1859                    kind: TokenNode::Group(Delimiter::Brace, data.0),
1860                })],
1861            },
1862            match semi {
1863                Some(semi) => MacStmtStyle::Semicolon(semi),
1864                None => MacStmtStyle::Braces,
1865            },
1866            attrs,
1867        ))))
1868    ));
1869
1870    #[cfg(feature = "full")]
1871    named!(stmt_local -> Stmt, do_parse!(
1872        attrs: many0!(call!(Attribute::parse_outer)) >>
1873        let_: syn!(Let) >>
1874        pat: syn!(Pat) >>
1875        ty: option!(tuple!(syn!(Colon), syn!(Ty))) >>
1876        init: option!(tuple!(syn!(Eq), syn!(Expr))) >>
1877        semi: syn!(Semi) >>
1878        (Stmt::Local(Box::new(Local {
1879            let_token: let_,
1880            semi_token: semi,
1881            colon_token: ty.as_ref().map(|p| Colon((p.0).0)),
1882            eq_token: init.as_ref().map(|p| Eq((p.0).0)),
1883            pat: Box::new(pat),
1884            ty: ty.map(|p| Box::new(p.1)),
1885            init: init.map(|p| Box::new(p.1)),
1886            attrs: attrs,
1887        })))
1888    ));
1889
1890    #[cfg(feature = "full")]
1891    named!(stmt_item -> Stmt, map!(syn!(Item), |i| Stmt::Item(Box::new(i))));
1892
1893    #[cfg(feature = "full")]
1894    named!(stmt_blockexpr -> Stmt, do_parse!(
1895        attrs: many0!(call!(Attribute::parse_outer)) >>
1896        mut e: expr_nosemi >>
1897        // If the next token is a `.` or a `?` it is special-cased to parse as
1898        // an expression instead of a blockexpression.
1899        not!(syn!(Dot)) >>
1900        not!(syn!(Question)) >>
1901        semi: option!(syn!(Semi)) >>
1902        ({
1903            e.attrs = attrs;
1904            if let Some(semi) = semi {
1905                Stmt::Semi(Box::new(e), semi)
1906            } else {
1907                Stmt::Expr(Box::new(e))
1908            }
1909        })
1910    ));
1911
1912    #[cfg(feature = "full")]
1913    named!(stmt_expr -> Stmt, do_parse!(
1914        attrs: many0!(call!(Attribute::parse_outer)) >>
1915        mut e: syn!(Expr) >>
1916        semi: syn!(Semi) >>
1917        ({
1918            e.attrs = attrs;
1919            Stmt::Semi(Box::new(e), semi)
1920        })
1921    ));
1922
1923    #[cfg(feature = "full")]
1924    impl Synom for Pat {
1925        named!(parse -> Self, alt!(
1926            syn!(PatWild) => { Pat::Wild } // must be before pat_ident
1927            |
1928            syn!(PatBox) => { Pat::Box }  // must be before pat_ident
1929            |
1930            syn!(PatRange) => { Pat::Range } // must be before pat_lit
1931            |
1932            syn!(PatTupleStruct) => { Pat::TupleStruct }  // must be before pat_ident
1933            |
1934            syn!(PatStruct) => { Pat::Struct } // must be before pat_ident
1935            |
1936            syn!(Mac) => { Pat::Mac } // must be before pat_ident
1937            |
1938            syn!(PatLit) => { Pat::Lit } // must be before pat_ident
1939            |
1940            syn!(PatIdent) => { Pat::Ident } // must be before pat_path
1941            |
1942            syn!(PatPath) => { Pat::Path }
1943            |
1944            syn!(PatTuple) => { Pat::Tuple }
1945            |
1946            syn!(PatRef) => { Pat::Ref }
1947            |
1948            syn!(PatSlice) => { Pat::Slice }
1949        ));
1950    }
1951
1952    #[cfg(feature = "full")]
1953    impl Synom for PatWild {
1954        named!(parse -> Self, map!(
1955            syn!(Underscore),
1956            |u| PatWild { underscore_token: u }
1957        ));
1958    }
1959
1960    #[cfg(feature = "full")]
1961    impl Synom for PatBox {
1962        named!(parse -> Self, do_parse!(
1963            boxed: syn!(Box_) >>
1964            pat: syn!(Pat) >>
1965            (PatBox {
1966                pat: Box::new(pat),
1967                box_token: boxed,
1968            })
1969        ));
1970    }
1971
1972    #[cfg(feature = "full")]
1973    impl Synom for PatIdent {
1974        named!(parse -> Self, do_parse!(
1975            mode: option!(syn!(Ref)) >>
1976            mutability: syn!(Mutability) >>
1977            name: alt!(
1978                syn!(Ident)
1979                |
1980                syn!(Self_) => { Into::into }
1981            ) >>
1982            not!(syn!(Lt)) >>
1983            not!(syn!(Colon2)) >>
1984            subpat: option!(tuple!(syn!(At), syn!(Pat))) >>
1985            (PatIdent {
1986                mode: match mode {
1987                    Some(mode) => BindingMode::ByRef(mode, mutability),
1988                    None => BindingMode::ByValue(mutability),
1989                },
1990                ident: name,
1991                at_token: subpat.as_ref().map(|p| At((p.0).0)),
1992                subpat: subpat.map(|p| Box::new(p.1)),
1993            })
1994        ));
1995    }
1996
1997    #[cfg(feature = "full")]
1998    impl Synom for PatTupleStruct {
1999        named!(parse -> Self, do_parse!(
2000            path: syn!(Path) >>
2001            tuple: syn!(PatTuple) >>
2002            (PatTupleStruct {
2003                path: path,
2004                pat: tuple,
2005            })
2006        ));
2007    }
2008
2009    #[cfg(feature = "full")]
2010    impl Synom for PatStruct {
2011        named!(parse -> Self, do_parse!(
2012            path: syn!(Path) >>
2013            data: braces!(do_parse!(
2014                fields: call!(Delimited::parse_terminated) >>
2015                base: option!(
2016                    cond!(fields.is_empty() || fields.trailing_delim(),
2017                          syn!(Dot2))
2018                ) >>
2019                (fields, base)
2020            )) >>
2021            (PatStruct {
2022                path: path,
2023                fields: (data.0).0,
2024                brace_token: data.1,
2025                dot2_token: (data.0).1.and_then(|m| m),
2026            })
2027        ));
2028    }
2029
2030    #[cfg(feature = "full")]
2031    impl Synom for FieldPat {
2032        named!(parse -> Self, alt!(
2033            do_parse!(
2034                ident: field_ident >>
2035                colon: syn!(Colon) >>
2036                pat: syn!(Pat) >>
2037                (FieldPat {
2038                    ident: ident,
2039                    pat: Box::new(pat),
2040                    is_shorthand: false,
2041                    attrs: Vec::new(),
2042                    colon_token: Some(colon),
2043                })
2044            )
2045            |
2046            do_parse!(
2047                boxed: option!(syn!(Box_)) >>
2048                mode: option!(syn!(Ref)) >>
2049                mutability: syn!(Mutability) >>
2050                ident: syn!(Ident) >>
2051                ({
2052                    let mut pat: Pat = PatIdent {
2053                        mode: if let Some(mode) = mode {
2054                            BindingMode::ByRef(mode, mutability)
2055                        } else {
2056                            BindingMode::ByValue(mutability)
2057                        },
2058                        ident: ident.clone(),
2059                        subpat: None,
2060                        at_token: None,
2061                    }.into();
2062                    if let Some(boxed) = boxed {
2063                        pat = PatBox {
2064                            pat: Box::new(pat),
2065                            box_token: boxed,
2066                        }.into();
2067                    }
2068                    FieldPat {
2069                        ident: ident,
2070                        pat: Box::new(pat),
2071                        is_shorthand: true,
2072                        attrs: Vec::new(),
2073                        colon_token: None,
2074                    }
2075                })
2076            )
2077        ));
2078    }
2079
2080    #[cfg(feature = "full")]
2081    named!(field_ident -> Ident, alt!(
2082        syn!(Ident)
2083        |
2084        do_parse!(
2085            lit: syn!(Lit) >>
2086            ({
2087                let s = lit.to_string();
2088                if s.parse::<usize>().is_ok() {
2089                    Ident::new(Term::intern(&s), lit.span)
2090                } else {
2091                    return parse_error();
2092                }
2093            })
2094        )
2095    ));
2096
2097    #[cfg(feature = "full")]
2098    impl Synom for PatPath {
2099        named!(parse -> Self, map!(
2100            syn!(ExprPath),
2101            |p| PatPath { qself: p.qself, path: p.path }
2102        ));
2103    }
2104
2105    #[cfg(feature = "full")]
2106    impl Synom for PatTuple {
2107        named!(parse -> Self, do_parse!(
2108            data: parens!(do_parse!(
2109                elems: call!(Delimited::parse_terminated) >>
2110                dotdot: map!(cond!(
2111                    elems.is_empty() || elems.trailing_delim(),
2112                    option!(do_parse!(
2113                        dots: syn!(Dot2) >>
2114                        trailing: option!(syn!(Comma)) >>
2115                        (dots, trailing)
2116                    ))
2117                ), |x| x.and_then(|x| x)) >>
2118                rest: cond!(match dotdot {
2119                                Some((_, Some(_))) => true,
2120                                _ => false,
2121                            },
2122                            call!(Delimited::parse_terminated)) >>
2123                (elems, dotdot, rest)
2124            )) >>
2125            ({
2126                let ((mut elems, dotdot, rest), parens) = data;
2127                let (dotdot, trailing) = match dotdot {
2128                    Some((a, b)) => (Some(a), Some(b)),
2129                    None => (None, None),
2130                };
2131                PatTuple {
2132                    paren_token: parens,
2133                    dots_pos: dotdot.as_ref().map(|_| elems.len()),
2134                    dot2_token: dotdot,
2135                    comma_token: trailing.and_then(|b| b),
2136                    pats: {
2137                        if let Some(rest) = rest {
2138                            for elem in rest {
2139                                elems.push(elem);
2140                            }
2141                        }
2142                        elems
2143                    },
2144                }
2145            })
2146        ));
2147    }
2148
2149    #[cfg(feature = "full")]
2150    impl Synom for PatRef {
2151        named!(parse -> Self, do_parse!(
2152            and: syn!(And) >>
2153            mutability: syn!(Mutability) >>
2154            pat: syn!(Pat) >>
2155            (PatRef {
2156                pat: Box::new(pat),
2157                mutbl: mutability,
2158                and_token: and,
2159            })
2160        ));
2161    }
2162
2163    #[cfg(feature = "full")]
2164    impl Synom for PatLit {
2165        named!(parse -> Self, do_parse!(
2166            lit: pat_lit_expr >>
2167            (if let ExprKind::Path(_) = lit.node {
2168                return parse_error(); // these need to be parsed by pat_path
2169            } else {
2170                PatLit {
2171                    expr: Box::new(lit),
2172                }
2173            })
2174        ));
2175    }
2176
2177    #[cfg(feature = "full")]
2178    impl Synom for PatRange {
2179        named!(parse -> Self, do_parse!(
2180            lo: pat_lit_expr >>
2181            limits: syn!(RangeLimits) >>
2182            hi: pat_lit_expr >>
2183            (PatRange {
2184                lo: Box::new(lo),
2185                hi: Box::new(hi),
2186                limits: limits,
2187            })
2188        ));
2189    }
2190
2191    #[cfg(feature = "full")]
2192    named!(pat_lit_expr -> Expr, do_parse!(
2193        neg: option!(syn!(Sub)) >>
2194        v: alt!(
2195            syn!(Lit) => { ExprKind::Lit }
2196            |
2197            syn!(ExprPath) => { ExprKind::Path }
2198        ) >>
2199        (if neg.is_some() {
2200            ExprKind::Unary(ExprUnary {
2201                op: UnOp::Neg(tokens::Sub::default()),
2202                expr: Box::new(v.into())
2203            }).into()
2204        } else {
2205            v.into()
2206        })
2207    ));
2208
2209    #[cfg(feature = "full")]
2210    impl Synom for PatSlice {
2211        named!(parse -> Self, map!(
2212            brackets!(do_parse!(
2213                before: call!(Delimited::parse_terminated) >>
2214                middle: option!(do_parse!(
2215                    dots: syn!(Dot2) >>
2216                    trailing: option!(syn!(Comma)) >>
2217                    (dots, trailing)
2218                )) >>
2219                after: cond!(
2220                    match middle {
2221                        Some((_, ref trailing)) => trailing.is_some(),
2222                        _ => false,
2223                    },
2224                    call!(Delimited::parse_terminated)
2225                ) >>
2226                (before, middle, after)
2227            )),
2228            |((before, middle, after), brackets)| {
2229                let mut before: Delimited<Pat, tokens::Comma> = before;
2230                let after: Option<Delimited<Pat, tokens::Comma>> = after;
2231                let middle: Option<(Dot2, Option<Comma>)> = middle;
2232                PatSlice {
2233                    dot2_token: middle.as_ref().map(|m| Dot2((m.0).0)),
2234                    comma_token: middle.as_ref().and_then(|m| {
2235                        m.1.as_ref().map(|m| Comma(m.0))
2236                    }),
2237                    bracket_token: brackets,
2238                    middle: middle.and_then(|_| {
2239                        if !before.is_empty() && !before.trailing_delim() {
2240                            Some(Box::new(before.pop().unwrap().into_item()))
2241                        } else {
2242                            None
2243                        }
2244                    }),
2245                    front: before,
2246                    back: after.unwrap_or_default(),
2247                }
2248            }
2249        ));
2250    }
2251
2252    #[cfg(feature = "full")]
2253    impl Synom for CaptureBy {
2254        named!(parse -> Self, alt!(
2255            syn!(Move) => { CaptureBy::Value }
2256            |
2257            epsilon!() => { |_| CaptureBy::Ref }
2258        ));
2259    }
2260}
2261
2262#[cfg(feature = "printing")]
2263mod printing {
2264    use super::*;
2265    #[cfg(feature = "full")]
2266    use attr::FilterAttrs;
2267    use quote::{Tokens, ToTokens};
2268
2269    /// If the given expression is a bare `ExprStruct`, wraps it in parenthesis
2270    /// before appending it to `Tokens`.
2271    #[cfg(feature = "full")]
2272    fn wrap_bare_struct(tokens: &mut Tokens, e: &Expr) {
2273        if let ExprKind::Struct(_) = e.node {
2274            tokens::Paren::default().surround(tokens, |tokens| {
2275                e.to_tokens(tokens);
2276            });
2277        } else {
2278            e.to_tokens(tokens);
2279        }
2280    }
2281
2282    impl ToTokens for Expr {
2283        #[cfg(feature = "full")]
2284        fn to_tokens(&self, tokens: &mut Tokens) {
2285            tokens.append_all(self.attrs.outer());
2286            self.node.to_tokens(tokens)
2287        }
2288
2289        #[cfg(not(feature = "full"))]
2290        fn to_tokens(&self, tokens: &mut Tokens) {
2291            self.node.to_tokens(tokens)
2292        }
2293    }
2294
2295    #[cfg(feature = "full")]
2296    impl ToTokens for ExprBox {
2297        fn to_tokens(&self, tokens: &mut Tokens) {
2298            self.box_token.to_tokens(tokens);
2299            self.expr.to_tokens(tokens);
2300        }
2301    }
2302
2303    #[cfg(feature = "full")]
2304    impl ToTokens for ExprInPlace {
2305        fn to_tokens(&self, tokens: &mut Tokens) {
2306            match self.kind {
2307                InPlaceKind::Arrow(ref arrow) => {
2308                    self.place.to_tokens(tokens);
2309                    arrow.to_tokens(tokens);
2310                    self.value.to_tokens(tokens);
2311                }
2312                InPlaceKind::In(ref _in) => {
2313                    _in.to_tokens(tokens);
2314                    self.place.to_tokens(tokens);
2315                    // NOTE: The second operand must be in a block, add one if
2316                    // it is not present.
2317                    if let ExprKind::Block(_) = self.value.node {
2318                        self.value.to_tokens(tokens);
2319                    } else {
2320                        tokens::Brace::default().surround(tokens, |tokens| {
2321                            self.value.to_tokens(tokens);
2322                        })
2323                    }
2324                }
2325            }
2326        }
2327    }
2328
2329    #[cfg(feature = "full")]
2330    impl ToTokens for ExprArray {
2331        fn to_tokens(&self, tokens: &mut Tokens) {
2332            self.bracket_token.surround(tokens, |tokens| {
2333                self.exprs.to_tokens(tokens);
2334            })
2335        }
2336    }
2337
2338    impl ToTokens for ExprCall {
2339        fn to_tokens(&self, tokens: &mut Tokens) {
2340            self.func.to_tokens(tokens);
2341            self.paren_token.surround(tokens, |tokens| {
2342                self.args.to_tokens(tokens);
2343            })
2344        }
2345    }
2346
2347    #[cfg(feature = "full")]
2348    impl ToTokens for ExprMethodCall {
2349        fn to_tokens(&self, tokens: &mut Tokens) {
2350            self.expr.to_tokens(tokens);
2351            self.dot_token.to_tokens(tokens);
2352            self.method.to_tokens(tokens);
2353            if !self.typarams.is_empty() {
2354                TokensOrDefault(&self.colon2_token).to_tokens(tokens);
2355                TokensOrDefault(&self.lt_token).to_tokens(tokens);
2356                self.typarams.to_tokens(tokens);
2357                TokensOrDefault(&self.gt_token).to_tokens(tokens);
2358            }
2359            self.paren_token.surround(tokens, |tokens| {
2360                self.args.to_tokens(tokens);
2361            });
2362        }
2363    }
2364
2365    #[cfg(feature = "full")]
2366    impl ToTokens for ExprTup {
2367        fn to_tokens(&self, tokens: &mut Tokens) {
2368            self.paren_token.surround(tokens, |tokens| {
2369                self.args.to_tokens(tokens);
2370                // If we only have one argument, we need a trailing comma to
2371                // distinguish ExprTup from ExprParen.
2372                if self.args.len() == 1 && !self.args.trailing_delim() {
2373                    tokens::Comma::default().to_tokens(tokens);
2374                }
2375                // XXX: Not sure how to handle this, but we never parse it yet.
2376                // Is this for an expression like (0,)? Can't we use the
2377                // trailing delimiter on Delimited for that? (,) isn't a valid
2378                // expression as far as I know.
2379                self.lone_comma.to_tokens(tokens);
2380            })
2381        }
2382    }
2383
2384    impl ToTokens for ExprBinary {
2385        fn to_tokens(&self, tokens: &mut Tokens) {
2386            self.left.to_tokens(tokens);
2387            self.op.to_tokens(tokens);
2388            self.right.to_tokens(tokens);
2389        }
2390    }
2391
2392    impl ToTokens for ExprUnary {
2393        fn to_tokens(&self, tokens: &mut Tokens) {
2394            self.op.to_tokens(tokens);
2395            self.expr.to_tokens(tokens);
2396        }
2397    }
2398
2399    impl ToTokens for ExprCast {
2400        fn to_tokens(&self, tokens: &mut Tokens) {
2401            self.expr.to_tokens(tokens);
2402            self.as_token.to_tokens(tokens);
2403            self.ty.to_tokens(tokens);
2404        }
2405    }
2406
2407    impl ToTokens for ExprType {
2408        fn to_tokens(&self, tokens: &mut Tokens) {
2409            self.expr.to_tokens(tokens);
2410            self.colon_token.to_tokens(tokens);
2411            self.ty.to_tokens(tokens);
2412        }
2413    }
2414
2415    #[cfg(feature = "full")]
2416    fn maybe_wrap_else(tokens: &mut Tokens,
2417                       else_token: &Option<tokens::Else>,
2418                       if_false: &Option<Box<Expr>>)
2419    {
2420        if let Some(ref if_false) = *if_false {
2421            TokensOrDefault(&else_token).to_tokens(tokens);
2422
2423            // If we are not one of the valid expressions to exist in an else
2424            // clause, wrap ourselves in a block.
2425            match if_false.node {
2426                ExprKind::If(_) |
2427                ExprKind::IfLet(_) |
2428                ExprKind::Block(_) => {
2429                    if_false.to_tokens(tokens);
2430                }
2431                _ => {
2432                    tokens::Brace::default().surround(tokens, |tokens| {
2433                        if_false.to_tokens(tokens);
2434                    });
2435                }
2436            }
2437        }
2438    }
2439
2440    #[cfg(feature = "full")]
2441    impl ToTokens for ExprIf {
2442        fn to_tokens(&self, tokens: &mut Tokens) {
2443            self.if_token.to_tokens(tokens);
2444            wrap_bare_struct(tokens, &self.cond);
2445            self.if_true.to_tokens(tokens);
2446            maybe_wrap_else(tokens, &self.else_token, &self.if_false);
2447        }
2448    }
2449
2450    #[cfg(feature = "full")]
2451    impl ToTokens for ExprIfLet {
2452        fn to_tokens(&self, tokens: &mut Tokens) {
2453            self.if_token.to_tokens(tokens);
2454            self.let_token.to_tokens(tokens);
2455            self.pat.to_tokens(tokens);
2456            self.eq_token.to_tokens(tokens);
2457            wrap_bare_struct(tokens, &self.expr);
2458            self.if_true.to_tokens(tokens);
2459            maybe_wrap_else(tokens, &self.else_token, &self.if_false);
2460        }
2461    }
2462
2463    #[cfg(feature = "full")]
2464    impl ToTokens for ExprWhile {
2465        fn to_tokens(&self, tokens: &mut Tokens) {
2466            if self.label.is_some() {
2467                self.label.to_tokens(tokens);
2468                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2469            }
2470            self.while_token.to_tokens(tokens);
2471            wrap_bare_struct(tokens, &self.cond);
2472            self.body.to_tokens(tokens);
2473        }
2474    }
2475
2476    #[cfg(feature = "full")]
2477    impl ToTokens for ExprWhileLet {
2478        fn to_tokens(&self, tokens: &mut Tokens) {
2479            if self.label.is_some() {
2480                self.label.to_tokens(tokens);
2481                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2482            }
2483            self.while_token.to_tokens(tokens);
2484            self.let_token.to_tokens(tokens);
2485            self.pat.to_tokens(tokens);
2486            self.eq_token.to_tokens(tokens);
2487            wrap_bare_struct(tokens, &self.expr);
2488            self.body.to_tokens(tokens);
2489        }
2490    }
2491
2492    #[cfg(feature = "full")]
2493    impl ToTokens for ExprForLoop {
2494        fn to_tokens(&self, tokens: &mut Tokens) {
2495            if self.label.is_some() {
2496                self.label.to_tokens(tokens);
2497                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2498            }
2499            self.for_token.to_tokens(tokens);
2500            self.pat.to_tokens(tokens);
2501            self.in_token.to_tokens(tokens);
2502            wrap_bare_struct(tokens, &self.expr);
2503            self.body.to_tokens(tokens);
2504        }
2505    }
2506
2507    #[cfg(feature = "full")]
2508    impl ToTokens for ExprLoop {
2509        fn to_tokens(&self, tokens: &mut Tokens) {
2510            if self.label.is_some() {
2511                self.label.to_tokens(tokens);
2512                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2513            }
2514            self.loop_token.to_tokens(tokens);
2515            self.body.to_tokens(tokens);
2516        }
2517    }
2518
2519    #[cfg(feature = "full")]
2520    impl ToTokens for ExprMatch {
2521        fn to_tokens(&self, tokens: &mut Tokens) {
2522            self.match_token.to_tokens(tokens);
2523            wrap_bare_struct(tokens, &self.expr);
2524            self.brace_token.surround(tokens, |tokens| {
2525                for (i,  arm) in self.arms.iter().enumerate() {
2526                    arm.to_tokens(tokens);
2527                    // Ensure that we have a comma after a non-block arm, except
2528                    // for the last one.
2529                    let is_last = i == self.arms.len() - 1;
2530                    if !is_last && arm_requires_comma(arm) && arm.comma.is_none() {
2531                        tokens::Comma::default().to_tokens(tokens);
2532                    }
2533                }
2534            });
2535        }
2536    }
2537
2538    #[cfg(feature = "full")]
2539    impl ToTokens for ExprCatch {
2540        fn to_tokens(&self, tokens: &mut Tokens) {
2541            self.do_token.to_tokens(tokens);
2542            self.catch_token.to_tokens(tokens);
2543            self.block.to_tokens(tokens);
2544        }
2545    }
2546
2547    #[cfg(feature = "full")]
2548    impl ToTokens for ExprYield {
2549        fn to_tokens(&self, tokens: &mut Tokens) {
2550            self.yield_token.to_tokens(tokens);
2551            self.expr.to_tokens(tokens);
2552        }
2553    }
2554
2555    #[cfg(feature = "full")]
2556    impl ToTokens for ExprClosure {
2557        fn to_tokens(&self, tokens: &mut Tokens) {
2558            self.capture.to_tokens(tokens);
2559            self.or1_token.to_tokens(tokens);
2560            for item in self.decl.inputs.iter() {
2561                match **item.item() {
2562                    FnArg::Captured(ArgCaptured { ref pat, ty: Ty::Infer(_), .. }) => {
2563                        pat.to_tokens(tokens);
2564                    }
2565                    _ => item.item().to_tokens(tokens),
2566                }
2567                item.delimiter().to_tokens(tokens);
2568            }
2569            self.or2_token.to_tokens(tokens);
2570            self.decl.output.to_tokens(tokens);
2571            self.body.to_tokens(tokens);
2572        }
2573    }
2574
2575    #[cfg(feature = "full")]
2576    impl ToTokens for ExprBlock {
2577        fn to_tokens(&self, tokens: &mut Tokens) {
2578            self.unsafety.to_tokens(tokens);
2579            self.block.to_tokens(tokens);
2580        }
2581    }
2582
2583    #[cfg(feature = "full")]
2584    impl ToTokens for ExprAssign {
2585        fn to_tokens(&self, tokens: &mut Tokens) {
2586            self.left.to_tokens(tokens);
2587            self.eq_token.to_tokens(tokens);
2588            self.right.to_tokens(tokens);
2589        }
2590    }
2591
2592    #[cfg(feature = "full")]
2593    impl ToTokens for ExprAssignOp {
2594        fn to_tokens(&self, tokens: &mut Tokens) {
2595            self.left.to_tokens(tokens);
2596            self.op.to_tokens(tokens);
2597            self.right.to_tokens(tokens);
2598        }
2599    }
2600
2601    #[cfg(feature = "full")]
2602    impl ToTokens for ExprField {
2603        fn to_tokens(&self, tokens: &mut Tokens) {
2604            self.expr.to_tokens(tokens);
2605            self.dot_token.to_tokens(tokens);
2606            // XXX: I don't think we can do anything if someone shoves a
2607            // nonsense Lit in here.
2608            self.field.to_tokens(tokens);
2609        }
2610    }
2611
2612    #[cfg(feature = "full")]
2613    impl ToTokens for ExprTupField {
2614        fn to_tokens(&self, tokens: &mut Tokens) {
2615            self.expr.to_tokens(tokens);
2616            self.dot_token.to_tokens(tokens);
2617            self.field.to_tokens(tokens);
2618        }
2619    }
2620
2621    impl ToTokens for ExprIndex {
2622        fn to_tokens(&self, tokens: &mut Tokens) {
2623            self.expr.to_tokens(tokens);
2624            self.bracket_token.surround(tokens, |tokens| {
2625                self.index.to_tokens(tokens);
2626            });
2627        }
2628    }
2629
2630    #[cfg(feature = "full")]
2631    impl ToTokens for ExprRange {
2632        fn to_tokens(&self, tokens: &mut Tokens) {
2633            self.from.to_tokens(tokens);
2634            self.limits.to_tokens(tokens);
2635            self.to.to_tokens(tokens);
2636        }
2637    }
2638
2639    impl ToTokens for ExprPath {
2640        fn to_tokens(&self, tokens: &mut Tokens) {
2641            ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
2642        }
2643    }
2644
2645    #[cfg(feature = "full")]
2646    impl ToTokens for ExprAddrOf {
2647        fn to_tokens(&self, tokens: &mut Tokens) {
2648            self.and_token.to_tokens(tokens);
2649            self.mutbl.to_tokens(tokens);
2650            self.expr.to_tokens(tokens);
2651        }
2652    }
2653
2654    #[cfg(feature = "full")]
2655    impl ToTokens for ExprBreak {
2656        fn to_tokens(&self, tokens: &mut Tokens) {
2657            self.break_token.to_tokens(tokens);
2658            self.label.to_tokens(tokens);
2659            self.expr.to_tokens(tokens);
2660        }
2661    }
2662
2663    #[cfg(feature = "full")]
2664    impl ToTokens for ExprContinue {
2665        fn to_tokens(&self, tokens: &mut Tokens) {
2666            self.continue_token.to_tokens(tokens);
2667            self.label.to_tokens(tokens);
2668        }
2669    }
2670
2671    #[cfg(feature = "full")]
2672    impl ToTokens for ExprRet {
2673        fn to_tokens(&self, tokens: &mut Tokens) {
2674            self.return_token.to_tokens(tokens);
2675            self.expr.to_tokens(tokens);
2676        }
2677    }
2678
2679    #[cfg(feature = "full")]
2680    impl ToTokens for ExprStruct {
2681        fn to_tokens(&self, tokens: &mut Tokens) {
2682            self.path.to_tokens(tokens);
2683            self.brace_token.surround(tokens, |tokens| {
2684                self.fields.to_tokens(tokens);
2685                if self.rest.is_some() {
2686                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
2687                    self.rest.to_tokens(tokens);
2688                }
2689            })
2690        }
2691    }
2692
2693    #[cfg(feature = "full")]
2694    impl ToTokens for ExprRepeat {
2695        fn to_tokens(&self, tokens: &mut Tokens) {
2696            self.bracket_token.surround(tokens, |tokens| {
2697                self.expr.to_tokens(tokens);
2698                self.semi_token.to_tokens(tokens);
2699                self.amt.to_tokens(tokens);
2700            })
2701        }
2702    }
2703
2704    impl ToTokens for ExprGroup {
2705        fn to_tokens(&self, tokens: &mut Tokens) {
2706            self.group_token.surround(tokens, |tokens| {
2707                self.expr.to_tokens(tokens);
2708            });
2709        }
2710    }
2711
2712    impl ToTokens for ExprParen {
2713        fn to_tokens(&self, tokens: &mut Tokens) {
2714            self.paren_token.surround(tokens, |tokens| {
2715                self.expr.to_tokens(tokens);
2716            });
2717        }
2718    }
2719
2720    #[cfg(feature = "full")]
2721    impl ToTokens for ExprTry {
2722        fn to_tokens(&self, tokens: &mut Tokens) {
2723            self.expr.to_tokens(tokens);
2724            self.question_token.to_tokens(tokens);
2725        }
2726    }
2727
2728    #[cfg(feature = "full")]
2729    impl ToTokens for FieldValue {
2730        fn to_tokens(&self, tokens: &mut Tokens) {
2731            self.ident.to_tokens(tokens);
2732            // XXX: Override self.is_shorthand if expr is not an IdentExpr with
2733            // the ident self.ident?
2734            if !self.is_shorthand {
2735                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2736                self.expr.to_tokens(tokens);
2737            }
2738        }
2739    }
2740
2741    #[cfg(feature = "full")]
2742    impl ToTokens for Arm {
2743        fn to_tokens(&self, tokens: &mut Tokens) {
2744            tokens.append_all(&self.attrs);
2745            self.pats.to_tokens(tokens);
2746            if self.guard.is_some() {
2747                TokensOrDefault(&self.if_token).to_tokens(tokens);
2748                self.guard.to_tokens(tokens);
2749            }
2750            self.rocket_token.to_tokens(tokens);
2751            self.body.to_tokens(tokens);
2752            self.comma.to_tokens(tokens);
2753        }
2754    }
2755
2756    #[cfg(feature = "full")]
2757    impl ToTokens for PatWild {
2758        fn to_tokens(&self, tokens: &mut Tokens) {
2759            self.underscore_token.to_tokens(tokens);
2760        }
2761    }
2762
2763    #[cfg(feature = "full")]
2764    impl ToTokens for PatIdent {
2765        fn to_tokens(&self, tokens: &mut Tokens) {
2766            self.mode.to_tokens(tokens);
2767            self.ident.to_tokens(tokens);
2768            if self.subpat.is_some() {
2769                TokensOrDefault(&self.at_token).to_tokens(tokens);
2770                self.subpat.to_tokens(tokens);
2771            }
2772        }
2773    }
2774
2775    #[cfg(feature = "full")]
2776    impl ToTokens for PatStruct {
2777        fn to_tokens(&self, tokens: &mut Tokens) {
2778            self.path.to_tokens(tokens);
2779            self.brace_token.surround(tokens, |tokens| {
2780                self.fields.to_tokens(tokens);
2781                // NOTE: We need a comma before the dot2 token if it is present.
2782                if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
2783                    tokens::Comma::default().to_tokens(tokens);
2784                }
2785                self.dot2_token.to_tokens(tokens);
2786            });
2787        }
2788    }
2789
2790    #[cfg(feature = "full")]
2791    impl ToTokens for PatTupleStruct {
2792        fn to_tokens(&self, tokens: &mut Tokens) {
2793            self.path.to_tokens(tokens);
2794            self.pat.to_tokens(tokens);
2795        }
2796    }
2797
2798    #[cfg(feature = "full")]
2799    impl ToTokens for PatPath {
2800        fn to_tokens(&self, tokens: &mut Tokens) {
2801            ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
2802        }
2803    }
2804
2805    #[cfg(feature = "full")]
2806    impl ToTokens for PatTuple {
2807        fn to_tokens(&self, tokens: &mut Tokens) {
2808            self.paren_token.surround(tokens, |tokens| {
2809                for (i, token) in self.pats.iter().enumerate() {
2810                    if Some(i) == self.dots_pos {
2811                        TokensOrDefault(&self.dot2_token).to_tokens(tokens);
2812                        TokensOrDefault(&self.comma_token).to_tokens(tokens);
2813                    }
2814                    token.to_tokens(tokens);
2815                }
2816
2817                if Some(self.pats.len()) == self.dots_pos {
2818                    // Ensure there is a comma before the .. token.
2819                    if !self.pats.empty_or_trailing() {
2820                        tokens::Comma::default().to_tokens(tokens);
2821                    }
2822                    self.dot2_token.to_tokens(tokens);
2823                }
2824            });
2825        }
2826    }
2827
2828    #[cfg(feature = "full")]
2829    impl ToTokens for PatBox {
2830        fn to_tokens(&self, tokens: &mut Tokens) {
2831            self.box_token.to_tokens(tokens);
2832            self.pat.to_tokens(tokens);
2833        }
2834    }
2835
2836    #[cfg(feature = "full")]
2837    impl ToTokens for PatRef {
2838        fn to_tokens(&self, tokens: &mut Tokens) {
2839            self.and_token.to_tokens(tokens);
2840            self.mutbl.to_tokens(tokens);
2841            self.pat.to_tokens(tokens);
2842        }
2843    }
2844
2845    #[cfg(feature = "full")]
2846    impl ToTokens for PatLit {
2847        fn to_tokens(&self, tokens: &mut Tokens) {
2848            self.expr.to_tokens(tokens);
2849        }
2850    }
2851
2852    #[cfg(feature = "full")]
2853    impl ToTokens for PatRange {
2854        fn to_tokens(&self, tokens: &mut Tokens) {
2855            self.lo.to_tokens(tokens);
2856            self.limits.to_tokens(tokens);
2857            self.hi.to_tokens(tokens);
2858        }
2859    }
2860
2861    #[cfg(feature = "full")]
2862    impl ToTokens for PatSlice {
2863        fn to_tokens(&self, tokens: &mut Tokens) {
2864            // XXX: This is a mess, and it will be so easy to screw it up. How
2865            // do we make this correct itself better?
2866            self.bracket_token.surround(tokens, |tokens| {
2867                self.front.to_tokens(tokens);
2868
2869                // If we need a comma before the middle or standalone .. token,
2870                // then make sure it's present.
2871                if !self.front.empty_or_trailing() &&
2872                    (self.middle.is_some() || self.dot2_token.is_some())
2873                {
2874                    tokens::Comma::default().to_tokens(tokens);
2875                }
2876
2877                // If we have an identifier, we always need a .. token.
2878                if self.middle.is_some() {
2879                    self.middle.to_tokens(tokens);
2880                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
2881                } else if self.dot2_token.is_some() {
2882                    self.dot2_token.to_tokens(tokens);
2883                }
2884
2885                // Make sure we have a comma before the back half.
2886                if !self.back.is_empty() {
2887                    TokensOrDefault(&self.comma_token).to_tokens(tokens);
2888                    self.back.to_tokens(tokens);
2889                } else {
2890                    self.comma_token.to_tokens(tokens);
2891                }
2892            })
2893        }
2894    }
2895
2896    #[cfg(feature = "full")]
2897    impl ToTokens for RangeLimits {
2898        fn to_tokens(&self, tokens: &mut Tokens) {
2899            match *self {
2900                RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
2901                RangeLimits::Closed(ref t) => t.to_tokens(tokens),
2902            }
2903        }
2904    }
2905
2906    #[cfg(feature = "full")]
2907    impl ToTokens for FieldPat {
2908        fn to_tokens(&self, tokens: &mut Tokens) {
2909            // XXX: Override is_shorthand if it was wrong?
2910            if !self.is_shorthand {
2911                self.ident.to_tokens(tokens);
2912                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2913            }
2914            self.pat.to_tokens(tokens);
2915        }
2916    }
2917
2918    #[cfg(feature = "full")]
2919    impl ToTokens for BindingMode {
2920        fn to_tokens(&self, tokens: &mut Tokens) {
2921            match *self {
2922                BindingMode::ByRef(ref t, ref m) => {
2923                    t.to_tokens(tokens);
2924                    m.to_tokens(tokens);
2925                }
2926                BindingMode::ByValue(ref m) => {
2927                    m.to_tokens(tokens);
2928                }
2929            }
2930        }
2931    }
2932
2933    #[cfg(feature = "full")]
2934    impl ToTokens for CaptureBy {
2935        fn to_tokens(&self, tokens: &mut Tokens) {
2936            match *self {
2937                CaptureBy::Value(ref t) => t.to_tokens(tokens),
2938                CaptureBy::Ref => {
2939                    // nothing
2940                }
2941            }
2942        }
2943    }
2944
2945    #[cfg(feature = "full")]
2946    impl ToTokens for Block {
2947        fn to_tokens(&self, tokens: &mut Tokens) {
2948            self.brace_token.surround(tokens, |tokens| {
2949                tokens.append_all(&self.stmts);
2950            });
2951        }
2952    }
2953
2954    #[cfg(feature = "full")]
2955    impl ToTokens for Stmt {
2956        fn to_tokens(&self, tokens: &mut Tokens) {
2957            match *self {
2958                Stmt::Local(ref local) => local.to_tokens(tokens),
2959                Stmt::Item(ref item) => item.to_tokens(tokens),
2960                Stmt::Expr(ref expr) => expr.to_tokens(tokens),
2961                Stmt::Semi(ref expr, ref semi) => {
2962                    expr.to_tokens(tokens);
2963                    semi.to_tokens(tokens);
2964                }
2965                Stmt::Mac(ref mac) => {
2966                    let (ref mac, ref style, ref attrs) = **mac;
2967                    tokens.append_all(attrs.outer());
2968                    mac.to_tokens(tokens);
2969                    match *style {
2970                        MacStmtStyle::Semicolon(ref s) => s.to_tokens(tokens),
2971                        MacStmtStyle::Braces | MacStmtStyle::NoBraces => {
2972                            // no semicolon
2973                        }
2974                    }
2975                }
2976            }
2977        }
2978    }
2979
2980    #[cfg(feature = "full")]
2981    impl ToTokens for Local {
2982        fn to_tokens(&self, tokens: &mut Tokens) {
2983            tokens.append_all(self.attrs.outer());
2984            self.let_token.to_tokens(tokens);
2985            self.pat.to_tokens(tokens);
2986            if self.ty.is_some() {
2987                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2988                self.ty.to_tokens(tokens);
2989            }
2990            if self.init.is_some() {
2991                TokensOrDefault(&self.eq_token).to_tokens(tokens);
2992                self.init.to_tokens(tokens);
2993            }
2994            self.semi_token.to_tokens(tokens);
2995        }
2996    }
2997}