1use cas_error::Error;
4use crate::{
5 parser::{error::UnexpectedToken, fmt::Latex, Parse, Parser},
6 tokenizer::TokenKind,
7};
8use std::{fmt, ops::Range};
9
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Serialize};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Associativity {
16 Left,
22
23 Right,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum Precedence {
35 Any,
37
38 Assign,
41
42 Range,
44
45 Or,
47
48 And,
50
51 Compare,
53
54 BitOr,
56
57 BitAnd,
59
60 Shift,
62
63 Term,
65
66 Factor,
69
70 Neg,
72
73 Exp,
75
76 Factorial,
78
79 BitNot,
81
82 Not,
84}
85
86impl PartialOrd for Precedence {
87 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
88 Some(self.cmp(other))
89 }
90}
91
92impl Ord for Precedence {
93 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
94 let left = *self as u8;
95 let right = *other as u8;
96 left.cmp(&right)
97 }
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
103pub enum UnaryOpKind {
104 Not,
105 BitNot,
106 Factorial,
107 Neg,
108}
109
110impl UnaryOpKind {
111 pub fn precedence(&self) -> Precedence {
113 match self {
114 Self::Not => Precedence::Not,
115 Self::BitNot => Precedence::BitNot,
116 Self::Factorial => Precedence::Factorial,
117 Self::Neg => Precedence::Neg,
118 }
119 }
120
121 pub fn associativity(&self) -> Associativity {
123 match self {
124 Self::Neg | Self::BitNot | Self::Not => Associativity::Right,
125 Self::Factorial => Associativity::Left,
126 }
127 }
128}
129
130#[derive(Debug, Clone, PartialEq, Eq)]
132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
133pub struct UnaryOp {
134 pub kind: UnaryOpKind,
136
137 pub span: Range<usize>,
139}
140
141impl UnaryOp {
142 pub fn precedence(&self) -> Precedence {
144 self.kind.precedence()
145 }
146
147 pub fn associativity(&self) -> Associativity {
149 self.kind.associativity()
150 }
151}
152
153impl<'source> Parse<'source> for UnaryOp {
154 fn std_parse(
155 input: &mut Parser<'source>,
156 _: &mut Vec<Error>
157 ) -> Result<Self, Vec<Error>> {
158 let token = input.next_token().map_err(|e| vec![e])?;
159 let kind = match token.kind {
160 TokenKind::Not => Ok(UnaryOpKind::Not),
161 TokenKind::BitNot => Ok(UnaryOpKind::BitNot),
162 TokenKind::Factorial => Ok(UnaryOpKind::Factorial),
163 TokenKind::Sub => Ok(UnaryOpKind::Neg),
164 _ => Err(vec![Error::new(
165 vec![token.span.clone()],
166 UnexpectedToken {
167 expected: &[
168 TokenKind::Not,
169 TokenKind::BitNot,
170 TokenKind::Factorial,
171 TokenKind::Sub,
172 ],
173 found: token.kind,
174 },
175 )]),
176 }?;
177
178 Ok(Self {
179 kind,
180 span: token.span,
181 })
182 }
183}
184
185impl std::fmt::Display for UnaryOp {
186 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
187 match self.kind {
188 UnaryOpKind::Not => write!(f, "not"),
189 UnaryOpKind::BitNot => write!(f, "~"),
190 UnaryOpKind::Factorial => write!(f, "!"),
191 UnaryOpKind::Neg => write!(f, "-"),
192 }
193 }
194}
195
196impl Latex for UnaryOp {
197 fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
198 match self.kind {
199 UnaryOpKind::Not => write!(f, "\\neg "),
200 UnaryOpKind::BitNot => write!(f, "\\sim "),
201 UnaryOpKind::Factorial => write!(f, "!"),
202 UnaryOpKind::Neg => write!(f, "-"),
203 }
204 }
205}
206
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
209#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
210pub enum BinOpKind {
211 Exp,
212 Mul,
213 Div,
214 Mod,
215 Add,
216 Sub,
217 BitRight,
218 BitLeft,
219 BitAnd,
220 BitOr,
221 Greater,
222 GreaterEq,
223 Less,
224 LessEq,
225 Eq,
226 NotEq,
227 ApproxEq,
228 ApproxNotEq,
229 And,
230 Or,
231}
232
233impl BinOpKind {
234 pub fn precedence(&self) -> Precedence {
236 match self {
237 Self::Exp => Precedence::Exp,
238 Self::Mul | Self::Div | Self::Mod => Precedence::Factor,
239 Self::Add | Self::Sub => Precedence::Term,
240 Self::BitRight | Self::BitLeft => Precedence::Shift,
241 Self::BitAnd => Precedence::BitAnd,
242 Self::BitOr => Precedence::BitOr,
243 Self::Greater | Self::GreaterEq | Self::Less | Self::LessEq
244 | Self::Eq | Self::NotEq | Self::ApproxEq | Self::ApproxNotEq => Precedence::Compare,
245 Self::And => Precedence::And,
246 Self::Or => Precedence::Or,
247 }
248 }
249
250 pub fn associativity(&self) -> Associativity {
252 match self {
253 Self::Exp => Associativity::Right,
254 Self::Mul | Self::Div | Self::Mod
255 | Self::Add | Self::Sub
256 | Self::BitRight | Self::BitLeft
257 | Self::BitAnd | Self::BitOr
258 | Self::Greater | Self::GreaterEq | Self::Less | Self::LessEq
259 | Self::Eq | Self::NotEq | Self::ApproxEq | Self::ApproxNotEq
260 | Self::And | Self::Or => Associativity::Left,
261 }
262 }
263}
264
265#[derive(Debug, Clone, PartialEq, Eq)]
267#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
268pub struct BinOp {
269 pub kind: BinOpKind,
271
272 pub implicit: bool,
274
275 pub span: Range<usize>,
277}
278
279impl BinOp {
280 pub fn precedence(&self) -> Precedence {
282 self.kind.precedence()
283 }
284
285 pub fn associativity(&self) -> Associativity {
287 self.kind.associativity()
288 }
289}
290
291impl<'source> Parse<'source> for BinOp {
292 fn std_parse(
293 input: &mut Parser<'source>,
294 _: &mut Vec<Error>
295 ) -> Result<Self, Vec<Error>> {
296 let token = input.next_token().map_err(|e| vec![e])?;
297 let kind = match token.kind {
298 TokenKind::Exp => Ok(BinOpKind::Exp),
299 TokenKind::Mul => Ok(BinOpKind::Mul),
300 TokenKind::Div => Ok(BinOpKind::Div),
301 TokenKind::Mod => Ok(BinOpKind::Mod),
302 TokenKind::Add => Ok(BinOpKind::Add),
303 TokenKind::Sub => Ok(BinOpKind::Sub),
304 TokenKind::BitRight => Ok(BinOpKind::BitRight),
305 TokenKind::BitLeft => Ok(BinOpKind::BitLeft),
306 TokenKind::BitAnd => Ok(BinOpKind::BitAnd),
307 TokenKind::BitOr => Ok(BinOpKind::BitOr),
308 TokenKind::Greater => Ok(BinOpKind::Greater),
309 TokenKind::GreaterEq => Ok(BinOpKind::GreaterEq),
310 TokenKind::Less => Ok(BinOpKind::Less),
311 TokenKind::LessEq => Ok(BinOpKind::LessEq),
312 TokenKind::Eq => Ok(BinOpKind::Eq),
313 TokenKind::NotEq => Ok(BinOpKind::NotEq),
314 TokenKind::ApproxEq => Ok(BinOpKind::ApproxEq),
315 TokenKind::ApproxNotEq => Ok(BinOpKind::ApproxNotEq),
316 TokenKind::And => Ok(BinOpKind::And),
317 TokenKind::Or => Ok(BinOpKind::Or),
318 _ => Err(vec![Error::new(
319 vec![token.span.clone()],
320 UnexpectedToken {
321 expected: &[
322 TokenKind::Exp,
323 TokenKind::Mul,
324 TokenKind::Div,
325 TokenKind::Add,
326 TokenKind::Sub,
327 ],
328 found: token.kind,
329 },
330 )]),
331 }?;
332
333 Ok(Self {
334 kind,
335 implicit: false,
336 span: token.span,
337 })
338 }
339}
340
341impl std::fmt::Display for BinOp {
342 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
343 if self.implicit {
344 return Ok(());
345 }
346
347 match self.kind {
348 BinOpKind::Exp => write!(f, "^"),
349 BinOpKind::Mul => write!(f, "*"),
350 BinOpKind::Div => write!(f, "/"),
351 BinOpKind::Mod => write!(f, "%"),
352 BinOpKind::Add => write!(f, "+"),
353 BinOpKind::Sub => write!(f, "-"),
354 BinOpKind::BitRight => write!(f, ">>"),
355 BinOpKind::BitLeft => write!(f, "<<"),
356 BinOpKind::BitAnd => write!(f, "&"),
357 BinOpKind::BitOr => write!(f, "|"),
358 BinOpKind::Greater => write!(f, ">"),
359 BinOpKind::GreaterEq => write!(f, ">="),
360 BinOpKind::Less => write!(f, "<"),
361 BinOpKind::LessEq => write!(f, "<="),
362 BinOpKind::Eq => write!(f, "=="),
363 BinOpKind::NotEq => write!(f, "!="),
364 BinOpKind::ApproxEq => write!(f, "~=="),
365 BinOpKind::ApproxNotEq => write!(f, "~!="),
366 BinOpKind::And => write!(f, "&&"),
367 BinOpKind::Or => write!(f, "||"),
368 }
369 }
370}
371
372impl Latex for BinOp {
373 fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
374 if self.implicit {
375 return Ok(());
376 }
377
378 match self.kind {
379 BinOpKind::Exp => write!(f, "^"),
380 BinOpKind::Mul => write!(f, "\\cdot "),
381 BinOpKind::Div => write!(f, "\\div "),
382 BinOpKind::Mod => write!(f, "\\mod "),
383 BinOpKind::Add => write!(f, "+"),
384 BinOpKind::Sub => write!(f, "-"),
385 BinOpKind::BitRight => write!(f, "\\gg "),
386 BinOpKind::BitLeft => write!(f, "\\ll "),
387 BinOpKind::BitAnd => write!(f, "\\&"),
388 BinOpKind::BitOr => write!(f, "\\vert "),
389 BinOpKind::Greater => write!(f, ">"),
390 BinOpKind::GreaterEq => write!(f, "\\geq "),
391 BinOpKind::Less => write!(f, "<"),
392 BinOpKind::LessEq => write!(f, "\\leq "),
393 BinOpKind::Eq => write!(f, "="),
394 BinOpKind::NotEq => write!(f, "\\neq "),
395 BinOpKind::ApproxEq => write!(f, "\\approx "),
396 BinOpKind::ApproxNotEq => write!(f, "\\not\\approx "),
397 BinOpKind::And => write!(f, "\\wedge "),
398 BinOpKind::Or => write!(f, "\\vee "),
399 }
400 }
401}
402
403#[derive(Debug, Clone, Copy, PartialEq, Eq)]
405#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
406pub enum AssignOpKind {
407 Assign,
408 Add,
409 Sub,
410 Mul,
411 Div,
412 Mod,
413 Exp,
414 And,
415 Or,
416 BitAnd,
417 BitOr,
418 BitRight,
419 BitLeft,
420}
421
422impl From<AssignOpKind> for BinOpKind {
423 fn from(value: AssignOpKind) -> Self {
424 match value {
425 AssignOpKind::Assign => Self::Eq,
426 AssignOpKind::Add => Self::Add,
427 AssignOpKind::Sub => Self::Sub,
428 AssignOpKind::Mul => Self::Mul,
429 AssignOpKind::Div => Self::Div,
430 AssignOpKind::Mod => Self::Mod,
431 AssignOpKind::Exp => Self::Exp,
432 AssignOpKind::And => Self::And,
433 AssignOpKind::Or => Self::Or,
434 AssignOpKind::BitAnd => Self::BitAnd,
435 AssignOpKind::BitOr => Self::BitOr,
436 AssignOpKind::BitRight => Self::BitRight,
437 AssignOpKind::BitLeft => Self::BitLeft,
438 }
439 }
440}
441
442#[derive(Debug, Clone, PartialEq, Eq)]
445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
446pub struct AssignOp {
447 pub kind: AssignOpKind,
449
450 pub span: Range<usize>,
452}
453
454impl AssignOp {
455 pub fn is_standard(&self) -> bool {
457 matches!(self.kind, AssignOpKind::Assign)
458 }
459
460 pub fn is_compound(&self) -> bool {
462 !self.is_standard()
463 }
464}
465
466impl<'source> Parse<'source> for AssignOp {
467 fn std_parse(
468 input: &mut Parser<'source>,
469 _: &mut Vec<Error>
470 ) -> Result<Self, Vec<Error>> {
471 let token = input.next_token().map_err(|e| vec![e])?;
472 let kind = match token.kind {
473 TokenKind::Assign => Ok(AssignOpKind::Assign),
474 TokenKind::AddAssign => Ok(AssignOpKind::Add),
475 TokenKind::SubAssign => Ok(AssignOpKind::Sub),
476 TokenKind::MulAssign => Ok(AssignOpKind::Mul),
477 TokenKind::DivAssign => Ok(AssignOpKind::Div),
478 TokenKind::ModAssign => Ok(AssignOpKind::Mod),
479 TokenKind::ExpAssign => Ok(AssignOpKind::Exp),
480 TokenKind::AndAssign => Ok(AssignOpKind::And),
481 TokenKind::OrAssign => Ok(AssignOpKind::Or),
482 TokenKind::BitAndAssign => Ok(AssignOpKind::BitAnd),
483 TokenKind::BitOrAssign => Ok(AssignOpKind::BitOr),
484 TokenKind::BitRightAssign => Ok(AssignOpKind::BitRight),
485 TokenKind::BitLeftAssign => Ok(AssignOpKind::BitLeft),
486 _ => Err(vec![Error::new(
487 vec![token.span.clone()],
488 UnexpectedToken {
489 expected: &[
490 TokenKind::Assign,
491 TokenKind::AddAssign,
492 TokenKind::SubAssign,
493 TokenKind::MulAssign,
494 TokenKind::DivAssign,
495 TokenKind::ModAssign,
496 TokenKind::ExpAssign,
497 TokenKind::AndAssign,
498 TokenKind::OrAssign,
499 TokenKind::BitAndAssign,
500 TokenKind::BitOrAssign,
501 TokenKind::BitRightAssign,
502 TokenKind::BitLeftAssign,
503 ],
504 found: token.kind,
505 },
506 )]),
507 }?;
508
509 Ok(Self {
510 kind,
511 span: token.span,
512 })
513 }
514}
515
516impl std::fmt::Display for AssignOp {
517 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
518 match self.kind {
519 AssignOpKind::Assign => write!(f, "="),
520 AssignOpKind::Add => write!(f, "+="),
521 AssignOpKind::Sub => write!(f, "-="),
522 AssignOpKind::Mul => write!(f, "*="),
523 AssignOpKind::Div => write!(f, "/="),
524 AssignOpKind::Mod => write!(f, "%="),
525 AssignOpKind::Exp => write!(f, "^="),
526 AssignOpKind::And => write!(f, "&&="),
527 AssignOpKind::Or => write!(f, "||="),
528 AssignOpKind::BitAnd => write!(f, "&="),
529 AssignOpKind::BitOr => write!(f, "|="),
530 AssignOpKind::BitRight => write!(f, ">>="),
531 AssignOpKind::BitLeft => write!(f, "<<="),
532 }
533 }
534}
535
536impl Latex for AssignOp {
537 fn fmt_latex(&self, f: &mut fmt::Formatter) -> fmt::Result {
538 match self.kind {
539 AssignOpKind::Assign => write!(f, "="),
540 AssignOpKind::Add => write!(f, "+="),
541 AssignOpKind::Sub => write!(f, "-="),
542 AssignOpKind::Mul => write!(f, "*="),
543 AssignOpKind::Div => write!(f, "/="),
544 AssignOpKind::Mod => write!(f, "\\mod="),
545 AssignOpKind::Exp => write!(f, "^="),
546 AssignOpKind::And => write!(f, "\\wedge="),
547 AssignOpKind::Or => write!(f, "\\vee="),
548 AssignOpKind::BitAnd => write!(f, "\\&="),
549 AssignOpKind::BitOr => write!(f, "\\vert="),
550 AssignOpKind::BitRight => write!(f, "\\gg="),
551 AssignOpKind::BitLeft => write!(f, "\\ll="),
552 }
553 }
554}