Skip to main content

mest_core/
token.rs

1use logos::Logos;
2use std::fmt::Display;
3
4#[derive(Debug, Clone, Logos)]
5pub enum Token<'a> {
6    #[token("if")]
7    If,
8    #[token("then")]
9    Then,
10    #[token("else")]
11    Else,
12    #[token("rec")]
13    Rec,
14    #[token("let")]
15    Let,
16    #[token("in")]
17    In,
18    #[token("true")]
19    True,
20    #[token("false")]
21    False,
22    #[token("match")]
23    Match,
24
25    #[regex(r"[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice())]
26    Ident(&'a str),
27
28    #[regex(r"[0-9]+\.[0-9]+", |lex| lex.slice().parse::<f64>().unwrap())]
29    Float(f64),
30
31    #[regex(r"[0-9]+", |lex| lex.slice().parse::<i64>().unwrap())]
32    Int(i64),
33
34    // comparison
35    #[token("==")]
36    EqEq,
37    #[token("!=")]
38    BangEq,
39    #[token("<=")]
40    LtEq,
41    #[token(">=")]
42    GtEq,
43    #[token("<")]
44    Lt,
45    #[token(">")]
46    Gt,
47
48    // logical
49    #[token("&&")]
50    AndAnd,
51    #[token("||")]
52    PipePipe,
53    #[token("!")]
54    Bang,
55
56    // arithmetic
57    #[token("+")]
58    Plus,
59    #[token("-")]
60    Minus,
61    #[token("*")]
62    Star,
63    #[token("/")]
64    Slash,
65    #[token("^")]
66    Caret,
67
68    // punctuation
69    #[token("|")]
70    Pipe,
71    #[token("=")]
72    Eq,
73    #[token("(")]
74    LParen,
75    #[token(")")]
76    RParen,
77    #[token("=>")]
78    StrongArrow,
79
80    #[regex(r"[ \t\r\n]+", logos::skip)]
81    WhiteSpace,
82
83    Error,
84}
85
86impl Display for Token<'_> {
87    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88        match self {
89            Token::If => write!(f, "if"),
90            Token::Then => write!(f, "then"),
91            Token::Else => write!(f, "else"),
92            Token::Rec => write!(f, "rec"),
93            Token::Let => write!(f, "let"),
94            Token::In => write!(f, "in"),
95            Token::True => write!(f, "true"),
96            Token::False => write!(f, "false"),
97            Token::Ident(v) => write!(f, "{v}"),
98            Token::Float(n) => write!(f, "{n}"),
99            Token::Int(n) => write!(f, "{n}"),
100            Token::EqEq => write!(f, "=="),
101            Token::BangEq => write!(f, "!="),
102            Token::LtEq => write!(f, "<="),
103            Token::GtEq => write!(f, ">="),
104            Token::Lt => write!(f, "<"),
105            Token::Gt => write!(f, ">"),
106            Token::AndAnd => write!(f, "&&"),
107            Token::PipePipe => write!(f, "||"),
108            Token::Bang => write!(f, "!"),
109            Token::Plus => write!(f, "+"),
110            Token::Minus => write!(f, "-"),
111            Token::Star => write!(f, "*"),
112            Token::Slash => write!(f, "/"),
113            Token::Caret => write!(f, "^"),
114            Token::Pipe => write!(f, "|"),
115            Token::Eq => write!(f, "="),
116            Token::LParen => write!(f, "("),
117            Token::RParen => write!(f, ")"),
118            Token::WhiteSpace => write!(f, "<whitespace>"),
119            Token::Error => write!(f, "<error>"),
120            Token::Match => write!(f, "match"),
121            Token::StrongArrow => write!(f, "=>"),
122        }
123    }
124}
125
126impl PartialEq for Token<'_> {
127    fn eq(&self, other: &Self) -> bool {
128        match (self, other) {
129            (Self::Ident(l), Self::Ident(r)) => l == r,
130            (Self::Float(l), Self::Float(r)) => (l.is_nan() && r.is_nan()) || l == r,
131            (Self::Int(l), Self::Int(r)) => l == r,
132            _ => core::mem::discriminant(self) == core::mem::discriminant(other),
133        }
134    }
135}
136
137impl Eq for Token<'_> {}