1use crate::ast;
5use crate::ast::Span;
6use std::num::ParseIntError;
7
8#[derive(Debug, PartialEq)]
10pub struct BinaryOperator {
11 pub span: Span,
13 pub operation: BinaryOperatorType,
15}
16
17#[derive(Debug, PartialEq, Clone)]
19#[allow(missing_docs)]
20pub enum BinaryOperatorType {
21 Add,
22 Subtract,
23 Multiply,
24 Divide,
25 Union,
26 Intersect,
27 PowerXor,
28 GreaterThan,
29 LessThan,
30 GreaterEqual,
31 LessEqual,
32 Equal,
33 Near,
34 NotEqual,
35 And,
36 Or,
37 Xor,
38}
39
40impl BinaryOperatorType {
41 pub fn as_str(&self) -> &'static str {
43 match self {
44 Self::Add => "+",
45 Self::Subtract => "-",
46 Self::Multiply => "*",
47 Self::Divide => "/",
48 Self::Union => "|",
49 Self::Intersect => "&",
50 Self::PowerXor => "^",
51 Self::GreaterThan => ">",
52 Self::LessThan => "<",
53 Self::GreaterEqual => "≥",
54 Self::LessEqual => "≤",
55 Self::Equal => "==",
56 Self::Near => "~",
57 Self::NotEqual => "!=",
58 Self::And => "&",
59 Self::Or => "|",
60 Self::Xor => "^",
61 }
62 }
63}
64
65#[derive(Debug, PartialEq)]
67pub struct UnaryOperator {
68 pub span: Span,
70 pub operation: UnaryOperatorType,
72}
73
74#[derive(Debug, PartialEq, Clone)]
76#[allow(missing_docs)]
77pub enum UnaryOperatorType {
78 Minus,
79 Plus,
80 Not,
81}
82
83impl UnaryOperatorType {
84 pub fn as_str(&self) -> &'static str {
86 match self {
87 UnaryOperatorType::Minus => "-",
88 UnaryOperatorType::Plus => "+",
89 UnaryOperatorType::Not => "!",
90 }
91 }
92}
93
94#[derive(Debug, PartialEq)]
96pub enum Expression {
97 Literal(ast::Literal),
99 Bracketed(Box<Expression>, Span),
101 Tuple(TupleExpression),
103 ArrayRange(ArrayRangeExpression),
105 ArrayList(ArrayListExpression),
107 String(FormatString),
109 QualifiedName(QualifiedName),
111 Marker(ast::Identifier),
113 BinaryOperation(BinaryOperation),
115 UnaryOperation(UnaryOperation),
117 Body(ast::Body),
119 Call(Call),
121 ElementAccess(ElementAccess),
123 If(If),
125 Error(Span),
127}
128
129impl Expression {
130 pub fn span(&self) -> Span {
132 match self {
133 Expression::Literal(ex) => ex.span.clone(),
134 Expression::Bracketed(_, span) => span.clone(),
135 Expression::Tuple(ex) => ex.span.clone(),
136 Expression::ArrayRange(ex) => ex.span.clone(),
137 Expression::ArrayList(ex) => ex.span.clone(),
138 Expression::String(ex) => ex.span.clone(),
139 Expression::QualifiedName(ex) => ex.span.clone(),
140 Expression::Marker(ex) => ex.span.clone(),
141 Expression::BinaryOperation(ex) => ex.span.clone(),
142 Expression::UnaryOperation(ex) => ex.span.clone(),
143 Expression::Body(ex) => ex.span.clone(),
144 Expression::Call(ex) => ex.span.clone(),
145 Expression::ElementAccess(ex) => ex.span.clone(),
146 Expression::If(ex) => ex.span.clone(),
147 Expression::Error(span) => span.clone(),
148 }
149 }
150
151 pub fn is_also_statement(&self) -> bool {
153 matches!(self, Expression::Body(_) | Expression::If(_))
154 }
155}
156
157#[derive(Debug, PartialEq)]
159#[allow(missing_docs)]
160pub struct FormatString {
161 pub span: Span,
162 pub extras: ast::ItemExtras,
163 pub parts: Vec<StringPart>,
164}
165
166#[derive(Debug, PartialEq)]
168#[allow(missing_docs)]
169pub enum StringPart {
170 Char(StringCharacter),
171 Content(ast::StringLiteral),
172 Expression(StringExpression),
173}
174
175#[derive(Debug, PartialEq)]
177#[allow(missing_docs)]
178pub struct StringCharacter {
179 pub span: Span,
180 pub character: char,
181}
182
183#[derive(Debug, PartialEq)]
185#[allow(missing_docs)]
186pub struct StringExpression {
187 pub span: Span,
188 pub extras: ast::ItemExtras,
189 pub expression: Box<Expression>,
190 pub specification: Box<StringFormatSpecification>,
191}
192
193#[derive(Debug, PartialEq)]
197#[allow(missing_docs)]
198pub struct StringFormatSpecification {
199 pub span: Span,
200 pub precision: Option<Result<u32, (ParseIntError, Span)>>,
201 pub width: Option<Result<u32, (ParseIntError, Span)>>,
202}
203
204impl StringFormatSpecification {
205 pub fn is_some(&self) -> bool {
207 self.precision.is_some() || self.width.is_some()
208 }
209}
210
211#[derive(Debug, PartialEq)]
213#[allow(missing_docs)]
214pub struct TupleItem {
215 pub span: Span,
216 pub extras: ast::ItemExtras,
217 pub name: Option<ast::Identifier>,
218 pub value: Expression,
219}
220
221impl ast::Dummy for TupleItem {
222 fn dummy(span: Span) -> Self {
223 Self {
224 span: span.clone(),
225 extras: ast::ItemExtras::default(),
226 name: None,
227 value: Expression::Error(span),
228 }
229 }
230}
231
232#[derive(Debug, PartialEq)]
234#[allow(missing_docs)]
235pub struct TupleExpression {
236 pub span: Span,
237 pub extras: ast::ItemExtras,
238 pub values: Vec<TupleItem>,
239}
240
241#[derive(Debug, PartialEq)]
243#[allow(missing_docs)]
244pub struct ArrayRangeExpression {
245 pub span: Span,
246 pub extras: ast::ItemExtras,
247 pub start: Box<ArrayItem>,
248 pub end: Box<ArrayItem>,
249 pub unit: Option<ast::Unit>,
250}
251
252#[derive(Debug, PartialEq)]
254#[allow(missing_docs)]
255pub struct ArrayListExpression {
256 pub span: Span,
257 pub extras: ast::ItemExtras,
258 pub items: Vec<ArrayItem>,
259 pub unit: Option<ast::Unit>,
260}
261
262#[derive(Debug, PartialEq)]
264#[allow(missing_docs)]
265pub struct ArrayItem {
266 pub span: Span,
267 pub extras: ast::ItemExtras,
268 pub expression: Expression,
269}
270
271#[derive(Debug, PartialEq)]
273#[allow(missing_docs)]
274pub struct QualifiedName {
275 pub span: Span,
276 pub extras: ast::ItemExtras,
277 pub parts: Vec<ast::Identifier>,
278}
279
280#[derive(Debug, PartialEq)]
282#[allow(missing_docs)]
283pub struct BinaryOperation {
284 pub span: Span,
285 pub lhs: Box<Expression>,
286 pub operation: BinaryOperator,
287 pub rhs: Box<Expression>,
288}
289
290#[derive(Debug, PartialEq)]
292#[allow(missing_docs)]
293pub struct UnaryOperation {
294 pub span: Span,
295 pub extras: ast::ItemExtras,
296 pub operation: UnaryOperator,
297 pub rhs: Box<Expression>,
298}
299
300#[derive(Debug, PartialEq)]
302#[allow(missing_docs)]
303pub struct Call {
304 pub span: Span,
305 pub extras: ast::ItemExtras,
306 pub name: QualifiedName,
307 pub arguments: ArgumentList,
308}
309
310#[derive(Debug, PartialEq)]
314#[allow(missing_docs)]
315pub struct ElementAccess {
316 pub span: Span,
317 pub value: Box<Expression>,
318 pub element_chain: Vec<Element>,
319}
320
321#[derive(Debug, PartialEq)]
323#[allow(missing_docs)]
324pub enum ElementInner {
325 Attribute(ast::Identifier),
326 Tuple(ast::Identifier),
327 Method(Call),
328 ArrayElement(Box<Expression>),
329}
330
331#[derive(Debug, PartialEq)]
332#[allow(missing_docs)]
333pub struct Element {
334 pub span: Span,
335 pub extras: ast::ItemExtras,
336 pub inner: ElementInner,
337}
338
339#[derive(Debug, PartialEq)]
340#[allow(missing_docs)]
341pub struct Body {
342 pub span: Span,
343 pub statements: ast::StatementList,
344}
345
346#[derive(Debug, PartialEq)]
348#[allow(missing_docs)]
349pub struct If {
350 pub span: Span,
351 pub if_span: Span,
352 pub extras: ast::ItemExtras,
353 pub condition: Box<Expression>,
354 pub body: Body,
355 pub next_if_span: Option<Span>,
356 pub next_if: Option<Box<If>>,
357 pub else_span: Option<Span>,
358 pub else_body: Option<Body>,
359}
360
361#[derive(Debug, PartialEq)]
363#[allow(missing_docs)]
364pub struct ArgumentList {
365 pub span: Span,
366 pub extras: ast::ItemExtras,
367 pub arguments: Vec<Argument>,
368}
369
370impl ast::Dummy for ArgumentList {
371 fn dummy(span: Span) -> Self {
372 Self {
373 span,
374 extras: ast::ItemExtras::default(),
375 arguments: Vec::new(),
376 }
377 }
378}
379
380#[derive(Debug, PartialEq)]
382#[allow(missing_docs)]
383pub enum Argument {
384 Unnamed(UnnamedArgument),
385 Named(NamedArgument),
386}
387
388impl Argument {
389 pub fn name(&self) -> Option<&ast::Identifier> {
391 match self {
392 Argument::Unnamed(_) => None,
393 Argument::Named(arg) => Some(&arg.name),
394 }
395 }
396
397 pub fn value(&self) -> &Expression {
399 match self {
400 Argument::Unnamed(arg) => &arg.value,
401 Argument::Named(arg) => &arg.value,
402 }
403 }
404
405 pub fn span(&self) -> &Span {
407 match self {
408 Argument::Unnamed(arg) => &arg.span,
409 Argument::Named(arg) => &arg.span,
410 }
411 }
412}
413
414#[derive(Debug, PartialEq)]
416#[allow(missing_docs)]
417pub struct UnnamedArgument {
418 pub span: Span,
419 pub extras: ast::ItemExtras,
420 pub value: Expression,
421}
422
423#[derive(Debug, PartialEq)]
425#[allow(missing_docs)]
426pub struct NamedArgument {
427 pub span: Span,
428 pub extras: ast::ItemExtras,
429 pub name: ast::Identifier,
430 pub value: Expression,
431}