Finish porting to the `Synom` trait
diff --git a/src/attr.rs b/src/attr.rs
index 9e498d2..76b1503 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -292,137 +292,123 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use mac::TokenTree;
- use mac::parsing::token_trees;
- use ty::parsing::mod_style_path;
- use proc_macro2::{self, TokenKind, OpKind, Literal};
+ use synom::IResult;
+ use synom::tokens::*;
+ use proc_macro2::{TokenKind, OpKind, TokenTree};
fn eq() -> TokenTree {
- TokenTree(proc_macro2::TokenTree {
+ TokenTree {
span: Default::default(),
kind: TokenKind::Op('=', OpKind::Alone),
- })
+ }
}
- fn doc(s: &str) -> TokenTree {
- TokenTree(proc_macro2::TokenTree {
- span: Default::default(),
- kind: TokenKind::Literal(Literal::doccomment(s)),
- })
+ impl Attribute {
+ #[cfg(feature = "full")]
+ pub fn parse_inner(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ pound: syn!(Pound) >>
+ bang: syn!(Bang) >>
+ path_and_tts: brackets!(tuple!(
+ call!(::Path::parse_mod_style),
+ call!(::TokenTree::parse_list)
+ )) >>
+ ({
+ let ((path, tts), bracket) = path_and_tts;
+
+ Attribute {
+ style: AttrStyle::Inner(bang),
+ path: path,
+ tts: tts,
+ is_sugared_doc: false,
+ pound_token: pound,
+ bracket_token: bracket,
+ }
+ })
+ )
+ |
+ map!(
+ lit_doc_comment,
+ |lit| Attribute {
+ style: AttrStyle::Inner(tokens::Bang::default()),
+ path: "doc".into(),
+ tts: vec![
+ ::TokenTree(eq()),
+ ::TokenTree(lit),
+ ],
+ is_sugared_doc: true,
+ pound_token: tokens::Pound::default(),
+ bracket_token: tokens::Bracket::default(),
+ }
+ )
+ }
+ }
+
+ pub fn parse_outer(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ pound: syn!(Pound) >>
+ path_and_tts: brackets!(tuple!(
+ call!(::Path::parse_mod_style),
+ call!(::TokenTree::parse_list)
+ )) >>
+ ({
+ let ((path, tts), bracket) = path_and_tts;
+
+ Attribute {
+ style: AttrStyle::Outer,
+ path: path,
+ tts: tts,
+ is_sugared_doc: false,
+ pound_token: pound,
+ bracket_token: bracket,
+ }
+ })
+ )
+ |
+ map!(
+ lit_doc_comment,
+ |lit| Attribute {
+ style: AttrStyle::Outer,
+ path: "doc".into(),
+ tts: vec![
+ ::TokenTree(eq()),
+ ::TokenTree(lit),
+ ],
+ is_sugared_doc: true,
+ pound_token: tokens::Pound::default(),
+ bracket_token: tokens::Bracket::default(),
+ }
+ )
+ }
+ }
}
- #[cfg(feature = "full")]
- named!(pub inner_attr -> Attribute, alt!(
- do_parse!(
- punct!("#") >>
- punct!("!") >>
- path_and_tts: delim!(Bracket, tuple!(mod_style_path, token_trees)) >>
- ({
- let (path, tts) = path_and_tts;
-
- Attribute {
- style: AttrStyle::Inner(tokens::Bang::default()),
- path: path,
- tts: tts,
- is_sugared_doc: false,
- pound_token: tokens::Pound::default(),
- bracket_token: tokens::Bracket::default(),
- }
- })
- )
- |
- do_parse!(
- comment: inner_doc_comment >>
- (Attribute {
- style: AttrStyle::Inner(tokens::Bang::default()),
- path: "doc".into(),
- tts: vec![
- eq(),
- doc(&format!("//!{}", content)),
- ],
- is_sugared_doc: true,
- pound_token: tokens::Pound::default(),
- bracket_token: tokens::Bracket::default(),
- })
- )
- |
- do_parse!(
- option!(whitespace) >>
- peek!(tag!("/*!")) >>
- com: block_comment >>
- (Attribute {
- style: AttrStyle::Inner(tokens::Bang::default()),
- path: "doc".into(),
- tts: vec![
- eq(),
- doc(com),
- ],
- is_sugared_doc: true,
- pound_token: tokens::Pound::default(),
- bracket_token: tokens::Bracket::default(),
- })
- )
- ));
-
- named!(pub outer_attr -> Attribute, alt!(
- do_parse!(
- punct!("#") >>
- path_and_tts: delim!(Bracket, tuple!(mod_style_path, token_trees)) >>
- ({
- let (path, tts) = path_and_tts;
-
- Attribute {
- style: AttrStyle::Outer,
- path: path,
- tts: tts,
- is_sugared_doc: false,
- pound_token: tokens::Pound::default(),
- bracket_token: tokens::Bracket::default(),
- }
- })
- )
- |
- do_parse!(
- punct!("///") >>
- not!(tag!("/")) >>
- content: take_until!("\n") >>
- (Attribute {
- style: AttrStyle::Outer,
- path: "doc".into(),
- tts: vec![
- eq(),
- doc(&format!("///{}", content)),
- ],
- is_sugared_doc: true,
- pound_token: tokens::Pound::default(),
- bracket_token: tokens::Bracket::default(),
- })
- )
- |
- do_parse!(
- option!(whitespace) >>
- peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
- com: block_comment >>
- (Attribute {
- style: AttrStyle::Outer,
- path: "doc".into(),
- tts: vec![
- eq(),
- doc(com),
- ],
- is_sugared_doc: true,
- pound_token: tokens::Pound::default(),
- bracket_token: tokens::Bracket::default(),
- })
- )
- ));
+ fn lit_doc_comment(input: &[TokenTree]) -> IResult<&[TokenTree], TokenTree> {
+ let mut tokens = input.iter();
+ let tok = match tokens.next() {
+ Some(tok) => tok,
+ None => return IResult::Error,
+ };
+ let literal = match tok.kind {
+ TokenKind::Literal(ref l) => l.to_string(),
+ _ => return IResult::Error,
+ };
+ if literal.starts_with("//") || literal.starts_with("/*") {
+ IResult::Done(tokens.as_slice(), tok.clone())
+ } else {
+ IResult::Error
+ }
+ }
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use quote::{Tokens, ToTokens};
- use proc_macro2::{Literal, TokenTree};
impl ToTokens for Attribute {
fn to_tokens(&self, tokens: &mut Tokens) {
@@ -431,32 +417,9 @@
if let Some(MetaItem::NameValue(ref pair)) = self.meta_item() {
if pair.ident == "doc" {
let value = pair.lit.value.to_string();
- match self.style {
- AttrStyle::Inner(_) if value.starts_with("//!") => {
- let doc = Literal::doccomment(&format!("{}\n", value));
- tokens.append(TokenTree {
- span: pair.lit.span.0,
- kind: TokenKind::Literal(doc),
- });
- return;
- }
- AttrStyle::Inner(_) if value.starts_with("/*!") => {
- pair.lit.to_tokens(tokens);
- return;
- }
- AttrStyle::Outer if value.starts_with("///") => {
- let doc = Literal::doccomment(&format!("{}\n", value));
- tokens.append(TokenTree {
- span: pair.lit.span.0,
- kind: TokenKind::Literal(doc),
- });
- return;
- }
- AttrStyle::Outer if value.starts_with("/**") => {
- pair.lit.to_tokens(tokens);
- return;
- }
- _ => {}
+ if value.starts_with('/') {
+ pair.lit.to_tokens(tokens);
+ return
}
}
}
diff --git a/src/constant.rs b/src/constant.rs
index 1a2818c..d76a827 100644
--- a/src/constant.rs
+++ b/src/constant.rs
@@ -89,103 +89,103 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use {BinOp, Ty};
- use lit::parsing::lit;
- use op::parsing::{binop, unop};
- use ty::parsing::{path, ty};
+ use proc_macro2::TokenTree;
+ use synom::{IResult, Synom};
+ use synom::tokens::*;
- named!(pub const_expr -> ConstExpr, do_parse!(
- mut e: alt!(
- expr_unary
- |
- expr_lit
- |
- expr_path
- |
- expr_paren
- // Cannot handle ConstExpr::Other here because for example
- // `[u32; n!()]` would end up successfully parsing `n` as
- // ConstExpr::Path and then fail to parse `!()`. Instead, callers
- // are required to handle Other. See ty::parsing::array_len and
- // data::parsing::discriminant.
- ) >>
- many0!(alt!(
- tap!(args: and_call => {
- let (args, paren) = args;
- e = ConstCall {
- func: Box::new(e),
- args: args,
- paren_token: paren,
- }.into();
- })
- |
- tap!(more: and_binary => {
- let (op, other) = more;
- e = ConstBinary { op: op, left: Box::new(e), right: Box::new(other) }.into();
- })
- |
- tap!(ty: and_cast => {
- let (ty, token) = ty;
- e = ConstCast {
- expr: Box::new(e),
- ty: Box::new(ty),
- as_token: token,
- }.into();
- })
- |
- tap!(i: and_index => {
- let (i, bracket) = i;
- e = ConstIndex {
- expr: Box::new(e),
- index: Box::new(i),
- bracket_token: bracket,
- }.into();
- })
- )) >>
- (e)
- ));
+ impl Synom for ConstExpr {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ mut e: alt!(
+ map!(syn!(ConstUnary), |e: ConstUnary| e.into())
+ |
+ map!(syn!(Lit), |e: Lit| e.into())
+ |
+ map!(syn!(Path), |e: Path| e.into())
+ |
+ map!(syn!(ConstParen), |e: ConstParen| e.into())
+ // Cannot handle ConstExpr::Other here because for example
+ // `[u32; n!()]` would end up successfully parsing `n` as
+ // ConstExpr::Path and then fail to parse `!()`. Instead, callers
+ // are required to handle Other. See ty::parsing::array_len and
+ // data::parsing::discriminant.
+ ) >>
+ many0!(alt!(
+ tap!(args: and_call => {
+ let (args, paren) = args;
+ e = ConstCall {
+ func: Box::new(e),
+ args: args,
+ paren_token: paren,
+ }.into();
+ })
+ |
+ tap!(more: and_binary => {
+ let (op, other) = more;
+ e = ConstBinary { op: op, left: Box::new(e), right: Box::new(other) }.into();
+ })
+ |
+ tap!(ty: and_cast => {
+ let (ty, token) = ty;
+ e = ConstCast {
+ expr: Box::new(e),
+ ty: Box::new(ty),
+ as_token: token,
+ }.into();
+ })
+ |
+ tap!(i: and_index => {
+ let (i, bracket) = i;
+ e = ConstIndex {
+ expr: Box::new(e),
+ index: Box::new(i),
+ bracket_token: bracket,
+ }.into();
+ })
+ )) >>
+ (e)
+ }
+ }
+ }
- named!(and_call -> (Delimited<ConstExpr, tokens::Comma>, tokens::Paren), do_parse!(
- punct!("(") >>
- args: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- const_expr) >>
- punct!(")") >>
- (args, tokens::Paren::default())
- ));
+ named!(and_call -> (Delimited<ConstExpr, tokens::Comma>, tokens::Paren),
+ parens!(call!(Delimited::parse_terminated)));
- named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
+ named!(and_binary -> (BinOp, ConstExpr),
+ tuple!(call!(BinOp::parse_binop), syn!(ConstExpr)));
- named!(expr_unary -> ConstExpr, do_parse!(
- operator: unop >>
- operand: const_expr >>
- (ConstUnary { op: operator, expr: Box::new(operand) }.into())
- ));
+ impl Synom for ConstUnary {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ operator: syn!(UnOp) >>
+ operand: syn!(ConstExpr) >>
+ (ConstUnary { op: operator, expr: Box::new(operand) })
+ }
+ }
+ }
- named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
+ named!(and_index -> (ConstExpr, tokens::Bracket),
+ brackets!(syn!(ConstExpr)));
- named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
-
- named!(and_index -> (ConstExpr, tokens::Bracket), do_parse!(
- punct!("[") >>
- expr: const_expr >>
- punct!("]") >>
- (expr, tokens::Bracket::default())
- ));
-
- named!(expr_paren -> ConstExpr, do_parse!(
- punct!("(") >>
- e: const_expr >>
- punct!(")") >>
- (ConstParen {
- expr: Box::new(e),
- paren_token: tokens::Paren::default(),
- }.into())
- ));
+ impl Synom for ConstParen {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ parens: parens!(syn!(ConstExpr)) >>
+ (ConstParen {
+ expr: Box::new(parens.0),
+ paren_token: parens.1,
+ })
+ }
+ }
+ }
named!(and_cast -> (Ty, tokens::As), do_parse!(
- keyword!("as") >>
- ty: ty >>
- (ty, tokens::As::default())
+ as_tok: syn!(As) >>
+ ty: syn!(Ty) >>
+ (ty, as_tok)
));
}
diff --git a/src/data.rs b/src/data.rs
index a1cf522..290c8ff 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -107,196 +107,109 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use WhereClause;
- #[cfg(feature = "full")]
- use ConstExpr;
- use attr::parsing::outer_attr;
- #[cfg(feature = "full")]
- use constant::parsing::const_expr;
- #[cfg(feature = "full")]
- use expr::parsing::expr;
- use generics::parsing::where_clause;
- use ident::parsing::ident;
- use ty::parsing::{mod_style_path, ty};
- named!(pub struct_body -> (WhereClause, VariantData, Option<tokens::Semi>), alt!(
- do_parse!(
- wh: where_clause >>
- body: struct_like_body >>
- (wh, VariantData::Struct(body.0, body.1), None)
- )
- |
- do_parse!(
- body: tuple_like_body >>
- wh: where_clause >>
- punct!(";") >>
- (wh, VariantData::Tuple(body.0, body.1), Some(tokens::Semi::default()))
- )
- |
- do_parse!(
- wh: where_clause >>
- punct!(";") >>
- (wh, VariantData::Unit, Some(tokens::Semi::default()))
- )
- ));
+ use synom::{IResult, Synom};
+ use synom::tokens;
+ use synom::tokens::*;
+ use proc_macro2::TokenTree;
- named!(pub enum_body -> (WhereClause, Delimited<Variant, tokens::Comma>, tokens::Brace), do_parse!(
- wh: where_clause >>
- punct!("{") >>
- variants: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- variant) >>
- punct!("}") >>
- (wh, variants, tokens::Brace::default())
- ));
+ impl Field {
+ pub fn parse_struct(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ id: syn!(Ident) >>
+ colon: syn!(Colon) >>
+ ty: syn!(Ty) >>
+ (Field {
+ ident: Some(id),
+ vis: vis,
+ attrs: attrs,
+ ty: ty,
+ colon_token: Some(colon),
+ })
+ }
+ }
- named!(variant -> Variant, do_parse!(
- attrs: many0!(outer_attr) >>
- id: ident >>
- data: alt!(
- struct_like_body => { |(d, b)| VariantData::Struct(d, b) }
- |
- tuple_like_body => { |(d, b)| VariantData::Tuple(d, b) }
- |
- epsilon!() => { |_| VariantData::Unit }
- ) >>
- disr: option!(preceded!(punct!("="), discriminant)) >>
- (Variant {
- ident: id,
- attrs: attrs,
- data: data,
- eq_token: disr.as_ref().map(|_| tokens::Eq::default()),
- discriminant: disr,
- })
- ));
-
- #[cfg(not(feature = "full"))]
- use constant::parsing::const_expr as discriminant;
-
- #[cfg(feature = "full")]
- named!(discriminant -> ConstExpr, alt!(
- terminated!(const_expr, after_discriminant)
- |
- terminated!(expr, after_discriminant) => { ConstExpr::Other }
- ));
-
- // XXX: HACKY
- #[cfg(feature = "full")]
- pub fn eof(input: &[synom::TokenTree]) -> synom::IResult<&[synom::TokenTree], &'static str> {
- if input.is_empty() {
- synom::IResult::Done(&[], "")
- } else {
- synom::IResult::Error
+ pub fn parse_tuple(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ ty: syn!(Ty) >>
+ (Field {
+ ident: None,
+ colon_token: None,
+ vis: vis,
+ attrs: attrs,
+ ty: ty,
+ })
+ }
}
}
- #[cfg(feature = "full")]
- named!(after_discriminant -> &str, peek!(alt!(punct!(",") | input_end!())));
-
- named!(pub struct_like_body -> (Delimited<Field, tokens::Comma>, tokens::Brace), do_parse!(
- punct!("{") >>
- fields: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- struct_field) >>
- punct!("}") >>
- (fields, tokens::Brace::default())
- ));
-
- named!(tuple_like_body -> (Delimited<Field, tokens::Comma>, tokens::Paren), do_parse!(
- punct!("(") >>
- fields: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- tuple_field) >>
- punct!(")") >>
- (fields, tokens::Paren::default())
- ));
-
- named!(struct_field -> Field, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- id: ident >>
- punct!(":") >>
- ty: ty >>
- (Field {
- ident: Some(id),
- vis: vis,
- attrs: attrs,
- ty: ty,
- colon_token: Some(tokens::Colon::default()),
- })
- ));
-
- named!(tuple_field -> Field, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- ty: ty >>
- (Field {
- ident: None,
- colon_token: None,
- vis: vis,
- attrs: attrs,
- ty: ty,
- })
- ));
-
- named!(pub visibility -> Visibility, alt!(
- do_parse!(
- keyword!("pub") >>
- punct!("(") >>
- keyword!("crate") >>
- punct!(")") >>
- (Visibility::Crate(VisCrate {
- crate_token: tokens::Crate::default(),
- paren_token: tokens::Paren::default(),
- pub_token: tokens::Pub::default(),
- }))
- )
- |
- do_parse!(
- keyword!("pub") >>
- punct!("(") >>
- keyword!("self") >>
- punct!(")") >>
- (Visibility::Restricted(VisRestricted {
- path: Box::new("self".into()),
- in_token: None,
- paren_token: tokens::Paren::default(),
- pub_token: tokens::Pub::default(),
- }))
- )
- |
- do_parse!(
- keyword!("pub") >>
- punct!("(") >>
- keyword!("super") >>
- punct!(")") >>
- (Visibility::Restricted(VisRestricted {
- path: Box::new("super".into()),
- in_token: None,
- paren_token: tokens::Paren::default(),
- pub_token: tokens::Pub::default(),
- }))
- )
- |
- do_parse!(
- keyword!("pub") >>
- punct!("(") >>
- keyword!("in") >>
- restricted: mod_style_path >>
- punct!(")") >>
- (Visibility::Restricted(VisRestricted {
- path: Box::new(restricted),
- in_token: Some(tokens::In::default()),
- paren_token: tokens::Paren::default(),
- pub_token: tokens::Pub::default(),
- }))
- )
- |
- keyword!("pub") => { |_| {
- Visibility::Public(VisPublic {
- pub_token: tokens::Pub::default(),
- })
- } }
- |
- epsilon!() => { |_| Visibility::Inherited(VisInherited {}) }
- ));
+ impl Synom for Visibility {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ pub_token: syn!(Pub) >>
+ other: parens!(syn!(tokens::Crate)) >>
+ (Visibility::Crate(VisCrate {
+ crate_token: other.0,
+ paren_token: other.1,
+ pub_token: pub_token,
+ }))
+ )
+ |
+ do_parse!(
+ pub_token: syn!(Pub) >>
+ other: parens!(syn!(Self_)) >>
+ (Visibility::Restricted(VisRestricted {
+ path: Box::new(other.0.into()),
+ in_token: None,
+ paren_token: other.1,
+ pub_token: pub_token,
+ }))
+ )
+ |
+ do_parse!(
+ pub_token: syn!(Pub) >>
+ other: parens!(syn!(Super)) >>
+ (Visibility::Restricted(VisRestricted {
+ path: Box::new(other.0.into()),
+ in_token: None,
+ paren_token: other.1,
+ pub_token: pub_token,
+ }))
+ )
+ |
+ do_parse!(
+ pub_token: syn!(Pub) >>
+ other: parens!(do_parse!(
+ in_tok: syn!(In) >>
+ restricted: call!(Path::parse_mod_style) >>
+ (in_tok, restricted)
+ )) >>
+ (Visibility::Restricted(VisRestricted {
+ path: Box::new((other.0).1),
+ in_token: Some((other.0).0),
+ paren_token: other.1,
+ pub_token: pub_token,
+ }))
+ )
+ |
+ syn!(Pub) => { |tok| {
+ Visibility::Public(VisPublic {
+ pub_token: tok,
+ })
+ } }
+ |
+ epsilon!() => { |_| Visibility::Inherited(VisInherited {}) }
+ }
+ }
+ }
}
#[cfg(feature = "printing")]
diff --git a/src/derive.rs b/src/derive.rs
index cf44b4d..7d6aabd 100644
--- a/src/derive.rs
+++ b/src/derive.rs
@@ -46,51 +46,144 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use Generics;
- use attr::parsing::outer_attr;
- use data::parsing::{visibility, struct_body, enum_body};
- use generics::parsing::generics;
- use ident::parsing::ident;
- named!(pub derive_input -> DeriveInput, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- which: alt!(keyword!("struct") | keyword!("enum")) >>
- id: ident >>
- generics: generics >>
- item: switch!(value!(which),
- "struct" => map!(struct_body, move |(wh, body, semi)| DeriveInput {
- ident: id,
- vis: vis,
- attrs: attrs,
- generics: Generics {
- where_clause: wh,
- .. generics
- },
- body: Body::Struct(BodyStruct {
- struct_token: tokens::Struct::default(),
- data: body,
- semi_token: semi,
- }),
- })
- |
- "enum" => map!(enum_body, move |(wh, body, brace)| DeriveInput {
- ident: id,
- vis: vis,
- attrs: attrs,
- generics: Generics {
- where_clause: wh,
- .. generics
- },
- body: Body::Enum(BodyEnum {
- variants: body,
- brace_token: brace,
- enum_token: tokens::Enum::default(),
- }),
- })
- ) >>
- (item)
+ use proc_macro2::TokenTree;
+ use synom::{IResult, Synom};
+ use synom::tokens::*;
+
+ impl Synom for DeriveInput {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ which: alt!(
+ syn!(Struct) => { Ok }
+ |
+ // weird hack to get around exhaustiveness check below
+ syn!(Enum) => { |e| Err((e, 1)) }
+ ) >>
+ id: syn!(Ident) >>
+ generics: syn!(Generics) >>
+ item: switch!(value!(which),
+ Ok(s) => map!(struct_body, move |(wh, body, semi)| DeriveInput {
+ ident: id,
+ vis: vis,
+ attrs: attrs,
+ generics: Generics {
+ where_clause: wh,
+ .. generics
+ },
+ body: Body::Struct(BodyStruct {
+ struct_token: s,
+ data: body,
+ semi_token: semi,
+ }),
+ })
+ |
+ Err((e, 1)) => map!(enum_body, move |(wh, body, brace)| DeriveInput {
+ ident: id,
+ vis: vis,
+ attrs: attrs,
+ generics: Generics {
+ where_clause: wh,
+ .. generics
+ },
+ body: Body::Enum(BodyEnum {
+ variants: body,
+ brace_token: brace,
+ enum_token: e,
+ }),
+ })
+ ) >>
+ (item)
+ }
+ }
+
+ fn description() -> Option<&'static str> {
+ Some("derive input")
+ }
+ }
+
+
+ named!(struct_body -> (WhereClause, VariantData, Option<tokens::Semi>), alt!(
+ do_parse!(
+ wh: syn!(WhereClause) >>
+ body: struct_like_body >>
+ (wh, VariantData::Struct(body.0, body.1), None)
+ )
+ |
+ do_parse!(
+ body: tuple_like_body >>
+ wh: syn!(WhereClause) >>
+ semi: syn!(Semi) >>
+ (wh, VariantData::Tuple(body.0, body.1), Some(semi))
+ )
+ |
+ do_parse!(
+ wh: syn!(WhereClause) >>
+ semi: syn!(Semi) >>
+ (wh, VariantData::Unit, Some(semi))
+ )
));
+
+ named!(enum_body -> (WhereClause, Delimited<Variant, tokens::Comma>, tokens::Brace), do_parse!(
+ wh: syn!(WhereClause) >>
+ data: braces!(Delimited::parse_terminated) >>
+ (wh, data.0, data.1)
+ ));
+
+ impl Synom for Variant {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ id: syn!(Ident) >>
+ data: alt!(
+ struct_like_body => { |(d, b)| VariantData::Struct(d, b) }
+ |
+ tuple_like_body => { |(d, b)| VariantData::Tuple(d, b) }
+ |
+ epsilon!() => { |_| VariantData::Unit }
+ ) >>
+ disr: option!(do_parse!(
+ eq: syn!(Eq) >>
+ disr: discriminant >>
+ (eq, disr)
+ )) >>
+ (Variant {
+ ident: id,
+ attrs: attrs,
+ data: data,
+ eq_token: disr.as_ref().map(|p| tokens::Eq((p.0).0)),
+ discriminant: disr.map(|p| p.1),
+ })
+ }
+ }
+ }
+
+ #[cfg(not(feature = "full"))]
+ named!(discriminant -> ConstExpr, syn!(ConstExpr));
+
+ #[cfg(feature = "full")]
+ named!(discriminant -> ConstExpr, alt!(
+ terminated!(syn!(ConstExpr), after_discriminant)
+ |
+ terminated!(syn!(Expr), after_discriminant) => { ConstExpr::Other }
+ ));
+
+ #[cfg(feature = "full")]
+ named!(after_discriminant -> (), peek!(alt!(
+ syn!(Comma) => { |_| () }
+ |
+ input_end!() => { |_| () }
+ )));
+
+ named!(struct_like_body -> (Delimited<Field, tokens::Comma>, tokens::Brace),
+ braces!(call!(Delimited::parse_terminated_with, Field::parse_struct)));
+
+ named!(tuple_like_body -> (Delimited<Field, tokens::Comma>, tokens::Paren),
+ parens!(call!(Delimited::parse_terminated_with, Field::parse_tuple)));
}
#[cfg(feature = "printing")]
diff --git a/src/expr.rs b/src/expr.rs
index 6ec7253..23f2faa 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -26,7 +26,7 @@
/// A `box x` expression.
pub Box(ExprBox {
pub expr: Box<Expr>,
- pub box_token: tokens::Box,
+ pub box_token: tokens::Box_,
}),
/// E.g. 'place <- val'.
@@ -485,7 +485,7 @@
/// A `box` pattern
pub Box(PatBox {
pub pat: Box<Pat>,
- pub box_token: tokens::Box,
+ pub box_token: tokens::Box_,
}),
/// A reference pattern, e.g. `&mut (a, b)`
pub Ref(PatRef {
@@ -587,20 +587,11 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use {BinOp, FnArg, FnDecl, FunctionRetTy, Ident, Lifetime, Mac,
- TokenTree, Ty, UnOp, Unsafety, ArgCaptured, TyInfer};
- use attr::parsing::outer_attr;
- use generics::parsing::lifetime;
- use ident::parsing::{ident, wordlike};
- use item::parsing::item;
- use lit::parsing::lit;
- use mac::parsing::{mac, token_stream};
- use synom::IResult::{self, Error};
- use op::parsing::{assign_op, binop, unop};
- use ty::parsing::{mutability, path, qpath, ty, unsafety};
- use synom::{self, IResult};
+ use ty::parsing::qpath;
- use proc_macro2::{self, TokenKind, Delimiter};
+ use proc_macro2::{TokenTree, TokenStream, TokenKind, Delimiter};
+ use synom::{IResult, Synom};
+ use synom::tokens::*;
// Struct literals are ambiguous in certain positions
// https://github.com/rust-lang/rfcs/pull/92
@@ -619,7 +610,16 @@
};
}
- named!(pub expr -> Expr, ambiguous_expr!(true));
+ impl Synom for Expr {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ ambiguous_expr!(input, true)
+ }
+
+ fn description() -> Option<&'static str> {
+ Some("expression")
+ }
+ }
+
named!(expr_no_struct -> Expr, ambiguous_expr!(false));
@@ -628,56 +628,61 @@
allow_struct: bool,
allow_block: bool)
-> IResult<&[synom::TokenTree], Expr> {
- do_parse!(
+ do_parse! {
i,
mut e: alt!(
- expr_lit // must be before expr_struct
+ syn!(Lit) => { ExprKind::Lit } // must be before expr_struct
|
- cond_reduce!(allow_struct, expr_struct) // must be before expr_path
+ // must be before expr_path
+ cond_reduce!(allow_struct, map!(syn!(ExprStruct), ExprKind::Struct))
|
- expr_paren // must be before expr_tup
+ syn!(ExprParen) => { ExprKind::Paren } // must be before expr_tup
|
- expr_mac // must be before expr_path
+ syn!(Mac) => { ExprKind::Mac } // must be before expr_path
|
call!(expr_break, allow_struct) // must be before expr_path
|
- expr_continue // must be before expr_path
+ syn!(ExprContinue) => { ExprKind::Continue } // must be before expr_path
|
call!(expr_ret, allow_struct) // must be before expr_path
|
call!(expr_box, allow_struct)
|
- expr_in_place
+ syn!(ExprInPlace) => { ExprKind::InPlace }
|
- expr_array
+ syn!(ExprArray) => { ExprKind::Array }
|
- expr_tup
+ syn!(ExprTup) => { ExprKind::Tup }
|
call!(expr_unary, allow_struct)
|
- expr_if
+ syn!(ExprIf) => { ExprKind::If }
|
- expr_while
+ syn!(ExprIfLet) => { ExprKind::IfLet }
|
- expr_for_loop
+ syn!(ExprWhile) => { ExprKind::While }
|
- expr_loop
+ syn!(ExprWhileLet) => { ExprKind::WhileLet }
|
- expr_match
+ syn!(ExprForLoop) => { ExprKind::ForLoop }
|
- expr_catch
+ syn!(ExprLoop) => { ExprKind::Loop }
+ |
+ syn!(ExprMatch) => { ExprKind::Match }
+ |
+ syn!(ExprCatch) => { ExprKind::Catch }
|
call!(expr_closure, allow_struct)
|
- cond_reduce!(allow_block, expr_block)
+ cond_reduce!(allow_block, map!(syn!(ExprBlock), ExprKind::Block))
|
call!(expr_range, allow_struct)
|
- expr_path
+ syn!(ExprPath) => { ExprKind::Path }
|
call!(expr_addr_of, allow_struct)
|
- expr_repeat
+ syn!(ExprRepeat) => { ExprKind::Repeat }
) >>
many0!(alt!(
tap!(args: and_call => {
@@ -776,287 +781,315 @@
}.into();
})
|
- tap!(_try: punct!("?") => {
+ tap!(question: syn!(Question) => {
e = ExprTry {
expr: Box::new(e.into()),
- question_token: tokens::Question::default(),
+ question_token: question,
}.into();
})
)) >>
(e.into())
- )
+ }
}
- named!(expr_mac -> ExprKind, map!(mac, ExprKind::Mac));
-
- named!(expr_paren -> ExprKind, do_parse!(
- punct!("(") >>
- e: expr >>
- punct!(")") >>
- (ExprParen {
- expr: Box::new(e),
- paren_token: tokens::Paren::default(),
- }.into())
- ));
+ impl Synom for ExprParen {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ e: parens!(syn!(Expr)) >>
+ (ExprParen {
+ expr: Box::new(e.0),
+ paren_token: e.1,
+ }.into())
+ }
+ }
+ }
named_ambiguous_expr!(expr_box -> ExprKind, allow_struct, do_parse!(
- keyword!("box") >>
+ box_: syn!(Box_) >>
inner: ambiguous_expr!(allow_struct) >>
(ExprBox {
expr: Box::new(inner),
- box_token: tokens::Box::default(),
+ box_token: box_,
}.into())
));
- named!(expr_in_place -> ExprKind, do_parse!(
- keyword!("in") >>
- place: expr_no_struct >>
- punct!("{") >>
- value: within_block >>
- punct!("}") >>
- (ExprInPlace {
- in_token: tokens::In::default(),
- place: Box::new(place),
- value: Box::new(Expr {
- node: ExprBlock {
- unsafety: Unsafety::Normal,
- block: Block {
- stmts: value,
- brace_token: tokens::Brace::default(),
- },
- }.into(),
- attrs: Vec::new(),
- }),
- }.into())
- ));
+ impl Synom for ExprInPlace {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ in_: syn!(In) >>
+ place: expr_no_struct >>
+ value: braces!(call!(Block::parse_within)) >>
+ (ExprInPlace {
+ in_token: in_,
+ place: Box::new(place),
+ value: Box::new(Expr {
+ node: ExprBlock {
+ unsafety: Unsafety::Normal,
+ block: Block {
+ stmts: value.0,
+ brace_token: value.1,
+ },
+ }.into(),
+ attrs: Vec::new(),
+ }),
+ })
+ }
+ }
+ }
- named!(expr_array -> ExprKind, do_parse!(
- punct!("[") >>
- elems: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- expr) >>
- punct!("]") >>
- (ExprArray {
- exprs: elems,
- bracket_token: tokens::Bracket::default(),
- }.into())
- ));
+ impl Synom for ExprArray {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ elems: brackets!(call!(Delimited::parse_terminated)) >>
+ (ExprArray {
+ exprs: elems.0,
+ bracket_token: elems.1,
+ })
+ }
+ }
+ }
- named!(and_call -> (Delimited<Expr, tokens::Comma>, tokens::Paren), do_parse!(
- punct!("(") >>
- args: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- expr) >>
- punct!(")") >>
- (args, tokens::Paren::default())
- ));
+ named!(and_call -> (Delimited<Expr, tokens::Comma>, tokens::Paren),
+ parens!(call!(Delimited::parse_terminated)));
named!(and_method_call -> ExprMethodCall, do_parse!(
- punct!(".") >>
- method: ident >>
+ dot: syn!(Dot) >>
+ method: syn!(Ident) >>
typarams: option!(do_parse!(
- punct!("::") >>
- punct!("<") >>
- tys: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- ty) >>
- punct!(">") >>
- (tys)
+ colon2: syn!(Colon2) >>
+ lt: syn!(Lt) >>
+ tys: call!(Delimited::parse_terminated) >>
+ gt: syn!(Gt) >>
+ (colon2, lt, tys, gt)
)) >>
- punct!("(") >>
- args: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- expr) >>
- punct!(")") >>
- (ExprMethodCall {
- // this expr will get overwritten after being returned
- expr: Box::new(ExprKind::Lit(Lit {
- span: Span::default(),
- value: LitKind::Bool(false),
- }).into()),
+ args: parens!(call!(Delimited::parse_terminated)) >>
+ ({
+ let (colon2, lt, tys, gt) = match typarams {
+ Some((a, b, c, d)) => (Some(a), Some(b), Some(c), Some(d)),
+ None => (None, None, None, None),
+ };
+ ExprMethodCall {
+ // this expr will get overwritten after being returned
+ expr: Box::new(ExprKind::Lit(Lit {
+ span: Span::default(),
+ value: LitKind::Bool(false),
+ }).into()),
- method: method,
- args: args,
- paren_token: tokens::Paren::default(),
- dot_token: tokens::Dot::default(),
- lt_token: typarams.as_ref().map(|_| tokens::Lt::default()),
- gt_token: typarams.as_ref().map(|_| tokens::Gt::default()),
- colon2_token: typarams.as_ref().map(|_| tokens::Colon2::default()),
- typarams: typarams.unwrap_or_default(),
+ method: method,
+ args: args.0,
+ paren_token: args.1,
+ dot_token: dot,
+ lt_token: lt,
+ gt_token: gt,
+ colon2_token: colon2,
+ typarams: tys.unwrap_or_default(),
+ }
})
));
- named!(expr_tup -> ExprKind, do_parse!(
- punct!("(") >>
- elems: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- expr) >>
- punct!(")") >>
- (ExprTup {
- args: elems,
- paren_token: tokens::Paren::default(),
- lone_comma: None, // TODO: parse this
- }.into())
- ));
+ impl Synom for ExprTup {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ elems: parens!(call!(Delimited::parse_terminated)) >>
+ (ExprTup {
+ args: elems.0,
+ paren_token: elems.1,
+ lone_comma: None, // TODO: parse this
+ })
+ }
+ }
+ }
named_ambiguous_expr!(and_binary -> (BinOp, Expr), allow_struct, tuple!(
- binop,
+ call!(BinOp::parse_binop),
ambiguous_expr!(allow_struct)
));
named_ambiguous_expr!(expr_unary -> ExprKind, allow_struct, do_parse!(
- operator: unop >>
+ operator: syn!(UnOp) >>
operand: ambiguous_expr!(allow_struct) >>
(ExprUnary { op: operator, expr: Box::new(operand) }.into())
));
- named!(expr_lit -> ExprKind, map!(lit, ExprKind::Lit));
-
- named!(and_cast -> (Ty, tokens::As), do_parse!(
- keyword!("as") >>
- ty: ty >>
- (ty, tokens::As::default())
+ named!(and_cast -> (Ty, As), do_parse!(
+ as_: syn!(As) >>
+ ty: syn!(Ty) >>
+ (ty, as_)
));
- named!(and_ascription -> (Ty, tokens::Colon),
- preceded!(punct!(":"), map!(ty, |t| (t, tokens::Colon::default()))));
+ named!(and_ascription -> (Ty, Colon),
+ map!(tuple!(syn!(Colon), syn!(Ty)), |(a, b)| (b, a)));
- enum Cond {
- Let(Pat, Expr, tokens::Eq, tokens::Let),
- Expr(Expr),
+ impl Synom for ExprIfLet {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ if_: syn!(If) >>
+ let_: syn!(Let) >>
+ pat: syn!(Pat) >>
+ eq: syn!(Eq) >>
+ cond: expr_no_struct >>
+ then_block: braces!(call!(Block::parse_within)) >>
+ else_block: option!(else_block) >>
+ (ExprIfLet {
+ pat: Box::new(pat),
+ let_token: let_,
+ eq_token: eq,
+ expr: Box::new(cond),
+ if_true: Block {
+ stmts: then_block.0,
+ brace_token: then_block.1,
+ },
+ if_token: if_,
+ else_token: else_block.as_ref().map(|p| Else((p.0).0)),
+ if_false: else_block.map(|p| Box::new(p.1.into())),
+ })
+ }
+ }
}
- named!(cond -> Cond, alt!(
- do_parse!(
- keyword!("let") >>
- pat: pat >>
- punct!("=") >>
- value: expr_no_struct >>
- (Cond::Let(pat, value, tokens::Eq::default(), tokens::Let::default()))
- )
- |
- map!(expr_no_struct, Cond::Expr)
- ));
+ impl Synom for ExprIf {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ if_: syn!(If) >>
+ cond: expr_no_struct >>
+ then_block: braces!(call!(Block::parse_within)) >>
+ else_block: option!(else_block) >>
+ (ExprIf {
+ cond: Box::new(cond),
+ if_true: Block {
+ stmts: then_block.0,
+ brace_token: then_block.1,
+ },
+ if_token: if_,
+ else_token: else_block.as_ref().map(|p| Else((p.0).0)),
+ if_false: else_block.map(|p| Box::new(p.1.into())),
+ })
+ }
+ }
+ }
- named!(expr_if -> ExprKind, do_parse!(
- keyword!("if") >>
- cond: cond >>
- then_block: delim!(Brace, within_block) >>
- else_block: option!(preceded!(
- keyword!("else"),
- alt!(
- expr_if
- |
- do_parse!(
- punct!("{") >>
- else_block: within_block >>
- punct!("}") >>
- (ExprKind::Block(ExprBlock {
- unsafety: Unsafety::Normal,
- block: Block {
- stmts: else_block,
- brace_token: tokens::Brace::default(),
- },
- }).into())
- )
+ named!(else_block -> (Else, ExprKind), do_parse!(
+ else_: syn!(Else) >>
+ expr: alt!(
+ syn!(ExprIf) => { ExprKind::If }
+ |
+ syn!(ExprIfLet) => { ExprKind::IfLet }
+ |
+ do_parse!(
+ else_block: braces!(call!(Block::parse_within)) >>
+ (ExprKind::Block(ExprBlock {
+ unsafety: Unsafety::Normal,
+ block: Block {
+ stmts: else_block.0,
+ brace_token: else_block.1,
+ },
+ }))
)
- )) >>
- (match cond {
- Cond::Let(pat, expr, eq_token, let_token) => ExprIfLet {
- pat: Box::new(pat),
- expr: Box::new(expr),
- eq_token: eq_token,
- let_token: let_token,
- if_true: Block {
- stmts: then_block,
- brace_token: tokens::Brace::default(),
- },
- if_token: tokens::If::default(),
- else_token: else_block.as_ref().map(|_| tokens::Else::default()),
- if_false: else_block.map(|els| Box::new(els.into())),
- }.into(),
- Cond::Expr(cond) => ExprIf {
- cond: Box::new(cond),
- if_true: Block {
- stmts: then_block,
- brace_token: tokens::Brace::default(),
- },
- if_token: tokens::If::default(),
- else_token: else_block.as_ref().map(|_| tokens::Else::default()),
- if_false: else_block.map(|els| Box::new(els.into())),
- }.into(),
- })
+ ) >>
+ (else_, expr)
));
- named!(expr_for_loop -> ExprKind, do_parse!(
- lbl: option!(terminated!(label, punct!(":"))) >>
- keyword!("for") >>
- pat: pat >>
- keyword!("in") >>
- expr: expr_no_struct >>
- loop_block: block >>
- (ExprForLoop {
- for_token: tokens::For::default(),
- in_token: tokens::In::default(),
- colon_token: lbl.as_ref().map(|_| tokens::Colon::default()),
- pat: Box::new(pat),
- expr: Box::new(expr),
- body: loop_block,
- label: lbl,
- }.into())
- ));
- named!(expr_loop -> ExprKind, do_parse!(
- lbl: option!(terminated!(label, punct!(":"))) >>
- keyword!("loop") >>
- loop_block: block >>
- (ExprLoop {
- loop_token: tokens::Loop::default(),
- colon_token: lbl.as_ref().map(|_| tokens::Colon::default()),
- body: loop_block,
- label: lbl,
- }.into())
- ));
+ impl Synom for ExprForLoop {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ lbl: option!(tuple!(label, syn!(Colon))) >>
+ for_: syn!(For) >>
+ pat: syn!(Pat) >>
+ in_: syn!(In) >>
+ expr: expr_no_struct >>
+ loop_block: syn!(Block) >>
+ (ExprForLoop {
+ for_token: for_,
+ in_token: in_,
+ pat: Box::new(pat),
+ expr: Box::new(expr),
+ body: loop_block,
+ colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
+ label: lbl.map(|p| p.0),
+ })
+ }
+ }
+ }
- named!(expr_match -> ExprKind, do_parse!(
- keyword!("match") >>
- obj: expr_no_struct >>
- res: delim!(Brace, do_parse!(
- mut arms: many0!(do_parse!(
- arm: match_arm >>
- cond!(arm_requires_comma(&arm), punct!(",")) >>
- cond!(!arm_requires_comma(&arm), option!(punct!(","))) >>
- (arm)
- )) >>
- last_arm: option!(match_arm) >>
- (ExprKind::Match(Box::new(obj), {
- arms.extend(last_arm);
- arms
- }))
- )) >>
- last_arm: option!(match_arm) >>
- punct!("}") >>
- (ExprMatch {
- expr: Box::new(obj),
- match_token: tokens::Match::default(),
- brace_token: tokens::Brace::default(),
- arms: {
- for arm in &mut arms {
- if arm_requires_comma(arm) {
- arm.comma = Some(tokens::Comma::default());
+ impl Synom for ExprLoop {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ lbl: option!(tuple!(label, syn!(Colon))) >>
+ loop_: syn!(Loop) >>
+ loop_block: syn!(Block) >>
+ (ExprLoop {
+ loop_token: loop_,
+ body: loop_block,
+ colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
+ label: lbl.map(|p| p.0),
+ })
+ }
+ }
+ }
+
+ impl Synom for ExprMatch {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ match_: syn!(Match) >>
+ obj: expr_no_struct >>
+ res: braces!(do_parse!(
+ mut arms: many0!(do_parse!(
+ arm: syn!(Arm) >>
+ cond!(arm_requires_comma(&arm), syn!(Comma)) >>
+ cond!(!arm_requires_comma(&arm), option!(syn!(Comma))) >>
+ (arm)
+ )) >>
+ last_arm: option!(syn!(Arm)) >>
+ ({
+ arms.extend(last_arm);
+ arms
+ })
+ )) >>
+ ({
+ let (mut arms, brace) = res;
+ ExprMatch {
+ expr: Box::new(obj),
+ match_token: match_,
+ brace_token: brace,
+ arms: {
+ for arm in &mut arms {
+ if arm_requires_comma(arm) {
+ arm.comma = Some(tokens::Comma::default());
+ }
+ }
+ arms
+ },
}
- }
- arms.extend(last_arm);
- arms
- },
- }.into())
- ));
+ })
+ }
+ }
+ }
- named!(expr_catch -> ExprKind, do_parse!(
- keyword!("do") >>
- keyword!("catch") >>
- catch_block: block >>
- (ExprCatch {
- block: catch_block,
- do_token: tokens::Do::default(),
- catch_token: tokens::Catch::default(),
- }.into())
- ));
+ impl Synom for ExprCatch {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ do_: syn!(Do) >>
+ catch_: syn!(Catch) >>
+ catch_block: syn!(Block) >>
+ (ExprCatch {
+ block: catch_block,
+ do_token: do_,
+ catch_token: catch_,
+ }.into())
+ }
+ }
+ }
fn arm_requires_comma(arm: &Arm) -> bool {
if let ExprKind::Block(ExprBlock { unsafety: Unsafety::Normal, .. }) = arm.body.node {
@@ -1066,45 +1099,48 @@
}
}
- named!(match_arm -> Arm, do_parse!(
- attrs: many0!(outer_attr) >>
- pats: separated_nonempty_list!(map!(punct!("|"), |_| tokens::Or::default()),
- pat) >>
- guard: option!(preceded!(keyword!("if"), expr)) >>
- punct!("=>") >>
- body: alt!(
- map!(block, |blk| {
- ExprKind::Block(ExprBlock {
- unsafety: Unsafety::Normal,
- block: blk,
- }).into()
- })
- |
- expr
- ) >>
- (Arm {
- rocket_token: tokens::Rocket::default(),
- if_token: guard.as_ref().map(|_| tokens::If::default()),
- attrs: attrs,
- pats: pats,
- guard: guard.map(Box::new),
- body: Box::new(body),
- comma: None,
- })
- ));
+ impl Synom for Arm {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ pats: call!(Delimited::parse_separated_nonempty) >>
+ guard: option!(tuple!(syn!(If), syn!(Expr))) >>
+ rocket: syn!(Rocket) >>
+ body: alt!(
+ map!(syn!(Block), |blk| {
+ ExprKind::Block(ExprBlock {
+ unsafety: Unsafety::Normal,
+ block: blk,
+ }).into()
+ })
+ |
+ syn!(Expr)
+ ) >>
+ (Arm {
+ rocket_token: rocket,
+ if_token: guard.as_ref().map(|p| If((p.0).0)),
+ attrs: attrs,
+ pats: pats,
+ guard: guard.map(|p| Box::new(p.1)),
+ body: Box::new(body),
+ comma: None,
+ })
+ }
+ }
+ }
named_ambiguous_expr!(expr_closure -> ExprKind, allow_struct, do_parse!(
- capture: capture_by >>
- punct!("|") >>
- inputs: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- closure_arg) >>
- punct!("|") >>
+ capture: syn!(CaptureBy) >>
+ or1: syn!(Or) >>
+ inputs: call!(Delimited::parse_terminated_with, fn_arg) >>
+ or2: syn!(Or) >>
ret_and_body: alt!(
do_parse!(
- punct!("->") >>
- ty: ty >>
- body: block >>
- (FunctionRetTy::Ty(ty, tokens::RArrow::default()),
+ arrow: syn!(RArrow) >>
+ ty: syn!(Ty) >>
+ body: syn!(Block) >>
+ (FunctionRetTy::Ty(ty, arrow),
ExprKind::Block(ExprBlock {
unsafety: Unsafety::Normal,
block: body,
@@ -1115,14 +1151,14 @@
) >>
(ExprClosure {
capture: capture,
- or1_token: tokens::Or::default(),
- or2_token: tokens::Or::default(),
+ or1_token: or1,
+ or2_token: or2,
decl: Box::new(FnDecl {
inputs: inputs,
output: ret_and_body.0,
variadic: false,
dot_tokens: None,
- fn_token: tokens::Fn::default(),
+ fn_token: tokens::Fn_::default(),
generics: Generics::default(),
paren_token: tokens::Paren::default(),
}),
@@ -1130,274 +1166,356 @@
}.into())
));
- named!(closure_arg -> FnArg, do_parse!(
- pat: pat >>
- ty: option!(preceded!(punct!(":"), ty)) >>
- (ArgCaptured {
- pat: pat,
- colon_token: tokens::Colon::default(),
- ty: ty.unwrap_or_else(|| TyInfer {
- underscore_token: tokens::Underscore::default(),
- }.into()),
- }.into())
- ));
-
- named!(expr_while -> ExprKind, do_parse!(
- lbl: option!(terminated!(label, punct!(":"))) >>
- keyword!("while") >>
- cond: cond >>
- while_block: block >>
- (match cond {
- Cond::Let(pat, expr, eq_token, let_token) => ExprWhileLet {
- eq_token: eq_token,
- let_token: let_token,
- while_token: tokens::While::default(),
- colon_token: lbl.as_ref().map(|_| tokens::Colon::default()),
- pat: Box::new(pat),
- expr: Box::new(expr),
- body: while_block,
- label: lbl,
- }.into(),
- Cond::Expr(cond) => ExprWhile {
- while_token: tokens::While::default(),
- colon_token: lbl.as_ref().map(|_| tokens::Colon::default()),
- cond: Box::new(cond),
- body: while_block,
- label: lbl,
- }.into(),
+ named!(fn_arg -> FnArg, do_parse!(
+ pat: syn!(Pat) >>
+ ty: option!(tuple!(syn!(Colon), syn!(Ty))) >>
+ ({
+ let (colon, ty) = ty.unwrap_or_else(|| {
+ (Colon::default(), TyInfer {
+ underscore_token: Underscore::default(),
+ }.into())
+ });
+ ArgCaptured {
+ pat: pat,
+ colon_token: colon,
+ ty: ty,
+ }.into()
})
));
- named!(expr_continue -> ExprKind, do_parse!(
- keyword!("continue") >>
- lbl: option!(label) >>
- (ExprContinue {
- continue_token: tokens::Continue::default(),
- label: lbl,
- }.into())
- ));
+ impl Synom for ExprWhile {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ lbl: option!(tuple!(label, syn!(Colon))) >>
+ while_: syn!(While) >>
+ cond: expr_no_struct >>
+ while_block: syn!(Block) >>
+ (ExprWhile {
+ while_token: while_,
+ colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
+ cond: Box::new(cond),
+ body: while_block,
+ label: lbl.map(|p| p.0),
+ })
+ }
+ }
+ }
+
+ impl Synom for ExprWhileLet {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ lbl: option!(tuple!(label, syn!(Colon))) >>
+ while_: syn!(While) >>
+ let_: syn!(Let) >>
+ pat: syn!(Pat) >>
+ eq: syn!(Eq) >>
+ value: expr_no_struct >>
+ while_block: syn!(Block) >>
+ (ExprWhileLet {
+ eq_token: eq,
+ let_token: let_,
+ while_token: while_,
+ colon_token: lbl.as_ref().map(|p| Colon((p.1).0)),
+ pat: Box::new(pat),
+ expr: Box::new(value),
+ body: while_block,
+ label: lbl.map(|p| p.0),
+ })
+ }
+ }
+ }
+
+ impl Synom for ExprContinue {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ cont: syn!(Continue) >>
+ lbl: option!(label) >>
+ (ExprContinue {
+ continue_token: cont,
+ label: lbl,
+ })
+ }
+ }
+ }
named_ambiguous_expr!(expr_break -> ExprKind, allow_struct, do_parse!(
- keyword!("break") >>
+ break_: syn!(Break) >>
lbl: option!(label) >>
val: option!(call!(ambiguous_expr, allow_struct, false)) >>
(ExprBreak {
label: lbl,
expr: val.map(Box::new),
- break_token: tokens::Break::default(),
+ break_token: break_,
}.into())
));
named_ambiguous_expr!(expr_ret -> ExprKind, allow_struct, do_parse!(
- keyword!("return") >>
+ return_: syn!(Return) >>
ret_value: option!(ambiguous_expr!(allow_struct)) >>
(ExprRet {
expr: ret_value.map(Box::new),
- return_token: tokens::Return::default(),
+ return_token: return_,
}.into())
));
- named!(expr_struct -> ExprKind, do_parse!(
- path: path >>
- punct!("{") >>
- fields: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- field_value) >>
- base: option!(
- cond!(fields.is_empty() || fields.trailing_delim(),
+ impl Synom for ExprStruct {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ path: syn!(Path) >>
+ data: braces!(do_parse!(
+ fields: call!(Delimited::parse_terminated) >>
+ base: option!(
+ cond!(fields.is_empty() || fields.trailing_delim(),
+ do_parse!(
+ dots: syn!(Dot2) >>
+ base: syn!(Expr) >>
+ (dots, base)
+ )
+ )
+ ) >>
+ (fields, base)
+ )) >>
+ ({
+ let ((fields, base), brace) = data;
+ let (dots, rest) = match base.and_then(|b| b) {
+ Some((dots, base)) => (Some(dots), Some(base)),
+ None => (None, None),
+ };
+ ExprStruct {
+ brace_token: brace,
+ path: path,
+ fields: fields,
+ dot2_token: dots,
+ rest: rest.map(Box::new),
+ }
+ })
+ }
+ }
+ }
+
+ impl Synom for FieldValue {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
do_parse!(
- punct!("..") >>
- base: expr >>
- (base)
+ name: wordlike >>
+ colon: syn!(Colon) >>
+ value: syn!(Expr) >>
+ (FieldValue {
+ ident: name,
+ expr: value,
+ is_shorthand: false,
+ attrs: Vec::new(),
+ colon_token: Some(colon),
+ })
)
- )
- ) >>
- punct!("}") >>
- (ExprStruct {
- brace_token: tokens::Brace::default(),
- path: path,
- fields: fields,
- dot2_token: base.as_ref().and_then(|b| b.as_ref())
- .map(|_| tokens::Dot2::default()),
- rest: base.and_then(|b| b.map(Box::new)),
- }.into())
- ));
+ |
+ map!(syn!(Ident), |name: Ident| FieldValue {
+ ident: name.clone(),
+ expr: ExprKind::Path(ExprPath { qself: None, path: name.into() }).into(),
+ is_shorthand: true,
+ attrs: Vec::new(),
+ colon_token: None,
+ })
+ }
+ }
+ }
- named!(field_value -> FieldValue, alt!(
- do_parse!(
- name: wordlike >>
- punct!(":") >>
- value: expr >>
- (FieldValue {
- ident: name,
- expr: value,
- is_shorthand: false,
- attrs: Vec::new(),
- colon_token: Some(tokens::Colon::default()),
- })
- )
- |
- map!(ident, |name: Ident| FieldValue {
- ident: name.clone(),
- expr: ExprKind::Path(ExprPath { qself: None, path: name.into() }).into(),
- is_shorthand: true,
- attrs: Vec::new(),
- colon_token: None,
- })
- ));
+ impl Synom for ExprRepeat {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ data: brackets!(do_parse!(
+ value: syn!(Expr) >>
+ semi: syn!(Semi) >>
+ times: syn!(Expr) >>
+ (value, semi, times)
+ )) >>
+ (ExprRepeat {
+ expr: Box::new((data.0).0),
+ amt: Box::new((data.0).2),
+ bracket_token: data.1,
+ semi_token: (data.0).1,
+ })
+ }
+ }
+ }
- named!(expr_repeat -> ExprKind, delim!(Bracket, do_parse!(
- value: expr >>
- punct!(";") >>
- times: expr >>
- punct!("]") >>
- (ExprRepeat {
- expr: Box::new(value),
- amt: Box::new(times),
- bracket_token: tokens::Bracket::default(),
- semi_token: tokens::Semi::default(),
- }.into())
- ));
-
- named!(expr_block -> ExprKind, do_parse!(
- rules: unsafety >>
- b: block >>
- (ExprBlock {
- unsafety: rules,
- block: b,
- }.into())
- ));
+ impl Synom for ExprBlock {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ rules: syn!(Unsafety) >>
+ b: syn!(Block) >>
+ (ExprBlock {
+ unsafety: rules,
+ block: b,
+ })
+ }
+ }
+ }
named_ambiguous_expr!(expr_range -> ExprKind, allow_struct, do_parse!(
- limits: range_limits >>
+ limits: syn!(RangeLimits) >>
hi: option!(ambiguous_expr!(allow_struct)) >>
(ExprRange { from: None, to: hi.map(Box::new), limits: limits }.into())
));
- named!(range_limits -> RangeLimits, alt!(
- punct!("...") => { |_| RangeLimits::Closed(tokens::Dot3::default()) }
- |
- punct!("..") => { |_| RangeLimits::HalfOpen(tokens::Dot2::default()) }
- ));
+ impl Synom for RangeLimits {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(Dot3) => { RangeLimits::Closed }
+ |
+ syn!(Dot2) => { RangeLimits::HalfOpen }
+ }
+ }
+ }
- named!(expr_path -> ExprKind, map!(qpath, |(qself, path)| {
- ExprPath { qself: qself, path: path }.into()
- }));
+ impl Synom for ExprPath {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ pair: qpath >>
+ (ExprPath {
+ qself: pair.0,
+ path: pair.1,
+ })
+ }
+ }
+ }
named_ambiguous_expr!(expr_addr_of -> ExprKind, allow_struct, do_parse!(
- punct!("&") >>
- mutability: mutability >>
+ and: syn!(And) >>
+ mutability: syn!(Mutability) >>
expr: ambiguous_expr!(allow_struct) >>
(ExprAddrOf {
mutbl: mutability,
expr: Box::new(expr),
- and_token: tokens::And::default(),
+ and_token: and,
}.into())
));
- named_ambiguous_expr!(and_assign -> (Expr, tokens::Eq), allow_struct, preceded!(
- punct!("="),
- map!(ambiguous_expr!(allow_struct), |t| (t, tokens::Eq::default()))
- ));
+ named_ambiguous_expr!(and_assign -> (Expr, Eq), allow_struct,
+ map!(
+ tuple!(syn!(Eq), ambiguous_expr!(allow_struct)),
+ |(a, b)| (b, a)
+ )
+ );
named_ambiguous_expr!(and_assign_op -> (BinOp, Expr), allow_struct, tuple!(
- assign_op,
+ call!(BinOp::parse_assign_op),
ambiguous_expr!(allow_struct)
));
- named!(and_field -> (Ident, tokens::Dot),
- preceded!(punct!("."), map!(ident, |t| (t, tokens::Dot::default()))));
+ named!(and_field -> (Ident, Dot),
+ map!(tuple!(syn!(Dot), syn!(Ident)), |(a, b)| (b, a)));
- named!(and_tup_field -> (Lit, tokens::Dot),
- preceded!(punct!("."), map!(lit, |l| (l, tokens::Dot::default()))));
+ named!(and_tup_field -> (Lit, Dot),
+ map!(tuple!(syn!(Dot), syn!(Lit)), |(a, b)| (b, a)));
- named!(and_index -> (Expr, tokens::Bracket),
- map!(delimited!(punct!("["), expr, punct!("]")),
- |t| (t, tokens::Bracket::default())));
+ named!(and_index -> (Expr, tokens::Bracket), brackets!(syn!(Expr)));
named_ambiguous_expr!(and_range -> (RangeLimits, Option<Expr>), allow_struct, tuple!(
- range_limits,
+ syn!(RangeLimits),
option!(call!(ambiguous_expr, allow_struct, false))
));
- named!(pub block -> Block, do_parse!(
- stmts: delim!(Brace, within_block) >>
- (Block {
- stmts: stmts,
- brace_token: tokens::Brace::default(),
- })
- ));
-
- named!(pub within_block -> Vec<Stmt>, do_parse!(
- many0!(punct!(";")) >>
- mut standalone: many0!(terminated!(stmt, many0!(punct!(";")))) >>
- last: option!(expr) >>
- (match last {
- None => standalone,
- Some(last) => {
- standalone.push(Stmt::Expr(Box::new(last)));
- standalone
+ impl Synom for Block {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ stmts: braces!(call!(Block::parse_within)) >>
+ (Block {
+ stmts: stmts.0,
+ brace_token: stmts.1,
+ })
}
- })
- ));
+ }
+ }
- named!(pub stmt -> Stmt, alt!(
- stmt_mac
- |
- stmt_local
- |
- stmt_item
- |
- stmt_expr
- ));
+ impl Block {
+ pub fn parse_within(input: &[TokenTree]) -> IResult<&[TokenTree], Vec<Stmt>> {
+ do_parse! {
+ input,
+ many0!(syn!(Semi)) >>
+ mut standalone: many0!(terminated!(syn!(Stmt), many0!(syn!(Semi)))) >>
+ last: option!(syn!(Expr)) >>
+ (match last {
+ None => standalone,
+ Some(last) => {
+ standalone.push(Stmt::Expr(Box::new(last)));
+ standalone
+ }
+ })
+ }
+ }
+ }
+
+ impl Synom for Stmt {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ stmt_mac
+ |
+ stmt_local
+ |
+ stmt_item
+ |
+ stmt_expr
+ }
+ }
+ }
named!(stmt_mac -> Stmt, do_parse!(
- attrs: many0!(outer_attr) >>
- what: path >>
- punct!("!") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ what: syn!(Path) >>
+ bang: syn!(Bang) >>
// Only parse braces here; paren and bracket will get parsed as
// expression statements
- punct!("{") >>
- ts: token_stream >>
- punct!("}") >>
- semi: option!(punct!(";")) >>
+ data: braces!(syn!(TokenStream)) >>
+ semi: option!(syn!(Semi)) >>
(Stmt::Mac(Box::new((
Mac {
path: what,
- bang_token: tokens::Bang::default(),
+ bang_token: bang,
tokens: vec![TokenTree(proc_macro2::TokenTree {
- span: Default::default(),
- kind: TokenKind::Sequence(Delimiter::Brace, ts),
+ span: ((data.1).0).0,
+ kind: TokenKind::Sequence(Delimiter::Brace, data.0),
})],
},
- if semi.is_some() {
- MacStmtStyle::Semicolon(tokens::Semi::default())
- } else {
- MacStmtStyle::Braces
+ match semi {
+ Some(semi) => MacStmtStyle::Semicolon(semi),
+ None => MacStmtStyle::Braces,
},
attrs,
))))
));
named!(stmt_local -> Stmt, do_parse!(
- attrs: many0!(outer_attr) >>
- keyword!("let") >>
- pat: pat >>
- ty: option!(preceded!(punct!(":"), ty)) >>
- init: option!(preceded!(punct!("="), expr)) >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ let_: syn!(Let) >>
+ pat: syn!(Pat) >>
+ ty: option!(tuple!(syn!(Colon), syn!(Ty))) >>
+ init: option!(tuple!(syn!(Eq), syn!(Expr))) >>
+ semi: syn!(Semi) >>
(Stmt::Local(Box::new(Local {
- let_token: tokens::Let::default(),
- semi_token: tokens::Semi::default(),
- colon_token: ty.as_ref().map(|_| tokens::Colon::default()),
- eq_token: init.as_ref().map(|_| tokens::Eq::default()),
+ let_token: let_,
+ semi_token: semi,
+ colon_token: ty.as_ref().map(|p| Colon((p.0).0)),
+ eq_token: init.as_ref().map(|p| Eq((p.0).0)),
pat: Box::new(pat),
- ty: ty.map(Box::new),
- init: init.map(Box::new),
+ ty: ty.map(|p| Box::new(p.1)),
+ init: init.map(|p| Box::new(p.1)),
attrs: attrs,
})))
));
- named!(stmt_item -> Stmt, map!(item, |i| Stmt::Item(Box::new(i))));
+ named!(stmt_item -> Stmt, map!(syn!(Item), |i| Stmt::Item(Box::new(i))));
fn requires_semi(e: &Expr) -> bool {
match e.node {
@@ -1415,13 +1533,13 @@
}
named!(stmt_expr -> Stmt, do_parse!(
- attrs: many0!(outer_attr) >>
- mut e: expr >>
- semi: option!(punct!(";")) >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ mut e: syn!(Expr) >>
+ semi: option!(syn!(Semi)) >>
({
e.attrs = attrs;
- if semi.is_some() {
- Stmt::Semi(Box::new(e), tokens::Semi::default())
+ if let Some(s) = semi {
+ Stmt::Semi(Box::new(e), s)
} else if requires_semi(&e) {
return IResult::Error;
} else {
@@ -1430,225 +1548,303 @@
})
));
- named!(pub pat -> Pat, alt!(
- pat_wild // must be before pat_ident
- |
- pat_box // must be before pat_ident
- |
- pat_range // must be before pat_lit
- |
- pat_tuple_struct // must be before pat_ident
- |
- pat_struct // must be before pat_ident
- |
- pat_mac // must be before pat_ident
- |
- pat_lit // must be before pat_ident
- |
- pat_ident // must be before pat_path
- |
- pat_path
- |
- map!(pat_tuple, |t: PatTuple| t.into())
- |
- pat_ref
- |
- pat_slice
- ));
+ impl Synom for Pat {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(PatWild) => { Pat::Wild } // must be before pat_ident
+ |
+ syn!(PatBox) => { Pat::Box } // must be before pat_ident
+ |
+ syn!(PatRange) => { Pat::Range } // must be before pat_lit
+ |
+ syn!(PatTupleStruct) => { Pat::TupleStruct } // must be before pat_ident
+ |
+ syn!(PatStruct) => { Pat::Struct } // must be before pat_ident
+ |
+ syn!(Mac) => { Pat::Mac } // must be before pat_ident
+ |
+ syn!(PatLit) => { Pat::Lit } // must be before pat_ident
+ |
+ syn!(PatIdent) => { Pat::Ident } // must be before pat_path
+ |
+ syn!(PatPath) => { Pat::Path }
+ |
+ syn!(PatTuple) => { Pat::Tuple }
+ |
+ syn!(PatRef) => { Pat::Ref }
+ |
+ syn!(PatSlice) => { Pat::Slice }
+ }
+ }
+ }
- named!(pat_mac -> Pat, map!(mac, Pat::Mac));
+ impl Synom for PatWild {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ map! {
+ input,
+ syn!(Underscore),
+ |u| PatWild { underscore_token: u }
+ }
+ }
+ }
- named!(pat_wild -> Pat, map!(keyword!("_"), |_| {
- PatWild { underscore_token: tokens::Underscore::default() }.into()
- }));
-
- named!(pat_box -> Pat, do_parse!(
- keyword!("box") >>
- pat: pat >>
- (PatBox {
- pat: Box::new(pat),
- box_token: tokens::Box::default(),
- }.into())
- ));
-
- named!(pat_ident -> Pat, do_parse!(
- mode: option!(keyword!("ref")) >>
- mutability: mutability >>
- name: alt!(
- ident
- |
- keyword!("self") => { Into::into }
- ) >>
- not!(punct!("<")) >>
- not!(punct!("::")) >>
- subpat: option!(preceded!(punct!("@"), pat)) >>
- (PatIdent {
- mode: if mode.is_some() {
- BindingMode::ByRef(tokens::Ref::default(), mutability)
- } else {
- BindingMode::ByValue(mutability)
- },
- ident: name,
- at_token: subpat.as_ref().map(|_| tokens::At::default()),
- subpat: subpat.map(Box::new),
- }.into())
- ));
-
- named!(pat_tuple_struct -> Pat, do_parse!(
- path: path >>
- tuple: pat_tuple >>
- (PatTupleStruct {
- path: path,
- pat: tuple,
- }.into())
- ));
-
- named!(pat_struct -> Pat, do_parse!(
- path: path >>
- punct!("{") >>
- fields: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- field_pat) >>
- base: option!(
- cond!(fields.is_empty() || fields.trailing_delim(),
- punct!(".."))
- ) >>
- punct!("}") >>
- (PatStruct {
- path: path,
- fields: fields,
- brace_token: tokens::Brace::default(),
- dot2_token: base.and_then(|m| m).map(|_| tokens::Dot2::default()),
- }.into())
- ));
-
- named!(field_pat -> FieldPat, alt!(
- do_parse!(
- ident: wordlike >>
- punct!(":") >>
- pat: pat >>
- (FieldPat {
- ident: ident,
- pat: Box::new(pat),
- is_shorthand: false,
- attrs: Vec::new(),
- colon_token: Some(tokens::Colon::default()),
- })
- )
- |
- do_parse!(
- boxed: option!(keyword!("box")) >>
- mode: option!(keyword!("ref")) >>
- mutability: mutability >>
- ident: ident >>
- ({
- let mut pat: Pat = PatIdent {
- mode: if mode.is_some() {
- BindingMode::ByRef(tokens::Ref::default(), mutability)
- } else {
- BindingMode::ByValue(mutability)
- },
- ident: ident.clone(),
- subpat: None,
- at_token: None,
- }.into();
- if boxed.is_some() {
- pat = PatBox {
- pat: Box::new(pat),
- box_token: tokens::Box::default(),
- }.into();
- }
- FieldPat {
- ident: ident,
+ impl Synom for PatBox {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ boxed: syn!(Box_) >>
+ pat: syn!(Pat) >>
+ (PatBox {
pat: Box::new(pat),
- is_shorthand: true,
- attrs: Vec::new(),
- colon_token: None,
+ box_token: boxed,
+ })
+ }
+ }
+ }
+
+ impl Synom for PatIdent {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ mode: option!(syn!(Ref)) >>
+ mutability: syn!(Mutability) >>
+ name: alt!(
+ syn!(Ident)
+ |
+ syn!(Self_) => { Into::into }
+ ) >>
+ not!(syn!(Lt)) >>
+ not!(syn!(Colon2)) >>
+ subpat: option!(tuple!(syn!(At), syn!(Pat))) >>
+ (PatIdent {
+ mode: match mode {
+ Some(mode) => BindingMode::ByRef(mode, mutability),
+ None => BindingMode::ByValue(mutability),
+ },
+ ident: name,
+ at_token: subpat.as_ref().map(|p| At((p.0).0)),
+ subpat: subpat.map(|p| Box::new(p.1)),
+ })
+ }
+ }
+ }
+
+ impl Synom for PatTupleStruct {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ path: syn!(Path) >>
+ tuple: syn!(PatTuple) >>
+ (PatTupleStruct {
+ path: path,
+ pat: tuple,
+ })
+ }
+ }
+ }
+
+ impl Synom for PatStruct {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ path: syn!(Path) >>
+ data: braces!(do_parse!(
+ fields: call!(Delimited::parse_terminated) >>
+ base: option!(
+ cond!(fields.is_empty() || fields.trailing_delim(),
+ syn!(Dot2))
+ ) >>
+ (fields, base)
+ )) >>
+ (PatStruct {
+ path: path,
+ fields: (data.0).0,
+ brace_token: data.1,
+ dot2_token: (data.0).1.and_then(|m| m),
+ })
+ }
+ }
+ }
+
+ impl Synom for FieldPat {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ ident: wordlike >>
+ colon: syn!(Colon) >>
+ pat: syn!(Pat) >>
+ (FieldPat {
+ ident: ident,
+ pat: Box::new(pat),
+ is_shorthand: false,
+ attrs: Vec::new(),
+ colon_token: Some(colon),
+ })
+ )
+ |
+ do_parse!(
+ boxed: option!(syn!(Box_)) >>
+ mode: option!(syn!(Ref)) >>
+ mutability: syn!(Mutability) >>
+ ident: syn!(Ident) >>
+ ({
+ let mut pat: Pat = PatIdent {
+ mode: if let Some(mode) = mode {
+ BindingMode::ByRef(mode, mutability)
+ } else {
+ BindingMode::ByValue(mutability)
+ },
+ ident: ident.clone(),
+ subpat: None,
+ at_token: None,
+ }.into();
+ if let Some(boxed) = boxed {
+ pat = PatBox {
+ pat: Box::new(pat),
+ box_token: boxed,
+ }.into();
+ }
+ FieldPat {
+ ident: ident,
+ pat: Box::new(pat),
+ is_shorthand: true,
+ attrs: Vec::new(),
+ colon_token: None,
+ }
+ })
+ )
+ }
+ }
+ }
+
+ named!(wordlike -> Ident, alt!(
+ syn!(Ident)
+ |
+ do_parse!(
+ lit: syn!(Lit) >>
+ ({
+ let s = lit.value.to_string();
+ if s.parse::<u32>().is_ok() {
+ Ident::new(s.into(), lit.span)
+ } else {
+ return IResult::Error
}
})
)
));
- named!(pat_path -> Pat, map!(qpath, |(qself, path)| {
- PatPath { qself: qself, path: path }.into()
- }));
+ impl Synom for PatPath {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ map! {
+ input,
+ syn!(ExprPath),
+ |p: ExprPath| PatPath { qself: p.qself, path: p.path }
+ }
+ }
+ }
- named!(pat_tuple -> PatTuple, do_parse!(
- punct!("(") >>
- mut elems: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- pat) >>
- dotdot: map!(cond!(
- elems.is_empty() || elems.trailing_delim(),
- option!(do_parse!(
- punct!("..") >>
- trailing: option!(punct!(",")) >>
- (trailing.is_some())
- ))
- ), |x: Option<_>| x.and_then(|x| x)) >>
- rest: cond!(dotdot == Some(true),
- terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- pat)) >>
- punct!(")") >>
- (PatTuple {
- paren_token: tokens::Paren::default(),
- dots_pos: dotdot.map(|_| elems.len()),
- dot2_token: dotdot.map(|_| tokens::Dot2::default()),
- comma_token: dotdot.and_then(|b| {
- if b {
- Some(tokens::Comma::default())
- } else {
- None
- }
- }),
- pats: {
- if let Some(rest) = rest {
- for elem in rest.into_iter() {
- elems.push(elem);
+ impl Synom for PatTuple {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ data: parens!(do_parse!(
+ elems: call!(Delimited::parse_terminated) >>
+ dotdot: map!(cond!(
+ elems.is_empty() || elems.trailing_delim(),
+ option!(do_parse!(
+ dots: syn!(Dot2) >>
+ trailing: option!(syn!(Comma)) >>
+ (dots, trailing)
+ ))
+ ), |x: Option<_>| x.and_then(|x| x)) >>
+ rest: cond!(match dotdot {
+ Some((_, Some(_))) => true,
+ _ => false,
+ },
+ call!(Delimited::parse_terminated)) >>
+ (elems, dotdot, rest)
+ )) >>
+ ({
+ let ((mut elems, dotdot, rest), parens) = data;
+ let (dotdot, trailing) = match dotdot {
+ Some((a, b)) => (Some(a), Some(b)),
+ None => (None, None),
+ };
+ PatTuple {
+ paren_token: parens,
+ dots_pos: dotdot.as_ref().map(|_| elems.len()),
+ dot2_token: dotdot,
+ comma_token: trailing.and_then(|b| b),
+ pats: {
+ if let Some(rest) = rest {
+ for elem in rest {
+ elems.push(elem);
+ }
+ }
+ elems
+ },
}
- }
- elems
- },
- })
- )));
+ })
+ }
+ }
+ }
- named!(pat_ref -> Pat, do_parse!(
- punct!("&") >>
- mutability: mutability >>
- pat: pat >>
- (PatRef {
- pat: Box::new(pat),
- mutbl: mutability,
- and_token: tokens::And::default(),
- }.into())
- ));
+ impl Synom for PatRef {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ and: syn!(And) >>
+ mutability: syn!(Mutability) >>
+ pat: syn!(Pat) >>
+ (PatRef {
+ pat: Box::new(pat),
+ mutbl: mutability,
+ and_token: and,
+ })
+ }
+ }
+ }
- named!(pat_lit -> Pat, do_parse!(
- lit: pat_lit_expr >>
- (if let ExprKind::Path(_) = lit.node {
- return IResult::Error; // these need to be parsed by pat_path
- } else {
- PatLit {
- expr: Box::new(lit),
- }.into()
- })
- ));
+ impl Synom for PatLit {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ lit: pat_lit_expr >>
+ (if let ExprKind::Path(_) = lit.node {
+ return IResult::Error; // these need to be parsed by pat_path
+ } else {
+ PatLit {
+ expr: Box::new(lit),
+ }
+ })
+ }
+ }
+ }
- named!(pat_range -> Pat, do_parse!(
- lo: pat_lit_expr >>
- limits: range_limits >>
- hi: pat_lit_expr >>
- (PatRange {
- lo: Box::new(lo),
- hi: Box::new(hi),
- limits: limits,
- }.into())
- ));
+ impl Synom for PatRange {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ lo: pat_lit_expr >>
+ limits: syn!(RangeLimits) >>
+ hi: pat_lit_expr >>
+ (PatRange {
+ lo: Box::new(lo),
+ hi: Box::new(hi),
+ limits: limits,
+ })
+ }
+ }
+ }
named!(pat_lit_expr -> Expr, do_parse!(
- neg: option!(punct!("-")) >>
+ neg: option!(syn!(Sub)) >>
v: alt!(
- lit => { ExprKind::Lit }
+ syn!(Lit) => { ExprKind::Lit }
|
- path => { |p| ExprPath { qself: None, path: p }.into() }
+ syn!(ExprPath) => { ExprKind::Path }
) >>
(if neg.is_some() {
ExprKind::Unary(ExprUnary {
@@ -1660,50 +1856,63 @@
})
));
- named!(pat_slice -> Pat, do_parse!(
- punct!("[") >>
- mut before: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- pat) >>
- middle: option!(do_parse!(
- punct!("..") >>
- trailing: option!(punct!(",")) >>
- (trailing.is_some())
- )) >>
- after: cond!(
- match middle {
- Some(trailing) => trailing,
- _ => false,
- },
- terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- pat)
- ) >>
- punct!("]") >>
- (PatSlice {
- dot2_token: middle.as_ref().map(|_| tokens::Dot2::default()),
- comma_token: {
- let trailing = middle.unwrap_or(false);
- if trailing {Some(tokens::Comma::default())} else {None}
- },
- bracket_token: tokens::Bracket::default(),
- middle: middle.and_then(|_| {
- if !before.is_empty() && !before.trailing_delim() {
- Some(Box::new(before.pop().unwrap().into_item()))
- } else {
- None
+ impl Synom for PatSlice {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ map! {
+ input,
+ brackets!(do_parse!(
+ before: call!(Delimited::parse_terminated) >>
+ middle: option!(do_parse!(
+ dots: syn!(Dot2) >>
+ trailing: option!(syn!(Comma)) >>
+ (dots, trailing)
+ )) >>
+ after: cond!(
+ match middle {
+ Some((_, ref trailing)) => trailing.is_some(),
+ _ => false,
+ },
+ call!(Delimited::parse_terminated)
+ ) >>
+ (before, middle, after)
+ )),
+ |((before, middle, after), brackets)| {
+ let mut before: Delimited<Pat, tokens::Comma> = before;
+ let after: Option<Delimited<Pat, tokens::Comma>> = after;
+ let middle: Option<(Dot2, Option<Comma>)> = middle;
+ PatSlice {
+ dot2_token: middle.as_ref().map(|m| Dot2((m.0).0)),
+ comma_token: middle.as_ref().and_then(|m| {
+ m.1.as_ref().map(|m| Comma(m.0))
+ }),
+ bracket_token: brackets,
+ middle: middle.and_then(|_| {
+ if !before.is_empty() && !before.trailing_delim() {
+ Some(Box::new(before.pop().unwrap().into_item()))
+ } else {
+ None
+ }
+ }),
+ front: before,
+ back: after.unwrap_or_default(),
+ }
}
- }),
- front: before,
- back: after.unwrap_or_default(),
- }.into())
- ));
+ }
+ }
+ }
- named!(capture_by -> CaptureBy, alt!(
- keyword!("move") => { |_| CaptureBy::Value(tokens::Move::default()) }
- |
- epsilon!() => { |_| CaptureBy::Ref }
- ));
+ impl Synom for CaptureBy {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(Move) => { CaptureBy::Value }
+ |
+ epsilon!() => { |_| CaptureBy::Ref }
+ }
+ }
+ }
- named!(label -> Ident, map!(lifetime, |lt: Lifetime| lt.ident));
+ named!(label -> Ident, map!(syn!(Lifetime), |lt: Lifetime| lt.ident));
}
#[cfg(feature = "printing")]
diff --git a/src/generics.rs b/src/generics.rs
index fa29e6a..71cd8f6 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -210,169 +210,206 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use attr::parsing::outer_attr;
- use ident::parsing::ident;
- use ty::parsing::{ty, poly_trait_ref};
- use synom::{TokenTree, IResult};
- named!(pub generics -> Generics, map!(
- alt!(
- do_parse!(
- punct!("<") >>
- lifetimes: terminated_list!(
- map!(punct!(","), |_| tokens::Comma::default()),
- lifetime_def
- ) >>
- ty_params: cond!(
- lifetimes.is_empty() || lifetimes.trailing_delim(),
- terminated_list!(
- map!(punct!(","), |_| tokens::Comma::default()),
- ty_param
+ use synom::{IResult, Synom};
+ use synom::tokens::*;
+ use proc_macro2::{TokenTree, TokenKind};
+
+ impl Synom for Generics {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ map! {
+ input,
+ alt!(
+ do_parse!(
+ lt: syn!(Lt) >>
+ lifetimes: call!(Delimited::parse_terminated) >>
+ ty_params: cond!(
+ lifetimes.is_empty() || lifetimes.trailing_delim(),
+ call!(Delimited::parse_terminated)
+ ) >>
+ gt: syn!(Gt) >>
+ (lifetimes, ty_params, Some(lt), Some(gt))
)
- ) >>
- punct!(">") >>
- (lifetimes, ty_params, true)
- )
- |
- epsilon!() => { |_| (Delimited::new(), None, false) }
- ),
- |(lifetimes, ty_params, any): (_, Option<_>, _)| Generics {
- lifetimes: lifetimes,
- ty_params: ty_params.unwrap_or_default(),
- where_clause: WhereClause::default(),
- gt_token: if any {Some(tokens::Gt::default())} else {None},
- lt_token: if any {Some(tokens::Lt::default())} else {None},
- }
- ));
-
- pub fn lifetime(input: &[TokenTree]) -> IResult<&[TokenTree], Lifetime> {
- use synom::*;
- if let Some(&TokenTree { kind: TokenKind::Word(ref id), .. }) = input.first() {
- // Check if this word is _actually_ a lifetime, and treat that differently
- if id.chars().next().unwrap() == '\'' {
- IResult::Done(&input[1..], Lifetime {
- ident: id.to_string().into()
- })
- } else {
- IResult::Error
+ |
+ epsilon!() => { |_| (Delimited::new(), None, None, None) }
+ ),
+ |(lifetimes, ty_params, lt, gt): (_, Option<_>, _, _)| Generics {
+ lifetimes: lifetimes,
+ ty_params: ty_params.unwrap_or_default(),
+ where_clause: WhereClause::default(),
+ gt_token: gt,
+ lt_token: lt,
+ }
}
- } else {
+ }
+ }
+
+ impl Synom for Lifetime {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ let mut tokens = input.iter();
+ let token = match tokens.next() {
+ Some(token) => token,
+ None => return IResult::Error,
+ };
+ if let TokenKind::Word(s) = token.kind {
+ if s.as_str().starts_with('\'') {
+ return IResult::Done(tokens.as_slice(), Lifetime {
+ ident: Ident {
+ span: Span(token.span),
+ sym: s,
+ },
+ })
+ }
+ }
IResult::Error
}
}
- named!(pub lifetime_def -> LifetimeDef, do_parse!(
- attrs: many0!(outer_attr) >>
- life: lifetime >>
- colon: option!(punct!(":")) >>
- bounds: cond!(
- colon.is_some(),
- separated_nonempty_list!(map!(punct!("+"), |_| tokens::Add::default()),
- lifetime)
- ) >>
- (LifetimeDef {
- attrs: attrs,
- lifetime: life,
- bounds: bounds.unwrap_or_default(),
- colon_token: colon.map(|_| tokens::Colon::default()),
- })
- ));
-
- named!(pub bound_lifetimes -> Option<BoundLifetimes>, option!(do_parse!(
- keyword!("for") >>
- punct!("<") >>
- lifetimes: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- lifetime_def) >>
- punct!(">") >>
- (BoundLifetimes {
- for_token: tokens::For::default(),
- lt_token: tokens::Lt::default(),
- gt_token: tokens::Gt::default(),
- lifetimes: lifetimes,
- })
- )));
-
- named!(ty_param -> TyParam, do_parse!(
- attrs: many0!(outer_attr) >>
- id: ident >>
- colon: option!(punct!(":")) >>
- bounds: cond!(
- colon.is_some(),
- separated_nonempty_list!(map!(punct!("+"), |_| tokens::Add::default()),
- ty_param_bound)
- ) >>
- default: option!(preceded!(
- punct!("="),
- ty
- )) >>
- (TyParam {
- attrs: attrs,
- ident: id,
- bounds: bounds.unwrap_or_default(),
- colon_token: colon.map(|_| tokens::Colon::default()),
- eq_token: default.as_ref().map(|_| tokens::Eq::default()),
- default: default,
- })
- ));
-
- named!(pub ty_param_bound -> TyParamBound, alt!(
- preceded!(punct!("?"), poly_trait_ref) => {
- |poly| TyParamBound::Trait(poly, TraitBoundModifier::Maybe(tokens::Question::default()))
+ impl Synom for LifetimeDef {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ life: syn!(Lifetime) >>
+ colon: option!(syn!(Colon)) >>
+ bounds: cond!(
+ colon.is_some(),
+ call!(Delimited::parse_separated_nonempty)
+ ) >>
+ (LifetimeDef {
+ attrs: attrs,
+ lifetime: life,
+ bounds: bounds.unwrap_or_default(),
+ colon_token: colon.map(|_| tokens::Colon::default()),
+ })
+ }
}
- |
- lifetime => { TyParamBound::Region }
- |
- poly_trait_ref => {
- |poly| TyParamBound::Trait(poly, TraitBoundModifier::None)
+ }
+
+ impl Synom for BoundLifetimes {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ for_: syn!(For) >>
+ lt: syn!(Lt) >>
+ lifetimes: call!(Delimited::parse_terminated) >>
+ gt: syn!(Gt) >>
+ (BoundLifetimes {
+ for_token: for_,
+ lt_token: lt,
+ gt_token: gt,
+ lifetimes: lifetimes,
+ })
+ }
}
- ));
+ }
- named!(pub where_clause -> WhereClause, alt!(
- do_parse!(
- keyword!("where") >>
- predicates: terminated_list!(
- map!(punct!(","), |_| tokens::Comma::default()),
- where_predicate
- ) >>
- (WhereClause {
- predicates: predicates,
- where_token: Some(tokens::Where::default()),
- })
- )
- |
- epsilon!() => { |_| WhereClause::default() }
- ));
+ impl Synom for TyParam {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ id: syn!(Ident) >>
+ colon: option!(syn!(Colon)) >>
+ bounds: cond!(
+ colon.is_some(),
+ call!(Delimited::parse_separated_nonempty)
+ ) >>
+ default: option!(do_parse!(
+ eq: syn!(Eq) >>
+ ty: syn!(Ty) >>
+ (eq, ty)
+ )) >>
+ (TyParam {
+ attrs: attrs,
+ ident: id,
+ bounds: bounds.unwrap_or_default(),
+ colon_token: colon,
+ eq_token: default.as_ref().map(|d| tokens::Eq((d.0).0)),
+ default: default.map(|d| d.1),
+ })
+ }
+ }
+ }
- named!(where_predicate -> WherePredicate, alt!(
- do_parse!(
- ident: lifetime >>
- colon: option!(punct!(":")) >>
- bounds: cond!(
- colon.is_some(),
- separated_list!(map!(punct!("+"), |_| tokens::Add::default()),
- lifetime)
- ) >>
- (WherePredicate::RegionPredicate(WhereRegionPredicate {
- lifetime: ident,
- bounds: bounds.unwrap_or_default(),
- colon_token: colon.map(|_| tokens::Colon::default()),
- }))
- )
- |
- do_parse!(
- bound_lifetimes: bound_lifetimes >>
- bounded_ty: ty >>
- punct!(":") >>
- bounds: separated_nonempty_list!(map!(punct!("+"), |_| tokens::Add::default()),
- ty_param_bound) >>
- (WherePredicate::BoundPredicate(WhereBoundPredicate {
- bound_lifetimes: bound_lifetimes,
- bounded_ty: bounded_ty,
- bounds: bounds,
- colon_token: tokens::Colon::default(),
- }))
- )
- ));
+ impl Synom for TyParamBound {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ question: syn!(Question) >>
+ poly: syn!(PolyTraitRef) >>
+ (TyParamBound::Trait(poly, TraitBoundModifier::Maybe(question)))
+ )
+ |
+ syn!(Lifetime) => { TyParamBound::Region }
+ |
+ syn!(PolyTraitRef) => {
+ |poly| TyParamBound::Trait(poly, TraitBoundModifier::None)
+ }
+ }
+ }
+
+ fn description() -> Option<&'static str> {
+ Some("type parameter buond")
+ }
+ }
+
+ impl Synom for WhereClause {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ where_: syn!(Where) >>
+ predicates: call!(Delimited::parse_terminated) >>
+ (WhereClause {
+ predicates: predicates,
+ where_token: Some(where_),
+ })
+ )
+ |
+ epsilon!() => { |_| WhereClause::default() }
+ }
+ }
+
+ fn description() -> Option<&'static str> {
+ Some("where clause")
+ }
+ }
+
+ impl Synom for WherePredicate {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ ident: syn!(Lifetime) >>
+ colon: option!(syn!(Colon)) >>
+ bounds: cond!(
+ colon.is_some(),
+ call!(Delimited::parse_separated)
+ ) >>
+ (WherePredicate::RegionPredicate(WhereRegionPredicate {
+ lifetime: ident,
+ bounds: bounds.unwrap_or_default(),
+ colon_token: colon,
+ }))
+ )
+ |
+ do_parse!(
+ bound_lifetimes: option!(syn!(BoundLifetimes)) >>
+ bounded_ty: syn!(Ty) >>
+ colon: syn!(Colon) >>
+ bounds: call!(Delimited::parse_separated_nonempty) >>
+ (WherePredicate::BoundPredicate(WhereBoundPredicate {
+ bound_lifetimes: bound_lifetimes,
+ bounded_ty: bounded_ty,
+ bounds: bounds,
+ colon_token: colon,
+ }))
+ )
+ }
+ }
+ }
}
#[cfg(feature = "printing")]
diff --git a/src/ident.rs b/src/ident.rs
index 1ed2c3e..3ffacc7 100644
--- a/src/ident.rs
+++ b/src/ident.rs
@@ -6,6 +6,7 @@
use proc_macro2::Symbol;
use Span;
+use tokens;
#[derive(Clone)]
pub struct Ident {
@@ -28,6 +29,24 @@
}
}
+impl From<tokens::Self_> for Ident {
+ fn from(tok: tokens::Self_) -> Self {
+ Ident::new("self".into(), tok.0)
+ }
+}
+
+impl From<tokens::CapSelf> for Ident {
+ fn from(tok: tokens::CapSelf) -> Self {
+ Ident::new("Self".into(), tok.0)
+ }
+}
+
+impl From<tokens::Super> for Ident {
+ fn from(tok: tokens::Super) -> Self {
+ Ident::new("super".into(), tok.0)
+ }
+}
+
impl<'a> From<Cow<'a, str>> for Ident {
fn from(s: Cow<'a, str>) -> Self {
Ident::new(s[..].into(), Span::default())
@@ -95,13 +114,24 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use synom::{TokenTree, TokenKind, IResult};
- #[cfg(feature = "full")]
- use lit::parsing::int;
+ use proc_macro2::{TokenTree, TokenKind};
+ use synom::{Synom, IResult};
- pub fn ident(input: &[TokenTree]) -> IResult<&[TokenTree], Ident> {
- if let IResult::Done(rest, id) = word(input) {
- match id.as_ref() {
+ impl Synom for Ident {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ let mut tokens = input.iter();
+ let token = match tokens.next() {
+ Some(token) => token,
+ None => return IResult::Error,
+ };
+ let word = match token.kind {
+ TokenKind::Word(s) => s,
+ _ => return IResult::Error,
+ };
+ if word.as_str().starts_with('\'') {
+ return IResult::Error
+ }
+ match word.as_str() {
// From https://doc.rust-lang.org/grammar.html#keywords
"abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
"crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
@@ -109,33 +139,20 @@
"mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
"return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
"true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
- "while" | "yield" => IResult::Error,
- _ => IResult::Done(rest, id),
+ "while" | "yield" => return IResult::Error,
+ _ => {}
}
- } else {
- IResult::Error
+
+ IResult::Done(tokens.as_slice(), Ident {
+ span: Span(token.span),
+ sym: word,
+ })
+ }
+
+ fn description() -> Option<&'static str> {
+ Some("identifier")
}
}
-
- pub fn word(input: &[TokenTree]) -> IResult<&[TokenTree], Ident> {
- if let Some(&TokenTree { kind: TokenKind::Word(ref id), .. }) = input.first() {
- // Check if this word is _actually_ a lifetime, and treat that differently
- if id.chars().next().unwrap() == '\'' {
- IResult::Error
- } else {
- IResult::Done(&input[1..], Ident(id.to_string()))
- }
- } else {
- IResult::Error
- }
- }
-
- #[cfg(feature = "full")]
- named!(pub wordlike -> Ident, alt!(
- word
- |
- int => { |d| format!("{}", d).into() }
- ));
}
#[cfg(feature = "printing")]
diff --git a/src/item.rs b/src/item.rs
index 3f8446a..d6d1521 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -243,7 +243,7 @@
ast_enum! {
#[cfg_attr(feature = "clone-impls", derive(Copy))]
pub enum Defaultness {
- Default(tokens::Default),
+ Default(tokens::Default_),
Final,
}
}
@@ -380,7 +380,7 @@
///
/// E.g. `fn foo(bar: baz)`
pub struct FnDecl {
- pub fn_token: tokens::Fn,
+ pub fn_token: tokens::Fn_,
pub paren_token: tokens::Paren,
pub inputs: Delimited<FnArg, tokens::Comma>,
pub output: FunctionRetTy,
@@ -417,62 +417,64 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use {Block, Generics, Ident, Mac, Path, VariantData};
- use attr::parsing::{inner_attr, outer_attr};
- use data::parsing::{struct_like_body, visibility};
- use expr::parsing::{expr, pat, within_block};
- use generics::parsing::{generics, lifetime, ty_param_bound, where_clause};
- use ident::parsing::ident;
- use mac::parsing::delimited;
- use derive::{Body, DeriveInput};
- use derive::parsing::derive_input;
- use ty::parsing::{abi, mutability, path, ty, unsafety, fn_ret_ty};
- named!(pub item -> Item, alt!(
- item_extern_crate
- |
- item_use
- |
- item_static
- |
- item_const
- |
- item_fn
- |
- item_mod
- |
- item_foreign_mod
- |
- item_ty
- |
- item_struct_or_enum
- |
- item_union
- |
- item_trait
- |
- item_default_impl
- |
- item_impl
- |
- item_mac
- ));
+ use proc_macro2::TokenTree;
+ use synom::{IResult, Synom};
+ use synom::tokens::*;
+ use synom::tokens;
- named!(pub items -> Vec<Item>, many0!(item));
+ impl Synom for Item {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ item_extern_crate
+ |
+ item_use
+ |
+ item_static
+ |
+ item_const
+ |
+ item_fn
+ |
+ item_mod
+ |
+ item_foreign_mod
+ |
+ item_ty
+ |
+ item_struct_or_enum
+ |
+ item_union
+ |
+ item_trait
+ |
+ item_default_impl
+ |
+ item_impl
+ |
+ item_mac
+ }
+ }
+
+ fn description() -> Option<&'static str> {
+ Some("item")
+ }
+ }
named!(item_mac -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- what: path >>
- punct!("!") >>
- name: option!(ident) >>
- body: delimited >>
- cond!(!body.is_braced(), punct!(";")) >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ what: syn!(Path) >>
+ bang: syn!(Bang) >>
+ name: option!(syn!(Ident)) >>
+ body: call!(::TokenTree::parse_delimited) >>
+ cond!(!body.is_braced(), syn!(Semi)) >>
(Item {
ident: name.unwrap_or_else(|| Ident::from("")),
vis: VisInherited {}.into(),
attrs: attrs,
node: ItemKind::Mac(Mac {
- bang_token: tokens::Bang::default(),
+ bang_token: bang,
path: what,
tokens: vec![body],
}),
@@ -480,144 +482,159 @@
));
named!(item_extern_crate -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("extern") >>
- keyword!("crate") >>
- id: ident >>
- rename: option!(preceded!(
- keyword!("as"),
- ident
- )) >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ extern_: syn!(Extern) >>
+ crate_: syn!(tokens::Crate) >>
+ id: syn!(Ident) >>
+ rename: option!(tuple!(syn!(As), syn!(Ident))) >>
+ semi: syn!(Semi) >>
({
- let (name, original_name) = match rename {
- Some(rename) => (rename, Some(id)),
- None => (id, None),
+ let (name, original_name, as_) = match rename {
+ Some((as_, rename)) => (rename, Some(id), Some(as_)),
+ None => (id, None, None),
};
Item {
ident: name,
vis: vis,
attrs: attrs,
node: ItemExternCrate {
- as_token: original_name.as_ref().map(|_| tokens::As::default()),
+ as_token: as_,
original: original_name,
- extern_token: tokens::Extern::default(),
- crate_token: tokens::Crate::default(),
- semi_token: tokens::Semi::default(),
+ extern_token: extern_,
+ crate_token: crate_,
+ semi_token: semi,
}.into(),
}
})
));
named!(item_use -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("use") >>
- what: view_path >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ use_: syn!(Use) >>
+ what: syn!(ViewPath) >>
+ semi: syn!(Semi) >>
(Item {
ident: "".into(),
vis: vis,
attrs: attrs,
node: ItemUse {
path: Box::new(what),
- use_token: tokens::Use::default(),
- semi_token: tokens::Semi::default(),
+ use_token: use_,
+ semi_token: semi,
}.into(),
})
));
- named!(view_path -> ViewPath, alt!(
- view_path_glob
- |
- view_path_list
- |
- view_path_list_root
- |
- view_path_simple // must be last
- ));
+ impl Synom for ViewPath {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(PathGlob) => { ViewPath::Glob }
+ |
+ syn!(PathList) => { ViewPath::List }
+ |
+ syn!(PathSimple) => { ViewPath::Simple } // must be last
+ }
+ }
+ }
+ impl Synom for PathSimple {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ path: syn!(Path) >>
+ rename: option!(tuple!(syn!(As), syn!(Ident))) >>
+ (PathSimple {
+ path: path,
+ as_token: rename.as_ref().map(|p| As((p.0).0)),
+ rename: rename.map(|p| p.1),
+ })
+ }
+ }
+ }
- named!(view_path_simple -> ViewPath, do_parse!(
- path: path >>
- rename: option!(preceded!(keyword!("as"), ident)) >>
- (PathSimple {
- path: path,
- as_token: rename.as_ref().map(|_| tokens::As::default()),
- rename: rename,
- }.into())
- ));
+ impl Synom for PathGlob {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ path: syn!(Path) >>
+ colon2: syn!(Colon2) >>
+ star: syn!(Star) >>
+ (PathGlob {
+ path: path,
+ colon2_token: colon2,
+ star_token: star,
+ })
+ }
+ }
+ }
- named!(view_path_glob -> ViewPath, do_parse!(
- path: path >>
- punct!("::") >>
- punct!("*") >>
- (PathGlob {
- path: path,
- colon2_token: tokens::Colon2::default(),
- star_token: tokens::Star::default(),
- }.into())
- ));
+ impl Synom for PathList {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ path: syn!(Path) >>
+ colon2: syn!(Colon2) >>
+ items: braces!(call!(Delimited::parse_terminated)) >>
+ (PathList {
+ path: path,
+ items: items.0,
+ brace_token: items.1,
+ colon2_token: colon2,
+ })
+ )
+ |
+ do_parse!(
+ global: option!(syn!(Colon2)) >>
+ items: braces!(call!(Delimited::parse_terminated)) >>
+ (PathList {
+ path: Path {
+ global: global.is_some(),
+ segments: Delimited::new(),
+ leading_colon: None,
+ },
+ colon2_token: global.unwrap_or_default(),
+ brace_token: items.1,
+ items: items.0,
+ })
+ )
+ }
+ }
+ }
- named!(view_path_list -> ViewPath, do_parse!(
- path: path >>
- punct!("::") >>
- punct!("{") >>
- items: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- path_list_item) >>
- punct!("}") >>
- (PathList {
- path: path,
- items: items,
- brace_token: tokens::Brace::default(),
- colon2_token: tokens::Colon2::default(),
- }.into())
- ));
-
- named!(view_path_list_root -> ViewPath, do_parse!(
- global: option!(punct!("::")) >>
- punct!("{") >>
- items: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- path_list_item) >>
- punct!("}") >>
- (PathList {
- path: Path {
- global: global.is_some(),
- segments: Delimited::new(),
- leading_colon: None,
- },
- colon2_token: tokens::Colon2::default(),
- brace_token: tokens::Brace::default(),
- items: items,
- }.into())
- ));
-
- named!(path_list_item -> PathListItem, do_parse!(
- name: alt!(
- ident
- |
- map!(keyword!("self"), Into::into)
- ) >>
- rename: option!(preceded!(keyword!("as"), ident)) >>
- (PathListItem {
- name: name,
- as_token: rename.as_ref().map(|_| tokens::As::default()),
- rename: rename,
- })
- ));
+ impl Synom for PathListItem {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ name: alt!(
+ syn!(Ident)
+ |
+ map!(syn!(Self_), Into::into)
+ ) >>
+ rename: option!(tuple!(syn!(As), syn!(Ident))) >>
+ (PathListItem {
+ name: name,
+ as_token: rename.as_ref().map(|p| As((p.0).0)),
+ rename: rename.map(|p| p.1),
+ })
+ }
+ }
+ }
named!(item_static -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("static") >>
- mutability: mutability >>
- id: ident >>
- punct!(":") >>
- ty: ty >>
- punct!("=") >>
- value: expr >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ static_: syn!(Static) >>
+ mutability: syn!(Mutability) >>
+ id: syn!(Ident) >>
+ colon: syn!(Colon) >>
+ ty: syn!(Ty) >>
+ eq: syn!(Eq) >>
+ value: syn!(Expr) >>
+ semi: syn!(Semi) >>
(Item {
ident: id,
vis: vis,
@@ -626,24 +643,24 @@
ty: Box::new(ty),
mutbl: mutability,
expr: Box::new(value),
- static_token: tokens::Static::default(),
- colon_token: tokens::Colon::default(),
- eq_token: tokens::Eq::default(),
- semi_token: tokens::Semi::default(),
+ static_token: static_,
+ colon_token: colon,
+ eq_token: eq,
+ semi_token: semi,
}.into(),
})
));
named!(item_const -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("const") >>
- id: ident >>
- punct!(":") >>
- ty: ty >>
- punct!("=") >>
- value: expr >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ const_: syn!(Const) >>
+ id: syn!(Ident) >>
+ colon: syn!(Colon) >>
+ ty: syn!(Ty) >>
+ eq: syn!(Eq) >>
+ value: syn!(Expr) >>
+ semi: syn!(Semi) >>
(Item {
ident: id,
vis: vis,
@@ -651,46 +668,44 @@
node: ItemConst {
ty: Box::new(ty),
expr: Box::new(value),
- const_token: tokens::Const::default(),
- colon_token: tokens::Colon::default(),
- eq_token: tokens::Eq::default(),
- semi_token: tokens::Semi::default(),
+ const_token: const_,
+ colon_token: colon,
+ eq_token: eq,
+ semi_token: semi,
}.into(),
})
));
named!(item_fn -> Item, do_parse!(
- outer_attrs: many0!(outer_attr) >>
- vis: visibility >>
- constness: constness >>
- unsafety: unsafety >>
- abi: option!(abi) >>
- keyword!("fn") >>
- name: ident >>
- generics: generics >>
- punct!("(") >>
- inputs: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- fn_arg) >>
- punct!(")") >>
- ret: fn_ret_ty >>
- where_clause: where_clause >>
- inner_attrs_stmts: delim!(Brace, tuple!(
- many0!(inner_attr), within_block
+ outer_attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ constness: syn!(Constness) >>
+ unsafety: syn!(Unsafety) >>
+ abi: option!(syn!(Abi)) >>
+ fn_: syn!(Fn_) >>
+ name: syn!(Ident) >>
+ generics: syn!(Generics) >>
+ inputs: parens!(Delimited::parse_terminated) >>
+ ret: syn!(FunctionRetTy) >>
+ where_clause: syn!(WhereClause) >>
+ inner_attrs_stmts: braces!(tuple!(
+ many0!(call!(Attribute::parse_inner)),
+ call!(Block::parse_within)
)) >>
(Item {
ident: name,
vis: vis,
attrs: {
let mut attrs = outer_attrs;
- attrs.extend(inner_attrs_stmts.0);
+ attrs.extend((inner_attrs_stmts.0).0);
attrs
},
node: ItemFn {
decl: Box::new(FnDecl {
dot_tokens: None,
- fn_token: tokens::Fn::default(),
- paren_token: tokens::Paren::default(),
- inputs: inputs,
+ fn_token: fn_,
+ paren_token: inputs.1,
+ inputs: inputs.0,
output: ret,
variadic: false,
generics: Generics {
@@ -702,70 +717,74 @@
constness: constness,
abi: abi,
block: Box::new(Block {
- stmts: stmts,
- brace_token: tokens::Brace::default(),
+ brace_token: inner_attrs_stmts.1,
+ stmts: (inner_attrs_stmts.0).1,
}),
}.into(),
})
));
- named!(fn_arg -> FnArg, alt!(
- do_parse!(
- punct!("&") >>
- lt: option!(lifetime) >>
- mutability: mutability >>
- keyword!("self") >>
- not!(punct!(":")) >>
- (ArgSelfRef {
- lifetime: lt,
- mutbl: mutability,
- and_token: tokens::And::default(),
- self_token: tokens::Self_::default(),
- }.into())
- )
- |
- do_parse!(
- mutability: mutability >>
- keyword!("self") >>
- not!(punct!(":")) >>
- (ArgSelf {
- mutbl: mutability,
- self_token: tokens::Self_::default(),
- }.into())
- )
- |
- do_parse!(
- pat: pat >>
- punct!(":") >>
- ty: ty >>
- (ArgCaptured {
- pat: pat,
- ty: ty,
- colon_token: tokens::Colon::default(),
- }.into())
- )
- |
- ty => { FnArg::Ignored }
- ));
+ impl Synom for FnArg {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ and: syn!(And) >>
+ lt: option!(syn!(Lifetime)) >>
+ mutability: syn!(Mutability) >>
+ self_: syn!(Self_) >>
+ not!(syn!(Colon)) >>
+ (ArgSelfRef {
+ lifetime: lt,
+ mutbl: mutability,
+ and_token: and,
+ self_token: self_,
+ }.into())
+ )
+ |
+ do_parse!(
+ mutability: syn!(Mutability) >>
+ self_: syn!(Self_) >>
+ not!(syn!(Colon)) >>
+ (ArgSelf {
+ mutbl: mutability,
+ self_token: self_,
+ }.into())
+ )
+ |
+ do_parse!(
+ pat: syn!(Pat) >>
+ colon: syn!(Colon) >>
+ ty: syn!(Ty) >>
+ (ArgCaptured {
+ pat: pat,
+ ty: ty,
+ colon_token: colon,
+ }.into())
+ )
+ |
+ syn!(Ty) => { FnArg::Ignored }
+ }
+ }
+ }
named!(item_mod -> Item, do_parse!(
- outer_attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("mod") >>
- id: ident >>
+ outer_attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ mod_: syn!(Mod) >>
+ id: syn!(Ident) >>
content: alt!(
- punct!(";") => { |_| None }
+ syn!(Semi) => { Ok }
|
- delim!(
- Brace,
+ braces!(
tuple!(
- many0!(inner_attr),
- items
+ many0!(call!(Attribute::parse_inner)),
+ many0!(syn!(Item))
)
- ) => { Some }
+ ) => { Err }
) >>
(match content {
- Some((inner_attrs, items)) => Item {
+ Err(((inner_attrs, items), braces)) => Item {
ident: id,
vis: vis,
attrs: {
@@ -774,128 +793,133 @@
attrs
},
node: ItemMod {
- mod_token: tokens::Mod::default(),
+ mod_token: mod_,
semi_token: None,
- items: Some((items, tokens::Brace::default())),
+ items: Some((items, braces)),
}.into(),
},
- None => Item {
+ Ok(semi) => Item {
ident: id,
vis: vis,
attrs: outer_attrs,
node: ItemMod {
items: None,
- mod_token: tokens::Mod::default(),
- semi_token: Some(tokens::Semi::default()),
+ mod_token: mod_,
+ semi_token: Some(semi),
}.into(),
},
})
));
named!(item_foreign_mod -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- abi: abi >>
- items: delim!(Brace, many0!(foreign_item)) >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ abi: syn!(Abi) >>
+ items: braces!(many0!(syn!(ForeignItem))) >>
(Item {
ident: "".into(),
vis: VisInherited {}.into(),
attrs: attrs,
node: ItemForeignMod {
- brace_token: tokens::Brace::default(),
+ brace_token: items.1,
abi: abi,
- items: items,
+ items: items.0,
}.into(),
})
));
- named!(foreign_item -> ForeignItem, alt!(
- foreign_fn
- |
- foreign_static
- ));
+ impl Synom for ForeignItem {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ foreign_fn
+ |
+ foreign_static
+ }
+ }
+ }
named!(foreign_fn -> ForeignItem, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("fn") >>
- name: ident >>
- generics: generics >>
- punct!("(") >>
- inputs: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- fn_arg) >>
- variadic: cond!(inputs.is_empty() || inputs.trailing_delim(),
- option!(punct!("..."))) >>
- punct!(")") >>
- ret: fn_ret_ty >>
- where_clause: where_clause >>
- punct!(";") >>
- (ForeignItem {
- ident: name,
- attrs: attrs,
- semi_token: tokens::Semi::default(),
- node: ForeignItemFn {
- decl: Box::new(FnDecl {
- fn_token: tokens::Fn::default(),
- paren_token: tokens::Paren::default(),
- inputs: inputs,
- variadic: variadic.map(|m| m.is_some()).unwrap_or(false),
- dot_tokens: if variadic.map(|m| m.is_some()).unwrap_or(false) {
- Some(tokens::Dot3::default())
- } else {
- None
- },
- output: ret,
- generics: Generics {
- where_clause: where_clause,
- .. generics
- },
- }),
- }.into(),
- vis: vis,
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ fn_: syn!(Fn_) >>
+ name: syn!(Ident) >>
+ generics: syn!(Generics) >>
+ inputs: parens!(do_parse!(
+ args: call!(Delimited::parse_terminated) >>
+ variadic: cond!(args.is_empty() || args.trailing_delim(),
+ option!(syn!(Dot3))) >>
+ (args, variadic)
+ )) >>
+ ret: syn!(FunctionRetTy) >>
+ where_clause: syn!(WhereClause) >>
+ semi: syn!(Semi) >>
+ ({
+ let ((inputs, variadic), parens) = inputs;
+ let variadic = variadic.and_then(|v| v);
+ ForeignItem {
+ ident: name,
+ attrs: attrs,
+ semi_token: semi,
+ node: ForeignItemFn {
+ decl: Box::new(FnDecl {
+ fn_token: fn_,
+ paren_token: parens,
+ inputs: inputs,
+ variadic: variadic.is_some(),
+ dot_tokens: variadic,
+ output: ret,
+ generics: Generics {
+ where_clause: where_clause,
+ .. generics
+ },
+ }),
+ }.into(),
+ vis: vis,
+ }
})
));
named!(foreign_static -> ForeignItem, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("static") >>
- mutability: mutability >>
- id: ident >>
- punct!(":") >>
- ty: ty >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ static_: syn!(Static) >>
+ mutability: syn!(Mutability) >>
+ id: syn!(Ident) >>
+ colon: syn!(Colon) >>
+ ty: syn!(Ty) >>
+ semi: syn!(Semi) >>
(ForeignItem {
ident: id,
attrs: attrs,
- semi_token: tokens::Semi::default(),
+ semi_token: semi,
node: ForeignItemStatic {
ty: Box::new(ty),
mutbl: mutability,
- static_token: tokens::Static::default(),
- colon_token: tokens::Colon::default(),
+ static_token: static_,
+ colon_token: colon,
}.into(),
vis: vis,
})
));
named!(item_ty -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("type") >>
- id: ident >>
- generics: generics >>
- where_clause: where_clause >>
- punct!("=") >>
- ty: ty >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ type_: syn!(Type) >>
+ id: syn!(Ident) >>
+ generics: syn!(Generics) >>
+ where_clause: syn!(WhereClause) >>
+ eq: syn!(Eq) >>
+ ty: syn!(Ty) >>
+ semi: syn!(Semi) >>
(Item {
ident: id,
vis: vis,
attrs: attrs,
node: ItemTy {
- type_token: tokens::Type::default(),
- eq_token: tokens::Eq::default(),
- semi_token: tokens::Semi::default(),
+ type_token: type_,
+ eq_token: eq,
+ semi_token: semi,
ty: Box::new(ty),
generics: Generics {
where_clause: where_clause,
@@ -906,7 +930,7 @@
));
named!(item_struct_or_enum -> Item, map!(
- derive_input,
+ syn!(DeriveInput),
|def: DeriveInput| Item {
ident: def.ident,
vis: def.vis,
@@ -933,19 +957,20 @@
));
named!(item_union -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- keyword!("union") >>
- id: ident >>
- generics: generics >>
- where_clause: where_clause >>
- fields: struct_like_body >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ union_: syn!(Union) >>
+ id: syn!(Ident) >>
+ generics: syn!(Generics) >>
+ where_clause: syn!(WhereClause) >>
+ fields: braces!(call!(Delimited::parse_terminated_with,
+ Field::parse_struct)) >>
(Item {
ident: id,
vis: vis,
attrs: attrs,
node: ItemUnion {
- union_token: tokens::Union::default(),
+ union_token: union_,
data: VariantData::Struct(fields.0, fields.1),
generics: Generics {
where_clause: where_clause,
@@ -956,46 +981,45 @@
));
named!(item_trait -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- unsafety: unsafety >>
- keyword!("trait") >>
- id: ident >>
- generics: generics >>
- colon: option!(punct!(":")) >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ unsafety: syn!(Unsafety) >>
+ trait_: syn!(Trait) >>
+ id: syn!(Ident) >>
+ generics: syn!(Generics) >>
+ colon: option!(syn!(Colon)) >>
bounds: cond!(colon.is_some(),
- separated_nonempty_list!(map!(punct!("+"), |_| tokens::Add::default()),
- ty_param_bound)
+ call!(Delimited::parse_separated_nonempty)
) >>
- where_clause: where_clause >>
- body: delim!(Brace, many0!(trait_item)) >>
+ where_clause: syn!(WhereClause) >>
+ body: braces!(many0!(syn!(TraitItem))) >>
(Item {
ident: id,
vis: vis,
attrs: attrs,
node: ItemTrait {
- trait_token: tokens::Trait::default(),
- brace_token: tokens::Brace::default(),
- colon_token: colon.map(|_| tokens::Colon::default()),
+ trait_token: trait_,
+ brace_token: body.1,
+ colon_token: colon,
unsafety: unsafety,
generics: Generics {
where_clause: where_clause,
.. generics
},
supertraits: bounds.unwrap_or_default(),
- items: body,
+ items: body.0,
}.into(),
})
));
named!(item_default_impl -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- unsafety: unsafety >>
- keyword!("impl") >>
- path: path >>
- keyword!("for") >>
- punct!("..") >>
- delim!(Brace, epsilon!()) >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ unsafety: syn!(Unsafety) >>
+ impl_: syn!(Impl) >>
+ path: syn!(Path) >>
+ for_: syn!(For) >>
+ dot2: syn!(Dot2) >>
+ braces: braces!(epsilon!()) >>
(Item {
ident: "".into(),
vis: VisInherited {}.into(),
@@ -1003,67 +1027,70 @@
node: ItemDefaultImpl {
unsafety: unsafety,
path: path,
- impl_token: tokens::Impl::default(),
- for_token: tokens::For::default(),
- dot2_token: tokens::Dot2::default(),
- brace_token: tokens::Brace::default(),
+ impl_token: impl_,
+ for_token: for_,
+ dot2_token: dot2,
+ brace_token: braces.1,
}.into(),
})
));
- named!(trait_item -> TraitItem, alt!(
- trait_item_const
- |
- trait_item_method
- |
- trait_item_type
- |
- trait_item_mac
- ));
+ impl Synom for TraitItem {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ trait_item_const
+ |
+ trait_item_method
+ |
+ trait_item_type
+ |
+ trait_item_mac
+ }
+ }
+ }
named!(trait_item_const -> TraitItem, do_parse!(
- attrs: many0!(outer_attr) >>
- keyword!("const") >>
- id: ident >>
- punct!(":") >>
- ty: ty >>
- value: option!(preceded!(punct!("="), expr)) >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ const_: syn!(Const) >>
+ id: syn!(Ident) >>
+ colon: syn!(Colon) >>
+ ty: syn!(Ty) >>
+ value: option!(tuple!(syn!(Eq), syn!(Expr))) >>
+ semi: syn!(Semi) >>
(TraitItem {
ident: id,
attrs: attrs,
node: TraitItemConst {
ty: ty,
- const_token: tokens::Const::default(),
- colon_token: tokens::Colon::default(),
- eq_token: value.as_ref().map(|_| tokens::Eq::default()),
- default: value,
- semi_token: tokens::Semi::default(),
+ const_token: const_,
+ colon_token: colon,
+ eq_token: value.as_ref().map(|p| Eq((p.0).0)),
+ default: value.map(|p| p.1),
+ semi_token: semi,
}.into(),
})
));
named!(trait_item_method -> TraitItem, do_parse!(
- outer_attrs: many0!(outer_attr) >>
- constness: constness >>
- unsafety: unsafety >>
- abi: option!(abi) >>
- keyword!("fn") >>
- name: ident >>
- generics: generics >>
- punct!("(") >>
- inputs: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()), fn_arg) >>
- punct!(")") >>
- ret: fn_ret_ty >>
- where_clause: where_clause >>
- body: option!(delim!(
- Brace,
- tuple!(many0!(inner_attr), within_block)
+ outer_attrs: many0!(call!(Attribute::parse_outer)) >>
+ constness: syn!(Constness) >>
+ unsafety: syn!(Unsafety) >>
+ abi: option!(syn!(Abi)) >>
+ fn_: syn!(Fn_) >>
+ name: syn!(Ident) >>
+ generics: syn!(Generics) >>
+ inputs: parens!(call!(Delimited::parse_terminated)) >>
+ ret: syn!(FunctionRetTy) >>
+ where_clause: syn!(WhereClause) >>
+ body: option!(braces!(
+ tuple!(many0!(call!(Attribute::parse_inner)),
+ call!(Block::parse_within))
)) >>
- semi: cond!(body.is_none(), punct!(";")) >>
+ semi: cond!(body.is_none(), syn!(Semi)) >>
({
let (inner_attrs, stmts) = match body {
- Some((inner_attrs, stmts)) => (inner_attrs, Some(stmts)),
+ Some(((inner_attrs, stmts), b)) => (inner_attrs, Some((stmts, b))),
None => (Vec::new(), None),
};
TraitItem {
@@ -1074,17 +1101,17 @@
attrs
},
node: TraitItemMethod {
- semi_token: semi.map(|_| tokens::Semi::default()),
+ semi_token: semi,
sig: MethodSig {
unsafety: unsafety,
constness: constness,
abi: abi,
decl: FnDecl {
- inputs: inputs,
+ inputs: inputs.0,
output: ret,
variadic: false,
- fn_token: tokens::Fn::default(),
- paren_token: tokens::Paren::default(),
+ fn_token: fn_,
+ paren_token: inputs.1,
dot_tokens: None,
generics: Generics {
where_clause: where_clause,
@@ -1094,8 +1121,8 @@
},
default: stmts.map(|stmts| {
Block {
- stmts: stmts,
- brace_token: tokens::Brace::default(),
+ stmts: stmts.0,
+ brace_token: stmts.1,
}
}),
}.into(),
@@ -1104,73 +1131,66 @@
));
named!(trait_item_type -> TraitItem, do_parse!(
- attrs: many0!(outer_attr) >>
- keyword!("type") >>
- id: ident >>
- colon: option!(punct!(":")) >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ type_: syn!(Type) >>
+ id: syn!(Ident) >>
+ colon: option!(syn!(Colon)) >>
bounds: cond!(colon.is_some(),
- separated_nonempty_list!(map!(punct!("+"), |_| tokens::Add::default()),
- ty_param_bound)
+ call!(Delimited::parse_separated_nonempty)
) >>
- default: option!(preceded!(punct!("="), ty)) >>
- punct!(";") >>
+ default: option!(tuple!(syn!(Eq), syn!(Ty))) >>
+ semi: syn!(Semi) >>
(TraitItem {
ident: id,
attrs: attrs,
node: TraitItemType {
- type_token: tokens::Type::default(),
- colon_token: colon.map(|_| tokens::Colon::default()),
+ type_token: type_,
+ colon_token: colon,
+ eq_token: default.as_ref().map(|p| Eq((p.0).0)),
bounds: bounds.unwrap_or_default(),
- eq_token: default.as_ref().map(|_| tokens::Eq::default()),
- semi_token: tokens::Semi::default(),
- default: default,
+ semi_token: semi,
+ default: default.map(|p| p.1),
}.into(),
})
));
named!(trait_item_mac -> TraitItem, do_parse!(
- attrs: many0!(outer_attr) >>
- what: path >>
- punct!("!") >>
- body: delimited >>
- cond!(!body.is_braced(), punct!(";")) >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ mac: syn!(Mac) >>
+ cond!(!mac.is_braced(), syn!(Semi)) >>
(TraitItem {
ident: "".into(),
attrs: attrs,
- node: TraitItemKind::Macro(Mac {
- path: what,
- bang_token: tokens::Bang::default(),
- tokens: vec![body],
- }),
+ node: TraitItemKind::Macro(mac),
})
));
named!(item_impl -> Item, do_parse!(
- attrs: many0!(outer_attr) >>
- unsafety: unsafety >>
- keyword!("impl") >>
- generics: generics >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ unsafety: syn!(Unsafety) >>
+ impl_: syn!(Impl) >>
+ generics: syn!(Generics) >>
polarity_path: alt!(
do_parse!(
- polarity: impl_polarity >>
- path: path >>
- keyword!("for") >>
- (polarity, Some(path))
+ polarity: syn!(ImplPolarity) >>
+ path: syn!(Path) >>
+ for_: syn!(For) >>
+ (polarity, Some(path), Some(for_))
)
|
- epsilon!() => { |_| (ImplPolarity::Positive, None) }
+ epsilon!() => { |_| (ImplPolarity::Positive, None, None) }
) >>
- self_ty: ty >>
- where_clause: where_clause >>
- body: delim!(Brace, many0!(impl_item)) >>
+ self_ty: syn!(Ty) >>
+ where_clause: syn!(WhereClause) >>
+ body: braces!(many0!(syn!(ImplItem))) >>
(Item {
ident: "".into(),
vis: VisInherited {}.into(),
attrs: attrs,
node: ItemImpl {
- impl_token: tokens::Impl::default(),
- brace_token: tokens::Brace::default(),
- for_token: polarity_path.1.as_ref().map(|_| tokens::For::default()),
+ impl_token: impl_,
+ brace_token: body.1,
+ for_token: polarity_path.2,
unsafety: unsafety,
polarity: polarity_path.0,
generics: Generics {
@@ -1179,32 +1199,37 @@
},
trait_: polarity_path.1,
self_ty: Box::new(self_ty),
- items: body,
+ items: body.0,
}.into(),
})
));
- named!(impl_item -> ImplItem, alt!(
- impl_item_const
- |
- impl_item_method
- |
- impl_item_type
- |
- impl_item_macro
- ));
+ impl Synom for ImplItem {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ impl_item_const
+ |
+ impl_item_method
+ |
+ impl_item_type
+ |
+ impl_item_macro
+ }
+ }
+ }
named!(impl_item_const -> ImplItem, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- defaultness: defaultness >>
- keyword!("const") >>
- id: ident >>
- punct!(":") >>
- ty: ty >>
- punct!("=") >>
- value: expr >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ defaultness: syn!(Defaultness) >>
+ const_: syn!(Const) >>
+ id: syn!(Ident) >>
+ colon: syn!(Colon) >>
+ ty: syn!(Ty) >>
+ eq: syn!(Eq) >>
+ value: syn!(Expr) >>
+ semi: syn!(Semi) >>
(ImplItem {
ident: id,
vis: vis,
@@ -1213,32 +1238,30 @@
node: ImplItemConst {
ty: ty,
expr: value,
- const_token: tokens::Const::default(),
- colon_token: tokens::Colon::default(),
- eq_token: tokens::Eq::default(),
- semi_token: tokens::Semi::default(),
+ const_token: const_,
+ colon_token: colon,
+ eq_token: eq,
+ semi_token: semi,
}.into(),
})
));
named!(impl_item_method -> ImplItem, do_parse!(
- outer_attrs: many0!(outer_attr) >>
- vis: visibility >>
- defaultness: defaultness >>
- constness: constness >>
- unsafety: unsafety >>
- abi: option!(abi) >>
- keyword!("fn") >>
- name: ident >>
- generics: generics >>
- punct!("(") >>
- inputs: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- fn_arg) >>
- punct!(")") >>
- ret: fn_ret_ty >>
- where_clause: where_clause >>
- inner_attrs_stmts: delim!(Brace, tuple!(
- many0!(inner_attr), within_block
+ outer_attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ defaultness: syn!(Defaultness) >>
+ constness: syn!(Constness) >>
+ unsafety: syn!(Unsafety) >>
+ abi: option!(syn!(Abi)) >>
+ fn_: syn!(Fn_) >>
+ name: syn!(Ident) >>
+ generics: syn!(Generics) >>
+ inputs: parens!(call!(Delimited::parse_terminated)) >>
+ ret: syn!(FunctionRetTy) >>
+ where_clause: syn!(WhereClause) >>
+ inner_attrs_stmts: braces!(tuple!(
+ many0!(call!(Attribute::parse_inner)),
+ call!(Block::parse_within)
)) >>
(ImplItem {
ident: name,
@@ -1246,7 +1269,7 @@
defaultness: defaultness,
attrs: {
let mut attrs = outer_attrs;
- attrs.extend(inner_attrs_stmts.0);
+ attrs.extend((inner_attrs_stmts.0).0);
attrs
},
node: ImplItemMethod {
@@ -1255,9 +1278,9 @@
constness: constness,
abi: abi,
decl: FnDecl {
- fn_token: tokens::Fn::default(),
- paren_token: tokens::Paren::default(),
- inputs: inputs,
+ fn_token: fn_,
+ paren_token: inputs.1,
+ inputs: inputs.0,
output: ret,
variadic: false,
generics: Generics {
@@ -1268,72 +1291,81 @@
},
},
block: Block {
- brace_token: tokens::Brace::default(),
- stmts: stmts,
+ brace_token: inner_attrs_stmts.1,
+ stmts: (inner_attrs_stmts.0).1,
},
}.into(),
})
));
named!(impl_item_type -> ImplItem, do_parse!(
- attrs: many0!(outer_attr) >>
- vis: visibility >>
- defaultness: defaultness >>
- keyword!("type") >>
- id: ident >>
- punct!("=") >>
- ty: ty >>
- punct!(";") >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ vis: syn!(Visibility) >>
+ defaultness: syn!(Defaultness) >>
+ type_: syn!(Type) >>
+ id: syn!(Ident) >>
+ eq: syn!(Eq) >>
+ ty: syn!(Ty) >>
+ semi: syn!(Semi) >>
(ImplItem {
ident: id,
vis: vis,
defaultness: defaultness,
attrs: attrs,
node: ImplItemType {
- type_token: tokens::Type::default(),
- eq_token: tokens::Eq::default(),
- semi_token: tokens::Semi::default(),
+ type_token: type_,
+ eq_token: eq,
+ semi_token: semi,
ty: ty,
}.into(),
})
));
named!(impl_item_macro -> ImplItem, do_parse!(
- attrs: many0!(outer_attr) >>
- what: path >>
- punct!("!") >>
- body: delimited >>
- cond!(!body.is_braced(), punct!(";")) >>
+ attrs: many0!(call!(Attribute::parse_outer)) >>
+ mac: syn!(Mac) >>
+ cond!(!mac.is_braced(), syn!(Semi)) >>
(ImplItem {
ident: "".into(),
vis: VisInherited {}.into(),
defaultness: Defaultness::Final,
attrs: attrs,
- node: ImplItemKind::Macro(Mac {
- path: what,
- bang_token: tokens::Bang::default(),
- tokens: vec![body],
- }),
+ node: ImplItemKind::Macro(mac),
})
));
- named!(impl_polarity -> ImplPolarity, alt!(
- punct!("!") => { |_| ImplPolarity::Negative(tokens::Bang::default()) }
- |
- epsilon!() => { |_| ImplPolarity::Positive }
- ));
+ impl Synom for ImplPolarity {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(Bang) => { ImplPolarity::Negative }
+ |
+ epsilon!() => { |_| ImplPolarity::Positive }
+ }
+ }
+ }
- named!(constness -> Constness, alt!(
- keyword!("const") => { |_| Constness::Const(tokens::Const::default()) }
- |
- epsilon!() => { |_| Constness::NotConst }
- ));
+ impl Synom for Constness {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(Const) => { Constness::Const }
+ |
+ epsilon!() => { |_| Constness::NotConst }
+ }
+ }
+ }
- named!(defaultness -> Defaultness, alt!(
- keyword!("default") => { |_| Defaultness::Default(tokens::Default::default()) }
- |
- epsilon!() => { |_| Defaultness::Final }
- ));
+ impl Synom for Defaultness {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(Default_) => { Defaultness::Default }
+ |
+ epsilon!() => { |_| Defaultness::Final }
+ }
+ }
+ }
}
#[cfg(feature = "printing")]
diff --git a/src/krate.rs b/src/krate.rs
index 7978a73..8e86430 100644
--- a/src/krate.rs
+++ b/src/krate.rs
@@ -11,32 +11,51 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use attr::parsing::inner_attr;
- use item::parsing::items;
- named!(pub krate -> Crate, do_parse!(
- // NOTE: The byte order mark and shebang are not tokens which can appear
- // in a TokenStream, so we can't parse them anymore.
+ use synom::{IResult, Synom, ParseError};
+ use proc_macro2::TokenTree;
- //option!(byte_order_mark) >>
- //shebang: option!(shebang) >>
- attrs: many0!(inner_attr) >>
- items: items >>
- (Crate {
- shebang: None,
- attrs: attrs,
- items: items,
- })
- ));
+ impl Synom for Crate {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ attrs: many0!(call!(Attribute::parse_inner)) >>
+ items: many0!(syn!(Item)) >>
+ (Crate {
+ shebang: None,
+ attrs: attrs,
+ items: items,
+ })
+ }
+ }
- // named!(byte_order_mark -> &str, tag!("\u{feff}"));
+ fn description() -> Option<&'static str> {
+ Some("crate")
+ }
- // named!(shebang -> String, do_parse!(
- // tag!("#!") >>
- // not!(tag!("[")) >>
- // content: take_until!("\n") >>
- // (format!("#!{}", content))
- // ));
+ fn parse_str_all(mut input: &str) -> Result<Self, ParseError> {
+ // Strip the BOM if it is present
+ const BOM: &'static str = "\u{feff}";
+ if input.starts_with(BOM) {
+ input = &input[BOM.len()..];
+ }
+
+ let mut shebang = None;
+ if input.starts_with("#!") && !input.starts_with("#![") {
+ if let Some(idx) = input.find('\n') {
+ shebang = Some(input[..idx].to_string());
+ input = &input[idx..];
+ } else {
+ shebang = Some(input.to_string());
+ input = "";
+ }
+ }
+
+ let mut krate: Crate = Self::parse_all(input.parse()?)?;
+ krate.shebang = shebang;
+ Ok(krate)
+ }
+ }
}
#[cfg(feature = "printing")]
@@ -47,10 +66,6 @@
impl ToTokens for Crate {
fn to_tokens(&self, tokens: &mut Tokens) {
- // TODO: how to handle shebang?
- // if let Some(ref shebang) = self.shebang {
- // tokens.append(&format!("{}\n", shebang));
- // }
tokens.append_all(self.attrs.inner());
tokens.append_all(&self.items);
}
diff --git a/src/lib.rs b/src/lib.rs
index e66a7e0..55f93ef 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -7,9 +7,6 @@
#[cfg(feature = "printing")]
extern crate quote;
-#[cfg(feature = "parsing")]
-extern crate relex;
-
#[cfg_attr(feature = "parsing", macro_use)]
extern crate synom;
@@ -97,10 +94,8 @@
#[cfg(feature = "printing")]
pub use ty::PathTokens;
-mod span;
-pub use span::Span;
-
-pub mod tokens;
+pub use synom::span::Span;
+pub use synom::tokens;
pub use synom::delimited;
#[cfg(feature = "visit")]
@@ -110,272 +105,43 @@
pub mod fold;
#[cfg(feature = "parsing")]
-pub use parsing::*;
-
-#[cfg(feature = "parsing")]
mod parsing {
use std::str::FromStr;
use super::*;
- use {derive, generics, ident, mac, ty, attr};
- use synom::{IResult, TokenStream};
+ use synom::{Synom, ParseError};
+ use proc_macro2::TokenStream;
- use std::convert::From;
- use std::error::Error;
- use std::fmt;
-
- #[cfg(feature = "full")]
- use {expr, item, krate};
-
- #[derive(Debug)]
- pub struct ParseError(String);
-
- impl Error for ParseError {
- fn description(&self) -> &str {
- &self.0
- }
- }
-
- impl fmt::Display for ParseError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- <String as fmt::Display>::fmt(&self.0, f)
- }
- }
-
- impl From<synom::LexError> for ParseError {
- fn from(_: synom::LexError) -> ParseError {
- ParseError("error while lexing input string".to_owned())
- }
- }
-
- /// Parse the stringified representation of a struct or enum passed
- /// to a `proc_macro_derive` function.
- pub fn parse_derive_input(input: TokenStream) -> Result<DeriveInput, ParseError> {
- unwrap("derive input", derive::parsing::derive_input, input)
- }
-
- /// Parse an entire crate into an AST. This function takes a string as input
- /// instead of a TokenStream, as we need to handle parsing the BOM and
- /// shebang from the string.
- #[cfg(feature = "full")]
- pub fn parse_crate(mut input: &str) -> Result<Crate, ParseError> {
- // Strip the BOM if it is present
- const BOM: &str = "\u{feff}";
- if input.starts_with(BOM) {
- input = &input[BOM.len()..];
- }
-
- let mut shebang = None;
- if input.starts_with("#!") && !input.starts_with("#![") {
- if let Some(idx) = input.find('\n') {
- shebang = Some(input[..idx].to_string());
- input = &input[idx..];
- } else {
- shebang = Some(input.to_string());
- input = "";
- }
- }
-
- let mut krate = unwrap("crate", krate::parsing::krate,
- input.parse()?)?;
- krate.shebang = shebang;
- Ok(krate)
-
- }
-
- #[cfg(feature = "full")]
- pub fn parse_item(input: TokenStream) -> Result<Item, ParseError> {
- unwrap("item", item::parsing::item, input)
- }
-
- #[cfg(feature = "full")]
- pub fn parse_items(input: TokenStream) -> Result<Vec<Item>, ParseError> {
- unwrap("items", item::parsing::items, input)
- }
-
- #[cfg(feature = "full")]
- pub fn parse_expr(input: TokenStream) -> Result<Expr, ParseError> {
- unwrap("expression", expr::parsing::expr, input)
- }
-
- pub fn parse_type(input: TokenStream) -> Result<Ty, ParseError> {
- unwrap("type", ty::parsing::ty, input)
- }
-
- /// Parse a path, such as `std::str::FromStr` or `::syn::parse_path`.
- pub fn parse_path(input: TokenStream) -> Result<Path, ParseError> {
- unwrap("path", ty::parsing::path, input)
- }
-
- pub fn parse_where_clause(input: TokenStream) -> Result<WhereClause, ParseError> {
- unwrap("where clause", generics::parsing::where_clause, input)
- }
-
- pub fn parse_token_trees(input: TokenStream) -> Result<Vec<TokenTree>, ParseError> {
- unwrap("token trees", mac::parsing::token_trees, input)
- }
-
- pub fn parse_ident(input: TokenStream) -> Result<Ident, ParseError> {
- unwrap("identifier", ident::parsing::ident, input)
- }
-
- pub fn parse_ty_param_bound(input: TokenStream) -> Result<TyParamBound, ParseError> {
- unwrap("type parameter bound",
- generics::parsing::ty_param_bound,
- input)
- }
-
- /// Parse an attribute declared outside the item it annotates, such as
- /// a struct annotation. They are written as `#[...]`.
- pub fn parse_outer_attr(input: TokenStream) -> Result<Attribute, ParseError> {
- unwrap("outer attribute", attr::parsing::outer_attr, input)
- }
-
- /// Parse an attribute declared inside the item it annotates. These are used
- /// for crate annotations or for mod-level declarations when modules are in
- /// their own files. They are written as `#![...]`.
- #[cfg(feature = "full")]
- pub fn parse_inner_attr(input: TokenStream) -> Result<Attribute, ParseError> {
- unwrap("inner attribute", attr::parsing::inner_attr, input)
- }
-
- /// Deprecated: Use `parse_derive_input` instead.
- #[doc(hidden)]
- #[deprecated(since="0.11.0", note = "Use `parse_derive_input` instead")]
- pub fn parse_macro_input(input: TokenStream) -> Result<MacroInput, ParseError> {
- parse_derive_input(input)
- }
-
- /// Alias for `syn::parse_derive_input`.
- impl FromStr for DeriveInput {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_derive_input(s.parse()?)
- }
- }
-
- /// Alias for `syn::parse_crate`.
- #[cfg(feature = "full")]
- impl FromStr for Crate {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_crate(s)
- }
- }
-
- /// Alias for `syn::parse_item`.
- #[cfg(feature = "full")]
- impl FromStr for Item {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_item(s.parse()?)
- }
- }
-
- /// Alias for `syn::parse_expr`.
- #[cfg(feature = "full")]
- impl FromStr for Expr {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_expr(s.parse()?)
- }
- }
-
- /// Alias for `syn::parse_type`.
- impl FromStr for Ty {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_type(s.parse()?)
- }
- }
-
- /// Alias for `syn::parse_path`.
- impl FromStr for Path {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_path(s.parse()?)
- }
- }
-
- /// Alias for `syn::parse_where_clause`.
- impl FromStr for WhereClause {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_where_clause(s.parse()?)
- }
- }
-
- /// Alias for `syn::parse_ident`.
- impl FromStr for Ident {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_ident(s.parse()?)
- }
- }
-
- /// Alias for `syn::parse_ty_param_bound`.
- impl FromStr for TyParamBound {
- type Err = ParseError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- parse_ty_param_bound(s.parse()?)
- }
- }
-
- fn unwrap<T>(name: &'static str,
- f: fn(&[synom::TokenTree]) -> IResult<&[synom::TokenTree], T>,
- input: TokenStream)
- -> Result<T, ParseError> {
- let input = synom::InputBuf::new(input);
- match f(&input) {
- IResult::Done(rest, t) => {
- if rest.is_empty() {
- Ok(t)
- } else if rest.len() == input.len() {
- // parsed nothing
- Err(ParseError(format!("failed to parse {}", name)))
- } else {
- Err(ParseError(format!("unparsed tokens after {}", name)))
+ macro_rules! traits {
+ ($($ty:ident,)*) => ($(
+ impl From<TokenStream> for $ty {
+ fn from(stream: TokenStream) -> $ty {
+ $ty::parse_all_unwrap(stream)
}
}
- IResult::Error => Err(ParseError(format!("failed to parse {}", name))),
- }
+
+ impl FromStr for $ty {
+ type Err = ParseError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ $ty::parse_str_all(s)
+ }
+ }
+ )*)
}
-}
-#[cfg(feature = "parsing")]
-pub mod parse {
- //! This module contains a set of exported nom parsers which can be used to
- //! parse custom grammars when used alongside the `synom` crate.
- //!
- //! Internally, `syn` uses a fork of `nom` called `synom` which resolves a
- //! persistent pitfall of using `nom` to parse Rust by eliminating the
- //! `IResult::Incomplete` variant. The `synom` crate should be used instead
- //! of `nom` when working with the parsers in this module.
-
- pub use synom::IResult;
+ traits! {
+ DeriveInput,
+ TyParamBound,
+ Ident,
+ WhereClause,
+ Ty,
+ }
#[cfg(feature = "full")]
- pub use item::parsing::item;
-
- #[cfg(feature = "full")]
- pub use expr::parsing::{expr, pat, block, stmt};
-
- pub use lit::parsing::{lit, string, byte_string, byte, character, float, int, boolean};
-
- pub use ty::parsing::{ty, path};
-
- pub use mac::parsing::token_tree as tt;
-
- pub use ident::parsing::ident;
-
- pub use generics::parsing::lifetime;
+ traits! {
+ Expr,
+ Item,
+ Crate,
+ }
}
diff --git a/src/lit.rs b/src/lit.rs
index fbec4a2..0be32d5 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -101,308 +101,26 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use escape::{cooked_byte, cooked_byte_string, cooked_char, cooked_string, raw_string};
- use proc_macro2::Literal;
- use synom::IResult;
- use synom::space::skip_whitespace;
- use unicode_xid::UnicodeXID;
+ use proc_macro2::TokenTree;
+ use synom::{Synom, IResult};
- fn l<T: Into<Literal>>(t: T) -> Lit {
- Lit {
- value: LitKind::Other(t.into()),
- span: Default::default(),
- }
- }
-
- named!(pub lit -> Lit, alt!(
- string
- |
- byte_string
- |
- byte
- |
- character
- |
- float
- |
- int
- |
- boolean
- ));
-
- named!(pub string -> Lit, alt!(
- quoted_string => { |s: String| l(&s[..]) }
- |
- preceded!(
- punct!("r"),
- raw_string
- ) => { |(s, n): (String, _)| l(Literal::raw_string(&s[..], n)) }
- ));
-
- named!(pub quoted_string -> String, delimited!(
- punct!("\""),
- cooked_string,
- tag!("\"")
- ));
-
- named!(pub byte_string -> Lit, alt!(
- delimited!(
- punct!("b\""),
- cooked_byte_string,
- tag!("\"")
- ) => { |vec: Vec<u8>| l(Literal::byte_string(&vec)) }
- |
- preceded!(
- punct!("br"),
- raw_string
- ) => { |(s, n): (String, _)| l(Literal::raw_byte_string(&s, n)) }
- ));
-
- named!(pub byte -> Lit, do_parse!(
- punct!("b") >>
- tag!("'") >>
- b: cooked_byte >>
- tag!("'") >>
- (l(Literal::byte_char(b)))
- ));
-
- named!(pub character -> Lit, do_parse!(
- punct!("'") >>
- ch: cooked_char >>
- tag!("'") >>
- (l(ch))
- ));
-
- named!(pub float -> Lit, do_parse!(
- value: float_string >>
- suffix: alt!(
- tag!("f32")
- |
- tag!("f64")
- |
- epsilon!() => { |_| "" }
- ) >>
- (l(Literal::float(&format!("{}{}", value, suffix))))
- ));
-
- named!(pub int -> Lit, do_parse!(
- value: digits >>
- suffix: alt!(
- tag!("isize")
- |
- tag!("i8")
- |
- tag!("i16")
- |
- tag!("i32")
- |
- tag!("i64")
- |
- tag!("usize")
- |
- tag!("u8")
- |
- tag!("u16")
- |
- tag!("u32")
- |
- tag!("u64")
- |
- epsilon!() => { |_| "" }
- ) >>
- (l(Literal::integer(&format!("{}{}", value, suffix))))
- ));
-
- named!(pub boolean -> Lit, alt!(
- keyword!("true") => { |_| Lit {
- span: Span::default(),
- value: LitKind::Bool(true),
- } }
- |
- keyword!("false") => { |_| Lit {
- span: Span::default(),
- value: LitKind::Bool(false),
- } }
- ));
-
- fn float_string(mut input: &str) -> IResult<&str, String> {
- input = skip_whitespace(input);
-
- let mut chars = input.chars().peekable();
- match chars.next() {
- Some(ch) if ch >= '0' && ch <= '9' => {}
- _ => return IResult::Error,
- }
-
- let mut len = 1;
- let mut has_dot = false;
- let mut has_exp = false;
- while let Some(&ch) = chars.peek() {
- match ch {
- '0'...'9' | '_' => {
- chars.next();
- len += 1;
- }
- '.' => {
- if has_dot {
- break;
- }
- relex::LToken::Lit(relex::Lit::Char(c)) => {
- Lit::Char(c)
- }
- relex::LToken::Lit(relex::Lit::Integer(v, suffix)) => {
- let suffix = match suffix {
- relex::IntSuffix::Unsuffixed =>
- IntTy::Unsuffixed,
- relex::IntSuffix::Isize =>
- IntTy::Isize,
- relex::IntSuffix::Usize =>
- IntTy::Usize,
- relex::IntSuffix::I8 =>
- IntTy::I8,
- relex::IntSuffix::U8 =>
- IntTy::U8,
- relex::IntSuffix::I16 =>
- IntTy::I16,
- relex::IntSuffix::U16 =>
- IntTy::U16,
- relex::IntSuffix::I32 =>
- IntTy::I32,
- relex::IntSuffix::U32 =>
- IntTy::U32,
- relex::IntSuffix::I64 =>
- IntTy::I64,
- relex::IntSuffix::U64 =>
- IntTy::U64,
- };
- Lit::Int(v, suffix)
- }
- relex::LToken::Lit(relex::Lit::Float(v, suffix)) => {
- let suffix = match suffix {
- relex::FloatSuffix::Unsuffixed =>
- FloatTy::Unsuffixed,
- relex::FloatSuffix::F32 =>
- FloatTy::F32,
- relex::FloatSuffix::F64 =>
- FloatTy::F64,
- };
- Lit::Float(v, suffix)
- }
- relex::LToken::Lit(relex::Lit::Str(s, relex::StrStyle::Cooked)) => {
- Lit::Str(s, StrStyle::Cooked)
- }
- relex::LToken::Lit(relex::Lit::Str(s, relex::StrStyle::Raw(n))) => {
- Lit::Str(s, StrStyle::Raw(n))
- }
- relex::LToken::Lit(relex::Lit::ByteStr(s, relex::StrStyle::Cooked)) => {
- Lit::ByteStr(s, StrStyle::Cooked)
- }
- relex::LToken::Lit(relex::Lit::ByteStr(s, relex::StrStyle::Raw(n))) => {
- Lit::ByteStr(s, StrStyle::Raw(n))
- }
- _ => return IResult::Error
- };
-
- IResult::Done(&i[1..], lit)
- }
- Some(&TokenTree{ kind: TokenKind::Word(ref w), .. }) => {
- if &**w == "true" {
- IResult::Done(&i[1..], Lit::Bool(true))
- } else if &**w == "false" {
- IResult::Done(&i[1..], Lit::Bool(false))
- } else {
- IResult::Error
- }
- }
- _ => IResult::Error
- }
- }
-
- #[cfg(feature = "full")]
- pub fn digits(i: &[TokenTree]) -> IResult<&[TokenTree], u64> {
- if let IResult::Done(r, Lit::Int(v, IntTy::Unsuffixed)) = lit(i) {
- IResult::Done(r, v)
- } else {
- IResult::Error
- }
- }
-
- pub fn string(i: &[TokenTree]) -> IResult<&[TokenTree], String> {
- if let IResult::Done(r, Lit::Str(v, _)) = lit(i) {
- IResult::Done(r, v)
- } else {
- IResult::Error
- }
- }
-
- pub fn byte_string(i: &[TokenTree]) -> IResult<&[TokenTree], Vec<u8>> {
- if let IResult::Done(r, Lit::ByteStr(v, _)) = lit(i) {
- IResult::Done(r, v)
- } else {
- IResult::Error
- }
- }
-
- pub fn digits(mut input: &str) -> IResult<&str, &str> {
- input = skip_whitespace(input);
-
- let base = if input.starts_with("0x") {
- 16
- } else if input.starts_with("0o") {
- 8
- } else if input.starts_with("0b") {
- 2
- } else {
- IResult::Error
- }
- }
-
- let mut value = 0u64;
- let mut len = if base == 10 {0} else {2};
- let mut empty = true;
- for b in input[len..].bytes() {
- let digit = match b {
- b'0'...b'9' => (b - b'0') as u64,
- b'a'...b'f' => 10 + (b - b'a') as u64,
- b'A'...b'F' => 10 + (b - b'A') as u64,
- b'_' => {
- if empty && base == 10 {
- return IResult::Error;
- }
- len += 1;
- continue;
- }
- _ => break,
- };
- if digit >= base {
- return IResult::Error;
- }
- value = match value.checked_mul(base) {
- Some(value) => value,
+ impl Synom for Lit {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ let mut tokens = input.iter();
+ let token = match tokens.next() {
+ Some(token) => token,
None => return IResult::Error,
};
- value = match value.checked_add(digit) {
- Some(value) => value,
- None => return IResult::Error,
+ let kind = match token.kind {
+ TokenKind::Literal(ref l) => LitKind::Other(l.clone()),
+ TokenKind::Word(ref s) if s.as_str() == "true" => LitKind::Bool(true),
+ TokenKind::Word(ref s) if s.as_str() == "false" => LitKind::Bool(false),
+ _ => return IResult::Error,
};
- len += 1;
- empty = false;
- }
- }
-
- pub fn int(i: &[TokenTree]) -> IResult<&[TokenTree], u64> {
- if let IResult::Done(r, Lit::Int(v, _)) = lit(i) {
- IResult::Done(r, v)
- } else {
- IResult::Error
- }
- }
-
- pub fn boolean(i: &[TokenTree]) -> IResult<&[TokenTree], bool> {
- if let IResult::Done(r, Lit::Bool(b)) = lit(i) {
- IResult::Done(r, b)
- } else {
- IResult::Done(&input[len..], &input[..len])
+ IResult::Done(tokens.as_slice(), Lit {
+ span: Span(token.span),
+ value: kind,
+ })
}
}
}
diff --git a/src/mac.rs b/src/mac.rs
index 8ce8c33..5e6d02e 100644
--- a/src/mac.rs
+++ b/src/mac.rs
@@ -134,195 +134,42 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use {Lifetime};
- use generics::parsing::lifetime;
- use ident::parsing::word;
- use lit::parsing::lit;
- use synom::IResult;
- use synom::space::{block_comment, whitespace, skip_whitespace};
- use ty::parsing::path;
- use proc_macro2::{self, TokenStream, TokenKind, Delimiter, OpKind, Literal};
- fn tt(kind: TokenKind) -> TokenTree {
- TokenTree(proc_macro2::TokenTree {
- kind: kind,
- span: Default::default(),
- })
- }
+ use proc_macro2::{TokenKind, TokenTree};
+ use synom::tokens::*;
+ use synom::{Synom, IResult};
- named!(pub mac -> Mac, do_parse!(
- what: path >>
- punct!("!") >>
- body: delimited >>
- (Mac {
- path: what,
- bang_token: tokens::Bang::default(),
- tokens: vec![body],
- })
- ));
-
- named!(pub token_trees -> Vec<TokenTree>, many0!(token_tree));
-
- named!(pub token_stream -> TokenStream,
- map!(token_trees, |t: Vec<TokenTree>| t.into_iter().map(|t| t.0).collect()));
-
- named!(pub delimited -> TokenTree, alt!(
- delimited!(
- punct!("("),
- token_stream,
- punct!(")")
- ) => { |ts| tt(TokenKind::Sequence(Delimiter::Parenthesis, ts)) }
- |
- delimited!(
- punct!("["),
- token_stream,
- punct!("]")
- ) => { |ts| tt(TokenKind::Sequence(Delimiter::Bracket, ts)) }
- |
- delimited!(
- punct!("{"),
- token_stream,
- punct!("}")
- ) => { |ts| tt(TokenKind::Sequence(Delimiter::Brace, ts)) }
- ));
-
- named!(pub token_tree -> TokenTree, alt!(
- token
- |
- delimited
- ));
-
- macro_rules! punct1 {
- ($i:expr, $punct:expr) => {
- punct1($i, $punct)
+ impl Synom for Mac {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ what: syn!(Path) >>
+ bang: syn!(Bang) >>
+ body: call!(::TokenTree::parse_delimited) >>
+ (Mac {
+ path: what,
+ bang_token: bang,
+ tokens: vec![body],
+ })
+ }
}
}
- fn punct1<'a>(input: &'a str, token: &'static str) -> IResult<&'a str, char> {
- let input = skip_whitespace(input);
- if input.starts_with(token) {
- IResult::Done(&input[1..], token.chars().next().unwrap())
- } else {
- IResult::Error
+ impl ::TokenTree {
+ pub fn parse_list(input: &[TokenTree]) -> IResult<&[TokenTree], Vec<Self>> {
+ IResult::Done(&[], input.iter().cloned().map(::TokenTree).collect())
+ }
+
+ pub fn parse_delimited(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ let mut tokens = input.iter();
+ match tokens.next() {
+ Some(token @ &TokenTree { kind: TokenKind::Sequence(..), .. }) => {
+ IResult::Done(tokens.as_slice(), ::TokenTree(token.clone()))
+ }
+ _ => IResult::Error,
+ }
}
}
-
- named!(token -> TokenTree, alt!(
- keyword!("_") => { |_| tt(TokenKind::Op('_', OpKind::Alone)) }
- |
- punct1!("&&") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) } // must be before BinOp
- |
- punct1!("||") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) } // must be before BinOp
- |
- punct1!("->") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) } // must be before BinOp
- |
- punct1!("<-") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) } // must be before Lt
- |
- punct1!("=>") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) } // must be before Eq
- |
- punct1!("...") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) } // must be before DotDot
- |
- punct1!("..") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) } // must be before Dot
- |
- punct1!(".") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- // must be before bin_op
- map!(doc_comment, |s: String| tt(TokenKind::Literal(Literal::doccomment(&s))))
- |
- bin_op_eq // must be before bin_op
- |
- bin_op
- |
- map!(lit, |l: Lit| l.into_token_tree())
- |
- map!(word, |w: Ident| tt(TokenKind::Word(w.sym)))
- |
- map!(lifetime, |lt: Lifetime| tt(TokenKind::Word(lt.ident.sym)))
- |
- punct1!("<=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("==") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("!=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!(">=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("::") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("=") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("<") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!(">") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("!") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("~") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("@") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!(",") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!(";") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!(":") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("#") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("$") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("?") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- ));
-
- named!(bin_op -> TokenTree, alt!(
- punct1!("+") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("-") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("*") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("/") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("%") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("^") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("&") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("|") => { |c| tt(TokenKind::Op(c, OpKind::Alone)) }
- |
- punct1!("<<") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!(">>") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- ));
-
- named!(bin_op_eq -> TokenTree, alt!(
- punct1!("+=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("-=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("*=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("/=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("%=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("^=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("&=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("|=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!("<<=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- |
- punct1!(">>=") => { |c| tt(TokenKind::Op(c, OpKind::Joint)) }
- ));
-
- named!(doc_comment -> String, alt!(
- inner_doc_comment
- |
- outer_doc_comment
- ));
}
#[cfg(feature = "printing")]
diff --git a/src/op.rs b/src/op.rs
index 636b974..e059929 100644
--- a/src/op.rs
+++ b/src/op.rs
@@ -77,75 +77,90 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
+ use synom::{TokenTree, IResult, Synom};
+ use synom::tokens::*;
- named!(pub binop -> BinOp, alt!(
- punct!("&&") => { |_| BinOp::And(tokens::AndAnd::default()) }
- |
- punct!("||") => { |_| BinOp::Or(tokens::OrOr::default()) }
- |
- punct!("<<") => { |_| BinOp::Shl(tokens::Shl::default()) }
- |
- punct!(">>") => { |_| BinOp::Shr(tokens::Shr::default()) }
- |
- punct!("==") => { |_| BinOp::Eq(tokens::EqEq::default()) }
- |
- punct!("<=") => { |_| BinOp::Le(tokens::Le::default()) }
- |
- punct!("!=") => { |_| BinOp::Ne(tokens::Ne::default()) }
- |
- punct!(">=") => { |_| BinOp::Ge(tokens::Ge::default()) }
- |
- punct!("+") => { |_| BinOp::Add(tokens::Add::default()) }
- |
- punct!("-") => { |_| BinOp::Sub(tokens::Sub::default()) }
- |
- punct!("*") => { |_| BinOp::Mul(tokens::Star::default()) }
- |
- punct!("/") => { |_| BinOp::Div(tokens::Div::default()) }
- |
- punct!("%") => { |_| BinOp::Rem(tokens::Rem::default()) }
- |
- punct!("^") => { |_| BinOp::BitXor(tokens::Caret::default()) }
- |
- punct!("&") => { |_| BinOp::BitAnd(tokens::And::default()) }
- |
- punct!("|") => { |_| BinOp::BitOr(tokens::Or::default()) }
- |
- punct!("<") => { |_| BinOp::Lt(tokens::Lt::default()) }
- |
- punct!(">") => { |_| BinOp::Gt(tokens::Gt::default()) }
- ));
+ impl BinOp {
+ pub fn parse_binop(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(AndAnd) => { BinOp::And }
+ |
+ syn!(OrOr) => { BinOp::Or }
+ |
+ syn!(Shl) => { BinOp::Shl }
+ |
+ syn!(Shr) => { BinOp::Shr }
+ |
+ syn!(EqEq) => { BinOp::Eq }
+ |
+ syn!(Le) => { BinOp::Le }
+ |
+ syn!(Ne) => { BinOp::Ne }
+ |
+ syn!(Ge) => { BinOp::Ge }
+ |
+ syn!(Add) => { BinOp::Add }
+ |
+ syn!(Sub) => { BinOp::Sub }
+ |
+ syn!(Star) => { BinOp::Mul }
+ |
+ syn!(Div) => { BinOp::Div }
+ |
+ syn!(Rem) => { BinOp::Rem }
+ |
+ syn!(Caret) => { BinOp::BitXor }
+ |
+ syn!(And) => { BinOp::BitAnd }
+ |
+ syn!(Or) => { BinOp::BitOr }
+ |
+ syn!(Lt) => { BinOp::Lt }
+ |
+ syn!(Gt) => { BinOp::Gt }
+ }
+ }
- #[cfg(feature = "full")]
- named!(pub assign_op -> BinOp, alt!(
- punct!("+=") => { |_| BinOp::AddEq(tokens::AddEq::default()) }
- |
- punct!("-=") => { |_| BinOp::SubEq(tokens::SubEq::default()) }
- |
- punct!("*=") => { |_| BinOp::MulEq(tokens::MulEq::default()) }
- |
- punct!("/=") => { |_| BinOp::DivEq(tokens::DivEq::default()) }
- |
- punct!("%=") => { |_| BinOp::RemEq(tokens::RemEq::default()) }
- |
- punct!("^=") => { |_| BinOp::BitXorEq(tokens::CaretEq::default()) }
- |
- punct!("&=") => { |_| BinOp::BitAndEq(tokens::AndEq::default()) }
- |
- punct!("|=") => { |_| BinOp::BitOrEq(tokens::OrEq::default()) }
- |
- punct!("<<=") => { |_| BinOp::ShlEq(tokens::ShlEq::default()) }
- |
- punct!(">>=") => { |_| BinOp::ShrEq(tokens::ShrEq::default()) }
- ));
+ #[cfg(feature = "full")]
+ pub fn parse_assign_op(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(AddEq) => { BinOp::AddEq }
+ |
+ syn!(SubEq) => { BinOp::SubEq }
+ |
+ syn!(MulEq) => { BinOp::MulEq }
+ |
+ syn!(DivEq) => { BinOp::DivEq }
+ |
+ syn!(RemEq) => { BinOp::RemEq }
+ |
+ syn!(CaretEq) => { BinOp::BitXorEq }
+ |
+ syn!(AndEq) => { BinOp::BitAndEq }
+ |
+ syn!(OrEq) => { BinOp::BitOrEq }
+ |
+ syn!(ShlEq) => { BinOp::ShlEq }
+ |
+ syn!(ShrEq) => { BinOp::ShrEq }
+ }
+ }
+ }
- named!(pub unop -> UnOp, alt!(
- punct!("*") => { |_| UnOp::Deref(tokens::Star::default()) }
- |
- punct!("!") => { |_| UnOp::Not(tokens::Bang::default()) }
- |
- punct!("-") => { |_| UnOp::Neg(tokens::Sub::default()) }
- ));
+ impl Synom for UnOp {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(Star) => { UnOp::Deref }
+ |
+ syn!(Bang) => { UnOp::Not }
+ |
+ syn!(Sub) => { UnOp::Neg }
+ }
+ }
+ }
}
#[cfg(feature = "printing")]
diff --git a/src/ty.rs b/src/ty.rs
index c6e8539..0ee4188 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -257,7 +257,7 @@
pub lifetimes: Option<BoundLifetimes>,
pub unsafety: Unsafety,
pub abi: Option<Abi>,
- pub fn_token: tokens::Fn,
+ pub fn_token: tokens::Fn_,
pub paren_token: tokens::Paren,
pub inputs: Delimited<BareFnArg, tokens::Comma>,
pub variadic: Option<tokens::Dot3>,
@@ -314,168 +314,213 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use {TyParamBound, TraitBoundModifier};
- #[cfg(feature = "full")]
- use ConstExpr;
- #[cfg(feature = "full")]
- use constant::parsing::const_expr;
- #[cfg(feature = "full")]
- use expr::parsing::expr;
- use generics::parsing::{lifetime, ty_param_bound, bound_lifetimes};
- use ident::parsing::ident;
- use lit::parsing::string;
- use mac::parsing::mac;
- #[cfg(feature = "full")]
- use synom::{IResult, TokenTree};
+ // use {TyParamBound, TraitBoundModifier};
+ // #[cfg(feature = "full")]
+ // use ConstExpr;
+ // #[cfg(feature = "full")]
+ // use constant::parsing::const_expr;
+ // #[cfg(feature = "full")]
+ // use expr::parsing::expr;
+ // use generics::parsing::{lifetime, ty_param_bound, bound_lifetimes};
+ // use ident::parsing::ident;
+ // use lit::parsing::string;
+ // use mac::parsing::mac;
+ use proc_macro2::TokenTree;
+ use synom::{IResult, Synom};
+ use synom::tokens::*;
- named!(pub ty -> Ty, alt!(
- ty_paren // must be before ty_tup
- |
- ty_mac // must be before ty_path
- |
- ty_path // must be before ty_poly_trait_ref
- |
- ty_vec
- |
- ty_array
- |
- ty_ptr
- |
- ty_rptr
- |
- ty_bare_fn
- |
- ty_never
- |
- ty_tup
- |
- ty_poly_trait_ref
- |
- ty_impl_trait
- ));
+ impl Synom for Ty {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ // must be before mac
+ syn!(TyParen) => { Ty::Paren }
+ |
+ // must be before path
+ syn!(Mac) => { Ty::Mac }
+ |
+ // must be before ty_poly_trait_ref
+ ty_path
+ |
+ syn!(TySlice) => { Ty::Slice }
+ |
+ syn!(TyArray) => { Ty::Array }
+ |
+ syn!(TyPtr) => { Ty::Ptr }
+ |
+ syn!(TyRptr) => { Ty::Rptr }
+ |
+ syn!(TyBareFn) => { Ty::BareFn }
+ |
+ syn!(TyNever) => { Ty::Never }
+ |
+ syn!(TyTup) => { Ty::Tup }
+ |
+ ty_poly_trait_ref
+ |
+ syn!(TyImplTrait) => { Ty::ImplTrait }
+ }
+ }
- named!(ty_mac -> Ty, map!(mac, Ty::Mac));
+ fn description() -> Option<&'static str> {
+ Some("type")
+ }
+ }
- named!(ty_vec -> Ty, delim!(Bracket, do_parse!(
- elem: ty >>
- punct!("]") >>
- (TySlice {
- ty: Box::new(elem),
- bracket_token: tokens::Bracket::default(),
- }.into())
- ));
+ impl Synom for TySlice {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ map! {
+ input,
+ brackets!(syn!(Ty)),
+ |(ty, b)| TySlice {
+ ty: Box::new(ty),
+ bracket_token: b,
+ }
+ }
+ }
+ }
- named!(ty_array -> Ty, delim!(Bracket, do_parse!(
- elem: ty >>
- punct!(";") >>
- len: array_len >>
- punct!("]") >>
- (TyArray {
- ty: Box::new(elem),
- amt: len,
- bracket_token: tokens::Bracket::default(),
- semi_token: tokens::Semi::default(),
- }.into())
- ));
+ impl Synom for TyArray {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ map! {
+ input,
+ brackets!(do_parse!(
+ elem: syn!(Ty) >>
+ semi: syn!(Semi) >>
+ len: array_len >>
+ (elem, semi, len)
+ )),
+ |((elem, semi, len), brackets)| {
+ TyArray {
+ ty: Box::new(elem),
+ amt: len,
+ bracket_token: brackets,
+ semi_token: semi,
+ }
+ }
+ }
+ }
+ }
#[cfg(not(feature = "full"))]
- use constant::parsing::const_expr as array_len;
+ named!(array_len -> ConstExpr, syn!(ConstExpr));
#[cfg(feature = "full")]
named!(array_len -> ConstExpr, alt!(
- terminated!(const_expr, input_end!())
+ terminated!(syn!(ConstExpr), input_end!())
|
- terminated!(expr, input_end!()) => { ConstExpr::Other }
+ terminated!(syn!(Expr), input_end!()) => { ConstExpr::Other }
));
- named!(ty_ptr -> Ty, do_parse!(
- punct!("*") >>
- mutability: alt!(
- keyword!("const") => { |_| Mutability::Immutable }
- |
- keyword!("mut") => { |_| Mutability::Mutable(tokens::Mut::default()) }
- ) >>
- target: ty >>
- (TyPtr {
- const_token: match mutability {
- Mutability::Mutable(_) => None,
- Mutability::Immutable => Some(tokens::Const::default()),
- },
- star_token: tokens::Star::default(),
- ty: Box::new(MutTy {
- ty: target,
- mutability: mutability,
- }),
- }.into())
- ));
+ impl Synom for TyPtr {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ star: syn!(Star) >>
+ mutability: alt!(
+ syn!(Const) => { |c| (Mutability::Immutable, Some(c)) }
+ |
+ syn!(Mut) => { |m| (Mutability::Mutable(m), None) }
+ ) >>
+ target: syn!(Ty) >>
+ (TyPtr {
+ const_token: mutability.1,
+ star_token: star,
+ ty: Box::new(MutTy {
+ ty: target,
+ mutability: mutability.0,
+ }),
+ })
+ }
+ }
+ }
- named!(ty_rptr -> Ty, do_parse!(
- punct!("&") >>
- life: option!(lifetime) >>
- mutability: mutability >>
- target: ty >>
- (TyRptr {
- lifetime: life,
- ty: Box::new(MutTy {
- ty: target,
- mutability: mutability,
- }),
- and_token: tokens::And::default(),
- }.into())
- ));
+ impl Synom for TyRptr {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ amp: syn!(And) >>
+ life: option!(syn!(Lifetime)) >>
+ mutability: syn!(Mutability) >>
+ target: syn!(Ty) >>
+ (TyRptr {
+ lifetime: life,
+ ty: Box::new(MutTy {
+ ty: target,
+ mutability: mutability,
+ }),
+ and_token: amp,
+ })
+ }
+ }
+ }
- named!(ty_bare_fn -> Ty, do_parse!(
- lifetimes: bound_lifetimes >>
- unsafety: unsafety >>
- abi: option!(abi) >>
- keyword!("fn") >>
- punct!("(") >>
- inputs: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- fn_arg) >>
- variadic: option!(cond_reduce!(inputs.is_empty() || inputs.trailing_delim(),
- punct!("..."))) >>
- punct!(")") >>
- output: fn_ret_ty >>
- (TyBareFn {
- ty: Box::new(BareFnTy {
- unsafety: unsafety,
- abi: abi,
- lifetimes: lifetimes,
- inputs: inputs,
- output: output,
- variadic: variadic.map(|_| tokens::Dot3::default()),
- fn_token: tokens::Fn::default(),
- paren_token: tokens::Paren::default(),
- }),
- }.into())
- ));
+ impl Synom for TyBareFn {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ lifetimes: option!(syn!(BoundLifetimes)) >>
+ unsafety: syn!(Unsafety) >>
+ abi: option!(syn!(Abi)) >>
+ fn_: syn!(Fn_) >>
+ parens: parens!(do_parse!(
+ inputs: call!(Delimited::parse_terminated) >>
+ variadic: option!(cond_reduce!(inputs.is_empty() || inputs.trailing_delim(),
+ syn!(Dot3))) >>
+ (inputs, variadic)
+ )) >>
+ output: syn!(FunctionRetTy) >>
+ (TyBareFn {
+ ty: Box::new(BareFnTy {
+ unsafety: unsafety,
+ abi: abi,
+ lifetimes: lifetimes,
+ output: output,
+ variadic: (parens.0).1,
+ fn_token: fn_,
+ paren_token: parens.1,
+ inputs: (parens.0).0,
+ }),
+ })
+ }
+ }
+ }
- named!(ty_never -> Ty, map!(punct!("!"), |_| TyNever {
- bang_token: tokens::Bang::default(),
- }.into()));
+ impl Synom for TyNever {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ map! {
+ input,
+ syn!(Bang),
+ |b| TyNever { bang_token: b }
+ }
+ }
+ }
- named!(ty_tup -> Ty, do_parse!(
- punct!("(") >>
- elems: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- ty) >>
- punct!(")") >>
- (TyTup {
- tys: elems,
- paren_token: tokens::Paren::default(),
- lone_comma: None, // TODO: does this just not parse?
- }.into())
- ));
+ impl Synom for TyTup {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ data: parens!(call!(Delimited::parse_terminated)) >>
+ (TyTup {
+ tys: data.0,
+ paren_token: data.1,
+ lone_comma: None, // TODO: does this just not parse?
+ })
+ }
+ }
+ }
named!(ty_path -> Ty, do_parse!(
qpath: qpath >>
parenthesized: cond!(
qpath.1.segments.get(qpath.1.segments.len() - 1).item().parameters.is_empty(),
- option!(parenthesized_parameter_data)
+ option!(syn!(ParenthesizedParameterData))
) >>
- bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
+ bounds: many0!(tuple!(syn!(Add), syn!(TyParamBound))) >>
({
let (qself, mut path) = qpath;
if let Some(Some(parenthesized)) = parenthesized {
+ let parenthesized = PathParameters::Parenthesized(parenthesized);
let len = path.segments.len();
path.segments.get_mut(len - 1).item_mut().parameters = parenthesized;
}
@@ -491,7 +536,7 @@
);
let mut new_bounds = Delimited::new();
new_bounds.push_first(path);
- for bound in bounds {
+ for (_tok, bound) in bounds {
new_bounds.push_default(bound);
}
TyTraitObject { bounds: new_bounds }.into()
@@ -499,263 +544,299 @@
})
));
- named!(parenthesized_parameter_data -> PathParameters, do_parse!(
- punct!("(") >>
- inputs: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
- ty) >>
- punct!(")") >>
- output: fn_ret_ty >>
- (PathParameters::Parenthesized(
- ParenthesizedParameterData {
- paren_token: tokens::Paren::default(),
- inputs: inputs,
- output: output,
- },
- ))
- ));
-
- named!(pub fn_ret_ty -> FunctionRetTy, map!(
- option!(preceded!(
- punct!("->"),
- ty
- )),
- |ty| {
- match ty {
- Some(ty) => FunctionRetTy::Ty(ty, tokens::RArrow::default()),
- None => FunctionRetTy::Default,
- }
- }
- ));
-
named!(pub qpath -> (Option<QSelf>, Path), alt!(
- map!(path, |p| (None, p))
+ map!(syn!(Path), |p| (None, p))
|
do_parse!(
- punct!("<") >>
- this: map!(ty, Box::new) >>
- path: option!(preceded!(
- keyword!("as"),
- path
+ lt: syn!(Lt) >>
+ this: map!(syn!(Ty), Box::new) >>
+ path: option!(do_parse!(
+ as_: syn!(As) >>
+ path: syn!(Path) >>
+ (as_, path)
)) >>
- punct!(">") >>
- punct!("::") >>
- rest: separated_nonempty_list!(
- map!(punct!("::"), |_| tokens::Colon2::default()),
- path_segment
- ) >>
+ gt: syn!(Gt) >>
+ colon2: syn!(Colon2) >>
+ rest: call!(Delimited::parse_separated_nonempty) >>
({
- let as_token = path.as_ref().map(|_| tokens::As::default());
- let (pos, path) = match path {
- Some(mut path) => {
+ let (pos, path, as_) = match path {
+ Some((as_, mut path)) => {
let pos = path.segments.len();
if !path.segments.is_empty() && !path.segments.trailing_delim() {
- path.segments.push_trailing(tokens::Colon2::default());
+ path.segments.push_trailing(colon2);
}
- for item in rest.into_iter() {
+ for item in rest {
path.segments.push(item);
}
- (pos, path)
+ (pos, path, Some(as_))
}
None => {
(0, Path {
leading_colon: None,
global: false,
segments: rest,
- })
+ }, None)
}
};
(Some(QSelf {
ty: this,
position: pos,
- gt_token: tokens::Gt::default(),
- lt_token: tokens::Lt::default(),
- as_token: as_token,
+ gt_token: gt,
+ lt_token: lt,
+ as_token: as_,
}), path)
})
)
|
- map!(keyword!("self"), |_| (None, "self".into()))
+ map!(syn!(Self_), |s: Self_| (None, s.into()))
));
+ impl Synom for ParenthesizedParameterData {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ data: parens!(call!(Delimited::parse_terminated)) >>
+ output: syn!(FunctionRetTy) >>
+ (ParenthesizedParameterData {
+ paren_token: data.1,
+ inputs: data.0,
+ output: output,
+ })
+ }
+ }
+ }
+
+ impl Synom for FunctionRetTy {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ arrow: syn!(RArrow) >>
+ ty: syn!(Ty) >>
+ (FunctionRetTy::Ty(ty, arrow))
+ )
+ |
+ epsilon!() => { |_| FunctionRetTy::Default }
+ }
+ }
+ }
+
named!(ty_poly_trait_ref -> Ty, map!(
- separated_nonempty_list!(map!(punct!("+"), |_| tokens::Add::default()),
- ty_param_bound),
+ call!(Delimited::parse_separated_nonempty),
|x| TyTraitObject { bounds: x }.into()
));
- named!(ty_impl_trait -> Ty, do_parse!(
- keyword!("impl") >>
- elem: separated_nonempty_list!(map!(punct!("+"), |_| tokens::Add::default()),
- ty_param_bound) >>
- (TyImplTrait {
- impl_token: tokens::Impl::default(),
- bounds: elem,
- }.into())
- ));
+ impl Synom for TyImplTrait {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ impl_: syn!(Impl) >>
+ elem: call!(Delimited::parse_separated_nonempty) >>
+ (TyImplTrait {
+ impl_token: impl_,
+ bounds: elem,
+ })
+ }
+ }
+ }
- named!(ty_paren -> Ty, do_parse!(
- punct!("(") >>
- elem: ty >>
- punct!(")") >>
- (TyParen {
- paren_token: tokens::Paren::default(),
- ty: Box::new(elem),
- }.into())
- ));
+ impl Synom for TyParen {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ data: parens!(syn!(Ty)) >>
+ (TyParen {
+ paren_token: data.1,
+ ty: Box::new(data.0),
+ })
+ }
+ }
+ }
- named!(pub mutability -> Mutability, alt!(
- keyword!("mut") => { |_| Mutability::Mutable(tokens::Mut::default()) }
- |
- epsilon!() => { |_| Mutability::Immutable }
- ));
+ impl Synom for Mutability {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(Mut) => { Mutability::Mutable }
+ |
+ epsilon!() => { |_| Mutability::Immutable }
+ }
+ }
+ }
- named!(pub path -> Path, do_parse!(
- global: option!(punct!("::")) >>
- segments: separated_nonempty_list!(map!(punct!("::"), |_| tokens::Colon2::default()),
- path_segment) >>
- (Path {
- global: global.is_some(),
- segments: segments,
- leading_colon: global.map(|_| tokens::Colon2::default()),
- })
- ));
+ impl Synom for Path {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ global: option!(syn!(Colon2)) >>
+ segments: call!(Delimited::parse_separated_nonempty) >>
+ (Path {
+ global: global.is_some(),
+ segments: segments,
+ leading_colon: global,
+ })
+ }
+ }
+ }
- named!(path_segment -> PathSegment, alt!(
- do_parse!(
- id: option!(ident) >>
- punct!("<") >>
- lifetimes: terminated_list!(
- map!(punct!(","), |_| tokens::Comma::default()),
- lifetime
- ) >>
- types: cond!(
- lifetimes.is_empty() || lifetimes.trailing_delim(),
- terminated_list!(
- map!(punct!(","), |_| tokens::Comma::default()),
- terminated!(ty, not!(punct!("=")))
+ impl Synom for PathSegment {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ do_parse!(
+ id: option!(syn!(Ident)) >>
+ lt: syn!(Lt) >>
+ lifetimes: call!(Delimited::parse_terminated) >>
+ types: cond!(
+ lifetimes.is_empty() || lifetimes.trailing_delim(),
+ call!(Delimited::parse_terminated_with,
+ ty_no_eq_after)
+ ) >>
+ bindings: cond!(
+ match types {
+ Some(ref t) => t.is_empty() || t.trailing_delim(),
+ None => lifetimes.is_empty() || lifetimes.trailing_delim(),
+ },
+ call!(Delimited::parse_terminated)
+ ) >>
+ gt: syn!(Gt) >>
+ (PathSegment {
+ ident: id.unwrap_or_else(|| "".into()),
+ parameters: PathParameters::AngleBracketed(
+ AngleBracketedParameterData {
+ gt_token: Some(gt),
+ lt_token: Some(lt),
+ lifetimes: lifetimes,
+ types: types.unwrap_or_default(),
+ bindings: bindings.unwrap_or_default(),
+ }
+ ),
+ })
)
- ) >>
- bindings: cond!(
- match types {
- Some(ref t) => t.is_empty() || t.trailing_delim(),
- None => lifetimes.is_empty() || lifetimes.trailing_delim(),
- },
- terminated_list!(
- map!(punct!(","), |_| tokens::Comma::default()),
- type_binding
- )
- ) >>
- punct!(">") >>
- (PathSegment {
- ident: id.unwrap_or_else(|| "".into()),
- parameters: PathParameters::AngleBracketed(
- AngleBracketedParameterData {
- gt_token: Some(tokens::Gt::default()),
- lt_token: Some(tokens::Lt::default()),
- lifetimes: lifetimes,
- types: types.unwrap_or_default(),
- bindings: bindings.unwrap_or_default(),
- }
- ),
- })
- )
- |
- map!(ident, Into::into)
- |
- map!(alt!(
- keyword!("super")
- |
- keyword!("self")
- |
- keyword!("Self")
- ), Into::into)
- ));
+ |
+ mod_style_path_segment
+ }
+ }
+ }
+ named!(ty_no_eq_after -> Ty, terminated!(syn!(Ty), not!(syn!(Eq))));
- named!(pub mod_style_path -> Path, do_parse!(
- global: option!(punct!("::")) >>
- segments: separated_nonempty_list!(map!(punct!("::"), |_| tokens::Colon2::default()),
- mod_style_path_segment) >>
- (Path {
- global: global.is_some(),
- segments: segments,
- leading_colon: global.map(|_| tokens::Colon2::default()),
- })
- ));
+ impl Path {
+ pub fn parse_mod_style(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ global: option!(syn!(Colon2)) >>
+ segments: call!(Delimited::parse_separated_nonempty_with,
+ mod_style_path_segment) >>
+ (Path {
+ global: global.is_some(),
+ segments: segments,
+ leading_colon: global,
+ })
+ }
+ }
+ }
named!(mod_style_path_segment -> PathSegment, alt!(
- map!(ident, Into::into)
+ map!(syn!(Ident), Into::into)
|
- map!(alt!(
- keyword!("super")
+ alt!(
+ syn!(Super) => { Into::into }
|
- keyword!("self")
+ syn!(Self_) => { Into::into }
|
- keyword!("Self")
- ), Into::into)
+ syn!(CapSelf) => { Into::into }
+ )
));
- named!(type_binding -> TypeBinding, do_parse!(
- id: ident >>
- punct!("=") >>
- ty: ty >>
- (TypeBinding {
- ident: id,
- eq_token: tokens::Eq::default(),
- ty: ty,
- })
- ));
-
- named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
- bound_lifetimes: bound_lifetimes >>
- trait_ref: path >>
- parenthesized: option!(cond_reduce!(
- trait_ref.segments.get(trait_ref.segments.len() - 1).item().parameters.is_empty(),
- parenthesized_parameter_data
- )) >>
- ({
- let mut trait_ref = trait_ref;
- if let Some(parenthesized) = parenthesized {
- let len = trait_ref.segments.len();
- trait_ref.segments.get_mut(len - 1).item_mut().parameters = parenthesized;
+ impl Synom for TypeBinding {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ id: syn!(Ident) >>
+ eq: syn!(Eq) >>
+ ty: syn!(Ty) >>
+ (TypeBinding {
+ ident: id,
+ eq_token: eq,
+ ty: ty,
+ })
}
- PolyTraitRef {
- bound_lifetimes: bound_lifetimes,
- trait_ref: trait_ref,
+ }
+ }
+
+ impl Synom for PolyTraitRef {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ bound_lifetimes: option!(syn!(BoundLifetimes)) >>
+ trait_ref: syn!(Path) >>
+ parenthesized: option!(cond_reduce!(
+ trait_ref.segments.get(trait_ref.segments.len() - 1).item().parameters.is_empty(),
+ syn!(ParenthesizedParameterData)
+ )) >>
+ ({
+ let mut trait_ref = trait_ref;
+ if let Some(parenthesized) = parenthesized {
+ let parenthesized = PathParameters::Parenthesized(parenthesized);
+ let len = trait_ref.segments.len();
+ trait_ref.segments.get_mut(len - 1).item_mut().parameters = parenthesized;
+ }
+ PolyTraitRef {
+ bound_lifetimes: bound_lifetimes,
+ trait_ref: trait_ref,
+ }
+ })
}
- })
- ));
+ }
+ }
- named!(pub fn_arg -> BareFnArg, do_parse!(
- name: option!(do_parse!(
- name: ident >>
- not!(punct!("::")) >>
- punct!(":") >>
- (name)
- )) >>
- ty: ty >>
- (BareFnArg {
- name: name.map(|t| (t, tokens::Colon::default())),
- ty: ty,
- })
- ));
+ impl Synom for BareFnArg {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ name: option!(do_parse!(
+ name: syn!(Ident) >>
+ not!(syn!(Colon2)) >>
+ colon: syn!(Colon) >>
+ (name, colon)
+ )) >>
+ ty: syn!(Ty) >>
+ (BareFnArg {
+ name: name,
+ ty: ty,
+ })
+ }
+ }
+ }
- named!(pub unsafety -> Unsafety, alt!(
- keyword!("unsafe") => { |_| Unsafety::Unsafe(tokens::Unsafe::default()) }
- |
- epsilon!() => { |_| Unsafety::Normal }
- ));
+ impl Synom for Unsafety {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ alt! {
+ input,
+ syn!(Unsafe) => { Unsafety::Unsafe }
+ |
+ epsilon!() => { |_| Unsafety::Normal }
+ }
+ }
+ }
- named!(pub abi -> Abi, do_parse!(
- keyword!("extern") >>
- name: option!(string) >>
- (Abi {
- extern_token: tokens::Extern::default(),
- kind: match name {
- Some(name) => AbiKind::Named(name),
- None => AbiKind::Default,
- },
- })
- ));
+ impl Synom for Abi {
+ fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
+ do_parse! {
+ input,
+ extern_: syn!(Extern) >>
+ // TODO: this parses all literals, not just strings
+ name: option!(syn!(Lit)) >>
+ (Abi {
+ extern_token: extern_,
+ kind: match name {
+ Some(name) => AbiKind::Named(name),
+ None => AbiKind::Default,
+ },
+ })
+ }
+ }
+ }
}
#[cfg(feature = "printing")]