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_ident() && !self.is_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_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)]
1089pub enum NonterminalKind {
1090 Item,
1091 Block,
1092 Stmt,
1093 Pat(NtPatKind),
1094 Expr(NtExprKind),
1095 Ty,
1096 Ident,
1097 Lifetime,
1098 Literal,
1099 Meta,
1100 Path,
1101 Vis,
1102 TT,
1103}
1104
1105impl NonterminalKind {
1106 pub fn from_symbol(
1109 symbol: Symbol,
1110 edition: impl FnOnce() -> Edition,
1111 ) -> Option<NonterminalKind> {
1112 Some(match symbol {
1113 sym::item => NonterminalKind::Item,
1114 sym::block => NonterminalKind::Block,
1115 sym::stmt => NonterminalKind::Stmt,
1116 sym::pat => {
1117 if edition().at_least_rust_2021() {
1118 NonterminalKind::Pat(PatWithOr)
1119 } else {
1120 NonterminalKind::Pat(PatParam { inferred: true })
1121 }
1122 }
1123 sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }),
1124 sym::expr => {
1125 if edition().at_least_rust_2024() {
1126 NonterminalKind::Expr(Expr)
1127 } else {
1128 NonterminalKind::Expr(Expr2021 { inferred: true })
1129 }
1130 }
1131 sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }),
1132 sym::ty => NonterminalKind::Ty,
1133 sym::ident => NonterminalKind::Ident,
1134 sym::lifetime => NonterminalKind::Lifetime,
1135 sym::literal => NonterminalKind::Literal,
1136 sym::meta => NonterminalKind::Meta,
1137 sym::path => NonterminalKind::Path,
1138 sym::vis => NonterminalKind::Vis,
1139 sym::tt => NonterminalKind::TT,
1140 _ => return None,
1141 })
1142 }
1143
1144 fn symbol(self) -> Symbol {
1145 match self {
1146 NonterminalKind::Item => sym::item,
1147 NonterminalKind::Block => sym::block,
1148 NonterminalKind::Stmt => sym::stmt,
1149 NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
1150 NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param,
1151 NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr,
1152 NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021,
1153 NonterminalKind::Ty => sym::ty,
1154 NonterminalKind::Ident => sym::ident,
1155 NonterminalKind::Lifetime => sym::lifetime,
1156 NonterminalKind::Literal => sym::literal,
1157 NonterminalKind::Meta => sym::meta,
1158 NonterminalKind::Path => sym::path,
1159 NonterminalKind::Vis => sym::vis,
1160 NonterminalKind::TT => sym::tt,
1161 }
1162 }
1163}
1164
1165impl fmt::Display for NonterminalKind {
1166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1167 write!(f, "{}", self.symbol())
1168 }
1169}
1170
1171#[cfg(target_pointer_width = "64")]
1173mod size_asserts {
1174 use rustc_data_structures::static_assert_size;
1175
1176 use super::*;
1177 static_assert_size!(Lit, 12);
1179 static_assert_size!(LitKind, 2);
1180 static_assert_size!(Token, 24);
1181 static_assert_size!(TokenKind, 16);
1182 }