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, Debug, Encodable, Decodable, HashStable_Generic)]
27pub enum InvisibleOrigin {
28 MetaVar(MetaVarKind),
30
31 ProcMacro,
34}
35
36impl InvisibleOrigin {
37 #[inline]
40 pub fn skip(&self) -> bool {
41 match self {
42 InvisibleOrigin::MetaVar(_) => false,
43 InvisibleOrigin::ProcMacro => true,
44 }
45 }
46}
47
48impl PartialEq for InvisibleOrigin {
49 #[inline]
50 fn eq(&self, _other: &InvisibleOrigin) -> bool {
51 false
59 }
60}
61
62#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
64pub enum MetaVarKind {
65 Item,
66 Block,
67 Stmt,
68 Pat(NtPatKind),
69 Expr {
70 kind: NtExprKind,
71 can_begin_literal_maybe_minus: bool,
73 can_begin_string_literal: bool,
75 },
76 Ty {
77 is_path: bool,
78 },
79 Ident,
80 Lifetime,
81 Literal,
82 Meta {
83 has_meta_form: bool,
85 },
86 Path,
87 Vis,
88 TT,
89}
90
91impl fmt::Display for MetaVarKind {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 let sym = match self {
94 MetaVarKind::Item => sym::item,
95 MetaVarKind::Block => sym::block,
96 MetaVarKind::Stmt => sym::stmt,
97 MetaVarKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
98 MetaVarKind::Pat(PatParam { inferred: false }) => sym::pat_param,
99 MetaVarKind::Expr { kind: Expr2021 { inferred: true } | Expr, .. } => sym::expr,
100 MetaVarKind::Expr { kind: Expr2021 { inferred: false }, .. } => sym::expr_2021,
101 MetaVarKind::Ty { .. } => sym::ty,
102 MetaVarKind::Ident => sym::ident,
103 MetaVarKind::Lifetime => sym::lifetime,
104 MetaVarKind::Literal => sym::literal,
105 MetaVarKind::Meta { .. } => sym::meta,
106 MetaVarKind::Path => sym::path,
107 MetaVarKind::Vis => sym::vis,
108 MetaVarKind::TT => sym::tt,
109 };
110 write!(f, "{sym}")
111 }
112}
113
114#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
118pub enum Delimiter {
119 Parenthesis,
121 Brace,
123 Bracket,
125 Invisible(InvisibleOrigin),
131}
132
133impl Delimiter {
134 #[inline]
138 pub fn skip(&self) -> bool {
139 match self {
140 Delimiter::Parenthesis | Delimiter::Bracket | Delimiter::Brace => false,
141 Delimiter::Invisible(origin) => origin.skip(),
142 }
143 }
144
145 pub fn eq_ignoring_invisible_origin(&self, other: &Delimiter) -> bool {
147 match (self, other) {
148 (Delimiter::Parenthesis, Delimiter::Parenthesis) => true,
149 (Delimiter::Brace, Delimiter::Brace) => true,
150 (Delimiter::Bracket, Delimiter::Bracket) => true,
151 (Delimiter::Invisible(_), Delimiter::Invisible(_)) => true,
152 _ => false,
153 }
154 }
155
156 pub fn as_open_token_kind(&self) -> TokenKind {
157 match *self {
158 Delimiter::Parenthesis => OpenParen,
159 Delimiter::Brace => OpenBrace,
160 Delimiter::Bracket => OpenBracket,
161 Delimiter::Invisible(origin) => OpenInvisible(origin),
162 }
163 }
164
165 pub fn as_close_token_kind(&self) -> TokenKind {
166 match *self {
167 Delimiter::Parenthesis => CloseParen,
168 Delimiter::Brace => CloseBrace,
169 Delimiter::Bracket => CloseBracket,
170 Delimiter::Invisible(origin) => CloseInvisible(origin),
171 }
172 }
173}
174
175#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
180pub enum LitKind {
181 Bool, Byte,
183 Char,
184 Integer, Float, Str,
187 StrRaw(u8), ByteStr,
189 ByteStrRaw(u8), CStr,
191 CStrRaw(u8),
192 Err(ErrorGuaranteed),
193}
194
195#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
197pub struct Lit {
198 pub kind: LitKind,
199 pub symbol: Symbol,
200 pub suffix: Option<Symbol>,
201}
202
203impl Lit {
204 pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
205 Lit { kind, symbol, suffix }
206 }
207
208 pub fn is_semantic_float(&self) -> bool {
211 match self.kind {
212 LitKind::Float => true,
213 LitKind::Integer => match self.suffix {
214 Some(sym) => sym == sym::f32 || sym == sym::f64,
215 None => false,
216 },
217 _ => false,
218 }
219 }
220
221 pub fn from_token(token: &Token) -> Option<Lit> {
224 match token.uninterpolate().kind {
225 Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)),
226 Literal(token_lit) => Some(token_lit),
227 OpenInvisible(InvisibleOrigin::MetaVar(
228 MetaVarKind::Literal | MetaVarKind::Expr { .. },
229 )) => {
230 panic!("from_token metavar");
232 }
233 _ => None,
234 }
235 }
236}
237
238impl fmt::Display for Lit {
239 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240 let Lit { kind, symbol, suffix } = *self;
241 match kind {
242 Byte => write!(f, "b'{symbol}'")?,
243 Char => write!(f, "'{symbol}'")?,
244 Str => write!(f, "\"{symbol}\"")?,
245 StrRaw(n) => write!(
246 f,
247 "r{delim}\"{string}\"{delim}",
248 delim = "#".repeat(n as usize),
249 string = symbol
250 )?,
251 ByteStr => write!(f, "b\"{symbol}\"")?,
252 ByteStrRaw(n) => write!(
253 f,
254 "br{delim}\"{string}\"{delim}",
255 delim = "#".repeat(n as usize),
256 string = symbol
257 )?,
258 CStr => write!(f, "c\"{symbol}\"")?,
259 CStrRaw(n) => {
260 write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize))?
261 }
262 Integer | Float | Bool | Err(_) => write!(f, "{symbol}")?,
263 }
264
265 if let Some(suffix) = suffix {
266 write!(f, "{suffix}")?;
267 }
268
269 Ok(())
270 }
271}
272
273impl LitKind {
274 pub fn article(self) -> &'static str {
276 match self {
277 Integer | Err(_) => "an",
278 _ => "a",
279 }
280 }
281
282 pub fn descr(self) -> &'static str {
283 match self {
284 Bool => "boolean",
285 Byte => "byte",
286 Char => "char",
287 Integer => "integer",
288 Float => "float",
289 Str | StrRaw(..) => "string",
290 ByteStr | ByteStrRaw(..) => "byte string",
291 CStr | CStrRaw(..) => "C string",
292 Err(_) => "error",
293 }
294 }
295
296 pub(crate) fn may_have_suffix(self) -> bool {
297 matches!(self, Integer | Float | Err(_))
298 }
299}
300
301pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool {
302 let ident_token = Token::new(Ident(name, is_raw), span);
303
304 !ident_token.is_reserved_ident()
305 || ident_token.is_path_segment_keyword()
306 || [
307 kw::Async,
308 kw::Do,
309 kw::Box,
310 kw::Break,
311 kw::Const,
312 kw::Continue,
313 kw::False,
314 kw::For,
315 kw::Gen,
316 kw::If,
317 kw::Let,
318 kw::Loop,
319 kw::Match,
320 kw::Move,
321 kw::Return,
322 kw::True,
323 kw::Try,
324 kw::Unsafe,
325 kw::While,
326 kw::Yield,
327 kw::Safe,
328 kw::Static,
329 ]
330 .contains(&name)
331}
332
333fn ident_can_begin_type(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool {
334 let ident_token = Token::new(Ident(name, is_raw), span);
335
336 !ident_token.is_reserved_ident()
337 || ident_token.is_path_segment_keyword()
338 || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn]
339 .contains(&name)
340}
341
342#[derive(PartialEq, Encodable, Decodable, Debug, Copy, Clone, HashStable_Generic)]
343pub enum IdentIsRaw {
344 No,
345 Yes,
346}
347
348impl IdentIsRaw {
349 pub fn to_print_mode_ident(self) -> IdentPrintMode {
350 match self {
351 IdentIsRaw::No => IdentPrintMode::Normal,
352 IdentIsRaw::Yes => IdentPrintMode::RawIdent,
353 }
354 }
355 pub fn to_print_mode_lifetime(self) -> IdentPrintMode {
356 match self {
357 IdentIsRaw::No => IdentPrintMode::Normal,
358 IdentIsRaw::Yes => IdentPrintMode::RawLifetime,
359 }
360 }
361}
362
363impl From<bool> for IdentIsRaw {
364 fn from(b: bool) -> Self {
365 if b { Self::Yes } else { Self::No }
366 }
367}
368
369#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
370pub enum TokenKind {
371 Eq,
374 Lt,
376 Le,
378 EqEq,
380 Ne,
382 Ge,
384 Gt,
386 AndAnd,
388 OrOr,
390 Bang,
392 Tilde,
394 Plus,
396 Minus,
398 Star,
400 Slash,
402 Percent,
404 Caret,
406 And,
408 Or,
410 Shl,
412 Shr,
414 PlusEq,
416 MinusEq,
418 StarEq,
420 SlashEq,
422 PercentEq,
424 CaretEq,
426 AndEq,
428 OrEq,
430 ShlEq,
432 ShrEq,
434
435 At,
438 Dot,
440 DotDot,
442 DotDotDot,
444 DotDotEq,
446 Comma,
448 Semi,
450 Colon,
452 PathSep,
454 RArrow,
456 LArrow,
458 FatArrow,
460 Pound,
462 Dollar,
464 Question,
466 SingleQuote,
468 OpenParen,
470 CloseParen,
472 OpenBrace,
474 CloseBrace,
476 OpenBracket,
478 CloseBracket,
480 OpenInvisible(InvisibleOrigin),
482 CloseInvisible(InvisibleOrigin),
484
485 Literal(Lit),
487
488 Ident(Symbol, IdentIsRaw),
494 NtIdent(Ident, IdentIsRaw),
498
499 Lifetime(Symbol, IdentIsRaw),
505 NtLifetime(Ident, IdentIsRaw),
509
510 DocComment(CommentKind, ast::AttrStyle, Symbol),
514
515 Eof,
517}
518
519#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
520pub struct Token {
521 pub kind: TokenKind,
522 pub span: Span,
523}
524
525impl TokenKind {
526 pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> TokenKind {
527 Literal(Lit::new(kind, symbol, suffix))
528 }
529
530 pub fn break_two_token_op(&self, n: u32) -> Option<(TokenKind, TokenKind)> {
535 assert!(n == 1 || n == 2);
536 Some(match (self, n) {
537 (Le, 1) => (Lt, Eq),
538 (EqEq, 1) => (Eq, Eq),
539 (Ne, 1) => (Bang, Eq),
540 (Ge, 1) => (Gt, Eq),
541 (AndAnd, 1) => (And, And),
542 (OrOr, 1) => (Or, Or),
543 (Shl, 1) => (Lt, Lt),
544 (Shr, 1) => (Gt, Gt),
545 (PlusEq, 1) => (Plus, Eq),
546 (MinusEq, 1) => (Minus, Eq),
547 (StarEq, 1) => (Star, Eq),
548 (SlashEq, 1) => (Slash, Eq),
549 (PercentEq, 1) => (Percent, Eq),
550 (CaretEq, 1) => (Caret, Eq),
551 (AndEq, 1) => (And, Eq),
552 (OrEq, 1) => (Or, Eq),
553 (ShlEq, 1) => (Lt, Le), (ShlEq, 2) => (Shl, Eq), (ShrEq, 1) => (Gt, Ge), (ShrEq, 2) => (Shr, Eq), (DotDot, 1) => (Dot, Dot),
558 (DotDotDot, 1) => (Dot, DotDot), (DotDotDot, 2) => (DotDot, Dot), (DotDotEq, 2) => (DotDot, Eq),
561 (PathSep, 1) => (Colon, Colon),
562 (RArrow, 1) => (Minus, Gt),
563 (LArrow, 1) => (Lt, Minus),
564 (FatArrow, 1) => (Eq, Gt),
565 _ => return None,
566 })
567 }
568
569 pub fn similar_tokens(&self) -> &[TokenKind] {
572 match self {
573 Comma => &[Dot, Lt, Semi],
574 Semi => &[Colon, Comma],
575 Colon => &[Semi],
576 FatArrow => &[Eq, RArrow, Ge, Gt],
577 _ => &[],
578 }
579 }
580
581 pub fn should_end_const_arg(&self) -> bool {
582 matches!(self, Gt | Ge | Shr | ShrEq)
583 }
584
585 pub fn is_delim(&self) -> bool {
586 self.open_delim().is_some() || self.close_delim().is_some()
587 }
588
589 pub fn open_delim(&self) -> Option<Delimiter> {
590 match *self {
591 OpenParen => Some(Delimiter::Parenthesis),
592 OpenBrace => Some(Delimiter::Brace),
593 OpenBracket => Some(Delimiter::Bracket),
594 OpenInvisible(origin) => Some(Delimiter::Invisible(origin)),
595 _ => None,
596 }
597 }
598
599 pub fn close_delim(&self) -> Option<Delimiter> {
600 match *self {
601 CloseParen => Some(Delimiter::Parenthesis),
602 CloseBrace => Some(Delimiter::Brace),
603 CloseBracket => Some(Delimiter::Bracket),
604 CloseInvisible(origin) => Some(Delimiter::Invisible(origin)),
605 _ => None,
606 }
607 }
608
609 pub fn is_close_delim_or_eof(&self) -> bool {
610 match self {
611 CloseParen | CloseBrace | CloseBracket | CloseInvisible(_) | Eof => true,
612 _ => false,
613 }
614 }
615}
616
617impl Token {
618 pub fn new(kind: TokenKind, span: Span) -> Self {
619 Token { kind, span }
620 }
621
622 pub fn dummy() -> Self {
624 Token::new(TokenKind::Question, DUMMY_SP)
625 }
626
627 pub fn from_ast_ident(ident: Ident) -> Self {
629 Token::new(Ident(ident.name, ident.is_raw_guess().into()), ident.span)
630 }
631
632 pub fn is_range_separator(&self) -> bool {
633 [DotDot, DotDotDot, DotDotEq].contains(&self.kind)
634 }
635
636 pub fn is_punct(&self) -> bool {
637 match self.kind {
638 Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Bang | Tilde | Plus | Minus
639 | Star | Slash | Percent | Caret | And | Or | Shl | Shr | PlusEq | MinusEq | StarEq
640 | SlashEq | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | Dot | DotDot
641 | DotDotDot | DotDotEq | Comma | Semi | Colon | PathSep | RArrow | LArrow
642 | FatArrow | Pound | Dollar | Question | SingleQuote => true,
643
644 OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
645 | OpenInvisible(_) | CloseInvisible(_) | Literal(..) | DocComment(..) | Ident(..)
646 | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Eof => false,
647 }
648 }
649
650 pub fn is_like_plus(&self) -> bool {
651 matches!(self.kind, Plus | PlusEq)
652 }
653
654 pub fn can_begin_expr(&self) -> bool {
659 match self.uninterpolate().kind {
660 Ident(name, is_raw) =>
661 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(
679 MetaVarKind::Block |
680 MetaVarKind::Expr { .. } |
681 MetaVarKind::Literal |
682 MetaVarKind::Path
683 )) => true,
684 _ => false,
685 }
686 }
687
688 pub fn can_begin_pattern(&self, pat_kind: NtPatKind) -> bool {
692 match &self.uninterpolate().kind {
693 Ident(..) | NtIdent(..) |
695 OpenParen | OpenBracket | And | Minus | AndAnd | Literal(_) | DotDot | DotDotDot | PathSep | Lt | Shl => true, Or => matches!(pat_kind, PatWithOr), OpenInvisible(InvisibleOrigin::MetaVar(
708 MetaVarKind::Expr { .. } |
709 MetaVarKind::Literal |
710 MetaVarKind::Meta { .. } |
711 MetaVarKind::Pat(_) |
712 MetaVarKind::Path |
713 MetaVarKind::Ty { .. }
714 )) => true,
715 _ => false,
716 }
717 }
718
719 pub fn can_begin_type(&self) -> bool {
721 match self.uninterpolate().kind {
722 Ident(name, is_raw) =>
723 ident_can_begin_type(name, self.span, is_raw), OpenParen | OpenBracket | Bang | Star | And | AndAnd | Question | Lifetime(..) | Lt | Shl | PathSep => true, OpenInvisible(InvisibleOrigin::MetaVar(
735 MetaVarKind::Ty { .. } |
736 MetaVarKind::Path
737 )) => true,
738 _ => false,
741 }
742 }
743
744 pub fn can_begin_const_arg(&self) -> bool {
746 match self.kind {
747 OpenBrace | Literal(..) | Minus => true,
748 Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
749 OpenInvisible(InvisibleOrigin::MetaVar(
750 MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal,
751 )) => true,
752 _ => false,
753 }
754 }
755
756 pub fn can_begin_item(&self) -> bool {
758 match self.kind {
759 Ident(name, _) => [
760 kw::Fn,
761 kw::Use,
762 kw::Struct,
763 kw::Enum,
764 kw::Pub,
765 kw::Trait,
766 kw::Extern,
767 kw::Impl,
768 kw::Unsafe,
769 kw::Const,
770 kw::Safe,
771 kw::Static,
772 kw::Union,
773 kw::Macro,
774 kw::Mod,
775 kw::Type,
776 ]
777 .contains(&name),
778 _ => false,
779 }
780 }
781
782 pub fn is_lit(&self) -> bool {
784 matches!(self.kind, Literal(..))
785 }
786
787 pub fn can_begin_literal_maybe_minus(&self) -> bool {
795 match self.uninterpolate().kind {
796 Literal(..) | Minus => true,
797 Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
798 OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) => match mv_kind {
799 MetaVarKind::Literal => true,
800 MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => {
801 can_begin_literal_maybe_minus
802 }
803 _ => false,
804 },
805 _ => false,
806 }
807 }
808
809 pub fn can_begin_string_literal(&self) -> bool {
810 match self.uninterpolate().kind {
811 Literal(..) => true,
812 OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) => match mv_kind {
813 MetaVarKind::Literal => true,
814 MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal,
815 _ => false,
816 },
817 _ => false,
818 }
819 }
820
821 pub fn uninterpolate(&self) -> Cow<'_, Token> {
826 match self.kind {
827 NtIdent(ident, is_raw) => Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)),
828 NtLifetime(ident, is_raw) => {
829 Cow::Owned(Token::new(Lifetime(ident.name, is_raw), ident.span))
830 }
831 _ => Cow::Borrowed(self),
832 }
833 }
834
835 #[inline]
837 pub fn ident(&self) -> Option<(Ident, IdentIsRaw)> {
838 match self.kind {
840 Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
841 NtIdent(ident, is_raw) => Some((ident, is_raw)),
842 _ => None,
843 }
844 }
845
846 #[inline]
848 pub fn lifetime(&self) -> Option<(Ident, IdentIsRaw)> {
849 match self.kind {
851 Lifetime(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
852 NtLifetime(ident, is_raw) => Some((ident, is_raw)),
853 _ => None,
854 }
855 }
856
857 pub fn is_ident(&self) -> bool {
859 self.ident().is_some()
860 }
861
862 pub fn is_lifetime(&self) -> bool {
864 self.lifetime().is_some()
865 }
866
867 pub fn is_ident_named(&self, name: Symbol) -> bool {
870 self.ident().is_some_and(|(ident, _)| ident.name == name)
871 }
872
873 pub fn is_metavar_expr(&self) -> bool {
876 matches!(
877 self.is_metavar_seq(),
878 Some(
879 MetaVarKind::Expr { .. }
880 | MetaVarKind::Literal
881 | MetaVarKind::Path
882 | MetaVarKind::Block
883 )
884 )
885 }
886
887 pub fn is_metavar_block(&self) -> bool {
889 matches!(self.is_metavar_seq(), Some(MetaVarKind::Block))
890 }
891
892 pub fn is_mutability(&self) -> bool {
894 self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)
895 }
896
897 pub fn is_qpath_start(&self) -> bool {
898 self == &Lt || self == &Shl
899 }
900
901 pub fn is_path_start(&self) -> bool {
902 self == &PathSep
903 || self.is_qpath_start()
904 || matches!(self.is_metavar_seq(), Some(MetaVarKind::Path))
905 || self.is_path_segment_keyword()
906 || self.is_non_reserved_ident()
907 }
908
909 pub fn is_keyword(&self, kw: Symbol) -> bool {
911 self.is_non_raw_ident_where(|id| id.name == kw)
912 }
913
914 pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool {
917 self.is_keyword(kw)
918 || (case == Case::Insensitive
919 && self.is_non_raw_ident_where(|id| {
920 id.name.as_str().eq_ignore_ascii_case(kw.as_str())
922 }))
923 }
924
925 pub fn is_path_segment_keyword(&self) -> bool {
926 self.is_non_raw_ident_where(Ident::is_path_segment_keyword)
927 }
928
929 pub fn is_special_ident(&self) -> bool {
932 self.is_non_raw_ident_where(Ident::is_special)
933 }
934
935 pub fn is_used_keyword(&self) -> bool {
937 self.is_non_raw_ident_where(Ident::is_used_keyword)
938 }
939
940 pub fn is_unused_keyword(&self) -> bool {
942 self.is_non_raw_ident_where(Ident::is_unused_keyword)
943 }
944
945 pub fn is_reserved_ident(&self) -> bool {
947 self.is_non_raw_ident_where(Ident::is_reserved)
948 }
949
950 pub fn is_non_reserved_ident(&self) -> bool {
951 self.ident().is_some_and(|(id, raw)| raw == IdentIsRaw::Yes || !Ident::is_reserved(id))
952 }
953
954 pub fn is_bool_lit(&self) -> bool {
956 self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
957 }
958
959 pub fn is_numeric_lit(&self) -> bool {
960 matches!(
961 self.kind,
962 Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. })
963 )
964 }
965
966 pub fn is_integer_lit(&self) -> bool {
968 matches!(self.kind, Literal(Lit { kind: LitKind::Integer, .. }))
969 }
970
971 pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
973 match self.ident() {
974 Some((id, IdentIsRaw::No)) => pred(id),
975 _ => false,
976 }
977 }
978
979 pub fn is_metavar_seq(&self) -> Option<MetaVarKind> {
982 match self.kind {
983 OpenInvisible(InvisibleOrigin::MetaVar(kind)) => Some(kind),
984 _ => None,
985 }
986 }
987
988 pub fn glue(&self, joint: &Token) -> Option<Token> {
989 let kind = match (&self.kind, &joint.kind) {
990 (Eq, Eq) => EqEq,
991 (Eq, Gt) => FatArrow,
992 (Eq, _) => return None,
993
994 (Lt, Eq) => Le,
995 (Lt, Lt) => Shl,
996 (Lt, Le) => ShlEq,
997 (Lt, Minus) => LArrow,
998 (Lt, _) => return None,
999
1000 (Gt, Eq) => Ge,
1001 (Gt, Gt) => Shr,
1002 (Gt, Ge) => ShrEq,
1003 (Gt, _) => return None,
1004
1005 (Bang, Eq) => Ne,
1006 (Bang, _) => return None,
1007
1008 (Plus, Eq) => PlusEq,
1009 (Plus, _) => return None,
1010
1011 (Minus, Eq) => MinusEq,
1012 (Minus, Gt) => RArrow,
1013 (Minus, _) => return None,
1014
1015 (Star, Eq) => StarEq,
1016 (Star, _) => return None,
1017
1018 (Slash, Eq) => SlashEq,
1019 (Slash, _) => return None,
1020
1021 (Percent, Eq) => PercentEq,
1022 (Percent, _) => return None,
1023
1024 (Caret, Eq) => CaretEq,
1025 (Caret, _) => return None,
1026
1027 (And, Eq) => AndEq,
1028 (And, And) => AndAnd,
1029 (And, _) => return None,
1030
1031 (Or, Eq) => OrEq,
1032 (Or, Or) => OrOr,
1033 (Or, _) => return None,
1034
1035 (Shl, Eq) => ShlEq,
1036 (Shl, _) => return None,
1037
1038 (Shr, Eq) => ShrEq,
1039 (Shr, _) => return None,
1040
1041 (Dot, Dot) => DotDot,
1042 (Dot, DotDot) => DotDotDot,
1043 (Dot, _) => return None,
1044
1045 (DotDot, Dot) => DotDotDot,
1046 (DotDot, Eq) => DotDotEq,
1047 (DotDot, _) => return None,
1048
1049 (Colon, Colon) => PathSep,
1050 (Colon, _) => return None,
1051
1052 (SingleQuote, Ident(name, is_raw)) => {
1053 Lifetime(Symbol::intern(&format!("'{name}")), *is_raw)
1054 }
1055 (SingleQuote, _) => return None,
1056
1057 (
1058 Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | PlusEq | MinusEq | StarEq | SlashEq
1059 | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | DotDotDot | DotDotEq
1060 | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question
1061 | OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
1062 | OpenInvisible(_) | CloseInvisible(_) | Literal(..) | Ident(..) | NtIdent(..)
1063 | Lifetime(..) | NtLifetime(..) | DocComment(..) | Eof,
1064 _,
1065 ) => {
1066 return None;
1067 }
1068 };
1069
1070 Some(Token::new(kind, self.span.to(joint.span)))
1071 }
1072}
1073
1074impl PartialEq<TokenKind> for Token {
1075 #[inline]
1076 fn eq(&self, rhs: &TokenKind) -> bool {
1077 self.kind == *rhs
1078 }
1079}
1080
1081#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1082pub enum NtPatKind {
1083 PatWithOr,
1085 PatParam { inferred: bool },
1089}
1090
1091#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1092pub enum NtExprKind {
1093 Expr,
1096 Expr2021 { inferred: bool },
1100}
1101
1102#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1104pub enum NonterminalKind {
1105 Item,
1106 Block,
1107 Stmt,
1108 Pat(NtPatKind),
1109 Expr(NtExprKind),
1110 Ty,
1111 Ident,
1112 Lifetime,
1113 Literal,
1114 Meta,
1115 Path,
1116 Vis,
1117 TT,
1118}
1119
1120impl NonterminalKind {
1121 pub fn from_symbol(
1124 symbol: Symbol,
1125 edition: impl FnOnce() -> Edition,
1126 ) -> Option<NonterminalKind> {
1127 Some(match symbol {
1128 sym::item => NonterminalKind::Item,
1129 sym::block => NonterminalKind::Block,
1130 sym::stmt => NonterminalKind::Stmt,
1131 sym::pat => {
1132 if edition().at_least_rust_2021() {
1133 NonterminalKind::Pat(PatWithOr)
1134 } else {
1135 NonterminalKind::Pat(PatParam { inferred: true })
1136 }
1137 }
1138 sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }),
1139 sym::expr => {
1140 if edition().at_least_rust_2024() {
1141 NonterminalKind::Expr(Expr)
1142 } else {
1143 NonterminalKind::Expr(Expr2021 { inferred: true })
1144 }
1145 }
1146 sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }),
1147 sym::ty => NonterminalKind::Ty,
1148 sym::ident => NonterminalKind::Ident,
1149 sym::lifetime => NonterminalKind::Lifetime,
1150 sym::literal => NonterminalKind::Literal,
1151 sym::meta => NonterminalKind::Meta,
1152 sym::path => NonterminalKind::Path,
1153 sym::vis => NonterminalKind::Vis,
1154 sym::tt => NonterminalKind::TT,
1155 _ => return None,
1156 })
1157 }
1158
1159 fn symbol(self) -> Symbol {
1160 match self {
1161 NonterminalKind::Item => sym::item,
1162 NonterminalKind::Block => sym::block,
1163 NonterminalKind::Stmt => sym::stmt,
1164 NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
1165 NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param,
1166 NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr,
1167 NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021,
1168 NonterminalKind::Ty => sym::ty,
1169 NonterminalKind::Ident => sym::ident,
1170 NonterminalKind::Lifetime => sym::lifetime,
1171 NonterminalKind::Literal => sym::literal,
1172 NonterminalKind::Meta => sym::meta,
1173 NonterminalKind::Path => sym::path,
1174 NonterminalKind::Vis => sym::vis,
1175 NonterminalKind::TT => sym::tt,
1176 }
1177 }
1178}
1179
1180impl fmt::Display for NonterminalKind {
1181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1182 write!(f, "{}", self.symbol())
1183 }
1184}
1185
1186#[cfg(target_pointer_width = "64")]
1188mod size_asserts {
1189 use rustc_data_structures::static_assert_size;
1190
1191 use super::*;
1192 static_assert_size!(Lit, 12);
1194 static_assert_size!(LitKind, 2);
1195 static_assert_size!(Token, 24);
1196 static_assert_size!(TokenKind, 16);
1197 }