1//! Tokens representing Rust punctuation, keywords, and delimiters.
2//!
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.
6//!
7//! [`Token!`]: crate::Token
8//!
9//! # Example
10//!
11//! The [`ItemStatic`] syntax tree node is defined like this.
12//!
13//! [`ItemStatic`]: crate::ItemStatic
14//!
15//! ```
16//! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility};
17//! #
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]>,
23//! pub ident: Ident,
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![;],
29//! }
30//! ```
31//!
32//! # Parsing
33//!
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.
37//!
38//! [`ParseStream::parse`]: crate::parse::ParseBuffer::parse()
39//! [`parenthesized!`]: crate::parenthesized!
40//! [`bracketed!`]: crate::bracketed!
41//! [`braced!`]: crate::braced!
42//!
43//! ```
44//! use syn::{Attribute, Result};
45//! use syn::parse::{Parse, ParseStream};
46//! #
47//! # enum ItemStatic {}
48//!
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> {
54//! Ok(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()?,
65//! })
66//! # }
67//! # unimplemented!()
68//! }
69//! }
70//! ```
71//!
72//! # Other operations
73//!
74//! Every keyword and punctuation token supports the following operations.
75//!
76//! - [Peeking] — `input.peek(Token![...])`
77//!
78//! - [Parsing] — `input.parse::<Token![...]>()?`
79//!
80//! - [Printing] — `quote!( ... #the_token ... )`
81//!
82//! - Construction from a [`Span`] — `let the_token = Token![...](sp)`
83//!
84//! - Field access to its span — `let sp = the_token.span`
85//!
86//! [Peeking]: crate::parse::ParseBuffer::peek()
87//! [Parsing]: crate::parse::ParseBuffer::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
90
91use self::private::WithSpan;
92#[cfg(feature = "parsing")]
93use crate::buffer::Cursor;
94#[cfg(feature = "parsing")]
95use crate::error::Result;
96#[cfg(feature = "parsing")]
97use crate::lifetime::Lifetime;
98#[cfg(feature = "parsing")]
99use crate::lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
100#[cfg(feature = "parsing")]
101use crate::lookahead;
102#[cfg(feature = "parsing")]
103use crate::parse::{Parse, ParseStream};
104use crate::span::IntoSpans;
105use proc_macro2::extra::DelimSpan;
106use proc_macro2::Span;
107#[cfg(feature = "printing")]
108use proc_macro2::TokenStream;
109#[cfg(any(feature = "parsing", feature = "printing"))]
110use proc_macro2::{Delimiter, Ident};
111#[cfg(feature = "parsing")]
112use proc_macro2::{Literal, Punct, TokenTree};
113#[cfg(feature = "printing")]
114use quote::{ToTokens, TokenStreamExt};
115#[cfg(feature = "extra-traits")]
116use std::cmp;
117#[cfg(feature = "extra-traits")]
118use std::fmt::{self, Debug};
119#[cfg(feature = "extra-traits")]
120use std::hash::{Hash, Hasher};
121use std::ops::{Deref, DerefMut};
122
123/// Marker trait for types that represent single tokens.
124///
125/// This trait is sealed and cannot be implemented for types outside of Syn.
126#[cfg(feature = "parsing")]
127pub trait Token: private::Sealed {
128 // Not public API.
129 #[doc(hidden)]
130 fn peek(cursor: Cursor) -> bool;
131
132 // Not public API.
133 #[doc(hidden)]
134 fn display() -> &'static str;
135}
136
137mod private {
138 use proc_macro2::Span;
139
140 #[cfg(feature = "parsing")]
141 pub trait Sealed {}
142
143 /// Support writing `token.span` rather than `token.spans[0]` on tokens that
144 /// hold a single span.
145 #[repr(transparent)]
146 pub struct WithSpan {
147 pub span: Span,
148 }
149}
150
151#[cfg(feature = "parsing")]
152impl private::Sealed for Ident {}
153
154#[cfg(feature = "parsing")]
155fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
156 use crate::parse::Unexpected;
157 use std::cell::Cell;
158 use std::rc::Rc;
159
160 let scope: Span = Span::call_site();
161 let unexpected: Rc> = Rc::new(Cell::new(Unexpected::None));
162 let buffer: ParseBuffer<'_> = crate::parse::new_parse_buffer(scope, cursor, unexpected);
163 peek(&buffer)
164}
165
166macro_rules! impl_token {
167 ($display:literal $name:ty) => {
168 #[cfg(feature = "parsing")]
169 impl Token for $name {
170 fn peek(cursor: Cursor) -> bool {
171 fn peek(input: ParseStream) -> bool {
172 <$name as Parse>::parse(input).is_ok()
173 }
174 peek_impl(cursor, peek)
175 }
176
177 fn display() -> &'static str {
178 $display
179 }
180 }
181
182 #[cfg(feature = "parsing")]
183 impl private::Sealed for $name {}
184 };
185}
186
187impl_token!("lifetime" Lifetime);
188impl_token!("literal" Lit);
189impl_token!("string literal" LitStr);
190impl_token!("byte string literal" LitByteStr);
191impl_token!("byte literal" LitByte);
192impl_token!("character literal" LitChar);
193impl_token!("integer literal" LitInt);
194impl_token!("floating point literal" LitFloat);
195impl_token!("boolean literal" LitBool);
196impl_token!("group token" proc_macro2::Group);
197
198macro_rules! impl_low_level_token {
199 ($display:literal $ty:ident $get:ident) => {
200 #[cfg(feature = "parsing")]
201 impl Token for $ty {
202 fn peek(cursor: Cursor) -> bool {
203 cursor.$get().is_some()
204 }
205
206 fn display() -> &'static str {
207 $display
208 }
209 }
210
211 #[cfg(feature = "parsing")]
212 impl private::Sealed for $ty {}
213 };
214}
215
216impl_low_level_token!("punctuation token" Punct punct);
217impl_low_level_token!("literal" Literal literal);
218impl_low_level_token!("token" TokenTree token_tree);
219
220// Not public API.
221#[doc(hidden)]
222#[cfg(feature = "parsing")]
223pub trait CustomToken {
224 fn peek(cursor: Cursor) -> bool;
225 fn display() -> &'static str;
226}
227
228#[cfg(feature = "parsing")]
229impl<T: CustomToken> private::Sealed for T {}
230
231#[cfg(feature = "parsing")]
232impl<T: CustomToken> Token for T {
233 fn peek(cursor: Cursor) -> bool {
234 <Self as CustomToken>::peek(cursor)
235 }
236
237 fn display() -> &'static str {
238 <Self as CustomToken>::display()
239 }
240}
241
242macro_rules! define_keywords {
243 ($($token:literal pub struct $name:ident)*) => {
244 $(
245 #[doc = concat!('`', $token, '`')]
246 ///
247 /// Don't try to remember the name of this type &mdash; use the
248 /// [`Token!`] macro instead.
249 ///
250 /// [`Token!`]: crate::token
251 pub struct $name {
252 pub span: Span,
253 }
254
255 #[doc(hidden)]
256 #[allow(non_snake_case)]
257 pub fn $name<S: IntoSpans<Span>>(span: S) -> $name {
258 $name {
259 span: span.into_spans(),
260 }
261 }
262
263 impl std::default::Default for $name {
264 fn default() -> Self {
265 $name {
266 span: Span::call_site(),
267 }
268 }
269 }
270
271 #[cfg(feature = "clone-impls")]
272 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
273 impl Copy for $name {}
274
275 #[cfg(feature = "clone-impls")]
276 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
277 impl Clone for $name {
278 fn clone(&self) -> Self {
279 *self
280 }
281 }
282
283 #[cfg(feature = "extra-traits")]
284 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
285 impl Debug for $name {
286 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
287 f.write_str(stringify!($name))
288 }
289 }
290
291 #[cfg(feature = "extra-traits")]
292 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
293 impl cmp::Eq for $name {}
294
295 #[cfg(feature = "extra-traits")]
296 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
297 impl PartialEq for $name {
298 fn eq(&self, _other: &$name) -> bool {
299 true
300 }
301 }
302
303 #[cfg(feature = "extra-traits")]
304 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
305 impl Hash for $name {
306 fn hash<H: Hasher>(&self, _state: &mut H) {}
307 }
308
309 #[cfg(feature = "printing")]
310 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
311 impl ToTokens for $name {
312 fn to_tokens(&self, tokens: &mut TokenStream) {
313 printing::keyword($token, self.span, tokens);
314 }
315 }
316
317 #[cfg(feature = "parsing")]
318 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
319 impl Parse for $name {
320 fn parse(input: ParseStream) -> Result<Self> {
321 Ok($name {
322 span: parsing::keyword(input, $token)?,
323 })
324 }
325 }
326
327 #[cfg(feature = "parsing")]
328 impl Token for $name {
329 fn peek(cursor: Cursor) -> bool {
330 parsing::peek_keyword(cursor, $token)
331 }
332
333 fn display() -> &'static str {
334 concat!("`", $token, "`")
335 }
336 }
337
338 #[cfg(feature = "parsing")]
339 impl private::Sealed for $name {}
340 )*
341 };
342}
343
344macro_rules! impl_deref_if_len_is_1 {
345 ($name:ident/1) => {
346 impl Deref for $name {
347 type Target = WithSpan;
348
349 fn deref(&self) -> &Self::Target {
350 unsafe { &*(self as *const Self).cast::<WithSpan>() }
351 }
352 }
353
354 impl DerefMut for $name {
355 fn deref_mut(&mut self) -> &mut Self::Target {
356 unsafe { &mut *(self as *mut Self).cast::<WithSpan>() }
357 }
358 }
359 };
360
361 ($name:ident/$len:literal) => {};
362}
363
364macro_rules! define_punctuation_structs {
365 ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {
366 $(
367 #[cfg_attr(not(doc), repr(transparent))]
368 #[doc = concat!('`', $token, '`')]
369 ///
370 /// Usage:
371 #[doc = concat!($usage, '.')]
372 ///
373 /// Don't try to remember the name of this type &mdash; use the
374 /// [`Token!`] macro instead.
375 ///
376 /// [`Token!`]: crate::token
377 pub struct $name {
378 pub spans: [Span; $len],
379 }
380
381 #[doc(hidden)]
382 #[allow(non_snake_case)]
383 pub fn $name<S: IntoSpans<[Span; $len]>>(spans: S) -> $name {
384 $name {
385 spans: spans.into_spans(),
386 }
387 }
388
389 impl std::default::Default for $name {
390 fn default() -> Self {
391 $name {
392 spans: [Span::call_site(); $len],
393 }
394 }
395 }
396
397 #[cfg(feature = "clone-impls")]
398 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
399 impl Copy for $name {}
400
401 #[cfg(feature = "clone-impls")]
402 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
403 impl Clone for $name {
404 fn clone(&self) -> Self {
405 *self
406 }
407 }
408
409 #[cfg(feature = "extra-traits")]
410 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
411 impl Debug for $name {
412 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
413 f.write_str(stringify!($name))
414 }
415 }
416
417 #[cfg(feature = "extra-traits")]
418 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
419 impl cmp::Eq for $name {}
420
421 #[cfg(feature = "extra-traits")]
422 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
423 impl PartialEq for $name {
424 fn eq(&self, _other: &$name) -> bool {
425 true
426 }
427 }
428
429 #[cfg(feature = "extra-traits")]
430 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
431 impl Hash for $name {
432 fn hash<H: Hasher>(&self, _state: &mut H) {}
433 }
434
435 impl_deref_if_len_is_1!($name/$len);
436 )*
437 };
438}
439
440macro_rules! define_punctuation {
441 ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {
442 $(
443 define_punctuation_structs! {
444 $token pub struct $name/$len #[doc = $usage]
445 }
446
447 #[cfg(feature = "printing")]
448 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
449 impl ToTokens for $name {
450 fn to_tokens(&self, tokens: &mut TokenStream) {
451 printing::punct($token, &self.spans, tokens);
452 }
453 }
454
455 #[cfg(feature = "parsing")]
456 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
457 impl Parse for $name {
458 fn parse(input: ParseStream) -> Result<Self> {
459 Ok($name {
460 spans: parsing::punct(input, $token)?,
461 })
462 }
463 }
464
465 #[cfg(feature = "parsing")]
466 impl Token for $name {
467 fn peek(cursor: Cursor) -> bool {
468 parsing::peek_punct(cursor, $token)
469 }
470
471 fn display() -> &'static str {
472 concat!("`", $token, "`")
473 }
474 }
475
476 #[cfg(feature = "parsing")]
477 impl private::Sealed for $name {}
478 )*
479 };
480}
481
482macro_rules! define_delimiters {
483 ($($delim:ident pub struct $name:ident #[$doc:meta])*) => {
484 $(
485 #[$doc]
486 pub struct $name {
487 pub span: DelimSpan,
488 }
489
490 #[doc(hidden)]
491 #[allow(non_snake_case)]
492 pub fn $name<S: IntoSpans<DelimSpan>>(span: S) -> $name {
493 $name {
494 span: span.into_spans(),
495 }
496 }
497
498 impl std::default::Default for $name {
499 fn default() -> Self {
500 $name(Span::call_site())
501 }
502 }
503
504 #[cfg(feature = "clone-impls")]
505 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
506 impl Copy for $name {}
507
508 #[cfg(feature = "clone-impls")]
509 #[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
510 impl Clone for $name {
511 fn clone(&self) -> Self {
512 *self
513 }
514 }
515
516 #[cfg(feature = "extra-traits")]
517 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
518 impl Debug for $name {
519 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
520 f.write_str(stringify!($name))
521 }
522 }
523
524 #[cfg(feature = "extra-traits")]
525 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
526 impl cmp::Eq for $name {}
527
528 #[cfg(feature = "extra-traits")]
529 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
530 impl PartialEq for $name {
531 fn eq(&self, _other: &$name) -> bool {
532 true
533 }
534 }
535
536 #[cfg(feature = "extra-traits")]
537 #[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
538 impl Hash for $name {
539 fn hash<H: Hasher>(&self, _state: &mut H) {}
540 }
541
542 impl $name {
543 #[cfg(feature = "printing")]
544 pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
545 where
546 F: FnOnce(&mut TokenStream),
547 {
548 let mut inner = TokenStream::new();
549 f(&mut inner);
550 printing::delim(Delimiter::$delim, self.span.join(), tokens, inner);
551 }
552 }
553
554 #[cfg(feature = "parsing")]
555 impl private::Sealed for $name {}
556 )*
557 };
558}
559
560define_punctuation_structs! {
561 "_" pub struct Underscore/1 /// wildcard patterns, inferred types, unnamed items in constants, extern crates, use declarations, and destructuring assignment
562}
563
564#[cfg(feature = "printing")]
565#[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
566impl ToTokens for Underscore {
567 fn to_tokens(&self, tokens: &mut TokenStream) {
568 tokens.append(token:Ident::new(string:"_", self.span));
569 }
570}
571
572#[cfg(feature = "parsing")]
573#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
574impl Parse for Underscore {
575 fn parse(input: ParseStream) -> Result<Self> {
576 input.step(|cursor: StepCursor<'_, '_>| {
577 if let Some((ident: Ident, rest: Cursor<'_>)) = cursor.ident() {
578 if ident == "_" {
579 return Ok((Underscore(spans:ident.span()), rest));
580 }
581 }
582 if let Some((punct: Punct, rest: Cursor<'_>)) = cursor.punct() {
583 if punct.as_char() == '_' {
584 return Ok((Underscore(spans:punct.span()), rest));
585 }
586 }
587 Err(cursor.error(message:"expected `_`"))
588 })
589 }
590}
591
592#[cfg(feature = "parsing")]
593impl Token for Underscore {
594 fn peek(cursor: Cursor) -> bool {
595 if let Some((ident: Ident, _rest: Cursor<'_>)) = cursor.ident() {
596 return ident == "_";
597 }
598 if let Some((punct: Punct, _rest: Cursor<'_>)) = cursor.punct() {
599 return punct.as_char() == '_';
600 }
601 false
602 }
603
604 fn display() -> &'static str {
605 "`_`"
606 }
607}
608
609#[cfg(feature = "parsing")]
610impl private::Sealed for Underscore {}
611
612/// None-delimited group
613pub struct Group {
614 pub span: Span,
615}
616
617#[doc(hidden)]
618#[allow(non_snake_case)]
619pub fn Group<S: IntoSpans<Span>>(span: S) -> Group {
620 Group {
621 span: span.into_spans(),
622 }
623}
624
625impl std::default::Default for Group {
626 fn default() -> Self {
627 Group {
628 span: Span::call_site(),
629 }
630 }
631}
632
633#[cfg(feature = "clone-impls")]
634#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
635impl Copy for Group {}
636
637#[cfg(feature = "clone-impls")]
638#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
639impl Clone for Group {
640 fn clone(&self) -> Self {
641 *self
642 }
643}
644
645#[cfg(feature = "extra-traits")]
646#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
647impl Debug for Group {
648 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
649 f.write_str(data:"Group")
650 }
651}
652
653#[cfg(feature = "extra-traits")]
654#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
655impl cmp::Eq for Group {}
656
657#[cfg(feature = "extra-traits")]
658#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
659impl PartialEq for Group {
660 fn eq(&self, _other: &Group) -> bool {
661 true
662 }
663}
664
665#[cfg(feature = "extra-traits")]
666#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
667impl Hash for Group {
668 fn hash<H: Hasher>(&self, _state: &mut H) {}
669}
670
671impl Group {
672 #[cfg(feature = "printing")]
673 pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
674 where
675 F: FnOnce(&mut TokenStream),
676 {
677 let mut inner: TokenStream = TokenStream::new();
678 f(&mut inner);
679 printing::delim(delim:Delimiter::None, self.span, tokens, inner);
680 }
681}
682
683#[cfg(feature = "parsing")]
684impl private::Sealed for Group {}
685
686#[cfg(feature = "parsing")]
687impl Token for Paren {
688 fn peek(cursor: Cursor) -> bool {
689 lookahead::is_delimiter(cursor, Delimiter::Parenthesis)
690 }
691
692 fn display() -> &'static str {
693 "parentheses"
694 }
695}
696
697#[cfg(feature = "parsing")]
698impl Token for Brace {
699 fn peek(cursor: Cursor) -> bool {
700 lookahead::is_delimiter(cursor, Delimiter::Brace)
701 }
702
703 fn display() -> &'static str {
704 "curly braces"
705 }
706}
707
708#[cfg(feature = "parsing")]
709impl Token for Bracket {
710 fn peek(cursor: Cursor) -> bool {
711 lookahead::is_delimiter(cursor, Delimiter::Bracket)
712 }
713
714 fn display() -> &'static str {
715 "square brackets"
716 }
717}
718
719#[cfg(feature = "parsing")]
720impl Token for Group {
721 fn peek(cursor: Cursor) -> bool {
722 lookahead::is_delimiter(cursor, Delimiter::None)
723 }
724
725 fn display() -> &'static str {
726 "invisible group"
727 }
728}
729
730define_keywords! {
731 "abstract" pub struct Abstract
732 "as" pub struct As
733 "async" pub struct Async
734 "auto" pub struct Auto
735 "await" pub struct Await
736 "become" pub struct Become
737 "box" pub struct Box
738 "break" pub struct Break
739 "const" pub struct Const
740 "continue" pub struct Continue
741 "crate" pub struct Crate
742 "default" pub struct Default
743 "do" pub struct Do
744 "dyn" pub struct Dyn
745 "else" pub struct Else
746 "enum" pub struct Enum
747 "extern" pub struct Extern
748 "final" pub struct Final
749 "fn" pub struct Fn
750 "for" pub struct For
751 "if" pub struct If
752 "impl" pub struct Impl
753 "in" pub struct In
754 "let" pub struct Let
755 "loop" pub struct Loop
756 "macro" pub struct Macro
757 "match" pub struct Match
758 "mod" pub struct Mod
759 "move" pub struct Move
760 "mut" pub struct Mut
761 "override" pub struct Override
762 "priv" pub struct Priv
763 "pub" pub struct Pub
764 "ref" pub struct Ref
765 "return" pub struct Return
766 "Self" pub struct SelfType
767 "self" pub struct SelfValue
768 "static" pub struct Static
769 "struct" pub struct Struct
770 "super" pub struct Super
771 "trait" pub struct Trait
772 "try" pub struct Try
773 "type" pub struct Type
774 "typeof" pub struct Typeof
775 "union" pub struct Union
776 "unsafe" pub struct Unsafe
777 "unsized" pub struct Unsized
778 "use" pub struct Use
779 "virtual" pub struct Virtual
780 "where" pub struct Where
781 "while" pub struct While
782 "yield" pub struct Yield
783}
784
785define_punctuation! {
786 "&" pub struct And/1 /// bitwise and logical AND, borrow, references, reference patterns
787 "&&" pub struct AndAnd/2 /// lazy AND, borrow, references, reference patterns
788 "&=" pub struct AndEq/2 /// bitwise AND assignment
789 "@" pub struct At/1 /// subpattern binding
790 "^" pub struct Caret/1 /// bitwise and logical XOR
791 "^=" pub struct CaretEq/2 /// bitwise XOR assignment
792 ":" pub struct Colon/1 /// various separators
793 "," pub struct Comma/1 /// various separators
794 "$" pub struct Dollar/1 /// macros
795 "." pub struct Dot/1 /// field access, tuple index
796 ".." pub struct DotDot/2 /// range, struct expressions, patterns, range patterns
797 "..." pub struct DotDotDot/3 /// variadic functions, range patterns
798 "..=" pub struct DotDotEq/3 /// inclusive range, range patterns
799 "=" pub struct Eq/1 /// assignment, attributes, various type definitions
800 "==" pub struct EqEq/2 /// equal
801 "=>" pub struct FatArrow/2 /// match arms, macros
802 ">=" pub struct Ge/2 /// greater than or equal to, generics
803 ">" pub struct Gt/1 /// greater than, generics, paths
804 "<-" pub struct LArrow/2 /// unused
805 "<=" pub struct Le/2 /// less than or equal to
806 "<" pub struct Lt/1 /// less than, generics, paths
807 "-" pub struct Minus/1 /// subtraction, negation
808 "-=" pub struct MinusEq/2 /// subtraction assignment
809 "!=" pub struct Ne/2 /// not equal
810 "!" pub struct Not/1 /// bitwise and logical NOT, macro calls, inner attributes, never type, negative impls
811 "|" pub struct Or/1 /// bitwise and logical OR, closures, patterns in match, if let, and while let
812 "|=" pub struct OrEq/2 /// bitwise OR assignment
813 "||" pub struct OrOr/2 /// lazy OR, closures
814 "::" pub struct PathSep/2 /// path separator
815 "%" pub struct Percent/1 /// remainder
816 "%=" pub struct PercentEq/2 /// remainder assignment
817 "+" pub struct Plus/1 /// addition, trait bounds, macro Kleene matcher
818 "+=" pub struct PlusEq/2 /// addition assignment
819 "#" pub struct Pound/1 /// attributes
820 "?" pub struct Question/1 /// question mark operator, questionably sized, macro Kleene matcher
821 "->" pub struct RArrow/2 /// function return type, closure return type, function pointer type
822 ";" pub struct Semi/1 /// terminator for various items and statements, array types
823 "<<" pub struct Shl/2 /// shift left, nested generics
824 "<<=" pub struct ShlEq/3 /// shift left assignment
825 ">>" pub struct Shr/2 /// shift right, nested generics
826 ">>=" pub struct ShrEq/3 /// shift right assignment, nested generics
827 "/" pub struct Slash/1 /// division
828 "/=" pub struct SlashEq/2 /// division assignment
829 "*" pub struct Star/1 /// multiplication, dereference, raw pointers, macro Kleene matcher, use wildcards
830 "*=" pub struct StarEq/2 /// multiplication assignment
831 "~" pub struct Tilde/1 /// unused since before Rust 1.0
832}
833
834define_delimiters! {
835 Brace pub struct Brace /// `{`&hellip;`}`
836 Bracket pub struct Bracket /// `[`&hellip;`]`
837 Parenthesis pub struct Paren /// `(`&hellip;`)`
838}
839
840/// A type-macro that expands to the name of the Rust type representation of a
841/// given token.
842///
843/// See the [token module] documentation for details and examples.
844///
845/// [token module]: crate::token
846#[macro_export]
847macro_rules! Token {
848 [abstract] => { $crate::token::Abstract };
849 [as] => { $crate::token::As };
850 [async] => { $crate::token::Async };
851 [auto] => { $crate::token::Auto };
852 [await] => { $crate::token::Await };
853 [become] => { $crate::token::Become };
854 [box] => { $crate::token::Box };
855 [break] => { $crate::token::Break };
856 [const] => { $crate::token::Const };
857 [continue] => { $crate::token::Continue };
858 [crate] => { $crate::token::Crate };
859 [default] => { $crate::token::Default };
860 [do] => { $crate::token::Do };
861 [dyn] => { $crate::token::Dyn };
862 [else] => { $crate::token::Else };
863 [enum] => { $crate::token::Enum };
864 [extern] => { $crate::token::Extern };
865 [final] => { $crate::token::Final };
866 [fn] => { $crate::token::Fn };
867 [for] => { $crate::token::For };
868 [if] => { $crate::token::If };
869 [impl] => { $crate::token::Impl };
870 [in] => { $crate::token::In };
871 [let] => { $crate::token::Let };
872 [loop] => { $crate::token::Loop };
873 [macro] => { $crate::token::Macro };
874 [match] => { $crate::token::Match };
875 [mod] => { $crate::token::Mod };
876 [move] => { $crate::token::Move };
877 [mut] => { $crate::token::Mut };
878 [override] => { $crate::token::Override };
879 [priv] => { $crate::token::Priv };
880 [pub] => { $crate::token::Pub };
881 [ref] => { $crate::token::Ref };
882 [return] => { $crate::token::Return };
883 [Self] => { $crate::token::SelfType };
884 [self] => { $crate::token::SelfValue };
885 [static] => { $crate::token::Static };
886 [struct] => { $crate::token::Struct };
887 [super] => { $crate::token::Super };
888 [trait] => { $crate::token::Trait };
889 [try] => { $crate::token::Try };
890 [type] => { $crate::token::Type };
891 [typeof] => { $crate::token::Typeof };
892 [union] => { $crate::token::Union };
893 [unsafe] => { $crate::token::Unsafe };
894 [unsized] => { $crate::token::Unsized };
895 [use] => { $crate::token::Use };
896 [virtual] => { $crate::token::Virtual };
897 [where] => { $crate::token::Where };
898 [while] => { $crate::token::While };
899 [yield] => { $crate::token::Yield };
900 [&] => { $crate::token::And };
901 [&&] => { $crate::token::AndAnd };
902 [&=] => { $crate::token::AndEq };
903 [@] => { $crate::token::At };
904 [^] => { $crate::token::Caret };
905 [^=] => { $crate::token::CaretEq };
906 [:] => { $crate::token::Colon };
907 [,] => { $crate::token::Comma };
908 [$] => { $crate::token::Dollar };
909 [.] => { $crate::token::Dot };
910 [..] => { $crate::token::DotDot };
911 [...] => { $crate::token::DotDotDot };
912 [..=] => { $crate::token::DotDotEq };
913 [=] => { $crate::token::Eq };
914 [==] => { $crate::token::EqEq };
915 [=>] => { $crate::token::FatArrow };
916 [>=] => { $crate::token::Ge };
917 [>] => { $crate::token::Gt };
918 [<-] => { $crate::token::LArrow };
919 [<=] => { $crate::token::Le };
920 [<] => { $crate::token::Lt };
921 [-] => { $crate::token::Minus };
922 [-=] => { $crate::token::MinusEq };
923 [!=] => { $crate::token::Ne };
924 [!] => { $crate::token::Not };
925 [|] => { $crate::token::Or };
926 [|=] => { $crate::token::OrEq };
927 [||] => { $crate::token::OrOr };
928 [::] => { $crate::token::PathSep };
929 [%] => { $crate::token::Percent };
930 [%=] => { $crate::token::PercentEq };
931 [+] => { $crate::token::Plus };
932 [+=] => { $crate::token::PlusEq };
933 [#] => { $crate::token::Pound };
934 [?] => { $crate::token::Question };
935 [->] => { $crate::token::RArrow };
936 [;] => { $crate::token::Semi };
937 [<<] => { $crate::token::Shl };
938 [<<=] => { $crate::token::ShlEq };
939 [>>] => { $crate::token::Shr };
940 [>>=] => { $crate::token::ShrEq };
941 [/] => { $crate::token::Slash };
942 [/=] => { $crate::token::SlashEq };
943 [*] => { $crate::token::Star };
944 [*=] => { $crate::token::StarEq };
945 [~] => { $crate::token::Tilde };
946 [_] => { $crate::token::Underscore };
947}
948
949// Not public API.
950#[doc(hidden)]
951#[cfg(feature = "parsing")]
952pub(crate) mod parsing {
953 use crate::buffer::Cursor;
954 use crate::error::{Error, Result};
955 use crate::parse::ParseStream;
956 use proc_macro2::{Spacing, Span};
957
958 pub(crate) fn keyword(input: ParseStream, token: &str) -> Result<Span> {
959 input.step(|cursor| {
960 if let Some((ident, rest)) = cursor.ident() {
961 if ident == token {
962 return Ok((ident.span(), rest));
963 }
964 }
965 Err(cursor.error(format!("expected `{}`", token)))
966 })
967 }
968
969 pub(crate) fn peek_keyword(cursor: Cursor, token: &str) -> bool {
970 if let Some((ident, _rest)) = cursor.ident() {
971 ident == token
972 } else {
973 false
974 }
975 }
976
977 #[doc(hidden)]
978 pub fn punct<const N: usize>(input: ParseStream, token: &str) -> Result<[Span; N]> {
979 let mut spans = [input.span(); N];
980 punct_helper(input, token, &mut spans)?;
981 Ok(spans)
982 }
983
984 fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span]) -> Result<()> {
985 input.step(|cursor| {
986 let mut cursor = *cursor;
987 assert_eq!(token.len(), spans.len());
988
989 for (i, ch) in token.chars().enumerate() {
990 match cursor.punct() {
991 Some((punct, rest)) => {
992 spans[i] = punct.span();
993 if punct.as_char() != ch {
994 break;
995 } else if i == token.len() - 1 {
996 return Ok(((), rest));
997 } else if punct.spacing() != Spacing::Joint {
998 break;
999 }
1000 cursor = rest;
1001 }
1002 None => break,
1003 }
1004 }
1005
1006 Err(Error::new(spans[0], format!("expected `{}`", token)))
1007 })
1008 }
1009
1010 #[doc(hidden)]
1011 pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
1012 for (i, ch) in token.chars().enumerate() {
1013 match cursor.punct() {
1014 Some((punct, rest)) => {
1015 if punct.as_char() != ch {
1016 break;
1017 } else if i == token.len() - 1 {
1018 return true;
1019 } else if punct.spacing() != Spacing::Joint {
1020 break;
1021 }
1022 cursor = rest;
1023 }
1024 None => break,
1025 }
1026 }
1027 false
1028 }
1029}
1030
1031// Not public API.
1032#[doc(hidden)]
1033#[cfg(feature = "printing")]
1034pub(crate) mod printing {
1035 use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
1036 use quote::TokenStreamExt;
1037
1038 #[doc(hidden)]
1039 pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
1040 assert_eq!(s.len(), spans.len());
1041
1042 let mut chars = s.chars();
1043 let mut spans = spans.iter();
1044 let ch = chars.next_back().unwrap();
1045 let span = spans.next_back().unwrap();
1046 for (ch, span) in chars.zip(spans) {
1047 let mut op = Punct::new(ch, Spacing::Joint);
1048 op.set_span(*span);
1049 tokens.append(op);
1050 }
1051
1052 let mut op = Punct::new(ch, Spacing::Alone);
1053 op.set_span(*span);
1054 tokens.append(op);
1055 }
1056
1057 pub(crate) fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
1058 tokens.append(Ident::new(s, span));
1059 }
1060
1061 pub(crate) fn delim(
1062 delim: Delimiter,
1063 span: Span,
1064 tokens: &mut TokenStream,
1065 inner: TokenStream,
1066 ) {
1067 let mut g = Group::new(delim, inner);
1068 g.set_span(span);
1069 tokens.append(g);
1070 }
1071}
1072