1use std::fmt::{Debug, Formatter};
4use strum::EnumString;
5use strum::IntoStaticStr;
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10#[derive(Copy, Clone, Eq, PartialEq, Debug, EnumString, IntoStaticStr)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub enum Operator {
13 #[strum(serialize = "+")]
14 Add,
15 #[strum(serialize = "-")]
16 Sub,
17 #[strum(serialize = "*")]
18 Star,
19 #[strum(serialize = "/")]
20 Quo,
21 #[strum(serialize = "%")]
22 Rem,
23
24 #[strum(serialize = "&")]
25 And,
26 #[strum(serialize = "|")]
27 Or,
28 #[strum(serialize = "^")]
29 Xor,
30 #[strum(serialize = "<<")]
31 Shl,
32 #[strum(serialize = ">>")]
33 Shr,
34 #[strum(serialize = "&^")]
35 AndNot,
36
37 #[strum(serialize = "+=")]
38 AddAssign,
39 #[strum(serialize = "-=")]
40 SubAssign,
41 #[strum(serialize = "*=")]
42 MulAssign,
43 #[strum(serialize = "/=")]
44 QuoAssign,
45 #[strum(serialize = "%=")]
46 RemAssign,
47
48 #[strum(serialize = "&=")]
49 AndAssign,
50 #[strum(serialize = "|=")]
51 OrAssign,
52 #[strum(serialize = "^=")]
53 XorAssign,
54 #[strum(serialize = "<<=")]
55 ShlAssign,
56 #[strum(serialize = ">>=")]
57 ShrAssign,
58 #[strum(serialize = "&^=")]
59 AndNotAssign,
60
61 #[strum(serialize = "&&")]
62 AndAnd,
63 #[strum(serialize = "||")]
64 OrOr,
65 #[strum(serialize = "<-")]
66 Arrow,
67 #[strum(serialize = "++")]
68 Inc,
69 #[strum(serialize = "--")]
70 Dec,
71
72 #[strum(serialize = "==")]
73 Equal,
74 #[strum(serialize = "<")]
75 Less,
76 #[strum(serialize = ">")]
77 Greater,
78 #[strum(serialize = "=")]
79 Assign,
80 #[strum(serialize = "!")]
81 Not,
82 #[strum(serialize = "~")]
83 Tiled,
84
85 #[strum(serialize = "!=")]
86 NotEqual,
87 #[strum(serialize = "<=")]
88 LessEqual,
89 #[strum(serialize = ">=")]
90 GreaterEqual,
91 #[strum(serialize = ":=")]
92 Define,
93 #[strum(serialize = "...")]
94 DotDotDot,
95
96 #[strum(serialize = "(")]
97 ParenLeft,
98 #[strum(serialize = ")")]
99 ParenRight,
100 #[strum(serialize = "[")]
101 BarackLeft,
102 #[strum(serialize = "]")]
103 BarackRight,
104 #[strum(serialize = "{")]
105 BraceLeft,
106 #[strum(serialize = "}")]
107 BraceRight,
108
109 #[strum(serialize = ",")]
110 Comma,
111 #[strum(serialize = ":")]
112 Colon,
113 #[strum(serialize = ".")]
114 Dot,
115 #[strum(serialize = ";")]
116 SemiColon,
117}
118
119#[derive(Copy, Clone, Eq, PartialEq, Debug, EnumString, IntoStaticStr)]
120#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
121pub enum Keyword {
122 #[strum(serialize = "break")]
123 Break,
124 #[strum(serialize = "case")]
125 Case,
126 #[strum(serialize = "chan")]
127 Chan,
128 #[strum(serialize = "const")]
129 Const,
130 #[strum(serialize = "continue")]
131 Continue,
132
133 #[strum(serialize = "default")]
134 Default,
135 #[strum(serialize = "defer")]
136 Defer,
137 #[strum(serialize = "else")]
138 Else,
139 #[strum(serialize = "fallthrough")]
140 FallThrough,
141 #[strum(serialize = "for")]
142 For,
143
144 #[strum(serialize = "func")]
145 Func,
146 #[strum(serialize = "go")]
147 Go,
148 #[strum(serialize = "goto")]
149 Goto,
150 #[strum(serialize = "if")]
151 If,
152 #[strum(serialize = "import")]
153 Import,
154
155 #[strum(serialize = "interface")]
156 Interface,
157 #[strum(serialize = "map")]
158 Map,
159 #[strum(serialize = "package")]
160 Package,
161 #[strum(serialize = "range")]
162 Range,
163 #[strum(serialize = "return")]
164 Return,
165
166 #[strum(serialize = "select")]
167 Select,
168 #[strum(serialize = "struct")]
169 Struct,
170 #[strum(serialize = "switch")]
171 Switch,
172 #[strum(serialize = "type")]
173 Type,
174 #[strum(serialize = "var")]
175 Var,
176}
177
178#[derive(Copy, Clone, Eq, PartialEq, Debug)]
179#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
180pub enum LitKind {
181 Ident,
182 String,
183 Integer,
184 Float,
185 Imag,
186 Char,
187}
188
189#[derive(Eq, PartialEq, Clone)]
190pub enum Token {
191 Comment(String),
192 Keyword(Keyword),
193 Operator(Operator),
194 Literal(LitKind, String),
195}
196
197impl From<Keyword> for Token {
198 fn from(word: Keyword) -> Self {
199 Token::Keyword(word)
200 }
201}
202
203impl From<Operator> for Token {
204 fn from(op: Operator) -> Self {
205 Token::Operator(op)
206 }
207}
208
209#[rustfmt::skip]
210impl Operator {
211 pub fn precedence(&self) -> usize {
212 match self {
213 | Operator::OrOr => 1,
214 | Operator::AndAnd => 2,
215 | Operator::Equal
216 | Operator::NotEqual
217 | Operator::Less
218 | Operator::Greater
219 | Operator::LessEqual
220 | Operator::GreaterEqual => 3,
221 | Operator::Add
222 | Operator::Sub
223 | Operator::Or
224 | Operator::Xor => 4,
225 | Operator::Star
226 | Operator::Quo
227 | Operator::Rem
228 | Operator::Shl
229 | Operator::Shr
230 | Operator::And
231 | Operator::AndNot => 5,
232 _ => 0,
233 }
234 }
235
236 pub(crate) fn to_str(self) -> &'static str {
237 self.into()
238 }
239}
240
241impl Keyword {
242 fn to_str(self) -> &'static str {
243 self.into()
244 }
245}
246
247impl Debug for Token {
248 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
249 match self {
250 Token::Comment(_) => write!(f, "/* comment */"),
251 Token::Literal(_, lit) => write!(f, "'{lit}'"),
252 Token::Operator(op) => write!(f, "'{}'", op.to_str()),
253 Token::Keyword(word) => write!(f, "'{}'", word.to_str()),
254 }
255 }
256}
257
258impl Token {
259 pub fn str_len(&self) -> usize {
260 match self {
261 Token::Operator(op) => op.to_str().len(),
262 Token::Keyword(word) => word.to_str().len(),
263 Token::Comment(text) => text.len(),
264 Token::Literal(_, value) => value.len(),
265 }
266 }
267
268 pub fn kind(&self) -> TokenKind {
269 match self {
270 Token::Comment(_) => TokenKind::Comment,
271 Token::Operator(op) => TokenKind::Operator(*op),
272 Token::Keyword(word) => TokenKind::Keyword(*word),
273 Token::Literal(kind, _) => TokenKind::Literal(*kind),
274 }
275 }
276
277 pub fn is<K: Into<TokenKind>>(&self, exp: K) -> bool {
278 self.kind() == exp.into()
279 }
280
281 pub fn precedence(&self) -> Option<(Operator, usize)> {
282 match self {
283 Token::Operator(op) => Some((*op, op.precedence())),
284 _ => None,
285 }
286 }
287}
288
289#[derive(Eq, PartialEq, Copy, Clone)]
290pub enum TokenKind {
291 Comment,
292 Keyword(Keyword),
293 Literal(LitKind),
294 Operator(Operator),
295}
296
297impl From<Keyword> for TokenKind {
298 fn from(word: Keyword) -> Self {
299 TokenKind::Keyword(word)
300 }
301}
302
303impl From<LitKind> for TokenKind {
304 fn from(lit: LitKind) -> Self {
305 TokenKind::Literal(lit)
306 }
307}
308
309impl From<Operator> for TokenKind {
310 fn from(op: Operator) -> Self {
311 TokenKind::Operator(op)
312 }
313}
314
315impl Debug for TokenKind {
316 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
317 match self {
318 Self::Comment => unreachable!(),
319 Self::Keyword(word) => write!(f, "'{}'", word.to_str()),
320 Self::Operator(op) => write!(f, "'{}'", op.to_str()),
321 Self::Literal(kind) => match kind {
322 LitKind::Ident => write!(f, "Identifier"),
323 LitKind::String => write!(f, "String Literals"),
324 LitKind::Integer => write!(f, "Integer Literals"),
325 LitKind::Imag => write!(f, "Imaginary Literals"),
326 LitKind::Char => write!(f, "Character Literals"),
327 LitKind::Float => write!(f, "Float Literals"),
328 },
329 }
330 }
331}