1#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Span {
7 pub offset: usize,
8 pub line: u32,
9 pub column: usize,
10 pub len: usize,
11}
12
13impl Span {
14 pub fn dummy() -> Self {
16 Self {
17 offset: 0,
18 line: 1,
19 column: 1,
20 len: 0,
21 }
22 }
23
24 pub fn to_lsp_range(&self) -> (u32, u32, u32, u32) {
26 let start_line = self.line.saturating_sub(1);
27 let start_char = self.column.saturating_sub(1);
28 let end_char = start_char.saturating_add(self.len);
29 (start_line, start_char as u32, start_line, end_char as u32)
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use super::Span;
36
37 #[test]
38 fn span_dummy() {
39 let s = Span::dummy();
40 assert_eq!(s.offset, 0);
41 assert_eq!(s.line, 1);
42 assert_eq!(s.column, 1);
43 assert_eq!(s.len, 0);
44 }
45}
46
47#[derive(Debug, Clone)]
48pub struct Node<T> {
49 pub span: Span,
50 pub value: T,
51}
52
53impl<T: PartialEq> PartialEq for Node<T> {
54 fn eq(&self, other: &Self) -> bool {
55 self.value == other.value
56 }
57}
58
59impl<T: Eq> Eq for Node<T> {}
60
61impl<T> Node<T> {
62 pub fn new(span: Span, value: T) -> Self {
63 Self { span, value }
64 }
65}
66
67impl<T> std::ops::Deref for Node<T> {
68 type Target = T;
69 fn deref(&self) -> &T {
70 &self.value
71 }
72}
73
74pub trait AstNode {
76 fn span(&self) -> Span;
77}
78
79impl<T> AstNode for Node<T> {
80 fn span(&self) -> Span {
81 self.span.clone()
82 }
83}
84
85#[derive(Debug, Clone, PartialEq, Eq)]
87pub enum BinaryOperator {
88 Eq,
89 Ne,
90 StrictEq,
91 StrictNe,
92 Lt,
93 Le,
94 Gt,
95 Ge,
96 Add,
97 Sub,
98 Mul,
99 Div,
100 Mod,
101 Exp,
102 Pow,
103 And,
104 Or,
105 Xor,
106 Implies,
107 Range,
108 BitOr,
109 BitAnd,
110 Other(String),
112}
113
114impl BinaryOperator {
115 pub fn from_token(token: &str) -> Self {
116 match token {
117 "==" => Self::Eq,
118 "!=" => Self::Ne,
119 "===" => Self::StrictEq,
120 "!==" => Self::StrictNe,
121 "<" => Self::Lt,
122 "<=" => Self::Le,
123 ">" => Self::Gt,
124 ">=" => Self::Ge,
125 "+" => Self::Add,
126 "-" => Self::Sub,
127 "*" => Self::Mul,
128 "/" => Self::Div,
129 "%" => Self::Mod,
130 "^" => Self::Pow,
131 "**" => Self::Exp,
132 "&&" | "and" => Self::And,
133 "||" | "or" => Self::Or,
134 "xor" => Self::Xor,
135 "implies" => Self::Implies,
136 ".." => Self::Range,
137 "|" => Self::BitOr,
138 "&" => Self::BitAnd,
139 other => Self::Other(other.to_string()),
140 }
141 }
142
143 pub fn as_str(&self) -> &str {
144 match self {
145 Self::Eq => "==",
146 Self::Ne => "!=",
147 Self::StrictEq => "===",
148 Self::StrictNe => "!==",
149 Self::Lt => "<",
150 Self::Le => "<=",
151 Self::Gt => ">",
152 Self::Ge => ">=",
153 Self::Add => "+",
154 Self::Sub => "-",
155 Self::Mul => "*",
156 Self::Div => "/",
157 Self::Mod => "%",
158 Self::Pow => "^",
159 Self::Exp => "**",
160 Self::And => "&&",
161 Self::Or => "||",
162 Self::Xor => "xor",
163 Self::Implies => "implies",
164 Self::Range => "..",
165 Self::BitOr => "|",
166 Self::BitAnd => "&",
167 Self::Other(s) => s.as_str(),
168 }
169 }
170}
171
172#[derive(Debug, Clone, PartialEq, Eq)]
174pub enum TypeCheckKind {
175 Istype,
176 Hastype,
177 As,
178}
179
180#[derive(Debug, Clone, PartialEq, Eq)]
182pub enum UnaryOperator {
183 Plus,
184 Minus,
185 Not,
186 BitNot,
187 Other(String),
188}
189
190impl UnaryOperator {
191 pub fn from_token(token: &str) -> Self {
192 match token {
193 "+" => Self::Plus,
194 "-" => Self::Minus,
195 "not" => Self::Not,
196 "~" => Self::BitNot,
197 other => Self::Other(other.to_string()),
198 }
199 }
200
201 pub fn as_str(&self) -> &str {
202 match self {
203 Self::Plus => "+",
204 Self::Minus => "-",
205 Self::Not => "not",
206 Self::BitNot => "~",
207 Self::Other(s) => s.as_str(),
208 }
209 }
210}
211
212#[derive(Debug, Clone, PartialEq, Eq)]
214pub enum Expression {
215 LiteralInteger(i64),
216 LiteralReal(String),
217 LiteralString(String),
218 LiteralBoolean(bool),
219 FeatureRef(String),
221 MemberAccess(Box<Node<Expression>>, String),
223 Index {
225 base: Box<Node<Expression>>,
226 index: Box<Node<Expression>>,
227 },
228 Bracket(Box<Node<Expression>>),
230 LiteralWithUnit {
232 value: Box<Node<Expression>>,
233 unit: Box<Node<Expression>>,
234 },
235 BinaryOp {
237 op: BinaryOperator,
238 left: Box<Node<Expression>>,
239 right: Box<Node<Expression>>,
240 },
241 UnaryOp {
243 op: UnaryOperator,
244 operand: Box<Node<Expression>>,
245 },
246 Invocation {
248 callee: Box<Node<Expression>>,
249 args: Vec<Node<Expression>>,
250 },
251 Tuple(Vec<Node<Expression>>),
253 Classification {
255 metaclass: String,
256 },
257 TypeCheck {
259 kind: TypeCheckKind,
260 operand: Option<Box<Node<Expression>>>,
261 type_name: String,
262 },
263 Select {
265 base: Box<Node<Expression>>,
266 selector: String,
267 },
268 Collect {
270 base: Box<Node<Expression>>,
271 selector: String,
272 },
273 Null,
275}
276
277impl Expression {
278 pub fn is_boolean_literal(&self) -> bool {
280 matches!(self, Self::LiteralBoolean(_))
281 }
282
283 pub fn is_classification(&self) -> bool {
285 matches!(self, Self::Classification { .. })
286 }
287
288 pub fn is_type_check(&self) -> bool {
290 matches!(self, Self::TypeCheck { .. })
291 }
292
293 pub fn binary_op_is_comparison(op: &BinaryOperator) -> bool {
295 matches!(
296 op,
297 BinaryOperator::Eq
298 | BinaryOperator::Ne
299 | BinaryOperator::StrictEq
300 | BinaryOperator::StrictNe
301 | BinaryOperator::Lt
302 | BinaryOperator::Le
303 | BinaryOperator::Gt
304 | BinaryOperator::Ge
305 )
306 }
307
308 pub fn binary_op_is_logical(op: &BinaryOperator) -> bool {
310 matches!(
311 op,
312 BinaryOperator::And
313 | BinaryOperator::Or
314 | BinaryOperator::Xor
315 | BinaryOperator::Implies
316 )
317 }
318}