1#[derive(Debug, Clone, Copy, PartialEq)]
6pub struct Position {
7 pub line: usize,
8 pub column: usize,
9}
10
11impl Position {
12 pub fn new(line: usize, column: usize) -> Self {
13 Position { line, column }
14 }
15}
16
17impl std::fmt::Display for Position {
18 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
19 write!(f, "line {}, column {}", self.line, self.column)
20 }
21}
22
23#[derive(Debug, Clone, PartialEq)]
25pub struct TokenWithPos {
26 pub token: Token,
27 pub pos: Position,
28}
29
30impl TokenWithPos {
31 pub fn new(token: Token, line: usize, column: usize) -> Self {
32 TokenWithPos {
33 token,
34 pos: Position::new(line, column),
35 }
36 }
37}
38
39#[derive(Debug, Clone, PartialEq)]
41pub enum Token {
42 Set,
44 Func,
45 Lambda,
46 Generator,
47 Lazy,
48 If,
49 Elif,
50 Else,
51 While,
52 For,
53 In,
54 Switch,
55 Case,
56 Default,
57 Return,
58 Yield,
59 Break,
60 Continue,
61 Import,
62 From,
63 As,
64 Export,
65 Throw,
66
67 Identifier(String),
69 Number(f64),
70 BigInteger(String), String(String),
72 Boolean(bool),
73 Null,
74
75 Plus, Minus, Multiply, Divide, Modulo, Equal, NotEqual, Less, LessEqual, Greater, GreaterEqual, And, Or, Not, Assign, LeftParen, RightParen, LeftBrace, RightBrace, LeftBracket, RightBracket, Comma, Colon, Semicolon, Newline, Arrow, Illegal(char),
113 EOF,
114}
115
116impl Token {
117 pub fn lookup_keyword(ident: &str) -> Token {
119 match ident {
120 "Set" => Token::Set,
122 "Func" => Token::Func,
123 "Lambda" => Token::Lambda,
124 "Generator" => Token::Generator,
125 "Lazy" => Token::Lazy,
126 "If" => Token::If,
127 "Elif" => Token::Elif,
128 "Else" => Token::Else,
129 "While" => Token::While,
130 "For" => Token::For,
131 "In" => Token::In,
132 "Switch" => Token::Switch,
133 "Case" => Token::Case,
134 "Default" => Token::Default,
135 "Return" => Token::Return,
136 "Yield" => Token::Yield,
137 "Break" => Token::Break,
138 "Continue" => Token::Continue,
139 "Import" => Token::Import,
140 "From" => Token::From,
141 "as" => Token::As,
142 "Export" => Token::Export,
143 "Throw" => Token::Throw,
144
145 "And" => Token::And,
147 "Or" => Token::Or,
148 "Not" => Token::Not,
149
150 "True" => Token::Boolean(true),
152 "False" => Token::Boolean(false),
153
154 "Null" => Token::Null,
156
157 _ => Token::Identifier(ident.to_string()),
159 }
160 }
161
162 pub fn token_type(&self) -> &str {
164 match self {
165 Token::Set => "Set",
166 Token::Func => "Func",
167 Token::Lambda => "Lambda",
168 Token::Generator => "Generator",
169 Token::Lazy => "Lazy",
170 Token::If => "If",
171 Token::Elif => "Elif",
172 Token::Else => "Else",
173 Token::While => "While",
174 Token::For => "For",
175 Token::In => "In",
176 Token::Switch => "Switch",
177 Token::Case => "Case",
178 Token::Default => "Default",
179 Token::Return => "Return",
180 Token::Yield => "Yield",
181 Token::Break => "Break",
182 Token::Continue => "Continue",
183 Token::Import => "Import",
184 Token::From => "From",
185 Token::As => "as",
186 Token::Export => "Export",
187 Token::Throw => "Throw",
188 Token::Identifier(_) => "Identifier",
189 Token::Number(_) => "Number",
190 Token::BigInteger(_) => "BigInteger",
191 Token::String(_) => "String",
192 Token::Boolean(_) => "Boolean",
193 Token::Null => "nil",
194 Token::Plus => "+",
195 Token::Minus => "-",
196 Token::Multiply => "*",
197 Token::Divide => "/",
198 Token::Modulo => "%",
199 Token::Equal => "==",
200 Token::NotEqual => "!=",
201 Token::Less => "<",
202 Token::LessEqual => "<=",
203 Token::Greater => ">",
204 Token::GreaterEqual => ">=",
205 Token::And => "&&",
206 Token::Or => "||",
207 Token::Not => "!",
208 Token::Assign => "=",
209 Token::LeftParen => "(",
210 Token::RightParen => ")",
211 Token::LeftBrace => "{",
212 Token::RightBrace => "}",
213 Token::LeftBracket => "[",
214 Token::RightBracket => "]",
215 Token::Comma => ",",
216 Token::Colon => ":",
217 Token::Semicolon => ";",
218 Token::Newline => "\\n",
219 Token::Arrow => "->",
220 Token::Illegal(_) => "Illegal",
221 Token::EOF => "EOF",
222 }
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
231 fn test_keyword_lookup() {
232 assert_eq!(Token::lookup_keyword("Set"), Token::Set);
233 assert_eq!(Token::lookup_keyword("Func"), Token::Func);
234 assert_eq!(Token::lookup_keyword("If"), Token::If);
235 assert_eq!(Token::lookup_keyword("True"), Token::Boolean(true));
236 assert_eq!(Token::lookup_keyword("False"), Token::Boolean(false));
237 assert_eq!(Token::lookup_keyword("Null"), Token::Null);
238
239 match Token::lookup_keyword("MY_VAR") {
241 Token::Identifier(s) => assert_eq!(s, "MY_VAR"),
242 _ => panic!("Expected identifier"),
243 }
244 }
245
246 #[test]
247 fn test_token_type() {
248 assert_eq!(Token::Set.token_type(), "Set");
249 assert_eq!(Token::Plus.token_type(), "+");
250 assert_eq!(Token::Equal.token_type(), "==");
251 assert_eq!(Token::LeftParen.token_type(), "(");
252 assert_eq!(Token::EOF.token_type(), "EOF");
253 }
254}