use super::*;
use proc_macro2::{Span, TokenStream};
use punctuated::Punctuated;
#[cfg(feature = "extra-traits")]
use std::hash::{Hash, Hasher};
#[cfg(all(feature = "parsing", feature = "full"))]
use std::mem;
#[cfg(feature = "extra-traits")]
use tt::TokenStreamHelper;
ast_enum_of_structs! {
pub enum Expr {
pub Box(ExprBox #full {
pub attrs: Vec<Attribute>,
pub box_token: Token![box],
pub expr: Box<Expr>,
}),
pub InPlace(ExprInPlace #full {
pub attrs: Vec<Attribute>,
pub place: Box<Expr>,
pub arrow_token: Token![<-],
pub value: Box<Expr>,
}),
pub Array(ExprArray #full {
pub attrs: Vec<Attribute>,
pub bracket_token: token::Bracket,
pub elems: Punctuated<Expr, Token![,]>,
}),
pub Call(ExprCall {
pub attrs: Vec<Attribute>,
pub func: Box<Expr>,
pub paren_token: token::Paren,
pub args: Punctuated<Expr, Token![,]>,
}),
pub MethodCall(ExprMethodCall #full {
pub attrs: Vec<Attribute>,
pub receiver: Box<Expr>,
pub dot_token: Token![.],
pub method: Ident,
pub turbofish: Option<MethodTurbofish>,
pub paren_token: token::Paren,
pub args: Punctuated<Expr, Token![,]>,
}),
pub Tuple(ExprTuple #full {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub elems: Punctuated<Expr, Token![,]>,
}),
pub Binary(ExprBinary {
pub attrs: Vec<Attribute>,
pub left: Box<Expr>,
pub op: BinOp,
pub right: Box<Expr>,
}),
pub Unary(ExprUnary {
pub attrs: Vec<Attribute>,
pub op: UnOp,
pub expr: Box<Expr>,
}),
pub Lit(ExprLit {
pub attrs: Vec<Attribute>,
pub lit: Lit,
}),
pub Cast(ExprCast {
pub attrs: Vec<Attribute>,
pub expr: Box<Expr>,
pub as_token: Token![as],
pub ty: Box<Type>,
}),
pub Type(ExprType #full {
pub attrs: Vec<Attribute>,
pub expr: Box<Expr>,
pub colon_token: Token![:],
pub ty: Box<Type>,
}),
pub Let(ExprLet #full {
pub attrs: Vec<Attribute>,
pub let_token: Token![let],
pub pats: Punctuated<Pat, Token![|]>,
pub eq_token: Token![=],
pub expr: Box<Expr>,
}),
pub If(ExprIf #full {
pub attrs: Vec<Attribute>,
pub if_token: Token![if],
pub cond: Box<Expr>,
pub then_branch: Block,
pub else_branch: Option<(Token![else], Box<Expr>)>,
}),
pub While(ExprWhile #full {
pub attrs: Vec<Attribute>,
pub label: Option<Label>,
pub while_token: Token![while],
pub cond: Box<Expr>,
pub body: Block,
}),
pub ForLoop(ExprForLoop #full {
pub attrs: Vec<Attribute>,
pub label: Option<Label>,
pub for_token: Token![for],
pub pat: Box<Pat>,
pub in_token: Token![in],
pub expr: Box<Expr>,
pub body: Block,
}),
pub Loop(ExprLoop #full {
pub attrs: Vec<Attribute>,
pub label: Option<Label>,
pub loop_token: Token![loop],
pub body: Block,
}),
pub Match(ExprMatch #full {
pub attrs: Vec<Attribute>,
pub match_token: Token![match],
pub expr: Box<Expr>,
pub brace_token: token::Brace,
pub arms: Vec<Arm>,
}),
pub Closure(ExprClosure #full {
pub attrs: Vec<Attribute>,
pub asyncness: Option<Token![async]>,
pub movability: Option<Token![static]>,
pub capture: Option<Token![move]>,
pub or1_token: Token![|],
pub inputs: Punctuated<FnArg, Token![,]>,
pub or2_token: Token![|],
pub output: ReturnType,
pub body: Box<Expr>,
}),
pub Unsafe(ExprUnsafe #full {
pub attrs: Vec<Attribute>,
pub unsafe_token: Token![unsafe],
pub block: Block,
}),
pub Block(ExprBlock #full {
pub attrs: Vec<Attribute>,
pub label: Option<Label>,
pub block: Block,
}),
pub Assign(ExprAssign #full {
pub attrs: Vec<Attribute>,
pub left: Box<Expr>,
pub eq_token: Token![=],
pub right: Box<Expr>,
}),
pub AssignOp(ExprAssignOp #full {
pub attrs: Vec<Attribute>,
pub left: Box<Expr>,
pub op: BinOp,
pub right: Box<Expr>,
}),
pub Field(ExprField {
pub attrs: Vec<Attribute>,
pub base: Box<Expr>,
pub dot_token: Token![.],
pub member: Member,
}),
pub Index(ExprIndex {
pub attrs: Vec<Attribute>,
pub expr: Box<Expr>,
pub bracket_token: token::Bracket,
pub index: Box<Expr>,
}),
pub Range(ExprRange #full {
pub attrs: Vec<Attribute>,
pub from: Option<Box<Expr>>,
pub limits: RangeLimits,
pub to: Option<Box<Expr>>,
}),
pub Path(ExprPath {
pub attrs: Vec<Attribute>,
pub qself: Option<QSelf>,
pub path: Path,
}),
pub Reference(ExprReference #full {
pub attrs: Vec<Attribute>,
pub and_token: Token![&],
pub mutability: Option<Token![mut]>,
pub expr: Box<Expr>,
}),
pub Break(ExprBreak #full {
pub attrs: Vec<Attribute>,
pub break_token: Token![break],
pub label: Option<Lifetime>,
pub expr: Option<Box<Expr>>,
}),
pub Continue(ExprContinue #full {
pub attrs: Vec<Attribute>,
pub continue_token: Token![continue],
pub label: Option<Lifetime>,
}),
pub Return(ExprReturn #full {
pub attrs: Vec<Attribute>,
pub return_token: Token![return],
pub expr: Option<Box<Expr>>,
}),
pub Macro(ExprMacro #full {
pub attrs: Vec<Attribute>,
pub mac: Macro,
}),
pub Struct(ExprStruct #full {
pub attrs: Vec<Attribute>,
pub path: Path,
pub brace_token: token::Brace,
pub fields: Punctuated<FieldValue, Token![,]>,
pub dot2_token: Option<Token![..]>,
pub rest: Option<Box<Expr>>,
}),
pub Repeat(ExprRepeat #full {
pub attrs: Vec<Attribute>,
pub bracket_token: token::Bracket,
pub expr: Box<Expr>,
pub semi_token: Token![;],
pub len: Box<Expr>,
}),
pub Paren(ExprParen {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub expr: Box<Expr>,
}),
pub Group(ExprGroup #full {
pub attrs: Vec<Attribute>,
pub group_token: token::Group,
pub expr: Box<Expr>,
}),
pub Try(ExprTry #full {
pub attrs: Vec<Attribute>,
pub expr: Box<Expr>,
pub question_token: Token![?],
}),
pub Async(ExprAsync #full {
pub attrs: Vec<Attribute>,
pub async_token: Token![async],
pub capture: Option<Token![move]>,
pub block: Block,
}),
pub TryBlock(ExprTryBlock #full {
pub attrs: Vec<Attribute>,
pub try_token: Token![try],
pub block: Block,
}),
pub Yield(ExprYield #full {
pub attrs: Vec<Attribute>,
pub yield_token: Token![yield],
pub expr: Option<Box<Expr>>,
}),
pub Verbatim(ExprVerbatim #manual_extra_traits {
pub tts: TokenStream,
}),
}
}
#[cfg(feature = "extra-traits")]
impl Eq for ExprVerbatim {}
#[cfg(feature = "extra-traits")]
impl PartialEq for ExprVerbatim {
fn eq(&self, other: &Self) -> bool {
TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
}
}
#[cfg(feature = "extra-traits")]
impl Hash for ExprVerbatim {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
TokenStreamHelper(&self.tts).hash(state);
}
}
impl Expr {
#[cfg(all(feature = "parsing", feature = "full"))]
fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
match *self {
Expr::Box(ExprBox { ref mut attrs, .. })
| Expr::InPlace(ExprInPlace { ref mut attrs, .. })
| Expr::Array(ExprArray { ref mut attrs, .. })
| Expr::Call(ExprCall { ref mut attrs, .. })
| Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
| Expr::Tuple(ExprTuple { ref mut attrs, .. })
| Expr::Binary(ExprBinary { ref mut attrs, .. })
| Expr::Unary(ExprUnary { ref mut attrs, .. })
| Expr::Lit(ExprLit { ref mut attrs, .. })
| Expr::Cast(ExprCast { ref mut attrs, .. })
| Expr::Type(ExprType { ref mut attrs, .. })
| Expr::Let(ExprLet { ref mut attrs, .. })
| Expr::If(ExprIf { ref mut attrs, .. })
| Expr::While(ExprWhile { ref mut attrs, .. })
| Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
| Expr::Loop(ExprLoop { ref mut attrs, .. })
| Expr::Match(ExprMatch { ref mut attrs, .. })
| Expr::Closure(ExprClosure { ref mut attrs, .. })
| Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
| Expr::Block(ExprBlock { ref mut attrs, .. })
| Expr::Assign(ExprAssign { ref mut attrs, .. })
| Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
| Expr::Field(ExprField { ref mut attrs, .. })
| Expr::Index(ExprIndex { ref mut attrs, .. })
| Expr::Range(ExprRange { ref mut attrs, .. })
| Expr::Path(ExprPath { ref mut attrs, .. })
| Expr::Reference(ExprReference { ref mut attrs, .. })
| Expr::Break(ExprBreak { ref mut attrs, .. })
| Expr::Continue(ExprContinue { ref mut attrs, .. })
| Expr::Return(ExprReturn { ref mut attrs, .. })
| Expr::Macro(ExprMacro { ref mut attrs, .. })
| Expr::Struct(ExprStruct { ref mut attrs, .. })
| Expr::Repeat(ExprRepeat { ref mut attrs, .. })
| Expr::Paren(ExprParen { ref mut attrs, .. })
| Expr::Group(ExprGroup { ref mut attrs, .. })
| Expr::Try(ExprTry { ref mut attrs, .. })
| Expr::Async(ExprAsync { ref mut attrs, .. })
| Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
| Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
Expr::Verbatim(_) => Vec::new(),
}
}
}
ast_enum! {
pub enum Member {
Named(Ident),
Unnamed(Index),
}
}
ast_struct! {
pub struct Index #manual_extra_traits {
pub index: u32,
pub span: Span,
}
}
impl From<usize> for Index {
fn from(index: usize) -> Index {
assert!(index < u32::max_value() as usize);
Index {
index: index as u32,
span: Span::call_site(),
}
}
}
#[cfg(feature = "extra-traits")]
impl Eq for Index {}
#[cfg(feature = "extra-traits")]
impl PartialEq for Index {
fn eq(&self, other: &Self) -> bool {
self.index == other.index
}
}
#[cfg(feature = "extra-traits")]
impl Hash for Index {
fn hash<H: Hasher>(&self, state: &mut H) {
self.index.hash(state);
}
}
#[cfg(feature = "full")]
ast_struct! {
pub struct MethodTurbofish {
pub colon2_token: Token![::],
pub lt_token: Token![<],
pub args: Punctuated<GenericMethodArgument, Token![,]>,
pub gt_token: Token![>],
}
}
#[cfg(feature = "full")]
ast_enum! {
pub enum GenericMethodArgument {
Type(Type),
Const(Expr),
}
}
#[cfg(feature = "full")]
ast_struct! {
pub struct FieldValue {
pub attrs: Vec<Attribute>,
pub member: Member,
pub colon_token: Option<Token![:]>,
pub expr: Expr,
}
}
#[cfg(feature = "full")]
ast_struct! {
pub struct Label {
pub name: Lifetime,
pub colon_token: Token![:],
}
}
#[cfg(feature = "full")]
ast_struct! {
pub struct Block {
pub brace_token: token::Brace,
pub stmts: Vec<Stmt>,
}
}
#[cfg(feature = "full")]
ast_enum! {
pub enum Stmt {
Local(Local),
Item(Item),
Expr(Expr),
Semi(Expr, Token![;]),
}
}
#[cfg(feature = "full")]
ast_struct! {
pub struct Local {
pub attrs: Vec<Attribute>,
pub let_token: Token![let],
pub pats: Punctuated<Pat, Token![|]>,
pub ty: Option<(Token![:], Box<Type>)>,
pub init: Option<(Token![=], Box<Expr>)>,
pub semi_token: Token![;],
}
}
#[cfg(feature = "full")]
ast_enum_of_structs! {
pub enum Pat {
pub Wild(PatWild {
pub underscore_token: Token![_],
}),
pub Ident(PatIdent {
pub by_ref: Option<Token![ref]>,
pub mutability: Option<Token![mut]>,
pub ident: Ident,
pub subpat: Option<(Token![@], Box<Pat>)>,
}),
pub Struct(PatStruct {
pub path: Path,
pub brace_token: token::Brace,
pub fields: Punctuated<FieldPat, Token![,]>,
pub dot2_token: Option<Token![..]>,
}),
pub TupleStruct(PatTupleStruct {
pub path: Path,
pub pat: PatTuple,
}),
pub Path(PatPath {
pub qself: Option<QSelf>,
pub path: Path,
}),
pub Tuple(PatTuple {
pub paren_token: token::Paren,
pub front: Punctuated<Pat, Token![,]>,
pub dot2_token: Option<Token![..]>,
pub comma_token: Option<Token![,]>,
pub back: Punctuated<Pat, Token![,]>,
}),
pub Box(PatBox {
pub box_token: Token![box],
pub pat: Box<Pat>,
}),
pub Ref(PatRef {
pub and_token: Token![&],
pub mutability: Option<Token![mut]>,
pub pat: Box<Pat>,
}),
pub Lit(PatLit {
pub expr: Box<Expr>,
}),
pub Range(PatRange {
pub lo: Box<Expr>,
pub limits: RangeLimits,
pub hi: Box<Expr>,
}),
pub Slice(PatSlice {
pub bracket_token: token::Bracket,
pub front: Punctuated<Pat, Token![,]>,
pub middle: Option<Box<Pat>>,
pub dot2_token: Option<Token![..]>,
pub comma_token: Option<Token![,]>,
pub back: Punctuated<Pat, Token![,]>,
}),
pub Macro(PatMacro {
pub mac: Macro,
}),
pub Verbatim(PatVerbatim #manual_extra_traits {
pub tts: TokenStream,
}),
}
}
#[cfg(all(feature = "full", feature = "extra-traits"))]
impl Eq for PatVerbatim {}
#[cfg(all(feature = "full", feature = "extra-traits"))]
impl PartialEq for PatVerbatim {
fn eq(&self, other: &Self) -> bool {
TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
}
}
#[cfg(all(feature = "full", feature = "extra-traits"))]
impl Hash for PatVerbatim {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
TokenStreamHelper(&self.tts).hash(state);
}
}
#[cfg(feature = "full")]
ast_struct! {
pub struct Arm {
pub attrs: Vec<Attribute>,
pub leading_vert: Option<Token![|]>,
pub pats: Punctuated<Pat, Token![|]>,
pub guard: Option<(Token![if], Box<Expr>)>,
pub fat_arrow_token: Token![=>],
pub body: Box<Expr>,
pub comma: Option<Token![,]>,
}
}
#[cfg(feature = "full")]
ast_enum! {
#[cfg_attr(feature = "clone-impls", derive(Copy))]
pub enum RangeLimits {
HalfOpen(Token![..]),
Closed(Token![..=]),
}
}
#[cfg(feature = "full")]
ast_struct! {
pub struct FieldPat {
pub attrs: Vec<Attribute>,
pub member: Member,
pub colon_token: Option<Token![:]>,
pub pat: Box<Pat>,
}
}
#[cfg(any(feature = "parsing", feature = "printing"))]
#[cfg(feature = "full")]
fn requires_terminator(expr: &Expr) -> bool {
match *expr {
Expr::Unsafe(..)
| Expr::Block(..)
| Expr::If(..)
| Expr::Match(..)
| Expr::While(..)
| Expr::Loop(..)
| Expr::ForLoop(..)
| Expr::Async(..)
| Expr::TryBlock(..) => false,
_ => true,
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
#[cfg(feature = "full")]
use ext::IdentExt;
use parse::{Parse, ParseStream, Result};
use path;
#[derive(Copy, Clone)]
pub struct AllowStruct(bool);
#[derive(Copy, Clone, PartialEq, PartialOrd)]
enum Precedence {
Any,
Assign,
Placement,
Range,
Or,
And,
Compare,
BitOr,
BitXor,
BitAnd,
Shift,
Arithmetic,
Term,
Cast,
}
impl Precedence {
fn of(op: &BinOp) -> Self {
match *op {
BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
BinOp::And(_) => Precedence::And,
BinOp::Or(_) => Precedence::Or,
BinOp::BitXor(_) => Precedence::BitXor,
BinOp::BitAnd(_) => Precedence::BitAnd,
BinOp::BitOr(_) => Precedence::BitOr,
BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
BinOp::Eq(_)
| BinOp::Lt(_)
| BinOp::Le(_)
| BinOp::Ne(_)
| BinOp::Ge(_)
| BinOp::Gt(_) => Precedence::Compare,
BinOp::AddEq(_)
| BinOp::SubEq(_)
| BinOp::MulEq(_)
| BinOp::DivEq(_)
| BinOp::RemEq(_)
| BinOp::BitXorEq(_)
| BinOp::BitAndEq(_)
| BinOp::BitOrEq(_)
| BinOp::ShlEq(_)
| BinOp::ShrEq(_) => Precedence::Assign,
}
}
}
impl Parse for Expr {
fn parse(input: ParseStream) -> Result<Self> {
ambiguous_expr(input, AllowStruct(true))
}
}
#[cfg(feature = "full")]
fn expr_no_struct(input: ParseStream) -> Result<Expr> {
ambiguous_expr(input, AllowStruct(false))
}
#[cfg(feature = "full")]
fn parse_expr(
input: ParseStream,
mut lhs: Expr,
allow_struct: AllowStruct,
base: Precedence,
) -> Result<Expr> {
loop {
if input
.fork()
.parse::<BinOp>()
.ok()
.map_or(false, |op| Precedence::of(&op) >= base)
{
let op: BinOp = input.parse()?;
let precedence = Precedence::of(&op);
let mut rhs = unary_expr(input, allow_struct)?;
loop {
let next = peek_precedence(input);
if next > precedence || next == precedence && precedence == Precedence::Assign {
rhs = parse_expr(input, rhs, allow_struct, next)?;
} else {
break;
}
}
lhs = if precedence == Precedence::Assign {
Expr::AssignOp(ExprAssignOp {
attrs: Vec::new(),
left: Box::new(lhs),
op: op,
right: Box::new(rhs),
})
} else {
Expr::Binary(ExprBinary {
attrs: Vec::new(),
left: Box::new(lhs),
op: op,
right: Box::new(rhs),
})
};
} else if Precedence::Assign >= base
&& input.peek(Token![=])
&& !input.peek(Token![==])
&& !input.peek(Token![=>])
{
let eq_token: Token![=] = input.parse()?;
let mut rhs = unary_expr(input, allow_struct)?;
loop {
let next = peek_precedence(input);
if next >= Precedence::Assign {
rhs = parse_expr(input, rhs, allow_struct, next)?;
} else {
break;
}
}
lhs = Expr::Assign(ExprAssign {
attrs: Vec::new(),
left: Box::new(lhs),
eq_token: eq_token,
right: Box::new(rhs),
});
} else if Precedence::Placement >= base && input.peek(Token![<-]) {
let arrow_token: Token![<-] = input.parse()?;
let mut rhs = unary_expr(input, allow_struct)?;
loop {
let next = peek_precedence(input);
if next > Precedence::Placement {
rhs = parse_expr(input, rhs, allow_struct, next)?;
} else {
break;
}
}
lhs = Expr::InPlace(ExprInPlace {
attrs: Vec::new(),
place: Box::new(lhs),
arrow_token: arrow_token,
value: Box::new(rhs),
});
} else if Precedence::Range >= base && input.peek(Token![..]) {
let limits: RangeLimits = input.parse()?;
let rhs = if input.is_empty()
|| input.peek(Token![,])
|| input.peek(Token![;])
|| !allow_struct.0 && input.peek(token::Brace)
{
None
} else {
let mut rhs = unary_expr(input, allow_struct)?;
loop {
let next = peek_precedence(input);
if next > Precedence::Range {
rhs = parse_expr(input, rhs, allow_struct, next)?;
} else {
break;
}
}
Some(rhs)
};
lhs = Expr::Range(ExprRange {
attrs: Vec::new(),
from: Some(Box::new(lhs)),
limits: limits,
to: rhs.map(Box::new),
});
} else if Precedence::Cast >= base && input.peek(Token![as]) {
let as_token: Token![as] = input.parse()?;
let ty = input.call(Type::without_plus)?;
lhs = Expr::Cast(ExprCast {
attrs: Vec::new(),
expr: Box::new(lhs),
as_token: as_token,
ty: Box::new(ty),
});
} else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
let colon_token: Token![:] = input.parse()?;
let ty = input.call(Type::without_plus)?;
lhs = Expr::Type(ExprType {
attrs: Vec::new(),
expr: Box::new(lhs),
colon_token: colon_token,
ty: Box::new(ty),
});
} else {
break;
}
}
Ok(lhs)
}
#[cfg(not(feature = "full"))]
fn parse_expr(
input: ParseStream,
mut lhs: Expr,
allow_struct: AllowStruct,
base: Precedence,
) -> Result<Expr> {
loop {
if input
.fork()
.parse::<BinOp>()
.ok()
.map_or(false, |op| Precedence::of(&op) >= base)
{
let op: BinOp = input.parse()?;
let precedence = Precedence::of(&op);
let mut rhs = unary_expr(input, allow_struct)?;
loop {
let next = peek_precedence(input);
if next > precedence || next == precedence && precedence == Precedence::Assign {
rhs = parse_expr(input, rhs, allow_struct, next)?;
} else {
break;
}
}
lhs = Expr::Binary(ExprBinary {
attrs: Vec::new(),
left: Box::new(lhs),
op: op,
right: Box::new(rhs),
});
} else if Precedence::Cast >= base && input.peek(Token![as]) {
let as_token: Token![as] = input.parse()?;
let ty = input.call(Type::without_plus)?;
lhs = Expr::Cast(ExprCast {
attrs: Vec::new(),
expr: Box::new(lhs),
as_token: as_token,
ty: Box::new(ty),
});
} else {
break;
}
}
Ok(lhs)
}
fn peek_precedence(input: ParseStream) -> Precedence {
if let Ok(op) = input.fork().parse() {
Precedence::of(&op)
} else if input.peek(Token![=]) && !input.peek(Token![=>]) {
Precedence::Assign
} else if input.peek(Token![<-]) {
Precedence::Placement
} else if input.peek(Token![..]) {
Precedence::Range
} else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
Precedence::Cast
} else {
Precedence::Any
}
}
fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
let lhs = unary_expr(input, allow_struct)?;
parse_expr(input, lhs, allow_struct, Precedence::Any)
}
#[cfg(feature = "full")]
fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
let ahead = input.fork();
ahead.call(Attribute::parse_outer)?;
if ahead.peek(Token![&])
|| ahead.peek(Token![box])
|| ahead.peek(Token![*])
|| ahead.peek(Token![!])
|| ahead.peek(Token![-])
{
let attrs = input.call(Attribute::parse_outer)?;
if input.peek(Token![&]) {
Ok(Expr::Reference(ExprReference {
attrs: attrs,
and_token: input.parse()?,
mutability: input.parse()?,
expr: Box::new(unary_expr(input, allow_struct)?),
}))
} else if input.peek(Token![box]) {
Ok(Expr::Box(ExprBox {
attrs: attrs,
box_token: input.parse()?,
expr: Box::new(unary_expr(input, allow_struct)?),
}))
} else {
Ok(Expr::Unary(ExprUnary {
attrs: attrs,
op: input.parse()?,
expr: Box::new(unary_expr(input, allow_struct)?),
}))
}
} else {
trailer_expr(input, allow_struct)
}
}
#[cfg(not(feature = "full"))]
fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
let ahead = input.fork();
ahead.call(Attribute::parse_outer)?;
if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
Ok(Expr::Unary(ExprUnary {
attrs: input.call(Attribute::parse_outer)?,
op: input.parse()?,
expr: Box::new(unary_expr(input, allow_struct)?),
}))
} else {
trailer_expr(input, allow_struct)
}
}
#[cfg(feature = "full")]
fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
if input.peek(token::Group) {
return input.call(expr_group).map(Expr::Group);
}
let outer_attrs = input.call(Attribute::parse_outer)?;
let atom = atom_expr(input, allow_struct)?;
let mut e = trailer_helper(input, atom)?;
let inner_attrs = e.replace_attrs(Vec::new());
let attrs = private::attrs(outer_attrs, inner_attrs);
e.replace_attrs(attrs);
Ok(e)
}
#[cfg(feature = "full")]
fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
loop {
if input.peek(token::Paren) {
let content;
e = Expr::Call(ExprCall {
attrs: Vec::new(),
func: Box::new(e),
paren_token: parenthesized!(content in input),
args: content.parse_terminated(Expr::parse)?,
});
} else if input.peek(Token![.]) && !input.peek(Token![..]) {
let dot_token: Token![.] = input.parse()?;
let member: Member = input.parse()?;
let turbofish = if member.is_named() && input.peek(Token![::]) {
Some(MethodTurbofish {
colon2_token: input.parse()?,
lt_token: input.parse()?,
args: {
let mut args = Punctuated::new();
loop {
if input.peek(Token![>]) {
break;
}
let value = input.call(generic_method_argument)?;
args.push_value(value);
if input.peek(Token![>]) {
break;
}
let punct = input.parse()?;
args.push_punct(punct);
}
args
},
gt_token: input.parse()?,
})
} else {
None
};
if turbofish.is_some() || input.peek(token::Paren) {
if let Member::Named(method) = member {
let content;
e = Expr::MethodCall(ExprMethodCall {
attrs: Vec::new(),
receiver: Box::new(e),
dot_token: dot_token,
method: method,
turbofish: turbofish,
paren_token: parenthesized!(content in input),
args: content.parse_terminated(Expr::parse)?,
});
continue;
}
}
e = Expr::Field(ExprField {
attrs: Vec::new(),
base: Box::new(e),
dot_token: dot_token,
member: member,
});
} else if input.peek(token::Bracket) {
let content;
e = Expr::Index(ExprIndex {
attrs: Vec::new(),
expr: Box::new(e),
bracket_token: bracketed!(content in input),
index: content.parse()?,
});
} else if input.peek(Token![?]) {
e = Expr::Try(ExprTry {
attrs: Vec::new(),
expr: Box::new(e),
question_token: input.parse()?,
});
} else {
break;
}
}
Ok(e)
}
#[cfg(not(feature = "full"))]
fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
let mut e = atom_expr(input, allow_struct)?;
loop {
if input.peek(token::Paren) {
let content;
e = Expr::Call(ExprCall {
attrs: Vec::new(),
func: Box::new(e),
paren_token: parenthesized!(content in input),
args: content.parse_terminated(Expr::parse)?,
});
} else if input.peek(Token![.]) {
e = Expr::Field(ExprField {
attrs: Vec::new(),
base: Box::new(e),
dot_token: input.parse()?,
member: input.parse()?,
});
} else if input.peek(token::Bracket) {
let content;
e = Expr::Index(ExprIndex {
attrs: Vec::new(),
expr: Box::new(e),
bracket_token: bracketed!(content in input),
index: content.parse()?,
});
} else {
break;
}
}
Ok(e)
}
#[cfg(feature = "full")]
fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
if input.peek(token::Group) {
input.call(expr_group).map(Expr::Group)
} else if input.peek(Lit) {
input.call(expr_lit).map(Expr::Lit)
} else if input.peek(Token![async])
&& (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
{
input.call(expr_async).map(Expr::Async)
} else if input.peek(Token![try]) && input.peek2(token::Brace) {
input.call(expr_try_block).map(Expr::TryBlock)
} else if input.peek(Token![|])
|| input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
|| input.peek(Token![static])
|| input.peek(Token![move])
{
expr_closure(input, allow_struct).map(Expr::Closure)
} else if input.peek(Ident)
|| input.peek(Token![::])
|| input.peek(Token![<])
|| input.peek(Token![self])
|| input.peek(Token![Self])
|| input.peek(Token![super])
|| input.peek(Token![extern])
|| input.peek(Token![crate])
{
path_or_macro_or_struct(input, allow_struct)
} else if input.peek(token::Paren) {
paren_or_tuple(input)
} else if input.peek(Token![break]) {
expr_break(input, allow_struct).map(Expr::Break)
} else if input.peek(Token![continue]) {
input.call(expr_continue).map(Expr::Continue)
} else if input.peek(Token![return]) {
expr_ret(input, allow_struct).map(Expr::Return)
} else if input.peek(token::Bracket) {
array_or_repeat(input)
} else if input.peek(Token![let]) {
input.call(expr_let).map(Expr::Let)
} else if input.peek(Token![if]) {
input.call(expr_if).map(Expr::If)
} else if input.peek(Token![while]) {
input.call(expr_while).map(Expr::While)
} else if input.peek(Token![for]) {
input.call(expr_for_loop).map(Expr::ForLoop)
} else if input.peek(Token![loop]) {
input.call(expr_loop).map(Expr::Loop)
} else if input.peek(Token![match]) {
input.call(expr_match).map(Expr::Match)
} else if input.peek(Token![yield]) {
input.call(expr_yield).map(Expr::Yield)
} else if input.peek(Token![unsafe]) {
input.call(expr_unsafe).map(Expr::Unsafe)
} else if input.peek(token::Brace) {
input.call(expr_block).map(Expr::Block)
} else if input.peek(Token![..]) {
expr_range(input, allow_struct).map(Expr::Range)
} else if input.peek(Lifetime) {
let the_label: Label = input.parse()?;
let mut expr = if input.peek(Token![while]) {
Expr::While(input.call(expr_while)?)
} else if input.peek(Token![for]) {
Expr::ForLoop(input.call(expr_for_loop)?)
} else if input.peek(Token![loop]) {
Expr::Loop(input.call(expr_loop)?)
} else if input.peek(token::Brace) {
Expr::Block(input.call(expr_block)?)
} else {
return Err(input.error("expected loop or block expression"));
};
match expr {
Expr::While(ExprWhile { ref mut label, .. })
| Expr::ForLoop(ExprForLoop { ref mut label, .. })
| Expr::Loop(ExprLoop { ref mut label, .. })
| Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
_ => unreachable!(),
}
Ok(expr)
} else {
Err(input.error("expected expression"))
}
}
#[cfg(not(feature = "full"))]
fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
if input.peek(Lit) {
input.call(expr_lit).map(Expr::Lit)
} else if input.peek(token::Paren) {
input.call(expr_paren).map(Expr::Paren)
} else if input.peek(Ident)
|| input.peek(Token![::])
|| input.peek(Token![<])
|| input.peek(Token![self])
|| input.peek(Token![Self])
|| input.peek(Token![super])
|| input.peek(Token![extern])
|| input.peek(Token![crate])
{
input.parse().map(Expr::Path)
} else {
Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
}
}
#[cfg(feature = "full")]
fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
let expr: ExprPath = input.parse()?;
if expr.qself.is_some() {
return Ok(Expr::Path(expr));
}
if input.peek(Token![!]) && !input.peek(Token![!=]) {
let mut contains_arguments = false;
for segment in &expr.path.segments {
match segment.arguments {
PathArguments::None => {}
PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
contains_arguments = true;
}
}
}
if !contains_arguments {
let bang_token: Token![!] = input.parse()?;
let (delimiter, tts) = mac::parse_delimiter(input)?;
return Ok(Expr::Macro(ExprMacro {
attrs: Vec::new(),
mac: Macro {
path: expr.path,
bang_token: bang_token,
delimiter: delimiter,
tts: tts,
},
}));
}
}
if allow_struct.0 && input.peek(token::Brace) {
let outer_attrs = Vec::new();
expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
} else {
Ok(Expr::Path(expr))
}
}
#[cfg(feature = "full")]
fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
let content;
let paren_token = parenthesized!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
if content.is_empty() {
return Ok(Expr::Tuple(ExprTuple {
attrs: inner_attrs,
paren_token: paren_token,
elems: Punctuated::new(),
}));
}
let first: Expr = content.parse()?;
if content.is_empty() {
return Ok(Expr::Paren(ExprParen {
attrs: inner_attrs,
paren_token: paren_token,
expr: Box::new(first),
}));
}
let mut elems = Punctuated::new();
elems.push_value(first);
while !content.is_empty() {
let punct = content.parse()?;
elems.push_punct(punct);
if content.is_empty() {
break;
}
let value = content.parse()?;
elems.push_value(value);
}
Ok(Expr::Tuple(ExprTuple {
attrs: inner_attrs,
paren_token: paren_token,
elems: elems,
}))
}
#[cfg(feature = "full")]
fn array_or_repeat(input: ParseStream) -> Result<Expr> {
let content;
let bracket_token = bracketed!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
if content.is_empty() {
return Ok(Expr::Array(ExprArray {
attrs: inner_attrs,
bracket_token: bracket_token,
elems: Punctuated::new(),
}));
}
let first: Expr = content.parse()?;
if content.is_empty() || content.peek(Token![,]) {
let mut elems = Punctuated::new();
elems.push_value(first);
while !content.is_empty() {
let punct = content.parse()?;
elems.push_punct(punct);
if content.is_empty() {
break;
}
let value = content.parse()?;
elems.push_value(value);
}
Ok(Expr::Array(ExprArray {
attrs: inner_attrs,
bracket_token: bracket_token,
elems: elems,
}))
} else if content.peek(Token![;]) {
let semi_token: Token![;] = content.parse()?;
let len: Expr = content.parse()?;
Ok(Expr::Repeat(ExprRepeat {
attrs: inner_attrs,
bracket_token: bracket_token,
expr: Box::new(first),
semi_token: semi_token,
len: Box::new(len),
}))
} else {
Err(content.error("expected `,` or `;`"))
}
}
#[cfg(feature = "full")]
fn expr_early(input: ParseStream) -> Result<Expr> {
let mut attrs = input.call(Attribute::parse_outer)?;
let mut expr = if input.peek(Token![if]) {
Expr::If(input.call(expr_if)?)
} else if input.peek(Token![while]) {
Expr::While(input.call(expr_while)?)
} else if input.peek(Token![for]) {
Expr::ForLoop(input.call(expr_for_loop)?)
} else if input.peek(Token![loop]) {
Expr::Loop(input.call(expr_loop)?)
} else if input.peek(Token![match]) {
Expr::Match(input.call(expr_match)?)
} else if input.peek(Token![try]) && input.peek2(token::Brace) {
Expr::TryBlock(input.call(expr_try_block)?)
} else if input.peek(Token![unsafe]) {
Expr::Unsafe(input.call(expr_unsafe)?)
} else if input.peek(token::Brace) {
Expr::Block(input.call(expr_block)?)
} else {
let allow_struct = AllowStruct(true);
let mut expr = unary_expr(input, allow_struct)?;
attrs.extend(expr.replace_attrs(Vec::new()));
expr.replace_attrs(attrs);
return parse_expr(input, expr, allow_struct, Precedence::Any);
};
if input.peek(Token![.]) || input.peek(Token![?]) {
expr = trailer_helper(input, expr)?;
attrs.extend(expr.replace_attrs(Vec::new()));
expr.replace_attrs(attrs);
let allow_struct = AllowStruct(true);
return parse_expr(input, expr, allow_struct, Precedence::Any);
}
attrs.extend(expr.replace_attrs(Vec::new()));
expr.replace_attrs(attrs);
Ok(expr)
}
pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
Ok(ExprLit {
attrs: Vec::new(),
lit: input.parse()?,
})
}
#[cfg(feature = "full")]
fn expr_group(input: ParseStream) -> Result<ExprGroup> {
let group = private::parse_group(input)?;
Ok(ExprGroup {
attrs: Vec::new(),
group_token: group.token,
expr: group.content.parse()?,
})
}
#[cfg(not(feature = "full"))]
fn expr_paren(input: ParseStream) -> Result<ExprParen> {
let content;
Ok(ExprParen {
attrs: Vec::new(),
paren_token: parenthesized!(content in input),
expr: content.parse()?,
})
}
#[cfg(feature = "full")]
fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
input.parse().map(GenericMethodArgument::Type)
}
#[cfg(feature = "full")]
fn expr_let(input: ParseStream) -> Result<ExprLet> {
Ok(ExprLet {
attrs: Vec::new(),
let_token: input.parse()?,
pats: {
let mut pats = Punctuated::new();
let value: Pat = input.parse()?;
pats.push_value(value);
while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
let punct = input.parse()?;
pats.push_punct(punct);
let value: Pat = input.parse()?;
pats.push_value(value);
}
pats
},
eq_token: input.parse()?,
expr: Box::new(input.call(expr_no_struct)?),
})
}
#[cfg(feature = "full")]
fn expr_if(input: ParseStream) -> Result<ExprIf> {
Ok(ExprIf {
attrs: Vec::new(),
if_token: input.parse()?,
cond: Box::new(input.call(expr_no_struct)?),
then_branch: input.parse()?,
else_branch: {
if input.peek(Token![else]) {
Some(input.call(else_block)?)
} else {
None
}
},
})
}
#[cfg(feature = "full")]
fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
let else_token: Token![else] = input.parse()?;
let lookahead = input.lookahead1();
let else_branch = if input.peek(Token![if]) {
input.call(expr_if).map(Expr::If)?
} else if input.peek(token::Brace) {
Expr::Block(ExprBlock {
attrs: Vec::new(),
label: None,
block: input.parse()?,
})
} else {
return Err(lookahead.error());
};
Ok((else_token, Box::new(else_branch)))
}
#[cfg(feature = "full")]
fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
let label: Option<Label> = input.parse()?;
let for_token: Token![for] = input.parse()?;
let pat: Pat = input.parse()?;
let in_token: Token![in] = input.parse()?;
let expr: Expr = input.call(expr_no_struct)?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let stmts = content.call(Block::parse_within)?;
Ok(ExprForLoop {
attrs: inner_attrs,
label: label,
for_token: for_token,
pat: Box::new(pat),
in_token: in_token,
expr: Box::new(expr),
body: Block {
brace_token: brace_token,
stmts: stmts,
},
})
}
#[cfg(feature = "full")]
fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
let label: Option<Label> = input.parse()?;
let loop_token: Token![loop] = input.parse()?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let stmts = content.call(Block::parse_within)?;
Ok(ExprLoop {
attrs: inner_attrs,
label: label,
loop_token: loop_token,
body: Block {
brace_token: brace_token,
stmts: stmts,
},
})
}
#[cfg(feature = "full")]
fn expr_match(input: ParseStream) -> Result<ExprMatch> {
let match_token: Token![match] = input.parse()?;
let expr = expr_no_struct(input)?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let mut arms = Vec::new();
while !content.is_empty() {
arms.push(content.call(Arm::parse)?);
}
Ok(ExprMatch {
attrs: inner_attrs,
match_token: match_token,
expr: Box::new(expr),
brace_token: brace_token,
arms: arms,
})
}
#[cfg(feature = "full")]
fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
Ok(ExprTryBlock {
attrs: Vec::new(),
try_token: input.parse()?,
block: input.parse()?,
})
}
#[cfg(feature = "full")]
fn expr_yield(input: ParseStream) -> Result<ExprYield> {
Ok(ExprYield {
attrs: Vec::new(),
yield_token: input.parse()?,
expr: {
if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
Some(input.parse()?)
} else {
None
}
},
})
}
#[cfg(feature = "full")]
fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
let asyncness: Option<Token![async]> = input.parse()?;
let movability: Option<Token![static]> = if asyncness.is_none() {
input.parse()?
} else {
None
};
let capture: Option<Token![move]> = input.parse()?;
let or1_token: Token![|] = input.parse()?;
let mut inputs = Punctuated::new();
loop {
if input.peek(Token![|]) {
break;
}
let value = fn_arg(input)?;
inputs.push_value(value);
if input.peek(Token![|]) {
break;
}
let punct: Token![,] = input.parse()?;
inputs.push_punct(punct);
}
let or2_token: Token![|] = input.parse()?;
let (output, body) = if input.peek(Token![->]) {
let arrow_token: Token![->] = input.parse()?;
let ty: Type = input.parse()?;
let body: Block = input.parse()?;
let output = ReturnType::Type(arrow_token, Box::new(ty));
let block = Expr::Block(ExprBlock {
attrs: Vec::new(),
label: None,
block: body,
});
(output, block)
} else {
let body = ambiguous_expr(input, allow_struct)?;
(ReturnType::Default, body)
};
Ok(ExprClosure {
attrs: Vec::new(),
asyncness: asyncness,
movability: movability,
capture: capture,
or1_token: or1_token,
inputs: inputs,
or2_token: or2_token,
output: output,
body: Box::new(body),
})
}
#[cfg(feature = "full")]
fn expr_async(input: ParseStream) -> Result<ExprAsync> {
Ok(ExprAsync {
attrs: Vec::new(),
async_token: input.parse()?,
capture: input.parse()?,
block: input.parse()?,
})
}
#[cfg(feature = "full")]
fn fn_arg(input: ParseStream) -> Result<FnArg> {
let pat: Pat = input.parse()?;
if input.peek(Token![:]) {
Ok(FnArg::Captured(ArgCaptured {
pat: pat,
colon_token: input.parse()?,
ty: input.parse()?,
}))
} else {
Ok(FnArg::Inferred(pat))
}
}
#[cfg(feature = "full")]
fn expr_while(input: ParseStream) -> Result<ExprWhile> {
let label: Option<Label> = input.parse()?;
let while_token: Token![while] = input.parse()?;
let cond = expr_no_struct(input)?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let stmts = content.call(Block::parse_within)?;
Ok(ExprWhile {
attrs: inner_attrs,
label: label,
while_token: while_token,
cond: Box::new(cond),
body: Block {
brace_token: brace_token,
stmts: stmts,
},
})
}
#[cfg(feature = "full")]
impl Parse for Label {
fn parse(input: ParseStream) -> Result<Self> {
Ok(Label {
name: input.parse()?,
colon_token: input.parse()?,
})
}
}
#[cfg(feature = "full")]
impl Parse for Option<Label> {
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(Lifetime) {
input.parse().map(Some)
} else {
Ok(None)
}
}
}
#[cfg(feature = "full")]
fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
Ok(ExprContinue {
attrs: Vec::new(),
continue_token: input.parse()?,
label: input.parse()?,
})
}
#[cfg(feature = "full")]
fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
Ok(ExprBreak {
attrs: Vec::new(),
break_token: input.parse()?,
label: input.parse()?,
expr: {
if input.is_empty()
|| input.peek(Token![,])
|| input.peek(Token![;])
|| !allow_struct.0 && input.peek(token::Brace)
{
None
} else {
let expr = ambiguous_expr(input, allow_struct)?;
Some(Box::new(expr))
}
},
})
}
#[cfg(feature = "full")]
fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
Ok(ExprReturn {
attrs: Vec::new(),
return_token: input.parse()?,
expr: {
if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
None
} else {
let expr = ambiguous_expr(input, allow_struct)?;
Some(Box::new(expr))
}
},
})
}
#[cfg(feature = "full")]
impl Parse for FieldValue {
fn parse(input: ParseStream) -> Result<Self> {
let member: Member = input.parse()?;
let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
let colon_token: Token![:] = input.parse()?;
let value: Expr = input.parse()?;
(Some(colon_token), value)
} else if let Member::Named(ref ident) = member {
let value = Expr::Path(ExprPath {
attrs: Vec::new(),
qself: None,
path: Path::from(ident.clone()),
});
(None, value)
} else {
unreachable!()
};
Ok(FieldValue {
attrs: Vec::new(),
member: member,
colon_token: colon_token,
expr: value,
})
}
}
#[cfg(feature = "full")]
fn expr_struct_helper(
input: ParseStream,
outer_attrs: Vec<Attribute>,
path: Path,
) -> Result<ExprStruct> {
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let mut fields = Punctuated::new();
loop {
let attrs = content.call(Attribute::parse_outer)?;
if content.fork().parse::<Member>().is_err() {
if attrs.is_empty() {
break;
} else {
return Err(content.error("expected struct field"));
}
}
fields.push(FieldValue {
attrs: attrs,
..content.parse()?
});
if !content.peek(Token![,]) {
break;
}
let punct: Token![,] = content.parse()?;
fields.push_punct(punct);
}
let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
let dot2_token: Token![..] = content.parse()?;
let rest: Expr = content.parse()?;
(Some(dot2_token), Some(Box::new(rest)))
} else {
(None, None)
};
Ok(ExprStruct {
attrs: private::attrs(outer_attrs, inner_attrs),
brace_token: brace_token,
path: path,
fields: fields,
dot2_token: dot2_token,
rest: rest,
})
}
#[cfg(feature = "full")]
fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
let unsafe_token: Token![unsafe] = input.parse()?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let stmts = content.call(Block::parse_within)?;
Ok(ExprUnsafe {
attrs: inner_attrs,
unsafe_token: unsafe_token,
block: Block {
brace_token: brace_token,
stmts: stmts,
},
})
}
#[cfg(feature = "full")]
pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
let label: Option<Label> = input.parse()?;
let content;
let brace_token = braced!(content in input);
let inner_attrs = content.call(Attribute::parse_inner)?;
let stmts = content.call(Block::parse_within)?;
Ok(ExprBlock {
attrs: inner_attrs,
label: label,
block: Block {
brace_token: brace_token,
stmts: stmts,
},
})
}
#[cfg(feature = "full")]
fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
Ok(ExprRange {
attrs: Vec::new(),
from: None,
limits: input.parse()?,
to: {
if input.is_empty()
|| input.peek(Token![,])
|| input.peek(Token![;])
|| !allow_struct.0 && input.peek(token::Brace)
{
None
} else {
let to = ambiguous_expr(input, allow_struct)?;
Some(Box::new(to))
}
},
})
}
#[cfg(feature = "full")]
impl Parse for RangeLimits {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![..=]) {
input.parse().map(RangeLimits::Closed)
} else if lookahead.peek(Token![...]) {
let dot3: Token![...] = input.parse()?;
Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
} else if lookahead.peek(Token![..]) {
input.parse().map(RangeLimits::HalfOpen)
} else {
Err(lookahead.error())
}
}
}
impl Parse for ExprPath {
fn parse(input: ParseStream) -> Result<Self> {
#[cfg(not(feature = "full"))]
let attrs = Vec::new();
#[cfg(feature = "full")]
let attrs = input.call(Attribute::parse_outer)?;
let (qself, path) = path::parsing::qpath(input, true)?;
Ok(ExprPath {
attrs: attrs,
qself: qself,
path: path,
})
}
}
#[cfg(feature = "full")]
impl Parse for Block {
fn parse(input: ParseStream) -> Result<Self> {
let content;
Ok(Block {
brace_token: braced!(content in input),
stmts: content.call(Block::parse_within)?,
})
}
}
#[cfg(feature = "full")]
impl Block {
pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
let mut stmts = Vec::new();
loop {
while input.peek(Token![;]) {
input.parse::<Token![;]>()?;
}
if input.is_empty() {
break;
}
let s = parse_stmt(input, true)?;
let requires_semicolon = if let Stmt::Expr(ref s) = s {
requires_terminator(s)
} else {
false
};
stmts.push(s);
if input.is_empty() {
break;
} else if requires_semicolon {
return Err(input.error("unexpected token"));
}
}
Ok(stmts)
}
}
#[cfg(feature = "full")]
impl Parse for Stmt {
fn parse(input: ParseStream) -> Result<Self> {
parse_stmt(input, false)
}
}
#[cfg(feature = "full")]
fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
let ahead = input.fork();
ahead.call(Attribute::parse_outer)?;
if {
let ahead = ahead.fork();
ahead.call(Path::parse_mod_style).is_ok()
&& ahead.parse::<Token![!]>().is_ok()
&& (ahead.peek(token::Brace) || ahead.peek(Ident))
} {
stmt_mac(input)
} else if ahead.peek(Token![let]) {
stmt_local(input).map(Stmt::Local)
} else if ahead.peek(Token![pub])
|| ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
|| ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
|| ahead.peek(Token![use])
|| ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
|| ahead.peek(Token![const])
|| ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
|| ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
|| ahead.peek(Token![fn])
|| ahead.peek(Token![mod])
|| ahead.peek(Token![type])
|| ahead.peek(Token![existential]) && ahead.peek2(Token![type])
|| ahead.peek(Token![struct])
|| ahead.peek(Token![enum])
|| ahead.peek(Token![union]) && ahead.peek2(Ident)
|| ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
|| ahead.peek(Token![trait])
|| ahead.peek(Token![default])
&& (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl ]))
|| ahead.peek(Token![impl ])
|| ahead.peek(Token![macro])
{
input.parse().map(Stmt::Item)
} else {
stmt_expr(input, allow_nosemi)
}
}
#[cfg(feature = "full")]
fn stmt_mac(input: ParseStream) -> Result<Stmt> {
let attrs = input.call(Attribute::parse_outer)?;
let path = input.call(Path::parse_mod_style)?;
let bang_token: Token![!] = input.parse()?;
let ident: Option<Ident> = input.parse()?;
let (delimiter, tts) = mac::parse_delimiter(input)?;
let semi_token: Option<Token![;]> = input.parse()?;
Ok(Stmt::Item(Item::Macro(ItemMacro {
attrs: attrs,
ident: ident,
mac: Macro {
path: path,
bang_token: bang_token,
delimiter: delimiter,
tts: tts,
},
semi_token: semi_token,
})))
}
#[cfg(feature = "full")]
fn stmt_local(input: ParseStream) -> Result<Local> {
Ok(Local {
attrs: input.call(Attribute::parse_outer)?,
let_token: input.parse()?,
pats: {
let mut pats = Punctuated::new();
let value: Pat = input.parse()?;
pats.push_value(value);
while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
let punct = input.parse()?;
pats.push_punct(punct);
let value: Pat = input.parse()?;
pats.push_value(value);
}
pats
},
ty: {
if input.peek(Token![:]) {
let colon_token: Token![:] = input.parse()?;
let ty: Type = input.parse()?;
Some((colon_token, Box::new(ty)))
} else {
None
}
},
init: {
if input.peek(Token![=]) {
let eq_token: Token![=] = input.parse()?;
let init: Expr = input.parse()?;
Some((eq_token, Box::new(init)))
} else {
None
}
},
semi_token: input.parse()?,
})
}
#[cfg(feature = "full")]
fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
let mut attrs = input.call(Attribute::parse_outer)?;
let mut e = expr_early(input)?;
attrs.extend(e.replace_attrs(Vec::new()));
e.replace_attrs(attrs);
if input.peek(Token![;]) {
return Ok(Stmt::Semi(e, input.parse()?));
}
if allow_nosemi || !requires_terminator(&e) {
Ok(Stmt::Expr(e))
} else {
Err(input.error("expected semicolon"))
}
}
#[cfg(feature = "full")]
impl Parse for Pat {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![_]) {
input.call(pat_wild).map(Pat::Wild)
} else if lookahead.peek(Token![box]) {
input.call(pat_box).map(Pat::Box)
} else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
pat_lit_or_range(input)
} else if input.peek(Ident)
&& ({
input.peek2(Token![::])
|| input.peek2(Token![!])
|| input.peek2(token::Brace)
|| input.peek2(token::Paren)
|| input.peek2(Token![..])
&& !{
let ahead = input.fork();
ahead.parse::<Ident>()?;
ahead.parse::<RangeLimits>()?;
ahead.is_empty() || ahead.peek(Token![,])
}
})
|| input.peek(Token![self]) && input.peek2(Token![::])
|| input.peek(Token![::])
|| input.peek(Token![<])
|| input.peek(Token![Self])
|| input.peek(Token![super])
|| input.peek(Token![extern])
|| input.peek(Token![crate])
{
pat_path_or_macro_or_struct_or_range(input)
} else if input.peek(Token![ref])
|| input.peek(Token![mut])
|| input.peek(Token![self])
|| input.peek(Ident)
{
input.call(pat_ident).map(Pat::Ident)
} else if lookahead.peek(token::Paren) {
input.call(pat_tuple).map(Pat::Tuple)
} else if lookahead.peek(Token![&]) {
input.call(pat_ref).map(Pat::Ref)
} else if lookahead.peek(token::Bracket) {
input.call(pat_slice).map(Pat::Slice)
} else {
Err(lookahead.error())
}
}
}
#[cfg(feature = "full")]
fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
let (qself, path) = path::parsing::qpath(input, true)?;
if input.peek(Token![..]) {
return pat_range(input, qself, path).map(Pat::Range);
}
if qself.is_some() {
return Ok(Pat::Path(PatPath {
qself: qself,
path: path,
}));
}
if input.peek(Token![!]) && !input.peek(Token![!=]) {
let mut contains_arguments = false;
for segment in &path.segments {
match segment.arguments {
PathArguments::None => {}
PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
contains_arguments = true;
}
}
}
if !contains_arguments {
let bang_token: Token![!] = input.parse()?;
let (delimiter, tts) = mac::parse_delimiter(input)?;
return Ok(Pat::Macro(PatMacro {
mac: Macro {
path: path,
bang_token: bang_token,
delimiter: delimiter,
tts: tts,
},
}));
}
}
if input.peek(token::Brace) {
pat_struct(input, path).map(Pat::Struct)
} else if input.peek(token::Paren) {
pat_tuple_struct(input, path).map(Pat::TupleStruct)
} else if input.peek(Token![..]) {
pat_range(input, qself, path).map(Pat::Range)
} else {
Ok(Pat::Path(PatPath {
qself: qself,
path: path,
}))
}
}
#[cfg(feature = "full")]
fn pat_wild(input: ParseStream) -> Result<PatWild> {
Ok(PatWild {
underscore_token: input.parse()?,
})
}
#[cfg(feature = "full")]
fn pat_box(input: ParseStream) -> Result<PatBox> {
Ok(PatBox {
box_token: input.parse()?,
pat: input.parse()?,
})
}
#[cfg(feature = "full")]
fn pat_ident(input: ParseStream) -> Result<PatIdent> {
Ok(PatIdent {
by_ref: input.parse()?,
mutability: input.parse()?,
ident: input.call(Ident::parse_any)?,
subpat: {
if input.peek(Token![@]) {
let at_token: Token![@] = input.parse()?;
let subpat: Pat = input.parse()?;
Some((at_token, Box::new(subpat)))
} else {
None
}
},
})
}
#[cfg(feature = "full")]
fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
Ok(PatTupleStruct {
path: path,
pat: input.call(pat_tuple)?,
})
}
#[cfg(feature = "full")]
fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
let content;
let brace_token = braced!(content in input);
let mut fields = Punctuated::new();
while !content.is_empty() && !content.peek(Token![..]) {
let value = content.call(field_pat)?;
fields.push_value(value);
if !content.peek(Token![,]) {
break;
}
let punct: Token![,] = content.parse()?;
fields.push_punct(punct);
}
let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
Some(content.parse()?)
} else {
None
};
Ok(PatStruct {
path: path,
brace_token: brace_token,
fields: fields,
dot2_token: dot2_token,
})
}
#[cfg(feature = "full")]
fn field_pat(input: ParseStream) -> Result<FieldPat> {
let boxed: Option<Token![box]> = input.parse()?;
let by_ref: Option<Token![ref]> = input.parse()?;
let mutability: Option<Token![mut]> = input.parse()?;
let member: Member = input.parse()?;
if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
|| member.is_unnamed()
{
return Ok(FieldPat {
attrs: Vec::new(),
member: member,
colon_token: input.parse()?,
pat: input.parse()?,
});
}
let ident = match member {
Member::Named(ident) => ident,
Member::Unnamed(_) => unreachable!(),
};
let mut pat = Pat::Ident(PatIdent {
by_ref: by_ref,
mutability: mutability,
ident: ident.clone(),
subpat: None,
});
if let Some(boxed) = boxed {
pat = Pat::Box(PatBox {
pat: Box::new(pat),
box_token: boxed,
});
}
Ok(FieldPat {
member: Member::Named(ident),
pat: Box::new(pat),
attrs: Vec::new(),
colon_token: None,
})
}
impl Parse for Member {
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(Ident) {
input.parse().map(Member::Named)
} else if input.peek(LitInt) {
input.parse().map(Member::Unnamed)
} else {
Err(input.error("expected identifier or integer"))
}
}
}
#[cfg(feature = "full")]
impl Parse for Arm {
fn parse(input: ParseStream) -> Result<Arm> {
let requires_comma;
Ok(Arm {
attrs: input.call(Attribute::parse_outer)?,
leading_vert: input.parse()?,
pats: {
let mut pats = Punctuated::new();
let value: Pat = input.parse()?;
pats.push_value(value);
loop {
if !input.peek(Token![|]) {
break;
}
let punct = input.parse()?;
pats.push_punct(punct);
let value: Pat = input.parse()?;
pats.push_value(value);
}
pats
},
guard: {
if input.peek(Token![if]) {
let if_token: Token![if] = input.parse()?;
let guard: Expr = input.parse()?;
Some((if_token, Box::new(guard)))
} else {
None
}
},
fat_arrow_token: input.parse()?,
body: {
let body = input.call(expr_early)?;
requires_comma = requires_terminator(&body);
Box::new(body)
},
comma: {
if requires_comma && !input.is_empty() {
Some(input.parse()?)
} else {
input.parse()?
}
},
})
}
}
impl Parse for Index {
fn parse(input: ParseStream) -> Result<Self> {
let lit: LitInt = input.parse()?;
if let IntSuffix::None = lit.suffix() {
Ok(Index {
index: lit.value() as u32,
span: lit.span(),
})
} else {
Err(Error::new(lit.span(), "expected unsuffixed integer"))
}
}
}
#[cfg(feature = "full")]
fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
Ok(PatRange {
lo: Box::new(Expr::Path(ExprPath {
attrs: Vec::new(),
qself: qself,
path: path,
})),
limits: input.parse()?,
hi: input.call(pat_lit_expr)?,
})
}
#[cfg(feature = "full")]
fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
let content;
let paren_token = parenthesized!(content in input);
let mut front = Punctuated::new();
let mut dot2_token = None::<Token![..]>;
let mut comma_token = None::<Token![,]>;
loop {
if content.is_empty() {
break;
}
if content.peek(Token![..]) {
dot2_token = Some(content.parse()?);
comma_token = content.parse()?;
break;
}
let value: Pat = content.parse()?;
front.push_value(value);
if content.is_empty() {
break;
}
let punct = content.parse()?;
front.push_punct(punct);
}
let mut back = Punctuated::new();
while !content.is_empty() {
let value: Pat = content.parse()?;
back.push_value(value);
if content.is_empty() {
break;
}
let punct = content.parse()?;
back.push_punct(punct);
}
Ok(PatTuple {
paren_token: paren_token,
front: front,
dot2_token: dot2_token,
comma_token: comma_token,
back: back,
})
}
#[cfg(feature = "full")]
fn pat_ref(input: ParseStream) -> Result<PatRef> {
Ok(PatRef {
and_token: input.parse()?,
mutability: input.parse()?,
pat: input.parse()?,
})
}
#[cfg(feature = "full")]
fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
let lo = input.call(pat_lit_expr)?;
if input.peek(Token![..]) {
Ok(Pat::Range(PatRange {
lo: lo,
limits: input.parse()?,
hi: input.call(pat_lit_expr)?,
}))
} else {
Ok(Pat::Lit(PatLit { expr: lo }))
}
}
#[cfg(feature = "full")]
fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
let neg: Option<Token![-]> = input.parse()?;
let lookahead = input.lookahead1();
let expr = if lookahead.peek(Lit) {
Expr::Lit(input.call(expr_lit)?)
} else if lookahead.peek(Ident)
|| lookahead.peek(Token![::])
|| lookahead.peek(Token![<])
|| lookahead.peek(Token![self])
|| lookahead.peek(Token![Self])
|| lookahead.peek(Token![super])
|| lookahead.peek(Token![extern])
|| lookahead.peek(Token![crate])
{
Expr::Path(input.parse()?)
} else {
return Err(lookahead.error());
};
Ok(Box::new(if let Some(neg) = neg {
Expr::Unary(ExprUnary {
attrs: Vec::new(),
op: UnOp::Neg(neg),
expr: Box::new(expr),
})
} else {
expr
}))
}
#[cfg(feature = "full")]
fn pat_slice(input: ParseStream) -> Result<PatSlice> {
let content;
let bracket_token = bracketed!(content in input);
let mut front = Punctuated::new();
let mut middle = None;
loop {
if content.is_empty() || content.peek(Token![..]) {
break;
}
let value: Pat = content.parse()?;
if content.peek(Token![..]) {
middle = Some(Box::new(value));
break;
}
front.push_value(value);
if content.is_empty() {
break;
}
let punct = content.parse()?;
front.push_punct(punct);
}
let dot2_token: Option<Token![..]> = content.parse()?;
let mut comma_token = None::<Token![,]>;
let mut back = Punctuated::new();
if dot2_token.is_some() {
comma_token = content.parse()?;
if comma_token.is_some() {
loop {
if content.is_empty() {
break;
}
let value: Pat = content.parse()?;
back.push_value(value);
if content.is_empty() {
break;
}
let punct = content.parse()?;
back.push_punct(punct);
}
}
}
Ok(PatSlice {
bracket_token: bracket_token,
front: front,
middle: middle,
dot2_token: dot2_token,
comma_token: comma_token,
back: back,
})
}
#[cfg(feature = "full")]
impl Member {
fn is_named(&self) -> bool {
match *self {
Member::Named(_) => true,
Member::Unnamed(_) => false,
}
}
fn is_unnamed(&self) -> bool {
match *self {
Member::Named(_) => false,
Member::Unnamed(_) => true,
}
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use proc_macro2::{Literal, TokenStream};
use quote::{ToTokens, TokenStreamExt};
#[cfg(feature = "full")]
use attr::FilterAttrs;
#[cfg(feature = "full")]
use print::TokensOrDefault;
#[cfg(feature = "full")]
fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
if let Expr::Struct(_) = *e {
token::Paren::default().surround(tokens, |tokens| {
e.to_tokens(tokens);
});
} else {
e.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
tokens.append_all(attrs.outer());
}
#[cfg(feature = "full")]
fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
tokens.append_all(attrs.inner());
}
#[cfg(not(feature = "full"))]
fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
#[cfg(not(feature = "full"))]
fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
#[cfg(feature = "full")]
impl ToTokens for ExprBox {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.box_token.to_tokens(tokens);
self.expr.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprInPlace {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.place.to_tokens(tokens);
self.arrow_token.to_tokens(tokens);
self.value.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprArray {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.bracket_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
self.elems.to_tokens(tokens);
})
}
}
impl ToTokens for ExprCall {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.func.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
self.args.to_tokens(tokens);
})
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprMethodCall {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.receiver.to_tokens(tokens);
self.dot_token.to_tokens(tokens);
self.method.to_tokens(tokens);
self.turbofish.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
self.args.to_tokens(tokens);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for MethodTurbofish {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.colon2_token.to_tokens(tokens);
self.lt_token.to_tokens(tokens);
self.args.to_tokens(tokens);
self.gt_token.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for GenericMethodArgument {
fn to_tokens(&self, tokens: &mut TokenStream) {
match *self {
GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
}
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprTuple {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.paren_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
self.elems.to_tokens(tokens);
if self.elems.len() == 1 && !self.elems.trailing_punct() {
<Token![,]>::default().to_tokens(tokens);
}
})
}
}
impl ToTokens for ExprBinary {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.left.to_tokens(tokens);
self.op.to_tokens(tokens);
self.right.to_tokens(tokens);
}
}
impl ToTokens for ExprUnary {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.op.to_tokens(tokens);
self.expr.to_tokens(tokens);
}
}
impl ToTokens for ExprLit {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.lit.to_tokens(tokens);
}
}
impl ToTokens for ExprCast {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.expr.to_tokens(tokens);
self.as_token.to_tokens(tokens);
self.ty.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprType {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.expr.to_tokens(tokens);
self.colon_token.to_tokens(tokens);
self.ty.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
if let Some((ref else_token, ref else_)) = *else_ {
else_token.to_tokens(tokens);
match **else_ {
Expr::If(_) | Expr::Block(_) => {
else_.to_tokens(tokens);
}
_ => {
token::Brace::default().surround(tokens, |tokens| {
else_.to_tokens(tokens);
});
}
}
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprLet {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.let_token.to_tokens(tokens);
self.pats.to_tokens(tokens);
self.eq_token.to_tokens(tokens);
wrap_bare_struct(tokens, &self.expr);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprIf {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.if_token.to_tokens(tokens);
wrap_bare_struct(tokens, &self.cond);
self.then_branch.to_tokens(tokens);
maybe_wrap_else(tokens, &self.else_branch);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprWhile {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.label.to_tokens(tokens);
self.while_token.to_tokens(tokens);
wrap_bare_struct(tokens, &self.cond);
self.body.brace_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
tokens.append_all(&self.body.stmts);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprForLoop {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.label.to_tokens(tokens);
self.for_token.to_tokens(tokens);
self.pat.to_tokens(tokens);
self.in_token.to_tokens(tokens);
wrap_bare_struct(tokens, &self.expr);
self.body.brace_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
tokens.append_all(&self.body.stmts);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprLoop {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.label.to_tokens(tokens);
self.loop_token.to_tokens(tokens);
self.body.brace_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
tokens.append_all(&self.body.stmts);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprMatch {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.match_token.to_tokens(tokens);
wrap_bare_struct(tokens, &self.expr);
self.brace_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
for (i, arm) in self.arms.iter().enumerate() {
arm.to_tokens(tokens);
let is_last = i == self.arms.len() - 1;
if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
<Token![,]>::default().to_tokens(tokens);
}
}
});
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprAsync {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.async_token.to_tokens(tokens);
self.capture.to_tokens(tokens);
self.block.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprTryBlock {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.try_token.to_tokens(tokens);
self.block.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprYield {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.yield_token.to_tokens(tokens);
self.expr.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprClosure {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.asyncness.to_tokens(tokens);
self.movability.to_tokens(tokens);
self.capture.to_tokens(tokens);
self.or1_token.to_tokens(tokens);
for input in self.inputs.pairs() {
match **input.value() {
FnArg::Captured(ArgCaptured {
ref pat,
ty: Type::Infer(_),
..
}) => {
pat.to_tokens(tokens);
}
_ => input.value().to_tokens(tokens),
}
input.punct().to_tokens(tokens);
}
self.or2_token.to_tokens(tokens);
self.output.to_tokens(tokens);
self.body.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprUnsafe {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.unsafe_token.to_tokens(tokens);
self.block.brace_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
tokens.append_all(&self.block.stmts);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprBlock {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.label.to_tokens(tokens);
self.block.brace_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
tokens.append_all(&self.block.stmts);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprAssign {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.left.to_tokens(tokens);
self.eq_token.to_tokens(tokens);
self.right.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprAssignOp {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.left.to_tokens(tokens);
self.op.to_tokens(tokens);
self.right.to_tokens(tokens);
}
}
impl ToTokens for ExprField {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.base.to_tokens(tokens);
self.dot_token.to_tokens(tokens);
self.member.to_tokens(tokens);
}
}
impl ToTokens for Member {
fn to_tokens(&self, tokens: &mut TokenStream) {
match *self {
Member::Named(ref ident) => ident.to_tokens(tokens),
Member::Unnamed(ref index) => index.to_tokens(tokens),
}
}
}
impl ToTokens for Index {
fn to_tokens(&self, tokens: &mut TokenStream) {
let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
lit.set_span(self.span);
tokens.append(lit);
}
}
impl ToTokens for ExprIndex {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.expr.to_tokens(tokens);
self.bracket_token.surround(tokens, |tokens| {
self.index.to_tokens(tokens);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprRange {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.from.to_tokens(tokens);
match self.limits {
RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
RangeLimits::Closed(ref t) => t.to_tokens(tokens),
}
self.to.to_tokens(tokens);
}
}
impl ToTokens for ExprPath {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
private::print_path(tokens, &self.qself, &self.path);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprReference {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.and_token.to_tokens(tokens);
self.mutability.to_tokens(tokens);
self.expr.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprBreak {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.break_token.to_tokens(tokens);
self.label.to_tokens(tokens);
self.expr.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprContinue {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.continue_token.to_tokens(tokens);
self.label.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprReturn {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.return_token.to_tokens(tokens);
self.expr.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprMacro {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.mac.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.path.to_tokens(tokens);
self.brace_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
self.fields.to_tokens(tokens);
if self.rest.is_some() {
TokensOrDefault(&self.dot2_token).to_tokens(tokens);
self.rest.to_tokens(tokens);
}
})
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprRepeat {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.bracket_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
self.expr.to_tokens(tokens);
self.semi_token.to_tokens(tokens);
self.len.to_tokens(tokens);
})
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprGroup {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.group_token.surround(tokens, |tokens| {
self.expr.to_tokens(tokens);
});
}
}
impl ToTokens for ExprParen {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.paren_token.surround(tokens, |tokens| {
inner_attrs_to_tokens(&self.attrs, tokens);
self.expr.to_tokens(tokens);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for ExprTry {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.expr.to_tokens(tokens);
self.question_token.to_tokens(tokens);
}
}
impl ToTokens for ExprVerbatim {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.tts.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for Label {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.name.to_tokens(tokens);
self.colon_token.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for FieldValue {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.member.to_tokens(tokens);
if let Some(ref colon_token) = self.colon_token {
colon_token.to_tokens(tokens);
self.expr.to_tokens(tokens);
}
}
}
#[cfg(feature = "full")]
impl ToTokens for Arm {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(&self.attrs);
self.leading_vert.to_tokens(tokens);
self.pats.to_tokens(tokens);
if let Some((ref if_token, ref guard)) = self.guard {
if_token.to_tokens(tokens);
guard.to_tokens(tokens);
}
self.fat_arrow_token.to_tokens(tokens);
self.body.to_tokens(tokens);
self.comma.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatWild {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.underscore_token.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatIdent {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.by_ref.to_tokens(tokens);
self.mutability.to_tokens(tokens);
self.ident.to_tokens(tokens);
if let Some((ref at_token, ref subpat)) = self.subpat {
at_token.to_tokens(tokens);
subpat.to_tokens(tokens);
}
}
}
#[cfg(feature = "full")]
impl ToTokens for PatStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.path.to_tokens(tokens);
self.brace_token.surround(tokens, |tokens| {
self.fields.to_tokens(tokens);
if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
<Token![,]>::default().to_tokens(tokens);
}
self.dot2_token.to_tokens(tokens);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for PatTupleStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.path.to_tokens(tokens);
self.pat.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatPath {
fn to_tokens(&self, tokens: &mut TokenStream) {
private::print_path(tokens, &self.qself, &self.path);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatTuple {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.paren_token.surround(tokens, |tokens| {
self.front.to_tokens(tokens);
if let Some(ref dot2_token) = self.dot2_token {
if !self.front.empty_or_trailing() {
<Token![,]>::default().to_tokens(tokens);
}
dot2_token.to_tokens(tokens);
self.comma_token.to_tokens(tokens);
if self.comma_token.is_none() && !self.back.is_empty() {
<Token![,]>::default().to_tokens(tokens);
}
}
self.back.to_tokens(tokens);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for PatBox {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.box_token.to_tokens(tokens);
self.pat.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatRef {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.and_token.to_tokens(tokens);
self.mutability.to_tokens(tokens);
self.pat.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatLit {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.expr.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatRange {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.lo.to_tokens(tokens);
match self.limits {
RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
}
self.hi.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatSlice {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.bracket_token.surround(tokens, |tokens| {
self.front.to_tokens(tokens);
if !self.front.empty_or_trailing()
&& (self.middle.is_some() || self.dot2_token.is_some())
{
<Token![,]>::default().to_tokens(tokens);
}
if self.middle.is_some() {
self.middle.to_tokens(tokens);
TokensOrDefault(&self.dot2_token).to_tokens(tokens);
} else if self.dot2_token.is_some() {
self.dot2_token.to_tokens(tokens);
}
if !self.back.is_empty() {
TokensOrDefault(&self.comma_token).to_tokens(tokens);
self.back.to_tokens(tokens);
} else {
self.comma_token.to_tokens(tokens);
}
})
}
}
#[cfg(feature = "full")]
impl ToTokens for PatMacro {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.mac.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for PatVerbatim {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.tts.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for FieldPat {
fn to_tokens(&self, tokens: &mut TokenStream) {
if let Some(ref colon_token) = self.colon_token {
self.member.to_tokens(tokens);
colon_token.to_tokens(tokens);
}
self.pat.to_tokens(tokens);
}
}
#[cfg(feature = "full")]
impl ToTokens for Block {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.brace_token.surround(tokens, |tokens| {
tokens.append_all(&self.stmts);
});
}
}
#[cfg(feature = "full")]
impl ToTokens for Stmt {
fn to_tokens(&self, tokens: &mut TokenStream) {
match *self {
Stmt::Local(ref local) => local.to_tokens(tokens),
Stmt::Item(ref item) => item.to_tokens(tokens),
Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Stmt::Semi(ref expr, ref semi) => {
expr.to_tokens(tokens);
semi.to_tokens(tokens);
}
}
}
}
#[cfg(feature = "full")]
impl ToTokens for Local {
fn to_tokens(&self, tokens: &mut TokenStream) {
outer_attrs_to_tokens(&self.attrs, tokens);
self.let_token.to_tokens(tokens);
self.pats.to_tokens(tokens);
if let Some((ref colon_token, ref ty)) = self.ty {
colon_token.to_tokens(tokens);
ty.to_tokens(tokens);
}
if let Some((ref eq_token, ref init)) = self.init {
eq_token.to_tokens(tokens);
init.to_tokens(tokens);
}
self.semi_token.to_tokens(tokens);
}
}
}