Lifetimes as single tokens from cursor
diff --git a/src/buffer.rs b/src/buffer.rs
index 9c5738f..b918a9a 100644
--- a/src/buffer.rs
+++ b/src/buffer.rs
@@ -20,12 +20,13 @@
feature = "proc-macro"
))]
use proc_macro as pm;
-use proc_macro2::{Delimiter, Ident, Literal, Span, TokenStream};
-use proc_macro2::{Group, Punct, TokenTree};
+use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::marker::PhantomData;
use std::ptr;
+use Lifetime;
+
/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
@@ -266,7 +267,9 @@
pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
self.ignore_none();
match *self.entry() {
- Entry::Punct(ref op) => Some((op.clone(), unsafe { self.bump() })),
+ Entry::Punct(ref op) if op.as_char() != '\'' => {
+ Some((op.clone(), unsafe { self.bump() }))
+ }
_ => None,
}
}
@@ -281,6 +284,28 @@
}
}
+ /// If the cursor is pointing at a `Lifetime`, returns it along with a
+ /// cursor pointing at the next `TokenTree`.
+ pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
+ self.ignore_none();
+ match *self.entry() {
+ Entry::Punct(ref op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
+ let next = unsafe { self.bump() };
+ match next.ident() {
+ Some((ident, rest)) => {
+ let lifetime = Lifetime {
+ apostrophe: op.span(),
+ ident: ident,
+ };
+ Some((lifetime, rest))
+ }
+ None => None,
+ }
+ }
+ _ => None,
+ }
+ }
+
/// Copies all remaining tokens visible from this cursor into a
/// `TokenStream`.
pub fn token_stream(self) -> TokenStream {
diff --git a/src/generics.rs b/src/generics.rs
index 5476192..8903408 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -802,7 +802,7 @@
impl Parse for WherePredicate {
fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(Lifetime) && input.peek3(Token![:]) {
+ if input.peek(Lifetime) && input.peek2(Token![:]) {
Ok(WherePredicate::Lifetime(PredicateLifetime {
lifetime: input.parse()?,
colon_token: input.parse()?,
diff --git a/src/lifetime.rs b/src/lifetime.rs
index 2df7ca8..e19cc97 100644
--- a/src/lifetime.rs
+++ b/src/lifetime.rs
@@ -118,23 +118,14 @@
pub mod parsing {
use super::*;
- use proc_macro2::Spacing;
-
- use ext::IdentExt;
use parse::{Parse, ParseStream, Result};
impl Parse for Lifetime {
fn parse(input: ParseStream) -> Result<Self> {
- Ok(Lifetime {
- apostrophe: input.step(|cursor| {
- if let Some((punct, rest)) = cursor.punct() {
- if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint {
- return Ok((punct.span(), rest));
- }
- }
- Err(cursor.error("expected lifetime"))
- })?,
- ident: input.call(Ident::parse_any)?,
+ input.step(|cursor| {
+ cursor
+ .lifetime()
+ .ok_or_else(|| cursor.error("expected lifetime"))
})
}
}
diff --git a/src/parse.rs b/src/parse.rs
index 3419303..afd0800 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -227,6 +227,18 @@
}
}
+fn skip(input: ParseStream) -> bool {
+ input.step(|cursor| {
+ if let Some((_lifetime, rest)) = cursor.lifetime() {
+ Ok((true, rest))
+ } else if let Some((_token, rest)) = cursor.token_tree() {
+ Ok((true, rest))
+ } else {
+ Ok((false, *cursor))
+ }
+ }).unwrap()
+}
+
impl<'a> ParseBuffer<'a> {
// Not public API.
#[doc(hidden)]
@@ -266,28 +278,13 @@
}
pub fn peek2<T: Peek>(&self, token: T) -> bool {
- if self.is_empty() {
- return false;
- }
let ahead = self.fork();
- ahead
- .step(|cursor| Ok(cursor.token_tree().unwrap()))
- .unwrap();
- ahead.peek(token)
+ skip(&ahead) && ahead.peek(token)
}
pub fn peek3<T: Peek>(&self, token: T) -> bool {
- if self.is_empty() {
- return false;
- }
let ahead = self.fork();
- ahead
- .step(|cursor| Ok(cursor.token_tree().unwrap()))
- .unwrap();
- ahead
- .step(|cursor| Ok(cursor.token_tree().unwrap()))
- .unwrap();
- ahead.peek(token)
+ skip(&ahead) && skip(&ahead) && ahead.peek(token)
}
pub fn parse_terminated<T, P: Parse>(
diff --git a/src/path.rs b/src/path.rs
index 3c4ce07..2dafac8 100644
--- a/src/path.rs
+++ b/src/path.rs
@@ -241,7 +241,7 @@
impl Parse for GenericArgument {
fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(Lifetime) && !input.peek3(Token![+]) {
+ if input.peek(Lifetime) && !input.peek2(Token![+]) {
return Ok(GenericArgument::Lifetime(input.parse()?));
}