mf_expression/lexer/
token.rs

1use std::fmt::{Display, Formatter};
2use std::hash::{Hash, Hasher};
3use std::str::FromStr;
4
5use nohash_hasher::IsEnabled;
6use strum_macros::{Display, EnumIter, EnumString, FromRepr, IntoStaticStr};
7
8/// Contains information from lexical analysis
9#[derive(Debug, PartialEq, Eq, Clone)]
10pub struct Token<'a> {
11    pub span: (u32, u32),
12    pub kind: TokenKind,
13    pub value: &'a str,
14}
15
16/// Classification of tokens
17#[derive(Debug, PartialEq, Eq, Clone, Copy, Display)]
18pub enum TokenKind {
19    Identifier(Identifier),
20    Boolean(bool),
21    Number,
22    QuotationMark(QuotationMark),
23    Literal,
24    Operator(Operator),
25    Bracket(Bracket),
26    TemplateString(TemplateString),
27}
28
29#[derive(
30    Debug, PartialEq, Eq, Clone, Copy, Display, EnumString, IntoStaticStr,
31)]
32pub enum Identifier {
33    #[strum(serialize = "$")]
34    ContextReference,
35    #[strum(serialize = "$root")]
36    RootReference,
37    #[strum(serialize = "#")]
38    CallbackReference,
39    #[strum(serialize = "null")]
40    Null,
41}
42
43#[derive(
44    Debug, PartialEq, Eq, Clone, Copy, Display, EnumString, IntoStaticStr,
45)]
46pub enum QuotationMark {
47    #[strum(serialize = "'")]
48    SingleQuote,
49    #[strum(serialize = "\"")]
50    DoubleQuote,
51    #[strum(serialize = "`")]
52    Backtick,
53}
54
55#[derive(Debug, PartialEq, Eq, Clone, Copy, EnumString, IntoStaticStr)]
56pub enum TemplateString {
57    #[strum(serialize = "${")]
58    ExpressionStart,
59    #[strum(serialize = "}")]
60    ExpressionEnd,
61}
62
63impl Display for TemplateString {
64    fn fmt(
65        &self,
66        f: &mut Formatter<'_>,
67    ) -> std::fmt::Result {
68        match *self {
69            TemplateString::ExpressionStart => {
70                ::core::fmt::Display::fmt("${", f)
71            },
72            TemplateString::ExpressionEnd => ::core::fmt::Display::fmt("}}", f),
73        }
74    }
75}
76
77#[derive(Debug, PartialEq, Eq, Clone, Copy)]
78pub enum Operator {
79    Arithmetic(ArithmeticOperator),
80    Logical(LogicalOperator),
81    Comparison(ComparisonOperator),
82    Range,        // ..
83    Comma,        // ,
84    Slice,        // :
85    Dot,          // .
86    QuestionMark, // ?
87    Assign,       // =
88    Semi,         // ;
89}
90
91impl Display for Operator {
92    fn fmt(
93        &self,
94        f: &mut Formatter<'_>,
95    ) -> std::fmt::Result {
96        match self {
97            Operator::Arithmetic(a) => write!(f, "{a}"),
98            Operator::Logical(l) => write!(f, "{l}"),
99            Operator::Comparison(c) => write!(f, "{c}"),
100            Operator::Range => write!(f, ".."),
101            Operator::Comma => write!(f, ","),
102            Operator::Slice => write!(f, ":"),
103            Operator::Dot => write!(f, "."),
104            Operator::QuestionMark => write!(f, "?"),
105            Operator::Assign => write!(f, "="),
106            Operator::Semi => write!(f, ";"),
107        }
108    }
109}
110
111impl FromStr for Operator {
112    type Err = strum::ParseError;
113
114    fn from_str(operator: &str) -> Result<Self, Self::Err> {
115        match operator {
116            ".." => Ok(Operator::Range),
117            "," => Ok(Operator::Comma),
118            ":" => Ok(Operator::Slice),
119            "." => Ok(Operator::Dot),
120            "?" => Ok(Operator::QuestionMark),
121            _ => ArithmeticOperator::try_from(operator)
122                .map(Operator::Arithmetic)
123                .or_else(|_| {
124                    LogicalOperator::try_from(operator).map(Operator::Logical)
125                })
126                .or_else(|_| {
127                    ComparisonOperator::try_from(operator)
128                        .map(Operator::Comparison)
129                }),
130        }
131    }
132}
133
134#[derive(Debug, PartialEq, Eq, Clone, Copy, Display, EnumString)]
135pub enum ArithmeticOperator {
136    #[strum(serialize = "+")]
137    Add,
138    #[strum(serialize = "-")]
139    Subtract,
140    #[strum(serialize = "*")]
141    Multiply,
142    #[strum(serialize = "/")]
143    Divide,
144    #[strum(serialize = "%")]
145    Modulus,
146    #[strum(serialize = "^")]
147    Power,
148}
149
150#[derive(Debug, PartialEq, Eq, Clone, Copy, Display, EnumString)]
151pub enum LogicalOperator {
152    #[strum(serialize = "and")]
153    And,
154    #[strum(serialize = "or")]
155    Or,
156    #[strum(serialize = "not", serialize = "!")]
157    Not,
158    #[strum(serialize = "??")]
159    NullishCoalescing,
160}
161
162#[derive(Debug, PartialEq, Eq, Clone, Copy, Display, EnumString)]
163pub enum ComparisonOperator {
164    #[strum(serialize = "==")]
165    Equal,
166    #[strum(serialize = "!=")]
167    NotEqual,
168    #[strum(serialize = "<")]
169    LessThan,
170    #[strum(serialize = ">")]
171    GreaterThan,
172    #[strum(serialize = "<=")]
173    LessThanOrEqual,
174    #[strum(serialize = ">=")]
175    GreaterThanOrEqual,
176    #[strum(serialize = "in")]
177    In,
178    #[strum(serialize = "not in")]
179    NotIn,
180}
181
182#[derive(
183    Debug,
184    PartialEq,
185    Eq,
186    Clone,
187    Copy,
188    EnumString,
189    IntoStaticStr,
190    EnumIter,
191    FromRepr,
192)]
193pub enum Bracket {
194    #[strum(serialize = "(")]
195    LeftParenthesis,
196    #[strum(serialize = ")")]
197    RightParenthesis,
198    #[strum(serialize = "[")]
199    LeftSquareBracket,
200    #[strum(serialize = "]")]
201    RightSquareBracket,
202    #[strum(serialize = "{")]
203    LeftCurlyBracket,
204    #[strum(serialize = "}")]
205    RightCurlyBracket,
206}
207
208impl Display for Bracket {
209    fn fmt(
210        &self,
211        f: &mut Formatter<'_>,
212    ) -> std::fmt::Result {
213        match *self {
214            Bracket::LeftParenthesis => ::core::fmt::Display::fmt("(", f),
215            Bracket::RightParenthesis => ::core::fmt::Display::fmt(")", f),
216            Bracket::LeftSquareBracket => ::core::fmt::Display::fmt("[", f),
217            Bracket::RightSquareBracket => ::core::fmt::Display::fmt("]", f),
218            Bracket::LeftCurlyBracket => ::core::fmt::Display::fmt("{", f),
219            Bracket::RightCurlyBracket => ::core::fmt::Display::fmt("}}", f),
220        }
221    }
222}
223
224impl Operator {
225    pub fn variant(&self) -> u8 {
226        match &self {
227            Operator::Arithmetic(a) => match a {
228                ArithmeticOperator::Add => 1,
229                ArithmeticOperator::Subtract => 2,
230                ArithmeticOperator::Multiply => 3,
231                ArithmeticOperator::Divide => 4,
232                ArithmeticOperator::Modulus => 5,
233                ArithmeticOperator::Power => 6,
234            },
235            Operator::Logical(l) => match l {
236                LogicalOperator::And => 7,
237                LogicalOperator::Or => 8,
238                LogicalOperator::Not => 9,
239                LogicalOperator::NullishCoalescing => 10,
240            },
241            Operator::Comparison(c) => match c {
242                ComparisonOperator::Equal => 11,
243                ComparisonOperator::NotEqual => 12,
244                ComparisonOperator::LessThan => 13,
245                ComparisonOperator::GreaterThan => 14,
246                ComparisonOperator::LessThanOrEqual => 15,
247                ComparisonOperator::GreaterThanOrEqual => 16,
248                ComparisonOperator::In => 17,
249                ComparisonOperator::NotIn => 18,
250            },
251            Operator::Range => 19,
252            Operator::Comma => 20,
253            Operator::Slice => 21,
254            Operator::Dot => 22,
255            Operator::QuestionMark => 23,
256            Operator::Assign => 24,
257            Operator::Semi => 25,
258        }
259    }
260}
261
262impl Hash for Operator {
263    fn hash<H: Hasher>(
264        &self,
265        state: &mut H,
266    ) {
267        state.write_u8(self.variant());
268    }
269}
270
271impl IsEnabled for Operator {}