I'm working on a proc_macro2
/syn
macro, and I've been using Cursor
to do low-level parsing of something... Rust-like. But deep in my grammar, I need to parse a syn::Type
. As far as I know, the only really good way to do this is to use the impl syn::parse::Parse
for syn::Type
.
So what I really would like to find is a nice way to write a function of signature
fn parse_generic<T: Parse>(c: Cursor) -> Option<(T, Cursor)>;
My question then is what is the best (simplest, least problematic) way to implement a function of this type?
Here is the best I've come up with so far:
fn parse_generic<T: Parse>(mut c: Cursor) -> Option<(T, Cursor)> {
match T::parse.parse2(c.token_stream()) {
Ok(t) => Some((t, Cursor::empty())), // because parse2 checks for end-of-stream!
Err(e) => {
// OK, because parse2 checks for end-of-stream, let's chop
// the input at the position of the error and try again (!).
let mut collected = Vec::new();
let upto = e.span().start();
while !c.eof() && c.span().start() != upto {
let (tt, next) = c.token_tree().unwrap();
collected.push(tt);
c = next;
}
match T::parse.parse2(collected.into_iter().collect()) {
Ok(t) => Some((t, c)),
Err(_) => None,
}
}
}
}
It's not disastrous, but it's not ideal either.