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}
79
80impl Display for Operator {
81    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
82        match self {
83            Operator::Arithmetic(a) => write!(f, "{a}"),
84            Operator::Logical(l) => write!(f, "{l}"),
85            Operator::Comparison(c) => write!(f, "{c}"),
86            Operator::Range => write!(f, ".."),
87            Operator::Comma => write!(f, ","),
88            Operator::Slice => write!(f, ":"),
89            Operator::Dot => write!(f, "."),
90            Operator::QuestionMark => write!(f, "?"),
91        }
92    }
93}
94
95impl FromStr for Operator {
96    type Err = strum::ParseError;
97
98    fn from_str(operator: &str) -> Result<Self, Self::Err> {
99        match operator {
100            ".." => Ok(Operator::Range),
101            "," => Ok(Operator::Comma),
102            ":" => Ok(Operator::Slice),
103            "." => Ok(Operator::Dot),
104            "?" => Ok(Operator::QuestionMark),
105            _ => ArithmeticOperator::try_from(operator)
106                .map(Operator::Arithmetic)
107                .or_else(|_| LogicalOperator::try_from(operator).map(Operator::Logical))
108                .or_else(|_| ComparisonOperator::try_from(operator).map(Operator::Comparison)),
109        }
110    }
111}
112
113#[derive(Debug, PartialEq, Eq, Clone, Copy, Display, EnumString)]
114pub enum ArithmeticOperator {
115    #[strum(serialize = "+")]
116    Add,
117    #[strum(serialize = "-")]
118    Subtract,
119    #[strum(serialize = "*")]
120    Multiply,
121    #[strum(serialize = "/")]
122    Divide,
123    #[strum(serialize = "%")]
124    Modulus,
125    #[strum(serialize = "^")]
126    Power,
127}
128
129#[derive(Debug, PartialEq, Eq, Clone, Copy, Display, EnumString)]
130pub enum LogicalOperator {
131    #[strum(serialize = "and")]
132    And,
133    #[strum(serialize = "or")]
134    Or,
135    #[strum(serialize = "not", serialize = "!")]
136    Not,
137    #[strum(serialize = "??")]
138    NullishCoalescing,
139}
140
141#[derive(Debug, PartialEq, Eq, Clone, Copy, Display, EnumString)]
142pub enum ComparisonOperator {
143    #[strum(serialize = "==")]
144    Equal,
145    #[strum(serialize = "!=")]
146    NotEqual,
147    #[strum(serialize = "<")]
148    LessThan,
149    #[strum(serialize = ">")]
150    GreaterThan,
151    #[strum(serialize = "<=")]
152    LessThanOrEqual,
153    #[strum(serialize = ">=")]
154    GreaterThanOrEqual,
155    #[strum(serialize = "in")]
156    In,
157    #[strum(serialize = "not in")]
158    NotIn,
159}
160
161#[derive(Debug, PartialEq, Eq, Clone, Copy, EnumString, IntoStaticStr, EnumIter, FromRepr)]
162pub enum Bracket {
163    #[strum(serialize = "(")]
164    LeftParenthesis,
165    #[strum(serialize = ")")]
166    RightParenthesis,
167    #[strum(serialize = "[")]
168    LeftSquareBracket,
169    #[strum(serialize = "]")]
170    RightSquareBracket,
171    #[strum(serialize = "{")]
172    LeftCurlyBracket,
173    #[strum(serialize = "}")]
174    RightCurlyBracket,
175}
176
177impl Display for Bracket {
178    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
179        match *self {
180            Bracket::LeftParenthesis => ::core::fmt::Display::fmt("(", f),
181            Bracket::RightParenthesis => ::core::fmt::Display::fmt(")", f),
182            Bracket::LeftSquareBracket => ::core::fmt::Display::fmt("[", f),
183            Bracket::RightSquareBracket => ::core::fmt::Display::fmt("]", f),
184            Bracket::LeftCurlyBracket => ::core::fmt::Display::fmt("{", f),
185            Bracket::RightCurlyBracket => ::core::fmt::Display::fmt("}}", f),
186        }
187    }
188}
189
190impl Operator {
191    pub fn variant(&self) -> u8 {
192        match &self {
193            Operator::Arithmetic(a) => match a {
194                ArithmeticOperator::Add => 1,
195                ArithmeticOperator::Subtract => 2,
196                ArithmeticOperator::Multiply => 3,
197                ArithmeticOperator::Divide => 4,
198                ArithmeticOperator::Modulus => 5,
199                ArithmeticOperator::Power => 6,
200            },
201            Operator::Logical(l) => match l {
202                LogicalOperator::And => 7,
203                LogicalOperator::Or => 8,
204                LogicalOperator::Not => 9,
205                LogicalOperator::NullishCoalescing => 10,
206            },
207            Operator::Comparison(c) => match c {
208                ComparisonOperator::Equal => 11,
209                ComparisonOperator::NotEqual => 12,
210                ComparisonOperator::LessThan => 13,
211                ComparisonOperator::GreaterThan => 14,
212                ComparisonOperator::LessThanOrEqual => 15,
213                ComparisonOperator::GreaterThanOrEqual => 16,
214                ComparisonOperator::In => 17,
215                ComparisonOperator::NotIn => 18,
216            },
217            Operator::Range => 19,
218            Operator::Comma => 20,
219            Operator::Slice => 21,
220            Operator::Dot => 22,
221            Operator::QuestionMark => 23,
222        }
223    }
224}
225
226impl Hash for Operator {
227    fn hash<H: Hasher>(&self, state: &mut H) {
228        state.write_u8(self.variant());
229    }
230}
231
232impl IsEnabled for Operator {}