1use std::borrow::Cow;
2
3use crate::span::Span;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub enum TokenKind {
7 Ident,
8 Int,
9 Float,
10
11 StringStart,
13 StringText,
14 InterpolationStart,
15 InterpolationEnd,
16 StringEnd,
17
18 State,
19 Let,
20 Fn,
21 View,
22 Struct,
23 If,
24 Else,
25 For,
26 In,
27 Return,
28 True,
29 False,
30
31 LParen,
32 RParen,
33 LBrace,
34 RBrace,
35 LBracket,
36 RBracket,
37 Comma,
38 Colon,
39 Dot,
40 DotDot,
41 Arrow,
42 Dollar,
43
44 Plus,
45 Minus,
46 Star,
47 Slash,
48 Percent,
49 Bang,
50 Eq,
51 EqEq,
52 BangEq,
53 Lt,
54 LtEq,
55 Gt,
56 GtEq,
57 AndAnd,
58 OrOr,
59 PlusEq,
60 MinusEq,
61 StarEq,
62 SlashEq,
63
64 Newline,
65 Eof,
66}
67
68pub const KEYWORDS: &[TokenKind] = &[
70 TokenKind::State,
71 TokenKind::Let,
72 TokenKind::Fn,
73 TokenKind::View,
74 TokenKind::Struct,
75 TokenKind::If,
76 TokenKind::Else,
77 TokenKind::For,
78 TokenKind::In,
79 TokenKind::Return,
80 TokenKind::True,
81 TokenKind::False,
82];
83
84pub const SYMBOLS: &[TokenKind] = &[
86 TokenKind::LParen,
87 TokenKind::RParen,
88 TokenKind::LBrace,
89 TokenKind::RBrace,
90 TokenKind::LBracket,
91 TokenKind::RBracket,
92 TokenKind::Comma,
93 TokenKind::Colon,
94 TokenKind::Dot,
95 TokenKind::DotDot,
96 TokenKind::Arrow,
97 TokenKind::Dollar,
98 TokenKind::Plus,
99 TokenKind::Minus,
100 TokenKind::Star,
101 TokenKind::Slash,
102 TokenKind::Percent,
103 TokenKind::Bang,
104 TokenKind::Eq,
105 TokenKind::EqEq,
106 TokenKind::BangEq,
107 TokenKind::Lt,
108 TokenKind::LtEq,
109 TokenKind::Gt,
110 TokenKind::GtEq,
111 TokenKind::AndAnd,
112 TokenKind::OrOr,
113 TokenKind::PlusEq,
114 TokenKind::MinusEq,
115 TokenKind::StarEq,
116 TokenKind::SlashEq,
117];
118
119impl TokenKind {
120 pub(crate) fn keyword(text: &str) -> Option<Self> {
121 KEYWORDS
122 .iter()
123 .copied()
124 .find(|kind| kind.text() == Some(text))
125 }
126
127 #[must_use]
130 pub const fn text(self) -> Option<&'static str> {
131 match self.spelling() {
132 Spelling::Fixed(text) => Some(text),
133 Spelling::Varies(_) => None,
134 }
135 }
136
137 #[must_use]
139 pub fn describe(self) -> Cow<'static, str> {
140 match self.spelling() {
141 Spelling::Fixed(text) => Cow::Owned(format!("`{text}`")),
142 Spelling::Varies(description) => Cow::Borrowed(description),
143 }
144 }
145
146 const fn spelling(self) -> Spelling {
147 use Spelling::{Fixed, Varies};
148 match self {
149 Self::Ident => Varies("a name"),
150 Self::Int | Self::Float => Varies("a number"),
151 Self::StringStart => Varies("a string"),
152 Self::StringText | Self::StringEnd => Varies("string text"),
153 Self::InterpolationStart => Varies("`{` in a string"),
154 Self::InterpolationEnd => Varies("`}` in a string"),
155 Self::Newline => Varies("end of line"),
156 Self::Eof => Varies("end of file"),
157 Self::State => Fixed("state"),
158 Self::Let => Fixed("let"),
159 Self::Fn => Fixed("fn"),
160 Self::View => Fixed("view"),
161 Self::Struct => Fixed("struct"),
162 Self::If => Fixed("if"),
163 Self::Else => Fixed("else"),
164 Self::For => Fixed("for"),
165 Self::In => Fixed("in"),
166 Self::Return => Fixed("return"),
167 Self::True => Fixed("true"),
168 Self::False => Fixed("false"),
169 Self::LParen => Fixed("("),
170 Self::RParen => Fixed(")"),
171 Self::LBrace => Fixed("{"),
172 Self::RBrace => Fixed("}"),
173 Self::LBracket => Fixed("["),
174 Self::RBracket => Fixed("]"),
175 Self::Comma => Fixed(","),
176 Self::Colon => Fixed(":"),
177 Self::Dot => Fixed("."),
178 Self::DotDot => Fixed(".."),
179 Self::Arrow => Fixed("->"),
180 Self::Dollar => Fixed("$"),
181 Self::Plus => Fixed("+"),
182 Self::Minus => Fixed("-"),
183 Self::Star => Fixed("*"),
184 Self::Slash => Fixed("/"),
185 Self::Percent => Fixed("%"),
186 Self::Bang => Fixed("!"),
187 Self::Eq => Fixed("="),
188 Self::EqEq => Fixed("=="),
189 Self::BangEq => Fixed("!="),
190 Self::Lt => Fixed("<"),
191 Self::LtEq => Fixed("<="),
192 Self::Gt => Fixed(">"),
193 Self::GtEq => Fixed(">="),
194 Self::AndAnd => Fixed("&&"),
195 Self::OrOr => Fixed("||"),
196 Self::PlusEq => Fixed("+="),
197 Self::MinusEq => Fixed("-="),
198 Self::StarEq => Fixed("*="),
199 Self::SlashEq => Fixed("/="),
200 }
201 }
202}
203
204enum Spelling {
206 Fixed(&'static str),
207 Varies(&'static str),
208}
209
210#[derive(Clone, Copy, Debug, PartialEq, Eq)]
211pub struct Token {
212 pub kind: TokenKind,
213 pub span: Span,
214}