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