Skip to main content

boa_ast/punctuator/
mod.rs

1//! The `Punctuator` enum, which contains all punctuators used in ECMAScript.
2//!
3//! More information:
4//!  - [ECMAScript Reference][spec]
5//!
6//! [spec]: https://tc39.es/ecma262/#prod-Punctuator
7
8use crate::expression::operator::{
9    assign::AssignOp,
10    binary::{ArithmeticOp, BinaryOp, BitwiseOp, LogicalOp, RelationalOp},
11};
12use std::fmt::{Display, Error, Formatter};
13
14#[cfg(test)]
15mod tests;
16
17/// All of the punctuators used in ECMAScript.
18///
19/// More information:
20///  - [ECMAScript Reference][spec]
21///
22/// [spec]: https://tc39.es/ecma262/#prod-Punctuator
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24#[derive(PartialEq, Eq, Clone, Copy, Debug, strum::EnumIter)]
25pub enum Punctuator {
26    /// `+`
27    Add,
28    /// `&`
29    And,
30    /// `=>`
31    Arrow,
32    /// `=`
33    Assign,
34    /// `+=`
35    AssignAdd,
36    /// `&=`
37    AssignAnd,
38    /// `&&=`
39    AssignBoolAnd,
40    /// `||=`
41    AssignBoolOr,
42    /// `??=`,
43    AssignCoalesce,
44    /// `/=`
45    AssignDiv,
46    /// `<<=`
47    AssignLeftSh,
48    /// `%=`
49    AssignMod,
50    /// `*=`
51    AssignMul,
52    /// `|=`
53    AssignOr,
54    /// `**=`
55    AssignPow,
56    /// `>>=`
57    AssignRightSh,
58    /// `-=`
59    AssignSub,
60    /// `>>>=`
61    AssignURightSh,
62    /// `^=`
63    AssignXor,
64    /// `&&`
65    BoolAnd,
66    /// `||`
67    BoolOr,
68    /// `}`
69    CloseBlock,
70    /// `]`
71    CloseBracket,
72    /// `)`
73    CloseParen,
74    /// `??`
75    Coalesce,
76    /// `:`
77    Colon,
78    /// `,`
79    Comma,
80    /// `--`
81    Dec,
82    /// `/`
83    Div,
84    /// `.`
85    Dot,
86    /// `==`
87    Eq,
88    /// `>`
89    GreaterThan,
90    /// `>=`
91    GreaterThanOrEq,
92    /// `++`
93    Inc,
94    /// `<<`
95    LeftSh,
96    /// `<`
97    LessThan,
98    /// `<=`
99    LessThanOrEq,
100    /// `%`
101    Mod,
102    /// `*`
103    Mul,
104    /// `~`
105    Neg,
106    /// `!`
107    Not,
108    /// `!=`
109    NotEq,
110    /// `{`
111    OpenBlock,
112    /// `[`
113    OpenBracket,
114    /// `(`
115    OpenParen,
116    /// `?.`
117    Optional,
118    /// `|`
119    Or,
120    /// `**`
121    Exp,
122    /// `?`
123    Question,
124    /// `>>`
125    RightSh,
126    /// `;`
127    Semicolon,
128    /// `...`
129    Spread,
130    /// `===`
131    StrictEq,
132    /// `!==`
133    StrictNotEq,
134    /// `-`
135    Sub,
136    /// `>>>`
137    URightSh,
138    /// `^`
139    Xor,
140}
141
142impl Punctuator {
143    /// Attempts to convert a punctuator (`+`, `=`...) to an Assign Operator
144    ///
145    /// If there is no match, `None` will be returned.
146    #[must_use]
147    pub const fn as_assign_op(self) -> Option<AssignOp> {
148        match self {
149            Self::Assign => Some(AssignOp::Assign),
150            Self::AssignAdd => Some(AssignOp::Add),
151            Self::AssignAnd => Some(AssignOp::And),
152            Self::AssignBoolAnd => Some(AssignOp::BoolAnd),
153            Self::AssignBoolOr => Some(AssignOp::BoolOr),
154            Self::AssignCoalesce => Some(AssignOp::Coalesce),
155            Self::AssignDiv => Some(AssignOp::Div),
156            Self::AssignLeftSh => Some(AssignOp::Shl),
157            Self::AssignMod => Some(AssignOp::Mod),
158            Self::AssignMul => Some(AssignOp::Mul),
159            Self::AssignOr => Some(AssignOp::Or),
160            Self::AssignPow => Some(AssignOp::Exp),
161            Self::AssignRightSh => Some(AssignOp::Shr),
162            Self::AssignSub => Some(AssignOp::Sub),
163            Self::AssignURightSh => Some(AssignOp::Ushr),
164            Self::AssignXor => Some(AssignOp::Xor),
165            _ => None,
166        }
167    }
168
169    /// Attempts to convert a punctuator (`+`, `=`...) to a Binary Operator
170    ///
171    /// If there is no match, `None` will be returned.
172    #[must_use]
173    pub const fn as_binary_op(self) -> Option<BinaryOp> {
174        match self {
175            Self::Add => Some(BinaryOp::Arithmetic(ArithmeticOp::Add)),
176            Self::Sub => Some(BinaryOp::Arithmetic(ArithmeticOp::Sub)),
177            Self::Mul => Some(BinaryOp::Arithmetic(ArithmeticOp::Mul)),
178            Self::Div => Some(BinaryOp::Arithmetic(ArithmeticOp::Div)),
179            Self::Mod => Some(BinaryOp::Arithmetic(ArithmeticOp::Mod)),
180            Self::Exp => Some(BinaryOp::Arithmetic(ArithmeticOp::Exp)),
181            Self::And => Some(BinaryOp::Bitwise(BitwiseOp::And)),
182            Self::Or => Some(BinaryOp::Bitwise(BitwiseOp::Or)),
183            Self::Xor => Some(BinaryOp::Bitwise(BitwiseOp::Xor)),
184            Self::BoolAnd => Some(BinaryOp::Logical(LogicalOp::And)),
185            Self::BoolOr => Some(BinaryOp::Logical(LogicalOp::Or)),
186            Self::Coalesce => Some(BinaryOp::Logical(LogicalOp::Coalesce)),
187            Self::Eq => Some(BinaryOp::Relational(RelationalOp::Equal)),
188            Self::NotEq => Some(BinaryOp::Relational(RelationalOp::NotEqual)),
189            Self::StrictEq => Some(BinaryOp::Relational(RelationalOp::StrictEqual)),
190            Self::StrictNotEq => Some(BinaryOp::Relational(RelationalOp::StrictNotEqual)),
191            Self::LessThan => Some(BinaryOp::Relational(RelationalOp::LessThan)),
192            Self::GreaterThan => Some(BinaryOp::Relational(RelationalOp::GreaterThan)),
193            Self::GreaterThanOrEq => Some(BinaryOp::Relational(RelationalOp::GreaterThanOrEqual)),
194            Self::LessThanOrEq => Some(BinaryOp::Relational(RelationalOp::LessThanOrEqual)),
195            Self::LeftSh => Some(BinaryOp::Bitwise(BitwiseOp::Shl)),
196            Self::RightSh => Some(BinaryOp::Bitwise(BitwiseOp::Shr)),
197            Self::URightSh => Some(BinaryOp::Bitwise(BitwiseOp::UShr)),
198            Self::Comma => Some(BinaryOp::Comma),
199            _ => None,
200        }
201    }
202
203    /// Retrieves the punctuator as a static string.
204    #[must_use]
205    pub const fn as_str(self) -> &'static str {
206        match self {
207            Self::Add => "+",
208            Self::And => "&",
209            Self::Arrow => "=>",
210            Self::Assign => "=",
211            Self::AssignAdd => "+=",
212            Self::AssignAnd => "&=",
213            Self::AssignBoolAnd => "&&=",
214            Self::AssignBoolOr => "||=",
215            Self::AssignCoalesce => "??=",
216            Self::AssignDiv => "/=",
217            Self::AssignLeftSh => "<<=",
218            Self::AssignMod => "%=",
219            Self::AssignMul => "*=",
220            Self::AssignOr => "|=",
221            Self::AssignPow => "**=",
222            Self::AssignRightSh => ">>=",
223            Self::AssignSub => "-=",
224            Self::AssignURightSh => ">>>=",
225            Self::AssignXor => "^=",
226            Self::BoolAnd => "&&",
227            Self::BoolOr => "||",
228            Self::Coalesce => "??",
229            Self::CloseBlock => "}",
230            Self::CloseBracket => "]",
231            Self::CloseParen => ")",
232            Self::Colon => ":",
233            Self::Comma => ",",
234            Self::Dec => "--",
235            Self::Div => "/",
236            Self::Dot => ".",
237            Self::Eq => "==",
238            Self::GreaterThan => ">",
239            Self::GreaterThanOrEq => ">=",
240            Self::Inc => "++",
241            Self::LeftSh => "<<",
242            Self::LessThan => "<",
243            Self::LessThanOrEq => "<=",
244            Self::Mod => "%",
245            Self::Mul => "*",
246            Self::Neg => "~",
247            Self::Not => "!",
248            Self::NotEq => "!=",
249            Self::OpenBlock => "{",
250            Self::OpenBracket => "[",
251            Self::OpenParen => "(",
252            Self::Optional => "?.",
253            Self::Or => "|",
254            Self::Exp => "**",
255            Self::Question => "?",
256            Self::RightSh => ">>",
257            Self::Semicolon => ";",
258            Self::Spread => "...",
259            Self::StrictEq => "===",
260            Self::StrictNotEq => "!==",
261            Self::Sub => "-",
262            Self::URightSh => ">>>",
263            Self::Xor => "^",
264        }
265    }
266}
267
268impl TryFrom<Punctuator> for AssignOp {
269    // TO-DO: proper error type
270    type Error = String;
271
272    fn try_from(punct: Punctuator) -> Result<Self, Self::Error> {
273        punct
274            .as_assign_op()
275            .ok_or_else(|| format!("No assignment operator for {punct}"))
276    }
277}
278
279impl TryFrom<Punctuator> for BinaryOp {
280    // TO-DO: proper error type
281    type Error = String;
282
283    fn try_from(punct: Punctuator) -> Result<Self, Self::Error> {
284        punct
285            .as_binary_op()
286            .ok_or_else(|| format!("No binary operator for {punct}"))
287    }
288}
289
290impl Display for Punctuator {
291    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
292        f.write_str(self.as_str())
293    }
294}
295
296impl From<Punctuator> for Box<str> {
297    fn from(p: Punctuator) -> Self {
298        p.as_str().into()
299    }
300}