standalone_syn/
expr.rs

1// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use super::*;
10use punctuated::Punctuated;
11use proc_macro2::{Span, TokenStream};
12#[cfg(feature = "extra-traits")]
13use std::hash::{Hash, Hasher};
14#[cfg(feature = "extra-traits")]
15use tt::TokenStreamHelper;
16#[cfg(feature = "full")]
17use std::mem;
18
19ast_enum_of_structs! {
20    /// A Rust expression.
21    ///
22    /// *This type is available if Syn is built with the `"derive"` or `"full"`
23    /// feature.*
24    ///
25    /// # Syntax tree enums
26    ///
27    /// This type is a syntax tree enum. In Syn this and other syntax tree enums
28    /// are designed to be traversed using the following rebinding idiom.
29    ///
30    /// ```
31    /// # use syn::Expr;
32    /// #
33    /// # fn example(expr: Expr) {
34    /// # const IGNORE: &str = stringify! {
35    /// let expr: Expr = /* ... */;
36    /// # };
37    /// match expr {
38    ///     Expr::MethodCall(expr) => {
39    ///         /* ... */
40    ///     }
41    ///     Expr::Cast(expr) => {
42    ///         /* ... */
43    ///     }
44    ///     Expr::IfLet(expr) => {
45    ///         /* ... */
46    ///     }
47    ///     /* ... */
48    ///     # _ => {}
49    /// }
50    /// # }
51    /// ```
52    ///
53    /// We begin with a variable `expr` of type `Expr` that has no fields
54    /// (because it is an enum), and by matching on it and rebinding a variable
55    /// with the same name `expr` we effectively imbue our variable with all of
56    /// the data fields provided by the variant that it turned out to be. So for
57    /// example above if we ended up in the `MethodCall` case then we get to use
58    /// `expr.receiver`, `expr.args` etc; if we ended up in the `IfLet` case we
59    /// get to use `expr.pat`, `expr.then_branch`, `expr.else_branch`.
60    ///
61    /// The pattern is similar if the input expression is borrowed:
62    ///
63    /// ```
64    /// # use syn::Expr;
65    /// #
66    /// # fn example(expr: &Expr) {
67    /// match *expr {
68    ///     Expr::MethodCall(ref expr) => {
69    /// #   }
70    /// #   _ => {}
71    /// # }
72    /// # }
73    /// ```
74    ///
75    /// This approach avoids repeating the variant names twice on every line.
76    ///
77    /// ```
78    /// # use syn::{Expr, ExprMethodCall};
79    /// #
80    /// # fn example(expr: Expr) {
81    /// # match expr {
82    /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
83    /// # }
84    /// # _ => {}
85    /// # }
86    /// # }
87    /// ```
88    ///
89    /// In general, the name to which a syntax tree enum variant is bound should
90    /// be a suitable name for the complete syntax tree enum type.
91    ///
92    /// ```
93    /// # use syn::{Expr, ExprField};
94    /// #
95    /// # fn example(discriminant: &ExprField) {
96    /// // Binding is called `base` which is the name I would use if I were
97    /// // assigning `*discriminant.base` without an `if let`.
98    /// if let Expr::Tuple(ref base) = *discriminant.base {
99    /// # }
100    /// # }
101    /// ```
102    ///
103    /// A sign that you may not be choosing the right variable names is if you
104    /// see names getting repeated in your code, like accessing
105    /// `receiver.receiver` or `pat.pat` or `cond.cond`.
106    pub enum Expr {
107        /// A box expression: `box f`.
108        ///
109        /// *This type is available if Syn is built with the `"full"` feature.*
110        pub Box(ExprBox #full {
111            pub attrs: Vec<Attribute>,
112            pub box_token: Token![box],
113            pub expr: Box<Expr>,
114        }),
115
116        /// A placement expression: `place <- value`.
117        ///
118        /// *This type is available if Syn is built with the `"full"` feature.*
119        pub InPlace(ExprInPlace #full {
120            pub attrs: Vec<Attribute>,
121            pub place: Box<Expr>,
122            pub arrow_token: Token![<-],
123            pub value: Box<Expr>,
124        }),
125
126        /// A slice literal expression: `[a, b, c, d]`.
127        ///
128        /// *This type is available if Syn is built with the `"full"` feature.*
129        pub Array(ExprArray #full {
130            pub attrs: Vec<Attribute>,
131            pub bracket_token: token::Bracket,
132            pub elems: Punctuated<Expr, Token![,]>,
133        }),
134
135        /// A function call expression: `invoke(a, b)`.
136        ///
137        /// *This type is available if Syn is built with the `"derive"` or
138        /// `"full"` feature.*
139        pub Call(ExprCall {
140            pub attrs: Vec<Attribute>,
141            pub func: Box<Expr>,
142            pub paren_token: token::Paren,
143            pub args: Punctuated<Expr, Token![,]>,
144        }),
145
146        /// A method call expression: `x.foo::<T>(a, b)`.
147        ///
148        /// *This type is available if Syn is built with the `"full"` feature.*
149        pub MethodCall(ExprMethodCall #full {
150            pub attrs: Vec<Attribute>,
151            pub receiver: Box<Expr>,
152            pub dot_token: Token![.],
153            pub method: Ident,
154            pub turbofish: Option<MethodTurbofish>,
155            pub paren_token: token::Paren,
156            pub args: Punctuated<Expr, Token![,]>,
157        }),
158
159        /// A tuple expression: `(a, b, c, d)`.
160        ///
161        /// *This type is available if Syn is built with the `"full"` feature.*
162        pub Tuple(ExprTuple #full {
163            pub attrs: Vec<Attribute>,
164            pub paren_token: token::Paren,
165            pub elems: Punctuated<Expr, Token![,]>,
166        }),
167
168        /// A binary operation: `a + b`, `a * b`.
169        ///
170        /// *This type is available if Syn is built with the `"derive"` or
171        /// `"full"` feature.*
172        pub Binary(ExprBinary {
173            pub attrs: Vec<Attribute>,
174            pub left: Box<Expr>,
175            pub op: BinOp,
176            pub right: Box<Expr>,
177        }),
178
179        /// A unary operation: `!x`, `*x`.
180        ///
181        /// *This type is available if Syn is built with the `"derive"` or
182        /// `"full"` feature.*
183        pub Unary(ExprUnary {
184            pub attrs: Vec<Attribute>,
185            pub op: UnOp,
186            pub expr: Box<Expr>,
187        }),
188
189        /// A literal in place of an expression: `1`, `"foo"`.
190        ///
191        /// *This type is available if Syn is built with the `"derive"` or
192        /// `"full"` feature.*
193        pub Lit(ExprLit {
194            pub attrs: Vec<Attribute>,
195            pub lit: Lit,
196        }),
197
198        /// A cast expression: `foo as f64`.
199        ///
200        /// *This type is available if Syn is built with the `"derive"` or
201        /// `"full"` feature.*
202        pub Cast(ExprCast {
203            pub attrs: Vec<Attribute>,
204            pub expr: Box<Expr>,
205            pub as_token: Token![as],
206            pub ty: Box<Type>,
207        }),
208
209        /// A type ascription expression: `foo: f64`.
210        ///
211        /// *This type is available if Syn is built with the `"full"` feature.*
212        pub Type(ExprType #full {
213            pub attrs: Vec<Attribute>,
214            pub expr: Box<Expr>,
215            pub colon_token: Token![:],
216            pub ty: Box<Type>,
217        }),
218
219        /// An `if` expression with an optional `else` block: `if expr { ... }
220        /// else { ... }`.
221        ///
222        /// The `else` branch expression may only be an `If`, `IfLet`, or
223        /// `Block` expression, not any of the other types of expression.
224        ///
225        /// *This type is available if Syn is built with the `"full"` feature.*
226        pub If(ExprIf #full {
227            pub attrs: Vec<Attribute>,
228            pub if_token: Token![if],
229            pub cond: Box<Expr>,
230            pub then_branch: Block,
231            pub else_branch: Option<(Token![else], Box<Expr>)>,
232        }),
233
234        /// An `if let` expression with an optional `else` block: `if let pat =
235        /// expr { ... } else { ... }`.
236        ///
237        /// The `else` branch expression may only be an `If`, `IfLet`, or
238        /// `Block` expression, not any of the other types of expression.
239        ///
240        /// *This type is available if Syn is built with the `"full"` feature.*
241        pub IfLet(ExprIfLet #full {
242            pub attrs: Vec<Attribute>,
243            pub if_token: Token![if],
244            pub let_token: Token![let],
245            pub pat: Box<Pat>,
246            pub eq_token: Token![=],
247            pub expr: Box<Expr>,
248            pub then_branch: Block,
249            pub else_branch: Option<(Token![else], Box<Expr>)>,
250        }),
251
252        /// A while loop: `while expr { ... }`.
253        ///
254        /// *This type is available if Syn is built with the `"full"` feature.*
255        pub While(ExprWhile #full {
256            pub attrs: Vec<Attribute>,
257            pub label: Option<Label>,
258            pub while_token: Token![while],
259            pub cond: Box<Expr>,
260            pub body: Block,
261        }),
262
263        /// A while-let loop: `while let pat = expr { ... }`.
264        ///
265        /// *This type is available if Syn is built with the `"full"` feature.*
266        pub WhileLet(ExprWhileLet #full {
267            pub attrs: Vec<Attribute>,
268            pub label: Option<Label>,
269            pub while_token: Token![while],
270            pub let_token: Token![let],
271            pub pat: Box<Pat>,
272            pub eq_token: Token![=],
273            pub expr: Box<Expr>,
274            pub body: Block,
275        }),
276
277        /// A for loop: `for pat in expr { ... }`.
278        ///
279        /// *This type is available if Syn is built with the `"full"` feature.*
280        pub ForLoop(ExprForLoop #full {
281            pub attrs: Vec<Attribute>,
282            pub label: Option<Label>,
283            pub for_token: Token![for],
284            pub pat: Box<Pat>,
285            pub in_token: Token![in],
286            pub expr: Box<Expr>,
287            pub body: Block,
288        }),
289
290        /// Conditionless loop: `loop { ... }`.
291        ///
292        /// *This type is available if Syn is built with the `"full"` feature.*
293        pub Loop(ExprLoop #full {
294            pub attrs: Vec<Attribute>,
295            pub label: Option<Label>,
296            pub loop_token: Token![loop],
297            pub body: Block,
298        }),
299
300        /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
301        ///
302        /// *This type is available if Syn is built with the `"full"` feature.*
303        pub Match(ExprMatch #full {
304            pub attrs: Vec<Attribute>,
305            pub match_token: Token![match],
306            pub expr: Box<Expr>,
307            pub brace_token: token::Brace,
308            pub arms: Vec<Arm>,
309        }),
310
311        /// A closure expression: `|a, b| a + b`.
312        ///
313        /// *This type is available if Syn is built with the `"full"` feature.*
314        pub Closure(ExprClosure #full {
315            pub attrs: Vec<Attribute>,
316            pub capture: Option<Token![move]>,
317            pub or1_token: Token![|],
318            pub inputs: Punctuated<FnArg, Token![,]>,
319            pub or2_token: Token![|],
320            pub output: ReturnType,
321            pub body: Box<Expr>,
322        }),
323
324        /// An unsafe block: `unsafe { ... }`.
325        ///
326        /// *This type is available if Syn is built with the `"full"` feature.*
327        pub Unsafe(ExprUnsafe #full {
328            pub attrs: Vec<Attribute>,
329            pub unsafe_token: Token![unsafe],
330            pub block: Block,
331        }),
332
333        /// A blocked scope: `{ ... }`.
334        ///
335        /// *This type is available if Syn is built with the `"full"` feature.*
336        pub Block(ExprBlock #full {
337            pub attrs: Vec<Attribute>,
338            pub block: Block,
339        }),
340
341        /// An assignment expression: `a = compute()`.
342        ///
343        /// *This type is available if Syn is built with the `"full"` feature.*
344        pub Assign(ExprAssign #full {
345            pub attrs: Vec<Attribute>,
346            pub left: Box<Expr>,
347            pub eq_token: Token![=],
348            pub right: Box<Expr>,
349        }),
350
351        /// A compound assignment expression: `counter += 1`.
352        ///
353        /// *This type is available if Syn is built with the `"full"` feature.*
354        pub AssignOp(ExprAssignOp #full {
355            pub attrs: Vec<Attribute>,
356            pub left: Box<Expr>,
357            pub op: BinOp,
358            pub right: Box<Expr>,
359        }),
360
361        /// Access of a named struct field (`obj.k`) or unnamed tuple struct
362        /// field (`obj.0`).
363        ///
364        /// *This type is available if Syn is built with the `"full"` feature.*
365        pub Field(ExprField #full {
366            pub attrs: Vec<Attribute>,
367            pub base: Box<Expr>,
368            pub dot_token: Token![.],
369            pub member: Member,
370        }),
371
372        /// A square bracketed indexing expression: `vector[2]`.
373        ///
374        /// *This type is available if Syn is built with the `"derive"` or
375        /// `"full"` feature.*
376        pub Index(ExprIndex {
377            pub attrs: Vec<Attribute>,
378            pub expr: Box<Expr>,
379            pub bracket_token: token::Bracket,
380            pub index: Box<Expr>,
381        }),
382
383        /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
384        ///
385        /// *This type is available if Syn is built with the `"full"` feature.*
386        pub Range(ExprRange #full {
387            pub attrs: Vec<Attribute>,
388            pub from: Option<Box<Expr>>,
389            pub limits: RangeLimits,
390            pub to: Option<Box<Expr>>,
391        }),
392
393        /// A path like `std::mem::replace` possibly containing generic
394        /// parameters and a qualified self-type.
395        ///
396        /// A plain identifier like `x` is a path of length 1.
397        ///
398        /// *This type is available if Syn is built with the `"derive"` or
399        /// `"full"` feature.*
400        pub Path(ExprPath {
401            pub attrs: Vec<Attribute>,
402            pub qself: Option<QSelf>,
403            pub path: Path,
404        }),
405
406        /// A referencing operation: `&a` or `&mut a`.
407        ///
408        /// *This type is available if Syn is built with the `"full"` feature.*
409        pub AddrOf(ExprAddrOf #full {
410            pub attrs: Vec<Attribute>,
411            pub and_token: Token![&],
412            pub mutability: Option<Token![mut]>,
413            pub expr: Box<Expr>,
414        }),
415
416        /// A `break`, with an optional label to break and an optional
417        /// expression.
418        ///
419        /// *This type is available if Syn is built with the `"full"` feature.*
420        pub Break(ExprBreak #full {
421            pub attrs: Vec<Attribute>,
422            pub break_token: Token![break],
423            pub label: Option<Lifetime>,
424            pub expr: Option<Box<Expr>>,
425        }),
426
427        /// A `continue`, with an optional label.
428        ///
429        /// *This type is available if Syn is built with the `"full"` feature.*
430        pub Continue(ExprContinue #full {
431            pub attrs: Vec<Attribute>,
432            pub continue_token: Token![continue],
433            pub label: Option<Lifetime>,
434        }),
435
436        /// A `return`, with an optional value to be returned.
437        ///
438        /// *This type is available if Syn is built with the `"full"` feature.*
439        pub Return(ExprReturn #full {
440            pub attrs: Vec<Attribute>,
441            pub return_token: Token![return],
442            pub expr: Option<Box<Expr>>,
443        }),
444
445        /// A macro invocation expression: `format!("{}", q)`.
446        ///
447        /// *This type is available if Syn is built with the `"full"` feature.*
448        pub Macro(ExprMacro #full {
449            pub attrs: Vec<Attribute>,
450            pub mac: Macro,
451        }),
452
453        /// A struct literal expression: `Point { x: 1, y: 1 }`.
454        ///
455        /// The `rest` provides the value of the remaining fields as in `S { a:
456        /// 1, b: 1, ..rest }`.
457        ///
458        /// *This type is available if Syn is built with the `"full"` feature.*
459        pub Struct(ExprStruct #full {
460            pub attrs: Vec<Attribute>,
461            pub path: Path,
462            pub brace_token: token::Brace,
463            pub fields: Punctuated<FieldValue, Token![,]>,
464            pub dot2_token: Option<Token![..]>,
465            pub rest: Option<Box<Expr>>,
466        }),
467
468        /// An array literal constructed from one repeated element: `[0u8; N]`.
469        ///
470        /// *This type is available if Syn is built with the `"full"` feature.*
471        pub Repeat(ExprRepeat #full {
472            pub attrs: Vec<Attribute>,
473            pub bracket_token: token::Bracket,
474            pub expr: Box<Expr>,
475            pub semi_token: Token![;],
476            pub len: Box<Expr>,
477        }),
478
479        /// A parenthesized expression: `(a + b)`.
480        ///
481        /// *This type is available if Syn is built with the `"full"` feature.*
482        pub Paren(ExprParen {
483            pub attrs: Vec<Attribute>,
484            pub paren_token: token::Paren,
485            pub expr: Box<Expr>,
486        }),
487
488        /// An expression contained within invisible delimiters.
489        ///
490        /// This variant is important for faithfully representing the precedence
491        /// of expressions and is related to `None`-delimited spans in a
492        /// `TokenStream`.
493        ///
494        /// *This type is available if Syn is built with the `"full"` feature.*
495        pub Group(ExprGroup #full {
496            pub attrs: Vec<Attribute>,
497            pub group_token: token::Group,
498            pub expr: Box<Expr>,
499        }),
500
501        /// A try-expression: `expr?`.
502        ///
503        /// *This type is available if Syn is built with the `"full"` feature.*
504        pub Try(ExprTry #full {
505            pub attrs: Vec<Attribute>,
506            pub expr: Box<Expr>,
507            pub question_token: Token![?],
508        }),
509
510        /// A catch expression: `do catch { ... }`.
511        ///
512        /// *This type is available if Syn is built with the `"full"` feature.*
513        pub Catch(ExprCatch #full {
514            pub attrs: Vec<Attribute>,
515            pub do_token: Token![do],
516            pub catch_token: Token![catch],
517            pub block: Block,
518        }),
519
520        /// A yield expression: `yield expr`.
521        ///
522        /// *This type is available if Syn is built with the `"full"` feature.*
523        pub Yield(ExprYield #full {
524            pub attrs: Vec<Attribute>,
525            pub yield_token: Token![yield],
526            pub expr: Option<Box<Expr>>,
527        }),
528
529        /// Tokens in expression position not interpreted by Syn.
530        ///
531        /// *This type is available if Syn is built with the `"derive"` or
532        /// `"full"` feature.*
533        pub Verbatim(ExprVerbatim #manual_extra_traits {
534            pub tts: TokenStream,
535        }),
536    }
537}
538
539#[cfg(feature = "extra-traits")]
540impl Eq for ExprVerbatim {}
541
542#[cfg(feature = "extra-traits")]
543impl PartialEq for ExprVerbatim {
544    fn eq(&self, other: &Self) -> bool {
545        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
546    }
547}
548
549#[cfg(feature = "extra-traits")]
550impl Hash for ExprVerbatim {
551    fn hash<H>(&self, state: &mut H)
552    where
553        H: Hasher,
554    {
555        TokenStreamHelper(&self.tts).hash(state);
556    }
557}
558
559impl Expr {
560    // Not public API.
561    #[doc(hidden)]
562    #[cfg(feature = "full")]
563    pub fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
564        match *self {
565            Expr::Box(ExprBox { ref mut attrs, .. })
566            | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
567            | Expr::Array(ExprArray { ref mut attrs, .. })
568            | Expr::Call(ExprCall { ref mut attrs, .. })
569            | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
570            | Expr::Tuple(ExprTuple { ref mut attrs, .. })
571            | Expr::Binary(ExprBinary { ref mut attrs, .. })
572            | Expr::Unary(ExprUnary { ref mut attrs, .. })
573            | Expr::Lit(ExprLit { ref mut attrs, .. })
574            | Expr::Cast(ExprCast { ref mut attrs, .. })
575            | Expr::Type(ExprType { ref mut attrs, .. })
576            | Expr::If(ExprIf { ref mut attrs, .. })
577            | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
578            | Expr::While(ExprWhile { ref mut attrs, .. })
579            | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
580            | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
581            | Expr::Loop(ExprLoop { ref mut attrs, .. })
582            | Expr::Match(ExprMatch { ref mut attrs, .. })
583            | Expr::Closure(ExprClosure { ref mut attrs, .. })
584            | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
585            | Expr::Block(ExprBlock { ref mut attrs, .. })
586            | Expr::Assign(ExprAssign { ref mut attrs, .. })
587            | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
588            | Expr::Field(ExprField { ref mut attrs, .. })
589            | Expr::Index(ExprIndex { ref mut attrs, .. })
590            | Expr::Range(ExprRange { ref mut attrs, .. })
591            | Expr::Path(ExprPath { ref mut attrs, .. })
592            | Expr::AddrOf(ExprAddrOf { ref mut attrs, .. })
593            | Expr::Break(ExprBreak { ref mut attrs, .. })
594            | Expr::Continue(ExprContinue { ref mut attrs, .. })
595            | Expr::Return(ExprReturn { ref mut attrs, .. })
596            | Expr::Macro(ExprMacro { ref mut attrs, .. })
597            | Expr::Struct(ExprStruct { ref mut attrs, .. })
598            | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
599            | Expr::Paren(ExprParen { ref mut attrs, .. })
600            | Expr::Group(ExprGroup { ref mut attrs, .. })
601            | Expr::Try(ExprTry { ref mut attrs, .. })
602            | Expr::Catch(ExprCatch { ref mut attrs, .. })
603            | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
604            Expr::Verbatim(_) => {
605                // TODO
606                Vec::new()
607            }
608        }
609    }
610}
611
612ast_enum! {
613    /// A struct or tuple struct field accessed in a struct literal or field
614    /// expression.
615    ///
616    /// *This type is available if Syn is built with the `"derive"` or `"full"`
617    /// feature.*
618    pub enum Member {
619        /// A named field like `self.x`.
620        Named(Ident),
621        /// An unnamed field like `self.0`.
622        Unnamed(Index),
623    }
624}
625
626ast_struct! {
627    /// The index of an unnamed tuple struct field.
628    ///
629    /// *This type is available if Syn is built with the `"derive"` or `"full"`
630    /// feature.*
631    pub struct Index #manual_extra_traits {
632        pub index: u32,
633        pub span: Span,
634    }
635}
636
637impl From<usize> for Index {
638    fn from(index: usize) -> Index {
639        assert!(index < std::u32::MAX as usize);
640        Index {
641            index: index as u32,
642            span: Span::def_site(),
643        }
644    }
645}
646
647#[cfg(feature = "extra-traits")]
648impl Eq for Index {}
649
650#[cfg(feature = "extra-traits")]
651impl PartialEq for Index {
652    fn eq(&self, other: &Self) -> bool {
653        self.index == other.index
654    }
655}
656
657#[cfg(feature = "extra-traits")]
658impl Hash for Index {
659    fn hash<H: Hasher>(&self, state: &mut H) {
660        self.index.hash(state);
661    }
662}
663
664#[cfg(feature = "full")]
665ast_struct! {
666    /// The `::<>` explicit type parameters passed to a method call:
667    /// `parse::<u64>()`.
668    ///
669    /// *This type is available if Syn is built with the `"full"` feature.*
670    pub struct MethodTurbofish {
671        pub colon2_token: Token![::],
672        pub lt_token: Token![<],
673        pub args: Punctuated<GenericMethodArgument, Token![,]>,
674        pub gt_token: Token![>],
675    }
676}
677
678#[cfg(feature = "full")]
679ast_enum! {
680    /// An individual generic argument to a method, like `T`.
681    ///
682    /// *This type is available if Syn is built with the `"full"` feature.*
683    pub enum GenericMethodArgument {
684        /// A type argument.
685        Type(Type),
686        /// A const expression. Must be inside of a block.
687        ///
688        /// NOTE: Identity expressions are represented as Type arguments, as
689        /// they are indistinguishable syntactically.
690        Const(Expr),
691    }
692}
693
694#[cfg(feature = "full")]
695ast_struct! {
696    /// A field-value pair in a struct literal.
697    ///
698    /// *This type is available if Syn is built with the `"full"` feature.*
699    pub struct FieldValue {
700        /// Attributes tagged on the field.
701        pub attrs: Vec<Attribute>,
702
703        /// Name or index of the field.
704        pub member: Member,
705
706        /// The colon in `Struct { x: x }`. If written in shorthand like
707        /// `Struct { x }`, there is no colon.
708        pub colon_token: Option<Token![:]>,
709
710        /// Value of the field.
711        pub expr: Expr,
712    }
713}
714
715#[cfg(feature = "full")]
716ast_struct! {
717    /// A lifetime labeling a `for`, `while`, or `loop`.
718    ///
719    /// *This type is available if Syn is built with the `"full"` feature.*
720    pub struct Label {
721        pub name: Lifetime,
722        pub colon_token: Token![:],
723    }
724}
725
726#[cfg(feature = "full")]
727ast_struct! {
728    /// A braced block containing Rust statements.
729    ///
730    /// *This type is available if Syn is built with the `"full"` feature.*
731    pub struct Block {
732        pub brace_token: token::Brace,
733        /// Statements in a block
734        pub stmts: Vec<Stmt>,
735    }
736}
737
738#[cfg(feature = "full")]
739ast_enum! {
740    /// A statement, usually ending in a semicolon.
741    ///
742    /// *This type is available if Syn is built with the `"full"` feature.*
743    pub enum Stmt {
744        /// A local (let) binding.
745        Local(Local),
746
747        /// An item definition.
748        Item(Item),
749
750        /// Expr without trailing semicolon.
751        Expr(Expr),
752
753        /// Expression with trailing semicolon.
754        Semi(Expr, Token![;]),
755    }
756}
757
758#[cfg(feature = "full")]
759ast_struct! {
760    /// A local `let` binding: `let x: u64 = s.parse()?`.
761    ///
762    /// *This type is available if Syn is built with the `"full"` feature.*
763    pub struct Local {
764        pub attrs: Vec<Attribute>,
765        pub let_token: Token![let],
766        pub pat: Box<Pat>,
767        pub ty: Option<(Token![:], Box<Type>)>,
768        pub init: Option<(Token![=], Box<Expr>)>,
769        pub semi_token: Token![;],
770    }
771}
772
773#[cfg(feature = "full")]
774ast_enum_of_structs! {
775    /// A pattern in a local binding, function signature, match expression, or
776    /// various other places.
777    ///
778    /// *This type is available if Syn is built with the `"full"` feature.*
779    ///
780    /// # Syntax tree enum
781    ///
782    /// This type is a [syntax tree enum].
783    ///
784    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
785    // Clippy false positive
786    // https://github.com/Manishearth/rust-clippy/issues/1241
787    #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
788    pub enum Pat {
789        /// A pattern that matches any value: `_`.
790        ///
791        /// *This type is available if Syn is built with the `"full"` feature.*
792        pub Wild(PatWild {
793            pub underscore_token: Token![_],
794        }),
795
796        /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
797        ///
798        /// *This type is available if Syn is built with the `"full"` feature.*
799        pub Ident(PatIdent {
800            pub by_ref: Option<Token![ref]>,
801            pub mutability: Option<Token![mut]>,
802            pub ident: Ident,
803            pub subpat: Option<(Token![@], Box<Pat>)>,
804        }),
805
806        /// A struct or struct variant pattern: `Variant { x, y, .. }`.
807        ///
808        /// *This type is available if Syn is built with the `"full"` feature.*
809        pub Struct(PatStruct {
810            pub path: Path,
811            pub brace_token: token::Brace,
812            pub fields: Punctuated<FieldPat, Token![,]>,
813            pub dot2_token: Option<Token![..]>,
814        }),
815
816        /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
817        ///
818        /// *This type is available if Syn is built with the `"full"` feature.*
819        pub TupleStruct(PatTupleStruct {
820            pub path: Path,
821            pub pat: PatTuple,
822        }),
823
824        /// A path pattern like `Color::Red`, optionally qualified with a
825        /// self-type.
826        ///
827        /// Unquailfied path patterns can legally refer to variants, structs,
828        /// constants or associated constants. Quailfied path patterns like
829        /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
830        /// associated constants.
831        ///
832        /// *This type is available if Syn is built with the `"full"` feature.*
833        pub Path(PatPath {
834            pub qself: Option<QSelf>,
835            pub path: Path,
836        }),
837
838        /// A tuple pattern: `(a, b)`.
839        ///
840        /// *This type is available if Syn is built with the `"full"` feature.*
841        pub Tuple(PatTuple {
842            pub paren_token: token::Paren,
843            pub front: Punctuated<Pat, Token![,]>,
844            pub dot2_token: Option<Token![..]>,
845            pub comma_token: Option<Token![,]>,
846            pub back: Punctuated<Pat, Token![,]>,
847        }),
848
849        /// A box pattern: `box v`.
850        ///
851        /// *This type is available if Syn is built with the `"full"` feature.*
852        pub Box(PatBox {
853            pub box_token: Token![box],
854            pub pat: Box<Pat>,
855        }),
856
857        /// A reference pattern: `&mut (first, second)`.
858        ///
859        /// *This type is available if Syn is built with the `"full"` feature.*
860        pub Ref(PatRef {
861            pub and_token: Token![&],
862            pub mutability: Option<Token![mut]>,
863            pub pat: Box<Pat>,
864        }),
865
866        /// A literal pattern: `0`.
867        ///
868        /// This holds an `Expr` rather than a `Lit` because negative numbers
869        /// are represented as an `Expr::Unary`.
870        ///
871        /// *This type is available if Syn is built with the `"full"` feature.*
872        pub Lit(PatLit {
873            pub expr: Box<Expr>,
874        }),
875
876        /// A range pattern: `1..=2`.
877        ///
878        /// *This type is available if Syn is built with the `"full"` feature.*
879        pub Range(PatRange {
880            pub lo: Box<Expr>,
881            pub limits: RangeLimits,
882            pub hi: Box<Expr>,
883        }),
884
885        /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
886        ///
887        /// *This type is available if Syn is built with the `"full"` feature.*
888        pub Slice(PatSlice {
889            pub bracket_token: token::Bracket,
890            pub front: Punctuated<Pat, Token![,]>,
891            pub middle: Option<Box<Pat>>,
892            pub dot2_token: Option<Token![..]>,
893            pub comma_token: Option<Token![,]>,
894            pub back: Punctuated<Pat, Token![,]>,
895        }),
896
897        /// A macro in expression position.
898        ///
899        /// *This type is available if Syn is built with the `"full"` feature.*
900        pub Macro(PatMacro {
901            pub mac: Macro,
902        }),
903
904        /// Tokens in pattern position not interpreted by Syn.
905        ///
906        /// *This type is available if Syn is built with the `"full"` feature.*
907        pub Verbatim(PatVerbatim #manual_extra_traits {
908            pub tts: TokenStream,
909        }),
910    }
911}
912
913#[cfg(all(feature = "full", feature = "extra-traits"))]
914impl Eq for PatVerbatim {}
915
916#[cfg(all(feature = "full", feature = "extra-traits"))]
917impl PartialEq for PatVerbatim {
918    fn eq(&self, other: &Self) -> bool {
919        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
920    }
921}
922
923#[cfg(all(feature = "full", feature = "extra-traits"))]
924impl Hash for PatVerbatim {
925    fn hash<H>(&self, state: &mut H)
926    where
927        H: Hasher,
928    {
929        TokenStreamHelper(&self.tts).hash(state);
930    }
931}
932
933#[cfg(feature = "full")]
934ast_struct! {
935    /// One arm of a `match` expression: `0...10 => { return true; }`.
936    ///
937    /// As in:
938    ///
939    /// ```rust
940    /// # fn f() -> bool {
941    /// #     let n = 0;
942    /// match n {
943    ///     0...10 => {
944    ///         return true;
945    ///     }
946    ///     // ...
947    ///     # _ => {}
948    /// }
949    /// #   false
950    /// # }
951    /// ```
952    ///
953    /// *This type is available if Syn is built with the `"full"` feature.*
954    pub struct Arm {
955        pub attrs: Vec<Attribute>,
956        pub pats: Punctuated<Pat, Token![|]>,
957        pub guard: Option<(Token![if], Box<Expr>)>,
958        pub rocket_token: Token![=>],
959        pub body: Box<Expr>,
960        pub comma: Option<Token![,]>,
961    }
962}
963
964#[cfg(feature = "full")]
965ast_enum! {
966    /// Limit types of a range, inclusive or exclusive.
967    ///
968    /// *This type is available if Syn is built with the `"full"` feature.*
969    #[cfg_attr(feature = "clone-impls", derive(Copy))]
970    pub enum RangeLimits {
971        /// Inclusive at the beginning, exclusive at the end.
972        HalfOpen(Token![..]),
973        /// Inclusive at the beginning and end.
974        Closed(Token![..=]),
975    }
976}
977
978#[cfg(feature = "full")]
979ast_struct! {
980    /// A single field in a struct pattern.
981    ///
982    /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
983    /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
984    ///
985    /// *This type is available if Syn is built with the `"full"` feature.*
986    pub struct FieldPat {
987        pub attrs: Vec<Attribute>,
988        pub member: Member,
989        pub colon_token: Option<Token![:]>,
990        pub pat: Box<Pat>,
991    }
992}
993
994#[cfg(any(feature = "parsing", feature = "printing"))]
995#[cfg(feature = "full")]
996fn arm_expr_requires_comma(expr: &Expr) -> bool {
997    // see https://github.com/rust-lang/rust/blob/eb8f2586e
998    //                       /src/libsyntax/parse/classify.rs#L17-L37
999    match *expr {
1000        Expr::Unsafe(..)
1001        | Expr::Block(..)
1002        | Expr::If(..)
1003        | Expr::IfLet(..)
1004        | Expr::Match(..)
1005        | Expr::While(..)
1006        | Expr::WhileLet(..)
1007        | Expr::Loop(..)
1008        | Expr::ForLoop(..)
1009        | Expr::Catch(..) => false,
1010        _ => true,
1011    }
1012}
1013
1014#[cfg(feature = "parsing")]
1015pub mod parsing {
1016    use super::*;
1017    use path::parsing::qpath;
1018    #[cfg(feature = "full")]
1019    use path::parsing::ty_no_eq_after;
1020
1021    #[cfg(feature = "full")]
1022    use proc_macro2::TokenStream;
1023    use synom::Synom;
1024    use buffer::Cursor;
1025    #[cfg(feature = "full")]
1026    use parse_error;
1027    use synom::PResult;
1028
1029    // When we're parsing expressions which occur before blocks, like in an if
1030    // statement's condition, we cannot parse a struct literal.
1031    //
1032    // Struct literals are ambiguous in certain positions
1033    // https://github.com/rust-lang/rfcs/pull/92
1034    macro_rules! ambiguous_expr {
1035        ($i:expr, $allow_struct:ident) => {
1036            ambiguous_expr($i, $allow_struct, true)
1037        };
1038    }
1039
1040    // When we are parsing an optional suffix expression, we cannot allow blocks
1041    // if structs are not allowed.
1042    //
1043    // Example:
1044    //
1045    //     if break {} {}
1046    //
1047    // is ambiguous between:
1048    //
1049    //     if (break {}) {}
1050    //     if (break) {} {}
1051    #[cfg(feature = "full")]
1052    macro_rules! opt_ambiguous_expr {
1053        ($i:expr, $allow_struct:ident) => {
1054            option!($i, call!(ambiguous_expr, $allow_struct, $allow_struct))
1055        };
1056    }
1057
1058    impl Synom for Expr {
1059        named!(parse -> Self, ambiguous_expr!(true));
1060
1061        fn description() -> Option<&'static str> {
1062            Some("expression")
1063        }
1064    }
1065
1066    #[cfg(feature = "full")]
1067    named!(expr_no_struct -> Expr, ambiguous_expr!(false));
1068
1069    // Parse an arbitrary expression.
1070    #[cfg(feature = "full")]
1071    fn ambiguous_expr(i: Cursor, allow_struct: bool, allow_block: bool) -> PResult<Expr> {
1072        call!(i, assign_expr, allow_struct, allow_block)
1073    }
1074
1075    #[cfg(not(feature = "full"))]
1076    fn ambiguous_expr(i: Cursor, allow_struct: bool, allow_block: bool) -> PResult<Expr> {
1077        // NOTE: We intentionally skip assign_expr, placement_expr, and
1078        // range_expr, as they are not parsed in non-full mode.
1079        call!(i, or_expr, allow_struct, allow_block)
1080    }
1081
1082    // Parse a left-associative binary operator.
1083    macro_rules! binop {
1084        (
1085            $name: ident,
1086            $next: ident,
1087            $submac: ident!( $($args:tt)* )
1088        ) => {
1089            named!($name(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
1090                mut e: call!($next, allow_struct, allow_block) >>
1091                many0!(do_parse!(
1092                    op: $submac!($($args)*) >>
1093                    rhs: call!($next, allow_struct, true) >>
1094                    ({
1095                        e = ExprBinary {
1096                            attrs: Vec::new(),
1097                            left: Box::new(e.into()),
1098                            op: op,
1099                            right: Box::new(rhs.into()),
1100                        }.into();
1101                    })
1102                )) >>
1103                (e)
1104            ));
1105        }
1106    }
1107
1108    // <placement> = <placement> ..
1109    // <placement> += <placement> ..
1110    // <placement> -= <placement> ..
1111    // <placement> *= <placement> ..
1112    // <placement> /= <placement> ..
1113    // <placement> %= <placement> ..
1114    // <placement> ^= <placement> ..
1115    // <placement> &= <placement> ..
1116    // <placement> |= <placement> ..
1117    // <placement> <<= <placement> ..
1118    // <placement> >>= <placement> ..
1119    //
1120    // NOTE: This operator is right-associative.
1121    #[cfg(feature = "full")]
1122    named!(assign_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
1123        mut e: call!(placement_expr, allow_struct, allow_block) >>
1124        alt!(
1125            do_parse!(
1126                eq: punct!(=) >>
1127                // Recurse into self to parse right-associative operator.
1128                rhs: call!(assign_expr, allow_struct, true) >>
1129                ({
1130                    e = ExprAssign {
1131                        attrs: Vec::new(),
1132                        left: Box::new(e),
1133                        eq_token: eq,
1134                        right: Box::new(rhs),
1135                    }.into();
1136                })
1137            )
1138            |
1139            do_parse!(
1140                op: call!(BinOp::parse_assign_op) >>
1141                // Recurse into self to parse right-associative operator.
1142                rhs: call!(assign_expr, allow_struct, true) >>
1143                ({
1144                    e = ExprAssignOp {
1145                        attrs: Vec::new(),
1146                        left: Box::new(e),
1147                        op: op,
1148                        right: Box::new(rhs),
1149                    }.into();
1150                })
1151            )
1152            |
1153            epsilon!()
1154        ) >>
1155        (e)
1156    ));
1157
1158    // <range> <- <range> ..
1159    //
1160    // NOTE: The `in place { expr }` version of this syntax is parsed in
1161    // `atom_expr`, not here.
1162    //
1163    // NOTE: This operator is right-associative.
1164    #[cfg(feature = "full")]
1165    named!(placement_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
1166        mut e: call!(range_expr, allow_struct, allow_block) >>
1167        alt!(
1168            do_parse!(
1169                arrow: punct!(<-) >>
1170                // Recurse into self to parse right-associative operator.
1171                rhs: call!(placement_expr, allow_struct, true) >>
1172                ({
1173                    e = ExprInPlace {
1174                        attrs: Vec::new(),
1175                        // op: BinOp::Place(larrow),
1176                        place: Box::new(e),
1177                        arrow_token: arrow,
1178                        value: Box::new(rhs),
1179                    }.into();
1180                })
1181            )
1182            |
1183            epsilon!()
1184        ) >>
1185        (e)
1186    ));
1187
1188    // <or> ... <or> ..
1189    // <or> .. <or> ..
1190    // <or> ..
1191    //
1192    // NOTE: This is currently parsed oddly - I'm not sure of what the exact
1193    // rules are for parsing these expressions are, but this is not correct.
1194    // For example, `a .. b .. c` is not a legal expression. It should not
1195    // be parsed as either `(a .. b) .. c` or `a .. (b .. c)` apparently.
1196    //
1197    // NOTE: The form of ranges which don't include a preceding expression are
1198    // parsed by `atom_expr`, rather than by this function.
1199    #[cfg(feature = "full")]
1200    named!(range_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
1201        mut e: call!(or_expr, allow_struct, allow_block) >>
1202        many0!(do_parse!(
1203            limits: syn!(RangeLimits) >>
1204            // We don't want to allow blocks here if we don't allow structs. See
1205            // the reasoning for `opt_ambiguous_expr!` above.
1206            hi: option!(call!(or_expr, allow_struct, allow_struct)) >>
1207            ({
1208                e = ExprRange {
1209                    attrs: Vec::new(),
1210                    from: Some(Box::new(e)),
1211                    limits: limits,
1212                    to: hi.map(|e| Box::new(e)),
1213                }.into();
1214            })
1215        )) >>
1216        (e)
1217    ));
1218
1219    // <and> || <and> ...
1220    binop!(or_expr, and_expr, map!(punct!(||), BinOp::Or));
1221
1222    // <compare> && <compare> ...
1223    binop!(and_expr, compare_expr, map!(punct!(&&), BinOp::And));
1224
1225    // <bitor> == <bitor> ...
1226    // <bitor> != <bitor> ...
1227    // <bitor> >= <bitor> ...
1228    // <bitor> <= <bitor> ...
1229    // <bitor> > <bitor> ...
1230    // <bitor> < <bitor> ...
1231    //
1232    // NOTE: This operator appears to be parsed as left-associative, but errors
1233    // if it is used in a non-associative manner.
1234    binop!(
1235        compare_expr,
1236        bitor_expr,
1237        alt!(
1238        punct!(==) => { BinOp::Eq }
1239        |
1240        punct!(!=) => { BinOp::Ne }
1241        |
1242        // must be above Lt
1243        punct!(<=) => { BinOp::Le }
1244        |
1245        // must be above Gt
1246        punct!(>=) => { BinOp::Ge }
1247        |
1248        do_parse!(
1249            // Make sure that we don't eat the < part of a <- operator
1250            not!(punct!(<-)) >>
1251            t: punct!(<) >>
1252            (BinOp::Lt(t))
1253        )
1254        |
1255        punct!(>) => { BinOp::Gt }
1256    )
1257    );
1258
1259    // <bitxor> | <bitxor> ...
1260    binop!(
1261        bitor_expr,
1262        bitxor_expr,
1263        do_parse!(not!(punct!(||)) >> not!(punct!(|=)) >> t: punct!(|) >> (BinOp::BitOr(t)))
1264    );
1265
1266    // <bitand> ^ <bitand> ...
1267    binop!(
1268        bitxor_expr,
1269        bitand_expr,
1270        do_parse!(
1271            // NOTE: Make sure we aren't looking at ^=.
1272            not!(punct!(^=)) >> t: punct!(^) >> (BinOp::BitXor(t))
1273        )
1274    );
1275
1276    // <shift> & <shift> ...
1277    binop!(
1278        bitand_expr,
1279        shift_expr,
1280        do_parse!(
1281            // NOTE: Make sure we aren't looking at && or &=.
1282            not!(punct!(&&)) >> not!(punct!(&=)) >> t: punct!(&) >> (BinOp::BitAnd(t))
1283        )
1284    );
1285
1286    // <arith> << <arith> ...
1287    // <arith> >> <arith> ...
1288    binop!(
1289        shift_expr,
1290        arith_expr,
1291        alt!(
1292        punct!(<<) => { BinOp::Shl }
1293        |
1294        punct!(>>) => { BinOp::Shr }
1295    )
1296    );
1297
1298    // <term> + <term> ...
1299    // <term> - <term> ...
1300    binop!(
1301        arith_expr,
1302        term_expr,
1303        alt!(
1304        punct!(+) => { BinOp::Add }
1305        |
1306        punct!(-) => { BinOp::Sub }
1307    )
1308    );
1309
1310    // <cast> * <cast> ...
1311    // <cast> / <cast> ...
1312    // <cast> % <cast> ...
1313    binop!(
1314        term_expr,
1315        cast_expr,
1316        alt!(
1317        punct!(*) => { BinOp::Mul }
1318        |
1319        punct!(/) => { BinOp::Div }
1320        |
1321        punct!(%) => { BinOp::Rem }
1322    )
1323    );
1324
1325    // <unary> as <ty>
1326    // <unary> : <ty>
1327    #[cfg(feature = "full")]
1328    named!(cast_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
1329        mut e: call!(unary_expr, allow_struct, allow_block) >>
1330        many0!(alt!(
1331            do_parse!(
1332                as_: keyword!(as) >>
1333                // We can't accept `A + B` in cast expressions, as it's
1334                // ambiguous with the + expression.
1335                ty: call!(Type::without_plus) >>
1336                ({
1337                    e = ExprCast {
1338                        attrs: Vec::new(),
1339                        expr: Box::new(e),
1340                        as_token: as_,
1341                        ty: Box::new(ty),
1342                    }.into();
1343                })
1344            )
1345            |
1346            do_parse!(
1347                colon: punct!(:) >>
1348                // We can't accept `A + B` in cast expressions, as it's
1349                // ambiguous with the + expression.
1350                ty: call!(Type::without_plus) >>
1351                ({
1352                    e = ExprType {
1353                        attrs: Vec::new(),
1354                        expr: Box::new(e),
1355                        colon_token: colon,
1356                        ty: Box::new(ty),
1357                    }.into();
1358                })
1359            )
1360        )) >>
1361        (e)
1362    ));
1363
1364    // <unary> as <ty>
1365    #[cfg(not(feature = "full"))]
1366    named!(cast_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
1367        mut e: call!(unary_expr, allow_struct, allow_block) >>
1368        many0!(do_parse!(
1369            as_: keyword!(as) >>
1370            // We can't accept `A + B` in cast expressions, as it's
1371            // ambiguous with the + expression.
1372            ty: call!(Type::without_plus) >>
1373            ({
1374                e = ExprCast {
1375                    attrs: Vec::new(),
1376                    expr: Box::new(e),
1377                    as_token: as_,
1378                    ty: Box::new(ty),
1379                }.into();
1380            })
1381        )) >>
1382        (e)
1383    ));
1384
1385    // <UnOp> <trailer>
1386    // & <trailer>
1387    // &mut <trailer>
1388    // box <trailer>
1389    #[cfg(feature = "full")]
1390    named!(unary_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
1391        do_parse!(
1392            op: syn!(UnOp) >>
1393            expr: call!(unary_expr, allow_struct, true) >>
1394            (ExprUnary {
1395                attrs: Vec::new(),
1396                op: op,
1397                expr: Box::new(expr),
1398            }.into())
1399        )
1400        |
1401        do_parse!(
1402            and: punct!(&) >>
1403            mutability: option!(keyword!(mut)) >>
1404            expr: call!(unary_expr, allow_struct, true) >>
1405            (ExprAddrOf {
1406                attrs: Vec::new(),
1407                and_token: and,
1408                mutability: mutability,
1409                expr: Box::new(expr),
1410            }.into())
1411        )
1412        |
1413        do_parse!(
1414            box_: keyword!(box) >>
1415            expr: call!(unary_expr, allow_struct, true) >>
1416            (ExprBox {
1417                attrs: Vec::new(),
1418                box_token: box_,
1419                expr: Box::new(expr),
1420            }.into())
1421        )
1422        |
1423        call!(trailer_expr, allow_struct, allow_block)
1424    ));
1425
1426    // XXX: This duplication is ugly
1427    #[cfg(not(feature = "full"))]
1428    named!(unary_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
1429        do_parse!(
1430            op: syn!(UnOp) >>
1431            expr: call!(unary_expr, allow_struct, true) >>
1432            (ExprUnary {
1433                attrs: Vec::new(),
1434                op: op,
1435                expr: Box::new(expr),
1436            }.into())
1437        )
1438        |
1439        call!(trailer_expr, allow_struct, allow_block)
1440    ));
1441
1442    // <atom> (..<args>) ...
1443    // <atom> . <ident> (..<args>) ...
1444    // <atom> . <ident> ...
1445    // <atom> . <lit> ...
1446    // <atom> [ <expr> ] ...
1447    // <atom> ? ...
1448    #[cfg(feature = "full")]
1449    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
1450        mut e: call!(atom_expr, allow_struct, allow_block) >>
1451        many0!(alt!(
1452            tap!(args: and_call => {
1453                let (paren, args) = args;
1454                e = ExprCall {
1455                    attrs: Vec::new(),
1456                    func: Box::new(e),
1457                    args: args,
1458                    paren_token: paren,
1459                }.into();
1460            })
1461            |
1462            tap!(more: and_method_call => {
1463                let mut call = more;
1464                call.receiver = Box::new(e);
1465                e = call.into();
1466            })
1467            |
1468            tap!(field: and_field => {
1469                let (token, member) = field;
1470                e = ExprField {
1471                    attrs: Vec::new(),
1472                    base: Box::new(e),
1473                    dot_token: token,
1474                    member: member,
1475                }.into();
1476            })
1477            |
1478            tap!(i: and_index => {
1479                let (bracket, i) = i;
1480                e = ExprIndex {
1481                    attrs: Vec::new(),
1482                    expr: Box::new(e),
1483                    bracket_token: bracket,
1484                    index: Box::new(i),
1485                }.into();
1486            })
1487            |
1488            tap!(question: punct!(?) => {
1489                e = ExprTry {
1490                    attrs: Vec::new(),
1491                    expr: Box::new(e),
1492                    question_token: question,
1493                }.into();
1494            })
1495        )) >>
1496        (e)
1497    ));
1498
1499    // XXX: Duplication == ugly
1500    #[cfg(not(feature = "full"))]
1501    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
1502        mut e: call!(atom_expr, allow_struct, allow_block) >>
1503        many0!(alt!(
1504            tap!(args: and_call => {
1505                e = ExprCall {
1506                    attrs: Vec::new(),
1507                    func: Box::new(e),
1508                    paren_token: args.0,
1509                    args: args.1,
1510                }.into();
1511            })
1512            |
1513            tap!(i: and_index => {
1514                e = ExprIndex {
1515                    attrs: Vec::new(),
1516                    expr: Box::new(e),
1517                    bracket_token: i.0,
1518                    index: Box::new(i.1),
1519                }.into();
1520            })
1521        )) >>
1522        (e)
1523    ));
1524
1525    // Parse all atomic expressions which don't have to worry about precedence
1526    // interactions, as they are fully contained.
1527    #[cfg(feature = "full")]
1528    named!(atom_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
1529        syn!(ExprGroup) => { Expr::Group } // must be placed first
1530        |
1531        syn!(ExprLit) => { Expr::Lit } // must be before expr_struct
1532        |
1533        // must be before expr_path
1534        cond_reduce!(allow_struct, syn!(ExprStruct)) => { Expr::Struct }
1535        |
1536        syn!(ExprParen) => { Expr::Paren } // must be before expr_tup
1537        |
1538        syn!(ExprMacro) => { Expr::Macro } // must be before expr_path
1539        |
1540        call!(expr_break, allow_struct) // must be before expr_path
1541        |
1542        syn!(ExprContinue) => { Expr::Continue } // must be before expr_path
1543        |
1544        call!(expr_ret, allow_struct) // must be before expr_path
1545        |
1546        syn!(ExprArray) => { Expr::Array }
1547        |
1548        syn!(ExprTuple) => { Expr::Tuple }
1549        |
1550        syn!(ExprIf) => { Expr::If }
1551        |
1552        syn!(ExprIfLet) => { Expr::IfLet }
1553        |
1554        syn!(ExprWhile) => { Expr::While }
1555        |
1556        syn!(ExprWhileLet) => { Expr::WhileLet }
1557        |
1558        syn!(ExprForLoop) => { Expr::ForLoop }
1559        |
1560        syn!(ExprLoop) => { Expr::Loop }
1561        |
1562        syn!(ExprMatch) => { Expr::Match }
1563        |
1564        syn!(ExprCatch) => { Expr::Catch }
1565        |
1566        syn!(ExprYield) => { Expr::Yield }
1567        |
1568        syn!(ExprUnsafe) => { Expr::Unsafe }
1569        |
1570        call!(expr_closure, allow_struct)
1571        |
1572        cond_reduce!(allow_block, syn!(ExprBlock)) => { Expr::Block }
1573        |
1574        // NOTE: This is the prefix-form of range
1575        call!(expr_range, allow_struct)
1576        |
1577        syn!(ExprPath) => { Expr::Path }
1578        |
1579        syn!(ExprRepeat) => { Expr::Repeat }
1580    ));
1581
1582    #[cfg(not(feature = "full"))]
1583    named!(atom_expr(_allow_struct: bool, _allow_block: bool) -> Expr, alt!(
1584        syn!(ExprLit) => { Expr::Lit }
1585        |
1586        syn!(ExprParen) => { Expr::Paren }
1587        |
1588        syn!(ExprPath) => { Expr::Path }
1589    ));
1590
1591    #[cfg(feature = "full")]
1592    named!(expr_nosemi -> Expr, map!(alt!(
1593        syn!(ExprIf) => { Expr::If }
1594        |
1595        syn!(ExprIfLet) => { Expr::IfLet }
1596        |
1597        syn!(ExprWhile) => { Expr::While }
1598        |
1599        syn!(ExprWhileLet) => { Expr::WhileLet }
1600        |
1601        syn!(ExprForLoop) => { Expr::ForLoop }
1602        |
1603        syn!(ExprLoop) => { Expr::Loop }
1604        |
1605        syn!(ExprMatch) => { Expr::Match }
1606        |
1607        syn!(ExprCatch) => { Expr::Catch }
1608        |
1609        syn!(ExprYield) => { Expr::Yield }
1610        |
1611        syn!(ExprUnsafe) => { Expr::Unsafe }
1612        |
1613        syn!(ExprBlock) => { Expr::Block }
1614    ), Expr::from));
1615
1616    impl Synom for ExprLit {
1617        named!(parse -> Self, do_parse!(
1618            lit: syn!(Lit) >>
1619            (ExprLit {
1620                attrs: Vec::new(),
1621                lit: lit,
1622            })
1623        ));
1624
1625        fn description() -> Option<&'static str> {
1626            Some("literal")
1627        }
1628    }
1629
1630    #[cfg(feature = "full")]
1631    impl Synom for ExprMacro {
1632        named!(parse -> Self, do_parse!(
1633            mac: syn!(Macro) >>
1634            (ExprMacro {
1635                attrs: Vec::new(),
1636                mac: mac,
1637            })
1638        ));
1639
1640        fn description() -> Option<&'static str> {
1641            Some("macro invocation expression")
1642        }
1643    }
1644
1645    #[cfg(feature = "full")]
1646    impl Synom for ExprGroup {
1647        named!(parse -> Self, do_parse!(
1648            e: grouped!(syn!(Expr)) >>
1649            (ExprGroup {
1650                attrs: Vec::new(),
1651                expr: Box::new(e.1),
1652                group_token: e.0,
1653            })
1654        ));
1655
1656        fn description() -> Option<&'static str> {
1657            Some("expression surrounded by invisible delimiters")
1658        }
1659    }
1660
1661    impl Synom for ExprParen {
1662        named!(parse -> Self, do_parse!(
1663            e: parens!(syn!(Expr)) >>
1664            (ExprParen {
1665                attrs: Vec::new(),
1666                paren_token: e.0,
1667                expr: Box::new(e.1),
1668            })
1669        ));
1670
1671        fn description() -> Option<&'static str> {
1672            Some("parenthesized expression")
1673        }
1674    }
1675
1676    #[cfg(feature = "full")]
1677    impl Synom for ExprArray {
1678        named!(parse -> Self, do_parse!(
1679            elems: brackets!(Punctuated::parse_terminated) >>
1680            (ExprArray {
1681                attrs: Vec::new(),
1682                bracket_token: elems.0,
1683                elems: elems.1,
1684            })
1685        ));
1686
1687        fn description() -> Option<&'static str> {
1688            Some("array expression")
1689        }
1690    }
1691
1692    named!(and_call -> (token::Paren, Punctuated<Expr, Token![,]>),
1693           parens!(Punctuated::parse_terminated));
1694
1695    #[cfg(feature = "full")]
1696    named!(and_method_call -> ExprMethodCall, do_parse!(
1697        dot: punct!(.) >>
1698        method: syn!(Ident) >>
1699        turbofish: option!(tuple!(
1700            punct!(::),
1701            punct!(<),
1702            call!(Punctuated::parse_terminated),
1703            punct!(>)
1704        )) >>
1705        args: parens!(Punctuated::parse_terminated) >>
1706        ({
1707            ExprMethodCall {
1708                attrs: Vec::new(),
1709                // this expr will get overwritten after being returned
1710                receiver: Box::new(Expr::Verbatim(ExprVerbatim {
1711                    tts: TokenStream::empty(),
1712                })),
1713
1714                method: method,
1715                turbofish: turbofish.map(|fish| MethodTurbofish {
1716                    colon2_token: fish.0,
1717                    lt_token: fish.1,
1718                    args: fish.2,
1719                    gt_token: fish.3,
1720                }),
1721                args: args.1,
1722                paren_token: args.0,
1723                dot_token: dot,
1724            }
1725        })
1726    ));
1727
1728    #[cfg(feature = "full")]
1729    impl Synom for GenericMethodArgument {
1730        // TODO parse const generics as well
1731        named!(parse -> Self, map!(ty_no_eq_after, GenericMethodArgument::Type));
1732
1733        fn description() -> Option<&'static str> {
1734            Some("generic method argument")
1735        }
1736    }
1737
1738    #[cfg(feature = "full")]
1739    impl Synom for ExprTuple {
1740        named!(parse -> Self, do_parse!(
1741            elems: parens!(Punctuated::parse_terminated) >>
1742            (ExprTuple {
1743                attrs: Vec::new(),
1744                elems: elems.1,
1745                paren_token: elems.0,
1746            })
1747        ));
1748
1749        fn description() -> Option<&'static str> {
1750            Some("tuple")
1751        }
1752    }
1753
1754    #[cfg(feature = "full")]
1755    impl Synom for ExprIfLet {
1756        named!(parse -> Self, do_parse!(
1757            if_: keyword!(if) >>
1758            let_: keyword!(let) >>
1759            pat: syn!(Pat) >>
1760            eq: punct!(=) >>
1761            cond: expr_no_struct >>
1762            then_block: braces!(Block::parse_within) >>
1763            else_block: option!(else_block) >>
1764            (ExprIfLet {
1765                attrs: Vec::new(),
1766                pat: Box::new(pat),
1767                let_token: let_,
1768                eq_token: eq,
1769                expr: Box::new(cond),
1770                then_branch: Block {
1771                    brace_token: then_block.0,
1772                    stmts: then_block.1,
1773                },
1774                if_token: if_,
1775                else_branch: else_block,
1776            })
1777        ));
1778
1779        fn description() -> Option<&'static str> {
1780            Some("`if let` expression")
1781        }
1782    }
1783
1784    #[cfg(feature = "full")]
1785    impl Synom for ExprIf {
1786        named!(parse -> Self, do_parse!(
1787            if_: keyword!(if) >>
1788            cond: expr_no_struct >>
1789            then_block: braces!(Block::parse_within) >>
1790            else_block: option!(else_block) >>
1791            (ExprIf {
1792                attrs: Vec::new(),
1793                cond: Box::new(cond),
1794                then_branch: Block {
1795                    brace_token: then_block.0,
1796                    stmts: then_block.1,
1797                },
1798                if_token: if_,
1799                else_branch: else_block,
1800            })
1801        ));
1802
1803        fn description() -> Option<&'static str> {
1804            Some("`if` expression")
1805        }
1806    }
1807
1808    #[cfg(feature = "full")]
1809    named!(else_block -> (Token![else], Box<Expr>), do_parse!(
1810        else_: keyword!(else) >>
1811        expr: alt!(
1812            syn!(ExprIf) => { Expr::If }
1813            |
1814            syn!(ExprIfLet) => { Expr::IfLet }
1815            |
1816            do_parse!(
1817                else_block: braces!(Block::parse_within) >>
1818                (Expr::Block(ExprBlock {
1819                    attrs: Vec::new(),
1820                    block: Block {
1821                        brace_token: else_block.0,
1822                        stmts: else_block.1,
1823                    },
1824                }))
1825            )
1826        ) >>
1827        (else_, Box::new(expr))
1828    ));
1829
1830    #[cfg(feature = "full")]
1831    impl Synom for ExprForLoop {
1832        named!(parse -> Self, do_parse!(
1833            label: option!(syn!(Label)) >>
1834            for_: keyword!(for) >>
1835            pat: syn!(Pat) >>
1836            in_: keyword!(in) >>
1837            expr: expr_no_struct >>
1838            loop_block: syn!(Block) >>
1839            (ExprForLoop {
1840                attrs: Vec::new(),
1841                for_token: for_,
1842                in_token: in_,
1843                pat: Box::new(pat),
1844                expr: Box::new(expr),
1845                body: loop_block,
1846                label: label,
1847            })
1848        ));
1849
1850        fn description() -> Option<&'static str> {
1851            Some("`for` loop")
1852        }
1853    }
1854
1855    #[cfg(feature = "full")]
1856    impl Synom for ExprLoop {
1857        named!(parse -> Self, do_parse!(
1858            label: option!(syn!(Label)) >>
1859            loop_: keyword!(loop) >>
1860            loop_block: syn!(Block) >>
1861            (ExprLoop {
1862                attrs: Vec::new(),
1863                loop_token: loop_,
1864                body: loop_block,
1865                label: label,
1866            })
1867        ));
1868
1869        fn description() -> Option<&'static str> {
1870            Some("`loop`")
1871        }
1872    }
1873
1874    #[cfg(feature = "full")]
1875    impl Synom for ExprMatch {
1876        named!(parse -> Self, do_parse!(
1877            match_: keyword!(match) >>
1878            obj: expr_no_struct >>
1879            res: braces!(many0!(Arm::parse)) >>
1880            (ExprMatch {
1881                attrs: Vec::new(),
1882                expr: Box::new(obj),
1883                match_token: match_,
1884                brace_token: res.0,
1885                arms: res.1,
1886            })
1887        ));
1888
1889        fn description() -> Option<&'static str> {
1890            Some("`match` expression")
1891        }
1892    }
1893
1894    #[cfg(feature = "full")]
1895    impl Synom for ExprCatch {
1896        named!(parse -> Self, do_parse!(
1897            do_: keyword!(do) >>
1898            catch_: keyword!(catch) >>
1899            catch_block: syn!(Block) >>
1900            (ExprCatch {
1901                attrs: Vec::new(),
1902                block: catch_block,
1903                do_token: do_,
1904                catch_token: catch_,
1905            })
1906        ));
1907
1908        fn description() -> Option<&'static str> {
1909            Some("`catch` expression")
1910        }
1911    }
1912
1913    #[cfg(feature = "full")]
1914    impl Synom for ExprYield {
1915        named!(parse -> Self, do_parse!(
1916            yield_: keyword!(yield) >>
1917            expr: option!(syn!(Expr)) >>
1918            (ExprYield {
1919                attrs: Vec::new(),
1920                yield_token: yield_,
1921                expr: expr.map(Box::new),
1922            })
1923        ));
1924
1925        fn description() -> Option<&'static str> {
1926            Some("`yield` expression")
1927        }
1928    }
1929
1930    #[cfg(feature = "full")]
1931    impl Synom for Arm {
1932        named!(parse -> Self, do_parse!(
1933            attrs: many0!(Attribute::parse_outer) >>
1934            pats: call!(Punctuated::parse_separated_nonempty) >>
1935            guard: option!(tuple!(keyword!(if), syn!(Expr))) >>
1936            rocket: punct!(=>) >>
1937            body: do_parse!(
1938                expr: alt!(expr_nosemi | syn!(Expr)) >>
1939                comma: switch!(value!(arm_expr_requires_comma(&expr)),
1940                    true => alt!(
1941                        input_end!() => { |_| None }
1942                        |
1943                        punct!(,) => { Some }
1944                    )
1945                    |
1946                    false => option!(punct!(,))
1947                ) >>
1948                (expr, comma)
1949            ) >>
1950            (Arm {
1951                rocket_token: rocket,
1952                attrs: attrs,
1953                pats: pats,
1954                guard: guard.map(|(if_, guard)| (if_, Box::new(guard))),
1955                body: Box::new(body.0),
1956                comma: body.1,
1957            })
1958        ));
1959
1960        fn description() -> Option<&'static str> {
1961            Some("`match` arm")
1962        }
1963    }
1964
1965    #[cfg(feature = "full")]
1966    named!(expr_closure(allow_struct: bool) -> Expr, do_parse!(
1967        capture: option!(keyword!(move)) >>
1968        or1: punct!(|) >>
1969        inputs: call!(Punctuated::parse_terminated_with, fn_arg) >>
1970        or2: punct!(|) >>
1971        ret_and_body: alt!(
1972            do_parse!(
1973                arrow: punct!(->) >>
1974                ty: syn!(Type) >>
1975                body: syn!(Block) >>
1976                (ReturnType::Type(arrow, Box::new(ty)),
1977                 Expr::Block(ExprBlock {
1978                     attrs: Vec::new(),
1979                    block: body,
1980                }))
1981            )
1982            |
1983            map!(ambiguous_expr!(allow_struct), |e| (ReturnType::Default, e))
1984        ) >>
1985        (ExprClosure {
1986            attrs: Vec::new(),
1987            capture: capture,
1988            or1_token: or1,
1989            inputs: inputs,
1990            or2_token: or2,
1991            output: ret_and_body.0,
1992            body: Box::new(ret_and_body.1),
1993        }.into())
1994    ));
1995
1996    #[cfg(feature = "full")]
1997    named!(fn_arg -> FnArg, do_parse!(
1998        pat: syn!(Pat) >>
1999        ty: option!(tuple!(punct!(:), syn!(Type))) >>
2000        ({
2001            if let Some((colon, ty)) = ty {
2002                FnArg::Captured(ArgCaptured {
2003                    pat: pat,
2004                    colon_token: colon,
2005                    ty: ty,
2006                })
2007            } else {
2008                FnArg::Inferred(pat)
2009            }
2010        })
2011    ));
2012
2013    #[cfg(feature = "full")]
2014    impl Synom for ExprWhile {
2015        named!(parse -> Self, do_parse!(
2016            label: option!(syn!(Label)) >>
2017            while_: keyword!(while) >>
2018            cond: expr_no_struct >>
2019            while_block: syn!(Block) >>
2020            (ExprWhile {
2021                attrs: Vec::new(),
2022                while_token: while_,
2023                cond: Box::new(cond),
2024                body: while_block,
2025                label: label,
2026            })
2027        ));
2028
2029        fn description() -> Option<&'static str> {
2030            Some("`while` expression")
2031        }
2032    }
2033
2034    #[cfg(feature = "full")]
2035    impl Synom for ExprWhileLet {
2036        named!(parse -> Self, do_parse!(
2037            label: option!(syn!(Label)) >>
2038            while_: keyword!(while) >>
2039            let_: keyword!(let) >>
2040            pat: syn!(Pat) >>
2041            eq: punct!(=) >>
2042            value: expr_no_struct >>
2043            while_block: syn!(Block) >>
2044            (ExprWhileLet {
2045                attrs: Vec::new(),
2046                eq_token: eq,
2047                let_token: let_,
2048                while_token: while_,
2049                pat: Box::new(pat),
2050                expr: Box::new(value),
2051                body: while_block,
2052                label: label,
2053            })
2054        ));
2055
2056        fn description() -> Option<&'static str> {
2057            Some("`while let` expression")
2058        }
2059    }
2060
2061    #[cfg(feature = "full")]
2062    impl Synom for Label {
2063        named!(parse -> Self, do_parse!(
2064            name: syn!(Lifetime) >>
2065            colon: punct!(:) >>
2066            (Label {
2067                name: name,
2068                colon_token: colon,
2069            })
2070        ));
2071
2072        fn description() -> Option<&'static str> {
2073            Some("`while let` expression")
2074        }
2075    }
2076
2077    #[cfg(feature = "full")]
2078    impl Synom for ExprContinue {
2079        named!(parse -> Self, do_parse!(
2080            cont: keyword!(continue) >>
2081            label: option!(syn!(Lifetime)) >>
2082            (ExprContinue {
2083                attrs: Vec::new(),
2084                continue_token: cont,
2085                label: label,
2086            })
2087        ));
2088
2089        fn description() -> Option<&'static str> {
2090            Some("`continue`")
2091        }
2092    }
2093
2094    #[cfg(feature = "full")]
2095    named!(expr_break(allow_struct: bool) -> Expr, do_parse!(
2096        break_: keyword!(break) >>
2097        label: option!(syn!(Lifetime)) >>
2098        // We can't allow blocks after a `break` expression when we wouldn't
2099        // allow structs, as this expression is ambiguous.
2100        val: opt_ambiguous_expr!(allow_struct) >>
2101        (ExprBreak {
2102            attrs: Vec::new(),
2103            label: label,
2104            expr: val.map(Box::new),
2105            break_token: break_,
2106        }.into())
2107    ));
2108
2109    #[cfg(feature = "full")]
2110    named!(expr_ret(allow_struct: bool) -> Expr, do_parse!(
2111        return_: keyword!(return) >>
2112        // NOTE: return is greedy and eats blocks after it even when in a
2113        // position where structs are not allowed, such as in if statement
2114        // conditions. For example:
2115        //
2116        // if return { println!("A") } {} // Prints "A"
2117        ret_value: option!(ambiguous_expr!(allow_struct)) >>
2118        (ExprReturn {
2119            attrs: Vec::new(),
2120            expr: ret_value.map(Box::new),
2121            return_token: return_,
2122        }.into())
2123    ));
2124
2125    #[cfg(feature = "full")]
2126    impl Synom for ExprStruct {
2127        named!(parse -> Self, do_parse!(
2128            path: syn!(Path) >>
2129            data: braces!(do_parse!(
2130                fields: call!(Punctuated::parse_terminated) >>
2131                base: option!(cond!(fields.empty_or_trailing(), do_parse!(
2132                    dots: punct!(..) >>
2133                    base: syn!(Expr) >>
2134                    (dots, base)
2135                ))) >>
2136                (fields, base)
2137            )) >>
2138            ({
2139                let (brace, (fields, base)) = data;
2140                let (dots, rest) = match base.and_then(|b| b) {
2141                    Some((dots, base)) => (Some(dots), Some(base)),
2142                    None => (None, None),
2143                };
2144                ExprStruct {
2145                    attrs: Vec::new(),
2146                    brace_token: brace,
2147                    path: path,
2148                    fields: fields,
2149                    dot2_token: dots,
2150                    rest: rest.map(Box::new),
2151                }
2152            })
2153        ));
2154
2155        fn description() -> Option<&'static str> {
2156            Some("struct literal expression")
2157        }
2158    }
2159
2160    #[cfg(feature = "full")]
2161    impl Synom for FieldValue {
2162        named!(parse -> Self, do_parse!(
2163            attrs: many0!(Attribute::parse_outer) >>
2164            field_value: alt!(
2165                tuple!(syn!(Member), map!(punct!(:), Some), syn!(Expr))
2166                |
2167                map!(syn!(Ident), |name| (
2168                    Member::Named(name),
2169                    None,
2170                    Expr::Path(ExprPath {
2171                        attrs: Vec::new(),
2172                        qself: None,
2173                        path: name.into(),
2174                    }),
2175                ))
2176            ) >>
2177            (FieldValue {
2178                attrs: attrs,
2179                member: field_value.0,
2180                colon_token: field_value.1,
2181                expr: field_value.2,
2182            })
2183        ));
2184
2185        fn description() -> Option<&'static str> {
2186            Some("field-value pair: `field: value`")
2187        }
2188    }
2189
2190    #[cfg(feature = "full")]
2191    impl Synom for ExprRepeat {
2192        named!(parse -> Self, do_parse!(
2193            data: brackets!(do_parse!(
2194                value: syn!(Expr) >>
2195                semi: punct!(;) >>
2196                times: syn!(Expr) >>
2197                (value, semi, times)
2198            )) >>
2199            (ExprRepeat {
2200                attrs: Vec::new(),
2201                expr: Box::new((data.1).0),
2202                len: Box::new((data.1).2),
2203                bracket_token: data.0,
2204                semi_token: (data.1).1,
2205            })
2206        ));
2207
2208        fn description() -> Option<&'static str> {
2209            Some("repeated array literal: `[val; N]`")
2210        }
2211    }
2212
2213    #[cfg(feature = "full")]
2214    impl Synom for ExprUnsafe {
2215        named!(parse -> Self, do_parse!(
2216            unsafe_: keyword!(unsafe) >>
2217            b: syn!(Block) >>
2218            (ExprUnsafe {
2219                attrs: Vec::new(),
2220                unsafe_token: unsafe_,
2221                block: b,
2222            })
2223        ));
2224
2225        fn description() -> Option<&'static str> {
2226            Some("unsafe block: `unsafe { .. }`")
2227        }
2228    }
2229
2230    #[cfg(feature = "full")]
2231    impl Synom for ExprBlock {
2232        named!(parse -> Self, do_parse!(
2233            b: syn!(Block) >>
2234            (ExprBlock {
2235                attrs: Vec::new(),
2236                block: b,
2237            })
2238        ));
2239
2240        fn description() -> Option<&'static str> {
2241            Some("block: `{ .. }`")
2242        }
2243    }
2244
2245    #[cfg(feature = "full")]
2246    named!(expr_range(allow_struct: bool) -> Expr, do_parse!(
2247        limits: syn!(RangeLimits) >>
2248        hi: opt_ambiguous_expr!(allow_struct) >>
2249        (ExprRange {
2250            attrs: Vec::new(),
2251            from: None,
2252            to: hi.map(Box::new),
2253            limits: limits,
2254        }.into())
2255    ));
2256
2257    #[cfg(feature = "full")]
2258    impl Synom for RangeLimits {
2259        named!(parse -> Self, alt!(
2260            // Must come before Dot2
2261            punct!(..=) => { RangeLimits::Closed }
2262            |
2263            // Must come before Dot2
2264            punct!(...) => { |dot3| RangeLimits::Closed(Token![..=](dot3.0)) }
2265            |
2266            punct!(..) => { RangeLimits::HalfOpen }
2267        ));
2268
2269        fn description() -> Option<&'static str> {
2270            Some("range limit: `..`, `...` or `..=`")
2271        }
2272    }
2273
2274    impl Synom for ExprPath {
2275        named!(parse -> Self, do_parse!(
2276            pair: qpath >>
2277            (ExprPath {
2278                attrs: Vec::new(),
2279                qself: pair.0,
2280                path: pair.1,
2281            })
2282        ));
2283
2284        fn description() -> Option<&'static str> {
2285            Some("path: `a::b::c`")
2286        }
2287    }
2288
2289    #[cfg(feature = "full")]
2290    named!(and_field -> (Token![.], Member), tuple!(punct!(.), syn!(Member)));
2291
2292    named!(and_index -> (token::Bracket, Expr), brackets!(syn!(Expr)));
2293
2294    #[cfg(feature = "full")]
2295    impl Synom for Block {
2296        named!(parse -> Self, do_parse!(
2297            stmts: braces!(Block::parse_within) >>
2298            (Block {
2299                brace_token: stmts.0,
2300                stmts: stmts.1,
2301            })
2302        ));
2303
2304        fn description() -> Option<&'static str> {
2305            Some("block: `{ .. }`")
2306        }
2307    }
2308
2309    #[cfg(feature = "full")]
2310    impl Block {
2311        named!(pub parse_within -> Vec<Stmt>, do_parse!(
2312            many0!(punct!(;)) >>
2313            mut standalone: many0!(do_parse!(
2314                stmt: syn!(Stmt) >>
2315                many0!(punct!(;)) >>
2316                (stmt)
2317            )) >>
2318            last: option!(do_parse!(
2319                attrs: many0!(Attribute::parse_outer) >>
2320                mut e: syn!(Expr) >>
2321                ({
2322                    e.replace_attrs(attrs);
2323                    Stmt::Expr(e)
2324                })
2325            )) >>
2326            (match last {
2327                None => standalone,
2328                Some(last) => {
2329                    standalone.push(last);
2330                    standalone
2331                }
2332            })
2333        ));
2334    }
2335
2336    #[cfg(feature = "full")]
2337    impl Synom for Stmt {
2338        named!(parse -> Self, alt!(
2339            stmt_mac
2340            |
2341            stmt_local
2342            |
2343            stmt_item
2344            |
2345            stmt_blockexpr
2346            |
2347            stmt_expr
2348        ));
2349
2350        fn description() -> Option<&'static str> {
2351            Some("statement")
2352        }
2353    }
2354
2355    #[cfg(feature = "full")]
2356    named!(stmt_mac -> Stmt, do_parse!(
2357        attrs: many0!(Attribute::parse_outer) >>
2358        what: call!(Path::parse_mod_style) >>
2359        bang: punct!(!) >>
2360    // Only parse braces here; paren and bracket will get parsed as
2361    // expression statements
2362        data: braces!(syn!(TokenStream)) >>
2363        semi: option!(punct!(;)) >>
2364        (Stmt::Item(Item::Macro(ItemMacro {
2365            attrs: attrs,
2366            ident: None,
2367            mac: Macro {
2368                path: what,
2369                bang_token: bang,
2370                delimiter: MacroDelimiter::Brace(data.0),
2371                tts: data.1,
2372            },
2373            semi_token: semi,
2374        })))
2375    ));
2376
2377    #[cfg(feature = "full")]
2378    named!(stmt_local -> Stmt, do_parse!(
2379        attrs: many0!(Attribute::parse_outer) >>
2380        let_: keyword!(let) >>
2381        pat: syn!(Pat) >>
2382        ty: option!(tuple!(punct!(:), syn!(Type))) >>
2383        init: option!(tuple!(punct!(=), syn!(Expr))) >>
2384        semi: punct!(;) >>
2385        (Stmt::Local(Local {
2386            attrs: attrs,
2387            let_token: let_,
2388            pat: Box::new(pat),
2389            ty: ty.map(|(colon, ty)| (colon, Box::new(ty))),
2390            init: init.map(|(eq, expr)| (eq, Box::new(expr))),
2391            semi_token: semi,
2392        }))
2393    ));
2394
2395    #[cfg(feature = "full")]
2396    named!(stmt_item -> Stmt, map!(syn!(Item), |i| Stmt::Item(i)));
2397
2398    #[cfg(feature = "full")]
2399    named!(stmt_blockexpr -> Stmt, do_parse!(
2400        attrs: many0!(Attribute::parse_outer) >>
2401        mut e: expr_nosemi >>
2402        // If the next token is a `.` or a `?` it is special-cased to parse as
2403        // an expression instead of a blockexpression.
2404        not!(punct!(.)) >>
2405        not!(punct!(?)) >>
2406        semi: option!(punct!(;)) >>
2407        ({
2408            e.replace_attrs(attrs);
2409            if let Some(semi) = semi {
2410                Stmt::Semi(e, semi)
2411            } else {
2412                Stmt::Expr(e)
2413            }
2414        })
2415    ));
2416
2417    #[cfg(feature = "full")]
2418    named!(stmt_expr -> Stmt, do_parse!(
2419        attrs: many0!(Attribute::parse_outer) >>
2420        mut e: syn!(Expr) >>
2421        semi: punct!(;) >>
2422        ({
2423            e.replace_attrs(attrs);
2424            Stmt::Semi(e, semi)
2425        })
2426    ));
2427
2428    #[cfg(feature = "full")]
2429    impl Synom for Pat {
2430        named!(parse -> Self, alt!(
2431            syn!(PatWild) => { Pat::Wild } // must be before pat_ident
2432            |
2433            syn!(PatBox) => { Pat::Box }  // must be before pat_ident
2434            |
2435            syn!(PatRange) => { Pat::Range } // must be before pat_lit
2436            |
2437            syn!(PatTupleStruct) => { Pat::TupleStruct }  // must be before pat_ident
2438            |
2439            syn!(PatStruct) => { Pat::Struct } // must be before pat_ident
2440            |
2441            syn!(PatMacro) => { Pat::Macro } // must be before pat_ident
2442            |
2443            syn!(PatLit) => { Pat::Lit } // must be before pat_ident
2444            |
2445            syn!(PatIdent) => { Pat::Ident } // must be before pat_path
2446            |
2447            syn!(PatPath) => { Pat::Path }
2448            |
2449            syn!(PatTuple) => { Pat::Tuple }
2450            |
2451            syn!(PatRef) => { Pat::Ref }
2452            |
2453            syn!(PatSlice) => { Pat::Slice }
2454        ));
2455
2456        fn description() -> Option<&'static str> {
2457            Some("pattern")
2458        }
2459    }
2460
2461    #[cfg(feature = "full")]
2462    impl Synom for PatWild {
2463        named!(parse -> Self, map!(
2464            punct!(_),
2465            |u| PatWild { underscore_token: u }
2466        ));
2467
2468        fn description() -> Option<&'static str> {
2469            Some("wild pattern: `_`")
2470        }
2471    }
2472
2473    #[cfg(feature = "full")]
2474    impl Synom for PatBox {
2475        named!(parse -> Self, do_parse!(
2476            boxed: keyword!(box) >>
2477            pat: syn!(Pat) >>
2478            (PatBox {
2479                pat: Box::new(pat),
2480                box_token: boxed,
2481            })
2482        ));
2483
2484        fn description() -> Option<&'static str> {
2485            Some("box pattern")
2486        }
2487    }
2488
2489    #[cfg(feature = "full")]
2490    impl Synom for PatIdent {
2491        named!(parse -> Self, do_parse!(
2492            by_ref: option!(keyword!(ref)) >>
2493            mutability: option!(keyword!(mut)) >>
2494            name: alt!(
2495                syn!(Ident)
2496                |
2497                keyword!(self) => { Into::into }
2498            ) >>
2499            not!(punct!(<)) >>
2500            not!(punct!(::)) >>
2501            subpat: option!(tuple!(punct!(@), syn!(Pat))) >>
2502            (PatIdent {
2503                by_ref: by_ref,
2504                mutability: mutability,
2505                ident: name,
2506                subpat: subpat.map(|(at, pat)| (at, Box::new(pat))),
2507            })
2508        ));
2509
2510        fn description() -> Option<&'static str> {
2511            Some("pattern identifier binding")
2512        }
2513    }
2514
2515    #[cfg(feature = "full")]
2516    impl Synom for PatTupleStruct {
2517        named!(parse -> Self, do_parse!(
2518            path: syn!(Path) >>
2519            tuple: syn!(PatTuple) >>
2520            (PatTupleStruct {
2521                path: path,
2522                pat: tuple,
2523            })
2524        ));
2525
2526        fn description() -> Option<&'static str> {
2527            Some("tuple struct pattern")
2528        }
2529    }
2530
2531    #[cfg(feature = "full")]
2532    impl Synom for PatStruct {
2533        named!(parse -> Self, do_parse!(
2534            path: syn!(Path) >>
2535            data: braces!(do_parse!(
2536                fields: call!(Punctuated::parse_terminated) >>
2537                base: option!(cond!(fields.empty_or_trailing(), punct!(..))) >>
2538                (fields, base)
2539            )) >>
2540            (PatStruct {
2541                path: path,
2542                fields: (data.1).0,
2543                brace_token: data.0,
2544                dot2_token: (data.1).1.and_then(|m| m),
2545            })
2546        ));
2547
2548        fn description() -> Option<&'static str> {
2549            Some("struct pattern")
2550        }
2551    }
2552
2553    #[cfg(feature = "full")]
2554    impl Synom for FieldPat {
2555        named!(parse -> Self, alt!(
2556            do_parse!(
2557                member: syn!(Member) >>
2558                colon: punct!(:) >>
2559                pat: syn!(Pat) >>
2560                (FieldPat {
2561                    member: member,
2562                    pat: Box::new(pat),
2563                    attrs: Vec::new(),
2564                    colon_token: Some(colon),
2565                })
2566            )
2567            |
2568            do_parse!(
2569                boxed: option!(keyword!(box)) >>
2570                by_ref: option!(keyword!(ref)) >>
2571                mutability: option!(keyword!(mut)) >>
2572                ident: syn!(Ident) >>
2573                ({
2574                    let mut pat: Pat = PatIdent {
2575                        by_ref: by_ref,
2576                        mutability: mutability,
2577                        ident: ident,
2578                        subpat: None,
2579                    }.into();
2580                    if let Some(boxed) = boxed {
2581                        pat = PatBox {
2582                            pat: Box::new(pat),
2583                            box_token: boxed,
2584                        }.into();
2585                    }
2586                    FieldPat {
2587                        member: Member::Named(ident),
2588                        pat: Box::new(pat),
2589                        attrs: Vec::new(),
2590                        colon_token: None,
2591                    }
2592                })
2593            )
2594        ));
2595
2596        fn description() -> Option<&'static str> {
2597            Some("field pattern")
2598        }
2599    }
2600
2601    #[cfg(feature = "full")]
2602    impl Synom for Member {
2603        named!(parse -> Self, alt!(
2604            syn!(Ident) => { Member::Named }
2605            |
2606            syn!(Index) => { Member::Unnamed }
2607        ));
2608
2609        fn description() -> Option<&'static str> {
2610            Some("field member")
2611        }
2612    }
2613
2614    #[cfg(feature = "full")]
2615    impl Synom for Index {
2616        named!(parse -> Self, do_parse!(
2617            lit: syn!(LitInt) >>
2618            ({
2619                if let IntSuffix::None = lit.suffix() {
2620                    Index { index: lit.value() as u32, span: lit.span }
2621                } else {
2622                    return parse_error();
2623                }
2624            })
2625        ));
2626
2627        fn description() -> Option<&'static str> {
2628            Some("field index")
2629        }
2630    }
2631
2632    #[cfg(feature = "full")]
2633    impl Synom for PatPath {
2634        named!(parse -> Self, map!(
2635            syn!(ExprPath),
2636            |p| PatPath { qself: p.qself, path: p.path }
2637        ));
2638
2639        fn description() -> Option<&'static str> {
2640            Some("path pattern")
2641        }
2642    }
2643
2644    #[cfg(feature = "full")]
2645    impl Synom for PatTuple {
2646        named!(parse -> Self, do_parse!(
2647            data: parens!(do_parse!(
2648                front: call!(Punctuated::parse_terminated) >>
2649                dotdot: option!(cond_reduce!(front.empty_or_trailing(),
2650                    tuple!(punct!(..), option!(punct!(,)))
2651                )) >>
2652                back: cond!(match dotdot {
2653                                Some((_, Some(_))) => true,
2654                                _ => false,
2655                            },
2656                            Punctuated::parse_terminated) >>
2657                (front, dotdot, back)
2658            )) >>
2659            ({
2660                let (parens, (front, dotdot, back)) = data;
2661                let (dotdot, trailing) = match dotdot {
2662                    Some((a, b)) => (Some(a), Some(b)),
2663                    None => (None, None),
2664                };
2665                PatTuple {
2666                    paren_token: parens,
2667                    front: front,
2668                    dot2_token: dotdot,
2669                    comma_token: trailing.unwrap_or_default(),
2670                    back: back.unwrap_or_default(),
2671                }
2672            })
2673        ));
2674
2675        fn description() -> Option<&'static str> {
2676            Some("tuple pattern")
2677        }
2678    }
2679
2680    #[cfg(feature = "full")]
2681    impl Synom for PatRef {
2682        named!(parse -> Self, do_parse!(
2683            and: punct!(&) >>
2684            mutability: option!(keyword!(mut)) >>
2685            pat: syn!(Pat) >>
2686            (PatRef {
2687                pat: Box::new(pat),
2688                mutability: mutability,
2689                and_token: and,
2690            })
2691        ));
2692
2693        fn description() -> Option<&'static str> {
2694            Some("reference pattern")
2695        }
2696    }
2697
2698    #[cfg(feature = "full")]
2699    impl Synom for PatLit {
2700        named!(parse -> Self, do_parse!(
2701            lit: pat_lit_expr >>
2702            (if let Expr::Path(_) = lit {
2703                return parse_error(); // these need to be parsed by pat_path
2704            } else {
2705                PatLit {
2706                    expr: Box::new(lit),
2707                }
2708            })
2709        ));
2710
2711        fn description() -> Option<&'static str> {
2712            Some("literal pattern")
2713        }
2714    }
2715
2716    #[cfg(feature = "full")]
2717    impl Synom for PatRange {
2718        named!(parse -> Self, do_parse!(
2719            lo: pat_lit_expr >>
2720            limits: syn!(RangeLimits) >>
2721            hi: pat_lit_expr >>
2722            (PatRange {
2723                lo: Box::new(lo),
2724                hi: Box::new(hi),
2725                limits: limits,
2726            })
2727        ));
2728
2729        fn description() -> Option<&'static str> {
2730            Some("range pattern")
2731        }
2732    }
2733
2734    #[cfg(feature = "full")]
2735    named!(pat_lit_expr -> Expr, do_parse!(
2736        neg: option!(punct!(-)) >>
2737        v: alt!(
2738            syn!(ExprLit) => { Expr::Lit }
2739            |
2740            syn!(ExprPath) => { Expr::Path }
2741        ) >>
2742        (if let Some(neg) = neg {
2743            Expr::Unary(ExprUnary {
2744                attrs: Vec::new(),
2745                op: UnOp::Neg(neg),
2746                expr: Box::new(v)
2747            })
2748        } else {
2749            v
2750        })
2751    ));
2752
2753    #[cfg(feature = "full")]
2754    impl Synom for PatSlice {
2755        named!(parse -> Self, map!(
2756            brackets!(do_parse!(
2757                before: call!(Punctuated::parse_terminated) >>
2758                middle: option!(do_parse!(
2759                    dots: punct!(..) >>
2760                    trailing: option!(punct!(,)) >>
2761                    (dots, trailing)
2762                )) >>
2763                after: cond!(
2764                    match middle {
2765                        Some((_, ref trailing)) => trailing.is_some(),
2766                        _ => false,
2767                    },
2768                    Punctuated::parse_terminated
2769                ) >>
2770                (before, middle, after)
2771            )),
2772            |(brackets, (before, middle, after))| {
2773                let mut before: Punctuated<Pat, Token![,]> = before;
2774                let after: Option<Punctuated<Pat, Token![,]>> = after;
2775                let middle: Option<(Token![..], Option<Token![,]>)> = middle;
2776                PatSlice {
2777                    dot2_token: middle.as_ref().map(|m| Token![..]((m.0).0)),
2778                    comma_token: middle.as_ref().and_then(|m| {
2779                        m.1.as_ref().map(|m| Token![,](m.0))
2780                    }),
2781                    bracket_token: brackets,
2782                    middle: middle.and_then(|_| {
2783                        if before.empty_or_trailing() {
2784                            None
2785                        } else {
2786                            Some(Box::new(before.pop().unwrap().into_value()))
2787                        }
2788                    }),
2789                    front: before,
2790                    back: after.unwrap_or_default(),
2791                }
2792            }
2793        ));
2794
2795        fn description() -> Option<&'static str> {
2796            Some("slice pattern")
2797        }
2798    }
2799
2800    #[cfg(feature = "full")]
2801    impl Synom for PatMacro {
2802        named!(parse -> Self, map!(syn!(Macro), |mac| PatMacro { mac: mac }));
2803
2804        fn description() -> Option<&'static str> {
2805            Some("macro pattern")
2806        }
2807    }
2808}
2809
2810#[cfg(feature = "printing")]
2811mod printing {
2812    use super::*;
2813    #[cfg(feature = "full")]
2814    use attr::FilterAttrs;
2815    use quote::{ToTokens, Tokens};
2816    use proc_macro2::{Literal, TokenNode, TokenTree};
2817
2818    // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
2819    // before appending it to `Tokens`.
2820    #[cfg(feature = "full")]
2821    fn wrap_bare_struct(tokens: &mut Tokens, e: &Expr) {
2822        if let Expr::Struct(_) = *e {
2823            token::Paren::default().surround(tokens, |tokens| {
2824                e.to_tokens(tokens);
2825            });
2826        } else {
2827            e.to_tokens(tokens);
2828        }
2829    }
2830
2831    #[cfg(feature = "full")]
2832    fn attrs_to_tokens(attrs: &[Attribute], tokens: &mut Tokens) {
2833        tokens.append_all(attrs.outer());
2834    }
2835
2836    #[cfg(not(feature = "full"))]
2837    fn attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut Tokens) {}
2838
2839    #[cfg(feature = "full")]
2840    impl ToTokens for ExprBox {
2841        fn to_tokens(&self, tokens: &mut Tokens) {
2842            tokens.append_all(self.attrs.outer());
2843            self.box_token.to_tokens(tokens);
2844            self.expr.to_tokens(tokens);
2845        }
2846    }
2847
2848    #[cfg(feature = "full")]
2849    impl ToTokens for ExprInPlace {
2850        fn to_tokens(&self, tokens: &mut Tokens) {
2851            tokens.append_all(self.attrs.outer());
2852            self.place.to_tokens(tokens);
2853            self.arrow_token.to_tokens(tokens);
2854            self.value.to_tokens(tokens);
2855        }
2856    }
2857
2858    #[cfg(feature = "full")]
2859    impl ToTokens for ExprArray {
2860        fn to_tokens(&self, tokens: &mut Tokens) {
2861            tokens.append_all(self.attrs.outer());
2862            self.bracket_token.surround(tokens, |tokens| {
2863                self.elems.to_tokens(tokens);
2864            })
2865        }
2866    }
2867
2868    impl ToTokens for ExprCall {
2869        fn to_tokens(&self, tokens: &mut Tokens) {
2870            attrs_to_tokens(&self.attrs, tokens);
2871            self.func.to_tokens(tokens);
2872            self.paren_token.surround(tokens, |tokens| {
2873                self.args.to_tokens(tokens);
2874            })
2875        }
2876    }
2877
2878    #[cfg(feature = "full")]
2879    impl ToTokens for ExprMethodCall {
2880        fn to_tokens(&self, tokens: &mut Tokens) {
2881            tokens.append_all(self.attrs.outer());
2882            self.receiver.to_tokens(tokens);
2883            self.dot_token.to_tokens(tokens);
2884            self.method.to_tokens(tokens);
2885            self.turbofish.to_tokens(tokens);
2886            self.paren_token.surround(tokens, |tokens| {
2887                self.args.to_tokens(tokens);
2888            });
2889        }
2890    }
2891
2892    #[cfg(feature = "full")]
2893    impl ToTokens for MethodTurbofish {
2894        fn to_tokens(&self, tokens: &mut Tokens) {
2895            self.colon2_token.to_tokens(tokens);
2896            self.lt_token.to_tokens(tokens);
2897            self.args.to_tokens(tokens);
2898            self.gt_token.to_tokens(tokens);
2899        }
2900    }
2901
2902    #[cfg(feature = "full")]
2903    impl ToTokens for GenericMethodArgument {
2904        fn to_tokens(&self, tokens: &mut Tokens) {
2905            match *self {
2906                GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
2907                GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
2908            }
2909        }
2910    }
2911
2912    #[cfg(feature = "full")]
2913    impl ToTokens for ExprTuple {
2914        fn to_tokens(&self, tokens: &mut Tokens) {
2915            tokens.append_all(self.attrs.outer());
2916            self.paren_token.surround(tokens, |tokens| {
2917                self.elems.to_tokens(tokens);
2918                // If we only have one argument, we need a trailing comma to
2919                // distinguish ExprTuple from ExprParen.
2920                if self.elems.len() == 1 && !self.elems.trailing_punct() {
2921                    <Token![,]>::default().to_tokens(tokens);
2922                }
2923            })
2924        }
2925    }
2926
2927    impl ToTokens for ExprBinary {
2928        fn to_tokens(&self, tokens: &mut Tokens) {
2929            attrs_to_tokens(&self.attrs, tokens);
2930            self.left.to_tokens(tokens);
2931            self.op.to_tokens(tokens);
2932            self.right.to_tokens(tokens);
2933        }
2934    }
2935
2936    impl ToTokens for ExprUnary {
2937        fn to_tokens(&self, tokens: &mut Tokens) {
2938            attrs_to_tokens(&self.attrs, tokens);
2939            self.op.to_tokens(tokens);
2940            self.expr.to_tokens(tokens);
2941        }
2942    }
2943
2944    impl ToTokens for ExprLit {
2945        fn to_tokens(&self, tokens: &mut Tokens) {
2946            attrs_to_tokens(&self.attrs, tokens);
2947            self.lit.to_tokens(tokens);
2948        }
2949    }
2950
2951    impl ToTokens for ExprCast {
2952        fn to_tokens(&self, tokens: &mut Tokens) {
2953            attrs_to_tokens(&self.attrs, tokens);
2954            self.expr.to_tokens(tokens);
2955            self.as_token.to_tokens(tokens);
2956            self.ty.to_tokens(tokens);
2957        }
2958    }
2959
2960    #[cfg(feature = "full")]
2961    impl ToTokens for ExprType {
2962        fn to_tokens(&self, tokens: &mut Tokens) {
2963            attrs_to_tokens(&self.attrs, tokens);
2964            self.expr.to_tokens(tokens);
2965            self.colon_token.to_tokens(tokens);
2966            self.ty.to_tokens(tokens);
2967        }
2968    }
2969
2970    #[cfg(feature = "full")]
2971    fn maybe_wrap_else(tokens: &mut Tokens, else_: &Option<(Token![else], Box<Expr>)>) {
2972        if let Some((ref else_token, ref else_)) = *else_ {
2973            else_token.to_tokens(tokens);
2974
2975            // If we are not one of the valid expressions to exist in an else
2976            // clause, wrap ourselves in a block.
2977            match **else_ {
2978                Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
2979                    else_.to_tokens(tokens);
2980                }
2981                _ => {
2982                    token::Brace::default().surround(tokens, |tokens| {
2983                        else_.to_tokens(tokens);
2984                    });
2985                }
2986            }
2987        }
2988    }
2989
2990    #[cfg(feature = "full")]
2991    impl ToTokens for ExprIf {
2992        fn to_tokens(&self, tokens: &mut Tokens) {
2993            tokens.append_all(self.attrs.outer());
2994            self.if_token.to_tokens(tokens);
2995            wrap_bare_struct(tokens, &self.cond);
2996            self.then_branch.to_tokens(tokens);
2997            maybe_wrap_else(tokens, &self.else_branch);
2998        }
2999    }
3000
3001    #[cfg(feature = "full")]
3002    impl ToTokens for ExprIfLet {
3003        fn to_tokens(&self, tokens: &mut Tokens) {
3004            tokens.append_all(self.attrs.outer());
3005            self.if_token.to_tokens(tokens);
3006            self.let_token.to_tokens(tokens);
3007            self.pat.to_tokens(tokens);
3008            self.eq_token.to_tokens(tokens);
3009            wrap_bare_struct(tokens, &self.expr);
3010            self.then_branch.to_tokens(tokens);
3011            maybe_wrap_else(tokens, &self.else_branch);
3012        }
3013    }
3014
3015    #[cfg(feature = "full")]
3016    impl ToTokens for ExprWhile {
3017        fn to_tokens(&self, tokens: &mut Tokens) {
3018            tokens.append_all(self.attrs.outer());
3019            self.label.to_tokens(tokens);
3020            self.while_token.to_tokens(tokens);
3021            wrap_bare_struct(tokens, &self.cond);
3022            self.body.to_tokens(tokens);
3023        }
3024    }
3025
3026    #[cfg(feature = "full")]
3027    impl ToTokens for ExprWhileLet {
3028        fn to_tokens(&self, tokens: &mut Tokens) {
3029            tokens.append_all(self.attrs.outer());
3030            self.label.to_tokens(tokens);
3031            self.while_token.to_tokens(tokens);
3032            self.let_token.to_tokens(tokens);
3033            self.pat.to_tokens(tokens);
3034            self.eq_token.to_tokens(tokens);
3035            wrap_bare_struct(tokens, &self.expr);
3036            self.body.to_tokens(tokens);
3037        }
3038    }
3039
3040    #[cfg(feature = "full")]
3041    impl ToTokens for ExprForLoop {
3042        fn to_tokens(&self, tokens: &mut Tokens) {
3043            tokens.append_all(self.attrs.outer());
3044            self.label.to_tokens(tokens);
3045            self.for_token.to_tokens(tokens);
3046            self.pat.to_tokens(tokens);
3047            self.in_token.to_tokens(tokens);
3048            wrap_bare_struct(tokens, &self.expr);
3049            self.body.to_tokens(tokens);
3050        }
3051    }
3052
3053    #[cfg(feature = "full")]
3054    impl ToTokens for ExprLoop {
3055        fn to_tokens(&self, tokens: &mut Tokens) {
3056            tokens.append_all(self.attrs.outer());
3057            self.label.to_tokens(tokens);
3058            self.loop_token.to_tokens(tokens);
3059            self.body.to_tokens(tokens);
3060        }
3061    }
3062
3063    #[cfg(feature = "full")]
3064    impl ToTokens for ExprMatch {
3065        fn to_tokens(&self, tokens: &mut Tokens) {
3066            tokens.append_all(self.attrs.outer());
3067            self.match_token.to_tokens(tokens);
3068            wrap_bare_struct(tokens, &self.expr);
3069            self.brace_token.surround(tokens, |tokens| {
3070                for (i, arm) in self.arms.iter().enumerate() {
3071                    arm.to_tokens(tokens);
3072                    // Ensure that we have a comma after a non-block arm, except
3073                    // for the last one.
3074                    let is_last = i == self.arms.len() - 1;
3075                    if !is_last && arm_expr_requires_comma(&arm.body) && arm.comma.is_none() {
3076                        <Token![,]>::default().to_tokens(tokens);
3077                    }
3078                }
3079            });
3080        }
3081    }
3082
3083    #[cfg(feature = "full")]
3084    impl ToTokens for ExprCatch {
3085        fn to_tokens(&self, tokens: &mut Tokens) {
3086            tokens.append_all(self.attrs.outer());
3087            self.do_token.to_tokens(tokens);
3088            self.catch_token.to_tokens(tokens);
3089            self.block.to_tokens(tokens);
3090        }
3091    }
3092
3093    #[cfg(feature = "full")]
3094    impl ToTokens for ExprYield {
3095        fn to_tokens(&self, tokens: &mut Tokens) {
3096            tokens.append_all(self.attrs.outer());
3097            self.yield_token.to_tokens(tokens);
3098            self.expr.to_tokens(tokens);
3099        }
3100    }
3101
3102    #[cfg(feature = "full")]
3103    impl ToTokens for ExprClosure {
3104        fn to_tokens(&self, tokens: &mut Tokens) {
3105            tokens.append_all(self.attrs.outer());
3106            self.capture.to_tokens(tokens);
3107            self.or1_token.to_tokens(tokens);
3108            for input in self.inputs.pairs() {
3109                match **input.value() {
3110                    FnArg::Captured(ArgCaptured {
3111                        ref pat,
3112                        ty: Type::Infer(_),
3113                        ..
3114                    }) => {
3115                        pat.to_tokens(tokens);
3116                    }
3117                    _ => input.value().to_tokens(tokens),
3118                }
3119                input.punct().to_tokens(tokens);
3120            }
3121            self.or2_token.to_tokens(tokens);
3122            self.output.to_tokens(tokens);
3123            self.body.to_tokens(tokens);
3124        }
3125    }
3126
3127    #[cfg(feature = "full")]
3128    impl ToTokens for ExprUnsafe {
3129        fn to_tokens(&self, tokens: &mut Tokens) {
3130            tokens.append_all(self.attrs.outer());
3131            self.unsafe_token.to_tokens(tokens);
3132            self.block.to_tokens(tokens);
3133        }
3134    }
3135
3136    #[cfg(feature = "full")]
3137    impl ToTokens for ExprBlock {
3138        fn to_tokens(&self, tokens: &mut Tokens) {
3139            tokens.append_all(self.attrs.outer());
3140            self.block.to_tokens(tokens);
3141        }
3142    }
3143
3144    #[cfg(feature = "full")]
3145    impl ToTokens for ExprAssign {
3146        fn to_tokens(&self, tokens: &mut Tokens) {
3147            tokens.append_all(self.attrs.outer());
3148            self.left.to_tokens(tokens);
3149            self.eq_token.to_tokens(tokens);
3150            self.right.to_tokens(tokens);
3151        }
3152    }
3153
3154    #[cfg(feature = "full")]
3155    impl ToTokens for ExprAssignOp {
3156        fn to_tokens(&self, tokens: &mut Tokens) {
3157            tokens.append_all(self.attrs.outer());
3158            self.left.to_tokens(tokens);
3159            self.op.to_tokens(tokens);
3160            self.right.to_tokens(tokens);
3161        }
3162    }
3163
3164    #[cfg(feature = "full")]
3165    impl ToTokens for ExprField {
3166        fn to_tokens(&self, tokens: &mut Tokens) {
3167            tokens.append_all(self.attrs.outer());
3168            self.base.to_tokens(tokens);
3169            self.dot_token.to_tokens(tokens);
3170            self.member.to_tokens(tokens);
3171        }
3172    }
3173
3174    impl ToTokens for Member {
3175        fn to_tokens(&self, tokens: &mut Tokens) {
3176            match *self {
3177                Member::Named(ident) => ident.to_tokens(tokens),
3178                Member::Unnamed(ref index) => index.to_tokens(tokens),
3179            }
3180        }
3181    }
3182
3183    impl ToTokens for Index {
3184        fn to_tokens(&self, tokens: &mut Tokens) {
3185            tokens.append(TokenTree {
3186                span: self.span,
3187                kind: TokenNode::Literal(Literal::integer(i64::from(self.index))),
3188            });
3189        }
3190    }
3191
3192    impl ToTokens for ExprIndex {
3193        fn to_tokens(&self, tokens: &mut Tokens) {
3194            attrs_to_tokens(&self.attrs, tokens);
3195            self.expr.to_tokens(tokens);
3196            self.bracket_token.surround(tokens, |tokens| {
3197                self.index.to_tokens(tokens);
3198            });
3199        }
3200    }
3201
3202    #[cfg(feature = "full")]
3203    impl ToTokens for ExprRange {
3204        fn to_tokens(&self, tokens: &mut Tokens) {
3205            tokens.append_all(self.attrs.outer());
3206            self.from.to_tokens(tokens);
3207            match self.limits {
3208                RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3209                RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3210            }
3211            self.to.to_tokens(tokens);
3212        }
3213    }
3214
3215    impl ToTokens for ExprPath {
3216        fn to_tokens(&self, tokens: &mut Tokens) {
3217            attrs_to_tokens(&self.attrs, tokens);
3218            ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
3219        }
3220    }
3221
3222    #[cfg(feature = "full")]
3223    impl ToTokens for ExprAddrOf {
3224        fn to_tokens(&self, tokens: &mut Tokens) {
3225            tokens.append_all(self.attrs.outer());
3226            self.and_token.to_tokens(tokens);
3227            self.mutability.to_tokens(tokens);
3228            self.expr.to_tokens(tokens);
3229        }
3230    }
3231
3232    #[cfg(feature = "full")]
3233    impl ToTokens for ExprBreak {
3234        fn to_tokens(&self, tokens: &mut Tokens) {
3235            tokens.append_all(self.attrs.outer());
3236            self.break_token.to_tokens(tokens);
3237            self.label.to_tokens(tokens);
3238            self.expr.to_tokens(tokens);
3239        }
3240    }
3241
3242    #[cfg(feature = "full")]
3243    impl ToTokens for ExprContinue {
3244        fn to_tokens(&self, tokens: &mut Tokens) {
3245            tokens.append_all(self.attrs.outer());
3246            self.continue_token.to_tokens(tokens);
3247            self.label.to_tokens(tokens);
3248        }
3249    }
3250
3251    #[cfg(feature = "full")]
3252    impl ToTokens for ExprReturn {
3253        fn to_tokens(&self, tokens: &mut Tokens) {
3254            tokens.append_all(self.attrs.outer());
3255            self.return_token.to_tokens(tokens);
3256            self.expr.to_tokens(tokens);
3257        }
3258    }
3259
3260    #[cfg(feature = "full")]
3261    impl ToTokens for ExprMacro {
3262        fn to_tokens(&self, tokens: &mut Tokens) {
3263            tokens.append_all(self.attrs.outer());
3264            self.mac.to_tokens(tokens);
3265        }
3266    }
3267
3268    #[cfg(feature = "full")]
3269    impl ToTokens for ExprStruct {
3270        fn to_tokens(&self, tokens: &mut Tokens) {
3271            tokens.append_all(self.attrs.outer());
3272            self.path.to_tokens(tokens);
3273            self.brace_token.surround(tokens, |tokens| {
3274                self.fields.to_tokens(tokens);
3275                if self.rest.is_some() {
3276                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
3277                    self.rest.to_tokens(tokens);
3278                }
3279            })
3280        }
3281    }
3282
3283    #[cfg(feature = "full")]
3284    impl ToTokens for ExprRepeat {
3285        fn to_tokens(&self, tokens: &mut Tokens) {
3286            tokens.append_all(self.attrs.outer());
3287            self.bracket_token.surround(tokens, |tokens| {
3288                self.expr.to_tokens(tokens);
3289                self.semi_token.to_tokens(tokens);
3290                self.len.to_tokens(tokens);
3291            })
3292        }
3293    }
3294
3295    #[cfg(feature = "full")]
3296    impl ToTokens for ExprGroup {
3297        fn to_tokens(&self, tokens: &mut Tokens) {
3298            attrs_to_tokens(&self.attrs, tokens);
3299            self.group_token.surround(tokens, |tokens| {
3300                self.expr.to_tokens(tokens);
3301            });
3302        }
3303    }
3304
3305    impl ToTokens for ExprParen {
3306        fn to_tokens(&self, tokens: &mut Tokens) {
3307            attrs_to_tokens(&self.attrs, tokens);
3308            self.paren_token.surround(tokens, |tokens| {
3309                self.expr.to_tokens(tokens);
3310            });
3311        }
3312    }
3313
3314    #[cfg(feature = "full")]
3315    impl ToTokens for ExprTry {
3316        fn to_tokens(&self, tokens: &mut Tokens) {
3317            tokens.append_all(self.attrs.outer());
3318            self.expr.to_tokens(tokens);
3319            self.question_token.to_tokens(tokens);
3320        }
3321    }
3322
3323    impl ToTokens for ExprVerbatim {
3324        fn to_tokens(&self, tokens: &mut Tokens) {
3325            self.tts.to_tokens(tokens);
3326        }
3327    }
3328
3329    #[cfg(feature = "full")]
3330    impl ToTokens for Label {
3331        fn to_tokens(&self, tokens: &mut Tokens) {
3332            self.name.to_tokens(tokens);
3333            self.colon_token.to_tokens(tokens);
3334        }
3335    }
3336
3337    #[cfg(feature = "full")]
3338    impl ToTokens for FieldValue {
3339        fn to_tokens(&self, tokens: &mut Tokens) {
3340            tokens.append_all(self.attrs.outer());
3341            self.member.to_tokens(tokens);
3342            if let Some(ref colon_token) = self.colon_token {
3343                colon_token.to_tokens(tokens);
3344                self.expr.to_tokens(tokens);
3345            }
3346        }
3347    }
3348
3349    #[cfg(feature = "full")]
3350    impl ToTokens for Arm {
3351        fn to_tokens(&self, tokens: &mut Tokens) {
3352            tokens.append_all(&self.attrs);
3353            self.pats.to_tokens(tokens);
3354            if let Some((ref if_token, ref guard)) = self.guard {
3355                if_token.to_tokens(tokens);
3356                guard.to_tokens(tokens);
3357            }
3358            self.rocket_token.to_tokens(tokens);
3359            self.body.to_tokens(tokens);
3360            self.comma.to_tokens(tokens);
3361        }
3362    }
3363
3364    #[cfg(feature = "full")]
3365    impl ToTokens for PatWild {
3366        fn to_tokens(&self, tokens: &mut Tokens) {
3367            self.underscore_token.to_tokens(tokens);
3368        }
3369    }
3370
3371    #[cfg(feature = "full")]
3372    impl ToTokens for PatIdent {
3373        fn to_tokens(&self, tokens: &mut Tokens) {
3374            self.by_ref.to_tokens(tokens);
3375            self.mutability.to_tokens(tokens);
3376            self.ident.to_tokens(tokens);
3377            if let Some((ref at_token, ref subpat)) = self.subpat {
3378                at_token.to_tokens(tokens);
3379                subpat.to_tokens(tokens);
3380            }
3381        }
3382    }
3383
3384    #[cfg(feature = "full")]
3385    impl ToTokens for PatStruct {
3386        fn to_tokens(&self, tokens: &mut Tokens) {
3387            self.path.to_tokens(tokens);
3388            self.brace_token.surround(tokens, |tokens| {
3389                self.fields.to_tokens(tokens);
3390                // NOTE: We need a comma before the dot2 token if it is present.
3391                if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
3392                    <Token![,]>::default().to_tokens(tokens);
3393                }
3394                self.dot2_token.to_tokens(tokens);
3395            });
3396        }
3397    }
3398
3399    #[cfg(feature = "full")]
3400    impl ToTokens for PatTupleStruct {
3401        fn to_tokens(&self, tokens: &mut Tokens) {
3402            self.path.to_tokens(tokens);
3403            self.pat.to_tokens(tokens);
3404        }
3405    }
3406
3407    #[cfg(feature = "full")]
3408    impl ToTokens for PatPath {
3409        fn to_tokens(&self, tokens: &mut Tokens) {
3410            ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3411        }
3412    }
3413
3414    #[cfg(feature = "full")]
3415    impl ToTokens for PatTuple {
3416        fn to_tokens(&self, tokens: &mut Tokens) {
3417            self.paren_token.surround(tokens, |tokens| {
3418                self.front.to_tokens(tokens);
3419                if let Some(ref dot2_token) = self.dot2_token {
3420                    if !self.front.empty_or_trailing() {
3421                        // Ensure there is a comma before the .. token.
3422                        <Token![,]>::default().to_tokens(tokens);
3423                    }
3424                    dot2_token.to_tokens(tokens);
3425                    self.comma_token.to_tokens(tokens);
3426                    if self.comma_token.is_none() && !self.back.is_empty() {
3427                        // Ensure there is a comma after the .. token.
3428                        <Token![,]>::default().to_tokens(tokens);
3429                    }
3430                }
3431                self.back.to_tokens(tokens);
3432            });
3433        }
3434    }
3435
3436    #[cfg(feature = "full")]
3437    impl ToTokens for PatBox {
3438        fn to_tokens(&self, tokens: &mut Tokens) {
3439            self.box_token.to_tokens(tokens);
3440            self.pat.to_tokens(tokens);
3441        }
3442    }
3443
3444    #[cfg(feature = "full")]
3445    impl ToTokens for PatRef {
3446        fn to_tokens(&self, tokens: &mut Tokens) {
3447            self.and_token.to_tokens(tokens);
3448            self.mutability.to_tokens(tokens);
3449            self.pat.to_tokens(tokens);
3450        }
3451    }
3452
3453    #[cfg(feature = "full")]
3454    impl ToTokens for PatLit {
3455        fn to_tokens(&self, tokens: &mut Tokens) {
3456            self.expr.to_tokens(tokens);
3457        }
3458    }
3459
3460    #[cfg(feature = "full")]
3461    impl ToTokens for PatRange {
3462        fn to_tokens(&self, tokens: &mut Tokens) {
3463            self.lo.to_tokens(tokens);
3464            match self.limits {
3465                RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3466                RangeLimits::Closed(ref t) => Token![...](t.0).to_tokens(tokens),
3467            }
3468            self.hi.to_tokens(tokens);
3469        }
3470    }
3471
3472    #[cfg(feature = "full")]
3473    impl ToTokens for PatSlice {
3474        fn to_tokens(&self, tokens: &mut Tokens) {
3475            // XXX: This is a mess, and it will be so easy to screw it up. How
3476            // do we make this correct itself better?
3477            self.bracket_token.surround(tokens, |tokens| {
3478                self.front.to_tokens(tokens);
3479
3480                // If we need a comma before the middle or standalone .. token,
3481                // then make sure it's present.
3482                if !self.front.empty_or_trailing()
3483                    && (self.middle.is_some() || self.dot2_token.is_some())
3484                {
3485                    <Token![,]>::default().to_tokens(tokens);
3486                }
3487
3488                // If we have an identifier, we always need a .. token.
3489                if self.middle.is_some() {
3490                    self.middle.to_tokens(tokens);
3491                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
3492                } else if self.dot2_token.is_some() {
3493                    self.dot2_token.to_tokens(tokens);
3494                }
3495
3496                // Make sure we have a comma before the back half.
3497                if !self.back.is_empty() {
3498                    TokensOrDefault(&self.comma_token).to_tokens(tokens);
3499                    self.back.to_tokens(tokens);
3500                } else {
3501                    self.comma_token.to_tokens(tokens);
3502                }
3503            })
3504        }
3505    }
3506
3507    #[cfg(feature = "full")]
3508    impl ToTokens for PatMacro {
3509        fn to_tokens(&self, tokens: &mut Tokens) {
3510            self.mac.to_tokens(tokens);
3511        }
3512    }
3513
3514    #[cfg(feature = "full")]
3515    impl ToTokens for PatVerbatim {
3516        fn to_tokens(&self, tokens: &mut Tokens) {
3517            self.tts.to_tokens(tokens);
3518        }
3519    }
3520
3521    #[cfg(feature = "full")]
3522    impl ToTokens for FieldPat {
3523        fn to_tokens(&self, tokens: &mut Tokens) {
3524            if let Some(ref colon_token) = self.colon_token {
3525                self.member.to_tokens(tokens);
3526                colon_token.to_tokens(tokens);
3527            }
3528            self.pat.to_tokens(tokens);
3529        }
3530    }
3531
3532    #[cfg(feature = "full")]
3533    impl ToTokens for Block {
3534        fn to_tokens(&self, tokens: &mut Tokens) {
3535            self.brace_token.surround(tokens, |tokens| {
3536                tokens.append_all(&self.stmts);
3537            });
3538        }
3539    }
3540
3541    #[cfg(feature = "full")]
3542    impl ToTokens for Stmt {
3543        fn to_tokens(&self, tokens: &mut Tokens) {
3544            match *self {
3545                Stmt::Local(ref local) => local.to_tokens(tokens),
3546                Stmt::Item(ref item) => item.to_tokens(tokens),
3547                Stmt::Expr(ref expr) => expr.to_tokens(tokens),
3548                Stmt::Semi(ref expr, ref semi) => {
3549                    expr.to_tokens(tokens);
3550                    semi.to_tokens(tokens);
3551                }
3552            }
3553        }
3554    }
3555
3556    #[cfg(feature = "full")]
3557    impl ToTokens for Local {
3558        fn to_tokens(&self, tokens: &mut Tokens) {
3559            tokens.append_all(self.attrs.outer());
3560            self.let_token.to_tokens(tokens);
3561            self.pat.to_tokens(tokens);
3562            if let Some((ref colon_token, ref ty)) = self.ty {
3563                colon_token.to_tokens(tokens);
3564                ty.to_tokens(tokens);
3565            }
3566            if let Some((ref eq_token, ref init)) = self.init {
3567                eq_token.to_tokens(tokens);
3568                init.to_tokens(tokens);
3569            }
3570            self.semi_token.to_tokens(tokens);
3571        }
3572    }
3573}