1use std::fmt;
2
3pub use TokenKind::*;
4use rustc_ast::token::InvisibleOrigin;
5pub use rustc_ast::token::{Delimiter, IdentIsRaw, Lit, LitKind};
6use rustc_span::{BytePos, Symbol};
7
8#[derive(Copy, Clone, Debug, PartialEq)]
9pub enum TokenKind {
10 Caret,
11 Or,
12 EqEq,
13 Eq,
14 AndAnd,
15 OrOr,
16 Plus,
17 Minus,
18 Slash,
19 Bang,
20 Star,
21 Colon,
22 Comma,
23 Semi,
24 RArrow,
25 Dot,
26 Le,
27 Ne,
28 GtFollowedByGt,
29 Gt,
30 LtFollowedByLt,
31 Lt,
32 Ge,
33 At,
34 Pound,
35 Iff,
36 FatArrow,
37 Literal(Lit),
38 Ident(Symbol, IdentIsRaw),
39 OpenParen,
40 CloseParen,
41 OpenBrace,
42 CloseBrace,
43 OpenBracket,
44 CloseBracket,
45 OpenInvisible(InvisibleOrigin),
46 CloseInvisible(InvisibleOrigin),
47 Invalid,
48 And,
49 Percent,
50 PathSep,
51 DotDot,
52 Eof,
53}
54
55#[derive(Clone, Copy)]
56pub struct Token {
57 pub kind: TokenKind,
58 pub lo: BytePos,
59 pub hi: BytePos,
60}
61
62impl Token {
63 pub fn new(kind: TokenKind, lo: BytePos, hi: BytePos) -> Self {
64 Self { kind, lo, hi }
65 }
66}
67
68impl TokenKind {
69 pub fn open_delim(delim: Delimiter) -> TokenKind {
70 match delim {
71 Delimiter::Parenthesis => TokenKind::OpenParen,
72 Delimiter::Bracket => TokenKind::OpenBracket,
73 Delimiter::Brace => TokenKind::OpenBrace,
74 Delimiter::Invisible(origin) => TokenKind::OpenInvisible(origin),
75 }
76 }
77
78 pub fn close_delim(delim: Delimiter) -> TokenKind {
79 match delim {
80 Delimiter::Parenthesis => TokenKind::CloseParen,
81 Delimiter::Bracket => TokenKind::CloseBracket,
82 Delimiter::Brace => TokenKind::CloseBrace,
83 Delimiter::Invisible(origin) => TokenKind::CloseInvisible(origin),
84 }
85 }
86
87 pub fn as_open_delim(&self) -> Option<Delimiter> {
88 match self {
89 Self::OpenParen => Some(Delimiter::Parenthesis),
90 Self::OpenBrace => Some(Delimiter::Brace),
91 Self::OpenBracket => Some(Delimiter::Bracket),
92 _ => None,
93 }
94 }
95
96 pub fn as_close_delim(&self) -> Option<Delimiter> {
97 match self {
98 Self::CloseParen => Some(Delimiter::Parenthesis),
99 Self::CloseBrace => Some(Delimiter::Brace),
100 Self::CloseBracket => Some(Delimiter::Bracket),
101 _ => None,
102 }
103 }
104
105 pub fn descr(&self) -> &'static str {
106 match self {
107 TokenKind::Caret => "^",
108 TokenKind::Or => "|",
109 TokenKind::EqEq => "==",
110 TokenKind::Eq => "=",
111 TokenKind::AndAnd => "&&",
112 TokenKind::OrOr => "||",
113 TokenKind::Plus => "+",
114 TokenKind::Minus => "-",
115 TokenKind::Slash => "/",
116 TokenKind::Bang => "!",
117 TokenKind::Star => "*",
118 TokenKind::Colon => ":",
119 TokenKind::Comma => ",",
120 TokenKind::Semi => ";",
121 TokenKind::RArrow => "->",
122 TokenKind::Dot => ".",
123 TokenKind::Le => "<=",
124 TokenKind::Ne => ">=",
125 TokenKind::GtFollowedByGt => ">",
126 TokenKind::Gt => ">",
127 TokenKind::LtFollowedByLt => "<",
128 TokenKind::Lt => "<",
129 TokenKind::Ge => ">=",
130 TokenKind::At => "@",
131 TokenKind::Pound => "#",
132 TokenKind::Iff => "<=>",
133 TokenKind::FatArrow => "=>",
134 TokenKind::Literal(_) => "literal",
135 TokenKind::Ident(..) => "identifier",
136 TokenKind::OpenParen => "(",
137 TokenKind::OpenBrace => "{",
138 TokenKind::OpenBracket => "[",
139 TokenKind::CloseParen => ")",
140 TokenKind::CloseBrace => "}",
141 TokenKind::CloseBracket => "]",
142 TokenKind::OpenInvisible(_) => "",
143 TokenKind::CloseInvisible(_) => "",
144 TokenKind::And => "&",
145 TokenKind::Percent => "%",
146 TokenKind::PathSep => "::",
147 TokenKind::DotDot => "..",
148 TokenKind::Eof => "<eof>",
149 TokenKind::Invalid => "<invalid>",
150 }
151 }
152
153 pub fn is_keyword(self, kw: Symbol) -> bool {
154 matches!(self, TokenKind::Ident(sym, IdentIsRaw::No) if sym == kw)
155 }
156
157 pub fn is_eof(self) -> bool {
158 matches!(self, TokenKind::Eof)
159 }
160}
161
162impl fmt::Display for TokenKind {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 match self {
165 TokenKind::Literal(lit) => write!(f, "{lit}"),
166 TokenKind::Ident(sym, _) => write!(f, "{sym}"),
167 _ => write!(f, "{}", self.descr()),
168 }
169 }
170}