luau_lexer/token/
operator.rs

1//! [`Operator`] and [`CompoundOperator`] structs.
2
3use std::fmt::{Display, Formatter, Result};
4
5use crate::prelude::Lexer;
6
7/// A luau operator like `+` and `-`
8#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
9#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
10pub enum Operator {
11    /// `+`
12    Plus,
13
14    /// `-`
15    Minus,
16
17    /// `/`
18    Division,
19
20    /// `//`
21    FloorDivision,
22
23    /// `*`
24    Multiplication,
25
26    /// `%`
27    Modulo,
28
29    /// `^`
30    Exponentiation,
31
32    /// `..`
33    Concatenation,
34
35    /// `~=`
36    NotEqual,
37
38    /// `and`
39    And,
40
41    /// `or`
42    Or,
43
44    /// `not`
45    Not,
46
47    /// `&`
48    Intersection,
49
50    /// `|`
51    Union,
52
53    /// `?`
54    Optional,
55
56    /// `#`
57    Length,
58}
59
60impl Operator {
61    /// Try converting the character (and maybe the next) into an operator.
62    pub fn try_from_chars(character: char, lexer: &mut Lexer) -> Option<Self> {
63        let value = match character {
64            '+' => Some(Self::Plus),
65            '-' => Some(Self::Minus),
66            '/' if lexer.consume_with_next('/') => Some(Self::FloorDivision),
67            '/' => Some(Self::Division),
68            '*' => Some(Self::Multiplication),
69            '%' => Some(Self::Modulo),
70            '^' => Some(Self::Exponentiation),
71            '~' if lexer.consume_with_next('=') => Some(Self::NotEqual),
72            '#' => Some(Self::Length),
73            '&' => Some(Self::Intersection),
74            '|' => Some(Self::Union),
75            '?' => Some(Self::Optional),
76            _ => None,
77        };
78        if value.is_some() {
79            lexer.consume(character);
80        }
81
82        value
83    }
84}
85
86impl Display for Operator {
87    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
88        f.write_str(match self {
89            Self::Plus => "+",
90            Self::Minus => "-",
91            Self::FloorDivision => "//",
92            Self::Division => "/",
93            Self::Multiplication => "*",
94            Self::Modulo => "%",
95            Self::Exponentiation => "^",
96            Self::NotEqual => "~=",
97            Self::Length => "#",
98            Self::Intersection => "&",
99            Self::Union => "|",
100            Self::Optional => "?",
101            Self::Concatenation => "..",
102            Self::And => "and",
103            Self::Or => "or",
104            Self::Not => "not",
105        })
106    }
107}
108
109/// A luau compound operator like `+=` and `//=`
110#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
111#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
112#[allow(clippy::module_name_repetitions)] // Wouldn't make much sense otherwise.
113pub enum CompoundOperator {
114    /// `+=`
115    PlusEqual,
116
117    /// `-=`
118    MinusEqual,
119
120    /// `/=`
121    DivisionEqual,
122
123    /// `//=`
124    FloorDivisionEqual,
125
126    /// `*=`
127    MultiplicationEqual,
128
129    /// `%=`
130    ModuloEqual,
131
132    /// `^=`
133    ExponentiationEqual,
134
135    /// `..=`
136    ConcatenationEqual,
137
138    /// `==`
139    EqualEqual,
140
141    /// `<=`
142    LessThanOrEqualTo,
143
144    /// `>=`
145    GreaterThanOrEqualTo,
146}
147
148impl CompoundOperator {
149    /// Try creating a compound operator from the passed operator, depending on the
150    /// next character.
151    pub fn try_from_operator(operator: Operator, lexer: &mut Lexer) -> Option<Self> {
152        if !lexer.consume('=') {
153            return None;
154        }
155
156        match operator {
157            Operator::Plus => Some(Self::PlusEqual),
158            Operator::Minus => Some(Self::MinusEqual),
159            Operator::FloorDivision => Some(Self::FloorDivisionEqual),
160            Operator::Division => Some(Self::DivisionEqual),
161            Operator::Multiplication => Some(Self::MultiplicationEqual),
162            Operator::Modulo => Some(Self::ModuloEqual),
163            Operator::Exponentiation => Some(Self::ExponentiationEqual),
164            Operator::Concatenation => Some(Self::ConcatenationEqual),
165            _ => None,
166        }
167    }
168}
169
170impl Display for CompoundOperator {
171    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
172        f.write_str(match self {
173            Self::PlusEqual => "+=",
174            Self::MinusEqual => "-=",
175            Self::FloorDivisionEqual => "//=",
176            Self::DivisionEqual => "/=",
177            Self::MultiplicationEqual => "*=",
178            Self::ModuloEqual => "%=",
179            Self::ExponentiationEqual => "^=",
180            Self::ConcatenationEqual => "..=",
181            Self::EqualEqual => "==",
182            Self::LessThanOrEqualTo => "<=",
183            Self::GreaterThanOrEqualTo => ">=",
184        })
185    }
186}