futures_await_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_expr_requires_comma(expr: &Expr) -> bool {
628    // see https://github.com/rust-lang/rust/blob/eb8f2586e
629    //                       /src/libsyntax/parse/classify.rs#L17-L37
630    match expr.node {
631        ExprKind::Block(..) |
632        ExprKind::If(..) |
633        ExprKind::IfLet(..) |
634        ExprKind::Match(..) |
635        ExprKind::While(..) |
636        ExprKind::WhileLet(..) |
637        ExprKind::Loop(..) |
638        ExprKind::ForLoop(..) |
639        ExprKind::Catch(..) => false,
640        _ => true,
641    }
642}
643
644#[cfg(feature = "parsing")]
645pub mod parsing {
646    use super::*;
647    use ty::parsing::qpath;
648
649    #[cfg(feature = "full")]
650    use proc_macro2::{TokenStream, TokenNode, Delimiter, Term};
651    use synom::{PResult, Cursor, Synom};
652    #[cfg(feature = "full")]
653    use synom::parse_error;
654    use synom::tokens::*;
655
656    /// When we're parsing expressions which occur before blocks, like in
657    /// an if statement's condition, we cannot parse a struct literal.
658    ///
659    /// Struct literals are ambiguous in certain positions
660    /// https://github.com/rust-lang/rfcs/pull/92
661    macro_rules! ambiguous_expr {
662        ($i:expr, $allow_struct:ident) => {
663            ambiguous_expr($i, $allow_struct, true)
664        };
665    }
666
667    /// When we are parsing an optional suffix expression, we cannot allow
668    /// blocks if structs are not allowed.
669    ///
670    /// Example:
671    /// ```ignore
672    /// if break { } { }
673    /// // is ambiguous between:
674    /// if (break { }) { }
675    /// // - or -
676    /// if (break) { } { }
677    /// ```
678    #[cfg(feature = "full")]
679    macro_rules! opt_ambiguous_expr {
680        ($i:expr, $allow_struct:ident) => {
681            option!($i, call!(ambiguous_expr, $allow_struct, $allow_struct))
682        };
683    }
684
685    impl Synom for Expr {
686        named!(parse -> Self, ambiguous_expr!(true));
687
688        fn description() -> Option<&'static str> {
689            Some("expression")
690        }
691    }
692
693    #[cfg(feature = "full")]
694    named!(expr_no_struct -> Expr, ambiguous_expr!(false));
695
696    /// Parse an arbitrary expression.
697    #[cfg(feature = "full")]
698    fn ambiguous_expr(i: Cursor,
699                      allow_struct: bool,
700                      allow_block: bool)
701                      -> PResult<Expr> {
702        map!(
703            i,
704            call!(assign_expr, allow_struct, allow_block),
705            ExprKind::into
706        )
707    }
708
709    #[cfg(not(feature = "full"))]
710    fn ambiguous_expr(i: Cursor,
711                      allow_struct: bool,
712                      allow_block: bool)
713                      -> PResult<Expr> {
714        map!(
715            i,
716            // NOTE: We intentionally skip assign_expr, placement_expr, and
717            // range_expr, as they are not parsed in non-full mode.
718            call!(or_expr, allow_struct, allow_block),
719            ExprKind::into
720        )
721    }
722
723    /// Parse a left-associative binary operator.
724    macro_rules! binop {
725        (
726            $name: ident,
727            $next: ident,
728            $submac: ident!( $($args:tt)* )
729        ) => {
730            named!($name(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
731                mut e: call!($next, allow_struct, allow_block) >>
732                many0!(do_parse!(
733                    op: $submac!($($args)*) >>
734                    rhs: call!($next, allow_struct, true) >>
735                    ({
736                        e = ExprBinary {
737                            left: Box::new(e.into()),
738                            op: op,
739                            right: Box::new(rhs.into()),
740                        }.into();
741                    })
742                )) >>
743                (e)
744            ));
745        }
746    }
747
748    /// ```ignore
749    /// <placement> = <placement> ..
750    /// <placement> += <placement> ..
751    /// <placement> -= <placement> ..
752    /// <placement> *= <placement> ..
753    /// <placement> /= <placement> ..
754    /// <placement> %= <placement> ..
755    /// <placement> ^= <placement> ..
756    /// <placement> &= <placement> ..
757    /// <placement> |= <placement> ..
758    /// <placement> <<= <placement> ..
759    /// <placement> >>= <placement> ..
760    /// ```
761    ///
762    /// NOTE: This operator is right-associative.
763    #[cfg(feature = "full")]
764    named!(assign_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
765        mut e: call!(placement_expr, allow_struct, allow_block) >>
766        alt!(
767            do_parse!(
768                eq: syn!(Eq) >>
769                // Recurse into self to parse right-associative operator.
770                rhs: call!(assign_expr, allow_struct, true) >>
771                ({
772                    e = ExprAssign {
773                        left: Box::new(e.into()),
774                        eq_token: eq,
775                        right: Box::new(rhs.into()),
776                    }.into();
777                })
778            )
779            |
780            do_parse!(
781                op: call!(BinOp::parse_assign_op) >>
782                // Recurse into self to parse right-associative operator.
783                rhs: call!(assign_expr, allow_struct, true) >>
784                ({
785                    e = ExprAssignOp {
786                        left: Box::new(e.into()),
787                        op: op,
788                        right: Box::new(rhs.into()),
789                    }.into();
790                })
791            )
792            |
793            epsilon!()
794        ) >>
795        (e)
796    ));
797
798    /// ```ignore
799    /// <range> <- <range> ..
800    /// ```
801    ///
802    /// NOTE: The `in place { expr }` version of this syntax is parsed in
803    /// `atom_expr`, not here.
804    ///
805    /// NOTE: This operator is right-associative.
806    #[cfg(feature = "full")]
807    named!(placement_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
808        mut e: call!(range_expr, allow_struct, allow_block) >>
809        alt!(
810            do_parse!(
811                arrow: syn!(LArrow) >>
812                // Recurse into self to parse right-associative operator.
813                rhs: call!(placement_expr, allow_struct, true) >>
814                ({
815                    e = ExprInPlace {
816                        // op: BinOp::Place(larrow),
817                        place: Box::new(e.into()),
818                        kind: InPlaceKind::Arrow(arrow),
819                        value: Box::new(rhs.into()),
820                    }.into();
821                })
822            )
823            |
824            epsilon!()
825        ) >>
826        (e)
827    ));
828
829    /// ```ignore
830    /// <or> ... <or> ..
831    /// <or> .. <or> ..
832    /// <or> ..
833    /// ```
834    ///
835    /// NOTE: This is currently parsed oddly - I'm not sure of what the exact
836    /// rules are for parsing these expressions are, but this is not correct.
837    /// For example, `a .. b .. c` is not a legal expression. It should not
838    /// be parsed as either `(a .. b) .. c` or `a .. (b .. c)` apparently.
839    ///
840    /// NOTE: The form of ranges which don't include a preceding expression are
841    /// parsed by `atom_expr`, rather than by this function.
842    #[cfg(feature = "full")]
843    named!(range_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
844        mut e: call!(or_expr, allow_struct, allow_block) >>
845        many0!(do_parse!(
846            limits: syn!(RangeLimits) >>
847            // We don't want to allow blocks here if we don't allow structs. See
848            // the reasoning for `opt_ambiguous_expr!` above.
849            hi: option!(call!(or_expr, allow_struct, allow_struct)) >>
850            ({
851                e = ExprRange {
852                    from: Some(Box::new(e.into())),
853                    limits: limits,
854                    to: hi.map(|e| Box::new(e.into())),
855                }.into();
856            })
857        )) >>
858        (e)
859    ));
860
861    /// ```ignore
862    /// <and> || <and> ...
863    /// ```
864    binop!(or_expr, and_expr, map!(syn!(OrOr), BinOp::Or));
865
866    /// ```ignore
867    /// <compare> && <compare> ...
868    /// ```
869    binop!(and_expr, compare_expr, map!(syn!(AndAnd), BinOp::And));
870
871    /// ```ignore
872    /// <bitor> == <bitor> ...
873    /// <bitor> != <bitor> ...
874    /// <bitor> >= <bitor> ...
875    /// <bitor> <= <bitor> ...
876    /// <bitor> > <bitor> ...
877    /// <bitor> < <bitor> ...
878    /// ```
879    ///
880    /// NOTE: This operator appears to be parsed as left-associative, but errors
881    /// if it is used in a non-associative manner.
882    binop!(compare_expr, bitor_expr, alt!(
883        syn!(EqEq) => { BinOp::Eq }
884        |
885        syn!(Ne) => { BinOp::Ne }
886        |
887        // must be above Lt
888        syn!(Le) => { BinOp::Le }
889        |
890        // must be above Gt
891        syn!(Ge) => { BinOp::Ge }
892        |
893        do_parse!(
894            // Make sure that we don't eat the < part of a <- operator
895            not!(syn!(LArrow)) >>
896            t: syn!(Lt) >>
897            (BinOp::Lt(t))
898        )
899        |
900        syn!(Gt) => { BinOp::Gt }
901    ));
902
903    /// ```ignore
904    /// <bitxor> | <bitxor> ...
905    /// ```
906    binop!(bitor_expr, bitxor_expr, do_parse!(
907        not!(syn!(OrOr)) >>
908        not!(syn!(OrEq)) >>
909        t: syn!(Or) >>
910        (BinOp::BitOr(t))
911    ));
912
913    /// ```ignore
914    /// <bitand> ^ <bitand> ...
915    /// ```
916    binop!(bitxor_expr, bitand_expr, do_parse!(
917        // NOTE: Make sure we aren't looking at ^=.
918        not!(syn!(CaretEq)) >>
919        t: syn!(Caret) >>
920        (BinOp::BitXor(t))
921    ));
922
923    /// ```ignore
924    /// <shift> & <shift> ...
925    /// ```
926    binop!(bitand_expr, shift_expr, do_parse!(
927        // NOTE: Make sure we aren't looking at && or &=.
928        not!(syn!(AndAnd)) >>
929        not!(syn!(AndEq)) >>
930        t: syn!(And) >>
931        (BinOp::BitAnd(t))
932    ));
933
934    /// ```ignore
935    /// <arith> << <arith> ...
936    /// <arith> >> <arith> ...
937    /// ```
938    binop!(shift_expr, arith_expr, alt!(
939        syn!(Shl) => { BinOp::Shl }
940        |
941        syn!(Shr) => { BinOp::Shr }
942    ));
943
944    /// ```ignore
945    /// <term> + <term> ...
946    /// <term> - <term> ...
947    /// ```
948    binop!(arith_expr, term_expr, alt!(
949        syn!(Add) => { BinOp::Add }
950        |
951        syn!(Sub) => { BinOp::Sub }
952    ));
953
954    /// ```ignore
955    /// <cast> * <cast> ...
956    /// <cast> / <cast> ...
957    /// <cast> % <cast> ...
958    /// ```
959    binop!(term_expr, cast_expr, alt!(
960        syn!(Star) => { BinOp::Mul }
961        |
962        syn!(Div) => { BinOp::Div }
963        |
964        syn!(Rem) => { BinOp::Rem }
965    ));
966
967    /// ```ignore
968    /// <unary> as <ty>
969    /// <unary> : <ty>
970    /// ```
971    named!(cast_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
972        mut e: call!(unary_expr, allow_struct, allow_block) >>
973        many0!(alt!(
974            do_parse!(
975                as_: syn!(As) >>
976                // We can't accept `A + B` in cast expressions, as it's
977                // ambiguous with the + expression.
978                ty: call!(Ty::without_plus) >>
979                ({
980                    e = ExprCast {
981                        expr: Box::new(e.into()),
982                        as_token: as_,
983                        ty: Box::new(ty),
984                    }.into();
985                })
986            )
987            |
988            do_parse!(
989                colon: syn!(Colon) >>
990                // We can't accept `A + B` in cast expressions, as it's
991                // ambiguous with the + expression.
992                ty: call!(Ty::without_plus) >>
993                ({
994                    e = ExprType {
995                        expr: Box::new(e.into()),
996                        colon_token: colon,
997                        ty: Box::new(ty),
998                    }.into();
999                })
1000            )
1001        )) >>
1002        (e)
1003    ));
1004
1005    /// ```
1006    /// <UnOp> <trailer>
1007    /// & <trailer>
1008    /// &mut <trailer>
1009    /// box <trailer>
1010    /// ```
1011    #[cfg(feature = "full")]
1012    named!(unary_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
1013        do_parse!(
1014            op: syn!(UnOp) >>
1015            expr: call!(unary_expr, allow_struct, true) >>
1016            (ExprUnary {
1017                op: op,
1018                expr: Box::new(expr.into()),
1019            }.into())
1020        )
1021        |
1022        do_parse!(
1023            and: syn!(And) >>
1024            mutability: syn!(Mutability) >>
1025            expr: call!(unary_expr, allow_struct, true) >>
1026            (ExprAddrOf {
1027                and_token: and,
1028                mutbl: mutability,
1029                expr: Box::new(expr.into()),
1030            }.into())
1031        )
1032        |
1033        do_parse!(
1034            box_: syn!(Box_) >>
1035            expr: call!(unary_expr, allow_struct, true) >>
1036            (ExprBox {
1037                box_token: box_,
1038                expr: Box::new(expr.into()),
1039            }.into())
1040        )
1041        |
1042        call!(trailer_expr, allow_struct, allow_block)
1043    ));
1044
1045    // XXX: This duplication is ugly
1046    #[cfg(not(feature = "full"))]
1047    named!(unary_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
1048        do_parse!(
1049            op: syn!(UnOp) >>
1050            expr: call!(unary_expr, allow_struct, true) >>
1051            (ExprUnary {
1052                op: op,
1053                expr: Box::new(expr.into()),
1054            }.into())
1055        )
1056        |
1057        call!(trailer_expr, allow_struct, allow_block)
1058    ));
1059
1060    /// ```ignore
1061    /// <atom> (..<args>) ...
1062    /// <atom> . <ident> (..<args>) ...
1063    /// <atom> . <ident> ...
1064    /// <atom> . <lit> ...
1065    /// <atom> [ <expr> ] ...
1066    /// <atom> ? ...
1067    /// ```
1068    #[cfg(feature = "full")]
1069    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
1070        mut e: call!(atom_expr, allow_struct, allow_block) >>
1071        many0!(alt!(
1072            tap!(args: and_call => {
1073                let (args, paren) = args;
1074                e = ExprCall {
1075                    func: Box::new(e.into()),
1076                    args: args,
1077                    paren_token: paren,
1078                }.into();
1079            })
1080            |
1081            tap!(more: and_method_call => {
1082                let mut call = more;
1083                call.expr = Box::new(e.into());
1084                e = call.into();
1085            })
1086            |
1087            tap!(field: and_field => {
1088                let (field, token) = field;
1089                e = ExprField {
1090                    expr: Box::new(e.into()),
1091                    field: field,
1092                    dot_token: token,
1093                }.into();
1094            })
1095            |
1096            tap!(field: and_tup_field => {
1097                let (field, token) = field;
1098                e = ExprTupField {
1099                    expr: Box::new(e.into()),
1100                    field: field,
1101                    dot_token: token,
1102                }.into();
1103            })
1104            |
1105            tap!(i: and_index => {
1106                let (i, token) = i;
1107                e = ExprIndex {
1108                    expr: Box::new(e.into()),
1109                    bracket_token: token,
1110                    index: Box::new(i),
1111                }.into();
1112            })
1113            |
1114            tap!(question: syn!(Question) => {
1115                e = ExprTry {
1116                    expr: Box::new(e.into()),
1117                    question_token: question,
1118                }.into();
1119            })
1120        )) >>
1121        (e)
1122    ));
1123
1124    // XXX: Duplication == ugly
1125    #[cfg(not(feature = "full"))]
1126    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
1127        mut e: call!(atom_expr, allow_struct, allow_block) >>
1128        many0!(alt!(
1129            tap!(args: and_call => {
1130                let (args, paren) = args;
1131                e = ExprCall {
1132                    func: Box::new(e.into()),
1133                    args: args,
1134                    paren_token: paren,
1135                }.into();
1136            })
1137            |
1138            tap!(i: and_index => {
1139                let (i, token) = i;
1140                e = ExprIndex {
1141                    expr: Box::new(e.into()),
1142                    bracket_token: token,
1143                    index: Box::new(i),
1144                }.into();
1145            })
1146        )) >>
1147        (e)
1148    ));
1149
1150    /// Parse all atomic expressions which don't have to worry about precidence
1151    /// interactions, as they are fully contained.
1152    #[cfg(feature = "full")]
1153    named!(atom_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
1154        syn!(ExprGroup) => { ExprKind::Group } // must be placed first
1155        |
1156        syn!(Lit) => { ExprKind::Lit } // must be before expr_struct
1157        |
1158        // must be before expr_path
1159        cond_reduce!(allow_struct, map!(syn!(ExprStruct), ExprKind::Struct))
1160        |
1161        syn!(ExprParen) => { ExprKind::Paren } // must be before expr_tup
1162        |
1163        syn!(Mac) => { ExprKind::Mac } // must be before expr_path
1164        |
1165        call!(expr_break, allow_struct) // must be before expr_path
1166        |
1167        syn!(ExprContinue) => { ExprKind::Continue } // must be before expr_path
1168        |
1169        call!(expr_ret, allow_struct) // must be before expr_path
1170        |
1171        // NOTE: The `in place { expr }` form. `place <- expr` is parsed above.
1172        syn!(ExprInPlace) => { ExprKind::InPlace }
1173        |
1174        syn!(ExprArray) => { ExprKind::Array }
1175        |
1176        syn!(ExprTup) => { ExprKind::Tup }
1177        |
1178        syn!(ExprIf) => { ExprKind::If }
1179        |
1180        syn!(ExprIfLet) => { ExprKind::IfLet }
1181        |
1182        syn!(ExprWhile) => { ExprKind::While }
1183        |
1184        syn!(ExprWhileLet) => { ExprKind::WhileLet }
1185        |
1186        syn!(ExprForLoop) => { ExprKind::ForLoop }
1187        |
1188        syn!(ExprLoop) => { ExprKind::Loop }
1189        |
1190        syn!(ExprMatch) => { ExprKind::Match }
1191        |
1192        syn!(ExprCatch) => { ExprKind::Catch }
1193        |
1194        syn!(ExprYield) => { ExprKind::Yield }
1195        |
1196        call!(expr_closure, allow_struct)
1197        |
1198        cond_reduce!(allow_block, map!(syn!(ExprBlock), ExprKind::Block))
1199        |
1200        // NOTE: This is the prefix-form of range
1201        call!(expr_range, allow_struct)
1202        |
1203        syn!(ExprPath) => { ExprKind::Path }
1204        |
1205        syn!(ExprRepeat) => { ExprKind::Repeat }
1206    ));
1207
1208    #[cfg(not(feature = "full"))]
1209    named!(atom_expr(_allow_struct: bool, _allow_block: bool) -> ExprKind, alt!(
1210        syn!(ExprGroup) => { ExprKind::Group } // must be placed first
1211        |
1212        syn!(Lit) => { ExprKind::Lit } // must be before expr_struct
1213        |
1214        syn!(ExprParen) => { ExprKind::Paren } // must be before expr_tup
1215        |
1216        syn!(Mac) => { ExprKind::Mac } // must be before expr_path
1217        |
1218        syn!(ExprPath) => { ExprKind::Path }
1219    ));
1220
1221
1222    #[cfg(feature = "full")]
1223    named!(expr_nosemi -> Expr, map!(alt!(
1224        syn!(ExprIf) => { ExprKind::If }
1225        |
1226        syn!(ExprIfLet) => { ExprKind::IfLet }
1227        |
1228        syn!(ExprWhile) => { ExprKind::While }
1229        |
1230        syn!(ExprWhileLet) => { ExprKind::WhileLet }
1231        |
1232        syn!(ExprForLoop) => { ExprKind::ForLoop }
1233        |
1234        syn!(ExprLoop) => { ExprKind::Loop }
1235        |
1236        syn!(ExprMatch) => { ExprKind::Match }
1237        |
1238        syn!(ExprCatch) => { ExprKind::Catch }
1239        |
1240        syn!(ExprYield) => { ExprKind::Yield }
1241        |
1242        syn!(ExprBlock) => { ExprKind::Block }
1243    ), Expr::from));
1244
1245    impl Synom for ExprGroup {
1246        named!(parse -> Self, do_parse!(
1247            e: grouped!(syn!(Expr)) >>
1248            (ExprGroup {
1249                expr: Box::new(e.0),
1250                group_token: e.1,
1251            }.into())
1252        ));
1253    }
1254
1255    impl Synom for ExprParen {
1256        named!(parse -> Self, do_parse!(
1257            e: parens!(syn!(Expr)) >>
1258            (ExprParen {
1259                expr: Box::new(e.0),
1260                paren_token: e.1,
1261            }.into())
1262        ));
1263    }
1264
1265    #[cfg(feature = "full")]
1266    impl Synom for ExprInPlace {
1267        named!(parse -> Self, do_parse!(
1268            in_: syn!(In) >>
1269            place: expr_no_struct >>
1270            value: braces!(call!(Block::parse_within)) >>
1271            (ExprInPlace {
1272                place: Box::new(place),
1273                kind: InPlaceKind::In(in_),
1274                value: Box::new(Expr {
1275                    node: ExprBlock {
1276                        unsafety: Unsafety::Normal,
1277                        block: Block {
1278                            stmts: value.0,
1279                            brace_token: value.1,
1280                        },
1281                    }.into(),
1282                    attrs: Vec::new(),
1283                }),
1284            })
1285        ));
1286    }
1287
1288    #[cfg(feature = "full")]
1289    impl Synom for ExprArray {
1290        named!(parse -> Self, do_parse!(
1291            elems: brackets!(call!(Delimited::parse_terminated)) >>
1292            (ExprArray {
1293                exprs: elems.0,
1294                bracket_token: elems.1,
1295            })
1296        ));
1297    }
1298
1299    named!(and_call -> (Delimited<Expr, tokens::Comma>, tokens::Paren),
1300           parens!(call!(Delimited::parse_terminated)));
1301
1302    #[cfg(feature = "full")]
1303    named!(and_method_call -> ExprMethodCall, do_parse!(
1304        dot: syn!(Dot) >>
1305        method: syn!(Ident) >>
1306        typarams: option!(do_parse!(
1307            colon2: syn!(Colon2) >>
1308            lt: syn!(Lt) >>
1309            tys: call!(Delimited::parse_terminated) >>
1310            gt: syn!(Gt) >>
1311            (colon2, lt, tys, gt)
1312        )) >>
1313        args: parens!(call!(Delimited::parse_terminated)) >>
1314        ({
1315            let (colon2, lt, tys, gt) = match typarams {
1316                Some((a, b, c, d)) => (Some(a), Some(b), Some(c), Some(d)),
1317                None => (None, None, None, None),
1318            };
1319            ExprMethodCall {
1320                // this expr will get overwritten after being returned
1321                expr: Box::new(ExprKind::Lit(Lit {
1322                    span: Span::default(),
1323                    value: LitKind::Bool(false),
1324                }).into()),
1325
1326                method: method,
1327                args: args.0,
1328                paren_token: args.1,
1329                dot_token: dot,
1330                lt_token: lt,
1331                gt_token: gt,
1332                colon2_token: colon2,
1333                typarams: tys.unwrap_or_default(),
1334            }
1335        })
1336    ));
1337
1338    #[cfg(feature = "full")]
1339    impl Synom for ExprTup {
1340        named!(parse -> Self, do_parse!(
1341            elems: parens!(call!(Delimited::parse_terminated)) >>
1342            (ExprTup {
1343                args: elems.0,
1344                paren_token: elems.1,
1345                lone_comma: None, // TODO: parse this
1346            })
1347        ));
1348    }
1349
1350    #[cfg(feature = "full")]
1351    impl Synom for ExprIfLet {
1352        named!(parse -> Self, do_parse!(
1353            if_: syn!(If) >>
1354            let_: syn!(Let) >>
1355            pat: syn!(Pat) >>
1356            eq: syn!(Eq) >>
1357            cond: expr_no_struct >>
1358            then_block: braces!(call!(Block::parse_within)) >>
1359            else_block: option!(else_block) >>
1360            (ExprIfLet {
1361                pat: Box::new(pat),
1362                let_token: let_,
1363                eq_token: eq,
1364                expr: Box::new(cond),
1365                if_true: Block {
1366                    stmts: then_block.0,
1367                    brace_token: then_block.1,
1368                },
1369                if_token: if_,
1370                else_token: else_block.as_ref().map(|p| Else((p.0).0)),
1371                if_false: else_block.map(|p| Box::new(p.1.into())),
1372            })
1373        ));
1374    }
1375
1376    #[cfg(feature = "full")]
1377    impl Synom for ExprIf {
1378        named!(parse -> Self, do_parse!(
1379            if_: syn!(If) >>
1380            cond: expr_no_struct >>
1381            then_block: braces!(call!(Block::parse_within)) >>
1382            else_block: option!(else_block) >>
1383            (ExprIf {
1384                cond: Box::new(cond),
1385                if_true: Block {
1386                    stmts: then_block.0,
1387                    brace_token: then_block.1,
1388                },
1389                if_token: if_,
1390                else_token: else_block.as_ref().map(|p| Else((p.0).0)),
1391                if_false: else_block.map(|p| Box::new(p.1.into())),
1392            })
1393        ));
1394    }
1395
1396    #[cfg(feature = "full")]
1397    named!(else_block -> (Else, ExprKind), do_parse!(
1398        else_: syn!(Else) >>
1399        expr: alt!(
1400            syn!(ExprIf) => { ExprKind::If }
1401            |
1402            syn!(ExprIfLet) => { ExprKind::IfLet }
1403            |
1404            do_parse!(
1405                else_block: braces!(call!(Block::parse_within)) >>
1406                (ExprKind::Block(ExprBlock {
1407                    unsafety: Unsafety::Normal,
1408                    block: Block {
1409                        stmts: else_block.0,
1410                        brace_token: else_block.1,
1411                    },
1412                }))
1413            )
1414        ) >>
1415        (else_, expr)
1416    ));
1417
1418
1419    #[cfg(feature = "full")]
1420    impl Synom for ExprForLoop {
1421        named!(parse -> Self, do_parse!(
1422            lbl: option!(tuple!(syn!(Lifetime), syn!(Colon))) >>
1423            for_: syn!(For) >>
1424            pat: syn!(Pat) >>
1425            in_: syn!(In) >>
1426            expr: expr_no_struct >>
1427            loop_block: syn!(Block) >>
1428            (ExprForLoop {
1429                for_token: for_,
1430                in_token: in_,
1431                pat: Box::new(pat),
1432                expr: Box::new(expr),
1433                body: loop_block,
1434                colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
1435                label: lbl.map(|p| p.0),
1436            })
1437        ));
1438    }
1439
1440    #[cfg(feature = "full")]
1441    impl Synom for ExprLoop {
1442        named!(parse -> Self, do_parse!(
1443            lbl: option!(tuple!(syn!(Lifetime), syn!(Colon))) >>
1444            loop_: syn!(Loop) >>
1445            loop_block: syn!(Block) >>
1446            (ExprLoop {
1447                loop_token: loop_,
1448                body: loop_block,
1449                colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
1450                label: lbl.map(|p| p.0),
1451            })
1452        ));
1453    }
1454
1455    #[cfg(feature = "full")]
1456    impl Synom for ExprMatch {
1457        named!(parse -> Self, do_parse!(
1458            match_: syn!(Match) >>
1459            obj: expr_no_struct >>
1460            res: braces!(many0!(syn!(Arm))) >>
1461            ({
1462                let (arms, brace) = res;
1463                ExprMatch {
1464                    expr: Box::new(obj),
1465                    match_token: match_,
1466                    brace_token: brace,
1467                    arms: arms,
1468                }
1469            })
1470        ));
1471    }
1472
1473    #[cfg(feature = "full")]
1474    impl Synom for ExprCatch {
1475        named!(parse -> Self, do_parse!(
1476            do_: syn!(Do) >>
1477            catch_: syn!(Catch) >>
1478            catch_block: syn!(Block) >>
1479            (ExprCatch {
1480                block: catch_block,
1481                do_token: do_,
1482                catch_token: catch_,
1483            }.into())
1484        ));
1485    }
1486
1487    #[cfg(feature = "full")]
1488    impl Synom for ExprYield {
1489        named!(parse -> Self, do_parse!(
1490            yield_: syn!(Yield) >>
1491            expr: option!(syn!(Expr)) >>
1492            (ExprYield {
1493                yield_token: yield_,
1494                expr: expr.map(Box::new),
1495            })
1496        ));
1497    }
1498
1499    #[cfg(feature = "full")]
1500    impl Synom for Arm {
1501        named!(parse -> Self, do_parse!(
1502            attrs: many0!(call!(Attribute::parse_outer)) >>
1503            pats: call!(Delimited::parse_separated_nonempty) >>
1504            guard: option!(tuple!(syn!(If), syn!(Expr))) >>
1505            rocket: syn!(Rocket) >>
1506            body: do_parse!(
1507                expr: alt!(expr_nosemi | syn!(Expr)) >>
1508                comma1: cond!(arm_expr_requires_comma(&expr), alt!(
1509                    map!(input_end!(), |_| None)
1510                    |
1511                    map!(syn!(Comma), Some)
1512                )) >>
1513                comma2: cond!(!arm_expr_requires_comma(&expr), option!(syn!(Comma))) >>
1514                (expr, comma1.and_then(|x| x).or(comma2.and_then(|x| x)))
1515            ) >>
1516            (Arm {
1517                rocket_token: rocket,
1518                if_token: guard.as_ref().map(|p| If((p.0).0)),
1519                attrs: attrs,
1520                pats: pats,
1521                guard: guard.map(|p| Box::new(p.1)),
1522                body: Box::new(body.0),
1523                comma: body.1,
1524            })
1525        ));
1526    }
1527
1528    #[cfg(feature = "full")]
1529    named!(expr_closure(allow_struct: bool) -> ExprKind, do_parse!(
1530        capture: syn!(CaptureBy) >>
1531        or1: syn!(Or) >>
1532        inputs: call!(Delimited::parse_terminated_with, fn_arg) >>
1533        or2: syn!(Or) >>
1534        ret_and_body: alt!(
1535            do_parse!(
1536                arrow: syn!(RArrow) >>
1537                ty: syn!(Ty) >>
1538                body: syn!(Block) >>
1539                (FunctionRetTy::Ty(ty, arrow),
1540                 ExprKind::Block(ExprBlock {
1541                    unsafety: Unsafety::Normal,
1542                    block: body,
1543                }).into())
1544            )
1545            |
1546            map!(ambiguous_expr!(allow_struct), |e| (FunctionRetTy::Default, e))
1547        ) >>
1548        (ExprClosure {
1549            capture: capture,
1550            or1_token: or1,
1551            or2_token: or2,
1552            decl: Box::new(FnDecl {
1553                inputs: inputs,
1554                output: ret_and_body.0,
1555                variadic: false,
1556                dot_tokens: None,
1557                fn_token: tokens::Fn_::default(),
1558                generics: Generics::default(),
1559                paren_token: tokens::Paren::default(),
1560            }),
1561            body: Box::new(ret_and_body.1),
1562        }.into())
1563    ));
1564
1565    #[cfg(feature = "full")]
1566    named!(fn_arg -> FnArg, do_parse!(
1567        pat: syn!(Pat) >>
1568        ty: option!(tuple!(syn!(Colon), syn!(Ty))) >>
1569        ({
1570            let (colon, ty) = ty.unwrap_or_else(|| {
1571                (Colon::default(), TyInfer {
1572                    underscore_token: Underscore::default(),
1573                }.into())
1574            });
1575            ArgCaptured {
1576                pat: pat,
1577                colon_token: colon,
1578                ty: ty,
1579            }.into()
1580        })
1581    ));
1582
1583    #[cfg(feature = "full")]
1584    impl Synom for ExprWhile {
1585        named!(parse -> Self, do_parse!(
1586            lbl: option!(tuple!(syn!(Lifetime), syn!(Colon))) >>
1587            while_: syn!(While) >>
1588            cond: expr_no_struct >>
1589            while_block: syn!(Block) >>
1590            (ExprWhile {
1591                while_token: while_,
1592                colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
1593                cond: Box::new(cond),
1594                body: while_block,
1595                label: lbl.map(|p| p.0),
1596            })
1597        ));
1598    }
1599
1600    #[cfg(feature = "full")]
1601    impl Synom for ExprWhileLet {
1602        named!(parse -> Self, do_parse!(
1603            lbl: option!(tuple!(syn!(Lifetime), syn!(Colon))) >>
1604            while_: syn!(While) >>
1605            let_: syn!(Let) >>
1606            pat: syn!(Pat) >>
1607            eq: syn!(Eq) >>
1608            value: expr_no_struct >>
1609            while_block: syn!(Block) >>
1610            (ExprWhileLet {
1611                eq_token: eq,
1612                let_token: let_,
1613                while_token: while_,
1614                colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
1615                pat: Box::new(pat),
1616                expr: Box::new(value),
1617                body: while_block,
1618                label: lbl.map(|p| p.0),
1619            })
1620        ));
1621    }
1622
1623    #[cfg(feature = "full")]
1624    impl Synom for ExprContinue {
1625        named!(parse -> Self, do_parse!(
1626            cont: syn!(Continue) >>
1627            lbl: option!(syn!(Lifetime)) >>
1628            (ExprContinue {
1629                continue_token: cont,
1630                label: lbl,
1631            })
1632        ));
1633    }
1634
1635    #[cfg(feature = "full")]
1636    named!(expr_break(allow_struct: bool) -> ExprKind, do_parse!(
1637        break_: syn!(Break) >>
1638        lbl: option!(syn!(Lifetime)) >>
1639        // We can't allow blocks after a `break` expression when we wouldn't
1640        // allow structs, as this expression is ambiguous.
1641        val: opt_ambiguous_expr!(allow_struct) >>
1642        (ExprBreak {
1643            label: lbl,
1644            expr: val.map(Box::new),
1645            break_token: break_,
1646        }.into())
1647    ));
1648
1649    #[cfg(feature = "full")]
1650    named!(expr_ret(allow_struct: bool) -> ExprKind, do_parse!(
1651        return_: syn!(Return) >>
1652        // NOTE: return is greedy and eats blocks after it even when in a
1653        // position where structs are not allowed, such as in if statement
1654        // conditions. For example:
1655        //
1656        // if return { println!("A") } { } // Prints "A"
1657        ret_value: option!(ambiguous_expr!(allow_struct)) >>
1658        (ExprRet {
1659            expr: ret_value.map(Box::new),
1660            return_token: return_,
1661        }.into())
1662    ));
1663
1664    #[cfg(feature = "full")]
1665    impl Synom for ExprStruct {
1666        named!(parse -> Self, do_parse!(
1667            path: syn!(Path) >>
1668            data: braces!(do_parse!(
1669                fields: call!(Delimited::parse_terminated) >>
1670                base: option!(
1671                    cond!(fields.is_empty() || fields.trailing_delim(),
1672                        do_parse!(
1673                            dots: syn!(Dot2) >>
1674                            base: syn!(Expr) >>
1675                            (dots, base)
1676                        )
1677                    )
1678                ) >>
1679                (fields, base)
1680            )) >>
1681            ({
1682                let ((fields, base), brace) = data;
1683                let (dots, rest) = match base.and_then(|b| b) {
1684                    Some((dots, base)) => (Some(dots), Some(base)),
1685                    None => (None, None),
1686                };
1687                ExprStruct {
1688                    brace_token: brace,
1689                    path: path,
1690                    fields: fields,
1691                    dot2_token: dots,
1692                    rest: rest.map(Box::new),
1693                }
1694            })
1695        ));
1696    }
1697
1698    #[cfg(feature = "full")]
1699    impl Synom for FieldValue {
1700        named!(parse -> Self, alt!(
1701            do_parse!(
1702                ident: field_ident >>
1703                colon: syn!(Colon) >>
1704                value: syn!(Expr) >>
1705                (FieldValue {
1706                    ident: ident,
1707                    expr: value,
1708                    is_shorthand: false,
1709                    attrs: Vec::new(),
1710                    colon_token: Some(colon),
1711                })
1712            )
1713            |
1714            map!(syn!(Ident), |name| FieldValue {
1715                ident: name.clone(),
1716                expr: ExprKind::Path(ExprPath { qself: None, path: name.into() }).into(),
1717                is_shorthand: true,
1718                attrs: Vec::new(),
1719                colon_token: None,
1720            })
1721        ));
1722    }
1723
1724    #[cfg(feature = "full")]
1725    impl Synom for ExprRepeat {
1726        named!(parse -> Self, do_parse!(
1727            data: brackets!(do_parse!(
1728                value: syn!(Expr) >>
1729                semi: syn!(Semi) >>
1730                times: syn!(Expr) >>
1731                (value, semi, times)
1732            )) >>
1733            (ExprRepeat {
1734                expr: Box::new((data.0).0),
1735                amt: Box::new((data.0).2),
1736                bracket_token: data.1,
1737                semi_token: (data.0).1,
1738            })
1739        ));
1740    }
1741
1742    #[cfg(feature = "full")]
1743    impl Synom for ExprBlock {
1744        named!(parse -> Self, do_parse!(
1745            rules: syn!(Unsafety) >>
1746            b: syn!(Block) >>
1747            (ExprBlock {
1748                unsafety: rules,
1749                block: b,
1750            })
1751        ));
1752    }
1753
1754    #[cfg(feature = "full")]
1755    named!(expr_range(allow_struct: bool) -> ExprKind, do_parse!(
1756        limits: syn!(RangeLimits) >>
1757        hi: opt_ambiguous_expr!(allow_struct) >>
1758        (ExprRange { from: None, to: hi.map(Box::new), limits: limits }.into())
1759    ));
1760
1761    #[cfg(feature = "full")]
1762    impl Synom for RangeLimits {
1763        named!(parse -> Self, alt!(
1764            // Must come before Dot2
1765            syn!(Dot3) => { RangeLimits::Closed }
1766            |
1767            syn!(Dot2) => { RangeLimits::HalfOpen }
1768        ));
1769    }
1770
1771    impl Synom for ExprPath {
1772        named!(parse -> Self, do_parse!(
1773            pair: qpath >>
1774            (ExprPath {
1775                qself: pair.0,
1776                path: pair.1,
1777            })
1778        ));
1779    }
1780
1781    #[cfg(feature = "full")]
1782    named!(and_field -> (Ident, Dot),
1783           map!(tuple!(syn!(Dot), syn!(Ident)), |(a, b)| (b, a)));
1784
1785    #[cfg(feature = "full")]
1786    named!(and_tup_field -> (Lit, Dot),
1787           map!(tuple!(syn!(Dot), syn!(Lit)), |(a, b)| (b, a)));
1788
1789    named!(and_index -> (Expr, tokens::Bracket), brackets!(syn!(Expr)));
1790
1791    #[cfg(feature = "full")]
1792    impl Synom for Block {
1793        named!(parse -> Self, do_parse!(
1794            stmts: braces!(call!(Block::parse_within)) >>
1795            (Block {
1796                stmts: stmts.0,
1797                brace_token: stmts.1,
1798            })
1799        ));
1800    }
1801
1802    #[cfg(feature = "full")]
1803    impl Block {
1804        named!(pub parse_within -> Vec<Stmt>, do_parse!(
1805            many0!(syn!(Semi)) >>
1806            mut standalone: many0!(terminated!(syn!(Stmt), many0!(syn!(Semi)))) >>
1807            last: option!(do_parse!(
1808                attrs: many0!(call!(Attribute::parse_outer)) >>
1809                mut e: syn!(Expr) >>
1810                ({
1811                    e.attrs = attrs;
1812                    Stmt::Expr(Box::new(e))
1813                })
1814            )) >>
1815            (match last {
1816                None => standalone,
1817                Some(last) => {
1818                    standalone.push(last);
1819                    standalone
1820                }
1821            })
1822        ));
1823    }
1824
1825    #[cfg(feature = "full")]
1826    impl Synom for Stmt {
1827        named!(parse -> Self, alt!(
1828            stmt_mac
1829            |
1830            stmt_local
1831            |
1832            stmt_item
1833            |
1834            stmt_blockexpr
1835            |
1836            stmt_expr
1837        ));
1838    }
1839
1840    #[cfg(feature = "full")]
1841    named!(stmt_mac -> Stmt, do_parse!(
1842        attrs: many0!(call!(Attribute::parse_outer)) >>
1843        what: syn!(Path) >>
1844        bang: syn!(Bang) >>
1845    // Only parse braces here; paren and bracket will get parsed as
1846    // expression statements
1847        data: braces!(syn!(TokenStream)) >>
1848        semi: option!(syn!(Semi)) >>
1849        (Stmt::Mac(Box::new((
1850            Mac {
1851                path: what,
1852                bang_token: bang,
1853                ident: None,
1854                tokens: vec![TokenTree(proc_macro2::TokenTree {
1855                    span: ((data.1).0).0,
1856                    kind: TokenNode::Group(Delimiter::Brace, data.0),
1857                })],
1858            },
1859            match semi {
1860                Some(semi) => MacStmtStyle::Semicolon(semi),
1861                None => MacStmtStyle::Braces,
1862            },
1863            attrs,
1864        ))))
1865    ));
1866
1867    #[cfg(feature = "full")]
1868    named!(stmt_local -> Stmt, do_parse!(
1869        attrs: many0!(call!(Attribute::parse_outer)) >>
1870        let_: syn!(Let) >>
1871        pat: syn!(Pat) >>
1872        ty: option!(tuple!(syn!(Colon), syn!(Ty))) >>
1873        init: option!(tuple!(syn!(Eq), syn!(Expr))) >>
1874        semi: syn!(Semi) >>
1875        (Stmt::Local(Box::new(Local {
1876            let_token: let_,
1877            semi_token: semi,
1878            colon_token: ty.as_ref().map(|p| Colon((p.0).0)),
1879            eq_token: init.as_ref().map(|p| Eq((p.0).0)),
1880            pat: Box::new(pat),
1881            ty: ty.map(|p| Box::new(p.1)),
1882            init: init.map(|p| Box::new(p.1)),
1883            attrs: attrs,
1884        })))
1885    ));
1886
1887    #[cfg(feature = "full")]
1888    named!(stmt_item -> Stmt, map!(syn!(Item), |i| Stmt::Item(Box::new(i))));
1889
1890    #[cfg(feature = "full")]
1891    named!(stmt_blockexpr -> Stmt, do_parse!(
1892        attrs: many0!(call!(Attribute::parse_outer)) >>
1893        mut e: expr_nosemi >>
1894        // If the next token is a `.` or a `?` it is special-cased to parse as
1895        // an expression instead of a blockexpression.
1896        not!(syn!(Dot)) >>
1897        not!(syn!(Question)) >>
1898        semi: option!(syn!(Semi)) >>
1899        ({
1900            e.attrs = attrs;
1901            if let Some(semi) = semi {
1902                Stmt::Semi(Box::new(e), semi)
1903            } else {
1904                Stmt::Expr(Box::new(e))
1905            }
1906        })
1907    ));
1908
1909    #[cfg(feature = "full")]
1910    named!(stmt_expr -> Stmt, do_parse!(
1911        attrs: many0!(call!(Attribute::parse_outer)) >>
1912        mut e: syn!(Expr) >>
1913        semi: syn!(Semi) >>
1914        ({
1915            e.attrs = attrs;
1916            Stmt::Semi(Box::new(e), semi)
1917        })
1918    ));
1919
1920    #[cfg(feature = "full")]
1921    impl Synom for Pat {
1922        named!(parse -> Self, alt!(
1923            syn!(PatWild) => { Pat::Wild } // must be before pat_ident
1924            |
1925            syn!(PatBox) => { Pat::Box }  // must be before pat_ident
1926            |
1927            syn!(PatRange) => { Pat::Range } // must be before pat_lit
1928            |
1929            syn!(PatTupleStruct) => { Pat::TupleStruct }  // must be before pat_ident
1930            |
1931            syn!(PatStruct) => { Pat::Struct } // must be before pat_ident
1932            |
1933            syn!(Mac) => { Pat::Mac } // must be before pat_ident
1934            |
1935            syn!(PatLit) => { Pat::Lit } // must be before pat_ident
1936            |
1937            syn!(PatIdent) => { Pat::Ident } // must be before pat_path
1938            |
1939            syn!(PatPath) => { Pat::Path }
1940            |
1941            syn!(PatTuple) => { Pat::Tuple }
1942            |
1943            syn!(PatRef) => { Pat::Ref }
1944            |
1945            syn!(PatSlice) => { Pat::Slice }
1946        ));
1947    }
1948
1949    #[cfg(feature = "full")]
1950    impl Synom for PatWild {
1951        named!(parse -> Self, map!(
1952            syn!(Underscore),
1953            |u| PatWild { underscore_token: u }
1954        ));
1955    }
1956
1957    #[cfg(feature = "full")]
1958    impl Synom for PatBox {
1959        named!(parse -> Self, do_parse!(
1960            boxed: syn!(Box_) >>
1961            pat: syn!(Pat) >>
1962            (PatBox {
1963                pat: Box::new(pat),
1964                box_token: boxed,
1965            })
1966        ));
1967    }
1968
1969    #[cfg(feature = "full")]
1970    impl Synom for PatIdent {
1971        named!(parse -> Self, do_parse!(
1972            mode: option!(syn!(Ref)) >>
1973            mutability: syn!(Mutability) >>
1974            name: alt!(
1975                syn!(Ident)
1976                |
1977                syn!(Self_) => { Into::into }
1978            ) >>
1979            not!(syn!(Lt)) >>
1980            not!(syn!(Colon2)) >>
1981            subpat: option!(tuple!(syn!(At), syn!(Pat))) >>
1982            (PatIdent {
1983                mode: match mode {
1984                    Some(mode) => BindingMode::ByRef(mode, mutability),
1985                    None => BindingMode::ByValue(mutability),
1986                },
1987                ident: name,
1988                at_token: subpat.as_ref().map(|p| At((p.0).0)),
1989                subpat: subpat.map(|p| Box::new(p.1)),
1990            })
1991        ));
1992    }
1993
1994    #[cfg(feature = "full")]
1995    impl Synom for PatTupleStruct {
1996        named!(parse -> Self, do_parse!(
1997            path: syn!(Path) >>
1998            tuple: syn!(PatTuple) >>
1999            (PatTupleStruct {
2000                path: path,
2001                pat: tuple,
2002            })
2003        ));
2004    }
2005
2006    #[cfg(feature = "full")]
2007    impl Synom for PatStruct {
2008        named!(parse -> Self, do_parse!(
2009            path: syn!(Path) >>
2010            data: braces!(do_parse!(
2011                fields: call!(Delimited::parse_terminated) >>
2012                base: option!(
2013                    cond!(fields.is_empty() || fields.trailing_delim(),
2014                          syn!(Dot2))
2015                ) >>
2016                (fields, base)
2017            )) >>
2018            (PatStruct {
2019                path: path,
2020                fields: (data.0).0,
2021                brace_token: data.1,
2022                dot2_token: (data.0).1.and_then(|m| m),
2023            })
2024        ));
2025    }
2026
2027    #[cfg(feature = "full")]
2028    impl Synom for FieldPat {
2029        named!(parse -> Self, alt!(
2030            do_parse!(
2031                ident: field_ident >>
2032                colon: syn!(Colon) >>
2033                pat: syn!(Pat) >>
2034                (FieldPat {
2035                    ident: ident,
2036                    pat: Box::new(pat),
2037                    is_shorthand: false,
2038                    attrs: Vec::new(),
2039                    colon_token: Some(colon),
2040                })
2041            )
2042            |
2043            do_parse!(
2044                boxed: option!(syn!(Box_)) >>
2045                mode: option!(syn!(Ref)) >>
2046                mutability: syn!(Mutability) >>
2047                ident: syn!(Ident) >>
2048                ({
2049                    let mut pat: Pat = PatIdent {
2050                        mode: if let Some(mode) = mode {
2051                            BindingMode::ByRef(mode, mutability)
2052                        } else {
2053                            BindingMode::ByValue(mutability)
2054                        },
2055                        ident: ident.clone(),
2056                        subpat: None,
2057                        at_token: None,
2058                    }.into();
2059                    if let Some(boxed) = boxed {
2060                        pat = PatBox {
2061                            pat: Box::new(pat),
2062                            box_token: boxed,
2063                        }.into();
2064                    }
2065                    FieldPat {
2066                        ident: ident,
2067                        pat: Box::new(pat),
2068                        is_shorthand: true,
2069                        attrs: Vec::new(),
2070                        colon_token: None,
2071                    }
2072                })
2073            )
2074        ));
2075    }
2076
2077    #[cfg(feature = "full")]
2078    named!(field_ident -> Ident, alt!(
2079        syn!(Ident)
2080        |
2081        do_parse!(
2082            lit: syn!(Lit) >>
2083            ({
2084                let s = lit.to_string();
2085                if s.parse::<usize>().is_ok() {
2086                    Ident::new(Term::intern(&s), lit.span)
2087                } else {
2088                    return parse_error();
2089                }
2090            })
2091        )
2092    ));
2093
2094    #[cfg(feature = "full")]
2095    impl Synom for PatPath {
2096        named!(parse -> Self, map!(
2097            syn!(ExprPath),
2098            |p| PatPath { qself: p.qself, path: p.path }
2099        ));
2100    }
2101
2102    #[cfg(feature = "full")]
2103    impl Synom for PatTuple {
2104        named!(parse -> Self, do_parse!(
2105            data: parens!(do_parse!(
2106                elems: call!(Delimited::parse_terminated) >>
2107                dotdot: map!(cond!(
2108                    elems.is_empty() || elems.trailing_delim(),
2109                    option!(do_parse!(
2110                        dots: syn!(Dot2) >>
2111                        trailing: option!(syn!(Comma)) >>
2112                        (dots, trailing)
2113                    ))
2114                ), |x| x.and_then(|x| x)) >>
2115                rest: cond!(match dotdot {
2116                                Some((_, Some(_))) => true,
2117                                _ => false,
2118                            },
2119                            call!(Delimited::parse_terminated)) >>
2120                (elems, dotdot, rest)
2121            )) >>
2122            ({
2123                let ((mut elems, dotdot, rest), parens) = data;
2124                let (dotdot, trailing) = match dotdot {
2125                    Some((a, b)) => (Some(a), Some(b)),
2126                    None => (None, None),
2127                };
2128                PatTuple {
2129                    paren_token: parens,
2130                    dots_pos: dotdot.as_ref().map(|_| elems.len()),
2131                    dot2_token: dotdot,
2132                    comma_token: trailing.and_then(|b| b),
2133                    pats: {
2134                        if let Some(rest) = rest {
2135                            for elem in rest {
2136                                elems.push(elem);
2137                            }
2138                        }
2139                        elems
2140                    },
2141                }
2142            })
2143        ));
2144    }
2145
2146    #[cfg(feature = "full")]
2147    impl Synom for PatRef {
2148        named!(parse -> Self, do_parse!(
2149            and: syn!(And) >>
2150            mutability: syn!(Mutability) >>
2151            pat: syn!(Pat) >>
2152            (PatRef {
2153                pat: Box::new(pat),
2154                mutbl: mutability,
2155                and_token: and,
2156            })
2157        ));
2158    }
2159
2160    #[cfg(feature = "full")]
2161    impl Synom for PatLit {
2162        named!(parse -> Self, do_parse!(
2163            lit: pat_lit_expr >>
2164            (if let ExprKind::Path(_) = lit.node {
2165                return parse_error(); // these need to be parsed by pat_path
2166            } else {
2167                PatLit {
2168                    expr: Box::new(lit),
2169                }
2170            })
2171        ));
2172    }
2173
2174    #[cfg(feature = "full")]
2175    impl Synom for PatRange {
2176        named!(parse -> Self, do_parse!(
2177            lo: pat_lit_expr >>
2178            limits: syn!(RangeLimits) >>
2179            hi: pat_lit_expr >>
2180            (PatRange {
2181                lo: Box::new(lo),
2182                hi: Box::new(hi),
2183                limits: limits,
2184            })
2185        ));
2186    }
2187
2188    #[cfg(feature = "full")]
2189    named!(pat_lit_expr -> Expr, do_parse!(
2190        neg: option!(syn!(Sub)) >>
2191        v: alt!(
2192            syn!(Lit) => { ExprKind::Lit }
2193            |
2194            syn!(ExprPath) => { ExprKind::Path }
2195        ) >>
2196        (if neg.is_some() {
2197            ExprKind::Unary(ExprUnary {
2198                op: UnOp::Neg(tokens::Sub::default()),
2199                expr: Box::new(v.into())
2200            }).into()
2201        } else {
2202            v.into()
2203        })
2204    ));
2205
2206    #[cfg(feature = "full")]
2207    impl Synom for PatSlice {
2208        named!(parse -> Self, map!(
2209            brackets!(do_parse!(
2210                before: call!(Delimited::parse_terminated) >>
2211                middle: option!(do_parse!(
2212                    dots: syn!(Dot2) >>
2213                    trailing: option!(syn!(Comma)) >>
2214                    (dots, trailing)
2215                )) >>
2216                after: cond!(
2217                    match middle {
2218                        Some((_, ref trailing)) => trailing.is_some(),
2219                        _ => false,
2220                    },
2221                    call!(Delimited::parse_terminated)
2222                ) >>
2223                (before, middle, after)
2224            )),
2225            |((before, middle, after), brackets)| {
2226                let mut before: Delimited<Pat, tokens::Comma> = before;
2227                let after: Option<Delimited<Pat, tokens::Comma>> = after;
2228                let middle: Option<(Dot2, Option<Comma>)> = middle;
2229                PatSlice {
2230                    dot2_token: middle.as_ref().map(|m| Dot2((m.0).0)),
2231                    comma_token: middle.as_ref().and_then(|m| {
2232                        m.1.as_ref().map(|m| Comma(m.0))
2233                    }),
2234                    bracket_token: brackets,
2235                    middle: middle.and_then(|_| {
2236                        if !before.is_empty() && !before.trailing_delim() {
2237                            Some(Box::new(before.pop().unwrap().into_item()))
2238                        } else {
2239                            None
2240                        }
2241                    }),
2242                    front: before,
2243                    back: after.unwrap_or_default(),
2244                }
2245            }
2246        ));
2247    }
2248
2249    #[cfg(feature = "full")]
2250    impl Synom for CaptureBy {
2251        named!(parse -> Self, alt!(
2252            syn!(Move) => { CaptureBy::Value }
2253            |
2254            epsilon!() => { |_| CaptureBy::Ref }
2255        ));
2256    }
2257}
2258
2259#[cfg(feature = "printing")]
2260mod printing {
2261    use super::*;
2262    #[cfg(feature = "full")]
2263    use attr::FilterAttrs;
2264    use quote::{Tokens, ToTokens};
2265
2266    /// If the given expression is a bare `ExprStruct`, wraps it in parenthesis
2267    /// before appending it to `Tokens`.
2268    #[cfg(feature = "full")]
2269    fn wrap_bare_struct(tokens: &mut Tokens, e: &Expr) {
2270        if let ExprKind::Struct(_) = e.node {
2271            tokens::Paren::default().surround(tokens, |tokens| {
2272                e.to_tokens(tokens);
2273            });
2274        } else {
2275            e.to_tokens(tokens);
2276        }
2277    }
2278
2279    impl ToTokens for Expr {
2280        #[cfg(feature = "full")]
2281        fn to_tokens(&self, tokens: &mut Tokens) {
2282            tokens.append_all(self.attrs.outer());
2283            self.node.to_tokens(tokens)
2284        }
2285
2286        #[cfg(not(feature = "full"))]
2287        fn to_tokens(&self, tokens: &mut Tokens) {
2288            self.node.to_tokens(tokens)
2289        }
2290    }
2291
2292    #[cfg(feature = "full")]
2293    impl ToTokens for ExprBox {
2294        fn to_tokens(&self, tokens: &mut Tokens) {
2295            self.box_token.to_tokens(tokens);
2296            self.expr.to_tokens(tokens);
2297        }
2298    }
2299
2300    #[cfg(feature = "full")]
2301    impl ToTokens for ExprInPlace {
2302        fn to_tokens(&self, tokens: &mut Tokens) {
2303            match self.kind {
2304                InPlaceKind::Arrow(ref arrow) => {
2305                    self.place.to_tokens(tokens);
2306                    arrow.to_tokens(tokens);
2307                    self.value.to_tokens(tokens);
2308                }
2309                InPlaceKind::In(ref _in) => {
2310                    _in.to_tokens(tokens);
2311                    self.place.to_tokens(tokens);
2312                    // NOTE: The second operand must be in a block, add one if
2313                    // it is not present.
2314                    if let ExprKind::Block(_) = self.value.node {
2315                        self.value.to_tokens(tokens);
2316                    } else {
2317                        tokens::Brace::default().surround(tokens, |tokens| {
2318                            self.value.to_tokens(tokens);
2319                        })
2320                    }
2321                }
2322            }
2323        }
2324    }
2325
2326    #[cfg(feature = "full")]
2327    impl ToTokens for ExprArray {
2328        fn to_tokens(&self, tokens: &mut Tokens) {
2329            self.bracket_token.surround(tokens, |tokens| {
2330                self.exprs.to_tokens(tokens);
2331            })
2332        }
2333    }
2334
2335    impl ToTokens for ExprCall {
2336        fn to_tokens(&self, tokens: &mut Tokens) {
2337            self.func.to_tokens(tokens);
2338            self.paren_token.surround(tokens, |tokens| {
2339                self.args.to_tokens(tokens);
2340            })
2341        }
2342    }
2343
2344    #[cfg(feature = "full")]
2345    impl ToTokens for ExprMethodCall {
2346        fn to_tokens(&self, tokens: &mut Tokens) {
2347            self.expr.to_tokens(tokens);
2348            self.dot_token.to_tokens(tokens);
2349            self.method.to_tokens(tokens);
2350            if !self.typarams.is_empty() {
2351                TokensOrDefault(&self.colon2_token).to_tokens(tokens);
2352                TokensOrDefault(&self.lt_token).to_tokens(tokens);
2353                self.typarams.to_tokens(tokens);
2354                TokensOrDefault(&self.gt_token).to_tokens(tokens);
2355            }
2356            self.paren_token.surround(tokens, |tokens| {
2357                self.args.to_tokens(tokens);
2358            });
2359        }
2360    }
2361
2362    #[cfg(feature = "full")]
2363    impl ToTokens for ExprTup {
2364        fn to_tokens(&self, tokens: &mut Tokens) {
2365            self.paren_token.surround(tokens, |tokens| {
2366                self.args.to_tokens(tokens);
2367                // If we only have one argument, we need a trailing comma to
2368                // distinguish ExprTup from ExprParen.
2369                if self.args.len() == 1 && !self.args.trailing_delim() {
2370                    tokens::Comma::default().to_tokens(tokens);
2371                }
2372                // XXX: Not sure how to handle this, but we never parse it yet.
2373                // Is this for an expression like (0,)? Can't we use the
2374                // trailing delimiter on Delimited for that? (,) isn't a valid
2375                // expression as far as I know.
2376                self.lone_comma.to_tokens(tokens);
2377            })
2378        }
2379    }
2380
2381    impl ToTokens for ExprBinary {
2382        fn to_tokens(&self, tokens: &mut Tokens) {
2383            self.left.to_tokens(tokens);
2384            self.op.to_tokens(tokens);
2385            self.right.to_tokens(tokens);
2386        }
2387    }
2388
2389    impl ToTokens for ExprUnary {
2390        fn to_tokens(&self, tokens: &mut Tokens) {
2391            self.op.to_tokens(tokens);
2392            self.expr.to_tokens(tokens);
2393        }
2394    }
2395
2396    impl ToTokens for ExprCast {
2397        fn to_tokens(&self, tokens: &mut Tokens) {
2398            self.expr.to_tokens(tokens);
2399            self.as_token.to_tokens(tokens);
2400            self.ty.to_tokens(tokens);
2401        }
2402    }
2403
2404    impl ToTokens for ExprType {
2405        fn to_tokens(&self, tokens: &mut Tokens) {
2406            self.expr.to_tokens(tokens);
2407            self.colon_token.to_tokens(tokens);
2408            self.ty.to_tokens(tokens);
2409        }
2410    }
2411
2412    #[cfg(feature = "full")]
2413    fn maybe_wrap_else(tokens: &mut Tokens,
2414                       else_token: &Option<tokens::Else>,
2415                       if_false: &Option<Box<Expr>>)
2416    {
2417        if let Some(ref if_false) = *if_false {
2418            TokensOrDefault(&else_token).to_tokens(tokens);
2419
2420            // If we are not one of the valid expressions to exist in an else
2421            // clause, wrap ourselves in a block.
2422            match if_false.node {
2423                ExprKind::If(_) |
2424                ExprKind::IfLet(_) |
2425                ExprKind::Block(_) => {
2426                    if_false.to_tokens(tokens);
2427                }
2428                _ => {
2429                    tokens::Brace::default().surround(tokens, |tokens| {
2430                        if_false.to_tokens(tokens);
2431                    });
2432                }
2433            }
2434        }
2435    }
2436
2437    #[cfg(feature = "full")]
2438    impl ToTokens for ExprIf {
2439        fn to_tokens(&self, tokens: &mut Tokens) {
2440            self.if_token.to_tokens(tokens);
2441            wrap_bare_struct(tokens, &self.cond);
2442            self.if_true.to_tokens(tokens);
2443            maybe_wrap_else(tokens, &self.else_token, &self.if_false);
2444        }
2445    }
2446
2447    #[cfg(feature = "full")]
2448    impl ToTokens for ExprIfLet {
2449        fn to_tokens(&self, tokens: &mut Tokens) {
2450            self.if_token.to_tokens(tokens);
2451            self.let_token.to_tokens(tokens);
2452            self.pat.to_tokens(tokens);
2453            self.eq_token.to_tokens(tokens);
2454            wrap_bare_struct(tokens, &self.expr);
2455            self.if_true.to_tokens(tokens);
2456            maybe_wrap_else(tokens, &self.else_token, &self.if_false);
2457        }
2458    }
2459
2460    #[cfg(feature = "full")]
2461    impl ToTokens for ExprWhile {
2462        fn to_tokens(&self, tokens: &mut Tokens) {
2463            if self.label.is_some() {
2464                self.label.to_tokens(tokens);
2465                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2466            }
2467            self.while_token.to_tokens(tokens);
2468            wrap_bare_struct(tokens, &self.cond);
2469            self.body.to_tokens(tokens);
2470        }
2471    }
2472
2473    #[cfg(feature = "full")]
2474    impl ToTokens for ExprWhileLet {
2475        fn to_tokens(&self, tokens: &mut Tokens) {
2476            if self.label.is_some() {
2477                self.label.to_tokens(tokens);
2478                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2479            }
2480            self.while_token.to_tokens(tokens);
2481            self.let_token.to_tokens(tokens);
2482            self.pat.to_tokens(tokens);
2483            self.eq_token.to_tokens(tokens);
2484            wrap_bare_struct(tokens, &self.expr);
2485            self.body.to_tokens(tokens);
2486        }
2487    }
2488
2489    #[cfg(feature = "full")]
2490    impl ToTokens for ExprForLoop {
2491        fn to_tokens(&self, tokens: &mut Tokens) {
2492            if self.label.is_some() {
2493                self.label.to_tokens(tokens);
2494                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2495            }
2496            self.for_token.to_tokens(tokens);
2497            self.pat.to_tokens(tokens);
2498            self.in_token.to_tokens(tokens);
2499            wrap_bare_struct(tokens, &self.expr);
2500            self.body.to_tokens(tokens);
2501        }
2502    }
2503
2504    #[cfg(feature = "full")]
2505    impl ToTokens for ExprLoop {
2506        fn to_tokens(&self, tokens: &mut Tokens) {
2507            if self.label.is_some() {
2508                self.label.to_tokens(tokens);
2509                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2510            }
2511            self.loop_token.to_tokens(tokens);
2512            self.body.to_tokens(tokens);
2513        }
2514    }
2515
2516    #[cfg(feature = "full")]
2517    impl ToTokens for ExprMatch {
2518        fn to_tokens(&self, tokens: &mut Tokens) {
2519            self.match_token.to_tokens(tokens);
2520            wrap_bare_struct(tokens, &self.expr);
2521            self.brace_token.surround(tokens, |tokens| {
2522                for (i,  arm) in self.arms.iter().enumerate() {
2523                    arm.to_tokens(tokens);
2524                    // Ensure that we have a comma after a non-block arm, except
2525                    // for the last one.
2526                    let is_last = i == self.arms.len() - 1;
2527                    if !is_last && arm_expr_requires_comma(&arm.body) && arm.comma.is_none() {
2528                        tokens::Comma::default().to_tokens(tokens);
2529                    }
2530                }
2531            });
2532        }
2533    }
2534
2535    #[cfg(feature = "full")]
2536    impl ToTokens for ExprCatch {
2537        fn to_tokens(&self, tokens: &mut Tokens) {
2538            self.do_token.to_tokens(tokens);
2539            self.catch_token.to_tokens(tokens);
2540            self.block.to_tokens(tokens);
2541        }
2542    }
2543
2544    #[cfg(feature = "full")]
2545    impl ToTokens for ExprYield {
2546        fn to_tokens(&self, tokens: &mut Tokens) {
2547            self.yield_token.to_tokens(tokens);
2548            self.expr.to_tokens(tokens);
2549        }
2550    }
2551
2552    #[cfg(feature = "full")]
2553    impl ToTokens for ExprClosure {
2554        fn to_tokens(&self, tokens: &mut Tokens) {
2555            self.capture.to_tokens(tokens);
2556            self.or1_token.to_tokens(tokens);
2557            for item in self.decl.inputs.iter() {
2558                match **item.item() {
2559                    FnArg::Captured(ArgCaptured { ref pat, ty: Ty::Infer(_), .. }) => {
2560                        pat.to_tokens(tokens);
2561                    }
2562                    _ => item.item().to_tokens(tokens),
2563                }
2564                item.delimiter().to_tokens(tokens);
2565            }
2566            self.or2_token.to_tokens(tokens);
2567            self.decl.output.to_tokens(tokens);
2568            self.body.to_tokens(tokens);
2569        }
2570    }
2571
2572    #[cfg(feature = "full")]
2573    impl ToTokens for ExprBlock {
2574        fn to_tokens(&self, tokens: &mut Tokens) {
2575            self.unsafety.to_tokens(tokens);
2576            self.block.to_tokens(tokens);
2577        }
2578    }
2579
2580    #[cfg(feature = "full")]
2581    impl ToTokens for ExprAssign {
2582        fn to_tokens(&self, tokens: &mut Tokens) {
2583            self.left.to_tokens(tokens);
2584            self.eq_token.to_tokens(tokens);
2585            self.right.to_tokens(tokens);
2586        }
2587    }
2588
2589    #[cfg(feature = "full")]
2590    impl ToTokens for ExprAssignOp {
2591        fn to_tokens(&self, tokens: &mut Tokens) {
2592            self.left.to_tokens(tokens);
2593            self.op.to_tokens(tokens);
2594            self.right.to_tokens(tokens);
2595        }
2596    }
2597
2598    #[cfg(feature = "full")]
2599    impl ToTokens for ExprField {
2600        fn to_tokens(&self, tokens: &mut Tokens) {
2601            self.expr.to_tokens(tokens);
2602            self.dot_token.to_tokens(tokens);
2603            // XXX: I don't think we can do anything if someone shoves a
2604            // nonsense Lit in here.
2605            self.field.to_tokens(tokens);
2606        }
2607    }
2608
2609    #[cfg(feature = "full")]
2610    impl ToTokens for ExprTupField {
2611        fn to_tokens(&self, tokens: &mut Tokens) {
2612            self.expr.to_tokens(tokens);
2613            self.dot_token.to_tokens(tokens);
2614            self.field.to_tokens(tokens);
2615        }
2616    }
2617
2618    impl ToTokens for ExprIndex {
2619        fn to_tokens(&self, tokens: &mut Tokens) {
2620            self.expr.to_tokens(tokens);
2621            self.bracket_token.surround(tokens, |tokens| {
2622                self.index.to_tokens(tokens);
2623            });
2624        }
2625    }
2626
2627    #[cfg(feature = "full")]
2628    impl ToTokens for ExprRange {
2629        fn to_tokens(&self, tokens: &mut Tokens) {
2630            self.from.to_tokens(tokens);
2631            self.limits.to_tokens(tokens);
2632            self.to.to_tokens(tokens);
2633        }
2634    }
2635
2636    impl ToTokens for ExprPath {
2637        fn to_tokens(&self, tokens: &mut Tokens) {
2638            ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
2639        }
2640    }
2641
2642    #[cfg(feature = "full")]
2643    impl ToTokens for ExprAddrOf {
2644        fn to_tokens(&self, tokens: &mut Tokens) {
2645            self.and_token.to_tokens(tokens);
2646            self.mutbl.to_tokens(tokens);
2647            self.expr.to_tokens(tokens);
2648        }
2649    }
2650
2651    #[cfg(feature = "full")]
2652    impl ToTokens for ExprBreak {
2653        fn to_tokens(&self, tokens: &mut Tokens) {
2654            self.break_token.to_tokens(tokens);
2655            self.label.to_tokens(tokens);
2656            self.expr.to_tokens(tokens);
2657        }
2658    }
2659
2660    #[cfg(feature = "full")]
2661    impl ToTokens for ExprContinue {
2662        fn to_tokens(&self, tokens: &mut Tokens) {
2663            self.continue_token.to_tokens(tokens);
2664            self.label.to_tokens(tokens);
2665        }
2666    }
2667
2668    #[cfg(feature = "full")]
2669    impl ToTokens for ExprRet {
2670        fn to_tokens(&self, tokens: &mut Tokens) {
2671            self.return_token.to_tokens(tokens);
2672            self.expr.to_tokens(tokens);
2673        }
2674    }
2675
2676    #[cfg(feature = "full")]
2677    impl ToTokens for ExprStruct {
2678        fn to_tokens(&self, tokens: &mut Tokens) {
2679            self.path.to_tokens(tokens);
2680            self.brace_token.surround(tokens, |tokens| {
2681                self.fields.to_tokens(tokens);
2682                if self.rest.is_some() {
2683                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
2684                    self.rest.to_tokens(tokens);
2685                }
2686            })
2687        }
2688    }
2689
2690    #[cfg(feature = "full")]
2691    impl ToTokens for ExprRepeat {
2692        fn to_tokens(&self, tokens: &mut Tokens) {
2693            self.bracket_token.surround(tokens, |tokens| {
2694                self.expr.to_tokens(tokens);
2695                self.semi_token.to_tokens(tokens);
2696                self.amt.to_tokens(tokens);
2697            })
2698        }
2699    }
2700
2701    impl ToTokens for ExprGroup {
2702        fn to_tokens(&self, tokens: &mut Tokens) {
2703            self.group_token.surround(tokens, |tokens| {
2704                self.expr.to_tokens(tokens);
2705            });
2706        }
2707    }
2708
2709    impl ToTokens for ExprParen {
2710        fn to_tokens(&self, tokens: &mut Tokens) {
2711            self.paren_token.surround(tokens, |tokens| {
2712                self.expr.to_tokens(tokens);
2713            });
2714        }
2715    }
2716
2717    #[cfg(feature = "full")]
2718    impl ToTokens for ExprTry {
2719        fn to_tokens(&self, tokens: &mut Tokens) {
2720            self.expr.to_tokens(tokens);
2721            self.question_token.to_tokens(tokens);
2722        }
2723    }
2724
2725    #[cfg(feature = "full")]
2726    impl ToTokens for FieldValue {
2727        fn to_tokens(&self, tokens: &mut Tokens) {
2728            self.ident.to_tokens(tokens);
2729            // XXX: Override self.is_shorthand if expr is not an IdentExpr with
2730            // the ident self.ident?
2731            if !self.is_shorthand {
2732                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2733                self.expr.to_tokens(tokens);
2734            }
2735        }
2736    }
2737
2738    #[cfg(feature = "full")]
2739    impl ToTokens for Arm {
2740        fn to_tokens(&self, tokens: &mut Tokens) {
2741            tokens.append_all(&self.attrs);
2742            self.pats.to_tokens(tokens);
2743            if self.guard.is_some() {
2744                TokensOrDefault(&self.if_token).to_tokens(tokens);
2745                self.guard.to_tokens(tokens);
2746            }
2747            self.rocket_token.to_tokens(tokens);
2748            self.body.to_tokens(tokens);
2749            self.comma.to_tokens(tokens);
2750        }
2751    }
2752
2753    #[cfg(feature = "full")]
2754    impl ToTokens for PatWild {
2755        fn to_tokens(&self, tokens: &mut Tokens) {
2756            self.underscore_token.to_tokens(tokens);
2757        }
2758    }
2759
2760    #[cfg(feature = "full")]
2761    impl ToTokens for PatIdent {
2762        fn to_tokens(&self, tokens: &mut Tokens) {
2763            self.mode.to_tokens(tokens);
2764            self.ident.to_tokens(tokens);
2765            if self.subpat.is_some() {
2766                TokensOrDefault(&self.at_token).to_tokens(tokens);
2767                self.subpat.to_tokens(tokens);
2768            }
2769        }
2770    }
2771
2772    #[cfg(feature = "full")]
2773    impl ToTokens for PatStruct {
2774        fn to_tokens(&self, tokens: &mut Tokens) {
2775            self.path.to_tokens(tokens);
2776            self.brace_token.surround(tokens, |tokens| {
2777                self.fields.to_tokens(tokens);
2778                // NOTE: We need a comma before the dot2 token if it is present.
2779                if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
2780                    tokens::Comma::default().to_tokens(tokens);
2781                }
2782                self.dot2_token.to_tokens(tokens);
2783            });
2784        }
2785    }
2786
2787    #[cfg(feature = "full")]
2788    impl ToTokens for PatTupleStruct {
2789        fn to_tokens(&self, tokens: &mut Tokens) {
2790            self.path.to_tokens(tokens);
2791            self.pat.to_tokens(tokens);
2792        }
2793    }
2794
2795    #[cfg(feature = "full")]
2796    impl ToTokens for PatPath {
2797        fn to_tokens(&self, tokens: &mut Tokens) {
2798            ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
2799        }
2800    }
2801
2802    #[cfg(feature = "full")]
2803    impl ToTokens for PatTuple {
2804        fn to_tokens(&self, tokens: &mut Tokens) {
2805            self.paren_token.surround(tokens, |tokens| {
2806                for (i, token) in self.pats.iter().enumerate() {
2807                    if Some(i) == self.dots_pos {
2808                        TokensOrDefault(&self.dot2_token).to_tokens(tokens);
2809                        TokensOrDefault(&self.comma_token).to_tokens(tokens);
2810                    }
2811                    token.to_tokens(tokens);
2812                }
2813
2814                if Some(self.pats.len()) == self.dots_pos {
2815                    // Ensure there is a comma before the .. token.
2816                    if !self.pats.empty_or_trailing() {
2817                        tokens::Comma::default().to_tokens(tokens);
2818                    }
2819                    self.dot2_token.to_tokens(tokens);
2820                }
2821            });
2822        }
2823    }
2824
2825    #[cfg(feature = "full")]
2826    impl ToTokens for PatBox {
2827        fn to_tokens(&self, tokens: &mut Tokens) {
2828            self.box_token.to_tokens(tokens);
2829            self.pat.to_tokens(tokens);
2830        }
2831    }
2832
2833    #[cfg(feature = "full")]
2834    impl ToTokens for PatRef {
2835        fn to_tokens(&self, tokens: &mut Tokens) {
2836            self.and_token.to_tokens(tokens);
2837            self.mutbl.to_tokens(tokens);
2838            self.pat.to_tokens(tokens);
2839        }
2840    }
2841
2842    #[cfg(feature = "full")]
2843    impl ToTokens for PatLit {
2844        fn to_tokens(&self, tokens: &mut Tokens) {
2845            self.expr.to_tokens(tokens);
2846        }
2847    }
2848
2849    #[cfg(feature = "full")]
2850    impl ToTokens for PatRange {
2851        fn to_tokens(&self, tokens: &mut Tokens) {
2852            self.lo.to_tokens(tokens);
2853            self.limits.to_tokens(tokens);
2854            self.hi.to_tokens(tokens);
2855        }
2856    }
2857
2858    #[cfg(feature = "full")]
2859    impl ToTokens for PatSlice {
2860        fn to_tokens(&self, tokens: &mut Tokens) {
2861            // XXX: This is a mess, and it will be so easy to screw it up. How
2862            // do we make this correct itself better?
2863            self.bracket_token.surround(tokens, |tokens| {
2864                self.front.to_tokens(tokens);
2865
2866                // If we need a comma before the middle or standalone .. token,
2867                // then make sure it's present.
2868                if !self.front.empty_or_trailing() &&
2869                    (self.middle.is_some() || self.dot2_token.is_some())
2870                {
2871                    tokens::Comma::default().to_tokens(tokens);
2872                }
2873
2874                // If we have an identifier, we always need a .. token.
2875                if self.middle.is_some() {
2876                    self.middle.to_tokens(tokens);
2877                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
2878                } else if self.dot2_token.is_some() {
2879                    self.dot2_token.to_tokens(tokens);
2880                }
2881
2882                // Make sure we have a comma before the back half.
2883                if !self.back.is_empty() {
2884                    TokensOrDefault(&self.comma_token).to_tokens(tokens);
2885                    self.back.to_tokens(tokens);
2886                } else {
2887                    self.comma_token.to_tokens(tokens);
2888                }
2889            })
2890        }
2891    }
2892
2893    #[cfg(feature = "full")]
2894    impl ToTokens for RangeLimits {
2895        fn to_tokens(&self, tokens: &mut Tokens) {
2896            match *self {
2897                RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
2898                RangeLimits::Closed(ref t) => t.to_tokens(tokens),
2899            }
2900        }
2901    }
2902
2903    #[cfg(feature = "full")]
2904    impl ToTokens for FieldPat {
2905        fn to_tokens(&self, tokens: &mut Tokens) {
2906            // XXX: Override is_shorthand if it was wrong?
2907            if !self.is_shorthand {
2908                self.ident.to_tokens(tokens);
2909                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2910            }
2911            self.pat.to_tokens(tokens);
2912        }
2913    }
2914
2915    #[cfg(feature = "full")]
2916    impl ToTokens for BindingMode {
2917        fn to_tokens(&self, tokens: &mut Tokens) {
2918            match *self {
2919                BindingMode::ByRef(ref t, ref m) => {
2920                    t.to_tokens(tokens);
2921                    m.to_tokens(tokens);
2922                }
2923                BindingMode::ByValue(ref m) => {
2924                    m.to_tokens(tokens);
2925                }
2926            }
2927        }
2928    }
2929
2930    #[cfg(feature = "full")]
2931    impl ToTokens for CaptureBy {
2932        fn to_tokens(&self, tokens: &mut Tokens) {
2933            match *self {
2934                CaptureBy::Value(ref t) => t.to_tokens(tokens),
2935                CaptureBy::Ref => {
2936                    // nothing
2937                }
2938            }
2939        }
2940    }
2941
2942    #[cfg(feature = "full")]
2943    impl ToTokens for Block {
2944        fn to_tokens(&self, tokens: &mut Tokens) {
2945            self.brace_token.surround(tokens, |tokens| {
2946                tokens.append_all(&self.stmts);
2947            });
2948        }
2949    }
2950
2951    #[cfg(feature = "full")]
2952    impl ToTokens for Stmt {
2953        fn to_tokens(&self, tokens: &mut Tokens) {
2954            match *self {
2955                Stmt::Local(ref local) => local.to_tokens(tokens),
2956                Stmt::Item(ref item) => item.to_tokens(tokens),
2957                Stmt::Expr(ref expr) => expr.to_tokens(tokens),
2958                Stmt::Semi(ref expr, ref semi) => {
2959                    expr.to_tokens(tokens);
2960                    semi.to_tokens(tokens);
2961                }
2962                Stmt::Mac(ref mac) => {
2963                    let (ref mac, ref style, ref attrs) = **mac;
2964                    tokens.append_all(attrs.outer());
2965                    mac.to_tokens(tokens);
2966                    match *style {
2967                        MacStmtStyle::Semicolon(ref s) => s.to_tokens(tokens),
2968                        MacStmtStyle::Braces | MacStmtStyle::NoBraces => {
2969                            // no semicolon
2970                        }
2971                    }
2972                }
2973            }
2974        }
2975    }
2976
2977    #[cfg(feature = "full")]
2978    impl ToTokens for Local {
2979        fn to_tokens(&self, tokens: &mut Tokens) {
2980            tokens.append_all(self.attrs.outer());
2981            self.let_token.to_tokens(tokens);
2982            self.pat.to_tokens(tokens);
2983            if self.ty.is_some() {
2984                TokensOrDefault(&self.colon_token).to_tokens(tokens);
2985                self.ty.to_tokens(tokens);
2986            }
2987            if self.init.is_some() {
2988                TokensOrDefault(&self.eq_token).to_tokens(tokens);
2989                self.init.to_tokens(tokens);
2990            }
2991            self.semi_token.to_tokens(tokens);
2992        }
2993    }
2994}