1#[derive(Debug, Clone, PartialEq)]
3pub enum TokenType {
4 Fn, Var, Import, Return, Identifier(String),
12 Number(f64),
13 String(String),
14 Color(String), Unit(String), Plus, Minus, Star, Slash, Percent, Equal, NotEqual, Less, Greater, LessEqual, GreaterEqual, Colon, Semicolon, Comma, Dot, At, LeftParen, RightParen, LeftBrace, RightBrace, LeftBracket, RightBracket, Arrow, Assign, Newline,
53 Indent,
54 Dedent,
55
56 Comment(String),
58
59 Eof,
61}
62
63#[derive(Debug, Clone, PartialEq)]
65pub struct Token {
66 pub token_type: TokenType,
67 pub lexeme: String,
68 pub line: usize,
69 pub column: usize,
70}
71
72impl Token {
73 pub fn new(token_type: TokenType, lexeme: String, line: usize, column: usize) -> Self {
75 Self {
76 token_type,
77 lexeme,
78 line,
79 column,
80 }
81 }
82
83 pub fn location(&self) -> crate::error::SourceLocation {
85 crate::error::SourceLocation::new(self.line, self.column)
86 }
87
88 pub fn is_keyword(&self) -> bool {
90 matches!(
91 self.token_type,
92 TokenType::Fn | TokenType::Var | TokenType::Import | TokenType::Return
93 )
94 }
95
96 pub fn is_operator(&self) -> bool {
98 matches!(
99 self.token_type,
100 TokenType::Plus
101 | TokenType::Minus
102 | TokenType::Star
103 | TokenType::Slash
104 | TokenType::Percent
105 )
106 }
107
108 pub fn is_delimiter(&self) -> bool {
110 matches!(
111 self.token_type,
112 TokenType::Colon
113 | TokenType::Semicolon
114 | TokenType::Comma
115 | TokenType::Dot
116 )
117 }
118}
119
120impl std::fmt::Display for Token {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 write!(
123 f,
124 "Token({:?}, '{}', {}:{})",
125 self.token_type, self.lexeme, self.line, self.column
126 )
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_token_creation() {
136 let token = Token::new(TokenType::Identifier("test".to_string()), "test".to_string(), 1, 1);
137 assert_eq!(token.line, 1);
138 assert_eq!(token.column, 1);
139 assert_eq!(token.lexeme, "test");
140 }
141
142 #[test]
143 fn test_is_keyword() {
144 let fn_token = Token::new(TokenType::Fn, "@fn".to_string(), 1, 1);
145 assert!(fn_token.is_keyword());
146
147 let id_token = Token::new(TokenType::Identifier("test".to_string()), "test".to_string(), 1, 1);
148 assert!(!id_token.is_keyword());
149 }
150
151 #[test]
152 fn test_is_operator() {
153 let plus_token = Token::new(TokenType::Plus, "+".to_string(), 1, 1);
154 assert!(plus_token.is_operator());
155 }
156}
157