blob: 266e4e901f24157e3385ece2227839ded58b82fa [file] [log] [blame]
David Tolnay80a914f2018-08-30 23:49:53 -07001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnay18c754c2018-08-21 23:26:58 -04009//! Parsing interface for parsing a token stream into a syntax tree node.
David Tolnay80a914f2018-08-30 23:49:53 -070010//!
David Tolnaye0c51762018-08-31 11:05:22 -070011//! Parsing in Syn is built on parser functions that take in a [`ParseStream`]
12//! and produce a [`Result<T>`] where `T` is some syntax tree node. Underlying
13//! these parser functions is a lower level mechanism built around the
14//! [`Cursor`] type. `Cursor` is a cheaply copyable cursor over a range of
15//! tokens in a token stream.
David Tolnay80a914f2018-08-30 23:49:53 -070016//!
David Tolnaye0c51762018-08-31 11:05:22 -070017//! [`ParseStream`]: type.ParseStream.html
18//! [`Result<T>`]: type.Result.html
David Tolnay80a914f2018-08-30 23:49:53 -070019//! [`Cursor`]: ../buffer/index.html
David Tolnay80a914f2018-08-30 23:49:53 -070020//!
David Tolnay43984452018-09-01 17:43:56 -070021//! # Example
David Tolnay80a914f2018-08-30 23:49:53 -070022//!
David Tolnay43984452018-09-01 17:43:56 -070023//! Here is a snippet of parsing code to get a feel for the style of the
24//! library. We define data structures for a subset of Rust syntax including
25//! enums (not shown) and structs, then provide implementations of the [`Parse`]
26//! trait to parse these syntax tree data structures from a token stream.
27//!
28//! ```
29//! # extern crate syn;
30//! #
31//! use syn::{braced, token, Field, Ident, Token};
32//! use syn::parse::{Parse, ParseStream, Result};
33//! use syn::punctuated::Punctuated;
34//!
35//! enum Item {
36//! Struct(ItemStruct),
37//! Enum(ItemEnum),
38//! }
39//!
40//! struct ItemStruct {
41//! struct_token: Token![struct],
42//! ident: Ident,
43//! brace_token: token::Brace,
44//! fields: Punctuated<Field, Token![,]>,
45//! }
46//! #
47//! # enum ItemEnum {}
48//!
49//! impl Parse for Item {
50//! fn parse(input: ParseStream) -> Result<Self> {
51//! let lookahead = input.lookahead1();
52//! if lookahead.peek(Token![struct]) {
53//! input.parse().map(Item::Struct)
54//! } else if lookahead.peek(Token![enum]) {
55//! input.parse().map(Item::Enum)
56//! } else {
57//! Err(lookahead.error())
58//! }
59//! }
60//! }
61//!
62//! impl Parse for ItemStruct {
63//! fn parse(input: ParseStream) -> Result<Self> {
64//! let content;
65//! Ok(ItemStruct {
66//! struct_token: input.parse()?,
67//! ident: input.parse()?,
68//! brace_token: braced!(content in input),
69//! fields: content.parse_terminated(Field::parse_named)?,
70//! })
71//! }
72//! }
73//! #
74//! # impl Parse for ItemEnum {
75//! # fn parse(input: ParseStream) -> Result<Self> {
76//! # unimplemented!()
77//! # }
78//! # }
79//! ```
80//!
81//! # The `syn::parse*` functions
David Tolnay80a914f2018-08-30 23:49:53 -070082//!
83//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve
84//! as an entry point for parsing syntax tree nodes that can be parsed in an
85//! obvious default way. These functions can return any syntax tree node that
David Tolnay8aacee12018-08-31 09:15:15 -070086//! implements the [`Parse`] trait, which includes most types in Syn.
David Tolnay80a914f2018-08-30 23:49:53 -070087//!
88//! [`syn::parse`]: ../fn.parse.html
89//! [`syn::parse2`]: ../fn.parse2.html
90//! [`syn::parse_str`]: ../fn.parse_str.html
David Tolnay8aacee12018-08-31 09:15:15 -070091//! [`Parse`]: trait.Parse.html
David Tolnay80a914f2018-08-30 23:49:53 -070092//!
93//! ```
94//! use syn::Type;
95//!
David Tolnay8aacee12018-08-31 09:15:15 -070096//! # fn run_parser() -> Result<(), syn::parse::Error> {
David Tolnay80a914f2018-08-30 23:49:53 -070097//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
98//! # Ok(())
99//! # }
100//! #
101//! # fn main() {
102//! # run_parser().unwrap();
103//! # }
104//! ```
105//!
106//! The [`parse_quote!`] macro also uses this approach.
107//!
108//! [`parse_quote!`]: ../macro.parse_quote.html
109//!
David Tolnay43984452018-09-01 17:43:56 -0700110//! # The `Parser` trait
David Tolnay80a914f2018-08-30 23:49:53 -0700111//!
112//! Some types can be parsed in several ways depending on context. For example
113//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like
114//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`]
115//! may or may not allow trailing punctuation, and parsing it the wrong way
116//! would either reject valid input or accept invalid input.
117//!
118//! [`Attribute`]: ../struct.Attribute.html
119//! [`Punctuated`]: ../punctuated/index.html
120//!
David Tolnaye0c51762018-08-31 11:05:22 -0700121//! The `Parse` trait is not implemented in these cases because there is no good
David Tolnay80a914f2018-08-30 23:49:53 -0700122//! behavior to consider the default.
123//!
124//! ```ignore
125//! // Can't parse `Punctuated` without knowing whether trailing punctuation
126//! // should be allowed in this context.
127//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?;
128//! ```
129//!
130//! In these cases the types provide a choice of parser functions rather than a
David Tolnaye0c51762018-08-31 11:05:22 -0700131//! single `Parse` implementation, and those parser functions can be invoked
David Tolnay80a914f2018-08-30 23:49:53 -0700132//! through the [`Parser`] trait.
133//!
134//! [`Parser`]: trait.Parser.html
135//!
136//! ```
David Tolnay80a914f2018-08-30 23:49:53 -0700137//! # extern crate syn;
138//! #
139//! # extern crate proc_macro2;
140//! # use proc_macro2::TokenStream;
141//! #
David Tolnay3e3f7752018-08-31 09:33:59 -0700142//! use syn::parse::Parser;
David Tolnay80a914f2018-08-30 23:49:53 -0700143//! use syn::punctuated::Punctuated;
David Tolnay9b00f652018-09-01 10:31:02 -0700144//! use syn::{Attribute, Expr, PathSegment, Token};
David Tolnay80a914f2018-08-30 23:49:53 -0700145//!
David Tolnay3e3f7752018-08-31 09:33:59 -0700146//! # fn run_parsers() -> Result<(), syn::parse::Error> {
David Tolnay80a914f2018-08-30 23:49:53 -0700147//! # let tokens = TokenStream::new().into();
148//! // Parse a nonempty sequence of path segments separated by `::` punctuation
149//! // with no trailing punctuation.
150//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty;
151//! let path = parser.parse(tokens)?;
152//!
153//! # let tokens = TokenStream::new().into();
154//! // Parse a possibly empty sequence of expressions terminated by commas with
155//! // an optional trailing punctuation.
156//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated;
157//! let args = parser.parse(tokens)?;
158//!
159//! # let tokens = TokenStream::new().into();
160//! // Parse zero or more outer attributes but not inner attributes.
David Tolnay3e3f7752018-08-31 09:33:59 -0700161//! let parser = Attribute::parse_outer;
162//! let attrs = parser.parse(tokens)?;
David Tolnay80a914f2018-08-30 23:49:53 -0700163//! #
164//! # Ok(())
165//! # }
166//! #
167//! # fn main() {}
168//! ```
169//!
David Tolnaye0c51762018-08-31 11:05:22 -0700170//! ---
David Tolnay80a914f2018-08-30 23:49:53 -0700171//!
172//! *This module is available if Syn is built with the `"parsing"` feature.*
David Tolnay18c754c2018-08-21 23:26:58 -0400173
174use std::cell::Cell;
175use std::fmt::Display;
176use std::marker::PhantomData;
177use std::mem;
178use std::ops::Deref;
David Tolnayeafc8052018-08-25 16:33:53 -0400179use std::rc::Rc;
David Tolnay80a914f2018-08-30 23:49:53 -0700180use std::str::FromStr;
David Tolnayeafc8052018-08-25 16:33:53 -0400181
David Tolnay80a914f2018-08-30 23:49:53 -0700182#[cfg(all(
183 not(all(target_arch = "wasm32", target_os = "unknown")),
184 feature = "proc-macro"
185))]
186use proc_macro;
David Tolnayf07b3342018-09-01 11:58:11 -0700187use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};
David Tolnay18c754c2018-08-21 23:26:58 -0400188
David Tolnay80a914f2018-08-30 23:49:53 -0700189use buffer::{Cursor, TokenBuffer};
David Tolnayb6254182018-08-25 08:44:54 -0400190use error;
David Tolnay94f06632018-08-31 10:17:17 -0700191use lookahead;
192use private;
David Tolnay577d0332018-08-25 21:45:24 -0400193use punctuated::Punctuated;
David Tolnay4fb71232018-08-25 23:14:50 -0400194use token::Token;
David Tolnay18c754c2018-08-21 23:26:58 -0400195
David Tolnayb6254182018-08-25 08:44:54 -0400196pub use error::{Error, Result};
197pub use lookahead::{Lookahead1, Peek};
David Tolnay18c754c2018-08-21 23:26:58 -0400198
199/// Parsing interface implemented by all types that can be parsed in a default
200/// way from a token stream.
201pub trait Parse: Sized {
202 fn parse(input: ParseStream) -> Result<Self>;
203}
204
205/// Input to a Syn parser function.
David Tolnaya0daa482018-09-01 02:09:40 -0700206///
207/// See the methods of this type under the documentation of [`ParseBuffer`]. For
208/// an overview of parsing in Syn, refer to the [module documentation].
209///
210/// [module documentation]: index.html
David Tolnay18c754c2018-08-21 23:26:58 -0400211pub type ParseStream<'a> = &'a ParseBuffer<'a>;
212
213/// Cursor position within a buffered token stream.
David Tolnay20d29a12018-09-01 15:15:33 -0700214///
215/// This type is more commonly used through the type alias [`ParseStream`] which
216/// is an alias for `&ParseBuffer`.
217///
218/// `ParseStream` is the input type for all parser functions in Syn. They have
219/// the signature `fn(ParseStream) -> Result<T>`.
David Tolnay18c754c2018-08-21 23:26:58 -0400220pub struct ParseBuffer<'a> {
221 scope: Span,
222 cell: Cell<Cursor<'static>>,
223 marker: PhantomData<Cursor<'a>>,
David Tolnayeafc8052018-08-25 16:33:53 -0400224 unexpected: Rc<Cell<Option<Span>>>,
225}
226
227impl<'a> Drop for ParseBuffer<'a> {
228 fn drop(&mut self) {
229 if !self.is_empty() && self.unexpected.get().is_none() {
230 self.unexpected.set(Some(self.cursor().span()));
231 }
232 }
David Tolnay18c754c2018-08-21 23:26:58 -0400233}
234
David Tolnay642832f2018-09-01 13:08:10 -0700235/// Cursor state associated with speculative parsing.
236///
237/// This type is the input of the closure provided to [`ParseStream::step`].
238///
239/// [`ParseStream::step`]: struct.ParseBuffer.html#method.step
David Tolnay9bd34392018-09-01 13:19:53 -0700240///
241/// # Example
242///
243/// ```
244/// # extern crate proc_macro2;
245/// # extern crate syn;
246/// #
247/// use proc_macro2::TokenTree;
248/// use syn::parse::{ParseStream, Result};
249///
250/// // This function advances the stream past the next occurrence of `@`. If
251/// // no `@` is present in the stream, the stream position is unchanged and
252/// // an error is returned.
253/// fn skip_past_next_at(input: ParseStream) -> Result<()> {
254/// input.step(|cursor| {
255/// let mut rest = *cursor;
256/// while let Some((tt, next)) = cursor.token_tree() {
257/// match tt {
258/// TokenTree::Punct(ref punct) if punct.as_char() == '@' => {
259/// return Ok(((), next));
260/// }
261/// _ => rest = next,
262/// }
263/// }
264/// Err(cursor.error("no `@` was found after this point"))
265/// })
266/// }
267/// #
268/// # fn main() {}
269/// ```
David Tolnay18c754c2018-08-21 23:26:58 -0400270#[derive(Copy, Clone)]
271pub struct StepCursor<'c, 'a> {
272 scope: Span,
273 cursor: Cursor<'c>,
274 marker: PhantomData<fn(Cursor<'c>) -> Cursor<'a>>,
275}
276
277impl<'c, 'a> Deref for StepCursor<'c, 'a> {
278 type Target = Cursor<'c>;
279
280 fn deref(&self) -> &Self::Target {
281 &self.cursor
282 }
283}
284
285impl<'c, 'a> StepCursor<'c, 'a> {
David Tolnay642832f2018-09-01 13:08:10 -0700286 /// Triggers an error at the current position of the parse stream.
287 ///
288 /// The `ParseStream::step` invocation will return this same error without
289 /// advancing the stream state.
David Tolnay18c754c2018-08-21 23:26:58 -0400290 pub fn error<T: Display>(self, message: T) -> Error {
291 error::new_at(self.scope, self.cursor, message)
292 }
293}
294
David Tolnay6ea3fdc2018-09-01 13:30:53 -0700295impl private {
296 pub fn advance_step_cursor<'c, 'a>(proof: StepCursor<'c, 'a>, to: Cursor<'c>) -> Cursor<'a> {
297 let _ = proof;
298 unsafe { mem::transmute::<Cursor<'c>, Cursor<'a>>(to) }
299 }
300}
301
David Tolnay66cb0c42018-08-31 09:01:30 -0700302fn skip(input: ParseStream) -> bool {
David Tolnay4ac232d2018-08-31 10:18:03 -0700303 input
304 .step(|cursor| {
305 if let Some((_lifetime, rest)) = cursor.lifetime() {
306 Ok((true, rest))
307 } else if let Some((_token, rest)) = cursor.token_tree() {
308 Ok((true, rest))
309 } else {
310 Ok((false, *cursor))
311 }
312 }).unwrap()
David Tolnay66cb0c42018-08-31 09:01:30 -0700313}
314
David Tolnay10951d52018-08-31 10:27:39 -0700315impl private {
David Tolnay70f30e92018-09-01 02:04:17 -0700316 pub fn new_parse_buffer(
317 scope: Span,
318 cursor: Cursor,
319 unexpected: Rc<Cell<Option<Span>>>,
320 ) -> ParseBuffer {
David Tolnay94f06632018-08-31 10:17:17 -0700321 let extend = unsafe { mem::transmute::<Cursor, Cursor<'static>>(cursor) };
David Tolnay18c754c2018-08-21 23:26:58 -0400322 ParseBuffer {
323 scope: scope,
324 cell: Cell::new(extend),
325 marker: PhantomData,
David Tolnayeafc8052018-08-25 16:33:53 -0400326 unexpected: unexpected,
David Tolnay18c754c2018-08-21 23:26:58 -0400327 }
328 }
329
David Tolnay94f06632018-08-31 10:17:17 -0700330 pub fn get_unexpected(buffer: &ParseBuffer) -> Rc<Cell<Option<Span>>> {
331 buffer.unexpected.clone()
332 }
333}
334
335impl<'a> ParseBuffer<'a> {
David Tolnay725e1c62018-09-01 12:07:25 -0700336 /// Parses a syntax tree node of type `T`, advancing the position of our
337 /// parse stream past it.
David Tolnay18c754c2018-08-21 23:26:58 -0400338 pub fn parse<T: Parse>(&self) -> Result<T> {
339 T::parse(self)
340 }
341
David Tolnay725e1c62018-09-01 12:07:25 -0700342 /// Calls the given parser function to parse a syntax tree node of type `T`
343 /// from this stream.
David Tolnay21ce84c2018-09-01 15:37:51 -0700344 ///
345 /// # Example
346 ///
347 /// The parser below invokes [`Attribute::parse_outer`] to parse a vector of
348 /// zero or more outer attributes.
349 ///
350 /// [`Attribute::parse_outer`]: ../struct.Attribute.html#method.parse_outer
351 ///
352 /// ```
353 /// # extern crate syn;
354 /// #
355 /// use syn::{Attribute, Ident, Token};
356 /// use syn::parse::{Parse, ParseStream, Result};
357 ///
358 /// // Parses a unit struct with attributes.
359 /// //
360 /// // #[path = "s.tmpl"]
361 /// // struct S;
362 /// struct UnitStruct {
363 /// attrs: Vec<Attribute>,
364 /// struct_token: Token![struct],
365 /// name: Ident,
366 /// semi_token: Token![;],
367 /// }
368 ///
369 /// impl Parse for UnitStruct {
370 /// fn parse(input: ParseStream) -> Result<Self> {
371 /// Ok(UnitStruct {
372 /// attrs: input.call(Attribute::parse_outer)?,
373 /// struct_token: input.parse()?,
374 /// name: input.parse()?,
375 /// semi_token: input.parse()?,
376 /// })
377 /// }
378 /// }
379 /// #
380 /// # fn main() {}
381 /// ```
David Tolnay3a515a02018-08-25 21:08:27 -0400382 pub fn call<T>(&self, function: fn(ParseStream) -> Result<T>) -> Result<T> {
383 function(self)
384 }
385
David Tolnay725e1c62018-09-01 12:07:25 -0700386 /// Looks at the next token in the parse stream to determine whether it
387 /// matches the requested type of token.
388 ///
389 /// Does not advance the position of the parse stream.
David Tolnayddebc3e2018-09-01 16:29:20 -0700390 ///
David Tolnay7d229e82018-09-01 16:42:34 -0700391 /// # Syntax
392 ///
393 /// Note that this method does not use turbofish syntax. Pass the peek type
394 /// inside of parentheses.
395 ///
396 /// - `input.peek(Token![struct])`
397 /// - `input.peek(Token![==])`
398 /// - `input.peek(Ident)`
399 /// - `input.peek(Lifetime)`
400 /// - `input.peek(token::Brace)`
401 ///
David Tolnayddebc3e2018-09-01 16:29:20 -0700402 /// # Example
403 ///
404 /// In this example we finish parsing the list of supertraits when the next
405 /// token in the input is either `where` or an opening curly brace.
406 ///
407 /// ```
408 /// # extern crate syn;
409 /// #
410 /// use syn::{braced, token, Generics, Ident, Token, TypeParamBound};
411 /// use syn::parse::{Parse, ParseStream, Result};
412 /// use syn::punctuated::Punctuated;
413 ///
414 /// // Parses a trait definition containing no associated items.
415 /// //
416 /// // trait Marker<'de, T>: A + B<'de> where Box<T>: Clone {}
417 /// struct MarkerTrait {
418 /// trait_token: Token![trait],
419 /// ident: Ident,
420 /// generics: Generics,
421 /// colon_token: Option<Token![:]>,
422 /// supertraits: Punctuated<TypeParamBound, Token![+]>,
423 /// brace_token: token::Brace,
424 /// }
425 ///
426 /// impl Parse for MarkerTrait {
427 /// fn parse(input: ParseStream) -> Result<Self> {
428 /// let trait_token: Token![trait] = input.parse()?;
429 /// let ident: Ident = input.parse()?;
430 /// let mut generics: Generics = input.parse()?;
431 /// let colon_token: Option<Token![:]> = input.parse()?;
432 ///
433 /// let mut supertraits = Punctuated::new();
434 /// if colon_token.is_some() {
435 /// loop {
436 /// supertraits.push_value(input.parse()?);
437 /// if input.peek(Token![where]) || input.peek(token::Brace) {
438 /// break;
439 /// }
440 /// supertraits.push_punct(input.parse()?);
441 /// }
442 /// }
443 ///
444 /// generics.where_clause = input.parse()?;
445 /// let content;
446 /// let empty_brace_token = braced!(content in input);
447 ///
448 /// Ok(MarkerTrait {
449 /// trait_token: trait_token,
450 /// ident: ident,
451 /// generics: generics,
452 /// colon_token: colon_token,
453 /// supertraits: supertraits,
454 /// brace_token: empty_brace_token,
455 /// })
456 /// }
457 /// }
458 /// #
459 /// # fn main() {}
460 /// ```
David Tolnayb77c8b62018-08-25 16:39:41 -0400461 pub fn peek<T: Peek>(&self, token: T) -> bool {
David Tolnay576779a2018-09-01 11:54:12 -0700462 let _ = token;
463 T::Token::peek(self.cursor())
David Tolnayb77c8b62018-08-25 16:39:41 -0400464 }
465
David Tolnay725e1c62018-09-01 12:07:25 -0700466 /// Looks at the second-next token in the parse stream.
David Tolnaye334b872018-09-01 16:38:10 -0700467 ///
468 /// This is commonly useful as a way to implement contextual keywords.
469 ///
470 /// # Example
471 ///
472 /// This example needs to use `peek2` because the symbol `union` is not a
473 /// keyword in Rust. We can't use just `peek` and decide to parse a union if
474 /// the very next token is `union`, because someone is free to write a `mod
475 /// union` and a macro invocation that looks like `union::some_macro! { ...
476 /// }`. In other words `union` is a contextual keyword.
477 ///
478 /// ```
479 /// # extern crate syn;
480 /// #
481 /// use syn::{Ident, ItemUnion, Macro, Token};
482 /// use syn::parse::{Parse, ParseStream, Result};
483 ///
484 /// // Parses either a union or a macro invocation.
485 /// enum UnionOrMacro {
486 /// // union MaybeUninit<T> { uninit: (), value: T }
487 /// Union(ItemUnion),
488 /// // lazy_static! { ... }
489 /// Macro(Macro),
490 /// }
491 ///
492 /// impl Parse for UnionOrMacro {
493 /// fn parse(input: ParseStream) -> Result<Self> {
494 /// if input.peek(Token![union]) && input.peek2(Ident) {
495 /// input.parse().map(UnionOrMacro::Union)
496 /// } else {
497 /// input.parse().map(UnionOrMacro::Macro)
498 /// }
499 /// }
500 /// }
501 /// #
502 /// # fn main() {}
503 /// ```
David Tolnay4fb71232018-08-25 23:14:50 -0400504 pub fn peek2<T: Peek>(&self, token: T) -> bool {
David Tolnay4fb71232018-08-25 23:14:50 -0400505 let ahead = self.fork();
David Tolnay66cb0c42018-08-31 09:01:30 -0700506 skip(&ahead) && ahead.peek(token)
David Tolnay4fb71232018-08-25 23:14:50 -0400507 }
508
David Tolnay725e1c62018-09-01 12:07:25 -0700509 /// Looks at the third-next token in the parse stream.
David Tolnay4fb71232018-08-25 23:14:50 -0400510 pub fn peek3<T: Peek>(&self, token: T) -> bool {
David Tolnay4fb71232018-08-25 23:14:50 -0400511 let ahead = self.fork();
David Tolnay66cb0c42018-08-31 09:01:30 -0700512 skip(&ahead) && skip(&ahead) && ahead.peek(token)
David Tolnay4fb71232018-08-25 23:14:50 -0400513 }
514
David Tolnay725e1c62018-09-01 12:07:25 -0700515 /// Parses zero or more occurrences of `T` separated by punctuation of type
516 /// `P`, with optional trailing punctuation.
517 ///
518 /// Parsing continues until the end of this parse stream. The entire content
519 /// of this parse stream must consist of `T` and `P`.
David Tolnay0abe65b2018-09-01 14:31:43 -0700520 ///
521 /// # Example
522 ///
523 /// ```rust
524 /// # extern crate quote;
525 /// # extern crate syn;
526 /// #
527 /// # use quote::quote;
528 /// #
529 /// use syn::{parenthesized, token, Ident, Token, Type};
530 /// use syn::parse::{Parse, ParseStream, Result};
531 /// use syn::punctuated::Punctuated;
532 ///
533 /// // Parse a simplified tuple struct syntax like:
534 /// //
535 /// // struct S(A, B);
536 /// struct TupleStruct {
537 /// struct_token: Token![struct],
538 /// ident: Ident,
539 /// paren_token: token::Paren,
540 /// fields: Punctuated<Type, Token![,]>,
541 /// semi_token: Token![;],
542 /// }
543 ///
544 /// impl Parse for TupleStruct {
545 /// fn parse(input: ParseStream) -> Result<Self> {
546 /// let content;
547 /// Ok(TupleStruct {
548 /// struct_token: input.parse()?,
549 /// ident: input.parse()?,
550 /// paren_token: parenthesized!(content in input),
551 /// fields: content.parse_terminated(Type::parse)?,
552 /// semi_token: input.parse()?,
553 /// })
554 /// }
555 /// }
556 /// #
557 /// # fn main() {
558 /// # let input = quote! {
559 /// # struct S(A, B);
560 /// # };
561 /// # syn::parse2::<TupleStruct>(input).unwrap();
562 /// # }
563 /// ```
David Tolnay577d0332018-08-25 21:45:24 -0400564 pub fn parse_terminated<T, P: Parse>(
565 &self,
566 parser: fn(ParseStream) -> Result<T>,
567 ) -> Result<Punctuated<T, P>> {
David Tolnayd0f80212018-08-30 18:32:14 -0700568 Punctuated::parse_terminated_with(self, parser)
David Tolnay577d0332018-08-25 21:45:24 -0400569 }
570
David Tolnay725e1c62018-09-01 12:07:25 -0700571 /// Returns whether there are tokens remaining in this stream.
572 ///
573 /// This method returns true at the end of the content of a set of
574 /// delimiters, as well as at the very end of the complete macro input.
David Tolnaycce6b5f2018-09-01 14:24:46 -0700575 ///
576 /// # Example
577 ///
578 /// ```rust
579 /// # extern crate syn;
580 /// #
581 /// use syn::{braced, token, Ident, Item, Token};
582 /// use syn::parse::{Parse, ParseStream, Result};
583 ///
584 /// // Parses a Rust `mod m { ... }` containing zero or more items.
585 /// struct Mod {
586 /// mod_token: Token![mod],
587 /// name: Ident,
588 /// brace_token: token::Brace,
589 /// items: Vec<Item>,
590 /// }
591 ///
592 /// impl Parse for Mod {
593 /// fn parse(input: ParseStream) -> Result<Self> {
594 /// let content;
595 /// Ok(Mod {
596 /// mod_token: input.parse()?,
597 /// name: input.parse()?,
598 /// brace_token: braced!(content in input),
599 /// items: {
600 /// let mut items = Vec::new();
601 /// while !content.is_empty() {
602 /// items.push(content.parse()?);
603 /// }
604 /// items
605 /// },
606 /// })
607 /// }
608 /// }
609 /// #
610 /// # fn main() {}
David Tolnayf5d30452018-09-01 02:29:04 -0700611 pub fn is_empty(&self) -> bool {
612 self.cursor().eof()
613 }
614
David Tolnay725e1c62018-09-01 12:07:25 -0700615 /// Constructs a helper for peeking at the next token in this stream and
616 /// building an error message if it is not one of a set of expected tokens.
David Tolnay2c77e772018-09-01 14:18:46 -0700617 ///
618 /// # Example
619 ///
620 /// ```
621 /// # extern crate syn;
622 /// #
623 /// use syn::{ConstParam, Ident, Lifetime, LifetimeDef, Token, TypeParam};
624 /// use syn::parse::{Parse, ParseStream, Result};
625 ///
626 /// // A generic parameter, a single one of the comma-separated elements inside
627 /// // angle brackets in:
628 /// //
629 /// // fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
630 /// //
631 /// // On invalid input, lookahead gives us a reasonable error message.
632 /// //
633 /// // error: expected one of: identifier, lifetime, `const`
634 /// // |
635 /// // 5 | fn f<!Sized>() {}
636 /// // | ^
637 /// enum GenericParam {
638 /// Type(TypeParam),
639 /// Lifetime(LifetimeDef),
640 /// Const(ConstParam),
641 /// }
642 ///
643 /// impl Parse for GenericParam {
644 /// fn parse(input: ParseStream) -> Result<Self> {
645 /// let lookahead = input.lookahead1();
646 /// if lookahead.peek(Ident) {
647 /// input.parse().map(GenericParam::Type)
648 /// } else if lookahead.peek(Lifetime) {
649 /// input.parse().map(GenericParam::Lifetime)
650 /// } else if lookahead.peek(Token![const]) {
651 /// input.parse().map(GenericParam::Const)
652 /// } else {
653 /// Err(lookahead.error())
654 /// }
655 /// }
656 /// }
657 /// #
658 /// # fn main() {}
659 /// ```
David Tolnayf5d30452018-09-01 02:29:04 -0700660 pub fn lookahead1(&self) -> Lookahead1<'a> {
661 lookahead::new(self.scope, self.cursor())
662 }
663
David Tolnay725e1c62018-09-01 12:07:25 -0700664 /// Forks a parse stream so that parsing tokens out of either the original
665 /// or the fork does not advance the position of the other.
666 ///
667 /// # Performance
668 ///
669 /// Forking a parse stream is a cheap fixed amount of work and does not
670 /// involve copying token buffers. Where you might hit performance problems
671 /// is if your macro ends up parsing a large amount of content more than
672 /// once.
673 ///
674 /// ```
675 /// # use syn::Expr;
676 /// # use syn::parse::{ParseStream, Result};
677 /// #
678 /// # fn bad(input: ParseStream) -> Result<Expr> {
679 /// // Do not do this.
680 /// if input.fork().parse::<Expr>().is_ok() {
681 /// return input.parse::<Expr>();
682 /// }
683 /// # unimplemented!()
684 /// # }
685 /// ```
686 ///
687 /// As a rule, avoid parsing an unbounded amount of tokens out of a forked
688 /// parse stream. Only use a fork when the amount of work performed against
689 /// the fork is small and bounded.
690 ///
David Tolnayec149b02018-09-01 14:17:28 -0700691 /// For a lower level but occasionally more performant way to perform
David Tolnay725e1c62018-09-01 12:07:25 -0700692 /// speculative parsing, consider using [`ParseStream::step`] instead.
693 ///
694 /// [`ParseStream::step`]: #method.step
David Tolnayec149b02018-09-01 14:17:28 -0700695 ///
696 /// # Example
697 ///
698 /// The parse implementation shown here parses possibly restricted `pub`
699 /// visibilities.
700 ///
701 /// - `pub`
702 /// - `pub(crate)`
703 /// - `pub(self)`
704 /// - `pub(super)`
705 /// - `pub(in some::path)`
706 ///
707 /// To handle the case of visibilities inside of tuple structs, the parser
708 /// needs to distinguish parentheses that specify visibility restrictions
709 /// from parentheses that form part of a tuple type.
710 ///
711 /// ```
712 /// # struct A;
713 /// # struct B;
714 /// # struct C;
715 /// #
716 /// struct S(pub(crate) A, pub (B, C));
717 /// ```
718 ///
719 /// In this example input the first tuple struct element of `S` has
720 /// `pub(crate)` visibility while the second tuple struct element has `pub`
721 /// visibility; the parentheses around `(B, C)` are part of the type rather
722 /// than part of a visibility restriction.
723 ///
724 /// The parser uses a forked parse stream to check the first token inside of
725 /// parentheses after the `pub` keyword. This is a small bounded amount of
726 /// work performed against the forked parse stream.
727 ///
728 /// ```
729 /// # extern crate syn;
730 /// #
731 /// use syn::{parenthesized, token, Ident, Path, Token};
732 /// use syn::ext::IdentExt;
733 /// use syn::parse::{Parse, ParseStream, Result};
734 ///
735 /// struct PubVisibility {
736 /// pub_token: Token![pub],
737 /// restricted: Option<Restricted>,
738 /// }
739 ///
740 /// struct Restricted {
741 /// paren_token: token::Paren,
742 /// in_token: Option<Token![in]>,
743 /// path: Path,
744 /// }
745 ///
746 /// impl Parse for PubVisibility {
747 /// fn parse(input: ParseStream) -> Result<Self> {
748 /// let pub_token: Token![pub] = input.parse()?;
749 ///
750 /// if input.peek(token::Paren) {
751 /// let ahead = input.fork();
752 /// let mut content;
753 /// parenthesized!(content in ahead);
754 ///
755 /// if content.peek(Token![crate])
756 /// || content.peek(Token![self])
757 /// || content.peek(Token![super])
758 /// {
759 /// return Ok(PubVisibility {
760 /// pub_token: pub_token,
761 /// restricted: Some(Restricted {
762 /// paren_token: parenthesized!(content in input),
763 /// in_token: None,
764 /// path: Path::from(content.call(Ident::parse_any)?),
765 /// }),
766 /// });
767 /// } else if content.peek(Token![in]) {
768 /// return Ok(PubVisibility {
769 /// pub_token: pub_token,
770 /// restricted: Some(Restricted {
771 /// paren_token: parenthesized!(content in input),
772 /// in_token: Some(content.parse()?),
773 /// path: content.call(Path::parse_mod_style)?,
774 /// }),
775 /// });
776 /// }
777 /// }
778 ///
779 /// Ok(PubVisibility {
780 /// pub_token: pub_token,
781 /// restricted: None,
782 /// })
783 /// }
784 /// }
785 /// #
786 /// # fn main() {}
787 /// ```
David Tolnayb77c8b62018-08-25 16:39:41 -0400788 pub fn fork(&self) -> Self {
David Tolnay6456a9d2018-08-26 08:11:18 -0400789 ParseBuffer {
790 scope: self.scope,
791 cell: self.cell.clone(),
792 marker: PhantomData,
793 // Not the parent's unexpected. Nothing cares whether the clone
794 // parses all the way.
795 unexpected: Rc::new(Cell::new(None)),
796 }
David Tolnayb77c8b62018-08-25 16:39:41 -0400797 }
798
David Tolnay725e1c62018-09-01 12:07:25 -0700799 /// Triggers an error at the current position of the parse stream.
David Tolnay23fce0b2018-09-01 13:50:31 -0700800 ///
801 /// # Example
802 ///
803 /// ```
804 /// # extern crate syn;
805 /// #
806 /// use syn::{Expr, Token};
807 /// use syn::parse::{Parse, ParseStream, Result};
808 ///
809 /// // Some kind of loop: `while` or `for` or `loop`.
810 /// struct Loop {
811 /// expr: Expr,
812 /// }
813 ///
814 /// impl Parse for Loop {
815 /// fn parse(input: ParseStream) -> Result<Self> {
816 /// if input.peek(Token![while])
817 /// || input.peek(Token![for])
818 /// || input.peek(Token![loop])
819 /// {
820 /// Ok(Loop {
821 /// expr: input.parse()?,
822 /// })
823 /// } else {
824 /// Err(input.error("expected some kind of loop"))
825 /// }
826 /// }
827 /// }
828 /// ```
David Tolnay4fb71232018-08-25 23:14:50 -0400829 pub fn error<T: Display>(&self, message: T) -> Error {
830 error::new_at(self.scope, self.cursor(), message)
831 }
832
David Tolnay725e1c62018-09-01 12:07:25 -0700833 /// Speculatively parses tokens from this parse stream, advancing the
834 /// position of this stream only if parsing succeeds.
David Tolnay9bd34392018-09-01 13:19:53 -0700835 ///
David Tolnayad1d1d22018-09-01 13:34:43 -0700836 /// This is a powerful low-level API used for defining the `Parse` impls of
837 /// the basic built-in token types. It is not something that will be used
838 /// widely outside of the Syn codebase.
839 ///
David Tolnay9bd34392018-09-01 13:19:53 -0700840 /// # Example
841 ///
842 /// ```
843 /// # extern crate proc_macro2;
844 /// # extern crate syn;
845 /// #
846 /// use proc_macro2::TokenTree;
847 /// use syn::parse::{ParseStream, Result};
848 ///
849 /// // This function advances the stream past the next occurrence of `@`. If
850 /// // no `@` is present in the stream, the stream position is unchanged and
851 /// // an error is returned.
852 /// fn skip_past_next_at(input: ParseStream) -> Result<()> {
853 /// input.step(|cursor| {
854 /// let mut rest = *cursor;
855 /// while let Some((tt, next)) = cursor.token_tree() {
856 /// match tt {
857 /// TokenTree::Punct(ref punct) if punct.as_char() == '@' => {
858 /// return Ok(((), next));
859 /// }
860 /// _ => rest = next,
861 /// }
862 /// }
863 /// Err(cursor.error("no `@` was found after this point"))
864 /// })
865 /// }
866 /// #
867 /// # fn main() {}
868 /// ```
David Tolnayb50c65a2018-08-30 21:14:57 -0700869 pub fn step<F, R>(&self, function: F) -> Result<R>
David Tolnay18c754c2018-08-21 23:26:58 -0400870 where
871 F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>,
872 {
David Tolnay6b65f852018-09-01 11:56:25 -0700873 let (node, rest) = function(StepCursor {
David Tolnay18c754c2018-08-21 23:26:58 -0400874 scope: self.scope,
875 cursor: self.cell.get(),
876 marker: PhantomData,
David Tolnay6b65f852018-09-01 11:56:25 -0700877 })?;
878 self.cell.set(rest);
879 Ok(node)
David Tolnay18c754c2018-08-21 23:26:58 -0400880 }
David Tolnayeafc8052018-08-25 16:33:53 -0400881
David Tolnay725e1c62018-09-01 12:07:25 -0700882 /// Provides low-level access to the token representation underlying this
883 /// parse stream.
884 ///
885 /// Cursors are immutable so no operations you perform against the cursor
886 /// will affect the state of this parse stream.
David Tolnayf5d30452018-09-01 02:29:04 -0700887 pub fn cursor(&self) -> Cursor<'a> {
888 self.cell.get()
889 }
890
David Tolnay94f06632018-08-31 10:17:17 -0700891 fn check_unexpected(&self) -> Result<()> {
David Tolnayeafc8052018-08-25 16:33:53 -0400892 match self.unexpected.get() {
893 Some(span) => Err(Error::new(span, "unexpected token")),
894 None => Ok(()),
895 }
896 }
David Tolnay18c754c2018-08-21 23:26:58 -0400897}
898
David Tolnaya7d69fc2018-08-26 13:30:24 -0400899impl<T: Parse> Parse for Box<T> {
900 fn parse(input: ParseStream) -> Result<Self> {
901 input.parse().map(Box::new)
902 }
903}
904
David Tolnay4fb71232018-08-25 23:14:50 -0400905impl<T: Parse + Token> Parse for Option<T> {
David Tolnay18c754c2018-08-21 23:26:58 -0400906 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay00f81fd2018-09-01 10:50:12 -0700907 if T::peek(input.cursor()) {
David Tolnay4fb71232018-08-25 23:14:50 -0400908 Ok(Some(input.parse()?))
909 } else {
910 Ok(None)
David Tolnay18c754c2018-08-21 23:26:58 -0400911 }
David Tolnay18c754c2018-08-21 23:26:58 -0400912 }
913}
David Tolnay4ac232d2018-08-31 10:18:03 -0700914
David Tolnay80a914f2018-08-30 23:49:53 -0700915impl Parse for TokenStream {
916 fn parse(input: ParseStream) -> Result<Self> {
917 input.step(|cursor| Ok((cursor.token_stream(), Cursor::empty())))
918 }
919}
920
921impl Parse for TokenTree {
922 fn parse(input: ParseStream) -> Result<Self> {
923 input.step(|cursor| match cursor.token_tree() {
924 Some((tt, rest)) => Ok((tt, rest)),
925 None => Err(cursor.error("expected token tree")),
926 })
927 }
928}
929
930impl Parse for Group {
931 fn parse(input: ParseStream) -> Result<Self> {
932 input.step(|cursor| {
933 for delim in &[Delimiter::Parenthesis, Delimiter::Brace, Delimiter::Bracket] {
934 if let Some((inside, span, rest)) = cursor.group(*delim) {
935 let mut group = Group::new(*delim, inside.token_stream());
936 group.set_span(span);
937 return Ok((group, rest));
938 }
939 }
940 Err(cursor.error("expected group token"))
941 })
942 }
943}
944
945impl Parse for Punct {
946 fn parse(input: ParseStream) -> Result<Self> {
947 input.step(|cursor| match cursor.punct() {
948 Some((punct, rest)) => Ok((punct, rest)),
949 None => Err(cursor.error("expected punctuation token")),
950 })
951 }
952}
953
954impl Parse for Literal {
955 fn parse(input: ParseStream) -> Result<Self> {
956 input.step(|cursor| match cursor.literal() {
957 Some((literal, rest)) => Ok((literal, rest)),
958 None => Err(cursor.error("expected literal token")),
959 })
960 }
961}
962
963/// Parser that can parse Rust tokens into a particular syntax tree node.
964///
965/// Refer to the [module documentation] for details about parsing in Syn.
966///
967/// [module documentation]: index.html
968///
969/// *This trait is available if Syn is built with the `"parsing"` feature.*
970pub trait Parser: Sized {
971 type Output;
972
973 /// Parse a proc-macro2 token stream into the chosen syntax tree node.
974 fn parse2(self, tokens: TokenStream) -> Result<Self::Output>;
975
976 /// Parse tokens of source code into the chosen syntax tree node.
977 ///
978 /// *This method is available if Syn is built with both the `"parsing"` and
979 /// `"proc-macro"` features.*
980 #[cfg(all(
981 not(all(target_arch = "wasm32", target_os = "unknown")),
982 feature = "proc-macro"
983 ))]
984 fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> {
985 self.parse2(proc_macro2::TokenStream::from(tokens))
986 }
987
988 /// Parse a string of Rust code into the chosen syntax tree node.
989 ///
990 /// # Hygiene
991 ///
992 /// Every span in the resulting syntax tree will be set to resolve at the
993 /// macro call site.
994 fn parse_str(self, s: &str) -> Result<Self::Output> {
995 self.parse2(proc_macro2::TokenStream::from_str(s)?)
996 }
997}
998
David Tolnay7b07aa12018-09-01 11:41:12 -0700999fn tokens_to_parse_buffer(tokens: &TokenBuffer) -> ParseBuffer {
1000 let scope = Span::call_site();
1001 let cursor = tokens.begin();
1002 let unexpected = Rc::new(Cell::new(None));
1003 private::new_parse_buffer(scope, cursor, unexpected)
1004}
1005
David Tolnay80a914f2018-08-30 23:49:53 -07001006impl<F, T> Parser for F
1007where
1008 F: FnOnce(ParseStream) -> Result<T>,
1009{
1010 type Output = T;
1011
1012 fn parse2(self, tokens: TokenStream) -> Result<T> {
1013 let buf = TokenBuffer::new2(tokens);
David Tolnay7b07aa12018-09-01 11:41:12 -07001014 let state = tokens_to_parse_buffer(&buf);
David Tolnay80a914f2018-08-30 23:49:53 -07001015 let node = self(&state)?;
1016 state.check_unexpected()?;
1017 if state.is_empty() {
1018 Ok(node)
1019 } else {
1020 Err(state.error("unexpected token"))
1021 }
1022 }
1023}