use rust_decimal::Decimal; #[derive(Debug, PartialEq, Eq, Clone)] pub struct Token { /// The type of the token pub token_type: TokenType, /// The line where the token was found pub line: usize, /// The column where the token was found pub column: usize, } impl Token { pub fn new(token_type: TokenType, line: usize, column: usize) -> Self { Self { token_type, line, column, } } } #[derive(Debug, PartialEq, Hash, Eq, Clone)] pub enum Temperature { Celsius(Number), Fahrenheit(Number), Kelvin(Number), } impl std::fmt::Display for Temperature { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Temperature::Celsius(n) => write!(f, "{}°C", n), Temperature::Fahrenheit(n) => write!(f, "{}°F", n), Temperature::Kelvin(n) => write!(f, "{}K", n), } } } impl Temperature { pub fn to_kelvin(self) -> Number { match self { Temperature::Celsius(n) => { let n = match n { Number::Integer(i) => Decimal::new(i as i64, 0), Number::Decimal(d) => d, }; Number::Decimal(n + Decimal::new(27315, 2)) } Temperature::Fahrenheit(n) => { let n = match n { Number::Integer(i) => Decimal::new(i as i64, 0), Number::Decimal(d) => d, }; let a = n - Decimal::new(32, 0); let b = Decimal::new(5, 0) / Decimal::new(9, 0); Number::Decimal(a * b + Decimal::new(27315, 2)) } Temperature::Kelvin(n) => n, } } } #[derive(Debug, PartialEq, Hash, Eq, Clone)] pub enum TokenType { /// Represents a string token String(String), /// Represents a number token Number(Number), /// Represents a boolean token Boolean(bool), /// Represents a keyword token Keyword(Keyword), /// Represents an identifier token Identifier(String), /// Represents a symbol token Symbol(Symbol), /// Represents an end of file token EOF, } impl std::fmt::Display for TokenType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TokenType::String(s) => write!(f, "{}", s), TokenType::Number(n) => write!(f, "{}", n), TokenType::Boolean(b) => write!(f, "{}", b), TokenType::Keyword(k) => write!(f, "{:?}", k), TokenType::Identifier(i) => write!(f, "{}", i), TokenType::Symbol(s) => write!(f, "{:?}", s), TokenType::EOF => write!(f, "EOF"), } } } #[derive(Debug, PartialEq, Hash, Eq, Clone, Copy)] pub enum Number { /// Represents an integer number Integer(u128), /// Represents a decimal type number with a precision of 64 bits Decimal(Decimal), } impl std::fmt::Display for Number { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Number::Integer(i) => write!(f, "{}", i), Number::Decimal(d) => write!(f, "{}", d), } } } impl std::convert::From for String { fn from(value: Number) -> Self { value.to_string() } } #[derive(Debug, PartialEq, Hash, Eq, Clone, Copy)] pub enum Symbol { // Single Character Symbols /// Represents the `(` symbol LParen, /// Represents the `)` symbol RParen, /// Represents the `{` symbol LBrace, /// Represents the `}` symbol RBrace, /// Represents the `[` symbol LBracket, /// Represents the `]` symbol RBracket, /// Represents the `;` symbol Semicolon, /// Represents the `:` symbol Colon, /// Represents the `,` symbol Comma, /// Represents the `+` symbol Plus, /// Represents the `-` symbol Minus, /// Represents the `*` symbol Asterisk, /// Represents the `/` symbol Slash, /// Represents the `<` symbol LessThan, /// Represents the `>` symbol GreaterThan, /// Represents the `=` symbol Assign, /// Represents the `!` symbol LogicalNot, /// Represents the `.` symbol Dot, /// Represents the `^` symbol Caret, /// Represents the `%` symbol Percent, // Double Character Symbols /// Represents the `==` symbol Equal, /// Represents the `!=` symbol NotEqual, /// Represents the `&&` Symbol LogicalAnd, // Represents the `||` Symbol LogicalOr, /// Represents the `<=` symbol LessThanOrEqual, /// Represents the `>=` symbol GreaterThanOrEqual, /// Represents the `**` symbol Exp, } impl Symbol { pub fn is_operator(&self) -> bool { matches!( self, Symbol::Plus | Symbol::Minus | Symbol::Asterisk | Symbol::Slash | Symbol::Exp | Symbol::Percent ) } pub fn is_comparison(&self) -> bool { matches!( self, Symbol::LessThan | Symbol::GreaterThan | Symbol::Equal | Symbol::NotEqual | Symbol::LessThanOrEqual | Symbol::GreaterThanOrEqual, ) } pub fn is_logical(&self) -> bool { matches!(self, Symbol::LogicalAnd | Symbol::LogicalOr) } } #[derive(Debug, PartialEq, Hash, Eq, Clone, Copy)] pub enum Keyword { /// Represents the `continue` keyword Continue, /// Represents the `let` keyword Let, /// Represents the `fn` keyword Fn, /// Represents the `if` keyword If, /// Represents the `device` keyword. Useful for defining a device at a specific address (ex. d0, d1, d2, etc.) Device, /// Represents the `else` keyword Else, /// Represents the `return` keyword Return, /// Represents the `enum` keyword Enum, /// Represents the `loop` keyword Loop, /// Represents the `break` keyword Break, /// Represents the `while` keyword While, }