use std::fmt; #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub struct Span { pub start: usize, pub end: usize, pub start_line: usize, pub start_column: usize, pub end_line: usize, pub end_column: usize, } impl Span { pub fn new( start: usize, end: usize, start_line: usize, start_column: usize, end_line: usize, end_column: usize, ) -> Self { Self { start, end, start_line, start_column, end_line, end_column, } } pub fn single(position: usize, line: usize, column: usize) -> Self { Self::new(position, position, line, column, line, column) } pub fn merge(self, other: Self) -> Self { Self { start: self.start.min(other.start), end: self.end.max(other.end), start_line: self.start_line, start_column: self.start_column, end_line: other.end_line, end_column: other.end_column, } } } #[derive(Debug, Clone, PartialEq)] pub struct Token { pub kind: TokenKind, pub span: Span, } impl Token { pub fn new(kind: TokenKind, span: Span) -> Self { Self { kind, span } } } #[derive(Debug, Clone, PartialEq)] pub enum TokenKind { Identifier(String), Integer(String), Float(String), String(String), Bool(bool), Keyword(Keyword), LeftParen, RightParen, Comma, Colon, Arrow, Plus, Minus, Star, Slash, Percent, Equal, EqualEqual, Bang, BangEqual, Less, LessEqual, Greater, GreaterEqual, AndAnd, OrOr, Newline, Indent, Dedent, Eof, } impl TokenKind { pub fn same_variant(&self, other: &Self) -> bool { std::mem::discriminant(self) == std::mem::discriminant(other) } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Keyword { Else, Fn, If, Let, Pub, Return, Struct, } impl Keyword { pub fn from_ident(value: &str) -> Option { match value { "else" => Some(Self::Else), "fn" => Some(Self::Fn), "if" => Some(Self::If), "let" => Some(Self::Let), "pub" => Some(Self::Pub), "return" => Some(Self::Return), "struct" => Some(Self::Struct), _ => None, } } } impl fmt::Display for TokenKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { TokenKind::Identifier(name) => write!(f, "identifier({name})"), TokenKind::Integer(value) => write!(f, "integer({value})"), TokenKind::Float(value) => write!(f, "float({value})"), TokenKind::String(value) => write!(f, "string({value})"), TokenKind::Bool(value) => write!(f, "bool({value})"), TokenKind::Keyword(keyword) => write!(f, "keyword({keyword:?})"), other => write!(f, "{other:?}"), } } }