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 descr(&self) -> &'static str {
88        match self {
89            TokenKind::Caret => "^",
90            TokenKind::Or => "|",
91            TokenKind::EqEq => "==",
92            TokenKind::Eq => "=",
93            TokenKind::AndAnd => "&&",
94            TokenKind::OrOr => "||",
95            TokenKind::Plus => "+",
96            TokenKind::Minus => "-",
97            TokenKind::Slash => "/",
98            TokenKind::Bang => "!",
99            TokenKind::Star => "*",
100            TokenKind::Colon => ":",
101            TokenKind::Comma => ",",
102            TokenKind::Semi => ";",
103            TokenKind::RArrow => "->",
104            TokenKind::Dot => ".",
105            TokenKind::Le => "<=",
106            TokenKind::Ne => ">=",
107            TokenKind::GtFollowedByGt => ">",
108            TokenKind::Gt => ">",
109            TokenKind::LtFollowedByLt => "<",
110            TokenKind::Lt => "<",
111            TokenKind::Ge => ">=",
112            TokenKind::At => "@",
113            TokenKind::Pound => "#",
114            TokenKind::Iff => "<=>",
115            TokenKind::FatArrow => "=>",
116            TokenKind::Literal(_) => "literal",
117            TokenKind::Ident(..) => "identifier",
118            TokenKind::OpenParen => "(",
119            TokenKind::OpenBrace => "{",
120            TokenKind::OpenBracket => "[",
121            TokenKind::CloseParen => ")",
122            TokenKind::CloseBrace => "}",
123            TokenKind::CloseBracket => "]",
124            TokenKind::OpenInvisible(_) => "",
125            TokenKind::CloseInvisible(_) => "",
126            TokenKind::And => "&",
127            TokenKind::Percent => "%",
128            TokenKind::PathSep => "::",
129            TokenKind::DotDot => "..",
130            TokenKind::Eof => "<eof>",
131            TokenKind::Invalid => "<invalid>",
132        }
133    }
134
135    pub fn is_keyword(self, kw: Symbol) -> bool {
136        matches!(self, TokenKind::Ident(sym, IdentIsRaw::No) if sym == kw)
137    }
138
139    pub fn is_eof(self) -> bool {
140        matches!(self, TokenKind::Eof)
141    }
142}
143
144impl fmt::Display for TokenKind {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        match self {
147            TokenKind::Literal(lit) => write!(f, "{lit}"),
148            TokenKind::Ident(sym, _) => write!(f, "{sym}"),
149            _ => write!(f, "{}", self.descr()),
150        }
151    }
152}