krab/common/
tokens.rs

1use std::fmt::Display;
2
3use super::Span;
4
5#[derive(Debug, Clone, PartialEq, PartialOrd)]
6pub struct Token {
7    pub kind: TokenKind,
8    pub span: Span,
9}
10
11impl Token {
12    pub const EOF: Token = Token {
13        kind: TokenKind::Eof,
14        span: Span::ZERO,
15    };
16
17    pub const fn new(kind: TokenKind, span: Span) -> Token {
18        Token { kind, span }
19    }
20
21    pub fn is_eof(&self) -> bool {
22        self.kind == TokenKind::Eof
23    }
24}
25
26impl PartialEq<TokenKind> for Token {
27    fn eq(&self, other: &TokenKind) -> bool {
28        &self.kind == other
29    }
30}
31
32impl Display for Token {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        self.kind.fmt(f)
35    }
36}
37
38// Kind
39#[derive(Debug, Clone, PartialEq, PartialOrd)]
40pub enum TokenKind {
41    Keyword(Keyword),
42    Literal(Literal),
43    Identifier(String),
44    Operator(Operator),
45    Punctuation(Punctuation),
46    Eof,
47    Invalid,
48}
49
50impl Display for TokenKind {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        match self {
53            Self::Keyword(x) => write!(f, "{x}"),
54            Self::Literal(x) => write!(f, "{x}"),
55            Self::Identifier(x) => write!(f, "{x}"),
56            Self::Operator(x) => write!(f, "{x}"),
57            Self::Punctuation(x) => write!(f, "{x}"),
58            Self::Eof => write!(f, "EOF"),
59            Self::Invalid => write!(f, "InvalidToken"),
60        }
61    }
62}
63
64#[derive(Debug, Clone, PartialEq, PartialOrd)]
65pub enum Literal {
66    Integer(i32),
67    Float(f32),
68    String(String),
69    Boolean(bool),
70}
71
72impl Display for Literal {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        match self {
75            Self::Integer(x) => write!(f, "{x}"),
76            Self::Float(x) => write!(f, "{x}"),
77            Self::String(x) => write!(f, "\"{x}\""),
78            Self::Boolean(x) => write!(f, "{x}"),
79        }
80    }
81}
82
83#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
84pub enum Keyword {
85    Let,
86    Const,
87    If,
88    Else,
89    While,
90    Function,
91    Return,
92    Break,
93    Continue,
94}
95
96impl Display for Keyword {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        match self {
99            Self::Let => write!(f, "let"),
100            Self::Const => write!(f, "const"),
101            Self::If => write!(f, "if"),
102            Self::Else => write!(f, "else"),
103            Self::While => write!(f, "while"),
104            Self::Function => write!(f, "fn"),
105            Self::Return => write!(f, "return"),
106            Self::Break => write!(f, "break"),
107            Self::Continue => write!(f, "continue"),
108        }
109    }
110}
111
112pub const SEMICOLON_TOKEN: TokenKind = TokenKind::Punctuation(Punctuation::Semicolon);
113
114#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
115pub enum Operator {
116    Add,
117    Subtract,
118    Multiply,
119    Divide,
120    Modulo,
121    Power,
122    And,
123    Or,
124    Not,
125    Assignment,
126    Equal,
127    NotEqual,
128    Less,
129    Greater,
130    LessOrEqual,
131    GreaterOrEqual,
132    Arrow,
133}
134
135impl Display for Operator {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        match self {
138            Self::Add => write!(f, "+"),
139            Self::Subtract => write!(f, "-"),
140            Self::Multiply => write!(f, "*"),
141            Self::Divide => write!(f, "/"),
142            Self::Modulo => write!(f, "%"),
143            Self::Power => write!(f, "^"),
144            Self::And => write!(f, "&&"),
145            Self::Or => write!(f, "||"),
146            Self::Not => write!(f, "!"),
147            Self::Assignment => write!(f, "="),
148            Self::Equal => write!(f, "=="),
149            Self::NotEqual => write!(f, "!="),
150            Self::Less => write!(f, "<"),
151            Self::Greater => write!(f, ">"),
152            Self::LessOrEqual => write!(f, "<="),
153            Self::GreaterOrEqual => write!(f, ">="),
154            Self::Arrow => write!(f, "->"),
155        }
156    }
157}
158
159impl Operator {
160    pub const fn is_binary(self) -> bool {
161        matches!(
162            self,
163            Operator::Add
164                | Operator::Subtract
165                | Operator::Multiply
166                | Operator::Divide
167                | Operator::Modulo
168                | Operator::Power
169        )
170    }
171
172    pub const fn is_unary(self) -> bool {
173        matches!(self, Operator::Subtract | Operator::Not)
174    }
175
176    pub const fn is_logical(self) -> bool {
177        matches!(
178            self,
179            Operator::Equal
180                | Operator::NotEqual
181                | Operator::Not
182                | Operator::Less
183                | Operator::LessOrEqual
184                | Operator::Greater
185                | Operator::GreaterOrEqual
186        )
187    }
188
189    pub const fn precedence(self) -> u8 {
190        match self {
191            Operator::Or => 1,
192            Operator::And => 2,
193            Operator::Equal | Operator::NotEqual => 3,
194            Operator::Less
195            | Operator::LessOrEqual
196            | Operator::Greater
197            | Operator::GreaterOrEqual => 4,
198            Operator::Add | Operator::Subtract => 5,
199            Operator::Multiply | Operator::Divide | Operator::Modulo => 6,
200            Operator::Power => 7,
201            Operator::Not => 8,
202            _ => 0,
203        }
204    }
205
206    pub const fn associativity(&self) -> Associativity {
207        if self.is_binary() {
208            Associativity::Left
209        } else {
210            Associativity::Right
211        }
212    }
213}
214
215#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
216pub enum Associativity {
217    Left,
218    Right,
219}
220
221#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
222pub enum Punctuation {
223    OpenParenthesis,  // (
224    CloseParenthesis, // )
225    OpenBrace,        // {
226    CloseBrace,       // }
227    OpenBrackets,     // [
228    CloseBrackets,    // ]
229    Semicolon,        // ;
230    Comma,            // ,
231    Colon,            // :
232    Dot,              // .
233    QuestionMark,     // ?
234}
235
236impl Display for Punctuation {
237    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238        match self {
239            Self::OpenParenthesis => write!(f, "("),
240            Self::CloseParenthesis => write!(f, ")"),
241            Self::OpenBrace => write!(f, "{{"),
242            Self::CloseBrace => write!(f, "}}"),
243            Self::OpenBrackets => write!(f, "["),
244            Self::CloseBrackets => write!(f, "]"),
245            Self::Semicolon => write!(f, ";"),
246            Self::Comma => write!(f, ","),
247            Self::Colon => write!(f, ":"),
248            Self::Dot => write!(f, "."),
249            Self::QuestionMark => write!(f, "?"),
250        }
251    }
252}