galvan_ast/item/
infix_operator.rs

1use derive_more::From;
2use galvan_ast_macro::PrintAst;
3
4use crate::{Expression, Ident, PrintAst};
5
6use super::ExpressionKind;
7
8pub trait InfixOperator {
9    fn symbol(&self) -> &str;
10}
11
12#[derive(Clone, Debug, PartialEq, Eq, From, PrintAst)]
13pub enum InfixExpression {
14    Logical(InfixOperation<LogicalOperator>),
15    Arithmetic(InfixOperation<ArithmeticOperator>),
16    Collection(InfixOperation<CollectionOperator>),
17    Range(InfixOperation<RangeOperator>),
18    Comparison(InfixOperation<ComparisonOperator>),
19    Member(InfixOperation<MemberOperator>),
20    Unwrap(InfixOperation<UnwrapOperator>),
21    Custom(InfixOperation<CustomInfix>),
22}
23
24impl InfixExpression {
25    pub fn is_comparison(&self) -> bool {
26        matches!(self, Self::Comparison(_))
27    }
28}
29
30#[derive(Clone, Debug, PartialEq, Eq, From)]
31pub struct InfixOperation<Op: InfixOperator> {
32    pub lhs: Expression,
33    pub operator: Op,
34    pub rhs: Expression,
35}
36
37impl<T: InfixOperator> PrintAst for InfixOperation<T> {
38    fn print_ast(&self, indent: usize) -> String {
39        let indent_str = " ".repeat(indent);
40        let mut result = format!("{}{}\n", indent_str, stringify!(#struct_name));
41
42        let field_value = self.lhs.print_ast(indent + 2);
43        result.push_str(&format!("{}  {}{}\n", indent_str, "lhs", field_value));
44
45        result.push_str(&format!(
46            "{}  {}{}\n",
47            indent_str,
48            "op",
49            self.operator.symbol()
50        ));
51
52        let field_value = self.lhs.print_ast(indent + 2);
53        result.push_str(&format!("{}  {}{}\n", indent_str, "rhs", field_value));
54
55        result
56    }
57}
58
59impl InfixOperation<MemberOperator> {
60    pub fn is_field(&self) -> bool {
61        match self.rhs.kind {
62            ExpressionKind::Ident(_) => true,
63            // TODO: Expression::Postfix(p) => match self p.without_postfix() {
64            // Expression::Ident(_) => true, _ => false },
65            _ => false,
66        }
67    }
68
69    pub fn field_ident(&self) -> Option<&Ident> {
70        match &self.rhs.kind {
71            ExpressionKind::Ident(ident) => Some(ident),
72            _ => None,
73        }
74    }
75}
76
77#[derive(Clone, Debug, PartialEq, Eq)]
78pub enum LogicalOperator {
79    Or,
80    And,
81    Xor,
82}
83
84impl InfixOperator for LogicalOperator {
85    fn symbol(&self) -> &str {
86        match self {
87            LogicalOperator::Or => "||",
88            LogicalOperator::And => "&&",
89            LogicalOperator::Xor => "^",
90        }
91    }
92}
93
94#[derive(Clone, Debug, PartialEq, Eq)]
95pub enum ArithmeticOperator {
96    Add,
97    Sub,
98    Mul,
99    Div,
100    Rem,
101    Exp,
102}
103
104impl InfixOperator for ArithmeticOperator {
105    fn symbol(&self) -> &str {
106        match self {
107            ArithmeticOperator::Add => "+",
108            ArithmeticOperator::Sub => "-",
109            ArithmeticOperator::Mul => "*",
110            ArithmeticOperator::Div => "/",
111            ArithmeticOperator::Rem => "%",
112            ArithmeticOperator::Exp => "^",
113        }
114    }
115}
116
117#[derive(Clone, Debug, PartialEq, Eq)]
118pub enum CollectionOperator {
119    Concat,
120    Remove,
121    Contains,
122}
123
124impl InfixOperator for CollectionOperator {
125    fn symbol(&self) -> &str {
126        match self {
127            CollectionOperator::Concat => "++",
128            CollectionOperator::Remove => "--",
129            CollectionOperator::Contains => "in",
130        }
131    }
132}
133
134#[derive(Clone, Debug, PartialEq, Eq)]
135pub enum ComparisonOperator {
136    LessEqual,
137    Less,
138    GreaterEqual,
139    Greater,
140    Equal,
141    NotEqual,
142    Identical,
143    NotIdentical,
144}
145
146impl InfixOperator for ComparisonOperator {
147    fn symbol(&self) -> &str {
148        match self {
149            ComparisonOperator::LessEqual => "≤",
150            ComparisonOperator::Less => "<",
151            ComparisonOperator::GreaterEqual => "≥",
152            ComparisonOperator::Greater => ">",
153            ComparisonOperator::Equal => "==",
154            ComparisonOperator::NotEqual => "≠",
155            ComparisonOperator::Identical => "===",
156            ComparisonOperator::NotIdentical => "!==",
157        }
158    }
159}
160
161#[derive(Clone, Debug, PartialEq, Eq)]
162pub enum MemberOperator {
163    Dot,
164    SafeCall,
165}
166
167impl InfixOperator for MemberOperator {
168    fn symbol(&self) -> &str {
169        match self {
170            MemberOperator::Dot => ".",
171            MemberOperator::SafeCall => "?.",
172        }
173    }
174}
175
176#[derive(Copy, Clone, Debug, PartialEq, Eq)]
177pub struct UnwrapOperator;
178
179impl InfixOperator for UnwrapOperator {
180    fn symbol(&self) -> &str {
181        "?"
182    }
183}
184
185#[derive(Clone, Debug, PartialEq, Eq)]
186pub struct CustomInfix(String);
187
188impl InfixOperator for CustomInfix {
189    fn symbol(&self) -> &str {
190        &self.0
191    }
192}
193
194#[derive(Clone, Debug, PartialEq, Eq)]
195pub enum RangeOperator {
196    Inclusive,
197    Exclusive,
198    Tolerance,
199    Interval,
200}
201
202impl InfixOperator for RangeOperator {
203    fn symbol(&self) -> &str {
204        match self {
205            RangeOperator::Inclusive => "..=",
206            RangeOperator::Exclusive => "..<",
207            RangeOperator::Tolerance => "±",
208            RangeOperator::Interval => "..+",
209        }
210    }
211}