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#[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#[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, Comma, Slice, Dot, QuestionMark, Assign, Semi, }
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 {}