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 //! ```edition2018
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 //! ```edition2018
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/0.6/quote/trait.ToTokens.html
89 //! [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html
90
91 use std;
92 #[cfg(feature = "extra-traits")]
93 use std::cmp;
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};
99
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};
109
110 use self::private::WithSpan;
111 #[cfg(feature = "parsing")]
112 use buffer::Cursor;
113 #[cfg(feature = "parsing")]
114 use error::Result;
115 #[cfg(any(feature = "full", feature = "derive"))]
116 #[cfg(feature = "parsing")]
117 use lifetime::Lifetime;
118 #[cfg(any(feature = "full", feature = "derive"))]
119 #[cfg(feature = "parsing")]
120 use lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
121 #[cfg(feature = "parsing")]
122 use lookahead;
123 #[cfg(feature = "parsing")]
124 use parse::{Parse, ParseStream};
125 use span::IntoSpans;
126
127 /// Marker trait for types that represent single tokens.
128 ///
129 /// This trait is sealed and cannot be implemented for types outside of Syn.
130 #[cfg(feature = "parsing")]
131 pub trait Token: private::Sealed {
132 // Not public API.
133 #[doc(hidden)]
peek(cursor: Cursor) -> bool134 fn peek(cursor: Cursor) -> bool;
135
136 // Not public API.
137 #[doc(hidden)]
display() -> &'static str138 fn display() -> &'static str;
139 }
140
141 mod private {
142 use proc_macro2::Span;
143
144 #[cfg(feature = "parsing")]
145 pub trait Sealed {}
146
147 /// Support writing `token.span` rather than `token.spans[0]` on tokens that
148 /// hold a single span.
149 #[repr(C)]
150 pub struct WithSpan {
151 pub span: Span,
152 }
153 }
154
155 #[cfg(feature = "parsing")]
156 impl private::Sealed for Ident {}
157
158 #[cfg(any(feature = "full", feature = "derive"))]
159 #[cfg(feature = "parsing")]
peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool160 fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
161 use std::cell::Cell;
162 use std::rc::Rc;
163
164 let scope = Span::call_site();
165 let unexpected = Rc::new(Cell::new(None));
166 let buffer = ::private::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 [`Token!`]
240 /// macro instead.
241 ///
242 /// [`Token!`]: index.html
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 [`Token!`]
346 /// macro instead.
347 ///
348 /// [`Token!`]: index.html
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 "become" pub struct Become /// `become`
599 "box" pub struct Box /// `box`
600 "break" pub struct Break /// `break`
601 "const" pub struct Const /// `const`
602 "continue" pub struct Continue /// `continue`
603 "crate" pub struct Crate /// `crate`
604 "default" pub struct Default /// `default`
605 "do" pub struct Do /// `do`
606 "dyn" pub struct Dyn /// `dyn`
607 "else" pub struct Else /// `else`
608 "enum" pub struct Enum /// `enum`
609 "existential" pub struct Existential /// `existential`
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 ($($dollar: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]: token/index.html
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 (become) => { $crate::token::Become };
721 (box) => { $crate::token::Box };
722 (break) => { $crate::token::Break };
723 (const) => { $crate::token::Const };
724 (continue) => { $crate::token::Continue };
725 (crate) => { $crate::token::Crate };
726 (default) => { $crate::token::Default };
727 (do) => { $crate::token::Do };
728 (dyn) => { $crate::token::Dyn };
729 (else) => { $crate::token::Else };
730 (enum) => { $crate::token::Enum };
731 (existential) => { $crate::token::Existential };
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::Dot };
783 (..) => { $crate::token::Dot2 };
784 (...) => { $crate::token::Dot3 };
785 (..=) => { $crate::token::DotDotEq };
786 (=) => { $crate::token::Eq };
787 (==) => { $crate::token::EqEq };
788 (>=) => { $crate::token::Ge };
789 (>) => { $crate::token::Gt };
790 (<=) => { $crate::token::Le };
791 (<) => { $crate::token::Lt };
792 (*=) => { $crate::token::MulEq };
793 (!=) => { $crate::token::Ne };
794 (|) => { $crate::token::Or };
795 (|=) => { $crate::token::OrEq };
796 (||) => { $crate::token::OrOr };
797 (#) => { $crate::token::Pound };
798 (?) => { $crate::token::Question };
799 (->) => { $crate::token::RArrow };
800 (<-) => { $crate::token::LArrow };
801 (%) => { $crate::token::Rem };
802 (%=) => { $crate::token::RemEq };
803 (=>) => { $crate::token::FatArrow };
804 (;) => { $crate::token::Semi };
805 (<<) => { $crate::token::Shl };
806 (<<=) => { $crate::token::ShlEq };
807 (>>) => { $crate::token::Shr };
808 (>>=) => { $crate::token::ShrEq };
809 (*) => { $crate::token::Star };
810 (-) => { $crate::token::Sub };
811 (-=) => { $crate::token::SubEq };
812 (~) => { $crate::token::Tilde };
813 (_) => { $crate::token::Underscore };
814 $($dollar => { $crate::token::Dollar };)*
815 }
816 };
817 }
818
819 #[cfg(syn_can_match_trailing_dollar)]
820 export_token_macro![($)];
821
822 // Old rustc does not support ($) => {...} as a macro rule.
823 #[cfg(not(syn_can_match_trailing_dollar))]
824 export_token_macro![];
825
826 // Old names. TODO: remove these re-exports in a breaking change.
827 // https://github.com/dtolnay/syn/issues/486
828 #[doc(hidden)]
829 pub use self::SelfType as CapSelf;
830 #[doc(hidden)]
831 pub use self::SelfValue as Self_;
832
833 // Not public API.
834 #[doc(hidden)]
835 #[cfg(feature = "parsing")]
836 pub mod parsing {
837 use proc_macro2::{Spacing, Span};
838
839 use buffer::Cursor;
840 use error::{Error, Result};
841 use parse::ParseStream;
842 use span::FromSpans;
843
keyword(input: ParseStream, token: &str) -> Result<Span>844 pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
845 input.step(|cursor| {
846 if let Some((ident, rest)) = cursor.ident() {
847 if ident == token {
848 return Ok((ident.span(), rest));
849 }
850 }
851 Err(cursor.error(format!("expected `{}`", token)))
852 })
853 }
854
peek_keyword(cursor: Cursor, token: &str) -> bool855 pub fn peek_keyword(cursor: Cursor, token: &str) -> bool {
856 if let Some((ident, _rest)) = cursor.ident() {
857 ident == token
858 } else {
859 false
860 }
861 }
862
punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S>863 pub fn punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S> {
864 let mut spans = [input.cursor().span(); 3];
865 punct_helper(input, token, &mut spans)?;
866 Ok(S::from_spans(&spans))
867 }
868
punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()>869 fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()> {
870 input.step(|cursor| {
871 let mut cursor = *cursor;
872 assert!(token.len() <= spans.len());
873
874 for (i, ch) in token.chars().enumerate() {
875 match cursor.punct() {
876 Some((punct, rest)) => {
877 spans[i] = punct.span();
878 if punct.as_char() != ch {
879 break;
880 } else if i == token.len() - 1 {
881 return Ok(((), rest));
882 } else if punct.spacing() != Spacing::Joint {
883 break;
884 }
885 cursor = rest;
886 }
887 None => break,
888 }
889 }
890
891 Err(Error::new(spans[0], format!("expected `{}`", token)))
892 })
893 }
894
peek_punct(mut cursor: Cursor, token: &str) -> bool895 pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
896 for (i, ch) in token.chars().enumerate() {
897 match cursor.punct() {
898 Some((punct, rest)) => {
899 if punct.as_char() != ch {
900 break;
901 } else if i == token.len() - 1 {
902 return true;
903 } else if punct.spacing() != Spacing::Joint {
904 break;
905 }
906 cursor = rest;
907 }
908 None => break,
909 }
910 }
911 false
912 }
913 }
914
915 // Not public API.
916 #[doc(hidden)]
917 #[cfg(feature = "printing")]
918 pub mod printing {
919 use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
920 use quote::TokenStreamExt;
921
punct(s: &str, spans: &[Span], tokens: &mut TokenStream)922 pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
923 assert_eq!(s.len(), spans.len());
924
925 let mut chars = s.chars();
926 let mut spans = spans.iter();
927 let ch = chars.next_back().unwrap();
928 let span = spans.next_back().unwrap();
929 for (ch, span) in chars.zip(spans) {
930 let mut op = Punct::new(ch, Spacing::Joint);
931 op.set_span(*span);
932 tokens.append(op);
933 }
934
935 let mut op = Punct::new(ch, Spacing::Alone);
936 op.set_span(*span);
937 tokens.append(op);
938 }
939
keyword(s: &str, span: Span, tokens: &mut TokenStream)940 pub fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
941 tokens.append(Ident::new(s, span));
942 }
943
delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F) where F: FnOnce(&mut TokenStream),944 pub fn delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F)
945 where
946 F: FnOnce(&mut TokenStream),
947 {
948 let delim = match s {
949 "(" => Delimiter::Parenthesis,
950 "[" => Delimiter::Bracket,
951 "{" => Delimiter::Brace,
952 " " => Delimiter::None,
953 _ => panic!("unknown delimiter: {}", s),
954 };
955 let mut inner = TokenStream::new();
956 f(&mut inner);
957 let mut g = Group::new(delim, inner);
958 g.set_span(span);
959 tokens.append(g);
960 }
961 }
962