1 use super::*;
2 
3 /// An expression.
4 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
5 pub struct Expr {
6     /// Type of the expression.
7     pub node: ExprKind,
8 
9     /// Attributes tagged on the expression.
10     pub attrs: Vec<Attribute>,
11 }
12 
13 impl From<ExprKind> for Expr {
from(node: ExprKind) -> Expr14     fn from(node: ExprKind) -> Expr {
15         Expr {
16             node: node,
17             attrs: Vec::new(),
18         }
19     }
20 }
21 
22 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
23 pub enum ExprKind {
24     /// A `box x` expression.
25     Box(Box<Expr>),
26 
27     /// First expr is the place; second expr is the value.
28     ///
29     /// E.g. 'plae <- val'.
30     InPlace(Box<Expr>, Box<Expr>),
31 
32     /// An array, e.g. `[a, b, c, d]`.
33     Array(Vec<Expr>),
34 
35     /// A function call.
36     ///
37     /// The first field resolves to the function itself,
38     /// and the second field is the list of arguments
39     Call(Box<Expr>, Vec<Expr>),
40 
41     /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
42     ///
43     /// The `Ident` is the identifier for the method name.
44     /// The vector of `Ty`s are the ascripted type parameters for the method
45     /// (within the angle brackets).
46     ///
47     /// The first element of the vector of `Expr`s is the expression that evaluates
48     /// to the object on which the method is being called on (the receiver),
49     /// and the remaining elements are the rest of the arguments.
50     ///
51     /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
52     /// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
53     MethodCall(Ident, Vec<Ty>, Vec<Expr>),
54 
55     /// A tuple, e.g. `(a, b, c, d)`.
56     Tup(Vec<Expr>),
57 
58     /// A binary operation, e.g. `a + b`, `a * b`.
59     Binary(BinOp, Box<Expr>, Box<Expr>),
60 
61     /// A unary operation, e.g. `!x`, `*x`.
62     Unary(UnOp, Box<Expr>),
63 
64     /// A literal, e.g. `1`, `"foo"`.
65     Lit(Lit),
66 
67     /// A cast, e.g. `foo as f64`.
68     Cast(Box<Expr>, Box<Ty>),
69 
70     /// A type ascription, e.g. `foo: f64`.
71     Type(Box<Expr>, Box<Ty>),
72 
73     /// An `if` block, with an optional else block
74     ///
75     /// E.g., `if expr { block } else { expr }`
76     If(Box<Expr>, Block, Option<Box<Expr>>),
77 
78     /// An `if let` expression with an optional else block
79     ///
80     /// E.g., `if let pat = expr { block } else { expr }`
81     ///
82     /// This is desugared to a `match` expression.
83     IfLet(Box<Pat>, Box<Expr>, Block, Option<Box<Expr>>),
84 
85     /// A while loop, with an optional label
86     ///
87     /// E.g., `'label: while expr { block }`
88     While(Box<Expr>, Block, Option<Ident>),
89 
90     /// A while-let loop, with an optional label.
91     ///
92     /// E.g., `'label: while let pat = expr { block }`
93     ///
94     /// This is desugared to a combination of `loop` and `match` expressions.
95     WhileLet(Box<Pat>, Box<Expr>, Block, Option<Ident>),
96 
97     /// A for loop, with an optional label.
98     ///
99     /// E.g., `'label: for pat in expr { block }`
100     ///
101     /// This is desugared to a combination of `loop` and `match` expressions.
102     ForLoop(Box<Pat>, Box<Expr>, Block, Option<Ident>),
103 
104     /// Conditionless loop with an optional label.
105     ///
106     /// E.g. `'label: loop { block }`
107     Loop(Block, Option<Ident>),
108 
109     /// A `match` block.
110     Match(Box<Expr>, Vec<Arm>),
111 
112     /// A closure (for example, `move |a, b, c| a + b + c`)
113     Closure(CaptureBy, Box<FnDecl>, Box<Expr>),
114 
115     /// A block (`{ ... }` or `unsafe { ... }`)
116     Block(Unsafety, Block),
117 
118     /// An assignment (`a = foo()`)
119     Assign(Box<Expr>, Box<Expr>),
120 
121     /// An assignment with an operator
122     ///
123     /// For example, `a += 1`.
124     AssignOp(BinOp, Box<Expr>, Box<Expr>),
125 
126     /// Access of a named struct field (`obj.foo`)
127     Field(Box<Expr>, Ident),
128 
129     /// Access of an unnamed field of a struct or tuple-struct
130     ///
131     /// For example, `foo.0`.
132     TupField(Box<Expr>, usize),
133 
134     /// An indexing operation (`foo[2]`)
135     Index(Box<Expr>, Box<Expr>),
136 
137     /// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`)
138     Range(Option<Box<Expr>>, Option<Box<Expr>>, RangeLimits),
139 
140     /// Variable reference, possibly containing `::` and/or type
141     /// parameters, e.g. foo::bar::<baz>.
142     ///
143     /// Optionally "qualified",
144     /// E.g. `<Vec<T> as SomeTrait>::SomeType`.
145     Path(Option<QSelf>, Path),
146 
147     /// A referencing operation (`&a` or `&mut a`)
148     AddrOf(Mutability, Box<Expr>),
149 
150     /// A `break`, with an optional label to break, and an optional expression
151     Break(Option<Ident>, Option<Box<Expr>>),
152 
153     /// A `continue`, with an optional label
154     Continue(Option<Ident>),
155 
156     /// A `return`, with an optional value to be returned
157     Ret(Option<Box<Expr>>),
158 
159     /// A macro invocation; pre-expansion
160     Mac(Mac),
161 
162     /// A struct literal expression.
163     ///
164     /// For example, `Foo {x: 1, y: 2}`, or
165     /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
166     Struct(Path, Vec<FieldValue>, Option<Box<Expr>>),
167 
168     /// An array literal constructed from one repeated element.
169     ///
170     /// For example, `[1; 5]`. The first expression is the element
171     /// to be repeated; the second is the number of times to repeat it.
172     Repeat(Box<Expr>, Box<Expr>),
173 
174     /// No-op: used solely so we can pretty-print faithfully
175     Paren(Box<Expr>),
176 
177     /// `expr?`
178     Try(Box<Expr>),
179 }
180 
181 /// A field-value pair in a struct literal.
182 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
183 pub struct FieldValue {
184     /// Name of the field.
185     pub ident: Ident,
186 
187     /// Value of the field.
188     pub expr: Expr,
189 
190     /// Whether this is a shorthand field, e.g. `Struct { x }`
191     /// instead of `Struct { x: x }`.
192     pub is_shorthand: bool,
193 
194     /// Attributes tagged on the field.
195     pub attrs: Vec<Attribute>,
196 }
197 
198 /// A Block (`{ .. }`).
199 ///
200 /// E.g. `{ .. }` as in `fn foo() { .. }`
201 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
202 pub struct Block {
203     /// Statements in a block
204     pub stmts: Vec<Stmt>,
205 }
206 
207 /// A statement, usually ending in a semicolon.
208 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
209 pub enum Stmt {
210     /// A local (let) binding.
211     Local(Box<Local>),
212 
213     /// An item definition.
214     Item(Box<Item>),
215 
216     /// Expr without trailing semicolon.
217     Expr(Box<Expr>),
218 
219     /// Expression with trailing semicolon;
220     Semi(Box<Expr>),
221 
222     /// Macro invocation.
223     Mac(Box<(Mac, MacStmtStyle, Vec<Attribute>)>),
224 }
225 
226 /// How a macro was invoked.
227 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
228 pub enum MacStmtStyle {
229     /// The macro statement had a trailing semicolon, e.g. `foo! { ... };`
230     /// `foo!(...);`, `foo![...];`
231     Semicolon,
232 
233     /// The macro statement had braces; e.g. foo! { ... }
234     Braces,
235 
236     /// The macro statement had parentheses or brackets and no semicolon; e.g.
237     /// `foo!(...)`. All of these will end up being converted into macro
238     /// expressions.
239     NoBraces,
240 }
241 
242 /// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`
243 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
244 pub struct Local {
245     pub pat: Box<Pat>,
246     pub ty: Option<Box<Ty>>,
247 
248     /// Initializer expression to set the value, if any
249     pub init: Option<Box<Expr>>,
250     pub attrs: Vec<Attribute>,
251 }
252 
253 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
254 // Clippy false positive
255 // https://github.com/Manishearth/rust-clippy/issues/1241
256 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
257 pub enum Pat {
258     /// Represents a wildcard pattern (`_`)
259     Wild,
260 
261     /// A `Pat::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`),
262     /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
263     /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
264     /// during name resolution.
265     Ident(BindingMode, Ident, Option<Box<Pat>>),
266 
267     /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
268     /// The `bool` is `true` in the presence of a `..`.
269     Struct(Path, Vec<FieldPat>, bool),
270 
271     /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
272     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
273     /// 0 <= position <= subpats.len()
274     TupleStruct(Path, Vec<Pat>, Option<usize>),
275 
276     /// A possibly qualified path pattern.
277     /// Unquailfied path patterns `A::B::C` can legally refer to variants, structs, constants
278     /// or associated constants. Quailfied path patterns `<A>::B::C`/`<A as Trait>::B::C` can
279     /// only legally refer to associated constants.
280     Path(Option<QSelf>, Path),
281 
282     /// A tuple pattern `(a, b)`.
283     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
284     /// 0 <= position <= subpats.len()
285     Tuple(Vec<Pat>, Option<usize>),
286     /// A `box` pattern
287     Box(Box<Pat>),
288     /// A reference pattern, e.g. `&mut (a, b)`
289     Ref(Box<Pat>, Mutability),
290     /// A literal
291     Lit(Box<Expr>),
292     /// A range pattern, e.g. `1...2`
293     Range(Box<Expr>, Box<Expr>),
294     /// `[a, b, ..i, y, z]` is represented as:
295     ///     `Pat::Slice(box [a, b], Some(i), box [y, z])`
296     Slice(Vec<Pat>, Option<Box<Pat>>, Vec<Pat>),
297     /// A macro pattern; pre-expansion
298     Mac(Mac),
299 }
300 
301 /// An arm of a 'match'.
302 ///
303 /// E.g. `0...10 => { println!("match!") }` as in
304 ///
305 /// ```rust,ignore
306 /// match n {
307 ///     0...10 => { println!("match!") },
308 ///     // ..
309 /// }
310 /// ```
311 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
312 pub struct Arm {
313     pub attrs: Vec<Attribute>,
314     pub pats: Vec<Pat>,
315     pub guard: Option<Box<Expr>>,
316     pub body: Box<Expr>,
317 }
318 
319 /// A capture clause
320 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
321 pub enum CaptureBy {
322     Value,
323     Ref,
324 }
325 
326 /// Limit types of a range (inclusive or exclusive)
327 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
328 pub enum RangeLimits {
329     /// Inclusive at the beginning, exclusive at the end
330     HalfOpen,
331     /// Inclusive at the beginning and end
332     Closed,
333 }
334 
335 /// A single field in a struct pattern
336 ///
337 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
338 /// are treated the same as `x: x, y: ref y, z: ref mut z`,
339 /// except `is_shorthand` is true
340 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
341 pub struct FieldPat {
342     /// The identifier for the field
343     pub ident: Ident,
344     /// The pattern the field is destructured to
345     pub pat: Box<Pat>,
346     pub is_shorthand: bool,
347     pub attrs: Vec<Attribute>,
348 }
349 
350 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
351 pub enum BindingMode {
352     ByRef(Mutability),
353     ByValue(Mutability),
354 }
355 
356 #[cfg(feature = "parsing")]
357 pub mod parsing {
358     use super::*;
359     use {BinOp, Delimited, DelimToken, FnArg, FnDecl, FunctionRetTy, Ident, Lifetime, Mac,
360          TokenTree, Ty, UnOp, Unsafety};
361     use attr::parsing::outer_attr;
362     use generics::parsing::lifetime;
363     use ident::parsing::{ident, wordlike};
364     use item::parsing::item;
365     use lit::parsing::{digits, lit};
366     use mac::parsing::{mac, token_trees};
367     use synom::IResult::{self, Error};
368     use op::parsing::{assign_op, binop, unop};
369     use ty::parsing::{mutability, path, qpath, ty, unsafety};
370 
371     // Struct literals are ambiguous in certain positions
372     // https://github.com/rust-lang/rfcs/pull/92
373     macro_rules! named_ambiguous_expr {
374         ($name:ident -> $o:ty, $allow_struct:ident, $submac:ident!( $($args:tt)* )) => {
375             fn $name(i: &str, $allow_struct: bool) -> $crate::synom::IResult<&str, $o> {
376                 $submac!(i, $($args)*)
377             }
378         };
379     }
380 
381     macro_rules! ambiguous_expr {
382         ($i:expr, $allow_struct:ident) => {
383             ambiguous_expr($i, $allow_struct, true)
384         };
385     }
386 
387     named!(pub expr -> Expr, ambiguous_expr!(true));
388 
389     named!(expr_no_struct -> Expr, ambiguous_expr!(false));
390 
391     #[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
ambiguous_expr(i: &str, allow_struct: bool, allow_block: bool) -> IResult<&str, Expr>392     fn ambiguous_expr(i: &str, allow_struct: bool, allow_block: bool) -> IResult<&str, Expr> {
393         do_parse!(
394             i,
395             mut e: alt!(
396                 expr_lit // must be before expr_struct
397                 |
398                 cond_reduce!(allow_struct, expr_struct) // must be before expr_path
399                 |
400                 expr_paren // must be before expr_tup
401                 |
402                 expr_mac // must be before expr_path
403                 |
404                 call!(expr_break, allow_struct) // must be before expr_path
405                 |
406                 expr_continue // must be before expr_path
407                 |
408                 call!(expr_ret, allow_struct) // must be before expr_path
409                 |
410                 call!(expr_box, allow_struct)
411                 |
412                 expr_in_place
413                 |
414                 expr_array
415                 |
416                 expr_tup
417                 |
418                 call!(expr_unary, allow_struct)
419                 |
420                 expr_if
421                 |
422                 expr_while
423                 |
424                 expr_for_loop
425                 |
426                 expr_loop
427                 |
428                 expr_match
429                 |
430                 call!(expr_closure, allow_struct)
431                 |
432                 cond_reduce!(allow_block, expr_block)
433                 |
434                 call!(expr_range, allow_struct)
435                 |
436                 expr_path
437                 |
438                 call!(expr_addr_of, allow_struct)
439                 |
440                 expr_repeat
441             ) >>
442             many0!(alt!(
443                 tap!(args: and_call => {
444                     e = ExprKind::Call(Box::new(e.into()), args);
445                 })
446                 |
447                 tap!(more: and_method_call => {
448                     let (method, ascript, mut args) = more;
449                     args.insert(0, e.into());
450                     e = ExprKind::MethodCall(method, ascript, args);
451                 })
452                 |
453                 tap!(more: call!(and_binary, allow_struct) => {
454                     let (op, other) = more;
455                     e = ExprKind::Binary(op, Box::new(e.into()), Box::new(other));
456                 })
457                 |
458                 tap!(ty: and_cast => {
459                     e = ExprKind::Cast(Box::new(e.into()), Box::new(ty));
460                 })
461                 |
462                 tap!(ty: and_ascription => {
463                     e = ExprKind::Type(Box::new(e.into()), Box::new(ty));
464                 })
465                 |
466                 tap!(v: call!(and_assign, allow_struct) => {
467                     e = ExprKind::Assign(Box::new(e.into()), Box::new(v));
468                 })
469                 |
470                 tap!(more: call!(and_assign_op, allow_struct) => {
471                     let (op, v) = more;
472                     e = ExprKind::AssignOp(op, Box::new(e.into()), Box::new(v));
473                 })
474                 |
475                 tap!(field: and_field => {
476                     e = ExprKind::Field(Box::new(e.into()), field);
477                 })
478                 |
479                 tap!(field: and_tup_field => {
480                     e = ExprKind::TupField(Box::new(e.into()), field as usize);
481                 })
482                 |
483                 tap!(i: and_index => {
484                     e = ExprKind::Index(Box::new(e.into()), Box::new(i));
485                 })
486                 |
487                 tap!(more: call!(and_range, allow_struct) => {
488                     let (limits, hi) = more;
489                     e = ExprKind::Range(Some(Box::new(e.into())), hi.map(Box::new), limits);
490                 })
491                 |
492                 tap!(_try: punct!("?") => {
493                     e = ExprKind::Try(Box::new(e.into()));
494                 })
495             )) >>
496             (e.into())
497         )
498     }
499 
500     named!(expr_mac -> ExprKind, map!(mac, ExprKind::Mac));
501 
502     named!(expr_paren -> ExprKind, do_parse!(
503         punct!("(") >>
504         e: expr >>
505         punct!(")") >>
506         (ExprKind::Paren(Box::new(e)))
507     ));
508 
509     named_ambiguous_expr!(expr_box -> ExprKind, allow_struct, do_parse!(
510         keyword!("box") >>
511         inner: ambiguous_expr!(allow_struct) >>
512         (ExprKind::Box(Box::new(inner)))
513     ));
514 
515     named!(expr_in_place -> ExprKind, do_parse!(
516         keyword!("in") >>
517         place: expr_no_struct >>
518         punct!("{") >>
519         value: within_block >>
520         punct!("}") >>
521         (ExprKind::InPlace(
522             Box::new(place),
523             Box::new(ExprKind::Block(Unsafety::Normal, Block {
524                 stmts: value,
525             }).into()),
526         ))
527     ));
528 
529     named!(expr_array -> ExprKind, do_parse!(
530         punct!("[") >>
531         elems: terminated_list!(punct!(","), expr) >>
532         punct!("]") >>
533         (ExprKind::Array(elems))
534     ));
535 
536     named!(and_call -> Vec<Expr>, do_parse!(
537         punct!("(") >>
538         args: terminated_list!(punct!(","), expr) >>
539         punct!(")") >>
540         (args)
541     ));
542 
543     named!(and_method_call -> (Ident, Vec<Ty>, Vec<Expr>), do_parse!(
544         punct!(".") >>
545         method: ident >>
546         ascript: opt_vec!(preceded!(
547             punct!("::"),
548             delimited!(
549                 punct!("<"),
550                 terminated_list!(punct!(","), ty),
551                 punct!(">")
552             )
553         )) >>
554         punct!("(") >>
555         args: terminated_list!(punct!(","), expr) >>
556         punct!(")") >>
557         (method, ascript, args)
558     ));
559 
560     named!(expr_tup -> ExprKind, do_parse!(
561         punct!("(") >>
562         elems: terminated_list!(punct!(","), expr) >>
563         punct!(")") >>
564         (ExprKind::Tup(elems))
565     ));
566 
567     named_ambiguous_expr!(and_binary -> (BinOp, Expr), allow_struct, tuple!(
568         binop,
569         ambiguous_expr!(allow_struct)
570     ));
571 
572     named_ambiguous_expr!(expr_unary -> ExprKind, allow_struct, do_parse!(
573         operator: unop >>
574         operand: ambiguous_expr!(allow_struct) >>
575         (ExprKind::Unary(operator, Box::new(operand)))
576     ));
577 
578     named!(expr_lit -> ExprKind, map!(lit, ExprKind::Lit));
579 
580     named!(and_cast -> Ty, do_parse!(
581         keyword!("as") >>
582         ty: ty >>
583         (ty)
584     ));
585 
586     named!(and_ascription -> Ty, preceded!(punct!(":"), ty));
587 
588     enum Cond {
589         Let(Pat, Expr),
590         Expr(Expr),
591     }
592 
593     named!(cond -> Cond, alt!(
594         do_parse!(
595             keyword!("let") >>
596             pat: pat >>
597             punct!("=") >>
598             value: expr_no_struct >>
599             (Cond::Let(pat, value))
600         )
601         |
602         map!(expr_no_struct, Cond::Expr)
603     ));
604 
605     named!(expr_if -> ExprKind, do_parse!(
606         keyword!("if") >>
607         cond: cond >>
608         punct!("{") >>
609         then_block: within_block >>
610         punct!("}") >>
611         else_block: option!(preceded!(
612             keyword!("else"),
613             alt!(
614                 expr_if
615                 |
616                 do_parse!(
617                     punct!("{") >>
618                     else_block: within_block >>
619                     punct!("}") >>
620                     (ExprKind::Block(Unsafety::Normal, Block {
621                         stmts: else_block,
622                     }).into())
623                 )
624             )
625         )) >>
626         (match cond {
627             Cond::Let(pat, expr) => ExprKind::IfLet(
628                 Box::new(pat),
629                 Box::new(expr),
630                 Block {
631                     stmts: then_block,
632                 },
633                 else_block.map(|els| Box::new(els.into())),
634             ),
635             Cond::Expr(cond) => ExprKind::If(
636                 Box::new(cond),
637                 Block {
638                     stmts: then_block,
639                 },
640                 else_block.map(|els| Box::new(els.into())),
641             ),
642         })
643     ));
644 
645     named!(expr_for_loop -> ExprKind, do_parse!(
646         lbl: option!(terminated!(label, punct!(":"))) >>
647         keyword!("for") >>
648         pat: pat >>
649         keyword!("in") >>
650         expr: expr_no_struct >>
651         loop_block: block >>
652         (ExprKind::ForLoop(Box::new(pat), Box::new(expr), loop_block, lbl))
653     ));
654 
655     named!(expr_loop -> ExprKind, do_parse!(
656         lbl: option!(terminated!(label, punct!(":"))) >>
657         keyword!("loop") >>
658         loop_block: block >>
659         (ExprKind::Loop(loop_block, lbl))
660     ));
661 
662     named!(expr_match -> ExprKind, do_parse!(
663         keyword!("match") >>
664         obj: expr_no_struct >>
665         punct!("{") >>
666         mut arms: many0!(do_parse!(
667             arm: match_arm >>
668             cond!(arm_requires_comma(&arm), punct!(",")) >>
669             cond!(!arm_requires_comma(&arm), option!(punct!(","))) >>
670             (arm)
671         )) >>
672         last_arm: option!(match_arm) >>
673         punct!("}") >>
674         (ExprKind::Match(Box::new(obj), {
675             arms.extend(last_arm);
676             arms
677         }))
678     ));
679 
arm_requires_comma(arm: &Arm) -> bool680     fn arm_requires_comma(arm: &Arm) -> bool {
681         if let ExprKind::Block(Unsafety::Normal, _) = arm.body.node {
682             false
683         } else {
684             true
685         }
686     }
687 
688     named!(match_arm -> Arm, do_parse!(
689         attrs: many0!(outer_attr) >>
690         pats: separated_nonempty_list!(punct!("|"), pat) >>
691         guard: option!(preceded!(keyword!("if"), expr)) >>
692         punct!("=>") >>
693         body: alt!(
694             map!(block, |blk| ExprKind::Block(Unsafety::Normal, blk).into())
695             |
696             expr
697         ) >>
698         (Arm {
699             attrs: attrs,
700             pats: pats,
701             guard: guard.map(Box::new),
702             body: Box::new(body),
703         })
704     ));
705 
706     named_ambiguous_expr!(expr_closure -> ExprKind, allow_struct, do_parse!(
707         capture: capture_by >>
708         punct!("|") >>
709         inputs: terminated_list!(punct!(","), closure_arg) >>
710         punct!("|") >>
711         ret_and_body: alt!(
712             do_parse!(
713                 punct!("->") >>
714                 ty: ty >>
715                 body: block >>
716                 (FunctionRetTy::Ty(ty), ExprKind::Block(Unsafety::Normal, body).into())
717             )
718             |
719             map!(ambiguous_expr!(allow_struct), |e| (FunctionRetTy::Default, e))
720         ) >>
721         (ExprKind::Closure(
722             capture,
723             Box::new(FnDecl {
724                 inputs: inputs,
725                 output: ret_and_body.0,
726                 variadic: false,
727             }),
728             Box::new(ret_and_body.1),
729         ))
730     ));
731 
732     named!(closure_arg -> FnArg, do_parse!(
733         pat: pat >>
734         ty: option!(preceded!(punct!(":"), ty)) >>
735         (FnArg::Captured(pat, ty.unwrap_or(Ty::Infer)))
736     ));
737 
738     named!(expr_while -> ExprKind, do_parse!(
739         lbl: option!(terminated!(label, punct!(":"))) >>
740         keyword!("while") >>
741         cond: cond >>
742         while_block: block >>
743         (match cond {
744             Cond::Let(pat, expr) => ExprKind::WhileLet(
745                 Box::new(pat),
746                 Box::new(expr),
747                 while_block,
748                 lbl,
749             ),
750             Cond::Expr(cond) => ExprKind::While(
751                 Box::new(cond),
752                 while_block,
753                 lbl,
754             ),
755         })
756     ));
757 
758     named!(expr_continue -> ExprKind, do_parse!(
759         keyword!("continue") >>
760         lbl: option!(label) >>
761         (ExprKind::Continue(lbl))
762     ));
763 
764     named_ambiguous_expr!(expr_break -> ExprKind, allow_struct, do_parse!(
765         keyword!("break") >>
766         lbl: option!(label) >>
767         val: option!(call!(ambiguous_expr, allow_struct, false)) >>
768         (ExprKind::Break(lbl, val.map(Box::new)))
769     ));
770 
771     named_ambiguous_expr!(expr_ret -> ExprKind, allow_struct, do_parse!(
772         keyword!("return") >>
773         ret_value: option!(ambiguous_expr!(allow_struct)) >>
774         (ExprKind::Ret(ret_value.map(Box::new)))
775     ));
776 
777     named!(expr_struct -> ExprKind, do_parse!(
778         path: path >>
779         punct!("{") >>
780         fields: separated_list!(punct!(","), field_value) >>
781         base: option!(do_parse!(
782             cond!(!fields.is_empty(), punct!(",")) >>
783             punct!("..") >>
784             base: expr >>
785             (base)
786         )) >>
787         cond!(!fields.is_empty() && base.is_none(), option!(punct!(","))) >>
788         punct!("}") >>
789         (ExprKind::Struct(path, fields, base.map(Box::new)))
790     ));
791 
792     named!(field_value -> FieldValue, alt!(
793         do_parse!(
794             name: wordlike >>
795             punct!(":") >>
796             value: expr >>
797             (FieldValue {
798                 ident: name,
799                 expr: value,
800                 is_shorthand: false,
801                 attrs: Vec::new(),
802             })
803         )
804         |
805         map!(ident, |name: Ident| FieldValue {
806             ident: name.clone(),
807             expr: ExprKind::Path(None, name.into()).into(),
808             is_shorthand: true,
809             attrs: Vec::new(),
810         })
811     ));
812 
813     named!(expr_repeat -> ExprKind, do_parse!(
814         punct!("[") >>
815         value: expr >>
816         punct!(";") >>
817         times: expr >>
818         punct!("]") >>
819         (ExprKind::Repeat(Box::new(value), Box::new(times)))
820     ));
821 
822     named!(expr_block -> ExprKind, do_parse!(
823         rules: unsafety >>
824         b: block >>
825         (ExprKind::Block(rules, Block {
826             stmts: b.stmts,
827         }))
828     ));
829 
830     named_ambiguous_expr!(expr_range -> ExprKind, allow_struct, do_parse!(
831         limits: range_limits >>
832         hi: option!(ambiguous_expr!(allow_struct)) >>
833         (ExprKind::Range(None, hi.map(Box::new), limits))
834     ));
835 
836     named!(range_limits -> RangeLimits, alt!(
837         punct!("...") => { |_| RangeLimits::Closed }
838         |
839         punct!("..") => { |_| RangeLimits::HalfOpen }
840     ));
841 
842     named!(expr_path -> ExprKind, map!(qpath, |(qself, path)| ExprKind::Path(qself, path)));
843 
844     named_ambiguous_expr!(expr_addr_of -> ExprKind, allow_struct, do_parse!(
845         punct!("&") >>
846         mutability: mutability >>
847         expr: ambiguous_expr!(allow_struct) >>
848         (ExprKind::AddrOf(mutability, Box::new(expr)))
849     ));
850 
851     named_ambiguous_expr!(and_assign -> Expr, allow_struct, preceded!(
852         punct!("="),
853         ambiguous_expr!(allow_struct)
854     ));
855 
856     named_ambiguous_expr!(and_assign_op -> (BinOp, Expr), allow_struct, tuple!(
857         assign_op,
858         ambiguous_expr!(allow_struct)
859     ));
860 
861     named!(and_field -> Ident, preceded!(punct!("."), ident));
862 
863     named!(and_tup_field -> u64, preceded!(punct!("."), digits));
864 
865     named!(and_index -> Expr, delimited!(punct!("["), expr, punct!("]")));
866 
867     named_ambiguous_expr!(and_range -> (RangeLimits, Option<Expr>), allow_struct, tuple!(
868         range_limits,
869         option!(call!(ambiguous_expr, allow_struct, false))
870     ));
871 
872     named!(pub block -> Block, do_parse!(
873         punct!("{") >>
874         stmts: within_block >>
875         punct!("}") >>
876         (Block {
877             stmts: stmts,
878         })
879     ));
880 
881     named!(pub within_block -> Vec<Stmt>, do_parse!(
882         many0!(punct!(";")) >>
883         mut standalone: many0!(terminated!(stmt, many0!(punct!(";")))) >>
884         last: option!(expr) >>
885         (match last {
886             None => standalone,
887             Some(last) => {
888                 standalone.push(Stmt::Expr(Box::new(last)));
889                 standalone
890             }
891         })
892     ));
893 
894     named!(pub stmt -> Stmt, alt!(
895         stmt_mac
896         |
897         stmt_local
898         |
899         stmt_item
900         |
901         stmt_expr
902     ));
903 
904     named!(stmt_mac -> Stmt, do_parse!(
905         attrs: many0!(outer_attr) >>
906         what: path >>
907         punct!("!") >>
908     // Only parse braces here; paren and bracket will get parsed as
909     // expression statements
910         punct!("{") >>
911         tts: token_trees >>
912         punct!("}") >>
913         semi: option!(punct!(";")) >>
914         (Stmt::Mac(Box::new((
915             Mac {
916                 path: what,
917                 tts: vec![TokenTree::Delimited(Delimited {
918                     delim: DelimToken::Brace,
919                     tts: tts,
920                 })],
921             },
922             if semi.is_some() {
923                 MacStmtStyle::Semicolon
924             } else {
925                 MacStmtStyle::Braces
926             },
927             attrs,
928         ))))
929     ));
930 
931     named!(stmt_local -> Stmt, do_parse!(
932         attrs: many0!(outer_attr) >>
933         keyword!("let") >>
934         pat: pat >>
935         ty: option!(preceded!(punct!(":"), ty)) >>
936         init: option!(preceded!(punct!("="), expr)) >>
937         punct!(";") >>
938         (Stmt::Local(Box::new(Local {
939             pat: Box::new(pat),
940             ty: ty.map(Box::new),
941             init: init.map(Box::new),
942             attrs: attrs,
943         })))
944     ));
945 
946     named!(stmt_item -> Stmt, map!(item, |i| Stmt::Item(Box::new(i))));
947 
requires_semi(e: &Expr) -> bool948     fn requires_semi(e: &Expr) -> bool {
949         match e.node {
950             ExprKind::If(_, _, _) |
951             ExprKind::IfLet(_, _, _, _) |
952             ExprKind::While(_, _, _) |
953             ExprKind::WhileLet(_, _, _, _) |
954             ExprKind::ForLoop(_, _, _, _) |
955             ExprKind::Loop(_, _) |
956             ExprKind::Match(_, _) |
957             ExprKind::Block(_, _) => false,
958 
959             _ => true,
960         }
961     }
962 
963     named!(stmt_expr -> Stmt, do_parse!(
964         attrs: many0!(outer_attr) >>
965         mut e: expr >>
966         semi: option!(punct!(";")) >>
967         ({
968             e.attrs = attrs;
969             if semi.is_some() {
970                 Stmt::Semi(Box::new(e))
971             } else if requires_semi(&e) {
972                 return Error;
973             } else {
974                 Stmt::Expr(Box::new(e))
975             }
976         })
977     ));
978 
979     named!(pub pat -> Pat, alt!(
980         pat_wild // must be before pat_ident
981         |
982         pat_box // must be before pat_ident
983         |
984         pat_range // must be before pat_lit
985         |
986         pat_tuple_struct // must be before pat_ident
987         |
988         pat_struct // must be before pat_ident
989         |
990         pat_mac // must be before pat_ident
991         |
992         pat_lit // must be before pat_ident
993         |
994         pat_ident // must be before pat_path
995         |
996         pat_path
997         |
998         pat_tuple
999         |
1000         pat_ref
1001         |
1002         pat_slice
1003     ));
1004 
1005     named!(pat_mac -> Pat, map!(mac, Pat::Mac));
1006 
1007     named!(pat_wild -> Pat, map!(keyword!("_"), |_| Pat::Wild));
1008 
1009     named!(pat_box -> Pat, do_parse!(
1010         keyword!("box") >>
1011         pat: pat >>
1012         (Pat::Box(Box::new(pat)))
1013     ));
1014 
1015     named!(pat_ident -> Pat, do_parse!(
1016         mode: option!(keyword!("ref")) >>
1017         mutability: mutability >>
1018         name: alt!(
1019             ident
1020             |
1021             keyword!("self") => { Into::into }
1022         ) >>
1023         not!(punct!("<")) >>
1024         not!(punct!("::")) >>
1025         subpat: option!(preceded!(punct!("@"), pat)) >>
1026         (Pat::Ident(
1027             if mode.is_some() {
1028                 BindingMode::ByRef(mutability)
1029             } else {
1030                 BindingMode::ByValue(mutability)
1031             },
1032             name,
1033             subpat.map(Box::new),
1034         ))
1035     ));
1036 
1037     named!(pat_tuple_struct -> Pat, do_parse!(
1038         path: path >>
1039         tuple: pat_tuple_helper >>
1040         (Pat::TupleStruct(path, tuple.0, tuple.1))
1041     ));
1042 
1043     named!(pat_struct -> Pat, do_parse!(
1044         path: path >>
1045         punct!("{") >>
1046         fields: separated_list!(punct!(","), field_pat) >>
1047         more: option!(preceded!(
1048             cond!(!fields.is_empty(), punct!(",")),
1049             punct!("..")
1050         )) >>
1051         cond!(!fields.is_empty() && more.is_none(), option!(punct!(","))) >>
1052         punct!("}") >>
1053         (Pat::Struct(path, fields, more.is_some()))
1054     ));
1055 
1056     named!(field_pat -> FieldPat, alt!(
1057         do_parse!(
1058             ident: wordlike >>
1059             punct!(":") >>
1060             pat: pat >>
1061             (FieldPat {
1062                 ident: ident,
1063                 pat: Box::new(pat),
1064                 is_shorthand: false,
1065                 attrs: Vec::new(),
1066             })
1067         )
1068         |
1069         do_parse!(
1070             boxed: option!(keyword!("box")) >>
1071             mode: option!(keyword!("ref")) >>
1072             mutability: mutability >>
1073             ident: ident >>
1074             ({
1075                 let mut pat = Pat::Ident(
1076                     if mode.is_some() {
1077                         BindingMode::ByRef(mutability)
1078                     } else {
1079                         BindingMode::ByValue(mutability)
1080                     },
1081                     ident.clone(),
1082                     None,
1083                 );
1084                 if boxed.is_some() {
1085                     pat = Pat::Box(Box::new(pat));
1086                 }
1087                 FieldPat {
1088                     ident: ident,
1089                     pat: Box::new(pat),
1090                     is_shorthand: true,
1091                     attrs: Vec::new(),
1092                 }
1093             })
1094         )
1095     ));
1096 
1097     named!(pat_path -> Pat, map!(qpath, |(qself, path)| Pat::Path(qself, path)));
1098 
1099     named!(pat_tuple -> Pat, map!(
1100         pat_tuple_helper,
1101         |(pats, dotdot)| Pat::Tuple(pats, dotdot)
1102     ));
1103 
1104     named!(pat_tuple_helper -> (Vec<Pat>, Option<usize>), do_parse!(
1105         punct!("(") >>
1106         mut elems: separated_list!(punct!(","), pat) >>
1107         dotdot: option!(do_parse!(
1108             cond!(!elems.is_empty(), punct!(",")) >>
1109             punct!("..") >>
1110             rest: many0!(preceded!(punct!(","), pat)) >>
1111             cond!(!rest.is_empty(), option!(punct!(","))) >>
1112             (rest)
1113         )) >>
1114         cond!(!elems.is_empty() && dotdot.is_none(), option!(punct!(","))) >>
1115         punct!(")") >>
1116         (match dotdot {
1117             Some(rest) => {
1118                 let pos = elems.len();
1119                 elems.extend(rest);
1120                 (elems, Some(pos))
1121             }
1122             None => (elems, None),
1123         })
1124     ));
1125 
1126     named!(pat_ref -> Pat, do_parse!(
1127         punct!("&") >>
1128         mutability: mutability >>
1129         pat: pat >>
1130         (Pat::Ref(Box::new(pat), mutability))
1131     ));
1132 
1133     named!(pat_lit -> Pat, do_parse!(
1134         lit: pat_lit_expr >>
1135         (if let ExprKind::Path(_, _) = lit.node {
1136             return IResult::Error; // these need to be parsed by pat_path
1137         } else {
1138             Pat::Lit(Box::new(lit))
1139         })
1140     ));
1141 
1142     named!(pat_range -> Pat, do_parse!(
1143         lo: pat_lit_expr >>
1144         punct!("...") >>
1145         hi: pat_lit_expr >>
1146         (Pat::Range(Box::new(lo), Box::new(hi)))
1147     ));
1148 
1149     named!(pat_lit_expr -> Expr, do_parse!(
1150         neg: option!(punct!("-")) >>
1151         v: alt!(
1152             lit => { ExprKind::Lit }
1153             |
1154             path => { |p| ExprKind::Path(None, p) }
1155         ) >>
1156         (if neg.is_some() {
1157             ExprKind::Unary(UnOp::Neg, Box::new(v.into())).into()
1158         } else {
1159             v.into()
1160         })
1161     ));
1162 
1163     named!(pat_slice -> Pat, do_parse!(
1164         punct!("[") >>
1165         mut before: separated_list!(punct!(","), pat) >>
1166         after: option!(do_parse!(
1167             comma_before_dots: option!(cond_reduce!(!before.is_empty(), punct!(","))) >>
1168             punct!("..") >>
1169             after: many0!(preceded!(punct!(","), pat)) >>
1170             cond!(!after.is_empty(), option!(punct!(","))) >>
1171             (comma_before_dots.is_some(), after)
1172         )) >>
1173         cond!(after.is_none(), option!(punct!(","))) >>
1174         punct!("]") >>
1175         (match after {
1176             None => Pat::Slice(before, None, Vec::new()),
1177             Some((true, after)) => {
1178                 if before.is_empty() {
1179                     return IResult::Error;
1180                 }
1181                 Pat::Slice(before, Some(Box::new(Pat::Wild)), after)
1182             }
1183             Some((false, after)) => {
1184                 let rest = before.pop().unwrap_or(Pat::Wild);
1185                 Pat::Slice(before, Some(Box::new(rest)), after)
1186             }
1187         })
1188     ));
1189 
1190     named!(capture_by -> CaptureBy, alt!(
1191         keyword!("move") => { |_| CaptureBy::Value }
1192         |
1193         epsilon!() => { |_| CaptureBy::Ref }
1194     ));
1195 
1196     named!(label -> Ident, map!(lifetime, |lt: Lifetime| lt.ident));
1197 }
1198 
1199 #[cfg(feature = "printing")]
1200 mod printing {
1201     use super::*;
1202     use {FnArg, FunctionRetTy, Mutability, Ty, Unsafety};
1203     use attr::FilterAttrs;
1204     use quote::{Tokens, ToTokens};
1205 
1206     impl ToTokens for Expr {
to_tokens(&self, tokens: &mut Tokens)1207         fn to_tokens(&self, tokens: &mut Tokens) {
1208             tokens.append_all(self.attrs.outer());
1209             match self.node {
1210                 ExprKind::Box(ref inner) => {
1211                     tokens.append("box");
1212                     inner.to_tokens(tokens);
1213                 }
1214                 ExprKind::InPlace(ref place, ref value) => {
1215                     tokens.append("in");
1216                     place.to_tokens(tokens);
1217                     value.to_tokens(tokens);
1218                 }
1219                 ExprKind::Array(ref tys) => {
1220                     tokens.append("[");
1221                     tokens.append_separated(tys, ",");
1222                     tokens.append("]");
1223                 }
1224                 ExprKind::Call(ref func, ref args) => {
1225                     func.to_tokens(tokens);
1226                     tokens.append("(");
1227                     tokens.append_separated(args, ",");
1228                     tokens.append(")");
1229                 }
1230                 ExprKind::MethodCall(ref ident, ref ascript, ref args) => {
1231                     args[0].to_tokens(tokens);
1232                     tokens.append(".");
1233                     ident.to_tokens(tokens);
1234                     if !ascript.is_empty() {
1235                         tokens.append("::");
1236                         tokens.append("<");
1237                         tokens.append_separated(ascript, ",");
1238                         tokens.append(">");
1239                     }
1240                     tokens.append("(");
1241                     tokens.append_separated(&args[1..], ",");
1242                     tokens.append(")");
1243                 }
1244                 ExprKind::Tup(ref fields) => {
1245                     tokens.append("(");
1246                     tokens.append_separated(fields, ",");
1247                     if fields.len() == 1 {
1248                         tokens.append(",");
1249                     }
1250                     tokens.append(")");
1251                 }
1252                 ExprKind::Binary(op, ref left, ref right) => {
1253                     left.to_tokens(tokens);
1254                     op.to_tokens(tokens);
1255                     right.to_tokens(tokens);
1256                 }
1257                 ExprKind::Unary(op, ref expr) => {
1258                     op.to_tokens(tokens);
1259                     expr.to_tokens(tokens);
1260                 }
1261                 ExprKind::Lit(ref lit) => lit.to_tokens(tokens),
1262                 ExprKind::Cast(ref expr, ref ty) => {
1263                     expr.to_tokens(tokens);
1264                     tokens.append("as");
1265                     ty.to_tokens(tokens);
1266                 }
1267                 ExprKind::Type(ref expr, ref ty) => {
1268                     expr.to_tokens(tokens);
1269                     tokens.append(":");
1270                     ty.to_tokens(tokens);
1271                 }
1272                 ExprKind::If(ref cond, ref then_block, ref else_block) => {
1273                     tokens.append("if");
1274                     cond.to_tokens(tokens);
1275                     then_block.to_tokens(tokens);
1276                     if let Some(ref else_block) = *else_block {
1277                         tokens.append("else");
1278                         else_block.to_tokens(tokens);
1279                     }
1280                 }
1281                 ExprKind::IfLet(ref pat, ref expr, ref then_block, ref else_block) => {
1282                     tokens.append("if");
1283                     tokens.append("let");
1284                     pat.to_tokens(tokens);
1285                     tokens.append("=");
1286                     expr.to_tokens(tokens);
1287                     then_block.to_tokens(tokens);
1288                     if let Some(ref else_block) = *else_block {
1289                         tokens.append("else");
1290                         else_block.to_tokens(tokens);
1291                     }
1292                 }
1293                 ExprKind::While(ref cond, ref body, ref label) => {
1294                     if let Some(ref label) = *label {
1295                         label.to_tokens(tokens);
1296                         tokens.append(":");
1297                     }
1298                     tokens.append("while");
1299                     cond.to_tokens(tokens);
1300                     body.to_tokens(tokens);
1301                 }
1302                 ExprKind::WhileLet(ref pat, ref expr, ref body, ref label) => {
1303                     if let Some(ref label) = *label {
1304                         label.to_tokens(tokens);
1305                         tokens.append(":");
1306                     }
1307                     tokens.append("while");
1308                     tokens.append("let");
1309                     pat.to_tokens(tokens);
1310                     tokens.append("=");
1311                     expr.to_tokens(tokens);
1312                     body.to_tokens(tokens);
1313                 }
1314                 ExprKind::ForLoop(ref pat, ref expr, ref body, ref label) => {
1315                     if let Some(ref label) = *label {
1316                         label.to_tokens(tokens);
1317                         tokens.append(":");
1318                     }
1319                     tokens.append("for");
1320                     pat.to_tokens(tokens);
1321                     tokens.append("in");
1322                     expr.to_tokens(tokens);
1323                     body.to_tokens(tokens);
1324                 }
1325                 ExprKind::Loop(ref body, ref label) => {
1326                     if let Some(ref label) = *label {
1327                         label.to_tokens(tokens);
1328                         tokens.append(":");
1329                     }
1330                     tokens.append("loop");
1331                     body.to_tokens(tokens);
1332                 }
1333                 ExprKind::Match(ref expr, ref arms) => {
1334                     tokens.append("match");
1335                     expr.to_tokens(tokens);
1336                     tokens.append("{");
1337                     tokens.append_all(arms);
1338                     tokens.append("}");
1339                 }
1340                 ExprKind::Closure(capture, ref decl, ref expr) => {
1341                     capture.to_tokens(tokens);
1342                     tokens.append("|");
1343                     for (i, input) in decl.inputs.iter().enumerate() {
1344                         if i > 0 {
1345                             tokens.append(",");
1346                         }
1347                         match *input {
1348                             FnArg::Captured(ref pat, Ty::Infer) => {
1349                                 pat.to_tokens(tokens);
1350                             }
1351                             _ => input.to_tokens(tokens),
1352                         }
1353                     }
1354                     tokens.append("|");
1355                     match decl.output {
1356                         FunctionRetTy::Default => { /* nothing */ }
1357                         FunctionRetTy::Ty(ref ty) => {
1358                             tokens.append("->");
1359                             ty.to_tokens(tokens);
1360                         }
1361                     }
1362                     expr.to_tokens(tokens);
1363                 }
1364                 ExprKind::Block(rules, ref block) => {
1365                     rules.to_tokens(tokens);
1366                     block.to_tokens(tokens);
1367                 }
1368                 ExprKind::Assign(ref var, ref expr) => {
1369                     var.to_tokens(tokens);
1370                     tokens.append("=");
1371                     expr.to_tokens(tokens);
1372                 }
1373                 ExprKind::AssignOp(op, ref var, ref expr) => {
1374                     var.to_tokens(tokens);
1375                     tokens.append(op.assign_op().unwrap());
1376                     expr.to_tokens(tokens);
1377                 }
1378                 ExprKind::Field(ref expr, ref field) => {
1379                     expr.to_tokens(tokens);
1380                     tokens.append(".");
1381                     field.to_tokens(tokens);
1382                 }
1383                 ExprKind::TupField(ref expr, field) => {
1384                     expr.to_tokens(tokens);
1385                     tokens.append(".");
1386                     tokens.append(&field.to_string());
1387                 }
1388                 ExprKind::Index(ref expr, ref index) => {
1389                     expr.to_tokens(tokens);
1390                     tokens.append("[");
1391                     index.to_tokens(tokens);
1392                     tokens.append("]");
1393                 }
1394                 ExprKind::Range(ref from, ref to, limits) => {
1395                     from.to_tokens(tokens);
1396                     match limits {
1397                         RangeLimits::HalfOpen => tokens.append(".."),
1398                         RangeLimits::Closed => tokens.append("..."),
1399                     }
1400                     to.to_tokens(tokens);
1401                 }
1402                 ExprKind::Path(None, ref path) => path.to_tokens(tokens),
1403                 ExprKind::Path(Some(ref qself), ref path) => {
1404                     tokens.append("<");
1405                     qself.ty.to_tokens(tokens);
1406                     if qself.position > 0 {
1407                         tokens.append("as");
1408                         for (i, segment) in path.segments
1409                                 .iter()
1410                                 .take(qself.position)
1411                                 .enumerate() {
1412                             if i > 0 || path.global {
1413                                 tokens.append("::");
1414                             }
1415                             segment.to_tokens(tokens);
1416                         }
1417                     }
1418                     tokens.append(">");
1419                     for segment in path.segments.iter().skip(qself.position) {
1420                         tokens.append("::");
1421                         segment.to_tokens(tokens);
1422                     }
1423                 }
1424                 ExprKind::AddrOf(mutability, ref expr) => {
1425                     tokens.append("&");
1426                     mutability.to_tokens(tokens);
1427                     expr.to_tokens(tokens);
1428                 }
1429                 ExprKind::Break(ref opt_label, ref opt_val) => {
1430                     tokens.append("break");
1431                     opt_label.to_tokens(tokens);
1432                     opt_val.to_tokens(tokens);
1433                 }
1434                 ExprKind::Continue(ref opt_label) => {
1435                     tokens.append("continue");
1436                     opt_label.to_tokens(tokens);
1437                 }
1438                 ExprKind::Ret(ref opt_expr) => {
1439                     tokens.append("return");
1440                     opt_expr.to_tokens(tokens);
1441                 }
1442                 ExprKind::Mac(ref mac) => mac.to_tokens(tokens),
1443                 ExprKind::Struct(ref path, ref fields, ref base) => {
1444                     path.to_tokens(tokens);
1445                     tokens.append("{");
1446                     tokens.append_separated(fields, ",");
1447                     if let Some(ref base) = *base {
1448                         if !fields.is_empty() {
1449                             tokens.append(",");
1450                         }
1451                         tokens.append("..");
1452                         base.to_tokens(tokens);
1453                     }
1454                     tokens.append("}");
1455                 }
1456                 ExprKind::Repeat(ref expr, ref times) => {
1457                     tokens.append("[");
1458                     expr.to_tokens(tokens);
1459                     tokens.append(";");
1460                     times.to_tokens(tokens);
1461                     tokens.append("]");
1462                 }
1463                 ExprKind::Paren(ref expr) => {
1464                     tokens.append("(");
1465                     expr.to_tokens(tokens);
1466                     tokens.append(")");
1467                 }
1468                 ExprKind::Try(ref expr) => {
1469                     expr.to_tokens(tokens);
1470                     tokens.append("?");
1471                 }
1472             }
1473         }
1474     }
1475 
1476     impl ToTokens for FieldValue {
to_tokens(&self, tokens: &mut Tokens)1477         fn to_tokens(&self, tokens: &mut Tokens) {
1478             self.ident.to_tokens(tokens);
1479             if !self.is_shorthand {
1480                 tokens.append(":");
1481                 self.expr.to_tokens(tokens);
1482             }
1483         }
1484     }
1485 
1486     impl ToTokens for Arm {
to_tokens(&self, tokens: &mut Tokens)1487         fn to_tokens(&self, tokens: &mut Tokens) {
1488             for attr in &self.attrs {
1489                 attr.to_tokens(tokens);
1490             }
1491             tokens.append_separated(&self.pats, "|");
1492             if let Some(ref guard) = self.guard {
1493                 tokens.append("if");
1494                 guard.to_tokens(tokens);
1495             }
1496             tokens.append("=>");
1497             self.body.to_tokens(tokens);
1498             match self.body.node {
1499                 ExprKind::Block(Unsafety::Normal, _) => {
1500                     // no comma
1501                 }
1502                 _ => tokens.append(","),
1503             }
1504         }
1505     }
1506 
1507     impl ToTokens for Pat {
to_tokens(&self, tokens: &mut Tokens)1508         fn to_tokens(&self, tokens: &mut Tokens) {
1509             match *self {
1510                 Pat::Wild => tokens.append("_"),
1511                 Pat::Ident(mode, ref ident, ref subpat) => {
1512                     mode.to_tokens(tokens);
1513                     ident.to_tokens(tokens);
1514                     if let Some(ref subpat) = *subpat {
1515                         tokens.append("@");
1516                         subpat.to_tokens(tokens);
1517                     }
1518                 }
1519                 Pat::Struct(ref path, ref fields, dots) => {
1520                     path.to_tokens(tokens);
1521                     tokens.append("{");
1522                     tokens.append_separated(fields, ",");
1523                     if dots {
1524                         if !fields.is_empty() {
1525                             tokens.append(",");
1526                         }
1527                         tokens.append("..");
1528                     }
1529                     tokens.append("}");
1530                 }
1531                 Pat::TupleStruct(ref path, ref pats, dotpos) => {
1532                     path.to_tokens(tokens);
1533                     tokens.append("(");
1534                     match dotpos {
1535                         Some(pos) => {
1536                             if pos > 0 {
1537                                 tokens.append_separated(&pats[..pos], ",");
1538                                 tokens.append(",");
1539                             }
1540                             tokens.append("..");
1541                             if pos < pats.len() {
1542                                 tokens.append(",");
1543                                 tokens.append_separated(&pats[pos..], ",");
1544                             }
1545                         }
1546                         None => tokens.append_separated(pats, ","),
1547                     }
1548                     tokens.append(")");
1549                 }
1550                 Pat::Path(None, ref path) => path.to_tokens(tokens),
1551                 Pat::Path(Some(ref qself), ref path) => {
1552                     tokens.append("<");
1553                     qself.ty.to_tokens(tokens);
1554                     if qself.position > 0 {
1555                         tokens.append("as");
1556                         for (i, segment) in path.segments
1557                                 .iter()
1558                                 .take(qself.position)
1559                                 .enumerate() {
1560                             if i > 0 || path.global {
1561                                 tokens.append("::");
1562                             }
1563                             segment.to_tokens(tokens);
1564                         }
1565                     }
1566                     tokens.append(">");
1567                     for segment in path.segments.iter().skip(qself.position) {
1568                         tokens.append("::");
1569                         segment.to_tokens(tokens);
1570                     }
1571                 }
1572                 Pat::Tuple(ref pats, dotpos) => {
1573                     tokens.append("(");
1574                     match dotpos {
1575                         Some(pos) => {
1576                             if pos > 0 {
1577                                 tokens.append_separated(&pats[..pos], ",");
1578                                 tokens.append(",");
1579                             }
1580                             tokens.append("..");
1581                             if pos < pats.len() {
1582                                 tokens.append(",");
1583                                 tokens.append_separated(&pats[pos..], ",");
1584                             }
1585                         }
1586                         None => {
1587                             tokens.append_separated(pats, ",");
1588                             if pats.len() == 1 {
1589                                 tokens.append(",");
1590                             }
1591                         }
1592                     }
1593                     tokens.append(")");
1594                 }
1595                 Pat::Box(ref inner) => {
1596                     tokens.append("box");
1597                     inner.to_tokens(tokens);
1598                 }
1599                 Pat::Ref(ref target, mutability) => {
1600                     tokens.append("&");
1601                     mutability.to_tokens(tokens);
1602                     target.to_tokens(tokens);
1603                 }
1604                 Pat::Lit(ref lit) => lit.to_tokens(tokens),
1605                 Pat::Range(ref lo, ref hi) => {
1606                     lo.to_tokens(tokens);
1607                     tokens.append("...");
1608                     hi.to_tokens(tokens);
1609                 }
1610                 Pat::Slice(ref before, ref rest, ref after) => {
1611                     tokens.append("[");
1612                     tokens.append_separated(before, ",");
1613                     if let Some(ref rest) = *rest {
1614                         if !before.is_empty() {
1615                             tokens.append(",");
1616                         }
1617                         if **rest != Pat::Wild {
1618                             rest.to_tokens(tokens);
1619                         }
1620                         tokens.append("..");
1621                         if !after.is_empty() {
1622                             tokens.append(",");
1623                         }
1624                         tokens.append_separated(after, ",");
1625                     }
1626                     tokens.append("]");
1627                 }
1628                 Pat::Mac(ref mac) => mac.to_tokens(tokens),
1629             }
1630         }
1631     }
1632 
1633     impl ToTokens for FieldPat {
to_tokens(&self, tokens: &mut Tokens)1634         fn to_tokens(&self, tokens: &mut Tokens) {
1635             if !self.is_shorthand {
1636                 self.ident.to_tokens(tokens);
1637                 tokens.append(":");
1638             }
1639             self.pat.to_tokens(tokens);
1640         }
1641     }
1642 
1643     impl ToTokens for BindingMode {
to_tokens(&self, tokens: &mut Tokens)1644         fn to_tokens(&self, tokens: &mut Tokens) {
1645             match *self {
1646                 BindingMode::ByRef(Mutability::Immutable) => {
1647                     tokens.append("ref");
1648                 }
1649                 BindingMode::ByRef(Mutability::Mutable) => {
1650                     tokens.append("ref");
1651                     tokens.append("mut");
1652                 }
1653                 BindingMode::ByValue(Mutability::Immutable) => {}
1654                 BindingMode::ByValue(Mutability::Mutable) => {
1655                     tokens.append("mut");
1656                 }
1657             }
1658         }
1659     }
1660 
1661     impl ToTokens for CaptureBy {
to_tokens(&self, tokens: &mut Tokens)1662         fn to_tokens(&self, tokens: &mut Tokens) {
1663             match *self {
1664                 CaptureBy::Value => tokens.append("move"),
1665                 CaptureBy::Ref => {
1666                     // nothing
1667                 }
1668             }
1669         }
1670     }
1671 
1672     impl ToTokens for Block {
to_tokens(&self, tokens: &mut Tokens)1673         fn to_tokens(&self, tokens: &mut Tokens) {
1674             tokens.append("{");
1675             tokens.append_all(&self.stmts);
1676             tokens.append("}");
1677         }
1678     }
1679 
1680     impl ToTokens for Stmt {
to_tokens(&self, tokens: &mut Tokens)1681         fn to_tokens(&self, tokens: &mut Tokens) {
1682             match *self {
1683                 Stmt::Local(ref local) => local.to_tokens(tokens),
1684                 Stmt::Item(ref item) => item.to_tokens(tokens),
1685                 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
1686                 Stmt::Semi(ref expr) => {
1687                     expr.to_tokens(tokens);
1688                     tokens.append(";");
1689                 }
1690                 Stmt::Mac(ref mac) => {
1691                     let (ref mac, style, ref attrs) = **mac;
1692                     tokens.append_all(attrs.outer());
1693                     mac.to_tokens(tokens);
1694                     match style {
1695                         MacStmtStyle::Semicolon => tokens.append(";"),
1696                         MacStmtStyle::Braces | MacStmtStyle::NoBraces => {
1697                             // no semicolon
1698                         }
1699                     }
1700                 }
1701             }
1702         }
1703     }
1704 
1705     impl ToTokens for Local {
to_tokens(&self, tokens: &mut Tokens)1706         fn to_tokens(&self, tokens: &mut Tokens) {
1707             tokens.append_all(self.attrs.outer());
1708             tokens.append("let");
1709             self.pat.to_tokens(tokens);
1710             if let Some(ref ty) = self.ty {
1711                 tokens.append(":");
1712                 ty.to_tokens(tokens);
1713             }
1714             if let Some(ref init) = self.init {
1715                 tokens.append("=");
1716                 init.to_tokens(tokens);
1717             }
1718             tokens.append(";");
1719         }
1720     }
1721 }
1722