syn icon indicating copy to clipboard operation
syn copied to clipboard

Feature request: method on ParseStream for "is this the last token"

Open belkadan opened this issue 4 years ago • 0 comments

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.)

belkadan avatar Aug 26 '20 23:08 belkadan