use std::any::Any; use std::fmt; /// struct that contains a single token pub struct Token<'a> { // the type pub token_type: TokenType, // the actual part of the code that resulted in this token pub lexeme: &'a str, // numeric (ie 1,2, 1.0 etc) and alphanumeric (any quoted text) values pub literal: Box, // the line that contains the code for this token instance pub line: usize, } impl Token<'_> { pub fn get_literal_as_string(&self) -> Option<&str> { self.literal.downcast_ref::().map(|s| s.as_str()) } pub fn get_literal_as_float(&self) -> Option { self.literal.downcast_ref::().map(|f| *f) } } impl fmt::Debug for Token<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let lit = match self.literal.downcast_ref::() { Some(as_string) => { as_string.to_string() } None => { format!("{:?}", self.literal) } }; write!(f, "Token [ type: {:?}, lexeme: {}, literal: {}, line: {} ]", self.token_type, self.lexeme, lit, self.line) } } #[derive(Eq, PartialEq, Debug, Clone, Copy)] pub enum TokenType { // Single-character tokens. LEFTPAREN, RIGHTPAREN, LEFTBRACE, RIGHTBRACE, COMMA, DOT, MINUS, PLUS, SEMICOLON, STAR, SLASH, // One or two character tokens. BANG, BANGEQUAL, EQUAL, EQUALEQUAL, GREATER, GREATEREQUAL, LESS, LESSEQUAL, // Literals. STRING, NUMBER, IDENTIFIER, // Keywords. AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR, PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE, EOF, // end of file }