1use crate::node::Node;
2use crate::node::Span;
3use logos::Logos;
4use smol_str::SmolStr;
5use std::ops::Add;
6
7#[derive(Debug, PartialEq, Eq, Clone)]
8pub struct Token<'a> {
9 pub kind: TokenKind,
10 pub text: &'a str,
11 pub span: Span,
12}
13
14impl<'a> From<Token<'a>> for Node<SmolStr> {
15 fn from(tok: Token<'a>) -> Node<SmolStr> {
16 Node::new(tok.text.into(), tok.span)
17 }
18}
19
20impl<'a> Add<&Token<'a>> for Span {
21 type Output = Self;
22
23 fn add(self, other: &Token<'a>) -> Self {
24 self + other.span
25 }
26}
27
28#[derive(Debug, Copy, Clone, PartialEq, Eq, Logos)]
29pub enum TokenKind {
30 #[regex(r"//[^\n]*", logos::skip)]
33 #[regex("[ \t]+", logos::skip)]
34 #[error]
35 Error,
36
37 #[regex(r"\n[ \t]*")]
38 Newline,
39
40 #[regex("[a-zA-Z_][a-zA-Z0-9_]*")]
41 Name,
42 #[regex("[0-9]+(?:_[0-9]+)*")]
43 Int,
44 #[regex("0[xX][0-9a-fA-F]+")]
45 Hex,
46 #[regex("0[oO][0-7]+")]
47 Octal,
48 #[regex("0[bB][0-1]+")]
49 Binary,
50 #[regex(r#""([^"\\]|\\.)*""#)]
52 #[regex(r#"'([^'\\]|\\.)*'"#)]
53 Text,
54 #[token("true")]
55 True,
56 #[token("false")]
57 False,
58 #[token("assert")]
61 Assert,
62 #[token("break")]
63 Break,
64 #[token("continue")]
65 Continue,
66 #[token("contract")]
67 Contract,
68 #[token("fn")]
69 Fn,
70 #[token("const")]
71 Const,
72 #[token("else")]
73 Else,
74 #[token("idx")]
75 Idx,
76 #[token("if")]
77 If,
78 #[token("match")]
79 Match,
80 #[token("impl")]
81 Impl,
82 #[token("pragma")]
83 Pragma,
84 #[token("for")]
85 For,
86 #[token("pub")]
87 Pub,
88 #[token("return")]
89 Return,
90 #[token("revert")]
91 Revert,
92 #[token("Self")]
93 SelfType,
94 #[token("self")]
95 SelfValue,
96 #[token("struct")]
97 Struct,
98 #[token("enum")]
99 Enum,
100 #[token("trait")]
101 Trait,
102 #[token("type")]
103 Type,
104 #[token("unsafe")]
105 Unsafe,
106 #[token("while")]
107 While,
108
109 #[token("and")]
110 And,
111 #[token("as")]
112 As,
113 #[token("in")]
114 In,
115 #[token("not")]
116 Not,
117 #[token("or")]
118 Or,
119 #[token("let")]
120 Let,
121 #[token("mut")]
122 Mut,
123 #[token("use")]
124 Use,
125 #[token("(")]
127 ParenOpen,
128 #[token(")")]
129 ParenClose,
130 #[token("[")]
131 BracketOpen,
132 #[token("]")]
133 BracketClose,
134 #[token("{")]
135 BraceOpen,
136 #[token("}")]
137 BraceClose,
138 #[token(":")]
139 Colon,
140 #[token("::")]
141 ColonColon,
142 #[token(",")]
143 Comma,
144 #[token("#")]
145 Hash,
146 #[token(";")]
147 Semi,
148 #[token("+")]
149 Plus,
150 #[token("-")]
151 Minus,
152 #[token("*")]
153 Star,
154 #[token("/")]
155 Slash,
156 #[token("|")]
157 Pipe,
158 #[token("&")]
159 Amper,
160 #[token("<")]
161 Lt,
162 #[token("<<")]
163 LtLt,
164 #[token(">")]
165 Gt,
166 #[token(">>")]
167 GtGt,
168 #[token("=")]
169 Eq,
170 #[token(".")]
171 Dot,
172 #[token("..")]
173 DotDot,
174 #[token("%")]
175 Percent,
176 #[token("==")]
177 EqEq,
178 #[token("!=")]
179 NotEq,
180 #[token("<=")]
181 LtEq,
182 #[token(">=")]
183 GtEq,
184 #[token("~")]
185 Tilde,
186 #[token("^")]
187 Hat,
188 #[token("**")]
189 StarStar,
190 #[token("**=")]
191 StarStarEq,
192 #[token("+=")]
193 PlusEq,
194 #[token("-=")]
195 MinusEq,
196 #[token("*=")]
197 StarEq,
198 #[token("/=")]
199 SlashEq,
200 #[token("%=")]
201 PercentEq,
202 #[token("&=")]
203 AmperEq,
204 #[token("|=")]
205 PipeEq,
206 #[token("^=")]
207 HatEq,
208 #[token("<<=")]
209 LtLtEq,
210 #[token(">>=")]
211 GtGtEq,
212 #[token("->")]
213 Arrow,
214 #[token("=>")]
215 FatArrow,
216}
217
218impl TokenKind {
219 pub fn describe(&self) -> &str {
223 use TokenKind::*;
224 match self {
225 Newline => "a newline",
226 Name => "a name",
227 Int => "a number",
228 Hex => "a hexadecimal number",
229 Octal => "an octal number",
230 Binary => "a binary number",
231 Text => "a string",
232
233 True => "keyword `true`",
234 False => "keyword `false`",
235 Assert => "keyword `assert`",
236 Break => "keyword `break`",
237 Continue => "keyword `continue`",
238 Contract => "keyword `contract`",
239 Fn => "keyword `fn`",
240 Const => "keyword `const`",
241 Let => "keyword `let`",
242 Mut => "keyword `mut`",
243 Else => "keyword `else`",
244 Idx => "keyword `idx`",
245 If => "keyword `if`",
246 Match => "keyword `match`",
247 Impl => "keyword `impl`",
248 Pragma => "keyword `pragma`",
249 For => "keyword `for`",
250 Pub => "keyword `pub`",
251 Return => "keyword `return`",
252 Revert => "keyword `revert`",
253 SelfType => "keyword `Self`",
254 SelfValue => "keyword `self`",
255 Struct => "keyword `struct`",
256 Enum => "keyword `enum`",
257 Trait => "keyword `trait`",
258 Type => "keyword `type`",
259 Unsafe => "keyword `unsafe`",
260 While => "keyword `while`",
261 And => "keyword `and`",
262 As => "keyword `as`",
263 In => "keyword `in`",
264 Not => "keyword `not`",
265 Or => "keyword `or`",
266 Use => "keyword `use`",
267 ParenOpen => "symbol `(`",
268 ParenClose => "symbol `)`",
269 BracketOpen => "symbol `[`",
270 BracketClose => "symbol `]`",
271 BraceOpen => "symbol `{`",
272 BraceClose => "symbol `}`",
273 Colon => "symbol `:`",
274 ColonColon => "symbol `::`",
275 Comma => "symbol `,`",
276 Hash => "symbol `#`",
277 Semi => "symbol `;`",
278 Plus => "symbol `+`",
279 Minus => "symbol `-`",
280 Star => "symbol `*`",
281 Slash => "symbol `/`",
282 Pipe => "symbol `|`",
283 Amper => "symbol `&`",
284 Lt => "symbol `<`",
285 LtLt => "symbol `<<`",
286 Gt => "symbol `>`",
287 GtGt => "symbol `>>`",
288 Eq => "symbol `=`",
289 Dot => "symbol `.`",
290 DotDot => "symbol `..`",
291 Percent => "symbol `%`",
292 EqEq => "symbol `==`",
293 NotEq => "symbol `!=`",
294 LtEq => "symbol `<=`",
295 GtEq => "symbol `>=`",
296 Tilde => "symbol `~`",
297 Hat => "symbol `^`",
298 StarStar => "symbol `**`",
299 StarStarEq => "symbol `**=`",
300 PlusEq => "symbol `+=`",
301 MinusEq => "symbol `-=`",
302 StarEq => "symbol `*=`",
303 SlashEq => "symbol `/=`",
304 PercentEq => "symbol `%=`",
305 AmperEq => "symbol `&=`",
306 PipeEq => "symbol `|=`",
307 HatEq => "symbol `^=`",
308 LtLtEq => "symbol `<<=`",
309 GtGtEq => "symbol `>>=`",
310 Arrow => "symbol `->`",
311 FatArrow => "symbol `=>`",
312
313 Error => unreachable!(), }
315 }
316}