Implement unary_expr
diff --git a/src/expr.rs b/src/expr.rs
index 3844710..615fe35 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1404,60 +1404,56 @@
// &mut <trailer>
// box <trailer>
#[cfg(feature = "full")]
- named2!(unary_expr(allow_struct: AllowStruct, allow_block: AllowBlock) -> Expr, alt!(
- do_parse!(
- attrs: many0!(Attribute::old_parse_outer) >>
- op: syn!(UnOp) >>
- expr: shim!(unary_expr, allow_struct, AllowBlock(true)) >>
- (ExprUnary {
- attrs: attrs,
- op: op,
- expr: Box::new(expr),
- }.into())
- )
- |
- do_parse!(
- attrs: many0!(Attribute::old_parse_outer) >>
- and: punct!(&) >>
- mutability: option!(keyword!(mut)) >>
- expr: shim!(unary_expr, allow_struct, AllowBlock(true)) >>
- (ExprReference {
- attrs: attrs,
- and_token: and,
- mutability: mutability,
- expr: Box::new(expr),
- }.into())
- )
- |
- do_parse!(
- attrs: many0!(Attribute::old_parse_outer) >>
- box_: keyword!(box) >>
- expr: shim!(unary_expr, allow_struct, AllowBlock(true)) >>
- (ExprBox {
- attrs: attrs,
- box_token: box_,
- expr: Box::new(expr),
- }.into())
- )
- |
- shim!(trailer_expr, allow_struct, allow_block)
- ));
+ fn unary_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> 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, AllowBlock(true))?),
+ }))
+ } else if input.peek(Token![box]) {
+ Ok(Expr::Box(ExprBox {
+ attrs: attrs,
+ box_token: input.parse()?,
+ expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
+ }))
+ } else {
+ Ok(Expr::Unary(ExprUnary {
+ attrs: attrs,
+ op: input.parse()?,
+ expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
+ }))
+ }
+ } else {
+ trailer_expr(input, allow_struct, allow_block)
+ }
+ }
// XXX: This duplication is ugly
#[cfg(not(feature = "full"))]
- named2!(unary_expr(allow_struct: AllowStruct, allow_block: AllowBlock) -> Expr, alt!(
- do_parse!(
- op: syn!(UnOp) >>
- expr: shim!(unary_expr, allow_struct, AllowBlock(true)) >>
- (ExprUnary {
- attrs: Vec::new(),
- op: op,
- expr: Box::new(expr),
- }.into())
- )
- |
- shim!(trailer_expr, allow_struct, allow_block)
- ));
+ fn unary_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> 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, AllowBlock(true))?),
+ }))
+ } else {
+ trailer_expr(input, allow_struct, allow_block)
+ }
+ }
#[cfg(feature = "full")]
fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {