1use core::fmt;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
7#[non_exhaustive]
8pub enum OpPriority {
9 Or,
11 And,
13 Comparison,
15 AddOrSub,
17 MulOrDiv,
19 Power,
21 Negation,
23 Call,
25}
26
27impl OpPriority {
28 pub const fn max_priority() -> Self {
30 Self::Call
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
36#[non_exhaustive]
37pub enum UnaryOp {
38 Neg,
40 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 pub fn priority(self) -> OpPriority {
56 match self {
57 Self::Neg | Self::Not => OpPriority::Negation,
58 }
59 }
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
64#[non_exhaustive]
65pub enum BinaryOp {
66 Add,
68 Sub,
70 Mul,
72 Div,
74 Power,
76 Eq,
78 NotEq,
80 And,
82 Or,
84 Gt,
86 Lt,
88 Ge,
90 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 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 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 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 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 pub fn is_order_comparison(self) -> bool {
166 matches!(self, Self::Gt | Self::Lt | Self::Le | Self::Ge)
167 }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
172#[non_exhaustive]
173pub enum Op {
174 Unary(UnaryOp),
176 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}