Parse paths
diff --git a/src/path.rs b/src/path.rs
index a848944..12c7549 100644
--- a/src/path.rs
+++ b/src/path.rs
@@ -227,122 +227,120 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
+ use parse::{Parse, ParseStream, Result};
+ use synom::ext::IdentExt;
use synom::Synom;
- impl Synom for Path {
- named!(parse -> Self, do_parse!(
- colon: option!(punct!(::)) >>
- segments: call!(Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty) >>
- cond_reduce!(segments.first().map_or(true, |seg| seg.value().ident != "dyn")) >>
- (Path {
- leading_colon: colon,
- segments: segments,
+ impl Parse for Path {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![dyn]) {
+ return Err(input.error("expected path"));
+ }
+
+ Ok(Path {
+ leading_colon: input.parse()?,
+ segments: input.parse_synom(Punctuated::parse_separated_nonempty)?,
})
- ));
-
- fn description() -> Option<&'static str> {
- Some("path")
}
}
- #[cfg(not(feature = "full"))]
- impl Synom for GenericArgument {
- named!(parse -> Self, alt!(
- call!(ty_no_eq_after) => { GenericArgument::Type }
- |
- syn!(Lifetime) => { GenericArgument::Lifetime }
- |
- syn!(Binding) => { GenericArgument::Binding }
- ));
- }
+ impl Parse for GenericArgument {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Lifetime) && !input.peek3(Token![+]) {
+ return Ok(GenericArgument::Lifetime(input.parse()?));
+ }
- #[cfg(feature = "full")]
- impl Synom for GenericArgument {
- named!(parse -> Self, alt!(
- call!(ty_no_eq_after) => { GenericArgument::Type }
- |
- syn!(Lifetime) => { GenericArgument::Lifetime }
- |
- syn!(Binding) => { GenericArgument::Binding }
- |
- syn!(ExprLit) => { |l| GenericArgument::Const(Expr::Lit(l)) }
- |
- syn!(ExprBlock) => { |b| GenericArgument::Const(Expr::Block(b)) }
- ));
+ if input.peek(Ident) && input.peek2(Token![=]) {
+ return Ok(GenericArgument::Binding(input.parse()?));
+ }
- fn description() -> Option<&'static str> {
- Some("generic argument")
+ #[cfg(feature = "full")]
+ {
+ if input.peek(Lit) {
+ let lit = input.parse_synom(ExprLit::parse)?;
+ return Ok(GenericArgument::Const(Expr::Lit(lit)));
+ }
+
+ if input.peek(token::Brace) {
+ let block = input.parse_synom(ExprBlock::parse)?;
+ return Ok(GenericArgument::Const(Expr::Block(block)));
+ }
+ }
+
+ Ok(GenericArgument::Type(input.parse_synom(ty_no_eq_after)?))
}
}
- impl Synom for AngleBracketedGenericArguments {
- named!(parse -> Self, do_parse!(
- colon2: option!(punct!(::)) >>
- lt: punct!(<) >>
- args: call!(Punctuated::parse_terminated) >>
- gt: punct!(>) >>
- (AngleBracketedGenericArguments {
- colon2_token: colon2,
- lt_token: lt,
- args: args,
- gt_token: gt,
+ impl Parse for AngleBracketedGenericArguments {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(AngleBracketedGenericArguments {
+ colon2_token: input.parse()?,
+ lt_token: input.parse()?,
+ args: {
+ let mut args = Punctuated::new();
+ loop {
+ if input.peek(Token![>]) {
+ break;
+ }
+ let value = input.parse()?;
+ args.push_value(value);
+ if input.peek(Token![>]) {
+ break;
+ }
+ let punct = input.parse()?;
+ args.push_punct(punct);
+ }
+ args
+ },
+ gt_token: input.parse()?,
})
- ));
-
- fn description() -> Option<&'static str> {
- Some("angle bracketed generic arguments")
}
}
- impl Synom for ParenthesizedGenericArguments {
- named!(parse -> Self, do_parse!(
- data: parens!(Punctuated::parse_terminated) >>
- output: call!(ReturnType::without_plus) >>
- (ParenthesizedGenericArguments {
- paren_token: data.0,
- inputs: data.1,
- output: output,
+ impl Parse for ParenthesizedGenericArguments {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(ParenthesizedGenericArguments {
+ paren_token: parenthesized!(content in input),
+ inputs: content.parse_synom(Punctuated::parse_terminated)?,
+ output: input.parse_synom(ReturnType::without_plus)?,
})
- ));
-
- fn description() -> Option<&'static str> {
- Some("parenthesized generic arguments: `Foo(A, B, ..) -> T`")
}
}
- impl Synom for PathSegment {
- named!(parse -> Self, alt!(
- do_parse!(
- ident: syn!(Ident) >>
- arguments: syn!(AngleBracketedGenericArguments) >>
- (PathSegment {
+ impl Parse for PathSegment {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![super])
+ || input.peek(Token![self])
+ || input.peek(Token![Self])
+ || input.peek(Token![crate])
+ || input.peek(Token![extern])
+ {
+ let ident = input.parse_synom(Ident::parse_any)?;
+ return Ok(PathSegment::from(ident));
+ }
+
+ let ident = input.parse()?;
+ if input.peek(Token![<]) && !input.peek2(Token![=])
+ || input.peek(Token![::]) && input.peek3(Token![<])
+ {
+ Ok(PathSegment {
ident: ident,
- arguments: PathArguments::AngleBracketed(arguments),
+ arguments: PathArguments::AngleBracketed(input.parse()?),
})
- )
- |
- mod_style_path_segment
- ));
-
- fn description() -> Option<&'static str> {
- Some("path segment")
+ } else {
+ Ok(PathSegment::from(ident))
+ }
}
}
- impl Synom for Binding {
- named!(parse -> Self, do_parse!(
- id: syn!(Ident) >>
- eq: punct!(=) >>
- ty: syn!(Type) >>
- (Binding {
- ident: id,
- eq_token: eq,
- ty: ty,
+ impl Parse for Binding {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(Binding {
+ ident: input.parse()?,
+ eq_token: input.parse()?,
+ ty: input.parse_synom(Type::parse)?,
})
- ));
-
- fn description() -> Option<&'static str> {
- Some("associated type binding")
}
}