boa/syntax/ast/
punctuator.rs

1//! This module implements the `Punctuator`, which represents all punctuators used in JavaScript
2//!
3//! More information:
4//!  - [ECMAScript Reference][spec]
5//!
6//! [spec]: https://tc39.es/ecma262/#prod-Punctuator
7
8use crate::syntax::ast::op::{AssignOp, BinOp, BitOp, CompOp, LogOp, NumOp};
9use std::{
10    convert::TryInto,
11    fmt::{Display, Error, Formatter},
12};
13
14#[cfg(feature = "deser")]
15use serde::{Deserialize, Serialize};
16
17/// The Punctuator enum describes all of the punctuators used in JavaScript.
18///
19/// More information:
20///  - [ECMAScript Reference][spec]
21///
22/// [spec]: https://tc39.es/ecma262/#prod-Punctuator
23#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
24#[derive(PartialEq, Clone, Copy, Debug)]
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    Or,
118    /// `**`
119    Exp,
120    /// `?`
121    Question,
122    /// `>>`
123    RightSh,
124    /// `;`
125    Semicolon,
126    /// `...`
127    Spread,
128    /// `===`
129    StrictEq,
130    /// `!==`
131    StrictNotEq,
132    /// `-`
133    Sub,
134    /// `>>>`
135    URightSh,
136    /// `^`
137    Xor,
138}
139
140impl Punctuator {
141    /// Attempts to convert a punctuator (`+`, `=`...) to a Binary Operator
142    ///
143    /// If there is no match, `None` will be returned.
144    pub fn as_binop(self) -> Option<BinOp> {
145        match self {
146            Self::AssignAdd => Some(BinOp::Assign(AssignOp::Add)),
147            Self::AssignAnd => Some(BinOp::Assign(AssignOp::And)),
148            Self::AssignBoolAnd => Some(BinOp::Assign(AssignOp::BoolAnd)),
149            Self::AssignBoolOr => Some(BinOp::Assign(AssignOp::BoolOr)),
150            Self::AssignCoalesce => Some(BinOp::Assign(AssignOp::Coalesce)),
151            Self::AssignDiv => Some(BinOp::Assign(AssignOp::Div)),
152            Self::AssignLeftSh => Some(BinOp::Assign(AssignOp::Shl)),
153            Self::AssignMod => Some(BinOp::Assign(AssignOp::Mod)),
154            Self::AssignMul => Some(BinOp::Assign(AssignOp::Mul)),
155            Self::AssignOr => Some(BinOp::Assign(AssignOp::Or)),
156            Self::AssignPow => Some(BinOp::Assign(AssignOp::Exp)),
157            Self::AssignRightSh => Some(BinOp::Assign(AssignOp::Shr)),
158            Self::AssignSub => Some(BinOp::Assign(AssignOp::Sub)),
159            Self::AssignURightSh => Some(BinOp::Assign(AssignOp::Ushr)),
160            Self::AssignXor => Some(BinOp::Assign(AssignOp::Xor)),
161            Self::Add => Some(BinOp::Num(NumOp::Add)),
162            Self::Sub => Some(BinOp::Num(NumOp::Sub)),
163            Self::Mul => Some(BinOp::Num(NumOp::Mul)),
164            Self::Div => Some(BinOp::Num(NumOp::Div)),
165            Self::Mod => Some(BinOp::Num(NumOp::Mod)),
166            Self::And => Some(BinOp::Bit(BitOp::And)),
167            Self::Or => Some(BinOp::Bit(BitOp::Or)),
168            Self::Xor => Some(BinOp::Bit(BitOp::Xor)),
169            Self::BoolAnd => Some(BinOp::Log(LogOp::And)),
170            Self::BoolOr => Some(BinOp::Log(LogOp::Or)),
171            Self::Coalesce => Some(BinOp::Log(LogOp::Coalesce)),
172            Self::Eq => Some(BinOp::Comp(CompOp::Equal)),
173            Self::NotEq => Some(BinOp::Comp(CompOp::NotEqual)),
174            Self::StrictEq => Some(BinOp::Comp(CompOp::StrictEqual)),
175            Self::StrictNotEq => Some(BinOp::Comp(CompOp::StrictNotEqual)),
176            Self::LessThan => Some(BinOp::Comp(CompOp::LessThan)),
177            Self::GreaterThan => Some(BinOp::Comp(CompOp::GreaterThan)),
178            Self::GreaterThanOrEq => Some(BinOp::Comp(CompOp::GreaterThanOrEqual)),
179            Self::LessThanOrEq => Some(BinOp::Comp(CompOp::LessThanOrEqual)),
180            Self::LeftSh => Some(BinOp::Bit(BitOp::Shl)),
181            Self::RightSh => Some(BinOp::Bit(BitOp::Shr)),
182            Self::URightSh => Some(BinOp::Bit(BitOp::UShr)),
183            Self::Comma => Some(BinOp::Comma),
184            _ => None,
185        }
186    }
187}
188
189impl TryInto<BinOp> for Punctuator {
190    type Error = String;
191    fn try_into(self) -> Result<BinOp, Self::Error> {
192        self.as_binop()
193            .ok_or_else(|| format!("No binary operation for {}", self))
194    }
195}
196
197impl Display for Punctuator {
198    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
199        write!(
200            f,
201            "{}",
202            match self {
203                Self::Add => "+",
204                Self::And => "&",
205                Self::Arrow => "=>",
206                Self::Assign => "=",
207                Self::AssignAdd => "+=",
208                Self::AssignAnd => "&=",
209                Self::AssignBoolAnd => "&&=",
210                Self::AssignBoolOr => "||=",
211                Self::AssignCoalesce => "??=",
212                Self::AssignDiv => "/=",
213                Self::AssignLeftSh => "<<=",
214                Self::AssignMod => "%=",
215                Self::AssignMul => "*=",
216                Self::AssignOr => "|=",
217                Self::AssignPow => "**=",
218                Self::AssignRightSh => ">>=",
219                Self::AssignSub => "-=",
220                Self::AssignURightSh => ">>>=",
221                Self::AssignXor => "^=",
222                Self::BoolAnd => "&&",
223                Self::BoolOr => "||",
224                Self::Coalesce => "??",
225                Self::CloseBlock => "}",
226                Self::CloseBracket => "]",
227                Self::CloseParen => ")",
228                Self::Colon => ":",
229                Self::Comma => ",",
230                Self::Dec => "--",
231                Self::Div => "/",
232                Self::Dot => ".",
233                Self::Eq => "==",
234                Self::GreaterThan => ">",
235                Self::GreaterThanOrEq => ">=",
236                Self::Inc => "++",
237                Self::LeftSh => "<<",
238                Self::LessThan => "<",
239                Self::LessThanOrEq => "<=",
240                Self::Mod => "%",
241                Self::Mul => "*",
242                Self::Neg => "~",
243                Self::Not => "!",
244                Self::NotEq => "!=",
245                Self::OpenBlock => "{",
246                Self::OpenBracket => "[",
247                Self::OpenParen => "(",
248                Self::Or => "|",
249                Self::Exp => "**",
250                Self::Question => "?",
251                Self::RightSh => ">>",
252                Self::Semicolon => ";",
253                Self::Spread => "...",
254                Self::StrictEq => "===",
255                Self::StrictNotEq => "!==",
256                Self::Sub => "-",
257                Self::URightSh => ">>>",
258                Self::Xor => "^",
259            }
260        )
261    }
262}