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))]
112pub enum CompoundOperator {
113    /// `+=`
114    PlusEqual,
115
116    /// `-=`
117    MinusEqual,
118
119    /// `/=`
120    DivisionEqual,
121
122    /// `//=`
123    FloorDivisionEqual,
124
125    /// `*=`
126    MultiplicationEqual,
127
128    /// `%=`
129    ModuloEqual,
130
131    /// `^=`
132    ExponentiationEqual,
133
134    /// `..=`
135    ConcatenationEqual,
136
137    /// `==`
138    EqualEqual,
139
140    /// `<=`
141    LessThanOrEqualTo,
142
143    /// `>=`
144    GreaterThanOrEqualTo,
145}
146
147impl CompoundOperator {
148    /// Try creating a compound operator from the passed operator, depending on the
149    /// next character.
150    pub fn try_from_operator(operator: Operator, lexer: &mut Lexer) -> Option<Self> {
151        if !lexer.consume('=') {
152            return None;
153        }
154
155        match operator {
156            Operator::Plus => Some(Self::PlusEqual),
157            Operator::Minus => Some(Self::MinusEqual),
158            Operator::FloorDivision => Some(Self::FloorDivisionEqual),
159            Operator::Division => Some(Self::DivisionEqual),
160            Operator::Multiplication => Some(Self::MultiplicationEqual),
161            Operator::Modulo => Some(Self::ModuloEqual),
162            Operator::Exponentiation => Some(Self::ExponentiationEqual),
163            Operator::Concatenation => Some(Self::ConcatenationEqual),
164            _ => None,
165        }
166    }
167}
168
169impl Display for CompoundOperator {
170    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
171        f.write_str(match self {
172            Self::PlusEqual => "+=",
173            Self::MinusEqual => "-=",
174            Self::FloorDivisionEqual => "//=",
175            Self::DivisionEqual => "/=",
176            Self::MultiplicationEqual => "*=",
177            Self::ModuloEqual => "%=",
178            Self::ExponentiationEqual => "^=",
179            Self::ConcatenationEqual => "..=",
180            Self::EqualEqual => "==",
181            Self::LessThanOrEqualTo => "<=",
182            Self::GreaterThanOrEqualTo => ">=",
183        })
184    }
185}