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