1use std::fmt::{self, Debug, Display, Formatter};
2
3use crate::Span;
4
5#[derive(Clone, Copy, PartialEq)]
6pub struct Token<'src> {
7 pub kind: TokenKind<'src>,
8 pub span: Span<'src>,
9}
10
11impl<'src> Token<'src> {
12 pub fn new(kind: TokenKind<'src>, span: Span<'src>) -> Self {
13 Self { kind, span }
14 }
15
16 pub fn dummy() -> Self {
17 Self {
18 kind: TokenKind::default(),
19 span: Span::dummy(),
20 }
21 }
22}
23
24impl Debug for Token<'_> {
25 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
26 write!(
27 f,
28 "{:<15} (l:{}:{} -- l:{}:{})",
29 format!("{:?}", self.kind),
30 self.span.start.line,
31 self.span.start.column,
32 self.span.end.line,
33 self.span.end.column
34 )
35 }
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Default)]
39pub enum TokenKind<'src> {
40 #[default]
42 Eof,
43
44 Ident(&'src str),
46 Int(i64),
48 Float(f64),
50 Char(u8),
52
53 True,
55 False,
57 Fn,
59 Let,
61 Mut,
63 Return,
65 Loop,
67 While,
69 For,
71 Break,
73 Continue,
75 If,
77 Else,
79 As,
81
82 LParen,
84 RParen,
86 LBrace,
88 RBrace,
90
91 Arrow,
93 Comma,
95 Colon,
97 Semicolon,
99
100 Not,
102 Minus,
104 Plus,
106 Star,
108 Slash,
110 Percent,
112 Pow,
114 Eq,
116 Neq,
118 Lt,
120 Gt,
122 Lte,
124 Gte,
126 Shl,
128 Shr,
130 BitOr,
132 BitAnd,
134 BitXor,
136 And,
138 Or,
140
141 Assign,
143 PlusAssign,
145 MinusAssign,
147 MulAssign,
149 DivAssign,
151 RemAssign,
153 PowAssign,
155 ShlAssign,
157 ShrAssign,
159 BitOrAssign,
161 BitAndAssign,
163 BitXorAssign,
165}
166
167impl<'src> TokenKind<'src> {
168 pub fn spanned(self, span: Span<'src>) -> Token<'src> {
169 Token { kind: self, span }
170 }
171
172 pub(crate) fn prec(&self) -> (u8, u8) {
173 match self {
174 TokenKind::Assign
175 | TokenKind::PlusAssign
176 | TokenKind::MinusAssign
177 | TokenKind::MulAssign
178 | TokenKind::DivAssign
179 | TokenKind::RemAssign
180 | TokenKind::PowAssign
181 | TokenKind::ShlAssign
182 | TokenKind::ShrAssign
183 | TokenKind::BitOrAssign
184 | TokenKind::BitAndAssign
185 | TokenKind::BitXorAssign => (1, 2),
186 TokenKind::Or => (3, 4),
187 TokenKind::And => (5, 6),
188 TokenKind::BitOr => (7, 8),
189 TokenKind::BitXor => (9, 10),
190 TokenKind::BitAnd => (11, 12),
191 TokenKind::Eq | TokenKind::Neq => (13, 14),
192 TokenKind::Lt | TokenKind::Gt | TokenKind::Lte | TokenKind::Gte => (15, 16),
193 TokenKind::Shl | TokenKind::Shr => (17, 18),
194 TokenKind::Plus | TokenKind::Minus => (19, 20),
195 TokenKind::Star | TokenKind::Slash | TokenKind::Percent => (21, 22),
196 TokenKind::As => (23, 24),
197 TokenKind::Pow => (26, 25), TokenKind::LParen => (28, 29),
199 _ => (0, 0),
200 }
201 }
202}
203
204impl Display for TokenKind<'_> {
205 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
206 match self {
207 Self::Eof => write!(f, "EOF"),
208 Self::Ident(ident) => write!(f, "{ident}"),
209 Self::Int(num) => write!(f, "{num}"),
210 Self::Float(num) => write!(f, "{num}"),
211 Self::Char(b'\\') => write!(f, "'\\\\'"),
212 Self::Char(b'\x08') => write!(f, "'\\b'"),
213 Self::Char(b'\n') => write!(f, "'\\n'"),
214 Self::Char(b'\r') => write!(f, "'\\r'"),
215 Self::Char(b'\t') => write!(f, "'\\t'"),
216 Self::Char(b'\'') => write!(f, "'\\''"),
217 Self::Char(char @ b' '..=b'~') => write!(f, "'{}'", *char as char),
218 Self::Char(char) => write!(f, "'\\x{char:x}'"),
219 Self::True => write!(f, "true"),
220 Self::False => write!(f, "false"),
221 Self::Fn => write!(f, "fn"),
222 Self::Let => write!(f, "let"),
223 Self::Mut => write!(f, "mut"),
224 Self::Return => write!(f, "return"),
225 Self::Loop => write!(f, "loop"),
226 Self::While => write!(f, "while"),
227 Self::For => write!(f, "for"),
228 Self::Break => write!(f, "break"),
229 Self::Continue => write!(f, "continue"),
230 Self::If => write!(f, "if"),
231 Self::Else => write!(f, "else"),
232 Self::As => write!(f, "as"),
233 Self::LParen => write!(f, "("),
234 Self::RParen => write!(f, ")"),
235 Self::LBrace => write!(f, "{{"),
236 Self::RBrace => write!(f, "}}"),
237 Self::Arrow => write!(f, "->"),
238 Self::Comma => write!(f, ","),
239 Self::Colon => write!(f, ":"),
240 Self::Semicolon => write!(f, ";"),
241 Self::Not => write!(f, "!"),
242 Self::Minus => write!(f, "-"),
243 Self::Plus => write!(f, "+"),
244 Self::Star => write!(f, "*"),
245 Self::Slash => write!(f, "/"),
246 Self::Percent => write!(f, "%"),
247 Self::Pow => write!(f, "**"),
248 Self::Eq => write!(f, "=="),
249 Self::Neq => write!(f, "!="),
250 Self::Lt => write!(f, "<"),
251 Self::Gt => write!(f, ">"),
252 Self::Lte => write!(f, "<="),
253 Self::Gte => write!(f, ">="),
254 Self::Shl => write!(f, "<<"),
255 Self::Shr => write!(f, ">>"),
256 Self::BitOr => write!(f, "|"),
257 Self::BitAnd => write!(f, "&"),
258 Self::BitXor => write!(f, "^"),
259 Self::And => write!(f, "&&"),
260 Self::Or => write!(f, "||"),
261 Self::Assign => write!(f, "="),
262 Self::PlusAssign => write!(f, "+="),
263 Self::MinusAssign => write!(f, "-="),
264 Self::MulAssign => write!(f, "*="),
265 Self::DivAssign => write!(f, "/="),
266 Self::RemAssign => write!(f, "%="),
267 Self::PowAssign => write!(f, "**="),
268 Self::ShlAssign => write!(f, "<<="),
269 Self::ShrAssign => write!(f, ">>="),
270 Self::BitOrAssign => write!(f, "|="),
271 Self::BitAndAssign => write!(f, "&="),
272 Self::BitXorAssign => write!(f, "^="),
273 }
274 }
275}
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280
281 #[test]
282 fn char_display() {
283 assert_eq!(TokenKind::Char(b'\\').to_string(), r"'\\'");
284 assert_eq!(TokenKind::Char(0x08).to_string(), r"'\b'");
285 assert_eq!(TokenKind::Char(b'\n').to_string(), r"'\n'");
286 assert_eq!(TokenKind::Char(b'\r').to_string(), r"'\r'");
287 assert_eq!(TokenKind::Char(b'\t').to_string(), r"'\t'");
288 assert_eq!(TokenKind::Char(b'\'').to_string(), r"'\''");
289 assert_eq!(TokenKind::Char(b'a').to_string(), "'a'");
290 assert_eq!(TokenKind::Char(b'0').to_string(), "'0'");
291 assert_eq!(TokenKind::Char(b' ').to_string(), "' '");
292 assert_eq!(TokenKind::Char(b'~').to_string(), "'~'");
293 assert_eq!(TokenKind::Char(0x7f).to_string(), r"'\x7f'");
294 assert_eq!(TokenKind::Char(0x1b).to_string(), r"'\x1b'");
295 }
296}