Parse None-delimited groups in types and expressions
diff --git a/src/expr.rs b/src/expr.rs
index fa7872b..2b73998 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -322,6 +322,16 @@
pub paren_token: tokens::Paren,
}),
+ /// No-op: used solely so we can pretty-print faithfully
+ ///
+ /// A `group` represents a `None`-delimited span in the input
+ /// `TokenStream` which affects the precidence of the resulting
+ /// expression. They are used for macro hygiene.
+ pub Group(ExprGroup {
+ pub expr: Box<Expr>,
+ pub group_token: tokens::Group,
+ }),
+
/// `expr?`
pub Try(ExprTry {
pub expr: Box<Expr>,
@@ -1036,6 +1046,8 @@
/// Parse all atomic expressions which don't have to worry about precidence
/// interactions, as they are fully contained.
named!(atom_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
+ syn!(ExprGroup) => { ExprKind::Group } // must be placed first
+ |
syn!(Lit) => { ExprKind::Lit } // must be before expr_struct
|
// must be before expr_path
@@ -1086,6 +1098,16 @@
syn!(ExprRepeat) => { ExprKind::Repeat }
));
+ impl Synom for ExprGroup {
+ named!(parse -> Self, do_parse!(
+ e: grouped!(syn!(Expr)) >>
+ (ExprGroup {
+ expr: Box::new(e.0),
+ group_token: e.1,
+ }.into())
+ ));
+ }
+
impl Synom for ExprParen {
named!(parse -> Self, do_parse!(
e: parens!(syn!(Expr)) >>
@@ -2374,6 +2396,14 @@
}
}
+ impl ToTokens for ExprGroup {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ self.group_token.surround(tokens, |tokens| {
+ self.expr.to_tokens(tokens);
+ });
+ }
+ }
+
impl ToTokens for ExprParen {
fn to_tokens(&self, tokens: &mut Tokens) {
self.paren_token.surround(tokens, |tokens| {
diff --git a/src/fold.rs b/src/fold.rs
index 2f4ef1c..9572065 100644
--- a/src/fold.rs
+++ b/src/fold.rs
@@ -234,6 +234,12 @@
..t
})
}
+ Group(t) => {
+ Group(TyGrpup {
+ ty: t.ty.lift(|v| folder.fold_ty(v)),
+ ..t
+ })
+ }
Paren(t) => {
Paren(TyParen {
ty: t.ty.lift(|v| folder.fold_ty(v)),
@@ -1037,6 +1043,12 @@
..e
})
}
+ Group(e) => {
+ Group(ExprGroup {
+ expr: e.expr.lift(|e| folder.fold_expr(e)),
+ ..e
+ })
+ }
Try(e) => {
Try(ExprTry {
expr: e.expr.lift(|e| folder.fold_expr(e)),
diff --git a/src/lib.rs b/src/lib.rs
index faab98f..95e222a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,7 +38,7 @@
ExprRange, ExprPath, ExprAddrOf, ExprBreak, ExprContinue,
ExprRet, ExprStruct, ExprRepeat, ExprParen, ExprTry, ExprCatch,
PatIdent, PatWild, PatStruct, PatTuple, PatTupleStruct, PatPath,
- PatBox, PatRef, PatLit, PatRange, PatSlice, InPlaceKind};
+ PatBox, PatRef, PatLit, PatRange, PatSlice, InPlaceKind, ExprGroup};
mod generics;
pub use generics::{Generics, LifetimeDef, TraitBoundModifier, TyParam, TyParamBound,
@@ -91,7 +91,7 @@
Mutability, ParenthesizedParameterData, Path, PathParameters, PathSegment,
PolyTraitRef, QSelf, Ty, TypeBinding, Unsafety, TySlice, TyArray,
TyPtr, TyRptr, TyBareFn, TyNever, TyTup, TyPath, TyTraitObject,
- TyImplTrait, TyParen, TyInfer};
+ TyImplTrait, TyParen, TyInfer, TyGroup};
#[cfg(feature = "printing")]
pub use ty::PathTokens;
diff --git a/src/ty.rs b/src/ty.rs
index e4e062e..3957ca9 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -66,6 +66,11 @@
pub paren_token: tokens::Paren,
pub ty: Box<Ty>,
}),
+ /// No-op: kept solely so that we can pretty-print faithfully
+ pub Group(TyGroup {
+ pub group_token: tokens::Group,
+ pub ty: Box<Ty>,
+ }),
/// TyKind::Infer means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
pub Infer(TyInfer {
@@ -341,6 +346,8 @@
}
named!(ambig_ty(allow_plus: bool) -> Ty, alt!(
+ syn!(TyGroup) => { Ty::Group }
+ |
// must be before mac
syn!(TyParen) => { Ty::Paren }
|
@@ -628,6 +635,16 @@
));
}
+ impl Synom for TyGroup {
+ named!(parse -> Self, do_parse!(
+ data: grouped!(syn!(Ty)) >>
+ (TyGroup {
+ group_token: data.1,
+ ty: Box::new(data.0),
+ })
+ ));
+ }
+
impl Synom for TyParen {
named!(parse -> Self, do_parse!(
data: parens!(syn!(Ty)) >>
@@ -910,6 +927,14 @@
}
}
+ impl ToTokens for TyGroup {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ self.group_token.surround(tokens, |tokens| {
+ self.ty.to_tokens(tokens);
+ });
+ }
+ }
+
impl ToTokens for TyParen {
fn to_tokens(&self, tokens: &mut Tokens) {
self.paren_token.surround(tokens, |tokens| {
diff --git a/src/visit.rs b/src/visit.rs
index df49e71..7ad2ee0 100644
--- a/src/visit.rs
+++ b/src/visit.rs
@@ -188,6 +188,7 @@
match *ty {
Ty::Slice(TySlice { ref ty, .. }) |
+ Ty::Group(TyGroup { ref ty, .. }) |
Ty::Paren(TyParen { ref ty, .. }) => visitor.visit_ty(ty),
Ty::Ptr(TyPtr { ref ty, .. }) => visitor.visit_ty(&ty.ty),
Ty::Rptr(TyRptr { ref lifetime, ref ty, .. }) => {
@@ -599,6 +600,7 @@
Box(ExprBox { ref expr, .. }) |
AddrOf(ExprAddrOf { ref expr, .. }) |
Paren(ExprParen { ref expr, .. }) |
+ Group(ExprGroup { ref expr, .. }) |
Try(ExprTry { ref expr, .. }) => {
visitor.visit_expr(expr);
}