arithmetic_parser/
ops.rs

1//! Operation-related types.
2
3use core::fmt;
4
5/// Priority of an operation.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
7#[non_exhaustive]
8pub enum OpPriority {
9    /// Boolean OR (`||`).
10    Or,
11    /// Boolean AND (`&&`).
12    And,
13    /// Equality and order comparisons: `==`, `!=`, `>`, `<`, `>=`, `<=`.
14    Comparison,
15    /// Addition or subtraction: `+` or `-`.
16    AddOrSub,
17    /// Multiplication or division: `*` or `/`.
18    MulOrDiv,
19    /// Power (`^`).
20    Power,
21    /// Numeric or Boolean negation: `!` or unary `-`.
22    Negation,
23    /// Function or method call.
24    Call,
25}
26
27impl OpPriority {
28    /// Returns the maximum priority.
29    pub const fn max_priority() -> Self {
30        Self::Call
31    }
32}
33
34/// Unary operation.
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
36#[non_exhaustive]
37pub enum UnaryOp {
38    /// Negation (`-`).
39    Neg,
40    /// Boolean negation (`!`).
41    Not,
42}
43
44impl fmt::Display for UnaryOp {
45    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match self {
47            UnaryOp::Neg => formatter.write_str("negation"),
48            UnaryOp::Not => formatter.write_str("logical negation"),
49        }
50    }
51}
52
53impl UnaryOp {
54    /// Returns a relative priority of this operation.
55    pub fn priority(self) -> OpPriority {
56        match self {
57            Self::Neg | Self::Not => OpPriority::Negation,
58        }
59    }
60}
61
62/// Binary arithmetic operation.
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
64#[non_exhaustive]
65pub enum BinaryOp {
66    /// Addition (`+`).
67    Add,
68    /// Subtraction (`-`).
69    Sub,
70    /// Multiplication (`*`).
71    Mul,
72    /// Division (`/`).
73    Div,
74    /// Power (`^`).
75    Power,
76    /// Equality (`==`).
77    Eq,
78    /// Non-equality (`!=`).
79    NotEq,
80    /// Boolean AND (`&&`).
81    And,
82    /// Boolean OR (`||`).
83    Or,
84    /// "Greater than" comparison.
85    Gt,
86    /// "Lesser than" comparison.
87    Lt,
88    /// "Greater or equal" comparison.
89    Ge,
90    /// "Lesser or equal" comparison.
91    Le,
92}
93
94impl fmt::Display for BinaryOp {
95    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
96        formatter.write_str(match self {
97            Self::Add => "addition",
98            Self::Sub => "subtraction",
99            Self::Mul => "multiplication",
100            Self::Div => "division",
101            Self::Power => "exponentiation",
102            Self::Eq => "equality comparison",
103            Self::NotEq => "non-equality comparison",
104            Self::And => "AND",
105            Self::Or => "OR",
106            Self::Gt => "greater comparison",
107            Self::Lt => "lesser comparison",
108            Self::Ge => "greater-or-equal comparison",
109            Self::Le => "lesser-or-equal comparison",
110        })
111    }
112}
113
114impl BinaryOp {
115    /// Returns the string representation of this operation.
116    pub fn as_str(self) -> &'static str {
117        match self {
118            Self::Add => "+",
119            Self::Sub => "-",
120            Self::Mul => "*",
121            Self::Div => "/",
122            Self::Power => "^",
123            Self::Eq => "==",
124            Self::NotEq => "!=",
125            Self::And => "&&",
126            Self::Or => "||",
127            Self::Gt => ">",
128            Self::Lt => "<",
129            Self::Ge => ">=",
130            Self::Le => "<=",
131        }
132    }
133
134    /// Returns the priority of this operation.
135    pub fn priority(self) -> OpPriority {
136        match self {
137            Self::Or => OpPriority::Or,
138            Self::And => OpPriority::And,
139            Self::Eq | Self::NotEq | Self::Gt | Self::Lt | Self::Le | Self::Ge => {
140                OpPriority::Comparison
141            }
142            Self::Add | Self::Sub => OpPriority::AddOrSub,
143            Self::Mul | Self::Div => OpPriority::MulOrDiv,
144            Self::Power => OpPriority::Power,
145        }
146    }
147
148    /// Checks if this operation is arithmetic.
149    pub fn is_arithmetic(self) -> bool {
150        matches!(
151            self,
152            Self::Add | Self::Sub | Self::Mul | Self::Div | Self::Power
153        )
154    }
155
156    /// Checks if this operation is a comparison.
157    pub fn is_comparison(self) -> bool {
158        matches!(
159            self,
160            Self::Eq | Self::NotEq | Self::Gt | Self::Lt | Self::Le | Self::Ge
161        )
162    }
163
164    /// Checks if this operation is an order comparison.
165    pub fn is_order_comparison(self) -> bool {
166        matches!(self, Self::Gt | Self::Lt | Self::Le | Self::Ge)
167    }
168}
169
170/// Generic operation, either unary or binary.
171#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
172#[non_exhaustive]
173pub enum Op {
174    /// Unary operation.
175    Unary(UnaryOp),
176    /// Binary operation.
177    Binary(BinaryOp),
178}
179
180impl fmt::Display for Op {
181    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
182        match self {
183            Self::Unary(inner) => fmt::Display::fmt(inner, formatter),
184            Self::Binary(inner) => fmt::Display::fmt(inner, formatter),
185        }
186    }
187}
188
189impl From<UnaryOp> for Op {
190    fn from(value: UnaryOp) -> Self {
191        Self::Unary(value)
192    }
193}
194
195impl From<BinaryOp> for Op {
196    fn from(value: BinaryOp) -> Self {
197        Self::Binary(value)
198    }
199}