1 //! Tokens representing Rust punctuation, keywords, and delimiters.
3 //! The type names in this module can be difficult to keep straight, so we
4 //! prefer to use the [`Token!`] macro instead. This is a type-macro that
5 //! expands to the token type of the given token.
7 //! [`Token!`]: ../macro.Token.html
11 //! The [`ItemStatic`] syntax tree node is defined like this.
13 //! [`ItemStatic`]: ../struct.ItemStatic.html
16 //! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility};
18 //! pub struct ItemStatic {
19 //! pub attrs: Vec<Attribute>,
20 //! pub vis: Visibility,
21 //! pub static_token: Token![static],
22 //! pub mutability: Option<Token![mut]>,
24 //! pub colon_token: Token![:],
25 //! pub ty: Box<Type>,
26 //! pub eq_token: Token![=],
27 //! pub expr: Box<Expr>,
28 //! pub semi_token: Token![;],
34 //! Keywords and punctuation can be parsed through the [`ParseStream::parse`]
35 //! method. Delimiter tokens are parsed using the [`parenthesized!`],
36 //! [`bracketed!`] and [`braced!`] macros.
38 //! [`ParseStream::parse`]: ../parse/struct.ParseBuffer.html#method.parse
39 //! [`parenthesized!`]: ../macro.parenthesized.html
40 //! [`bracketed!`]: ../macro.bracketed.html
41 //! [`braced!`]: ../macro.braced.html
44 //! use syn::{Attribute, Result};
45 //! use syn::parse::{Parse, ParseStream};
47 //! # enum ItemStatic {}
49 //! // Parse the ItemStatic struct shown above.
50 //! impl Parse for ItemStatic {
51 //! fn parse(input: ParseStream) -> Result<Self> {
52 //! # use syn::ItemStatic;
53 //! # fn parse(input: ParseStream) -> Result<ItemStatic> {
55 //! attrs: input.call(Attribute::parse_outer)?,
56 //! vis: input.parse()?,
57 //! static_token: input.parse()?,
58 //! mutability: input.parse()?,
59 //! ident: input.parse()?,
60 //! colon_token: input.parse()?,
61 //! ty: input.parse()?,
62 //! eq_token: input.parse()?,
63 //! expr: input.parse()?,
64 //! semi_token: input.parse()?,
67 //! # unimplemented!()
72 //! # Other operations
74 //! Every keyword and punctuation token supports the following operations.
76 //! - [Peeking] — `input.peek(Token![...])`
78 //! - [Parsing] — `input.parse::<Token![...]>()?`
80 //! - [Printing] — `quote!( ... #the_token ... )`
82 //! - Construction from a [`Span`] — `let the_token = Token![...](sp)`
84 //! - Field access to its span — `let sp = the_token.span`
86 //! [Peeking]: ../parse/struct.ParseBuffer.html#method.peek
87 //! [Parsing]: ../parse/struct.ParseBuffer.html#method.parse
88 //! [Printing]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html
89 //! [`Span`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html
92 #[cfg(feature = "extra-traits")]
94 #[cfg(feature = "extra-traits")]
95 use std
::fmt
::{self, Debug}
;
96 #[cfg(feature = "extra-traits")]
97 use std
::hash
::{Hash, Hasher}
;
98 use std
::ops
::{Deref, DerefMut}
;
100 #[cfg(feature = "parsing")]
101 use proc_macro2
::Delimiter
;
102 #[cfg(any(feature = "parsing", feature = "printing"))]
103 use proc_macro2
::Ident
;
104 use proc_macro2
::Span
;
105 #[cfg(feature = "printing")]
106 use proc_macro2
::TokenStream
;
107 #[cfg(feature = "printing")]
108 use quote
::{ToTokens, TokenStreamExt}
;
110 use self::private
::WithSpan
;
111 #[cfg(feature = "parsing")]
112 use crate::buffer
::Cursor
;
113 #[cfg(feature = "parsing")]
114 use crate::error
::Result
;
115 #[cfg(any(feature = "full", feature = "derive"))]
116 #[cfg(feature = "parsing")]
117 use crate::lifetime
::Lifetime
;
118 #[cfg(any(feature = "full", feature = "derive"))]
119 #[cfg(feature = "parsing")]
120 use crate::lit
::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr}
;
121 #[cfg(feature = "parsing")]
122 use crate::lookahead
;
123 #[cfg(feature = "parsing")]
124 use crate::parse
::{Parse, ParseStream}
;
125 use crate::span
::IntoSpans
;
127 /// Marker trait for types that represent single tokens.
129 /// This trait is sealed and cannot be implemented for types outside of Syn.
130 #[cfg(feature = "parsing")]
131 pub trait Token
: private
::Sealed
{
134 fn peek(cursor
: Cursor
) -> bool
;
138 fn display() -> &'
static str;
142 use proc_macro2
::Span
;
144 #[cfg(feature = "parsing")]
147 /// Support writing `token.span` rather than `token.spans[0]` on tokens that
148 /// hold a single span.
150 pub struct WithSpan
{
155 #[cfg(feature = "parsing")]
156 impl private
::Sealed
for Ident {}
158 #[cfg(any(feature = "full", feature = "derive"))]
159 #[cfg(feature = "parsing")]
160 fn peek_impl(cursor
: Cursor
, peek
: fn(ParseStream
) -> bool
) -> bool
{
161 use crate::parse
::Unexpected
;
165 let scope
= Span
::call_site();
166 let unexpected
= Rc
::new(Cell
::new(Unexpected
::None
));
167 let buffer
= crate::parse
::new_parse_buffer(scope
, cursor
, unexpected
);
171 #[cfg(any(feature = "full", feature = "derive"))]
172 macro_rules
! impl_token
{
173 ($name
:ident $display
:expr
) => {
174 #[cfg(feature = "parsing")]
175 impl Token
for $name
{
176 fn peek(cursor
: Cursor
) -> bool
{
177 fn peek(input
: ParseStream
) -> bool
{
178 <$name
as Parse
>::parse(input
).is_ok()
180 peek_impl(cursor
, peek
)
183 fn display() -> &'
static str {
188 #[cfg(feature = "parsing")]
189 impl private
::Sealed
for $name {}
193 #[cfg(any(feature = "full", feature = "derive"))]
194 impl_token
!(Lifetime
"lifetime");
195 #[cfg(any(feature = "full", feature = "derive"))]
196 impl_token
!(Lit
"literal");
197 #[cfg(any(feature = "full", feature = "derive"))]
198 impl_token
!(LitStr
"string literal");
199 #[cfg(any(feature = "full", feature = "derive"))]
200 impl_token
!(LitByteStr
"byte string literal");
201 #[cfg(any(feature = "full", feature = "derive"))]
202 impl_token
!(LitByte
"byte literal");
203 #[cfg(any(feature = "full", feature = "derive"))]
204 impl_token
!(LitChar
"character literal");
205 #[cfg(any(feature = "full", feature = "derive"))]
206 impl_token
!(LitInt
"integer literal");
207 #[cfg(any(feature = "full", feature = "derive"))]
208 impl_token
!(LitFloat
"floating point literal");
209 #[cfg(any(feature = "full", feature = "derive"))]
210 impl_token
!(LitBool
"boolean literal");
214 #[cfg(feature = "parsing")]
215 pub trait CustomToken
{
216 fn peek(cursor
: Cursor
) -> bool
;
217 fn display() -> &'
static str;
220 #[cfg(feature = "parsing")]
221 impl<T
: CustomToken
> private
::Sealed
for T {}
223 #[cfg(feature = "parsing")]
224 impl<T
: CustomToken
> Token
for T
{
225 fn peek(cursor
: Cursor
) -> bool
{
226 <Self as CustomToken
>::peek(cursor
)
229 fn display() -> &'
static str {
230 <Self as CustomToken
>::display()
234 macro_rules
! define_keywords
{
235 ($
($token
:tt
pub struct $name
:ident
#[$doc:meta])*) => {
237 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
240 /// Don't try to remember the name of this type — use the
241 /// [`Token!`] macro instead.
243 /// [`Token!`]: crate::token
249 #[allow(non_snake_case)]
250 pub fn $name
<S
: IntoSpans
<[Span
; 1]>>(span
: S
) -> $name
{
252 span
: span
.into_spans()[0],
256 impl std
::default::Default
for $name
{
257 fn default() -> Self {
259 span
: Span
::call_site(),
264 #[cfg(feature = "extra-traits")]
265 impl Debug
for $name
{
266 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
267 f
.write_str(stringify
!($name
))
271 #[cfg(feature = "extra-traits")]
272 impl cmp
::Eq
for $name {}
274 #[cfg(feature = "extra-traits")]
275 impl PartialEq
for $name
{
276 fn eq(&self, _other
: &$name
) -> bool
{
281 #[cfg(feature = "extra-traits")]
282 impl Hash
for $name
{
283 fn hash
<H
: Hasher
>(&self, _state
: &mut H
) {}
286 #[cfg(feature = "printing")]
287 impl ToTokens
for $name
{
288 fn to_tokens(&self, tokens
: &mut TokenStream
) {
289 printing
::keyword($token
, self.span
, tokens
);
293 #[cfg(feature = "parsing")]
294 impl Parse
for $name
{
295 fn parse(input
: ParseStream
) -> Result
<Self> {
297 span
: parsing
::keyword(input
, $token
)?
,
302 #[cfg(feature = "parsing")]
303 impl Token
for $name
{
304 fn peek(cursor
: Cursor
) -> bool
{
305 parsing
::peek_keyword(cursor
, $token
)
308 fn display() -> &'
static str {
309 concat
!("`", $token
, "`")
313 #[cfg(feature = "parsing")]
314 impl private
::Sealed
for $name {}
319 macro_rules
! impl_deref_if_len_is_1
{
321 impl Deref
for $name
{
322 type Target
= WithSpan
;
324 fn deref(&self) -> &Self::Target
{
325 unsafe { &*(self as *const Self as *const WithSpan) }
329 impl DerefMut
for $name
{
330 fn deref_mut(&mut self) -> &mut Self::Target
{
331 unsafe { &mut *(self as *mut Self as *mut WithSpan) }
336 ($name
:ident
/$len
:tt
) => {}
;
339 macro_rules
! define_punctuation_structs
{
340 ($
($token
:tt
pub struct $name
:ident
/$len
:tt
#[$doc:meta])*) => {
342 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
346 /// Don't try to remember the name of this type — use the
347 /// [`Token!`] macro instead.
349 /// [`Token!`]: crate::token
351 pub spans
: [Span
; $len
],
355 #[allow(non_snake_case)]
356 pub fn $name
<S
: IntoSpans
<[Span
; $len
]>>(spans
: S
) -> $name
{
358 spans
: spans
.into_spans(),
362 impl std
::default::Default
for $name
{
363 fn default() -> Self {
365 spans
: [Span
::call_site(); $len
],
370 #[cfg(feature = "extra-traits")]
371 impl Debug
for $name
{
372 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
373 f
.write_str(stringify
!($name
))
377 #[cfg(feature = "extra-traits")]
378 impl cmp
::Eq
for $name {}
380 #[cfg(feature = "extra-traits")]
381 impl PartialEq
for $name
{
382 fn eq(&self, _other
: &$name
) -> bool
{
387 #[cfg(feature = "extra-traits")]
388 impl Hash
for $name
{
389 fn hash
<H
: Hasher
>(&self, _state
: &mut H
) {}
392 impl_deref_if_len_is_1
!($name
/$len
);
397 macro_rules
! define_punctuation
{
398 ($
($token
:tt
pub struct $name
:ident
/$len
:tt
#[$doc:meta])*) => {
400 define_punctuation_structs
! {
401 $token
pub struct $name
/$len
#[$doc]
404 #[cfg(feature = "printing")]
405 impl ToTokens
for $name
{
406 fn to_tokens(&self, tokens
: &mut TokenStream
) {
407 printing
::punct($token
, &self.spans
, tokens
);
411 #[cfg(feature = "parsing")]
412 impl Parse
for $name
{
413 fn parse(input
: ParseStream
) -> Result
<Self> {
415 spans
: parsing
::punct(input
, $token
)?
,
420 #[cfg(feature = "parsing")]
421 impl Token
for $name
{
422 fn peek(cursor
: Cursor
) -> bool
{
423 parsing
::peek_punct(cursor
, $token
)
426 fn display() -> &'
static str {
427 concat
!("`", $token
, "`")
431 #[cfg(feature = "parsing")]
432 impl private
::Sealed
for $name {}
437 macro_rules
! define_delimiters
{
438 ($
($token
:tt
pub struct $name
:ident
#[$doc:meta])*) => {
440 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
447 #[allow(non_snake_case)]
448 pub fn $name
<S
: IntoSpans
<[Span
; 1]>>(span
: S
) -> $name
{
450 span
: span
.into_spans()[0],
454 impl std
::default::Default
for $name
{
455 fn default() -> Self {
457 span
: Span
::call_site(),
462 #[cfg(feature = "extra-traits")]
463 impl Debug
for $name
{
464 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
465 f
.write_str(stringify
!($name
))
469 #[cfg(feature = "extra-traits")]
470 impl cmp
::Eq
for $name {}
472 #[cfg(feature = "extra-traits")]
473 impl PartialEq
for $name
{
474 fn eq(&self, _other
: &$name
) -> bool
{
479 #[cfg(feature = "extra-traits")]
480 impl Hash
for $name
{
481 fn hash
<H
: Hasher
>(&self, _state
: &mut H
) {}
485 #[cfg(feature = "printing")]
486 pub fn surround
<F
>(&self, tokens
: &mut TokenStream
, f
: F
)
488 F
: FnOnce(&mut TokenStream
),
490 printing
::delim($token
, self.span
, tokens
, f
);
494 #[cfg(feature = "parsing")]
495 impl private
::Sealed
for $name {}
500 define_punctuation_structs
! {
501 "_" pub struct Underscore
/1 /// `_`
504 #[cfg(feature = "printing")]
505 impl ToTokens
for Underscore
{
506 fn to_tokens(&self, tokens
: &mut TokenStream
) {
507 tokens
.append(Ident
::new("_", self.span
));
511 #[cfg(feature = "parsing")]
512 impl Parse
for Underscore
{
513 fn parse(input
: ParseStream
) -> Result
<Self> {
514 input
.step(|cursor
| {
515 if let Some((ident
, rest
)) = cursor
.ident() {
517 return Ok((Underscore(ident
.span()), rest
));
520 if let Some((punct
, rest
)) = cursor
.punct() {
521 if punct
.as_char() == '_'
{
522 return Ok((Underscore(punct
.span()), rest
));
525 Err(cursor
.error("expected `_`"))
530 #[cfg(feature = "parsing")]
531 impl Token
for Underscore
{
532 fn peek(cursor
: Cursor
) -> bool
{
533 if let Some((ident
, _rest
)) = cursor
.ident() {
536 if let Some((punct
, _rest
)) = cursor
.punct() {
537 return punct
.as_char() == '_'
;
542 fn display() -> &'
static str {
547 #[cfg(feature = "parsing")]
548 impl private
::Sealed
for Underscore {}
550 #[cfg(feature = "parsing")]
551 impl Token
for Paren
{
552 fn peek(cursor
: Cursor
) -> bool
{
553 lookahead
::is_delimiter(cursor
, Delimiter
::Parenthesis
)
556 fn display() -> &'
static str {
561 #[cfg(feature = "parsing")]
562 impl Token
for Brace
{
563 fn peek(cursor
: Cursor
) -> bool
{
564 lookahead
::is_delimiter(cursor
, Delimiter
::Brace
)
567 fn display() -> &'
static str {
572 #[cfg(feature = "parsing")]
573 impl Token
for Bracket
{
574 fn peek(cursor
: Cursor
) -> bool
{
575 lookahead
::is_delimiter(cursor
, Delimiter
::Bracket
)
578 fn display() -> &'
static str {
583 #[cfg(feature = "parsing")]
584 impl Token
for Group
{
585 fn peek(cursor
: Cursor
) -> bool
{
586 lookahead
::is_delimiter(cursor
, Delimiter
::None
)
589 fn display() -> &'
static str {
595 "abstract" pub struct Abstract
/// `abstract`
596 "as" pub struct As
/// `as`
597 "async" pub struct Async
/// `async`
598 "auto" pub struct Auto
/// `auto`
599 "await" pub struct Await
/// `await`
600 "become" pub struct Become
/// `become`
601 "box" pub struct Box
/// `box`
602 "break" pub struct Break
/// `break`
603 "const" pub struct Const
/// `const`
604 "continue" pub struct Continue
/// `continue`
605 "crate" pub struct Crate
/// `crate`
606 "default" pub struct Default
/// `default`
607 "do" pub struct Do
/// `do`
608 "dyn" pub struct Dyn
/// `dyn`
609 "else" pub struct Else
/// `else`
610 "enum" pub struct Enum
/// `enum`
611 "extern" pub struct Extern
/// `extern`
612 "final" pub struct Final
/// `final`
613 "fn" pub struct Fn
/// `fn`
614 "for" pub struct For
/// `for`
615 "if" pub struct If
/// `if`
616 "impl" pub struct Impl
/// `impl`
617 "in" pub struct In
/// `in`
618 "let" pub struct Let
/// `let`
619 "loop" pub struct Loop
/// `loop`
620 "macro" pub struct Macro
/// `macro`
621 "match" pub struct Match
/// `match`
622 "mod" pub struct Mod
/// `mod`
623 "move" pub struct Move
/// `move`
624 "mut" pub struct Mut
/// `mut`
625 "override" pub struct Override
/// `override`
626 "priv" pub struct Priv
/// `priv`
627 "pub" pub struct Pub
/// `pub`
628 "ref" pub struct Ref
/// `ref`
629 "return" pub struct Return
/// `return`
630 "Self" pub struct SelfType
/// `Self`
631 "self" pub struct SelfValue
/// `self`
632 "static" pub struct Static
/// `static`
633 "struct" pub struct Struct
/// `struct`
634 "super" pub struct Super
/// `super`
635 "trait" pub struct Trait
/// `trait`
636 "try" pub struct Try
/// `try`
637 "type" pub struct Type
/// `type`
638 "typeof" pub struct Typeof
/// `typeof`
639 "union" pub struct Union
/// `union`
640 "unsafe" pub struct Unsafe
/// `unsafe`
641 "unsized" pub struct Unsized
/// `unsized`
642 "use" pub struct Use
/// `use`
643 "virtual" pub struct Virtual
/// `virtual`
644 "where" pub struct Where
/// `where`
645 "while" pub struct While
/// `while`
646 "yield" pub struct Yield
/// `yield`
649 define_punctuation
! {
650 "+" pub struct Add
/1 /// `+`
651 "+=" pub struct AddEq
/2 /// `+=`
652 "&" pub struct And
/1 /// `&`
653 "&&" pub struct AndAnd
/2 /// `&&`
654 "&=" pub struct AndEq
/2 /// `&=`
655 "@" pub struct At
/1 /// `@`
656 "!" pub struct Bang
/1 /// `!`
657 "^" pub struct Caret
/1 /// `^`
658 "^=" pub struct CaretEq
/2 /// `^=`
659 ":" pub struct Colon
/1 /// `:`
660 "::" pub struct Colon2
/2 /// `::`
661 "," pub struct Comma
/1 /// `,`
662 "/" pub struct Div
/1 /// `/`
663 "/=" pub struct DivEq
/2 /// `/=`
664 "$" pub struct Dollar
/1 /// `$`
665 "." pub struct Dot
/1 /// `.`
666 ".." pub struct Dot2
/2 /// `..`
667 "..." pub struct Dot3
/3 /// `...`
668 "..=" pub struct DotDotEq
/3 /// `..=`
669 "=" pub struct Eq
/1 /// `=`
670 "==" pub struct EqEq
/2 /// `==`
671 ">=" pub struct Ge
/2 /// `>=`
672 ">" pub struct Gt
/1 /// `>`
673 "<=" pub struct Le
/2 /// `<=`
674 "<" pub struct Lt
/1 /// `<`
675 "*=" pub struct MulEq
/2 /// `*=`
676 "!=" pub struct Ne
/2 /// `!=`
677 "|" pub struct Or
/1 /// `|`
678 "|=" pub struct OrEq
/2 /// `|=`
679 "||" pub struct OrOr
/2 /// `||`
680 "#" pub struct Pound
/1 /// `#`
681 "?" pub struct Question
/1 /// `?`
682 "->" pub struct RArrow
/2 /// `->`
683 "<-" pub struct LArrow
/2 /// `<-`
684 "%" pub struct Rem
/1 /// `%`
685 "%=" pub struct RemEq
/2 /// `%=`
686 "=>" pub struct FatArrow
/2 /// `=>`
687 ";" pub struct Semi
/1 /// `;`
688 "<<" pub struct Shl
/2 /// `<<`
689 "<<=" pub struct ShlEq
/3 /// `<<=`
690 ">>" pub struct Shr
/2 /// `>>`
691 ">>=" pub struct ShrEq
/3 /// `>>=`
692 "*" pub struct Star
/1 /// `*`
693 "-" pub struct Sub
/1 /// `-`
694 "-=" pub struct SubEq
/2 /// `-=`
695 "~" pub struct Tilde
/1 /// `~`
699 "{" pub struct Brace /// `{...}`
700 "[" pub struct Bracket /// `[...]`
701 "(" pub struct Paren /// `(...)`
702 " " pub struct Group /// None-delimited group
705 macro_rules! export_token_macro {
706 ($($await_rule:tt)*) => {
707 /// A type-macro that expands to the name of the Rust type representation of a
710 /// See the [token module] documentation for details and examples.
712 /// [token module]: crate::token
713 // Unfortunate duplication due to a rustdoc bug.
714 // https://github.com/rust-lang/rust/issues/45939
717 (abstract) => { $crate::token::Abstract };
718 (as) => { $crate::token::As };
719 (async) => { $crate::token::Async };
720 (auto) => { $crate::token::Auto };
721 $($await_rule => { $crate::token::Await };)*
722 (become) => { $crate::token::Become };
723 (box) => { $crate::token::Box };
724 (break) => { $crate::token::Break };
725 (const) => { $crate::token::Const };
726 (continue) => { $crate::token::Continue };
727 (crate) => { $crate::token::Crate };
728 (default) => { $crate::token::Default };
729 (do) => { $crate::token::Do };
730 (dyn) => { $crate::token::Dyn };
731 (else) => { $crate::token::Else };
732 (enum) => { $crate::token::Enum };
733 (extern) => { $crate::token::Extern };
734 (final) => { $crate::token::Final };
735 (fn) => { $crate::token::Fn };
736 (for) => { $crate::token::For };
737 (if) => { $crate::token::If };
738 (impl) => { $crate::token::Impl };
739 (in) => { $crate::token::In };
740 (let) => { $crate::token::Let };
741 (loop) => { $crate::token::Loop };
742 (macro) => { $crate::token::Macro };
743 (match) => { $crate::token::Match };
744 (mod) => { $crate::token::Mod };
745 (move) => { $crate::token::Move };
746 (mut) => { $crate::token::Mut };
747 (override) => { $crate::token::Override };
748 (priv) => { $crate::token::Priv };
749 (pub) => { $crate::token::Pub };
750 (ref) => { $crate::token::Ref };
751 (return) => { $crate::token::Return };
752 (Self) => { $crate::token::SelfType };
753 (self) => { $crate::token::SelfValue };
754 (static) => { $crate::token::Static };
755 (struct) => { $crate::token::Struct };
756 (super) => { $crate::token::Super };
757 (trait) => { $crate::token::Trait };
758 (try) => { $crate::token::Try };
759 (type) => { $crate::token::Type };
760 (typeof) => { $crate::token::Typeof };
761 (union) => { $crate::token::Union };
762 (unsafe) => { $crate::token::Unsafe };
763 (unsized) => { $crate::token::Unsized };
764 (use) => { $crate::token::Use };
765 (virtual) => { $crate::token::Virtual };
766 (where) => { $crate::token::Where };
767 (while) => { $crate::token::While };
768 (yield) => { $crate::token::Yield };
769 (+) => { $crate::token::Add };
770 (+=) => { $crate::token::AddEq };
771 (&) => { $crate::token::And };
772 (&&) => { $crate::token::AndAnd };
773 (&=) => { $crate::token::AndEq };
774 (@) => { $crate::token::At };
775 (!) => { $crate::token::Bang };
776 (^) => { $crate::token::Caret };
777 (^=) => { $crate::token::CaretEq };
778 (:) => { $crate::token::Colon };
779 (::) => { $crate::token::Colon2 };
780 (,) => { $crate::token::Comma };
781 (/) => { $crate::token::Div };
782 (/=) => { $crate::token::DivEq };
783 ($) => { $crate::token::Dollar };
784 (.) => { $crate::token::Dot };
785 (..) => { $crate::token::Dot2 };
786 (...) => { $crate::token::Dot3 };
787 (..=) => { $crate::token::DotDotEq };
788 (=) => { $crate::token::Eq };
789 (==) => { $crate::token::EqEq };
790 (>=) => { $crate::token::Ge };
791 (>) => { $crate::token::Gt };
792 (<=) => { $crate::token::Le };
793 (<) => { $crate::token::Lt };
794 (*=) => { $crate::token::MulEq };
795 (!=) => { $crate::token::Ne };
796 (|) => { $crate::token::Or };
797 (|=) => { $crate::token::OrEq };
798 (||) => { $crate::token::OrOr };
799 (#) => { $crate::token::Pound };
800 (?) => { $crate::token::Question };
801 (->) => { $crate::token::RArrow };
802 (<-) => { $crate::token::LArrow };
803 (%) => { $crate::token::Rem };
804 (%=) => { $crate::token::RemEq };
805 (=>) => { $crate::token::FatArrow };
806 (;) => { $crate::token::Semi };
807 (<<) => { $crate::token::Shl };
808 (<<=) => { $crate::token::ShlEq };
809 (>>) => { $crate::token::Shr };
810 (>>=) => { $crate::token::ShrEq };
811 (*) => { $crate::token::Star };
812 (-) => { $crate::token::Sub };
813 (-=) => { $crate::token::SubEq };
814 (~) => { $crate::token::Tilde };
815 (_) => { $crate::token::Underscore };
820 // Old rustc does not permit `await` appearing anywhere in the source file.
821 // https://github.com/rust-lang/rust/issues/57919
822 // We put the Token![await] rule in a place that is not lexed by old rustc.
823 #[cfg(not(syn_omit_await_from_token_macro))]
824 include!("await
.rs
"); // export_token_macro![(await)];
825 #[cfg(syn_omit_await_from_token_macro)]
826 export_token_macro![];
830 #[cfg(feature = "parsing
")]
832 use proc_macro2::{Spacing, Span};
834 use crate::buffer::Cursor;
835 use crate::error::{Error, Result};
836 use crate::parse::ParseStream;
837 use crate::span::FromSpans;
839 pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
840 input.step(|cursor| {
841 if let Some((ident, rest)) = cursor.ident() {
843 return Ok((ident.span(), rest));
846 Err(cursor.error(format!("expected `{}`
", token)))
850 pub fn peek_keyword(cursor: Cursor, token: &str) -> bool {
851 if let Some((ident, _rest)) = cursor.ident() {
858 pub fn punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S> {
859 let mut spans = [input.cursor().span(); 3];
860 punct_helper(input, token, &mut spans)?;
861 Ok(S::from_spans(&spans))
864 fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()> {
865 input.step(|cursor| {
866 let mut cursor = *cursor;
867 assert!(token.len() <= spans.len());
869 for (i, ch) in token.chars().enumerate() {
870 match cursor.punct() {
871 Some((punct, rest)) => {
872 spans[i] = punct.span();
873 if punct.as_char() != ch {
875 } else if i == token.len() - 1 {
876 return Ok(((), rest));
877 } else if punct.spacing() != Spacing::Joint {
886 Err(Error::new(spans[0], format!("expected `{}`
", token)))
890 pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
891 for (i, ch) in token.chars().enumerate() {
892 match cursor.punct() {
893 Some((punct, rest)) => {
894 if punct.as_char() != ch {
896 } else if i == token.len() - 1 {
898 } else if punct.spacing() != Spacing::Joint {
912 #[cfg(feature = "printing
")]
914 use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
915 use quote::TokenStreamExt;
917 pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
918 assert_eq!(s.len(), spans.len());
920 let mut chars = s.chars();
921 let mut spans = spans.iter();
922 let ch = chars.next_back().unwrap();
923 let span = spans.next_back().unwrap();
924 for (ch, span) in chars.zip(spans) {
925 let mut op = Punct::new(ch, Spacing::Joint);
930 let mut op = Punct::new(ch, Spacing::Alone);
935 pub fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
936 tokens.append(Ident::new(s, span));
939 pub fn delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F)
941 F: FnOnce(&mut TokenStream),
943 let delim = match s {
944 "(" => Delimiter::Parenthesis,
945 "[" => Delimiter::Bracket,
946 "{" => Delimiter::Brace,
947 " " => Delimiter::None,
948 _ => panic!("unknown delimiter
: {}
", s),
950 let mut inner = TokenStream::new();
952 let mut g = Group::new(delim, inner);