Separate delimiter and tokenstream in macro ast
diff --git a/codegen/src/main.rs b/codegen/src/main.rs
index 0115cae..1c199f1 100644
--- a/codegen/src/main.rs
+++ b/codegen/src/main.rs
@@ -127,16 +127,16 @@
// Try to parse the AstItem declaration out of the item.
let found = if path_eq(&item.mac.path, &"ast_struct".into()) {
- syn::parse_tokens::<parsing::AstStruct>(item.mac.tt.clone().into_tokens())
+ syn::parse_tokens::<parsing::AstStruct>(item.mac.tts.clone().into_tokens())
.map_err(|_| err_msg("failed to parse ast_struct"))?
.0
} else if path_eq(&item.mac.path, &"ast_enum".into()) {
- syn::parse_tokens::<parsing::AstEnum>(item.mac.tt.clone().into_tokens())
+ syn::parse_tokens::<parsing::AstEnum>(item.mac.tts.clone().into_tokens())
.map_err(|_| err_msg("failed to parse ast_enum"))?
.0
} else if path_eq(&item.mac.path, &"ast_enum_of_structs".into()) {
syn::parse_tokens::<parsing::AstEnumOfStructs>(
- item.mac.tt.clone().into_tokens(),
+ item.mac.tts.clone().into_tokens(),
).map_err(|_| err_msg("failed to parse ast_enum_of_structs"))?
.0
} else {
@@ -221,21 +221,21 @@
// ast_struct! parsing
pub struct AstStruct(pub Vec<AstItem>);
impl Synom for AstStruct {
- named!(parse -> Self, map!(braces!(do_parse!(
+ named!(parse -> Self, do_parse!(
many0!(Attribute::parse_outer) >>
keyword!(pub) >>
keyword!(struct) >>
res: call!(ast_struct_inner) >>
- (res)
- )), |x| AstStruct(vec![x.0])));
+ (AstStruct(vec![res]))
+ ));
}
// ast_enum! parsing
pub struct AstEnum(pub Vec<AstItem>);
impl Synom for AstEnum {
- named!(parse -> Self, map!(braces!(syn!(DeriveInput)), |x| {
+ named!(parse -> Self, map!(syn!(DeriveInput), |x| {
AstEnum(vec![AstItem {
- ast: x.0,
+ ast: x,
features: quote!(),
eos_full: false,
}])
@@ -268,7 +268,7 @@
// ast_enum_of_structs! parsing
pub struct AstEnumOfStructs(pub Vec<AstItem>);
impl Synom for AstEnumOfStructs {
- named!(parse -> Self, map!(braces!(do_parse!(
+ named!(parse -> Self, do_parse!(
many0!(Attribute::parse_outer) >>
keyword!(pub) >>
keyword!(enum) >>
@@ -298,7 +298,7 @@
items.extend(body.0.into_iter().filter_map(|v| v.inner));
AstEnumOfStructs(items)
})
- )), |x| x.0));
+ ));
}
}
diff --git a/src/expr.rs b/src/expr.rs
index 41edfad..101cc9d 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -796,7 +796,7 @@
use ty::parsing::ty_no_eq_after;
#[cfg(feature = "full")]
- use proc_macro2::{Delimiter, Span, TokenNode, TokenStream};
+ use proc_macro2::{Span, TokenStream};
use synom::Synom;
use cursor::Cursor;
#[cfg(feature = "full")]
@@ -2042,10 +2042,8 @@
mac: Macro {
path: what,
bang_token: bang,
- tt: proc_macro2::TokenTree {
- span: (data.1).0,
- kind: TokenNode::Group(Delimiter::Brace, data.0),
- },
+ delimiter: MacroDelimiter::Brace(data.1),
+ tts: data.0,
},
semi_token: semi,
}))))
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index 3013ab5..3faa53c 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -252,6 +252,8 @@
fn fold_macro(&mut self, i: Macro) -> Macro { fold_macro(self, i) }
+fn fold_macro_delimiter(&mut self, i: MacroDelimiter) -> MacroDelimiter { fold_macro_delimiter(self, i) }
+
fn fold_member(&mut self, i: Member) -> Member { fold_member(self, i) }
fn fold_meta_item(&mut self, i: MetaItem) -> MetaItem { fold_meta_item(self, i) }
@@ -1798,7 +1800,9 @@
vis: _visitor.fold_visibility(_i . vis),
macro_token: Token ! [ macro ](tokens_helper(_visitor, &(_i . macro_token).0)),
ident: _visitor.fold_ident(_i . ident),
+ paren_token: Paren(tokens_helper(_visitor, &(_i . paren_token).0)),
args: _i . args,
+ brace_token: Brace(tokens_helper(_visitor, &(_i . brace_token).0)),
body: _i . body,
}
}
@@ -1946,7 +1950,29 @@
Macro {
path: _visitor.fold_path(_i . path),
bang_token: Token ! [ ! ](tokens_helper(_visitor, &(_i . bang_token).0)),
- tt: _i . tt,
+ delimiter: _visitor.fold_macro_delimiter(_i . delimiter),
+ tts: _i . tts,
+ }
+}
+
+pub fn fold_macro_delimiter<V: Folder + ?Sized>(_visitor: &mut V, _i: MacroDelimiter) -> MacroDelimiter {
+ use ::MacroDelimiter::*;
+ match _i {
+ Paren(_binding_0, ) => {
+ Paren (
+ Paren(tokens_helper(_visitor, &(_binding_0).0)),
+ )
+ }
+ Brace(_binding_0, ) => {
+ Brace (
+ Brace(tokens_helper(_visitor, &(_binding_0).0)),
+ )
+ }
+ Bracket(_binding_0, ) => {
+ Bracket (
+ Bracket(tokens_helper(_visitor, &(_binding_0).0)),
+ )
+ }
}
}
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index 120d1fd..6beacf0 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -248,6 +248,8 @@
fn visit_macro(&mut self, i: &'ast Macro) { visit_macro(self, i) }
+fn visit_macro_delimiter(&mut self, i: &'ast MacroDelimiter) { visit_macro_delimiter(self, i) }
+
fn visit_member(&mut self, i: &'ast Member) { visit_member(self, i) }
fn visit_meta_item(&mut self, i: &'ast MetaItem) { visit_meta_item(self, i) }
@@ -1408,7 +1410,9 @@
_visitor.visit_visibility(& _i . vis);
tokens_helper(_visitor, &(& _i . macro_token).0);
_visitor.visit_ident(& _i . ident);
+ tokens_helper(_visitor, &(& _i . paren_token).0);
// Skipped field _i . args;
+ tokens_helper(_visitor, &(& _i . brace_token).0);
// Skipped field _i . body;
}
# [ cfg ( feature = "full" ) ]
@@ -1535,7 +1539,23 @@
pub fn visit_macro<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Macro) {
_visitor.visit_path(& _i . path);
tokens_helper(_visitor, &(& _i . bang_token).0);
- // Skipped field _i . tt;
+ _visitor.visit_macro_delimiter(& _i . delimiter);
+ // Skipped field _i . tts;
+}
+
+pub fn visit_macro_delimiter<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast MacroDelimiter) {
+ use ::MacroDelimiter::*;
+ match *_i {
+ Paren(ref _binding_0, ) => {
+ tokens_helper(_visitor, &(_binding_0).0);
+ }
+ Brace(ref _binding_0, ) => {
+ tokens_helper(_visitor, &(_binding_0).0);
+ }
+ Bracket(ref _binding_0, ) => {
+ tokens_helper(_visitor, &(_binding_0).0);
+ }
+ }
}
pub fn visit_member<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Member) {
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index 00d9c17..9c164dc 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -248,6 +248,8 @@
fn visit_macro_mut(&mut self, i: &mut Macro) { visit_macro_mut(self, i) }
+fn visit_macro_delimiter_mut(&mut self, i: &mut MacroDelimiter) { visit_macro_delimiter_mut(self, i) }
+
fn visit_member_mut(&mut self, i: &mut Member) { visit_member_mut(self, i) }
fn visit_meta_item_mut(&mut self, i: &mut MetaItem) { visit_meta_item_mut(self, i) }
@@ -1408,7 +1410,9 @@
_visitor.visit_visibility_mut(& mut _i . vis);
tokens_helper(_visitor, &mut (& mut _i . macro_token).0);
_visitor.visit_ident_mut(& mut _i . ident);
+ tokens_helper(_visitor, &mut (& mut _i . paren_token).0);
// Skipped field _i . args;
+ tokens_helper(_visitor, &mut (& mut _i . brace_token).0);
// Skipped field _i . body;
}
# [ cfg ( feature = "full" ) ]
@@ -1535,7 +1539,23 @@
pub fn visit_macro_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Macro) {
_visitor.visit_path_mut(& mut _i . path);
tokens_helper(_visitor, &mut (& mut _i . bang_token).0);
- // Skipped field _i . tt;
+ _visitor.visit_macro_delimiter_mut(& mut _i . delimiter);
+ // Skipped field _i . tts;
+}
+
+pub fn visit_macro_delimiter_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut MacroDelimiter) {
+ use ::MacroDelimiter::*;
+ match *_i {
+ Paren(ref mut _binding_0, ) => {
+ tokens_helper(_visitor, &mut (_binding_0).0);
+ }
+ Brace(ref mut _binding_0, ) => {
+ tokens_helper(_visitor, &mut (_binding_0).0);
+ }
+ Bracket(ref mut _binding_0, ) => {
+ tokens_helper(_visitor, &mut (_binding_0).0);
+ }
+ }
}
pub fn visit_member_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Member) {
diff --git a/src/item.rs b/src/item.rs
index 90b70f0..1953756 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -1,9 +1,10 @@
use super::*;
use delimited::Delimited;
-use proc_macro2::{TokenTree, TokenStream};
+use proc_macro2::{TokenStream};
+use token::{Paren, Brace};
#[cfg(feature = "extra-traits")]
-use mac::{TokenTreeHelper, TokenStreamHelper};
+use mac::TokenStreamHelper;
#[cfg(feature = "extra-traits")]
use std::hash::{Hash, Hasher};
@@ -186,14 +187,15 @@
pub mac: Macro,
pub semi_token: Option<Token![;]>,
}),
- /// FIXME will need to revisit what this looks like in the AST.
pub Macro2(ItemMacro2 #manual_extra_traits {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub macro_token: Token![macro],
pub ident: Ident,
- pub args: TokenTree,
- pub body: TokenTree,
+ pub paren_token: Paren,
+ pub args: TokenStream,
+ pub brace_token: Brace,
+ pub body: TokenStream,
}),
pub Verbatim(ItemVerbatim #manual_extra_traits {
pub tts: TokenStream,
@@ -208,9 +210,10 @@
impl PartialEq for ItemMacro2 {
fn eq(&self, other: &Self) -> bool {
self.attrs == other.attrs && self.vis == other.vis && self.macro_token == other.macro_token
- && self.ident == other.ident
- && TokenTreeHelper(&self.args) == TokenTreeHelper(&other.args)
- && TokenTreeHelper(&self.body) == TokenTreeHelper(&other.body)
+ && self.ident == other.ident && self.paren_token == other.paren_token
+ && TokenStreamHelper(&self.args) == TokenStreamHelper(&other.args)
+ && self.brace_token == other.brace_token
+ && TokenStreamHelper(&self.body) == TokenStreamHelper(&other.body)
}
}
@@ -224,8 +227,10 @@
self.vis.hash(state);
self.macro_token.hash(state);
self.ident.hash(state);
- TokenTreeHelper(&self.args).hash(state);
- TokenTreeHelper(&self.body).hash(state);
+ self.paren_token.hash(state);
+ TokenStreamHelper(&self.args).hash(state);
+ self.brace_token.hash(state);
+ TokenStreamHelper(&self.body).hash(state);
}
}
@@ -531,7 +536,6 @@
use super::*;
use synom::{Synom, Cursor, PResult};
- use proc_macro2::{TokenNode, Delimiter};
impl_synom!(Item "item" alt!(
syn!(ItemExternCrate) => { Item::ExternCrate }
@@ -573,14 +577,15 @@
bang: punct!(!) >>
ident: option!(syn!(Ident)) >>
body: call!(tt::delimited) >>
- semi: cond!(!is_braced(&body), punct!(;)) >>
+ semi: cond!(!is_brace(&body.0), punct!(;)) >>
(ItemMacro {
attrs: attrs,
ident: ident,
mac: Macro {
path: what,
bang_token: bang,
- tt: body,
+ delimiter: body.0,
+ tts: body.1,
},
semi_token: semi,
})
@@ -599,8 +604,10 @@
vis: vis,
macro_token: macro_,
ident: ident,
- args: args,
- body: body,
+ paren_token: args.0,
+ args: args.1,
+ brace_token: body.0,
+ body: body.1,
})
));
@@ -1195,7 +1202,7 @@
impl_synom!(TraitItemMacro "trait item macro" do_parse!(
attrs: many0!(Attribute::parse_outer) >>
mac: syn!(Macro) >>
- semi: cond!(!is_braced(&mac.tt), punct!(;)) >>
+ semi: cond!(!is_brace(&mac.delimiter), punct!(;)) >>
(TraitItemMacro {
attrs: attrs,
mac: mac,
@@ -1348,7 +1355,7 @@
impl_synom!(ImplItemMacro "macro in impl block" do_parse!(
attrs: many0!(Attribute::parse_outer) >>
mac: syn!(Macro) >>
- semi: cond!(!is_braced(&mac.tt), punct!(;)) >>
+ semi: cond!(!is_brace(&mac.delimiter), punct!(;)) >>
(ImplItemMacro {
attrs: attrs,
mac: mac,
@@ -1356,10 +1363,10 @@
})
));
- fn is_braced(tt: &TokenTree) -> bool {
- match tt.kind {
- TokenNode::Group(Delimiter::Brace, _) => true,
- _ => false,
+ fn is_brace(delimiter: &MacroDelimiter) -> bool {
+ match *delimiter {
+ MacroDelimiter::Brace(_) => true,
+ MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false,
}
}
}
@@ -1582,7 +1589,17 @@
self.mac.path.to_tokens(tokens);
self.mac.bang_token.to_tokens(tokens);
self.ident.to_tokens(tokens);
- self.mac.tt.to_tokens(tokens);
+ match self.mac.delimiter {
+ MacroDelimiter::Paren(ref paren) => {
+ paren.surround(tokens, |tokens| self.mac.tts.to_tokens(tokens));
+ }
+ MacroDelimiter::Brace(ref brace) => {
+ brace.surround(tokens, |tokens| self.mac.tts.to_tokens(tokens));
+ }
+ MacroDelimiter::Bracket(ref bracket) => {
+ bracket.surround(tokens, |tokens| self.mac.tts.to_tokens(tokens));
+ }
+ }
self.semi_token.to_tokens(tokens);
}
}
@@ -1593,8 +1610,12 @@
self.vis.to_tokens(tokens);
self.macro_token.to_tokens(tokens);
self.ident.to_tokens(tokens);
- self.args.to_tokens(tokens);
- self.body.to_tokens(tokens);
+ self.paren_token.surround(tokens, |tokens| {
+ self.args.to_tokens(tokens);
+ });
+ self.brace_token.surround(tokens, |tokens| {
+ self.body.to_tokens(tokens);
+ });
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 33a8fb4..56c3be0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -73,7 +73,7 @@
pub use lit::{Lit, LitKind};
mod mac;
-pub use mac::Macro;
+pub use mac::{Macro, MacroDelimiter};
mod derive;
pub use derive::{Body, BodyEnum, BodyStruct, DeriveInput};
diff --git a/src/mac.rs b/src/mac.rs
index 98aa49a..a43c311 100644
--- a/src/mac.rs
+++ b/src/mac.rs
@@ -1,20 +1,32 @@
use super::*;
-
-use proc_macro2::TokenTree;
+use proc_macro2::TokenStream;
+use token::{Paren, Brace, Bracket};
#[cfg(feature = "extra-traits")]
-use proc_macro2::{TokenStream, TokenNode, Delimiter};
+use proc_macro2::{TokenTree, TokenNode, Delimiter};
#[cfg(feature = "extra-traits")]
use std::hash::{Hash, Hasher};
ast_struct! {
- /// Represents a macro invocation. The Path indicates which macro
- /// is being invoked, and the vector of token-trees contains the source
- /// of the macro invocation.
+ /// Represents a macro invocation. The Path indicates which macro is being
+ /// invoked, and the `TokenStream` contains the source of the macro
+ /// invocation.
pub struct Macro #manual_extra_traits {
pub path: Path,
pub bang_token: Token![!],
- pub tt: TokenTree,
+ pub delimiter: MacroDelimiter,
+ pub tts: TokenStream,
+ }
+}
+
+ast_enum! {
+ pub enum MacroDelimiter {
+ /// `macro!(...)`
+ Paren(Paren),
+ /// `macro!{...}`
+ Brace(Brace),
+ /// `macro![...]`
+ Bracket(Bracket),
}
}
@@ -25,7 +37,8 @@
impl PartialEq for Macro {
fn eq(&self, other: &Self) -> bool {
self.path == other.path && self.bang_token == other.bang_token
- && TokenTreeHelper(&self.tt) == TokenTreeHelper(&other.tt)
+ && self.delimiter == other.delimiter
+ && TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
}
}
@@ -37,7 +50,8 @@
{
self.path.hash(state);
self.bang_token.hash(state);
- TokenTreeHelper(&self.tt).hash(state);
+ self.delimiter.hash(state);
+ TokenStreamHelper(&self.tts).hash(state);
}
}
@@ -167,7 +181,8 @@
(Macro {
path: what,
bang_token: bang,
- tt: body,
+ delimiter: body.0,
+ tts: body.1,
})
));
}
@@ -182,7 +197,17 @@
fn to_tokens(&self, tokens: &mut Tokens) {
self.path.to_tokens(tokens);
self.bang_token.to_tokens(tokens);
- self.tt.to_tokens(tokens);
+ match self.delimiter {
+ MacroDelimiter::Paren(ref paren) => {
+ paren.surround(tokens, |tokens| self.tts.to_tokens(tokens));
+ }
+ MacroDelimiter::Brace(ref brace) => {
+ brace.surround(tokens, |tokens| self.tts.to_tokens(tokens));
+ }
+ MacroDelimiter::Bracket(ref bracket) => {
+ bracket.surround(tokens, |tokens| self.tts.to_tokens(tokens));
+ }
+ }
}
}
}
diff --git a/src/tt.rs b/src/tt.rs
index db22284..b0952a0 100644
--- a/src/tt.rs
+++ b/src/tt.rs
@@ -1,48 +1,55 @@
-use proc_macro2::{TokenNode, TokenTree};
+use proc_macro2::{TokenNode, TokenStream, TokenTree, Delimiter};
use cursor::Cursor;
use parse_error;
use synom::PResult;
+use MacroDelimiter;
+use token::{Paren, Brace, Bracket};
-#[cfg(feature = "full")]
-use proc_macro2::Delimiter;
-
-pub fn delimited(input: Cursor) -> PResult<TokenTree> {
+pub fn delimited(input: Cursor) -> PResult<(MacroDelimiter, TokenStream)> {
match input.token_tree() {
Some((
rest,
- token @ TokenTree {
- kind: TokenNode::Group(..),
- ..
+ TokenTree {
+ span,
+ kind: TokenNode::Group(delimiter, tts),
},
- )) => Ok((rest, token)),
+ )) => {
+ let delimiter = match delimiter {
+ Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)),
+ Delimiter::Brace => MacroDelimiter::Brace(Brace(span)),
+ Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)),
+ Delimiter::None => return parse_error(),
+ };
+ Ok((rest, (delimiter, tts)))
+ }
_ => parse_error(),
}
}
#[cfg(feature = "full")]
-pub fn braced(input: Cursor) -> PResult<TokenTree> {
+pub fn braced(input: Cursor) -> PResult<(Brace, TokenStream)> {
match input.token_tree() {
Some((
rest,
- token @ TokenTree {
- kind: TokenNode::Group(Delimiter::Brace, ..),
- ..
+ TokenTree {
+ span,
+ kind: TokenNode::Group(Delimiter::Brace, tts),
},
- )) => Ok((rest, token)),
+ )) => Ok((rest, (Brace(span), tts))),
_ => parse_error(),
}
}
#[cfg(feature = "full")]
-pub fn parenthesized(input: Cursor) -> PResult<TokenTree> {
+pub fn parenthesized(input: Cursor) -> PResult<(Paren, TokenStream)> {
match input.token_tree() {
Some((
rest,
- token @ TokenTree {
- kind: TokenNode::Group(Delimiter::Parenthesis, ..),
- ..
+ TokenTree {
+ span,
+ kind: TokenNode::Group(Delimiter::Parenthesis, tts),
},
- )) => Ok((rest, token)),
+ )) => Ok((rest, (Paren(span), tts))),
_ => parse_error(),
}
}