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

Provided by KDAB

Privacy Policy