syn
syn copied to clipboard
Feature request: method on ParseStream for "is this the last token"
Purely out of curiosity, I recently attempted parsing Objective-C message syntax inline in Rust using syn
:
[receiver-expr no-arg-selector]
[receiver-expr selector-piece:arg-expr selector-piece:second-arg-expr...]
impl Parse for MessageSend {
fn parse(input: ParseStream) -> Result<Self> {
let receiver: Expr = input.parse()?;
// First speculatively parse zero-argument syntax.
let no_arg_stream = input.fork();
no_arg_stream.call(Ident::parse_any)?;
if no_arg_stream.is_empty() {
return Ok(MessageSend {
receiver,
selector: Selector::ZeroArguments(input.call(Ident::parse_any)?),
arguments: Vec::new(),
})
}
// If that fails, parse multi-argument syntax.
let mut selector_pieces: Vec<Ident> = Vec::new();
let mut arguments: Vec<Expr> = Vec::new();
while !input.is_empty() {
selector_pieces.push(input.call(Ident::parse_any)?);
input.parse::<Token![:]>()?;
arguments.push(input.parse()?);
}
Ok(MessageSend {
receiver,
selector: Selector::SomeArguments(selector_pieces),
arguments,
})
}
}
What I wanted to do was ask "is the next token the last one [in the group]" and use that to decide whether I'm parsing the no-argument or has-argument syntax. However, ParseStream doesn't expose any methods for doing so, despite having peek2
and even peek3
. I ended up forking the stream because that seemed simplest. (I realize that I could have either parsed the identifier unilaterally and then checked, or used step()
to double-parse as efficiently as possible, but neither were as ergonomic, and performance wasn't exactly important for this toy project.)