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