cas_parser/parser/token/
op.rs

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