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!`]: ../macro.Token.html
8 //!
9 //! # Example
10 //!
11 //! The [`ItemStatic`] syntax tree node is defined like this.
12 //!
13 //! [`ItemStatic`]: ../struct.ItemStatic.html
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`]: ../parse/struct.ParseBuffer.html#method.parse
39 //! [`parenthesized!`]: ../macro.parenthesized.html
40 //! [`bracketed!`]: ../macro.bracketed.html
41 //! [`braced!`]: ../macro.braced.html
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]: ../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
90
91 #[cfg(feature = "extra-traits")]
92 use std::cmp;
93 #[cfg(feature = "extra-traits")]
94 use std::fmt::{self, Debug};
95 #[cfg(feature = "extra-traits")]
96 use std::hash::{Hash, Hasher};
97 use std::ops::{Deref, DerefMut};
98
99 #[cfg(feature = "parsing")]
100 use proc_macro2::Delimiter;
101 #[cfg(any(feature = "parsing", feature = "printing"))]
102 use proc_macro2::Ident;
103 use proc_macro2::Span;
104 #[cfg(feature = "printing")]
105 use proc_macro2::TokenStream;
106 #[cfg(feature = "printing")]
107 use quote::{ToTokens, TokenStreamExt};
108
109 use self::private::WithSpan;
110 #[cfg(feature = "parsing")]
111 use crate::buffer::Cursor;
112 #[cfg(feature = "parsing")]
113 use crate::error::Result;
114 #[cfg(any(feature = "full", feature = "derive"))]
115 #[cfg(feature = "parsing")]
116 use crate::lifetime::Lifetime;
117 #[cfg(any(feature = "full", feature = "derive"))]
118 #[cfg(feature = "parsing")]
119 use crate::lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
120 #[cfg(feature = "parsing")]
121 use crate::lookahead;
122 #[cfg(feature = "parsing")]
123 use crate::parse::{Parse, ParseStream};
124 use crate::span::IntoSpans;
125
126 /// Marker trait for types that represent single tokens.
127 ///
128 /// This trait is sealed and cannot be implemented for types outside of Syn.
129 #[cfg(feature = "parsing")]
130 pub trait Token: private::Sealed {
131 // Not public API.
132 #[doc(hidden)]
peek(cursor: Cursor) -> bool133 fn peek(cursor: Cursor) -> bool;
134
135 // Not public API.
136 #[doc(hidden)]
display() -> &'static str137 fn display() -> &'static str;
138 }
139
140 mod private {
141 use proc_macro2::Span;
142
143 #[cfg(feature = "parsing")]
144 pub trait Sealed {}
145
146 /// Support writing `token.span` rather than `token.spans[0]` on tokens that
147 /// hold a single span.
148 #[repr(C)]
149 pub struct WithSpan {
150 pub span: Span,
151 }
152 }
153
154 #[cfg(feature = "parsing")]
155 impl private::Sealed for Ident {}
156
157 #[cfg(any(feature = "full", feature = "derive"))]
158 #[cfg(feature = "parsing")]
peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool159 fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
160 use crate::parse::Unexpected;
161 use std::cell::Cell;
162 use std::rc::Rc;
163
164 let scope = Span::call_site();
165 let unexpected = Rc::new(Cell::new(Unexpected::None));
166 let buffer = crate::parse::new_parse_buffer(scope, cursor, unexpected);
167 peek(&buffer)
168 }
169
170 #[cfg(any(feature = "full", feature = "derive"))]
171 macro_rules! impl_token {
172 ($name:ident $display:expr) => {
173 #[cfg(feature = "parsing")]
174 impl Token for $name {
175 fn peek(cursor: Cursor) -> bool {
176 fn peek(input: ParseStream) -> bool {
177 <$name as Parse>::parse(input).is_ok()
178 }
179 peek_impl(cursor, peek)
180 }
181
182 fn display() -> &'static str {
183 $display
184 }
185 }
186
187 #[cfg(feature = "parsing")]
188 impl private::Sealed for $name {}
189 };
190 }
191
192 #[cfg(any(feature = "full", feature = "derive"))]
193 impl_token!(Lifetime "lifetime");
194 #[cfg(any(feature = "full", feature = "derive"))]
195 impl_token!(Lit "literal");
196 #[cfg(any(feature = "full", feature = "derive"))]
197 impl_token!(LitStr "string literal");
198 #[cfg(any(feature = "full", feature = "derive"))]
199 impl_token!(LitByteStr "byte string literal");
200 #[cfg(any(feature = "full", feature = "derive"))]
201 impl_token!(LitByte "byte literal");
202 #[cfg(any(feature = "full", feature = "derive"))]
203 impl_token!(LitChar "character literal");
204 #[cfg(any(feature = "full", feature = "derive"))]
205 impl_token!(LitInt "integer literal");
206 #[cfg(any(feature = "full", feature = "derive"))]
207 impl_token!(LitFloat "floating point literal");
208 #[cfg(any(feature = "full", feature = "derive"))]
209 impl_token!(LitBool "boolean literal");
210
211 // Not public API.
212 #[doc(hidden)]
213 #[cfg(feature = "parsing")]
214 pub trait CustomToken {
peek(cursor: Cursor) -> bool215 fn peek(cursor: Cursor) -> bool;
display() -> &'static str216 fn display() -> &'static str;
217 }
218
219 #[cfg(feature = "parsing")]
220 impl<T: CustomToken> private::Sealed for T {}
221
222 #[cfg(feature = "parsing")]
223 impl<T: CustomToken> Token for T {
peek(cursor: Cursor) -> bool224 fn peek(cursor: Cursor) -> bool {
225 <Self as CustomToken>::peek(cursor)
226 }
227
display() -> &'static str228 fn display() -> &'static str {
229 <Self as CustomToken>::display()
230 }
231 }
232
233 macro_rules! define_keywords {
234 ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
235 $(
236 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
237 #[$doc]
238 ///
239 /// Don't try to remember the name of this type — use the
240 /// [`Token!`] macro instead.
241 ///
242 /// [`Token!`]: crate::token
243 pub struct $name {
244 pub span: Span,
245 }
246
247 #[doc(hidden)]
248 #[allow(non_snake_case)]
249 pub fn $name<S: IntoSpans<[Span; 1]>>(span: S) -> $name {
250 $name {
251 span: span.into_spans()[0],
252 }
253 }
254
255 impl std::default::Default for $name {
256 fn default() -> Self {
257 $name {
258 span: Span::call_site(),
259 }
260 }
261 }
262
263 #[cfg(feature = "extra-traits")]
264 impl Debug for $name {
265 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266 f.write_str(stringify!($name))
267 }
268 }
269
270 #[cfg(feature = "extra-traits")]
271 impl cmp::Eq for $name {}
272
273 #[cfg(feature = "extra-traits")]
274 impl PartialEq for $name {
275 fn eq(&self, _other: &$name) -> bool {
276 true
277 }
278 }
279
280 #[cfg(feature = "extra-traits")]
281 impl Hash for $name {
282 fn hash<H: Hasher>(&self, _state: &mut H) {}
283 }
284
285 #[cfg(feature = "printing")]
286 impl ToTokens for $name {
287 fn to_tokens(&self, tokens: &mut TokenStream) {
288 printing::keyword($token, self.span, tokens);
289 }
290 }
291
292 #[cfg(feature = "parsing")]
293 impl Parse for $name {
294 fn parse(input: ParseStream) -> Result<Self> {
295 Ok($name {
296 span: parsing::keyword(input, $token)?,
297 })
298 }
299 }
300
301 #[cfg(feature = "parsing")]
302 impl Token for $name {
303 fn peek(cursor: Cursor) -> bool {
304 parsing::peek_keyword(cursor, $token)
305 }
306
307 fn display() -> &'static str {
308 concat!("`", $token, "`")
309 }
310 }
311
312 #[cfg(feature = "parsing")]
313 impl private::Sealed for $name {}
314 )*
315 };
316 }
317
318 macro_rules! impl_deref_if_len_is_1 {
319 ($name:ident/1) => {
320 impl Deref for $name {
321 type Target = WithSpan;
322
323 fn deref(&self) -> &Self::Target {
324 unsafe { &*(self as *const Self as *const WithSpan) }
325 }
326 }
327
328 impl DerefMut for $name {
329 fn deref_mut(&mut self) -> &mut Self::Target {
330 unsafe { &mut *(self as *mut Self as *mut WithSpan) }
331 }
332 }
333 };
334
335 ($name:ident/$len:tt) => {};
336 }
337
338 macro_rules! define_punctuation_structs {
339 ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
340 $(
341 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
342 #[repr(C)]
343 #[$doc]
344 ///
345 /// Don't try to remember the name of this type — use the
346 /// [`Token!`] macro instead.
347 ///
348 /// [`Token!`]: crate::token
349 pub struct $name {
350 pub spans: [Span; $len],
351 }
352
353 #[doc(hidden)]
354 #[allow(non_snake_case)]
355 pub fn $name<S: IntoSpans<[Span; $len]>>(spans: S) -> $name {
356 $name {
357 spans: spans.into_spans(),
358 }
359 }
360
361 impl std::default::Default for $name {
362 fn default() -> Self {
363 $name {
364 spans: [Span::call_site(); $len],
365 }
366 }
367 }
368
369 #[cfg(feature = "extra-traits")]
370 impl Debug for $name {
371 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
372 f.write_str(stringify!($name))
373 }
374 }
375
376 #[cfg(feature = "extra-traits")]
377 impl cmp::Eq for $name {}
378
379 #[cfg(feature = "extra-traits")]
380 impl PartialEq for $name {
381 fn eq(&self, _other: &$name) -> bool {
382 true
383 }
384 }
385
386 #[cfg(feature = "extra-traits")]
387 impl Hash for $name {
388 fn hash<H: Hasher>(&self, _state: &mut H) {}
389 }
390
391 impl_deref_if_len_is_1!($name/$len);
392 )*
393 };
394 }
395
396 macro_rules! define_punctuation {
397 ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
398 $(
399 define_punctuation_structs! {
400 $token pub struct $name/$len #[$doc]
401 }
402
403 #[cfg(feature = "printing")]
404 impl ToTokens for $name {
405 fn to_tokens(&self, tokens: &mut TokenStream) {
406 printing::punct($token, &self.spans, tokens);
407 }
408 }
409
410 #[cfg(feature = "parsing")]
411 impl Parse for $name {
412 fn parse(input: ParseStream) -> Result<Self> {
413 Ok($name {
414 spans: parsing::punct(input, $token)?,
415 })
416 }
417 }
418
419 #[cfg(feature = "parsing")]
420 impl Token for $name {
421 fn peek(cursor: Cursor) -> bool {
422 parsing::peek_punct(cursor, $token)
423 }
424
425 fn display() -> &'static str {
426 concat!("`", $token, "`")
427 }
428 }
429
430 #[cfg(feature = "parsing")]
431 impl private::Sealed for $name {}
432 )*
433 };
434 }
435
436 macro_rules! define_delimiters {
437 ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
438 $(
439 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
440 #[$doc]
441 pub struct $name {
442 pub span: Span,
443 }
444
445 #[doc(hidden)]
446 #[allow(non_snake_case)]
447 pub fn $name<S: IntoSpans<[Span; 1]>>(span: S) -> $name {
448 $name {
449 span: span.into_spans()[0],
450 }
451 }
452
453 impl std::default::Default for $name {
454 fn default() -> Self {
455 $name {
456 span: Span::call_site(),
457 }
458 }
459 }
460
461 #[cfg(feature = "extra-traits")]
462 impl Debug for $name {
463 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
464 f.write_str(stringify!($name))
465 }
466 }
467
468 #[cfg(feature = "extra-traits")]
469 impl cmp::Eq for $name {}
470
471 #[cfg(feature = "extra-traits")]
472 impl PartialEq for $name {
473 fn eq(&self, _other: &$name) -> bool {
474 true
475 }
476 }
477
478 #[cfg(feature = "extra-traits")]
479 impl Hash for $name {
480 fn hash<H: Hasher>(&self, _state: &mut H) {}
481 }
482
483 impl $name {
484 #[cfg(feature = "printing")]
485 pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
486 where
487 F: FnOnce(&mut TokenStream),
488 {
489 printing::delim($token, self.span, tokens, f);
490 }
491 }
492
493 #[cfg(feature = "parsing")]
494 impl private::Sealed for $name {}
495 )*
496 };
497 }
498
499 define_punctuation_structs! {
500 "_" pub struct Underscore/1 /// `_`
501 }
502
503 #[cfg(feature = "printing")]
504 impl ToTokens for Underscore {
to_tokens(&self, tokens: &mut TokenStream)505 fn to_tokens(&self, tokens: &mut TokenStream) {
506 tokens.append(Ident::new("_", self.span));
507 }
508 }
509
510 #[cfg(feature = "parsing")]
511 impl Parse for Underscore {
parse(input: ParseStream) -> Result<Self>512 fn parse(input: ParseStream) -> Result<Self> {
513 input.step(|cursor| {
514 if let Some((ident, rest)) = cursor.ident() {
515 if ident == "_" {
516 return Ok((Underscore(ident.span()), rest));
517 }
518 }
519 if let Some((punct, rest)) = cursor.punct() {
520 if punct.as_char() == '_' {
521 return Ok((Underscore(punct.span()), rest));
522 }
523 }
524 Err(cursor.error("expected `_`"))
525 })
526 }
527 }
528
529 #[cfg(feature = "parsing")]
530 impl Token for Underscore {
peek(cursor: Cursor) -> bool531 fn peek(cursor: Cursor) -> bool {
532 if let Some((ident, _rest)) = cursor.ident() {
533 return ident == "_";
534 }
535 if let Some((punct, _rest)) = cursor.punct() {
536 return punct.as_char() == '_';
537 }
538 false
539 }
540
display() -> &'static str541 fn display() -> &'static str {
542 "`_`"
543 }
544 }
545
546 #[cfg(feature = "parsing")]
547 impl private::Sealed for Underscore {}
548
549 #[cfg(feature = "parsing")]
550 impl Token for Paren {
peek(cursor: Cursor) -> bool551 fn peek(cursor: Cursor) -> bool {
552 lookahead::is_delimiter(cursor, Delimiter::Parenthesis)
553 }
554
display() -> &'static str555 fn display() -> &'static str {
556 "parentheses"
557 }
558 }
559
560 #[cfg(feature = "parsing")]
561 impl Token for Brace {
peek(cursor: Cursor) -> bool562 fn peek(cursor: Cursor) -> bool {
563 lookahead::is_delimiter(cursor, Delimiter::Brace)
564 }
565
display() -> &'static str566 fn display() -> &'static str {
567 "curly braces"
568 }
569 }
570
571 #[cfg(feature = "parsing")]
572 impl Token for Bracket {
peek(cursor: Cursor) -> bool573 fn peek(cursor: Cursor) -> bool {
574 lookahead::is_delimiter(cursor, Delimiter::Bracket)
575 }
576
display() -> &'static str577 fn display() -> &'static str {
578 "square brackets"
579 }
580 }
581
582 #[cfg(feature = "parsing")]
583 impl Token for Group {
peek(cursor: Cursor) -> bool584 fn peek(cursor: Cursor) -> bool {
585 lookahead::is_delimiter(cursor, Delimiter::None)
586 }
587
display() -> &'static str588 fn display() -> &'static str {
589 "invisible group"
590 }
591 }
592
593 define_keywords! {
594 "abstract" pub struct Abstract /// `abstract`
595 "as" pub struct As /// `as`
596 "async" pub struct Async /// `async`
597 "auto" pub struct Auto /// `auto`
598 "await" pub struct Await /// `await`
599 "become" pub struct Become /// `become`
600 "box" pub struct Box /// `box`
601 "break" pub struct Break /// `break`
602 "const" pub struct Const /// `const`
603 "continue" pub struct Continue /// `continue`
604 "crate" pub struct Crate /// `crate`
605 "default" pub struct Default /// `default`
606 "do" pub struct Do /// `do`
607 "dyn" pub struct Dyn /// `dyn`
608 "else" pub struct Else /// `else`
609 "enum" pub struct Enum /// `enum`
610 "extern" pub struct Extern /// `extern`
611 "final" pub struct Final /// `final`
612 "fn" pub struct Fn /// `fn`
613 "for" pub struct For /// `for`
614 "if" pub struct If /// `if`
615 "impl" pub struct Impl /// `impl`
616 "in" pub struct In /// `in`
617 "let" pub struct Let /// `let`
618 "loop" pub struct Loop /// `loop`
619 "macro" pub struct Macro /// `macro`
620 "match" pub struct Match /// `match`
621 "mod" pub struct Mod /// `mod`
622 "move" pub struct Move /// `move`
623 "mut" pub struct Mut /// `mut`
624 "override" pub struct Override /// `override`
625 "priv" pub struct Priv /// `priv`
626 "pub" pub struct Pub /// `pub`
627 "ref" pub struct Ref /// `ref`
628 "return" pub struct Return /// `return`
629 "Self" pub struct SelfType /// `Self`
630 "self" pub struct SelfValue /// `self`
631 "static" pub struct Static /// `static`
632 "struct" pub struct Struct /// `struct`
633 "super" pub struct Super /// `super`
634 "trait" pub struct Trait /// `trait`
635 "try" pub struct Try /// `try`
636 "type" pub struct Type /// `type`
637 "typeof" pub struct Typeof /// `typeof`
638 "union" pub struct Union /// `union`
639 "unsafe" pub struct Unsafe /// `unsafe`
640 "unsized" pub struct Unsized /// `unsized`
641 "use" pub struct Use /// `use`
642 "virtual" pub struct Virtual /// `virtual`
643 "where" pub struct Where /// `where`
644 "while" pub struct While /// `while`
645 "yield" pub struct Yield /// `yield`
646 }
647
648 define_punctuation! {
649 "+" pub struct Add/1 /// `+`
650 "+=" pub struct AddEq/2 /// `+=`
651 "&" pub struct And/1 /// `&`
652 "&&" pub struct AndAnd/2 /// `&&`
653 "&=" pub struct AndEq/2 /// `&=`
654 "@" pub struct At/1 /// `@`
655 "!" pub struct Bang/1 /// `!`
656 "^" pub struct Caret/1 /// `^`
657 "^=" pub struct CaretEq/2 /// `^=`
658 ":" pub struct Colon/1 /// `:`
659 "::" pub struct Colon2/2 /// `::`
660 "," pub struct Comma/1 /// `,`
661 "/" pub struct Div/1 /// `/`
662 "/=" pub struct DivEq/2 /// `/=`
663 "$" pub struct Dollar/1 /// `$`
664 "." pub struct Dot/1 /// `.`
665 ".." pub struct Dot2/2 /// `..`
666 "..." pub struct Dot3/3 /// `...`
667 "..=" pub struct DotDotEq/3 /// `..=`
668 "=" pub struct Eq/1 /// `=`
669 "==" pub struct EqEq/2 /// `==`
670 ">=" pub struct Ge/2 /// `>=`
671 ">" pub struct Gt/1 /// `>`
672 "<=" pub struct Le/2 /// `<=`
673 "<" pub struct Lt/1 /// `<`
674 "*=" pub struct MulEq/2 /// `*=`
675 "!=" pub struct Ne/2 /// `!=`
676 "|" pub struct Or/1 /// `|`
677 "|=" pub struct OrEq/2 /// `|=`
678 "||" pub struct OrOr/2 /// `||`
679 "#" pub struct Pound/1 /// `#`
680 "?" pub struct Question/1 /// `?`
681 "->" pub struct RArrow/2 /// `->`
682 "<-" pub struct LArrow/2 /// `<-`
683 "%" pub struct Rem/1 /// `%`
684 "%=" pub struct RemEq/2 /// `%=`
685 "=>" pub struct FatArrow/2 /// `=>`
686 ";" pub struct Semi/1 /// `;`
687 "<<" pub struct Shl/2 /// `<<`
688 "<<=" pub struct ShlEq/3 /// `<<=`
689 ">>" pub struct Shr/2 /// `>>`
690 ">>=" pub struct ShrEq/3 /// `>>=`
691 "*" pub struct Star/1 /// `*`
692 "-" pub struct Sub/1 /// `-`
693 "-=" pub struct SubEq/2 /// `-=`
694 "~" pub struct Tilde/1 /// `~`
695 }
696
697 define_delimiters! {
698 "{" pub struct Brace /// `{...}`
699 "[" pub struct Bracket /// `[...]`
700 "(" pub struct Paren /// `(...)`
701 " " pub struct Group /// None-delimited group
702 }
703
704 macro_rules! export_token_macro {
705 ($($await_rule:tt)*) => {
706 /// A type-macro that expands to the name of the Rust type representation of a
707 /// given token.
708 ///
709 /// See the [token module] documentation for details and examples.
710 ///
711 /// [token module]: crate::token
712 // Unfortunate duplication due to a rustdoc bug.
713 // https://github.com/rust-lang/rust/issues/45939
714 #[macro_export]
715 macro_rules! Token {
716 (abstract) => { $crate::token::Abstract };
717 (as) => { $crate::token::As };
718 (async) => { $crate::token::Async };
719 (auto) => { $crate::token::Auto };
720 $($await_rule => { $crate::token::Await };)*
721 (become) => { $crate::token::Become };
722 (box) => { $crate::token::Box };
723 (break) => { $crate::token::Break };
724 (const) => { $crate::token::Const };
725 (continue) => { $crate::token::Continue };
726 (crate) => { $crate::token::Crate };
727 (default) => { $crate::token::Default };
728 (do) => { $crate::token::Do };
729 (dyn) => { $crate::token::Dyn };
730 (else) => { $crate::token::Else };
731 (enum) => { $crate::token::Enum };
732 (extern) => { $crate::token::Extern };
733 (final) => { $crate::token::Final };
734 (fn) => { $crate::token::Fn };
735 (for) => { $crate::token::For };
736 (if) => { $crate::token::If };
737 (impl) => { $crate::token::Impl };
738 (in) => { $crate::token::In };
739 (let) => { $crate::token::Let };
740 (loop) => { $crate::token::Loop };
741 (macro) => { $crate::token::Macro };
742 (match) => { $crate::token::Match };
743 (mod) => { $crate::token::Mod };
744 (move) => { $crate::token::Move };
745 (mut) => { $crate::token::Mut };
746 (override) => { $crate::token::Override };
747 (priv) => { $crate::token::Priv };
748 (pub) => { $crate::token::Pub };
749 (ref) => { $crate::token::Ref };
750 (return) => { $crate::token::Return };
751 (Self) => { $crate::token::SelfType };
752 (self) => { $crate::token::SelfValue };
753 (static) => { $crate::token::Static };
754 (struct) => { $crate::token::Struct };
755 (super) => { $crate::token::Super };
756 (trait) => { $crate::token::Trait };
757 (try) => { $crate::token::Try };
758 (type) => { $crate::token::Type };
759 (typeof) => { $crate::token::Typeof };
760 (union) => { $crate::token::Union };
761 (unsafe) => { $crate::token::Unsafe };
762 (unsized) => { $crate::token::Unsized };
763 (use) => { $crate::token::Use };
764 (virtual) => { $crate::token::Virtual };
765 (where) => { $crate::token::Where };
766 (while) => { $crate::token::While };
767 (yield) => { $crate::token::Yield };
768 (+) => { $crate::token::Add };
769 (+=) => { $crate::token::AddEq };
770 (&) => { $crate::token::And };
771 (&&) => { $crate::token::AndAnd };
772 (&=) => { $crate::token::AndEq };
773 (@) => { $crate::token::At };
774 (!) => { $crate::token::Bang };
775 (^) => { $crate::token::Caret };
776 (^=) => { $crate::token::CaretEq };
777 (:) => { $crate::token::Colon };
778 (::) => { $crate::token::Colon2 };
779 (,) => { $crate::token::Comma };
780 (/) => { $crate::token::Div };
781 (/=) => { $crate::token::DivEq };
782 ($) => { $crate::token::Dollar };
783 (.) => { $crate::token::Dot };
784 (..) => { $crate::token::Dot2 };
785 (...) => { $crate::token::Dot3 };
786 (..=) => { $crate::token::DotDotEq };
787 (=) => { $crate::token::Eq };
788 (==) => { $crate::token::EqEq };
789 (>=) => { $crate::token::Ge };
790 (>) => { $crate::token::Gt };
791 (<=) => { $crate::token::Le };
792 (<) => { $crate::token::Lt };
793 (*=) => { $crate::token::MulEq };
794 (!=) => { $crate::token::Ne };
795 (|) => { $crate::token::Or };
796 (|=) => { $crate::token::OrEq };
797 (||) => { $crate::token::OrOr };
798 (#) => { $crate::token::Pound };
799 (?) => { $crate::token::Question };
800 (->) => { $crate::token::RArrow };
801 (<-) => { $crate::token::LArrow };
802 (%) => { $crate::token::Rem };
803 (%=) => { $crate::token::RemEq };
804 (=>) => { $crate::token::FatArrow };
805 (;) => { $crate::token::Semi };
806 (<<) => { $crate::token::Shl };
807 (<<=) => { $crate::token::ShlEq };
808 (>>) => { $crate::token::Shr };
809 (>>=) => { $crate::token::ShrEq };
810 (*) => { $crate::token::Star };
811 (-) => { $crate::token::Sub };
812 (-=) => { $crate::token::SubEq };
813 (~) => { $crate::token::Tilde };
814 (_) => { $crate::token::Underscore };
815 }
816 };
817 }
818
819 // Old rustc does not permit `await` appearing anywhere in the source file.
820 // https://github.com/rust-lang/rust/issues/57919
821 // We put the Token![await] rule in a place that is not lexed by old rustc.
822 #[cfg(not(syn_omit_await_from_token_macro))]
823 include!("await.rs"); // export_token_macro![(await)];
824 #[cfg(syn_omit_await_from_token_macro)]
825 export_token_macro![];
826
827 // Not public API.
828 #[doc(hidden)]
829 #[cfg(feature = "parsing")]
830 pub mod parsing {
831 use proc_macro2::{Spacing, Span};
832
833 use crate::buffer::Cursor;
834 use crate::error::{Error, Result};
835 use crate::parse::ParseStream;
836 use crate::span::FromSpans;
837
keyword(input: ParseStream, token: &str) -> Result<Span>838 pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
839 input.step(|cursor| {
840 if let Some((ident, rest)) = cursor.ident() {
841 if ident == token {
842 return Ok((ident.span(), rest));
843 }
844 }
845 Err(cursor.error(format!("expected `{}`", token)))
846 })
847 }
848
peek_keyword(cursor: Cursor, token: &str) -> bool849 pub fn peek_keyword(cursor: Cursor, token: &str) -> bool {
850 if let Some((ident, _rest)) = cursor.ident() {
851 ident == token
852 } else {
853 false
854 }
855 }
856
punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S>857 pub fn punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S> {
858 let mut spans = [input.span(); 3];
859 punct_helper(input, token, &mut spans)?;
860 Ok(S::from_spans(&spans))
861 }
862
punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()>863 fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()> {
864 input.step(|cursor| {
865 let mut cursor = *cursor;
866 assert!(token.len() <= spans.len());
867
868 for (i, ch) in token.chars().enumerate() {
869 match cursor.punct() {
870 Some((punct, rest)) => {
871 spans[i] = punct.span();
872 if punct.as_char() != ch {
873 break;
874 } else if i == token.len() - 1 {
875 return Ok(((), rest));
876 } else if punct.spacing() != Spacing::Joint {
877 break;
878 }
879 cursor = rest;
880 }
881 None => break,
882 }
883 }
884
885 Err(Error::new(spans[0], format!("expected `{}`", token)))
886 })
887 }
888
peek_punct(mut cursor: Cursor, token: &str) -> bool889 pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
890 for (i, ch) in token.chars().enumerate() {
891 match cursor.punct() {
892 Some((punct, rest)) => {
893 if punct.as_char() != ch {
894 break;
895 } else if i == token.len() - 1 {
896 return true;
897 } else if punct.spacing() != Spacing::Joint {
898 break;
899 }
900 cursor = rest;
901 }
902 None => break,
903 }
904 }
905 false
906 }
907 }
908
909 // Not public API.
910 #[doc(hidden)]
911 #[cfg(feature = "printing")]
912 pub mod printing {
913 use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
914 use quote::TokenStreamExt;
915
punct(s: &str, spans: &[Span], tokens: &mut TokenStream)916 pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
917 assert_eq!(s.len(), spans.len());
918
919 let mut chars = s.chars();
920 let mut spans = spans.iter();
921 let ch = chars.next_back().unwrap();
922 let span = spans.next_back().unwrap();
923 for (ch, span) in chars.zip(spans) {
924 let mut op = Punct::new(ch, Spacing::Joint);
925 op.set_span(*span);
926 tokens.append(op);
927 }
928
929 let mut op = Punct::new(ch, Spacing::Alone);
930 op.set_span(*span);
931 tokens.append(op);
932 }
933
keyword(s: &str, span: Span, tokens: &mut TokenStream)934 pub fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
935 tokens.append(Ident::new(s, span));
936 }
937
delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F) where F: FnOnce(&mut TokenStream),938 pub fn delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F)
939 where
940 F: FnOnce(&mut TokenStream),
941 {
942 let delim = match s {
943 "(" => Delimiter::Parenthesis,
944 "[" => Delimiter::Bracket,
945 "{" => Delimiter::Brace,
946 " " => Delimiter::None,
947 _ => panic!("unknown delimiter: {}", s),
948 };
949 let mut inner = TokenStream::new();
950 f(&mut inner);
951 let mut g = Group::new(delim, inner);
952 g.set_span(span);
953 tokens.append(g);
954 }
955 }
956