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