1use std::borrow::Cow;
2use std::fmt;
3
4pub use LitKind::*;
5pub use NtExprKind::*;
6pub use NtPatKind::*;
7pub use TokenKind::*;
8use rustc_macros::{Decodable, Encodable, HashStable_Generic};
9use rustc_span::edition::Edition;
10use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, kw, sym};
11#[allow(clippy::useless_attribute)] #[allow(hidden_glob_reexports)]
13use rustc_span::{Ident, Symbol};
14
15use crate::ast;
16use crate::util::case::Case;
17
18#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
19pub enum CommentKind {
20 Line,
21 Block,
22}
23
24#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic)]
26pub enum InvisibleOrigin {
27 MetaVar(MetaVarKind),
29
30 ProcMacro,
33}
34
35impl InvisibleOrigin {
36 #[inline]
39 pub fn skip(&self) -> bool {
40 match self {
41 InvisibleOrigin::MetaVar(_) => false,
42 InvisibleOrigin::ProcMacro => true,
43 }
44 }
45}
46
47impl PartialEq for InvisibleOrigin {
48 #[inline]
49 fn eq(&self, _other: &InvisibleOrigin) -> bool {
50 false
58 }
59}
60
61#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
63pub enum MetaVarKind {
64 Item,
65 Block,
66 Stmt,
67 Pat(NtPatKind),
68 Expr {
69 kind: NtExprKind,
70 can_begin_literal_maybe_minus: bool,
72 can_begin_string_literal: bool,
74 },
75 Ty {
76 is_path: bool,
77 },
78 Ident,
79 Lifetime,
80 Literal,
81 Meta {
82 has_meta_form: bool,
84 },
85 Path,
86 Vis,
87 TT,
88}
89
90impl fmt::Display for MetaVarKind {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 let sym = match self {
93 MetaVarKind::Item => sym::item,
94 MetaVarKind::Block => sym::block,
95 MetaVarKind::Stmt => sym::stmt,
96 MetaVarKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
97 MetaVarKind::Pat(PatParam { inferred: false }) => sym::pat_param,
98 MetaVarKind::Expr { kind: Expr2021 { inferred: true } | Expr, .. } => sym::expr,
99 MetaVarKind::Expr { kind: Expr2021 { inferred: false }, .. } => sym::expr_2021,
100 MetaVarKind::Ty { .. } => sym::ty,
101 MetaVarKind::Ident => sym::ident,
102 MetaVarKind::Lifetime => sym::lifetime,
103 MetaVarKind::Literal => sym::literal,
104 MetaVarKind::Meta { .. } => sym::meta,
105 MetaVarKind::Path => sym::path,
106 MetaVarKind::Vis => sym::vis,
107 MetaVarKind::TT => sym::tt,
108 };
109 write!(f, "{sym}")
110 }
111}
112
113#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
117pub enum Delimiter {
118 Parenthesis,
120 Brace,
122 Bracket,
124 Invisible(InvisibleOrigin),
130}
131
132impl Delimiter {
133 #[inline]
137 pub fn skip(&self) -> bool {
138 match self {
139 Delimiter::Parenthesis | Delimiter::Bracket | Delimiter::Brace => false,
140 Delimiter::Invisible(origin) => origin.skip(),
141 }
142 }
143
144 pub fn eq_ignoring_invisible_origin(&self, other: &Delimiter) -> bool {
146 match (self, other) {
147 (Delimiter::Parenthesis, Delimiter::Parenthesis) => true,
148 (Delimiter::Brace, Delimiter::Brace) => true,
149 (Delimiter::Bracket, Delimiter::Bracket) => true,
150 (Delimiter::Invisible(_), Delimiter::Invisible(_)) => true,
151 _ => false,
152 }
153 }
154
155 pub fn as_open_token_kind(&self) -> TokenKind {
156 match *self {
157 Delimiter::Parenthesis => OpenParen,
158 Delimiter::Brace => OpenBrace,
159 Delimiter::Bracket => OpenBracket,
160 Delimiter::Invisible(origin) => OpenInvisible(origin),
161 }
162 }
163
164 pub fn as_close_token_kind(&self) -> TokenKind {
165 match *self {
166 Delimiter::Parenthesis => CloseParen,
167 Delimiter::Brace => CloseBrace,
168 Delimiter::Bracket => CloseBracket,
169 Delimiter::Invisible(origin) => CloseInvisible(origin),
170 }
171 }
172}
173
174#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
179pub enum LitKind {
180 Bool, Byte,
182 Char,
183 Integer, Float, Str,
186 StrRaw(u8), ByteStr,
188 ByteStrRaw(u8), CStr,
190 CStrRaw(u8),
191 Err(ErrorGuaranteed),
192}
193
194#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
196pub struct Lit {
197 pub kind: LitKind,
198 pub symbol: Symbol,
199 pub suffix: Option<Symbol>,
200}
201
202impl Lit {
203 pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
204 Lit { kind, symbol, suffix }
205 }
206
207 pub fn is_semantic_float(&self) -> bool {
210 match self.kind {
211 LitKind::Float => true,
212 LitKind::Integer => match self.suffix {
213 Some(sym) => sym == sym::f32 || sym == sym::f64,
214 None => false,
215 },
216 _ => false,
217 }
218 }
219
220 pub fn from_token(token: &Token) -> Option<Lit> {
223 match token.uninterpolate().kind {
224 Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)),
225 Literal(token_lit) => Some(token_lit),
226 OpenInvisible(InvisibleOrigin::MetaVar(
227 MetaVarKind::Literal | MetaVarKind::Expr { .. },
228 )) => {
229 panic!("from_token metavar");
231 }
232 _ => None,
233 }
234 }
235}
236
237impl fmt::Display for Lit {
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 let Lit { kind, symbol, suffix } = *self;
240 match kind {
241 Byte => write!(f, "b'{symbol}'")?,
242 Char => write!(f, "'{symbol}'")?,
243 Str => write!(f, "\"{symbol}\"")?,
244 StrRaw(n) => write!(
245 f,
246 "r{delim}\"{string}\"{delim}",
247 delim = "#".repeat(n as usize),
248 string = symbol
249 )?,
250 ByteStr => write!(f, "b\"{symbol}\"")?,
251 ByteStrRaw(n) => write!(
252 f,
253 "br{delim}\"{string}\"{delim}",
254 delim = "#".repeat(n as usize),
255 string = symbol
256 )?,
257 CStr => write!(f, "c\"{symbol}\"")?,
258 CStrRaw(n) => {
259 write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize))?
260 }
261 Integer | Float | Bool | Err(_) => write!(f, "{symbol}")?,
262 }
263
264 if let Some(suffix) = suffix {
265 write!(f, "{suffix}")?;
266 }
267
268 Ok(())
269 }
270}
271
272impl LitKind {
273 pub fn article(self) -> &'static str {
275 match self {
276 Integer | Err(_) => "an",
277 _ => "a",
278 }
279 }
280
281 pub fn descr(self) -> &'static str {
282 match self {
283 Bool => "boolean",
284 Byte => "byte",
285 Char => "char",
286 Integer => "integer",
287 Float => "float",
288 Str | StrRaw(..) => "string",
289 ByteStr | ByteStrRaw(..) => "byte string",
290 CStr | CStrRaw(..) => "C string",
291 Err(_) => "error",
292 }
293 }
294
295 pub(crate) fn may_have_suffix(self) -> bool {
296 matches!(self, Integer | Float | Err(_))
297 }
298}
299
300pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool {
301 let ident_token = Token::new(Ident(name, is_raw), span);
302
303 !ident_token.is_reserved_ident()
304 || ident_token.is_path_segment_keyword()
305 || [
306 kw::Async,
307 kw::Do,
308 kw::Box,
309 kw::Break,
310 kw::Const,
311 kw::Continue,
312 kw::False,
313 kw::For,
314 kw::Gen,
315 kw::If,
316 kw::Let,
317 kw::Loop,
318 kw::Match,
319 kw::Move,
320 kw::Return,
321 kw::True,
322 kw::Try,
323 kw::Unsafe,
324 kw::While,
325 kw::Yield,
326 kw::Safe,
327 kw::Static,
328 ]
329 .contains(&name)
330}
331
332fn ident_can_begin_type(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool {
333 let ident_token = Token::new(Ident(name, is_raw), span);
334
335 !ident_token.is_reserved_ident()
336 || ident_token.is_path_segment_keyword()
337 || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn]
338 .contains(&name)
339}
340
341#[derive(PartialEq, Encodable, Decodable, Debug, Copy, Clone, HashStable_Generic)]
342pub enum IdentIsRaw {
343 No,
344 Yes,
345}
346
347impl From<bool> for IdentIsRaw {
348 fn from(b: bool) -> Self {
349 if b { Self::Yes } else { Self::No }
350 }
351}
352
353impl From<IdentIsRaw> for bool {
354 fn from(is_raw: IdentIsRaw) -> bool {
355 matches!(is_raw, IdentIsRaw::Yes)
356 }
357}
358
359#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
360pub enum TokenKind {
361 Eq,
364 Lt,
366 Le,
368 EqEq,
370 Ne,
372 Ge,
374 Gt,
376 AndAnd,
378 OrOr,
380 Bang,
382 Tilde,
384 Plus,
386 Minus,
388 Star,
390 Slash,
392 Percent,
394 Caret,
396 And,
398 Or,
400 Shl,
402 Shr,
404 PlusEq,
406 MinusEq,
408 StarEq,
410 SlashEq,
412 PercentEq,
414 CaretEq,
416 AndEq,
418 OrEq,
420 ShlEq,
422 ShrEq,
424
425 At,
428 Dot,
430 DotDot,
432 DotDotDot,
434 DotDotEq,
436 Comma,
438 Semi,
440 Colon,
442 PathSep,
444 RArrow,
446 LArrow,
448 FatArrow,
450 Pound,
452 Dollar,
454 Question,
456 SingleQuote,
458 OpenParen,
460 CloseParen,
462 OpenBrace,
464 CloseBrace,
466 OpenBracket,
468 CloseBracket,
470 OpenInvisible(InvisibleOrigin),
472 CloseInvisible(InvisibleOrigin),
474
475 Literal(Lit),
477
478 Ident(Symbol, IdentIsRaw),
484 NtIdent(Ident, IdentIsRaw),
488
489 Lifetime(Symbol, IdentIsRaw),
495 NtLifetime(Ident, IdentIsRaw),
499
500 DocComment(CommentKind, ast::AttrStyle, Symbol),
504
505 Eof,
507}
508
509#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
510pub struct Token {
511 pub kind: TokenKind,
512 pub span: Span,
513}
514
515impl TokenKind {
516 pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> TokenKind {
517 Literal(Lit::new(kind, symbol, suffix))
518 }
519
520 pub fn break_two_token_op(&self, n: u32) -> Option<(TokenKind, TokenKind)> {
525 assert!(n == 1 || n == 2);
526 Some(match (self, n) {
527 (Le, 1) => (Lt, Eq),
528 (EqEq, 1) => (Eq, Eq),
529 (Ne, 1) => (Bang, Eq),
530 (Ge, 1) => (Gt, Eq),
531 (AndAnd, 1) => (And, And),
532 (OrOr, 1) => (Or, Or),
533 (Shl, 1) => (Lt, Lt),
534 (Shr, 1) => (Gt, Gt),
535 (PlusEq, 1) => (Plus, Eq),
536 (MinusEq, 1) => (Minus, Eq),
537 (StarEq, 1) => (Star, Eq),
538 (SlashEq, 1) => (Slash, Eq),
539 (PercentEq, 1) => (Percent, Eq),
540 (CaretEq, 1) => (Caret, Eq),
541 (AndEq, 1) => (And, Eq),
542 (OrEq, 1) => (Or, Eq),
543 (ShlEq, 1) => (Lt, Le), (ShlEq, 2) => (Shl, Eq), (ShrEq, 1) => (Gt, Ge), (ShrEq, 2) => (Shr, Eq), (DotDot, 1) => (Dot, Dot),
548 (DotDotDot, 1) => (Dot, DotDot), (DotDotDot, 2) => (DotDot, Dot), (DotDotEq, 2) => (DotDot, Eq),
551 (PathSep, 1) => (Colon, Colon),
552 (RArrow, 1) => (Minus, Gt),
553 (LArrow, 1) => (Lt, Minus),
554 (FatArrow, 1) => (Eq, Gt),
555 _ => return None,
556 })
557 }
558
559 pub fn similar_tokens(&self) -> &[TokenKind] {
562 match self {
563 Comma => &[Dot, Lt, Semi],
564 Semi => &[Colon, Comma],
565 Colon => &[Semi],
566 FatArrow => &[Eq, RArrow, Ge, Gt],
567 _ => &[],
568 }
569 }
570
571 pub fn should_end_const_arg(&self) -> bool {
572 matches!(self, Gt | Ge | Shr | ShrEq)
573 }
574
575 pub fn is_delim(&self) -> bool {
576 self.open_delim().is_some() || self.close_delim().is_some()
577 }
578
579 pub fn open_delim(&self) -> Option<Delimiter> {
580 match *self {
581 OpenParen => Some(Delimiter::Parenthesis),
582 OpenBrace => Some(Delimiter::Brace),
583 OpenBracket => Some(Delimiter::Bracket),
584 OpenInvisible(origin) => Some(Delimiter::Invisible(origin)),
585 _ => None,
586 }
587 }
588
589 pub fn close_delim(&self) -> Option<Delimiter> {
590 match *self {
591 CloseParen => Some(Delimiter::Parenthesis),
592 CloseBrace => Some(Delimiter::Brace),
593 CloseBracket => Some(Delimiter::Bracket),
594 CloseInvisible(origin) => Some(Delimiter::Invisible(origin)),
595 _ => None,
596 }
597 }
598
599 pub fn is_close_delim_or_eof(&self) -> bool {
600 match self {
601 CloseParen | CloseBrace | CloseBracket | CloseInvisible(_) | Eof => true,
602 _ => false,
603 }
604 }
605}
606
607impl Token {
608 pub fn new(kind: TokenKind, span: Span) -> Self {
609 Token { kind, span }
610 }
611
612 pub fn dummy() -> Self {
614 Token::new(TokenKind::Question, DUMMY_SP)
615 }
616
617 pub fn from_ast_ident(ident: Ident) -> Self {
619 Token::new(Ident(ident.name, ident.is_raw_guess().into()), ident.span)
620 }
621
622 pub fn is_range_separator(&self) -> bool {
623 [DotDot, DotDotDot, DotDotEq].contains(&self.kind)
624 }
625
626 pub fn is_punct(&self) -> bool {
627 match self.kind {
628 Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Bang | Tilde | Plus | Minus
629 | Star | Slash | Percent | Caret | And | Or | Shl | Shr | PlusEq | MinusEq | StarEq
630 | SlashEq | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | Dot | DotDot
631 | DotDotDot | DotDotEq | Comma | Semi | Colon | PathSep | RArrow | LArrow
632 | FatArrow | Pound | Dollar | Question | SingleQuote => true,
633
634 OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
635 | OpenInvisible(_) | CloseInvisible(_) | Literal(..) | DocComment(..) | Ident(..)
636 | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Eof => false,
637 }
638 }
639
640 pub fn is_like_plus(&self) -> bool {
641 matches!(self.kind, Plus | PlusEq)
642 }
643
644 pub fn can_begin_expr(&self) -> bool {
649 match self.uninterpolate().kind {
650 Ident(name, is_raw) =>
651 ident_can_begin_expr(name, self.span, is_raw), OpenParen | OpenBrace | OpenBracket | Literal(..) | Bang | Minus | Star | Or | OrOr | And | AndAnd | DotDot | DotDotDot | DotDotEq | Lt | Shl | PathSep | Lifetime(..) | Pound => true, OpenInvisible(InvisibleOrigin::MetaVar(
669 MetaVarKind::Block |
670 MetaVarKind::Expr { .. } |
671 MetaVarKind::Literal |
672 MetaVarKind::Path
673 )) => true,
674 _ => false,
675 }
676 }
677
678 pub fn can_begin_pattern(&self, pat_kind: NtPatKind) -> bool {
682 match &self.uninterpolate().kind {
683 Ident(..) | NtIdent(..) |
685 OpenParen | OpenBracket | And | Minus | AndAnd | Literal(_) | DotDot | DotDotDot | PathSep | Lt | Shl => true, Or => matches!(pat_kind, PatWithOr), OpenInvisible(InvisibleOrigin::MetaVar(
698 MetaVarKind::Expr { .. } |
699 MetaVarKind::Literal |
700 MetaVarKind::Meta { .. } |
701 MetaVarKind::Pat(_) |
702 MetaVarKind::Path |
703 MetaVarKind::Ty { .. }
704 )) => true,
705 _ => false,
706 }
707 }
708
709 pub fn can_begin_type(&self) -> bool {
711 match self.uninterpolate().kind {
712 Ident(name, is_raw) =>
713 ident_can_begin_type(name, self.span, is_raw), OpenParen | OpenBracket | Bang | Star | And | AndAnd | Question | Lifetime(..) | Lt | Shl | PathSep => true, OpenInvisible(InvisibleOrigin::MetaVar(
725 MetaVarKind::Ty { .. } |
726 MetaVarKind::Path
727 )) => true,
728 _ => false,
731 }
732 }
733
734 pub fn can_begin_const_arg(&self) -> bool {
736 match self.kind {
737 OpenBrace | Literal(..) | Minus => true,
738 Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
739 OpenInvisible(InvisibleOrigin::MetaVar(
740 MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal,
741 )) => true,
742 _ => false,
743 }
744 }
745
746 pub fn can_begin_item(&self) -> bool {
748 match self.kind {
749 Ident(name, _) => [
750 kw::Fn,
751 kw::Use,
752 kw::Struct,
753 kw::Enum,
754 kw::Pub,
755 kw::Trait,
756 kw::Extern,
757 kw::Impl,
758 kw::Unsafe,
759 kw::Const,
760 kw::Safe,
761 kw::Static,
762 kw::Union,
763 kw::Macro,
764 kw::Mod,
765 kw::Type,
766 ]
767 .contains(&name),
768 _ => false,
769 }
770 }
771
772 pub fn is_lit(&self) -> bool {
774 matches!(self.kind, Literal(..))
775 }
776
777 pub fn can_begin_literal_maybe_minus(&self) -> bool {
785 match self.uninterpolate().kind {
786 Literal(..) | Minus => true,
787 Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
788 OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) => match mv_kind {
789 MetaVarKind::Literal => true,
790 MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => {
791 can_begin_literal_maybe_minus
792 }
793 _ => false,
794 },
795 _ => false,
796 }
797 }
798
799 pub fn can_begin_string_literal(&self) -> bool {
800 match self.uninterpolate().kind {
801 Literal(..) => true,
802 OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) => match mv_kind {
803 MetaVarKind::Literal => true,
804 MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal,
805 _ => false,
806 },
807 _ => false,
808 }
809 }
810
811 pub fn uninterpolate(&self) -> Cow<'_, Token> {
816 match self.kind {
817 NtIdent(ident, is_raw) => Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)),
818 NtLifetime(ident, is_raw) => {
819 Cow::Owned(Token::new(Lifetime(ident.name, is_raw), ident.span))
820 }
821 _ => Cow::Borrowed(self),
822 }
823 }
824
825 #[inline]
827 pub fn ident(&self) -> Option<(Ident, IdentIsRaw)> {
828 match self.kind {
830 Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
831 NtIdent(ident, is_raw) => Some((ident, is_raw)),
832 _ => None,
833 }
834 }
835
836 #[inline]
838 pub fn lifetime(&self) -> Option<(Ident, IdentIsRaw)> {
839 match self.kind {
841 Lifetime(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
842 NtLifetime(ident, is_raw) => Some((ident, is_raw)),
843 _ => None,
844 }
845 }
846
847 pub fn is_ident(&self) -> bool {
849 self.ident().is_some()
850 }
851
852 pub fn is_lifetime(&self) -> bool {
854 self.lifetime().is_some()
855 }
856
857 pub fn is_ident_named(&self, name: Symbol) -> bool {
860 self.ident().is_some_and(|(ident, _)| ident.name == name)
861 }
862
863 pub fn is_metavar_expr(&self) -> bool {
866 matches!(
867 self.is_metavar_seq(),
868 Some(
869 MetaVarKind::Expr { .. }
870 | MetaVarKind::Literal
871 | MetaVarKind::Path
872 | MetaVarKind::Block
873 )
874 )
875 }
876
877 pub fn is_metavar_block(&self) -> bool {
879 matches!(self.is_metavar_seq(), Some(MetaVarKind::Block))
880 }
881
882 pub fn is_mutability(&self) -> bool {
884 self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)
885 }
886
887 pub fn is_qpath_start(&self) -> bool {
888 self == &Lt || self == &Shl
889 }
890
891 pub fn is_path_start(&self) -> bool {
892 self == &PathSep
893 || self.is_qpath_start()
894 || matches!(self.is_metavar_seq(), Some(MetaVarKind::Path))
895 || self.is_path_segment_keyword()
896 || self.is_non_reserved_ident()
897 }
898
899 pub fn is_keyword(&self, kw: Symbol) -> bool {
901 self.is_non_raw_ident_where(|id| id.name == kw)
902 }
903
904 pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool {
907 self.is_keyword(kw)
908 || (case == Case::Insensitive
909 && self.is_non_raw_ident_where(|id| {
910 id.name.as_str().eq_ignore_ascii_case(kw.as_str())
912 }))
913 }
914
915 pub fn is_path_segment_keyword(&self) -> bool {
916 self.is_non_raw_ident_where(Ident::is_path_segment_keyword)
917 }
918
919 pub fn is_special_ident(&self) -> bool {
922 self.is_non_raw_ident_where(Ident::is_special)
923 }
924
925 pub fn is_used_keyword(&self) -> bool {
927 self.is_non_raw_ident_where(Ident::is_used_keyword)
928 }
929
930 pub fn is_unused_keyword(&self) -> bool {
932 self.is_non_raw_ident_where(Ident::is_unused_keyword)
933 }
934
935 pub fn is_reserved_ident(&self) -> bool {
937 self.is_non_raw_ident_where(Ident::is_reserved)
938 }
939
940 pub fn is_non_reserved_ident(&self) -> bool {
941 self.ident().is_some_and(|(id, raw)| raw == IdentIsRaw::Yes || !Ident::is_reserved(id))
942 }
943
944 pub fn is_bool_lit(&self) -> bool {
946 self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
947 }
948
949 pub fn is_numeric_lit(&self) -> bool {
950 matches!(
951 self.kind,
952 Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. })
953 )
954 }
955
956 pub fn is_integer_lit(&self) -> bool {
958 matches!(self.kind, Literal(Lit { kind: LitKind::Integer, .. }))
959 }
960
961 pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
963 match self.ident() {
964 Some((id, IdentIsRaw::No)) => pred(id),
965 _ => false,
966 }
967 }
968
969 pub fn is_metavar_seq(&self) -> Option<MetaVarKind> {
972 match self.kind {
973 OpenInvisible(InvisibleOrigin::MetaVar(kind)) => Some(kind),
974 _ => None,
975 }
976 }
977
978 pub fn glue(&self, joint: &Token) -> Option<Token> {
979 let kind = match (&self.kind, &joint.kind) {
980 (Eq, Eq) => EqEq,
981 (Eq, Gt) => FatArrow,
982 (Eq, _) => return None,
983
984 (Lt, Eq) => Le,
985 (Lt, Lt) => Shl,
986 (Lt, Le) => ShlEq,
987 (Lt, Minus) => LArrow,
988 (Lt, _) => return None,
989
990 (Gt, Eq) => Ge,
991 (Gt, Gt) => Shr,
992 (Gt, Ge) => ShrEq,
993 (Gt, _) => return None,
994
995 (Bang, Eq) => Ne,
996 (Bang, _) => return None,
997
998 (Plus, Eq) => PlusEq,
999 (Plus, _) => return None,
1000
1001 (Minus, Eq) => MinusEq,
1002 (Minus, Gt) => RArrow,
1003 (Minus, _) => return None,
1004
1005 (Star, Eq) => StarEq,
1006 (Star, _) => return None,
1007
1008 (Slash, Eq) => SlashEq,
1009 (Slash, _) => return None,
1010
1011 (Percent, Eq) => PercentEq,
1012 (Percent, _) => return None,
1013
1014 (Caret, Eq) => CaretEq,
1015 (Caret, _) => return None,
1016
1017 (And, Eq) => AndEq,
1018 (And, And) => AndAnd,
1019 (And, _) => return None,
1020
1021 (Or, Eq) => OrEq,
1022 (Or, Or) => OrOr,
1023 (Or, _) => return None,
1024
1025 (Shl, Eq) => ShlEq,
1026 (Shl, _) => return None,
1027
1028 (Shr, Eq) => ShrEq,
1029 (Shr, _) => return None,
1030
1031 (Dot, Dot) => DotDot,
1032 (Dot, DotDot) => DotDotDot,
1033 (Dot, _) => return None,
1034
1035 (DotDot, Dot) => DotDotDot,
1036 (DotDot, Eq) => DotDotEq,
1037 (DotDot, _) => return None,
1038
1039 (Colon, Colon) => PathSep,
1040 (Colon, _) => return None,
1041
1042 (SingleQuote, Ident(name, is_raw)) => {
1043 Lifetime(Symbol::intern(&format!("'{name}")), *is_raw)
1044 }
1045 (SingleQuote, _) => return None,
1046
1047 (
1048 Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | PlusEq | MinusEq | StarEq | SlashEq
1049 | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | DotDotDot | DotDotEq
1050 | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question
1051 | OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
1052 | OpenInvisible(_) | CloseInvisible(_) | Literal(..) | Ident(..) | NtIdent(..)
1053 | Lifetime(..) | NtLifetime(..) | DocComment(..) | Eof,
1054 _,
1055 ) => {
1056 return None;
1057 }
1058 };
1059
1060 Some(Token::new(kind, self.span.to(joint.span)))
1061 }
1062}
1063
1064impl PartialEq<TokenKind> for Token {
1065 #[inline]
1066 fn eq(&self, rhs: &TokenKind) -> bool {
1067 self.kind == *rhs
1068 }
1069}
1070
1071#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1072pub enum NtPatKind {
1073 PatWithOr,
1075 PatParam { inferred: bool },
1079}
1080
1081#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1082pub enum NtExprKind {
1083 Expr,
1086 Expr2021 { inferred: bool },
1090}
1091
1092#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1094pub enum NonterminalKind {
1095 Item,
1096 Block,
1097 Stmt,
1098 Pat(NtPatKind),
1099 Expr(NtExprKind),
1100 Ty,
1101 Ident,
1102 Lifetime,
1103 Literal,
1104 Meta,
1105 Path,
1106 Vis,
1107 TT,
1108}
1109
1110impl NonterminalKind {
1111 pub fn from_symbol(
1114 symbol: Symbol,
1115 edition: impl FnOnce() -> Edition,
1116 ) -> Option<NonterminalKind> {
1117 Some(match symbol {
1118 sym::item => NonterminalKind::Item,
1119 sym::block => NonterminalKind::Block,
1120 sym::stmt => NonterminalKind::Stmt,
1121 sym::pat => {
1122 if edition().at_least_rust_2021() {
1123 NonterminalKind::Pat(PatWithOr)
1124 } else {
1125 NonterminalKind::Pat(PatParam { inferred: true })
1126 }
1127 }
1128 sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }),
1129 sym::expr => {
1130 if edition().at_least_rust_2024() {
1131 NonterminalKind::Expr(Expr)
1132 } else {
1133 NonterminalKind::Expr(Expr2021 { inferred: true })
1134 }
1135 }
1136 sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }),
1137 sym::ty => NonterminalKind::Ty,
1138 sym::ident => NonterminalKind::Ident,
1139 sym::lifetime => NonterminalKind::Lifetime,
1140 sym::literal => NonterminalKind::Literal,
1141 sym::meta => NonterminalKind::Meta,
1142 sym::path => NonterminalKind::Path,
1143 sym::vis => NonterminalKind::Vis,
1144 sym::tt => NonterminalKind::TT,
1145 _ => return None,
1146 })
1147 }
1148
1149 fn symbol(self) -> Symbol {
1150 match self {
1151 NonterminalKind::Item => sym::item,
1152 NonterminalKind::Block => sym::block,
1153 NonterminalKind::Stmt => sym::stmt,
1154 NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
1155 NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param,
1156 NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr,
1157 NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021,
1158 NonterminalKind::Ty => sym::ty,
1159 NonterminalKind::Ident => sym::ident,
1160 NonterminalKind::Lifetime => sym::lifetime,
1161 NonterminalKind::Literal => sym::literal,
1162 NonterminalKind::Meta => sym::meta,
1163 NonterminalKind::Path => sym::path,
1164 NonterminalKind::Vis => sym::vis,
1165 NonterminalKind::TT => sym::tt,
1166 }
1167 }
1168}
1169
1170impl fmt::Display for NonterminalKind {
1171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1172 write!(f, "{}", self.symbol())
1173 }
1174}
1175
1176#[cfg(target_pointer_width = "64")]
1178mod size_asserts {
1179 use rustc_data_structures::static_assert_size;
1180
1181 use super::*;
1182 static_assert_size!(Lit, 12);
1184 static_assert_size!(LitKind, 2);
1185 static_assert_size!(Token, 24);
1186 static_assert_size!(TokenKind, 16);
1187 }