Macro parsing
diff --git a/src/attr.rs b/src/attr.rs
index 1f16ab3..fa021d7 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -165,7 +165,7 @@
|
do_parse!(
option!(whitespace) >>
- peek!(tag!("/**")) >>
+ peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
com: block_comment >>
(Attribute {
style: AttrStyle::Outer,
diff --git a/src/expr.rs b/src/expr.rs
index 2865c2c..e3e4e55 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -346,6 +346,7 @@
use ident::parsing::ident;
use item::parsing::item;
use lit::parsing::lit;
+ use mac::parsing::mac;
use nom::IResult::Error;
use ty::parsing::{mutability, path, qpath, ty};
@@ -388,7 +389,8 @@
expr_continue
|
expr_ret
- // TODO: Mac
+ |
+ expr_mac
|
expr_repeat
) >>
@@ -429,6 +431,8 @@
(e)
));
+ named!(expr_mac -> Expr, map!(mac, Expr::Mac));
+
named!(expr_paren -> Expr, do_parse!(
punct!("(") >>
e: expr >>
@@ -876,9 +880,12 @@
// TODO: Lit
// TODO: Range
// TODO: Vec
- // TODO: Mac
+ |
+ pat_mac
));
+ named!(pat_mac -> Pat, map!(mac, Pat::Mac));
+
named!(pat_wild -> Pat, map!(keyword!("_"), |_| Pat::Wild));
named!(pat_ident -> Pat, do_parse!(
diff --git a/src/item.rs b/src/item.rs
index 874455f..1c0ec66 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -227,13 +227,14 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use {FunctionRetTy, Generics};
+ use {FunctionRetTy, Generics, Ident, Mac, TokenTree, Visibility};
use attr::parsing::outer_attr;
use data::parsing::visibility;
use expr::parsing::{block, expr, pat};
use generics::parsing::{generics, where_clause};
use ident::parsing::ident;
use lit::parsing::quoted_string;
+ use mac::parsing::delimited;
use macro_input::{Body, MacroInput};
use macro_input::parsing::macro_input;
use ty::parsing::{mutability, ty};
@@ -257,7 +258,25 @@
// TODO: Trait
// TODO: DefaultImpl
// TODO: Impl
- // TODO: Mac
+ |
+ item_mac
+ ));
+
+ named!(item_mac -> Item, do_parse!(
+ attrs: many0!(outer_attr) >>
+ path: ident >>
+ punct!("!") >>
+ name: option!(ident) >>
+ body: delimited >>
+ (Item {
+ ident: name.unwrap_or_else(|| Ident::new("")),
+ vis: Visibility::Inherited,
+ attrs: attrs,
+ node: ItemKind::Mac(Mac {
+ path: path.into(),
+ tts: vec![TokenTree::Delimited(body)],
+ }),
+ })
));
named!(item_extern_crate -> Item, do_parse!(
diff --git a/src/lib.rs b/src/lib.rs
index efde6ba..7173b6f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -119,7 +119,6 @@
DelimToken,
Delimited,
Mac,
- SequenceRepetition,
Token,
TokenTree,
};
diff --git a/src/mac.rs b/src/mac.rs
index f227a25..b3fed3a 100644
--- a/src/mac.rs
+++ b/src/mac.rs
@@ -30,10 +30,6 @@
Token(Token),
/// A delimited sequence of token trees
Delimited(Delimited),
-
- // This only makes sense in MBE macros.
- /// A kleene-style repetition sequence with a span
- Sequence(SequenceRepetition),
}
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -45,26 +41,6 @@
}
#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct SequenceRepetition {
- /// The sequence of token trees
- pub tts: Vec<TokenTree>,
- /// The optional separator
- pub separator: Option<Token>,
- /// Whether the sequence can be repeated zero (*), or one or more times (+)
- pub op: KleeneOp,
- /// The number of `MatchNt`s that appear in the sequence (and subsequences)
- pub num_captures: usize,
-}
-
-/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
-/// for token sequences.
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum KleeneOp {
- ZeroOrMore,
- OneOrMore,
-}
-
-#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Token {
/* Expression-operator symbols. */
Eq,
@@ -96,28 +72,16 @@
Pound,
Dollar,
Question,
- /// An opening delimiter, eg. `{`
- OpenDelim(DelimToken),
- /// A closing delimiter, eg. `}`
- CloseDelim(DelimToken),
/* Literals */
- Literal(Lit, Option<String>),
+ Literal(Lit),
/* Name components */
Ident(Ident),
Underscore,
Lifetime(Ident),
- // Can be expanded into several tokens.
- /// Doc comment
DocComment(String),
- // In left-hand-sides of MBE macros:
- /// Parse a nonterminal (name to bind, name of NT)
- MatchNt(Ident, Ident),
- // In right-hand-sides of MBE macros:
- /// A syntactic variable that will be filled in by macro expansion.
- SubstNt(Ident),
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@@ -143,6 +107,189 @@
Bracket,
/// A curly brace: `{` or `}`
Brace,
- /// An empty delimiter
- NoDelim,
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+ use super::*;
+ use Lifetime;
+ use generics::parsing::lifetime;
+ use ident::parsing::ident;
+ use lit::parsing::lit;
+ use space::{block_comment, whitespace};
+
+ named!(pub mac -> Mac, do_parse!(
+ name: ident >>
+ punct!("!") >>
+ body: delimited >>
+ (Mac {
+ path: name.into(),
+ tts: vec![TokenTree::Delimited(body)],
+ })
+ ));
+
+ named!(pub delimited -> Delimited, alt!(
+ delimited!(
+ punct!("("),
+ many0!(token_tree),
+ punct!(")")
+ ) => { |tts| Delimited { delim: DelimToken::Paren, tts: tts } }
+ |
+ delimited!(
+ punct!("["),
+ many0!(token_tree),
+ punct!("]")
+ ) => { |tts| Delimited { delim: DelimToken::Bracket, tts: tts } }
+ |
+ delimited!(
+ punct!("{"),
+ many0!(token_tree),
+ punct!("}")
+ ) => { |tts| Delimited { delim: DelimToken::Brace, tts: tts } }
+ ));
+
+ named!(token_tree -> TokenTree, alt!(
+ map!(token, TokenTree::Token)
+ |
+ map!(delimited, TokenTree::Delimited)
+ ));
+
+ named!(token -> Token, alt!(
+ map!(bin_op_eq, Token::BinOpEq)
+ |
+ map!(bin_op, Token::BinOp)
+ |
+ punct!("=") => { |_| Token::Eq }
+ |
+ punct!("<") => { |_| Token::Lt }
+ |
+ punct!("<=") => { |_| Token::Le }
+ |
+ punct!("==") => { |_| Token::EqEq }
+ |
+ punct!("!=") => { |_| Token::Ne }
+ |
+ punct!(">=") => { |_| Token::Ge }
+ |
+ punct!(">") => { |_| Token::Gt }
+ |
+ punct!("&&") => { |_| Token::AndAnd }
+ |
+ punct!("||") => { |_| Token::OrOr }
+ |
+ punct!("!") => { |_| Token::Not }
+ |
+ punct!("~") => { |_| Token::Tilde }
+ |
+ punct!("@") => { |_| Token::At }
+ |
+ punct!(".") => { |_| Token::Dot }
+ |
+ punct!("..") => { |_| Token::DotDot }
+ |
+ punct!("...") => { |_| Token::DotDotDot }
+ |
+ punct!(",") => { |_| Token::Comma }
+ |
+ punct!(";") => { |_| Token::Semi }
+ |
+ punct!(":") => { |_| Token::Colon }
+ |
+ punct!("::") => { |_| Token::ModSep }
+ |
+ punct!("->") => { |_| Token::RArrow }
+ |
+ punct!("<-") => { |_| Token::LArrow }
+ |
+ punct!("=>") => { |_| Token::FatArrow }
+ |
+ punct!("#") => { |_| Token::Pound }
+ |
+ punct!("$") => { |_| Token::Dollar }
+ |
+ punct!("?") => { |_| Token::Question }
+ |
+ punct!("_") => { |_| Token::Underscore }
+ |
+ map!(lit, Token::Literal)
+ |
+ map!(ident, Token::Ident)
+ |
+ map!(lifetime, |lt: Lifetime| Token::Lifetime(lt.ident))
+ |
+ map!(doc_comment, Token::DocComment)
+ ));
+
+ named!(bin_op -> BinOpToken, alt!(
+ punct!("+") => { |_| BinOpToken::Plus }
+ |
+ punct!("-") => { |_| BinOpToken::Minus }
+ |
+ punct!("*") => { |_| BinOpToken::Star }
+ |
+ punct!("/") => { |_| BinOpToken::Slash }
+ |
+ punct!("%") => { |_| BinOpToken::Percent }
+ |
+ punct!("^") => { |_| BinOpToken::Caret }
+ |
+ punct!("&") => { |_| BinOpToken::And }
+ |
+ punct!("|") => { |_| BinOpToken::Or }
+ |
+ punct!("<<") => { |_| BinOpToken::Shl }
+ |
+ punct!(">>") => { |_| BinOpToken::Shr }
+ ));
+
+ named!(bin_op_eq -> BinOpToken, alt!(
+ punct!("+=") => { |_| BinOpToken::Plus }
+ |
+ punct!("-=") => { |_| BinOpToken::Minus }
+ |
+ punct!("*=") => { |_| BinOpToken::Star }
+ |
+ punct!("/=") => { |_| BinOpToken::Slash }
+ |
+ punct!("%=") => { |_| BinOpToken::Percent }
+ |
+ punct!("^=") => { |_| BinOpToken::Caret }
+ |
+ punct!("&=") => { |_| BinOpToken::And }
+ |
+ punct!("|=") => { |_| BinOpToken::Or }
+ |
+ punct!("<<=") => { |_| BinOpToken::Shl }
+ |
+ punct!(">>=") => { |_| BinOpToken::Shr }
+ ));
+
+ named!(doc_comment -> String, alt!(
+ do_parse!(
+ punct!("//!") >>
+ content: take_until!("\n") >>
+ (format!("//!{}", content))
+ )
+ |
+ do_parse!(
+ option!(whitespace) >>
+ peek!(tag!("/*!")) >>
+ com: block_comment >>
+ (com.to_owned())
+ )
+ |
+ do_parse!(
+ punct!("///") >>
+ not!(peek!(tag!("/"))) >>
+ content: take_until!("\n") >>
+ (format!("///{}", content))
+ )
+ |
+ do_parse!(
+ option!(whitespace) >>
+ peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
+ com: block_comment >>
+ (com.to_owned())
+ )
+ ));
}
diff --git a/src/ty.rs b/src/ty.rs
index 7cba5f9..1c4917b 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -59,6 +59,15 @@
pub segments: Vec<PathSegment>,
}
+impl<T> From<T> for Path where T: Into<PathSegment> {
+ fn from(segment: T) -> Self {
+ Path {
+ global: false,
+ segments: vec![segment.into()],
+ }
+ }
+}
+
/// A segment of a path: an identifier, an optional lifetime, and a set of types.
///
/// E.g. `std`, `String` or `Box<T>`
@@ -68,10 +77,10 @@
pub parameters: PathParameters,
}
-impl PathSegment {
- pub fn ident(ident: Ident) -> Self {
+impl<T> From<T> for PathSegment where T: Into<Ident> {
+ fn from(ident: T) -> Self {
PathSegment {
- ident: ident,
+ ident: ident.into(),
parameters: PathParameters::none(),
}
}
@@ -373,7 +382,7 @@
})
)
|
- map!(ident, PathSegment::ident)
+ map!(ident, Into::into)
));
named!(type_binding -> TypeBinding, do_parse!(
diff --git a/tests/test_macro_input.rs b/tests/test_macro_input.rs
index 0334157..c00ba4d 100644
--- a/tests/test_macro_input.rs
+++ b/tests/test_macro_input.rs
@@ -1,13 +1,6 @@
extern crate syn;
use syn::*;
-fn simple_ty(ident: &str) -> Ty {
- Ty::Path(None, Path {
- global: false,
- segments: vec![PathSegment::ident(ident.into())],
- })
-}
-
#[test]
fn test_unit() {
let raw = "struct Unit;";
@@ -52,7 +45,7 @@
ident: Some("ident".into()),
vis: Visibility::Public,
attrs: Vec::new(),
- ty: simple_ty("Ident"),
+ ty: Ty::Path(None, "Ident".into()),
},
Field {
ident: Some("attrs".into()),
@@ -66,7 +59,7 @@
parameters: PathParameters::AngleBracketed(
AngleBracketedParameterData {
lifetimes: Vec::new(),
- types: vec![simple_ty("Attribute")],
+ types: vec![Ty::Path(None, "Attribute".into())],
bindings: Vec::new(),
},
),
@@ -140,7 +133,7 @@
ident: None,
vis: Visibility::Inherited,
attrs: Vec::new(),
- ty: simple_ty("T"),
+ ty: Ty::Path(None, "T".into()),
},
]),
discriminant: None,
@@ -153,7 +146,7 @@
ident: None,
vis: Visibility::Inherited,
attrs: Vec::new(),
- ty: simple_ty("E"),
+ ty: Ty::Path(None, "E".into()),
},
]),
discriminant: None,