1 //! Tokens representing Rust punctuation, keywords, and delimiters.
3 //! The type names in this module can be difficult to keep straight, so we
4 //! prefer to use the [`Token!`] macro instead. This is a type-macro that
5 //! expands to the token type of the given token.
7 //! [`Token!`]: ../macro.Token.html
11 //! The [`ItemStatic`] syntax tree node is defined like this.
13 //! [`ItemStatic`]: ../struct.ItemStatic.html
16 //! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility};
18 //! pub struct ItemStatic {
19 //! pub attrs: Vec<Attribute>,
20 //! pub vis: Visibility,
21 //! pub static_token: Token![static],
22 //! pub mutability: Option<Token![mut]>,
24 //! pub colon_token: Token![:],
25 //! pub ty: Box<Type>,
26 //! pub eq_token: Token![=],
27 //! pub expr: Box<Expr>,
28 //! pub semi_token: Token![;],
34 //! Keywords and punctuation can be parsed through the [`ParseStream::parse`]
35 //! method. Delimiter tokens are parsed using the [`parenthesized!`],
36 //! [`bracketed!`] and [`braced!`] macros.
38 //! [`ParseStream::parse`]: ../parse/struct.ParseBuffer.html#method.parse
39 //! [`parenthesized!`]: ../macro.parenthesized.html
40 //! [`bracketed!`]: ../macro.bracketed.html
41 //! [`braced!`]: ../macro.braced.html
44 //! use syn::{Attribute, Result};
45 //! use syn::parse::{Parse, ParseStream};
47 //! # enum ItemStatic {}
49 //! // Parse the ItemStatic struct shown above.
50 //! impl Parse for ItemStatic {
51 //! fn parse(input: ParseStream) -> Result<Self> {
52 //! # use syn::ItemStatic;
53 //! # fn parse(input: ParseStream) -> Result<ItemStatic> {
55 //! attrs: input.call(Attribute::parse_outer)?,
56 //! vis: input.parse()?,
57 //! static_token: input.parse()?,
58 //! mutability: input.parse()?,
59 //! ident: input.parse()?,
60 //! colon_token: input.parse()?,
61 //! ty: input.parse()?,
62 //! eq_token: input.parse()?,
63 //! expr: input.parse()?,
64 //! semi_token: input.parse()?,
67 //! # unimplemented!()
73 #[cfg(feature = "extra-traits")]
75 #[cfg(feature = "extra-traits")]
76 use std
::fmt
::{self, Debug}
;
77 #[cfg(feature = "extra-traits")]
78 use std
::hash
::{Hash, Hasher}
;
80 #[cfg(feature = "parsing")]
81 use proc_macro2
::Delimiter
;
82 #[cfg(any(feature = "parsing", feature = "printing"))]
83 use proc_macro2
::Ident
;
84 use proc_macro2
::Span
;
85 #[cfg(feature = "printing")]
86 use proc_macro2
::TokenStream
;
87 #[cfg(feature = "printing")]
88 use quote
::{ToTokens, TokenStreamExt}
;
90 #[cfg(feature = "parsing")]
92 #[cfg(feature = "parsing")]
94 #[cfg(any(feature = "full", feature = "derive"))]
95 #[cfg(feature = "parsing")]
96 use lifetime
::Lifetime
;
97 #[cfg(any(feature = "full", feature = "derive"))]
98 #[cfg(feature = "parsing")]
99 use lit
::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr}
;
100 #[cfg(feature = "parsing")]
102 #[cfg(feature = "parsing")]
103 use parse
::{Parse, ParseStream}
;
106 /// Marker trait for types that represent single tokens.
108 /// This trait is sealed and cannot be implemented for types outside of Syn.
109 #[cfg(feature = "parsing")]
110 pub trait Token
: private
::Sealed
{
113 fn peek(cursor
: Cursor
) -> bool
;
117 fn display() -> &'
static str;
120 #[cfg(feature = "parsing")]
125 #[cfg(feature = "parsing")]
126 impl private
::Sealed
for Ident {}
128 #[cfg(any(feature = "full", feature = "derive"))]
129 #[cfg(feature = "parsing")]
130 fn peek_impl(cursor
: Cursor
, peek
: fn(ParseStream
) -> bool
) -> bool
{
134 let scope
= Span
::call_site();
135 let unexpected
= Rc
::new(Cell
::new(None
));
136 let buffer
= ::private
::new_parse_buffer(scope
, cursor
, unexpected
);
140 #[cfg(any(feature = "full", feature = "derive"))]
141 macro_rules
! impl_token
{
142 ($name
:ident $display
:expr
) => {
143 #[cfg(feature = "parsing")]
144 impl Token
for $name
{
145 fn peek(cursor
: Cursor
) -> bool
{
146 fn peek(input
: ParseStream
) -> bool
{
147 <$name
as Parse
>::parse(input
).is_ok()
149 peek_impl(cursor
, peek
)
152 fn display() -> &'
static str {
157 #[cfg(feature = "parsing")]
158 impl private
::Sealed
for $name {}
162 #[cfg(any(feature = "full", feature = "derive"))]
163 impl_token
!(Lifetime
"lifetime");
164 #[cfg(any(feature = "full", feature = "derive"))]
165 impl_token
!(Lit
"literal");
166 #[cfg(any(feature = "full", feature = "derive"))]
167 impl_token
!(LitStr
"string literal");
168 #[cfg(any(feature = "full", feature = "derive"))]
169 impl_token
!(LitByteStr
"byte string literal");
170 #[cfg(any(feature = "full", feature = "derive"))]
171 impl_token
!(LitByte
"byte literal");
172 #[cfg(any(feature = "full", feature = "derive"))]
173 impl_token
!(LitChar
"character literal");
174 #[cfg(any(feature = "full", feature = "derive"))]
175 impl_token
!(LitInt
"integer literal");
176 #[cfg(any(feature = "full", feature = "derive"))]
177 impl_token
!(LitFloat
"floating point literal");
178 #[cfg(any(feature = "full", feature = "derive"))]
179 impl_token
!(LitBool
"boolean literal");
182 #[cfg(feature = "parsing")]
184 pub trait CustomKeyword
{
185 fn ident() -> &'
static str;
186 fn display() -> &'
static str;
189 #[cfg(feature = "parsing")]
190 impl<K
: CustomKeyword
> private
::Sealed
for K {}
192 #[cfg(feature = "parsing")]
193 impl<K
: CustomKeyword
> Token
for K
{
194 fn peek(cursor
: Cursor
) -> bool
{
195 parsing
::peek_keyword(cursor
, K
::ident())
198 fn display() -> &'
static str {
203 macro_rules
! define_keywords
{
204 ($
($token
:tt
pub struct $name
:ident
#[$doc:meta])*) => {
206 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
209 /// Don't try to remember the name of this type -- use the [`Token!`]
212 /// [`Token!`]: index.html
218 #[allow(non_snake_case)]
219 pub fn $name
<S
: IntoSpans
<[Span
; 1]>>(span
: S
) -> $name
{
221 span
: span
.into_spans()[0],
225 impl std
::default::Default
for $name
{
226 fn default() -> Self {
228 span
: Span
::call_site(),
233 #[cfg(feature = "extra-traits")]
234 impl Debug
for $name
{
235 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
236 f
.write_str(stringify
!($name
))
240 #[cfg(feature = "extra-traits")]
241 impl cmp
::Eq
for $name {}
243 #[cfg(feature = "extra-traits")]
244 impl PartialEq
for $name
{
245 fn eq(&self, _other
: &$name
) -> bool
{
250 #[cfg(feature = "extra-traits")]
251 impl Hash
for $name
{
252 fn hash
<H
: Hasher
>(&self, _state
: &mut H
) {}
255 #[cfg(feature = "printing")]
256 impl ToTokens
for $name
{
257 fn to_tokens(&self, tokens
: &mut TokenStream
) {
258 printing
::keyword($token
, self.span
, tokens
);
262 #[cfg(feature = "parsing")]
263 impl Parse
for $name
{
264 fn parse(input
: ParseStream
) -> Result
<Self> {
266 span
: parsing
::keyword(input
, $token
)?
,
271 #[cfg(feature = "parsing")]
272 impl Token
for $name
{
273 fn peek(cursor
: Cursor
) -> bool
{
274 parsing
::peek_keyword(cursor
, $token
)
277 fn display() -> &'
static str {
278 concat
!("`", $token
, "`")
282 #[cfg(feature = "parsing")]
283 impl private
::Sealed
for $name {}
288 macro_rules
! define_punctuation_structs
{
289 ($
($token
:tt
pub struct $name
:ident
/$len
:tt
#[$doc:meta])*) => {
291 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
294 /// Don't try to remember the name of this type -- use the [`Token!`]
297 /// [`Token!`]: index.html
299 pub spans
: [Span
; $len
],
303 #[allow(non_snake_case)]
304 pub fn $name
<S
: IntoSpans
<[Span
; $len
]>>(spans
: S
) -> $name
{
306 spans
: spans
.into_spans(),
310 impl std
::default::Default
for $name
{
311 fn default() -> Self {
313 spans
: [Span
::call_site(); $len
],
318 #[cfg(feature = "extra-traits")]
319 impl Debug
for $name
{
320 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
321 f
.write_str(stringify
!($name
))
325 #[cfg(feature = "extra-traits")]
326 impl cmp
::Eq
for $name {}
328 #[cfg(feature = "extra-traits")]
329 impl PartialEq
for $name
{
330 fn eq(&self, _other
: &$name
) -> bool
{
335 #[cfg(feature = "extra-traits")]
336 impl Hash
for $name
{
337 fn hash
<H
: Hasher
>(&self, _state
: &mut H
) {}
343 macro_rules
! define_punctuation
{
344 ($
($token
:tt
pub struct $name
:ident
/$len
:tt
#[$doc:meta])*) => {
346 define_punctuation_structs
! {
347 $token
pub struct $name
/$len
#[$doc]
350 #[cfg(feature = "printing")]
351 impl ToTokens
for $name
{
352 fn to_tokens(&self, tokens
: &mut TokenStream
) {
353 printing
::punct($token
, &self.spans
, tokens
);
357 #[cfg(feature = "parsing")]
358 impl Parse
for $name
{
359 fn parse(input
: ParseStream
) -> Result
<Self> {
361 spans
: parsing
::punct(input
, $token
)?
,
366 #[cfg(feature = "parsing")]
367 impl Token
for $name
{
368 fn peek(cursor
: Cursor
) -> bool
{
369 parsing
::peek_punct(cursor
, $token
)
372 fn display() -> &'
static str {
373 concat
!("`", $token
, "`")
377 #[cfg(feature = "parsing")]
378 impl private
::Sealed
for $name {}
383 macro_rules
! define_delimiters
{
384 ($
($token
:tt
pub struct $name
:ident
#[$doc:meta])*) => {
386 #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
393 #[allow(non_snake_case)]
394 pub fn $name
<S
: IntoSpans
<[Span
; 1]>>(span
: S
) -> $name
{
396 span
: span
.into_spans()[0],
400 impl std
::default::Default
for $name
{
401 fn default() -> Self {
403 span
: Span
::call_site(),
408 #[cfg(feature = "extra-traits")]
409 impl Debug
for $name
{
410 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
411 f
.write_str(stringify
!($name
))
415 #[cfg(feature = "extra-traits")]
416 impl cmp
::Eq
for $name {}
418 #[cfg(feature = "extra-traits")]
419 impl PartialEq
for $name
{
420 fn eq(&self, _other
: &$name
) -> bool
{
425 #[cfg(feature = "extra-traits")]
426 impl Hash
for $name
{
427 fn hash
<H
: Hasher
>(&self, _state
: &mut H
) {}
431 #[cfg(feature = "printing")]
432 pub fn surround
<F
>(&self, tokens
: &mut TokenStream
, f
: F
)
434 F
: FnOnce(&mut TokenStream
),
436 printing
::delim($token
, self.span
, tokens
, f
);
440 #[cfg(feature = "parsing")]
441 impl private
::Sealed
for $name {}
446 define_punctuation_structs
! {
447 "_" pub struct Underscore
/1 /// `_`
450 #[cfg(feature = "printing")]
451 impl ToTokens
for Underscore
{
452 fn to_tokens(&self, tokens
: &mut TokenStream
) {
453 tokens
.append(Ident
::new("_", self.spans
[0]));
457 #[cfg(feature = "parsing")]
458 impl Parse
for Underscore
{
459 fn parse(input
: ParseStream
) -> Result
<Self> {
460 input
.step(|cursor
| {
461 if let Some((ident
, rest
)) = cursor
.ident() {
463 return Ok((Underscore(ident
.span()), rest
));
466 if let Some((punct
, rest
)) = cursor
.punct() {
467 if punct
.as_char() == '_'
{
468 return Ok((Underscore(punct
.span()), rest
));
471 Err(cursor
.error("expected `_`"))
476 #[cfg(feature = "parsing")]
477 impl Token
for Underscore
{
478 fn peek(cursor
: Cursor
) -> bool
{
479 if let Some((ident
, _rest
)) = cursor
.ident() {
482 if let Some((punct
, _rest
)) = cursor
.punct() {
483 return punct
.as_char() == '_'
;
488 fn display() -> &'
static str {
493 #[cfg(feature = "parsing")]
494 impl private
::Sealed
for Underscore {}
496 #[cfg(feature = "parsing")]
497 impl Token
for Paren
{
498 fn peek(cursor
: Cursor
) -> bool
{
499 lookahead
::is_delimiter(cursor
, Delimiter
::Parenthesis
)
502 fn display() -> &'
static str {
507 #[cfg(feature = "parsing")]
508 impl Token
for Brace
{
509 fn peek(cursor
: Cursor
) -> bool
{
510 lookahead
::is_delimiter(cursor
, Delimiter
::Brace
)
513 fn display() -> &'
static str {
518 #[cfg(feature = "parsing")]
519 impl Token
for Bracket
{
520 fn peek(cursor
: Cursor
) -> bool
{
521 lookahead
::is_delimiter(cursor
, Delimiter
::Bracket
)
524 fn display() -> &'
static str {
529 #[cfg(feature = "parsing")]
530 impl Token
for Group
{
531 fn peek(cursor
: Cursor
) -> bool
{
532 lookahead
::is_delimiter(cursor
, Delimiter
::None
)
535 fn display() -> &'
static str {
541 "abstract" pub struct Abstract
/// `abstract`
542 "as" pub struct As
/// `as`
543 "async" pub struct Async
/// `async`
544 "auto" pub struct Auto
/// `auto`
545 "become" pub struct Become
/// `become`
546 "box" pub struct Box
/// `box`
547 "break" pub struct Break
/// `break`
548 "const" pub struct Const
/// `const`
549 "continue" pub struct Continue
/// `continue`
550 "crate" pub struct Crate
/// `crate`
551 "default" pub struct Default
/// `default`
552 "do" pub struct Do
/// `do`
553 "dyn" pub struct Dyn
/// `dyn`
554 "else" pub struct Else
/// `else`
555 "enum" pub struct Enum
/// `enum`
556 "existential" pub struct Existential
/// `existential`
557 "extern" pub struct Extern
/// `extern`
558 "final" pub struct Final
/// `final`
559 "fn" pub struct Fn
/// `fn`
560 "for" pub struct For
/// `for`
561 "if" pub struct If
/// `if`
562 "impl" pub struct Impl
/// `impl`
563 "in" pub struct In
/// `in`
564 "let" pub struct Let
/// `let`
565 "loop" pub struct Loop
/// `loop`
566 "macro" pub struct Macro
/// `macro`
567 "match" pub struct Match
/// `match`
568 "mod" pub struct Mod
/// `mod`
569 "move" pub struct Move
/// `move`
570 "mut" pub struct Mut
/// `mut`
571 "override" pub struct Override
/// `override`
572 "priv" pub struct Priv
/// `priv`
573 "pub" pub struct Pub
/// `pub`
574 "ref" pub struct Ref
/// `ref`
575 "return" pub struct Return
/// `return`
576 "Self" pub struct SelfType
/// `Self`
577 "self" pub struct SelfValue
/// `self`
578 "static" pub struct Static
/// `static`
579 "struct" pub struct Struct
/// `struct`
580 "super" pub struct Super
/// `super`
581 "trait" pub struct Trait
/// `trait`
582 "try" pub struct Try
/// `try`
583 "type" pub struct Type
/// `type`
584 "typeof" pub struct Typeof
/// `typeof`
585 "union" pub struct Union
/// `union`
586 "unsafe" pub struct Unsafe
/// `unsafe`
587 "unsized" pub struct Unsized
/// `unsized`
588 "use" pub struct Use
/// `use`
589 "virtual" pub struct Virtual
/// `virtual`
590 "where" pub struct Where
/// `where`
591 "while" pub struct While
/// `while`
592 "yield" pub struct Yield
/// `yield`
595 define_punctuation
! {
596 "+" pub struct Add
/1 /// `+`
597 "+=" pub struct AddEq
/2 /// `+=`
598 "&" pub struct And
/1 /// `&`
599 "&&" pub struct AndAnd
/2 /// `&&`
600 "&=" pub struct AndEq
/2 /// `&=`
601 "@" pub struct At
/1 /// `@`
602 "!" pub struct Bang
/1 /// `!`
603 "^" pub struct Caret
/1 /// `^`
604 "^=" pub struct CaretEq
/2 /// `^=`
605 ":" pub struct Colon
/1 /// `:`
606 "::" pub struct Colon2
/2 /// `::`
607 "," pub struct Comma
/1 /// `,`
608 "/" pub struct Div
/1 /// `/`
609 "/=" pub struct DivEq
/2 /// `/=`
610 "$" pub struct Dollar
/1 /// `$`
611 "." pub struct Dot
/1 /// `.`
612 ".." pub struct Dot2
/2 /// `..`
613 "..." pub struct Dot3
/3 /// `...`
614 "..=" pub struct DotDotEq
/3 /// `..=`
615 "=" pub struct Eq
/1 /// `=`
616 "==" pub struct EqEq
/2 /// `==`
617 ">=" pub struct Ge
/2 /// `>=`
618 ">" pub struct Gt
/1 /// `>`
619 "<=" pub struct Le
/2 /// `<=`
620 "<" pub struct Lt
/1 /// `<`
621 "*=" pub struct MulEq
/2 /// `*=`
622 "!=" pub struct Ne
/2 /// `!=`
623 "|" pub struct Or
/1 /// `|`
624 "|=" pub struct OrEq
/2 /// `|=`
625 "||" pub struct OrOr
/2 /// `||`
626 "#" pub struct Pound
/1 /// `#`
627 "?" pub struct Question
/1 /// `?`
628 "->" pub struct RArrow
/2 /// `->`
629 "<-" pub struct LArrow
/2 /// `<-`
630 "%" pub struct Rem
/1 /// `%`
631 "%=" pub struct RemEq
/2 /// `%=`
632 "=>" pub struct FatArrow
/2 /// `=>`
633 ";" pub struct Semi
/1 /// `;`
634 "<<" pub struct Shl
/2 /// `<<`
635 "<<=" pub struct ShlEq
/3 /// `<<=`
636 ">>" pub struct Shr
/2 /// `>>`
637 ">>=" pub struct ShrEq
/3 /// `>>=`
638 "*" pub struct Star
/1 /// `*`
639 "-" pub struct Sub
/1 /// `-`
640 "-=" pub struct SubEq
/2 /// `-=`
641 "~" pub struct Tilde
/1 /// `~`
645 "{" pub struct Brace /// `{...}`
646 "[" pub struct Bracket /// `[...]`
647 "(" pub struct Paren /// `(...)`
648 " " pub struct Group /// None-delimited group
651 /// A type-macro that expands to the name of the Rust type representation of a
654 /// See the [token module] documentation for details and examples.
656 /// [token module]: token/index.html
657 // Unfortunate duplication due to a rustdoc bug.
658 // https://github.com/rust-lang/rust/issues/45939
660 #[cfg_attr(rustfmt, rustfmt_skip)]
662 (abstract) => { $crate::token::Abstract };
663 (as) => { $crate::token::As };
664 (async) => { $crate::token::Async };
665 (auto) => { $crate::token::Auto };
666 (become) => { $crate::token::Become };
667 (box) => { $crate::token::Box };
668 (break) => { $crate::token::Break };
669 (const) => { $crate::token::Const };
670 (continue) => { $crate::token::Continue };
671 (crate) => { $crate::token::Crate };
672 (default) => { $crate::token::Default };
673 (do) => { $crate::token::Do };
674 (dyn) => { $crate::token::Dyn };
675 (else) => { $crate::token::Else };
676 (enum) => { $crate::token::Enum };
677 (existential) => { $crate::token::Existential };
678 (extern) => { $crate::token::Extern };
679 (final) => { $crate::token::Final };
680 (fn) => { $crate::token::Fn };
681 (for) => { $crate::token::For };
682 (if) => { $crate::token::If };
683 (impl) => { $crate::token::Impl };
684 (in) => { $crate::token::In };
685 (let) => { $crate::token::Let };
686 (loop) => { $crate::token::Loop };
687 (macro) => { $crate::token::Macro };
688 (match) => { $crate::token::Match };
689 (mod) => { $crate::token::Mod };
690 (move) => { $crate::token::Move };
691 (mut) => { $crate::token::Mut };
692 (override) => { $crate::token::Override };
693 (priv) => { $crate::token::Priv };
694 (pub) => { $crate::token::Pub };
695 (ref) => { $crate::token::Ref };
696 (return) => { $crate::token::Return };
697 (Self) => { $crate::token::SelfType };
698 (self) => { $crate::token::SelfValue };
699 (static) => { $crate::token::Static };
700 (struct) => { $crate::token::Struct };
701 (super) => { $crate::token::Super };
702 (trait) => { $crate::token::Trait };
703 (try) => { $crate::token::Try };
704 (type) => { $crate::token::Type };
705 (typeof) => { $crate::token::Typeof };
706 (union) => { $crate::token::Union };
707 (unsafe) => { $crate::token::Unsafe };
708 (unsized) => { $crate::token::Unsized };
709 (use) => { $crate::token::Use };
710 (virtual) => { $crate::token::Virtual };
711 (where) => { $crate::token::Where };
712 (while) => { $crate::token::While };
713 (yield) => { $crate::token::Yield };
714 (+) => { $crate::token::Add };
715 (+=) => { $crate::token::AddEq };
716 (&) => { $crate::token::And };
717 (&&) => { $crate::token::AndAnd };
718 (&=) => { $crate::token::AndEq };
719 (@) => { $crate::token::At };
720 (!) => { $crate::token::Bang };
721 (^) => { $crate::token::Caret };
722 (^=) => { $crate::token::CaretEq };
723 (:) => { $crate::token::Colon };
724 (::) => { $crate::token::Colon2 };
725 (,) => { $crate::token::Comma };
726 (/) => { $crate::token::Div };
727 (/=) => { $crate::token::DivEq };
728 (.) => { $crate::token::Dot };
729 (..) => { $crate::token::Dot2 };
730 (...) => { $crate::token::Dot3 };
731 (..=) => { $crate::token::DotDotEq };
732 (=) => { $crate::token::Eq };
733 (==) => { $crate::token::EqEq };
734 (>=) => { $crate::token::Ge };
735 (>) => { $crate::token::Gt };
736 (<=) => { $crate::token::Le };
737 (<) => { $crate::token::Lt };
738 (*=) => { $crate::token::MulEq };
739 (!=) => { $crate::token::Ne };
740 (|) => { $crate::token::Or };
741 (|=) => { $crate::token::OrEq };
742 (||) => { $crate::token::OrOr };
743 (#) => { $crate::token::Pound };
744 (?) => { $crate::token::Question };
745 (->) => { $crate::token::RArrow };
746 (<-) => { $crate::token::LArrow };
747 (%) => { $crate::token::Rem };
748 (%=) => { $crate::token::RemEq };
749 (=>) => { $crate::token::FatArrow };
750 (;) => { $crate::token::Semi };
751 (<<) => { $crate::token::Shl };
752 (<<=) => { $crate::token::ShlEq };
753 (>>) => { $crate::token::Shr };
754 (>>=) => { $crate::token::ShrEq };
755 (*) => { $crate::token::Star };
756 (-) => { $crate::token::Sub };
757 (-=) => { $crate::token::SubEq };
758 (~) => { $crate::token::Tilde };
759 (_) => { $crate::token::Underscore };
762 // Old names. TODO: remove these re-exports in a breaking change.
763 // https://github.com/dtolnay/syn/issues/486
765 pub use self::SelfType as CapSelf;
767 pub use self::SelfValue as Self_;
769 #[cfg(feature = "parsing
")]
771 use proc_macro2::{Spacing, Span};
774 use error::{Error, Result};
775 use parse::ParseStream;
778 pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
779 input.step(|cursor| {
780 if let Some((ident, rest)) = cursor.ident() {
782 return Ok((ident.span(), rest));
785 Err(cursor.error(format!("expected `{}`
", token)))
789 pub fn peek_keyword(cursor: Cursor, token: &str) -> bool {
790 if let Some((ident, _rest)) = cursor.ident() {
797 pub fn punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S> {
798 let mut spans = [input.cursor().span(); 3];
799 punct_helper(input, token, &mut spans)?;
800 Ok(S::from_spans(&spans))
803 fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()> {
804 input.step(|cursor| {
805 let mut cursor = *cursor;
806 assert!(token.len() <= spans.len());
808 for (i, ch) in token.chars().enumerate() {
809 match cursor.punct() {
810 Some((punct, rest)) => {
811 spans[i] = punct.span();
812 if punct.as_char() != ch {
814 } else if i == token.len() - 1 {
815 return Ok(((), rest));
816 } else if punct.spacing() != Spacing::Joint {
825 Err(Error::new(spans[0], format!("expected `{}`
", token)))
829 pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
830 for (i, ch) in token.chars().enumerate() {
831 match cursor.punct() {
832 Some((punct, rest)) => {
833 if punct.as_char() != ch {
835 } else if i == token.len() - 1 {
837 } else if punct.spacing() != Spacing::Joint {
849 #[cfg(feature = "printing
")]
851 use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
852 use quote::TokenStreamExt;
854 pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
855 assert_eq!(s.len(), spans.len());
857 let mut chars = s.chars();
858 let mut spans = spans.iter();
859 let ch = chars.next_back().unwrap();
860 let span = spans.next_back().unwrap();
861 for (ch, span) in chars.zip(spans) {
862 let mut op = Punct::new(ch, Spacing::Joint);
867 let mut op = Punct::new(ch, Spacing::Alone);
872 pub fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
873 tokens.append(Ident::new(s, span));
876 pub fn delim<F>(s: &str, span: Span, tokens: &mut TokenStream, f: F)
878 F: FnOnce(&mut TokenStream),
880 let delim = match s {
881 "(" => Delimiter::Parenthesis,
882 "[" => Delimiter::Bracket,
883 "{" => Delimiter::Brace,
884 " " => Delimiter::None,
885 _ => panic!("unknown delimiter
: {}
", s),
887 let mut inner = TokenStream::new();
889 let mut g = Group::new(delim, inner);