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 }