4 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
6 /// Type of the expression.
9 /// Attributes tagged on the expression.
10 pub attrs
: Vec
<Attribute
>,
13 impl From
<ExprKind
> for Expr
{
14 fn from(node
: ExprKind
) -> Expr
{
22 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
24 /// A `box x` expression.
27 /// First expr is the place; second expr is the value.
29 /// E.g. 'plae <- val'.
30 InPlace(Box
<Expr
>, Box
<Expr
>),
32 /// An array, e.g. `[a, b, c, d]`.
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
>),
41 /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
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).
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.
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
>),
55 /// A tuple, e.g. `(a, b, c, d)`.
58 /// A binary operation, e.g. `a + b`, `a * b`.
59 Binary(BinOp
, Box
<Expr
>, Box
<Expr
>),
61 /// A unary operation, e.g. `!x`, `*x`.
62 Unary(UnOp
, Box
<Expr
>),
64 /// A literal, e.g. `1`, `"foo"`.
67 /// A cast, e.g. `foo as f64`.
68 Cast(Box
<Expr
>, Box
<Ty
>),
70 /// A type ascription, e.g. `foo: f64`.
71 Type(Box
<Expr
>, Box
<Ty
>),
73 /// An `if` block, with an optional else block
75 /// E.g., `if expr { block } else { expr }`
76 If(Box
<Expr
>, Block
, Option
<Box
<Expr
>>),
78 /// An `if let` expression with an optional else block
80 /// E.g., `if let pat = expr { block } else { expr }`
82 /// This is desugared to a `match` expression.
83 IfLet(Box
<Pat
>, Box
<Expr
>, Block
, Option
<Box
<Expr
>>),
85 /// A while loop, with an optional label
87 /// E.g., `'label: while expr { block }`
88 While(Box
<Expr
>, Block
, Option
<Ident
>),
90 /// A while-let loop, with an optional label.
92 /// E.g., `'label: while let pat = expr { block }`
94 /// This is desugared to a combination of `loop` and `match` expressions.
95 WhileLet(Box
<Pat
>, Box
<Expr
>, Block
, Option
<Ident
>),
97 /// A for loop, with an optional label.
99 /// E.g., `'label: for pat in expr { block }`
101 /// This is desugared to a combination of `loop` and `match` expressions.
102 ForLoop(Box
<Pat
>, Box
<Expr
>, Block
, Option
<Ident
>),
104 /// Conditionless loop with an optional label.
106 /// E.g. `'label: loop { block }`
107 Loop(Block
, Option
<Ident
>),
110 Match(Box
<Expr
>, Vec
<Arm
>),
112 /// A closure (for example, `move |a, b, c| a + b + c`)
113 Closure(CaptureBy
, Box
<FnDecl
>, Box
<Expr
>),
115 /// A block (`{ ... }` or `unsafe { ... }`)
116 Block(Unsafety
, Block
),
118 /// An assignment (`a = foo()`)
119 Assign(Box
<Expr
>, Box
<Expr
>),
121 /// An assignment with an operator
123 /// For example, `a += 1`.
124 AssignOp(BinOp
, Box
<Expr
>, Box
<Expr
>),
126 /// Access of a named struct field (`obj.foo`)
127 Field(Box
<Expr
>, Ident
),
129 /// Access of an unnamed field of a struct or tuple-struct
131 /// For example, `foo.0`.
132 TupField(Box
<Expr
>, usize),
134 /// An indexing operation (`foo[2]`)
135 Index(Box
<Expr
>, Box
<Expr
>),
137 /// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`)
138 Range(Option
<Box
<Expr
>>, Option
<Box
<Expr
>>, RangeLimits
),
140 /// Variable reference, possibly containing `::` and/or type
141 /// parameters, e.g. foo::bar::<baz>.
143 /// Optionally "qualified",
144 /// E.g. `<Vec<T> as SomeTrait>::SomeType`.
145 Path(Option
<QSelf
>, Path
),
147 /// A referencing operation (`&a` or `&mut a`)
148 AddrOf(Mutability
, Box
<Expr
>),
150 /// A `break`, with an optional label to break, and an optional expression
151 Break(Option
<Ident
>, Option
<Box
<Expr
>>),
153 /// A `continue`, with an optional label
154 Continue(Option
<Ident
>),
156 /// A `return`, with an optional value to be returned
157 Ret(Option
<Box
<Expr
>>),
159 /// A macro invocation; pre-expansion
162 /// A struct literal expression.
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
>>),
168 /// An array literal constructed from one repeated element.
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
>),
174 /// No-op: used solely so we can pretty-print faithfully
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.
187 /// Value of the field.
190 /// Whether this is a shorthand field, e.g. `Struct { x }`
191 /// instead of `Struct { x: x }`.
192 pub is_shorthand
: bool
,
194 /// Attributes tagged on the field.
195 pub attrs
: Vec
<Attribute
>,
198 /// A Block (`{ .. }`).
200 /// E.g. `{ .. }` as in `fn foo() { .. }`
201 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
203 /// Statements in a block
204 pub stmts
: Vec
<Stmt
>,
207 /// A statement, usually ending in a semicolon.
208 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
210 /// A local (let) binding.
213 /// An item definition.
216 /// Expr without trailing semicolon.
219 /// Expression with trailing semicolon;
222 /// Macro invocation.
223 Mac(Box
<(Mac
, MacStmtStyle
, Vec
<Attribute
>)>),
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![...];`
233 /// The macro statement had braces; e.g. foo! { ... }
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
242 /// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`
243 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
246 pub ty
: Option
<Box
<Ty
>>,
248 /// Initializer expression to set the value, if any
249 pub init
: Option
<Box
<Expr
>>,
250 pub attrs
: Vec
<Attribute
>,
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))]
258 /// Represents a wildcard pattern (`_`)
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
>>),
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
),
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>),
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
),
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>),
288 /// A reference pattern, e.g. `&mut (a, b)`
289 Ref(Box
<Pat
>, Mutability
),
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
301 /// An arm of a 'match'.
303 /// E.g. `0...10 => { println!("match!") }` as in
307 /// 0...10 => { println!("match!") },
311 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
313 pub attrs
: Vec
<Attribute
>,
315 pub guard
: Option
<Box
<Expr
>>,
320 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
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
331 /// Inclusive at the beginning and end
335 /// A single field in a struct pattern
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
344 /// The pattern the field is destructured to
346 pub is_shorthand
: bool
,
347 pub attrs
: Vec
<Attribute
>,
350 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
351 pub enum BindingMode
{
356 #[cfg(feature = "parsing")]
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}
;
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
)*)
381 macro_rules
! ambiguous_expr
{
382 ($i
:expr
, $allow_struct
:ident
) => {
383 ambiguous_expr($i
, $allow_struct
, true)
387 named
!(pub expr
-> Expr
, ambiguous_expr
!(true));
389 named
!(expr_no_struct
-> Expr
, ambiguous_expr
!(false));
391 #[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
392 fn ambiguous_expr(i
: &str, allow_struct
: bool
, allow_block
: bool
) -> IResult
<&str, Expr
> {
396 expr_lit
// must be before expr_struct
398 cond_reduce
!(allow_struct
, expr_struct
) // must be before expr_path
400 expr_paren
// must be before expr_tup
402 expr_mac
// must be before expr_path
404 call
!(expr_break
, allow_struct
) // must be before expr_path
406 expr_continue
// must be before expr_path
408 call
!(expr_ret
, allow_struct
) // must be before expr_path
410 call
!(expr_box
, allow_struct
)
418 call
!(expr_unary
, allow_struct
)
430 call
!(expr_closure
, allow_struct
)
432 cond_reduce
!(allow_block
, expr_block
)
434 call
!(expr_range
, allow_struct
)
438 call
!(expr_addr_of
, allow_struct
)
443 tap
!(args
: and_call
=> {
444 e
= ExprKind
::Call(Box
::new(e
.into()), args
);
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
);
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
));
458 tap
!(ty
: and_cast
=> {
459 e
= ExprKind
::Cast(Box
::new(e
.into()), Box
::new(ty
));
462 tap
!(ty
: and_ascription
=> {
463 e
= ExprKind
::Type(Box
::new(e
.into()), Box
::new(ty
));
466 tap
!(v
: call
!(and_assign
, allow_struct
) => {
467 e
= ExprKind
::Assign(Box
::new(e
.into()), Box
::new(v
));
470 tap
!(more
: call
!(and_assign_op
, allow_struct
) => {
472 e
= ExprKind
::AssignOp(op
, Box
::new(e
.into()), Box
::new(v
));
475 tap
!(field
: and_field
=> {
476 e
= ExprKind
::Field(Box
::new(e
.into()), field
);
479 tap
!(field
: and_tup_field
=> {
480 e
= ExprKind
::TupField(Box
::new(e
.into()), field
as usize);
483 tap
!(i
: and_index
=> {
484 e
= ExprKind
::Index(Box
::new(e
.into()), Box
::new(i
));
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
);
492 tap
!(_try
: punct
!("?") => {
493 e
= ExprKind
::Try(Box
::new(e
.into()));
500 named
!(expr_mac
-> ExprKind
, map
!(mac
, ExprKind
::Mac
));
502 named
!(expr_paren
-> ExprKind
, do_parse
!(
506 (ExprKind
::Paren(Box
::new(e
)))
509 named_ambiguous_expr
!(expr_box
-> ExprKind
, allow_struct
, do_parse
!(
511 inner
: ambiguous_expr
!(allow_struct
) >>
512 (ExprKind
::Box(Box
::new(inner
)))
515 named
!(expr_in_place
-> ExprKind
, do_parse
!(
517 place
: expr_no_struct
>>
519 value
: within_block
>>
523 Box
::new(ExprKind
::Block(Unsafety
::Normal
, Block
{
529 named
!(expr_array
-> ExprKind
, do_parse
!(
531 elems
: terminated_list
!(punct
!(","), expr
) >>
533 (ExprKind
::Array(elems
))
536 named
!(and_call
-> Vec
<Expr
>, do_parse
!(
538 args
: terminated_list
!(punct
!(","), expr
) >>
543 named
!(and_method_call
-> (Ident
, Vec
<Ty
>, Vec
<Expr
>), do_parse
!(
546 ascript
: opt_vec
!(preceded
!(
550 terminated_list
!(punct
!(","), ty
),
555 args
: terminated_list
!(punct
!(","), expr
) >>
557 (method
, ascript
, args
)
560 named
!(expr_tup
-> ExprKind
, do_parse
!(
562 elems
: terminated_list
!(punct
!(","), expr
) >>
564 (ExprKind
::Tup(elems
))
567 named_ambiguous_expr
!(and_binary
-> (BinOp
, Expr
), allow_struct
, tuple
!(
569 ambiguous_expr
!(allow_struct
)
572 named_ambiguous_expr
!(expr_unary
-> ExprKind
, allow_struct
, do_parse
!(
574 operand
: ambiguous_expr
!(allow_struct
) >>
575 (ExprKind
::Unary(operator
, Box
::new(operand
)))
578 named
!(expr_lit
-> ExprKind
, map
!(lit
, ExprKind
::Lit
));
580 named
!(and_cast
-> Ty
, do_parse
!(
586 named
!(and_ascription
-> Ty
, preceded
!(punct
!(":"), ty
));
593 named
!(cond
-> Cond
, alt
!(
598 value
: expr_no_struct
>>
599 (Cond
::Let(pat
, value
))
602 map
!(expr_no_struct
, Cond
::Expr
)
605 named
!(expr_if
-> ExprKind
, do_parse
!(
609 then_block
: within_block
>>
611 else_block
: option
!(preceded
!(
618 else_block
: within_block
>>
620 (ExprKind
::Block(Unsafety
::Normal
, Block
{
627 Cond
::Let(pat
, expr
) => ExprKind
::IfLet(
633 else_block
.map(|els
| Box
::new(els
.into())),
635 Cond
::Expr(cond
) => ExprKind
::If(
640 else_block
.map(|els
| Box
::new(els
.into())),
645 named
!(expr_for_loop
-> ExprKind
, do_parse
!(
646 lbl
: option
!(terminated
!(label
, punct
!(":"))) >>
650 expr
: expr_no_struct
>>
652 (ExprKind
::ForLoop(Box
::new(pat
), Box
::new(expr
), loop_block
, lbl
))
655 named
!(expr_loop
-> ExprKind
, do_parse
!(
656 lbl
: option
!(terminated
!(label
, punct
!(":"))) >>
659 (ExprKind
::Loop(loop_block
, lbl
))
662 named
!(expr_match
-> ExprKind
, do_parse
!(
664 obj
: expr_no_struct
>>
666 mut arms
: many0
!(do_parse
!(
668 cond
!(arm_requires_comma(&arm
), punct
!(",")) >>
669 cond
!(!arm_requires_comma(&arm
), option
!(punct
!(","))) >>
672 last_arm
: option
!(match_arm
) >>
674 (ExprKind
::Match(Box
::new(obj
), {
675 arms
.extend(last_arm
);
680 fn arm_requires_comma(arm
: &Arm
) -> bool
{
681 if let ExprKind
::Block(Unsafety
::Normal
, _
) = arm
.body
.node
{
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
)) >>
694 map
!(block
, |blk
| ExprKind
::Block(Unsafety
::Normal
, blk
).into())
701 guard
: guard
.map(Box
::new
),
702 body
: Box
::new(body
),
706 named_ambiguous_expr
!(expr_closure
-> ExprKind
, allow_struct
, do_parse
!(
707 capture
: capture_by
>>
709 inputs
: terminated_list
!(punct
!(","), closure_arg
) >>
716 (FunctionRetTy
::Ty(ty
), ExprKind
::Block(Unsafety
::Normal
, body
).into())
719 map
!(ambiguous_expr
!(allow_struct
), |e
| (FunctionRetTy
::Default
, e
))
725 output
: ret_and_body
.0,
728 Box
::new(ret_and_body
.1),
732 named
!(closure_arg
-> FnArg
, do_parse
!(
734 ty
: option
!(preceded
!(punct
!(":"), ty
)) >>
735 (FnArg
::Captured(pat
, ty
.unwrap_or(Ty
::Infer
)))
738 named
!(expr_while
-> ExprKind
, do_parse
!(
739 lbl
: option
!(terminated
!(label
, punct
!(":"))) >>
742 while_block
: block
>>
744 Cond
::Let(pat
, expr
) => ExprKind
::WhileLet(
750 Cond
::Expr(cond
) => ExprKind
::While(
758 named
!(expr_continue
-> ExprKind
, do_parse
!(
759 keyword
!("continue") >>
760 lbl
: option
!(label
) >>
761 (ExprKind
::Continue(lbl
))
764 named_ambiguous_expr
!(expr_break
-> ExprKind
, allow_struct
, do_parse
!(
766 lbl
: option
!(label
) >>
767 val
: option
!(call
!(ambiguous_expr
, allow_struct
, false)) >>
768 (ExprKind
::Break(lbl
, val
.map(Box
::new
)))
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
)))
777 named
!(expr_struct
-> ExprKind
, do_parse
!(
780 fields
: separated_list
!(punct
!(","), field_value
) >>
781 base
: option
!(do_parse
!(
782 cond
!(!fields
.is_empty(), punct
!(",")) >>
787 cond
!(!fields
.is_empty() && base
.is_none(), option
!(punct
!(","))) >>
789 (ExprKind
::Struct(path
, fields
, base
.map(Box
::new
)))
792 named
!(field_value
-> FieldValue
, alt
!(
805 map
!(ident
, |name
: Ident
| FieldValue
{
807 expr
: ExprKind
::Path(None
, name
.into()).into(),
813 named
!(expr_repeat
-> ExprKind
, do_parse
!(
819 (ExprKind
::Repeat(Box
::new(value
), Box
::new(times
)))
822 named
!(expr_block
-> ExprKind
, do_parse
!(
825 (ExprKind
::Block(rules
, Block
{
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
))
836 named
!(range_limits
-> RangeLimits
, alt
!(
837 punct
!("...") => { |_| RangeLimits::Closed }
839 punct
!("..") => { |_| RangeLimits::HalfOpen }
842 named
!(expr_path
-> ExprKind
, map
!(qpath
, |(qself
, path
)| ExprKind
::Path(qself
, path
)));
844 named_ambiguous_expr
!(expr_addr_of
-> ExprKind
, allow_struct
, do_parse
!(
846 mutability
: mutability
>>
847 expr
: ambiguous_expr
!(allow_struct
) >>
848 (ExprKind
::AddrOf(mutability
, Box
::new(expr
)))
851 named_ambiguous_expr
!(and_assign
-> Expr
, allow_struct
, preceded
!(
853 ambiguous_expr
!(allow_struct
)
856 named_ambiguous_expr
!(and_assign_op
-> (BinOp
, Expr
), allow_struct
, tuple
!(
858 ambiguous_expr
!(allow_struct
)
861 named
!(and_field
-> Ident
, preceded
!(punct
!("."), ident
));
863 named
!(and_tup_field
-> u64, preceded
!(punct
!("."), digits
));
865 named
!(and_index
-> Expr
, delimited
!(punct
!("["), expr
, punct
!("]")));
867 named_ambiguous_expr
!(and_range
-> (RangeLimits
, Option
<Expr
>), allow_struct
, tuple
!(
869 option
!(call
!(ambiguous_expr
, allow_struct
, false))
872 named
!(pub block
-> Block
, do_parse
!(
874 stmts
: within_block
>>
881 named
!(pub within_block
-> Vec
<Stmt
>, do_parse
!(
882 many0
!(punct
!(";")) >>
883 mut standalone
: many0
!(terminated
!(stmt
, many0
!(punct
!(";")))) >>
884 last
: option
!(expr
) >>
888 standalone
.push(Stmt
::Expr(Box
::new(last
)));
894 named
!(pub stmt
-> Stmt
, alt
!(
904 named
!(stmt_mac
-> Stmt
, do_parse
!(
905 attrs
: many0
!(outer_attr
) >>
908 // Only parse braces here; paren and bracket will get parsed as
909 // expression statements
913 semi
: option
!(punct
!(";")) >>
914 (Stmt
::Mac(Box
::new((
917 tts
: vec
![TokenTree
::Delimited(Delimited
{
918 delim
: DelimToken
::Brace
,
923 MacStmtStyle
::Semicolon
931 named
!(stmt_local
-> Stmt
, do_parse
!(
932 attrs
: many0
!(outer_attr
) >>
935 ty
: option
!(preceded
!(punct
!(":"), ty
)) >>
936 init
: option
!(preceded
!(punct
!("="), expr
)) >>
938 (Stmt
::Local(Box
::new(Local
{
940 ty
: ty
.map(Box
::new
),
941 init
: init
.map(Box
::new
),
946 named
!(stmt_item
-> Stmt
, map
!(item
, |i
| Stmt
::Item(Box
::new(i
))));
948 fn requires_semi(e
: &Expr
) -> bool
{
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,
963 named
!(stmt_expr
-> Stmt
, do_parse
!(
964 attrs
: many0
!(outer_attr
) >>
966 semi
: option
!(punct
!(";")) >>
970 Stmt
::Semi(Box
::new(e
))
971 } else if requires_semi(&e
) {
974 Stmt
::Expr(Box
::new(e
))
979 named
!(pub pat
-> Pat
, alt
!(
980 pat_wild
// must be before pat_ident
982 pat_box
// must be before pat_ident
984 pat_range
// must be before pat_lit
986 pat_tuple_struct
// must be before pat_ident
988 pat_struct
// must be before pat_ident
990 pat_mac
// must be before pat_ident
992 pat_lit
// must be before pat_ident
994 pat_ident
// must be before pat_path
1005 named
!(pat_mac
-> Pat
, map
!(mac
, Pat
::Mac
));
1007 named
!(pat_wild
-> Pat
, map
!(keyword
!("_"), |_
| Pat
::Wild
));
1009 named
!(pat_box
-> Pat
, do_parse
!(
1012 (Pat
::Box(Box
::new(pat
)))
1015 named
!(pat_ident
-> Pat
, do_parse
!(
1016 mode
: option
!(keyword
!("ref")) >>
1017 mutability
: mutability
>>
1021 keyword
!("self") => { Into::into }
1023 not
!(punct
!("<")) >>
1024 not
!(punct
!("::")) >>
1025 subpat
: option
!(preceded
!(punct
!("@"), pat
)) >>
1028 BindingMode
::ByRef(mutability
)
1030 BindingMode
::ByValue(mutability
)
1033 subpat
.map(Box
::new
),
1037 named
!(pat_tuple_struct
-> Pat
, do_parse
!(
1039 tuple
: pat_tuple_helper
>>
1040 (Pat
::TupleStruct(path
, tuple
.0, tuple
.1))
1043 named
!(pat_struct
-> Pat
, do_parse
!(
1046 fields
: separated_list
!(punct
!(","), field_pat
) >>
1047 more
: option
!(preceded
!(
1048 cond
!(!fields
.is_empty(), punct
!(",")),
1051 cond
!(!fields
.is_empty() && more
.is_none(), option
!(punct
!(","))) >>
1053 (Pat
::Struct(path
, fields
, more
.is_some()))
1056 named
!(field_pat
-> FieldPat
, alt
!(
1064 is_shorthand
: false,
1070 boxed
: option
!(keyword
!("box")) >>
1071 mode
: option
!(keyword
!("ref")) >>
1072 mutability
: mutability
>>
1075 let mut pat
= Pat
::Ident(
1077 BindingMode
::ByRef(mutability
)
1079 BindingMode
::ByValue(mutability
)
1084 if boxed
.is_some() {
1085 pat
= Pat
::Box(Box
::new(pat
));
1097 named
!(pat_path
-> Pat
, map
!(qpath
, |(qself
, path
)| Pat
::Path(qself
, path
)));
1099 named
!(pat_tuple
-> Pat
, map
!(
1101 |(pats
, dotdot
)| Pat
::Tuple(pats
, dotdot
)
1104 named
!(pat_tuple_helper
-> (Vec
<Pat
>, Option
<usize>), do_parse
!(
1106 mut elems
: separated_list
!(punct
!(","), pat
) >>
1107 dotdot
: option
!(do_parse
!(
1108 cond
!(!elems
.is_empty(), punct
!(",")) >>
1110 rest
: many0
!(preceded
!(punct
!(","), pat
)) >>
1111 cond
!(!rest
.is_empty(), option
!(punct
!(","))) >>
1114 cond
!(!elems
.is_empty() && dotdot
.is_none(), option
!(punct
!(","))) >>
1118 let pos
= elems
.len();
1122 None
=> (elems
, None
),
1126 named
!(pat_ref
-> Pat
, do_parse
!(
1128 mutability
: mutability
>>
1130 (Pat
::Ref(Box
::new(pat
), mutability
))
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
1138 Pat
::Lit(Box
::new(lit
))
1142 named
!(pat_range
-> Pat
, do_parse
!(
1146 (Pat
::Range(Box
::new(lo
), Box
::new(hi
)))
1149 named
!(pat_lit_expr
-> Expr
, do_parse
!(
1150 neg
: option
!(punct
!("-")) >>
1152 lit
=> { ExprKind::Lit }
1154 path
=> { |p| ExprKind::Path(None, p) }
1157 ExprKind
::Unary(UnOp
::Neg
, Box
::new(v
.into())).into()
1163 named
!(pat_slice
-> Pat
, do_parse
!(
1165 mut before
: separated_list
!(punct
!(","), pat
) >>
1166 after
: option
!(do_parse
!(
1167 comma_before_dots
: option
!(cond_reduce
!(!before
.is_empty(), punct
!(","))) >>
1169 after
: many0
!(preceded
!(punct
!(","), pat
)) >>
1170 cond
!(!after
.is_empty(), option
!(punct
!(","))) >>
1171 (comma_before_dots
.is_some(), after
)
1173 cond
!(after
.is_none(), option
!(punct
!(","))) >>
1176 None
=> Pat
::Slice(before
, None
, Vec
::new()),
1177 Some((true, after
)) => {
1178 if before
.is_empty() {
1179 return IResult
::Error
;
1181 Pat
::Slice(before
, Some(Box
::new(Pat
::Wild
)), after
)
1183 Some((false, after
)) => {
1184 let rest
= before
.pop().unwrap_or(Pat
::Wild
);
1185 Pat
::Slice(before
, Some(Box
::new(rest
)), after
)
1190 named
!(capture_by
-> CaptureBy
, alt
!(
1191 keyword
!("move") => { |_| CaptureBy::Value }
1193 epsilon
!() => { |_| CaptureBy::Ref }
1196 named
!(label
-> Ident
, map
!(lifetime
, |lt
: Lifetime
| lt
.ident
));
1199 #[cfg(feature = "printing")]
1202 use {FnArg, FunctionRetTy, Mutability, Ty, Unsafety}
;
1203 use attr
::FilterAttrs
;
1204 use quote
::{Tokens, ToTokens}
;
1206 impl ToTokens
for Expr
{
1207 fn to_tokens(&self, tokens
: &mut Tokens
) {
1208 tokens
.append_all(self.attrs
.outer());
1210 ExprKind
::Box(ref inner
) => {
1211 tokens
.append("box");
1212 inner
.to_tokens(tokens
);
1214 ExprKind
::InPlace(ref place
, ref value
) => {
1215 tokens
.append("in");
1216 place
.to_tokens(tokens
);
1217 value
.to_tokens(tokens
);
1219 ExprKind
::Array(ref tys
) => {
1221 tokens
.append_separated(tys
, ",");
1224 ExprKind
::Call(ref func
, ref args
) => {
1225 func
.to_tokens(tokens
);
1227 tokens
.append_separated(args
, ",");
1230 ExprKind
::MethodCall(ref ident
, ref ascript
, ref args
) => {
1231 args
[0].to_tokens(tokens
);
1233 ident
.to_tokens(tokens
);
1234 if !ascript
.is_empty() {
1235 tokens
.append("::");
1237 tokens
.append_separated(ascript
, ",");
1241 tokens
.append_separated(&args
[1..], ",");
1244 ExprKind
::Tup(ref fields
) => {
1246 tokens
.append_separated(fields
, ",");
1247 if fields
.len() == 1 {
1252 ExprKind
::Binary(op
, ref left
, ref right
) => {
1253 left
.to_tokens(tokens
);
1254 op
.to_tokens(tokens
);
1255 right
.to_tokens(tokens
);
1257 ExprKind
::Unary(op
, ref expr
) => {
1258 op
.to_tokens(tokens
);
1259 expr
.to_tokens(tokens
);
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
);
1267 ExprKind
::Type(ref expr
, ref ty
) => {
1268 expr
.to_tokens(tokens
);
1270 ty
.to_tokens(tokens
);
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
);
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
);
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
);
1293 ExprKind
::While(ref cond
, ref body
, ref label
) => {
1294 if let Some(ref label
) = *label
{
1295 label
.to_tokens(tokens
);
1298 tokens
.append("while");
1299 cond
.to_tokens(tokens
);
1300 body
.to_tokens(tokens
);
1302 ExprKind
::WhileLet(ref pat
, ref expr
, ref body
, ref label
) => {
1303 if let Some(ref label
) = *label
{
1304 label
.to_tokens(tokens
);
1307 tokens
.append("while");
1308 tokens
.append("let");
1309 pat
.to_tokens(tokens
);
1311 expr
.to_tokens(tokens
);
1312 body
.to_tokens(tokens
);
1314 ExprKind
::ForLoop(ref pat
, ref expr
, ref body
, ref label
) => {
1315 if let Some(ref label
) = *label
{
1316 label
.to_tokens(tokens
);
1319 tokens
.append("for");
1320 pat
.to_tokens(tokens
);
1321 tokens
.append("in");
1322 expr
.to_tokens(tokens
);
1323 body
.to_tokens(tokens
);
1325 ExprKind
::Loop(ref body
, ref label
) => {
1326 if let Some(ref label
) = *label
{
1327 label
.to_tokens(tokens
);
1330 tokens
.append("loop");
1331 body
.to_tokens(tokens
);
1333 ExprKind
::Match(ref expr
, ref arms
) => {
1334 tokens
.append("match");
1335 expr
.to_tokens(tokens
);
1337 tokens
.append_all(arms
);
1340 ExprKind
::Closure(capture
, ref decl
, ref expr
) => {
1341 capture
.to_tokens(tokens
);
1343 for (i
, input
) in decl
.inputs
.iter().enumerate() {
1348 FnArg
::Captured(ref pat
, Ty
::Infer
) => {
1349 pat
.to_tokens(tokens
);
1351 _
=> input
.to_tokens(tokens
),
1356 FunctionRetTy
::Default
=> { /* nothing */ }
1357 FunctionRetTy
::Ty(ref ty
) => {
1358 tokens
.append("->");
1359 ty
.to_tokens(tokens
);
1362 expr
.to_tokens(tokens
);
1364 ExprKind
::Block(rules
, ref block
) => {
1365 rules
.to_tokens(tokens
);
1366 block
.to_tokens(tokens
);
1368 ExprKind
::Assign(ref var
, ref expr
) => {
1369 var
.to_tokens(tokens
);
1371 expr
.to_tokens(tokens
);
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
);
1378 ExprKind
::Field(ref expr
, ref field
) => {
1379 expr
.to_tokens(tokens
);
1381 field
.to_tokens(tokens
);
1383 ExprKind
::TupField(ref expr
, field
) => {
1384 expr
.to_tokens(tokens
);
1386 tokens
.append(&field
.to_string());
1388 ExprKind
::Index(ref expr
, ref index
) => {
1389 expr
.to_tokens(tokens
);
1391 index
.to_tokens(tokens
);
1394 ExprKind
::Range(ref from
, ref to
, limits
) => {
1395 from
.to_tokens(tokens
);
1397 RangeLimits
::HalfOpen
=> tokens
.append(".."),
1398 RangeLimits
::Closed
=> tokens
.append("..."),
1400 to
.to_tokens(tokens
);
1402 ExprKind
::Path(None
, ref path
) => path
.to_tokens(tokens
),
1403 ExprKind
::Path(Some(ref qself
), ref path
) => {
1405 qself
.ty
.to_tokens(tokens
);
1406 if qself
.position
> 0 {
1407 tokens
.append("as");
1408 for (i
, segment
) in path
.segments
1410 .take(qself
.position
)
1412 if i
> 0 || path
.global
{
1413 tokens
.append("::");
1415 segment
.to_tokens(tokens
);
1419 for segment
in path
.segments
.iter().skip(qself
.position
) {
1420 tokens
.append("::");
1421 segment
.to_tokens(tokens
);
1424 ExprKind
::AddrOf(mutability
, ref expr
) => {
1426 mutability
.to_tokens(tokens
);
1427 expr
.to_tokens(tokens
);
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
);
1434 ExprKind
::Continue(ref opt_label
) => {
1435 tokens
.append("continue");
1436 opt_label
.to_tokens(tokens
);
1438 ExprKind
::Ret(ref opt_expr
) => {
1439 tokens
.append("return");
1440 opt_expr
.to_tokens(tokens
);
1442 ExprKind
::Mac(ref mac
) => mac
.to_tokens(tokens
),
1443 ExprKind
::Struct(ref path
, ref fields
, ref base
) => {
1444 path
.to_tokens(tokens
);
1446 tokens
.append_separated(fields
, ",");
1447 if let Some(ref base
) = *base
{
1448 if !fields
.is_empty() {
1451 tokens
.append("..");
1452 base
.to_tokens(tokens
);
1456 ExprKind
::Repeat(ref expr
, ref times
) => {
1458 expr
.to_tokens(tokens
);
1460 times
.to_tokens(tokens
);
1463 ExprKind
::Paren(ref expr
) => {
1465 expr
.to_tokens(tokens
);
1468 ExprKind
::Try(ref expr
) => {
1469 expr
.to_tokens(tokens
);
1476 impl ToTokens
for FieldValue
{
1477 fn to_tokens(&self, tokens
: &mut Tokens
) {
1478 self.ident
.to_tokens(tokens
);
1479 if !self.is_shorthand
{
1481 self.expr
.to_tokens(tokens
);
1486 impl ToTokens
for Arm
{
1487 fn to_tokens(&self, tokens
: &mut Tokens
) {
1488 for attr
in &self.attrs
{
1489 attr
.to_tokens(tokens
);
1491 tokens
.append_separated(&self.pats
, "|");
1492 if let Some(ref guard
) = self.guard
{
1493 tokens
.append("if");
1494 guard
.to_tokens(tokens
);
1496 tokens
.append("=>");
1497 self.body
.to_tokens(tokens
);
1498 match self.body
.node
{
1499 ExprKind
::Block(Unsafety
::Normal
, _
) => {
1502 _
=> tokens
.append(","),
1507 impl ToTokens
for Pat
{
1508 fn to_tokens(&self, tokens
: &mut Tokens
) {
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
{
1516 subpat
.to_tokens(tokens
);
1519 Pat
::Struct(ref path
, ref fields
, dots
) => {
1520 path
.to_tokens(tokens
);
1522 tokens
.append_separated(fields
, ",");
1524 if !fields
.is_empty() {
1527 tokens
.append("..");
1531 Pat
::TupleStruct(ref path
, ref pats
, dotpos
) => {
1532 path
.to_tokens(tokens
);
1537 tokens
.append_separated(&pats
[..pos
], ",");
1540 tokens
.append("..");
1541 if pos
< pats
.len() {
1543 tokens
.append_separated(&pats
[pos
..], ",");
1546 None
=> tokens
.append_separated(pats
, ","),
1550 Pat
::Path(None
, ref path
) => path
.to_tokens(tokens
),
1551 Pat
::Path(Some(ref qself
), ref path
) => {
1553 qself
.ty
.to_tokens(tokens
);
1554 if qself
.position
> 0 {
1555 tokens
.append("as");
1556 for (i
, segment
) in path
.segments
1558 .take(qself
.position
)
1560 if i
> 0 || path
.global
{
1561 tokens
.append("::");
1563 segment
.to_tokens(tokens
);
1567 for segment
in path
.segments
.iter().skip(qself
.position
) {
1568 tokens
.append("::");
1569 segment
.to_tokens(tokens
);
1572 Pat
::Tuple(ref pats
, dotpos
) => {
1577 tokens
.append_separated(&pats
[..pos
], ",");
1580 tokens
.append("..");
1581 if pos
< pats
.len() {
1583 tokens
.append_separated(&pats
[pos
..], ",");
1587 tokens
.append_separated(pats
, ",");
1588 if pats
.len() == 1 {
1595 Pat
::Box(ref inner
) => {
1596 tokens
.append("box");
1597 inner
.to_tokens(tokens
);
1599 Pat
::Ref(ref target
, mutability
) => {
1601 mutability
.to_tokens(tokens
);
1602 target
.to_tokens(tokens
);
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
);
1610 Pat
::Slice(ref before
, ref rest
, ref after
) => {
1612 tokens
.append_separated(before
, ",");
1613 if let Some(ref rest
) = *rest
{
1614 if !before
.is_empty() {
1617 if **rest
!= Pat
::Wild
{
1618 rest
.to_tokens(tokens
);
1620 tokens
.append("..");
1621 if !after
.is_empty() {
1624 tokens
.append_separated(after
, ",");
1628 Pat
::Mac(ref mac
) => mac
.to_tokens(tokens
),
1633 impl ToTokens
for FieldPat
{
1634 fn to_tokens(&self, tokens
: &mut Tokens
) {
1635 if !self.is_shorthand
{
1636 self.ident
.to_tokens(tokens
);
1639 self.pat
.to_tokens(tokens
);
1643 impl ToTokens
for BindingMode
{
1644 fn to_tokens(&self, tokens
: &mut Tokens
) {
1646 BindingMode
::ByRef(Mutability
::Immutable
) => {
1647 tokens
.append("ref");
1649 BindingMode
::ByRef(Mutability
::Mutable
) => {
1650 tokens
.append("ref");
1651 tokens
.append("mut");
1653 BindingMode
::ByValue(Mutability
::Immutable
) => {}
1654 BindingMode
::ByValue(Mutability
::Mutable
) => {
1655 tokens
.append("mut");
1661 impl ToTokens
for CaptureBy
{
1662 fn to_tokens(&self, tokens
: &mut Tokens
) {
1664 CaptureBy
::Value
=> tokens
.append("move"),
1672 impl ToTokens
for Block
{
1673 fn to_tokens(&self, tokens
: &mut Tokens
) {
1675 tokens
.append_all(&self.stmts
);
1680 impl ToTokens
for Stmt
{
1681 fn to_tokens(&self, tokens
: &mut Tokens
) {
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
);
1690 Stmt
::Mac(ref mac
) => {
1691 let (ref mac
, style
, ref attrs
) = **mac
;
1692 tokens
.append_all(attrs
.outer());
1693 mac
.to_tokens(tokens
);
1695 MacStmtStyle
::Semicolon
=> tokens
.append(";"),
1696 MacStmtStyle
::Braces
| MacStmtStyle
::NoBraces
=> {
1705 impl ToTokens
for Local
{
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
{
1712 ty
.to_tokens(tokens
);
1714 if let Some(ref init
) = self.init
{
1716 init
.to_tokens(tokens
);