Struct ParseBuffer
struct ParseBuffer<'a> { ... }
Cursor position within a buffered token stream.
This type is more commonly used through the type alias ParseStream which
is an alias for &ParseBuffer.
ParseStream is the input type for all parser functions in Syn. They have
the signature fn(ParseStream) -> Result<T>.
Calling a parser function
There is no public way to construct a ParseBuffer. Instead, if you are
looking to invoke a parser function that requires ParseStream as input,
you will need to go through one of the public parsing entry points.
- The
parse_macro_input!macro if parsing input of a procedural macro; - One of the
syn::parse*functions; or - A method of the
Parsertrait.
Implementations
impl<'a> ParseBuffer<'a>
fn parse<T: Parse>(self: &Self) -> Result<T>Parses a syntax tree node of type
T, advancing the position of our parse stream past it.fn call<T>(self: &'a Self, function: fn(_: ParseStream<'a>) -> Result<T>) -> Result<T>Calls the given parser function to parse a syntax tree node of type
Tfrom this stream.Example
The parser below invokes
Attribute::parse_outerto parse a vector of zero or more outer attributes.use ; use ; // Parses a unit struct with attributes. // // #[path = "s.tmpl"] // struct S;fn peek<T: Peek>(self: &Self, token: T) -> boolLooks at the next token in the parse stream to determine whether it matches the requested type of token.
Does not advance the position of the parse stream.
Syntax
Note that this method does not use turbofish syntax. Pass the peek type inside of parentheses.
input.peek(Token![struct])input.peek(Token![==])input.peek(syn::Ident)(does not accept keywords)input.peek(syn::Ident::peek_any)input.peek(Lifetime)input.peek(token::Brace)
Example
In this example we finish parsing the list of supertraits when the next token in the input is either
whereor an opening curly brace.use ; use ; use Punctuated; // Parses a trait definition containing no associated items. // // trait Marker<'de, T>: A + B<'de> where Box<T>: Clone {}fn peek2<T: Peek>(self: &Self, token: T) -> boolLooks at the second-next token in the parse stream.
This is commonly useful as a way to implement contextual keywords.
Example
This example needs to use
peek2because the symbolunionis not a keyword in Rust. We can't use justpeekand decide to parse a union if the very next token isunion, because someone is free to write amod unionand a macro invocation that looks likeunion::some_macro! { ... }. In other wordsunionis a contextual keyword.use ; use ; // Parses either a union or a macro invocation.fn peek3<T: Peek>(self: &Self, token: T) -> boolLooks at the third-next token in the parse stream.
fn parse_terminated<T, P>(self: &'a Self, parser: fn(_: ParseStream<'a>) -> Result<T>, separator: P) -> Result<Punctuated<T, <P as >::Token>> where P: Peek, <P as >::Token: ParseParses zero or more occurrences of
Tseparated by punctuation of typeP, with optional trailing punctuation.Parsing continues until the end of this parse stream. The entire content of this parse stream must consist of
TandP.Example
# use quote; # use ; use ; use Punctuated; // Parse a simplified tuple struct syntax like: // // struct S(A, B); # # let input = quote! ; # .unwrap;See also
If your separator is anything more complicated than an invocation of the
Token!macro, this method won't be applicable and you can instead directly usePunctuated's parser functions:parse_terminated,parse_separated_nonemptyetc.use ; use ; use Punctuated; ;fn is_empty(self: &Self) -> boolReturns whether there are no more tokens remaining to be parsed from this stream.
This method returns true upon reaching the end of the content within a set of delimiters, as well as at the end of the tokens provided to the outermost parsing entry point.
This is equivalent to
.peek(syn::parse::End). Use.peek2(End)or.peek3(End)to look for the end of a parse stream further ahead than the current position.Example
use ; use ; // Parses a Rust `mod m { ... }` containing zero or more items.fn lookahead1(self: &Self) -> Lookahead1<'a>Constructs a helper for peeking at the next token in this stream and building an error message if it is not one of a set of expected tokens.
Example
use ; use ; // A generic parameter, a single one of the comma-separated elements inside // angle brackets in: // // fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... } // // On invalid input, lookahead gives us a reasonable error message. // // error: expected one of: identifier, lifetime, `const` // | // 5 | fn f<!Sized>() {} // | ^fn fork(self: &Self) -> SelfForks a parse stream so that parsing tokens out of either the original or the fork does not advance the position of the other.
Performance
Forking a parse stream is a cheap fixed amount of work and does not involve copying token buffers. Where you might hit performance problems is if your macro ends up parsing a large amount of content more than once.
# use ; # use ParseStream; # #As a rule, avoid parsing an unbounded amount of tokens out of a forked parse stream. Only use a fork when the amount of work performed against the fork is small and bounded.
When complex speculative parsing against the forked stream is unavoidable, use
parse::discouraged::Speculativeto advance the original stream once the fork's parse is determined to have been successful.For a lower level way to perform speculative parsing at the token level, consider using
ParseStream::stepinstead.Example
The parse implementation shown here parses possibly restricted
pubvisibilities.pubpub(crate)pub(self)pub(super)pub(in some::path)
To handle the case of visibilities inside of tuple structs, the parser needs to distinguish parentheses that specify visibility restrictions from parentheses that form part of a tuple type.
# ; # ; # ; # A, pub );In this example input the first tuple struct element of
Shaspub(crate)visibility while the second tuple struct element haspubvisibility; the parentheses around(B, C)are part of the type rather than part of a visibility restriction.The parser uses a forked parse stream to check the first token inside of parentheses after the
pubkeyword. This is a small bounded amount of work performed against the forked parse stream.use ; use IdentExt; use ;fn error<T: Display>(self: &Self, message: T) -> ErrorTriggers an error at the current position of the parse stream.
Example
use ; use ; // Some kind of loop: `while` or `for` or `loop`.fn step<F, R>(self: &Self, function: F) -> Result<R> where F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>Speculatively parses tokens from this parse stream, advancing the position of this stream only if parsing succeeds.
This is a powerful low-level API used for defining the
Parseimpls of the basic built-in token types. It is not something that will be used widely outside of the Syn codebase.Example
use TokenTree; use Result; use ParseStream; // This function advances the stream past the next occurrence of `@`. If // no `@` is present in the stream, the stream position is unchanged and // an error is returned. # # # # use Parser; # let remainder = remainder_after_skipping_past_next_at # .parse_str # .unwrap; # assert_eq!;fn span(self: &Self) -> SpanReturns the
Spanof the next token in the parse stream, orSpan::call_site()if this parse stream has completely exhausted its inputTokenStream.fn cursor(self: &Self) -> Cursor<'a>Provides low-level access to the token representation underlying this parse stream.
Cursors are immutable so no operations you perform against the cursor will affect the state of this parse stream.
Example
use TokenStream; use Cursor; use ; // Run a parser that returns T, but get its output as TokenStream instead of T. // This works without T needing to implement ToTokens. // Collect tokens between two cursors as a TokenStream.
impl<'a> AnyDelimiter for crate::parse::ParseBuffer<'a>
fn parse_any_delimiter(self: &Self) -> Result<(Delimiter, DelimSpan, ParseBuffer<'_>)>
impl<'a> Debug for ParseBuffer<'a>
fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> fmt::Result
impl<'a> Display for ParseBuffer<'a>
fn fmt(self: &Self, f: &mut fmt::Formatter<'_>) -> fmt::Result
impl<'a> Drop for ParseBuffer<'a>
fn drop(self: &mut Self)
impl<'a> Freeze for ParseBuffer<'a>
impl<'a> RefUnwindSafe for ParseBuffer<'a>
impl<'a> Send for ParseBuffer<'a>
impl<'a> Speculative for crate::parse::ParseBuffer<'a>
fn advance_to(self: &Self, fork: &Self)
impl<'a> Sync for ParseBuffer<'a>
impl<'a> Unpin for ParseBuffer<'a>
impl<'a> UnwindSafe for ParseBuffer<'a>
impl<T> Any for ParseBuffer<'a>
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for ParseBuffer<'a>
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for ParseBuffer<'a>
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> From for ParseBuffer<'a>
fn from(t: T) -> TReturns the argument unchanged.
impl<T> ToString for ParseBuffer<'a>
fn to_string(self: &Self) -> String
impl<T, U> Into for ParseBuffer<'a>
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for ParseBuffer<'a>
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for ParseBuffer<'a>
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>