1use std::convert::TryFrom;
7
8use crate::{derive_ASTNode, TSXKeyword, TSXToken};
9
10#[rustfmt::skip]
14#[derive(Debug, PartialEq, Eq, Clone, Copy)]
15#[apply(derive_ASTNode!)]
16pub enum BinaryOperator {
17 Add, Subtract, Multiply, Divide, Modulo, Exponent,
18
19 BitwiseShiftLeft, BitwiseShiftRight, BitwiseShiftRightUnsigned,
20 BitwiseAnd, BitwiseXOr, BitwiseOr,
21
22 StrictEqual, StrictNotEqual, Equal, NotEqual,
23 GreaterThan, LessThan, LessThanEqual, GreaterThanEqual,
24
25 LogicalAnd, LogicalOr,
26 NullCoalescing,
27
28 Pipe,
30 Compose
31}
32
33impl BinaryOperator {
34 #[must_use]
35 pub fn is_non_standard(&self) -> bool {
36 matches!(self, BinaryOperator::Pipe | BinaryOperator::Compose)
37 }
38}
39
40#[rustfmt::skip]
42#[derive(Debug, PartialEq, Eq, Clone, Copy)]
43#[apply(derive_ASTNode!)]
44pub enum BinaryAssignmentOperator {
45 LogicalNullishAssignment,
46
47 AddAssign, SubtractAssign, MultiplyAssign, DivideAssign, ModuloAssign, ExponentAssign,
48 LogicalAndAssign, LogicalOrAssign,
49 BitwiseShiftLeftAssign, BitwiseShiftRightAssign, BitwiseShiftRightUnsigned,
50 BitwiseAndAssign, BitwiseXOrAssign, BitwiseOrAssign,
51}
52
53#[rustfmt::skip]
54#[derive(Debug, PartialEq, Eq, Clone, Copy)]
55#[apply(derive_ASTNode!)]
56pub enum UnaryOperator {
57 Plus, Negation,
58 BitwiseNot, LogicalNot,
59 Await, TypeOf, Void, Delete,
60 Yield, DelegatedYield,
61}
62
63#[derive(Debug, PartialEq, Eq, Clone, Copy)]
64#[apply(derive_ASTNode!)]
65pub enum IncrementOrDecrement {
66 Increment,
67 Decrement,
68}
69
70#[derive(Debug, PartialEq, Eq, Clone, Copy)]
71#[apply(derive_ASTNode!)]
72pub enum UnaryPrefixAssignmentOperator {
73 Invert,
74 IncrementOrDecrement(IncrementOrDecrement),
75}
76
77#[derive(Debug, PartialEq, Eq, Clone, Copy)]
78#[apply(derive_ASTNode!)]
79pub struct UnaryPostfixAssignmentOperator(pub IncrementOrDecrement);
80
81#[derive(Debug, PartialEq, Eq, Clone, Copy)]
82pub enum AssociativityDirection {
83 NA,
84 LeftToRight,
85 RightToLeft,
86}
87
88impl AssociativityDirection {
89 pub(crate) fn should_return(self, parent_precedence: u8, upcoming_precedence: u8) -> bool {
90 match self {
91 AssociativityDirection::RightToLeft => parent_precedence > upcoming_precedence,
92 AssociativityDirection::NA | AssociativityDirection::LeftToRight => {
93 parent_precedence >= upcoming_precedence
94 }
95 }
96 }
97}
98
99pub trait Operator: for<'a> TryFrom<&'a TSXToken> {
100 fn to_str(&self) -> &'static str;
102
103 fn precedence(&self) -> u8;
105
106 fn associativity_direction(&self) -> AssociativityDirection;
108
109 fn is_associative(&self) -> bool;
111
112 fn precedence_and_associativity_direction(&self) -> (u8, AssociativityDirection) {
113 (self.precedence(), self.associativity_direction())
114 }
115}
116
117impl Operator for BinaryOperator {
118 fn to_str(&self) -> &'static str {
119 match self {
120 BinaryOperator::Add => "+",
121 BinaryOperator::Subtract => "-",
122 BinaryOperator::Multiply => "*",
123 BinaryOperator::Divide => "/",
124 BinaryOperator::Exponent => "**",
125 BinaryOperator::LessThan => "<",
126 BinaryOperator::GreaterThan => ">",
127 BinaryOperator::LessThanEqual => "<=",
128 BinaryOperator::GreaterThanEqual => ">=",
129 BinaryOperator::Equal => "==",
130 BinaryOperator::StrictEqual => "===",
131 BinaryOperator::NotEqual => "!=",
132 BinaryOperator::StrictNotEqual => "!==",
133 BinaryOperator::Modulo => "%",
134 BinaryOperator::NullCoalescing => "??",
135 BinaryOperator::LogicalAnd => "&&",
136 BinaryOperator::LogicalOr => "||",
137 BinaryOperator::BitwiseShiftLeft => "<<",
138 BinaryOperator::BitwiseShiftRight => ">>",
139 BinaryOperator::BitwiseShiftRightUnsigned => ">>>",
140 BinaryOperator::BitwiseAnd => "&",
141 BinaryOperator::BitwiseOr => "|",
142 BinaryOperator::BitwiseXOr => "^",
143 BinaryOperator::Compose => "<@>", BinaryOperator::Pipe => "|>",
145 }
146 }
147
148 fn precedence(&self) -> u8 {
149 match self {
150 BinaryOperator::Pipe | BinaryOperator::Compose => 15,
151 BinaryOperator::Exponent => 14,
152 BinaryOperator::Multiply | BinaryOperator::Divide | BinaryOperator::Modulo => 13,
153 BinaryOperator::Add | BinaryOperator::Subtract => 12,
154 BinaryOperator::BitwiseShiftLeft
155 | BinaryOperator::BitwiseShiftRightUnsigned
156 | BinaryOperator::BitwiseShiftRight => 11,
157 BinaryOperator::LessThan
158 | BinaryOperator::LessThanEqual
159 | BinaryOperator::GreaterThanEqual
160 | BinaryOperator::GreaterThan => 10,
161 BinaryOperator::Equal
162 | BinaryOperator::NotEqual
163 | BinaryOperator::StrictEqual
164 | BinaryOperator::StrictNotEqual => 9,
165 BinaryOperator::BitwiseAnd => 8,
166 BinaryOperator::BitwiseXOr => 7,
167 BinaryOperator::BitwiseOr => 6,
168 BinaryOperator::LogicalAnd => 5,
169 BinaryOperator::NullCoalescing | BinaryOperator::LogicalOr => 4,
170 }
171 }
172
173 fn associativity_direction(&self) -> AssociativityDirection {
174 if let BinaryOperator::Exponent = self {
175 AssociativityDirection::RightToLeft
176 } else {
177 AssociativityDirection::LeftToRight
178 }
179 }
180
181 fn is_associative(&self) -> bool {
182 !matches!(self, Self::Subtract | Self::Exponent | Self::Divide)
183 }
184}
185
186impl Operator for UnaryOperator {
187 fn to_str(&self) -> &'static str {
188 match self {
189 UnaryOperator::Plus => "+",
190 UnaryOperator::Negation => "-",
191 UnaryOperator::BitwiseNot => "~",
192 UnaryOperator::LogicalNot => "!",
193 UnaryOperator::Delete => "delete ",
194 UnaryOperator::Yield => "yield ",
195 UnaryOperator::DelegatedYield => "yield* ",
196 UnaryOperator::Await => "await ",
197 UnaryOperator::TypeOf => "typeof ",
198 UnaryOperator::Void => "void ",
199 }
200 }
201
202 fn precedence(&self) -> u8 {
203 match self {
204 UnaryOperator::TypeOf
205 | UnaryOperator::Await
206 | UnaryOperator::Delete
207 | UnaryOperator::Void
208 | UnaryOperator::BitwiseNot
209 | UnaryOperator::LogicalNot
210 | UnaryOperator::Plus
211 | UnaryOperator::Negation => 15,
212 UnaryOperator::Yield | UnaryOperator::DelegatedYield => 2,
213 }
214 }
215
216 fn associativity_direction(&self) -> AssociativityDirection {
217 AssociativityDirection::RightToLeft
218 }
219
220 fn is_associative(&self) -> bool {
221 true
222 }
223}
224
225impl Operator for BinaryAssignmentOperator {
226 fn to_str(&self) -> &'static str {
227 match self {
228 BinaryAssignmentOperator::LogicalNullishAssignment => "??=",
229 BinaryAssignmentOperator::AddAssign => "+=",
230 BinaryAssignmentOperator::SubtractAssign => "-=",
231 BinaryAssignmentOperator::MultiplyAssign => "*=",
232 BinaryAssignmentOperator::DivideAssign => "/=",
233 BinaryAssignmentOperator::ModuloAssign => "%=",
234 BinaryAssignmentOperator::ExponentAssign => "**=",
235 BinaryAssignmentOperator::BitwiseShiftLeftAssign => "<<=",
236 BinaryAssignmentOperator::BitwiseShiftRightAssign => ">>=",
237 BinaryAssignmentOperator::BitwiseShiftRightUnsigned => ">>>=",
238 BinaryAssignmentOperator::BitwiseAndAssign => "&=",
239 BinaryAssignmentOperator::BitwiseXOrAssign => "^=",
240 BinaryAssignmentOperator::BitwiseOrAssign => "|=",
241 BinaryAssignmentOperator::LogicalAndAssign => "&&=",
242 BinaryAssignmentOperator::LogicalOrAssign => "||=",
243 }
244 }
245
246 fn precedence(&self) -> u8 {
247 ASSIGNMENT_PRECEDENCE
248 }
249
250 fn associativity_direction(&self) -> AssociativityDirection {
251 AssociativityDirection::RightToLeft
252 }
253
254 fn is_associative(&self) -> bool {
255 true
257 }
258}
259
260impl Operator for UnaryPrefixAssignmentOperator {
261 fn precedence(&self) -> u8 {
262 15
263 }
264
265 fn associativity_direction(&self) -> AssociativityDirection {
266 AssociativityDirection::RightToLeft
267 }
268
269 fn to_str(&self) -> &'static str {
270 match self {
271 UnaryPrefixAssignmentOperator::Invert => ">!", UnaryPrefixAssignmentOperator::IncrementOrDecrement(inc_or_dec) => inc_or_dec.to_str(),
273 }
274 }
275
276 fn is_associative(&self) -> bool {
277 true
278 }
279}
280
281impl Operator for UnaryPostfixAssignmentOperator {
282 fn precedence(&self) -> u8 {
283 16
284 }
285
286 fn associativity_direction(&self) -> AssociativityDirection {
287 AssociativityDirection::NA
288 }
289
290 fn to_str(&self) -> &'static str {
291 self.0.to_str()
292 }
293
294 fn is_associative(&self) -> bool {
295 true
296 }
297}
298
299impl IncrementOrDecrement {
300 fn to_str(self) -> &'static str {
301 match self {
302 IncrementOrDecrement::Increment => "++",
303 IncrementOrDecrement::Decrement => "--",
304 }
305 }
306}
307
308impl From<BinaryAssignmentOperator> for BinaryOperator {
309 fn from(val: BinaryAssignmentOperator) -> Self {
310 match val {
311 BinaryAssignmentOperator::LogicalNullishAssignment => BinaryOperator::NullCoalescing,
312 BinaryAssignmentOperator::AddAssign => BinaryOperator::Add,
313 BinaryAssignmentOperator::SubtractAssign => BinaryOperator::Subtract,
314 BinaryAssignmentOperator::MultiplyAssign => BinaryOperator::Multiply,
315 BinaryAssignmentOperator::DivideAssign => BinaryOperator::Divide,
316 BinaryAssignmentOperator::ModuloAssign => BinaryOperator::Modulo,
317 BinaryAssignmentOperator::ExponentAssign => BinaryOperator::Exponent,
318 BinaryAssignmentOperator::LogicalAndAssign => BinaryOperator::LogicalAnd,
319 BinaryAssignmentOperator::LogicalOrAssign => BinaryOperator::LogicalOr,
320 BinaryAssignmentOperator::BitwiseShiftLeftAssign => BinaryOperator::BitwiseShiftLeft,
321 BinaryAssignmentOperator::BitwiseShiftRightAssign => BinaryOperator::BitwiseShiftRight,
322 BinaryAssignmentOperator::BitwiseShiftRightUnsigned => {
323 BinaryOperator::BitwiseShiftRightUnsigned
324 }
325 BinaryAssignmentOperator::BitwiseAndAssign => BinaryOperator::BitwiseAnd,
326 BinaryAssignmentOperator::BitwiseXOrAssign => BinaryOperator::BitwiseXOr,
327 BinaryAssignmentOperator::BitwiseOrAssign => BinaryOperator::BitwiseOr,
328 }
329 }
330}
331
332impl TryFrom<&TSXToken> for BinaryAssignmentOperator {
333 type Error = ();
334
335 fn try_from(expression: &TSXToken) -> Result<Self, Self::Error> {
336 match expression {
337 TSXToken::AddAssign => Ok(BinaryAssignmentOperator::AddAssign),
338 TSXToken::SubtractAssign => Ok(BinaryAssignmentOperator::SubtractAssign),
339 TSXToken::MultiplyAssign => Ok(BinaryAssignmentOperator::MultiplyAssign),
340 TSXToken::DivideAssign => Ok(BinaryAssignmentOperator::DivideAssign),
341 TSXToken::ExponentAssign => Ok(BinaryAssignmentOperator::ExponentAssign),
342 TSXToken::LogicalAndAssign => Ok(BinaryAssignmentOperator::LogicalAndAssign),
343 TSXToken::LogicalOrAssign => Ok(BinaryAssignmentOperator::LogicalOrAssign),
344 TSXToken::BitwiseAndAssign => Ok(BinaryAssignmentOperator::BitwiseAndAssign),
345 TSXToken::BitwiseOrAssign => Ok(BinaryAssignmentOperator::BitwiseOrAssign),
346 TSXToken::BitwiseXorAssign => Ok(BinaryAssignmentOperator::BitwiseXOrAssign),
347 TSXToken::BitwiseShiftLeftAssign => {
348 Ok(BinaryAssignmentOperator::BitwiseShiftLeftAssign)
349 }
350 TSXToken::BitwiseShiftRightAssign => {
351 Ok(BinaryAssignmentOperator::BitwiseShiftRightAssign)
352 }
353 TSXToken::BitwiseShiftRightUnsignedAssign => {
354 Ok(BinaryAssignmentOperator::BitwiseShiftRightUnsigned)
355 }
356 TSXToken::NullishCoalescingAssign => {
357 Ok(BinaryAssignmentOperator::LogicalNullishAssignment)
358 }
359 _ => Err(()),
360 }
361 }
362}
363
364impl TryFrom<&TSXToken> for BinaryOperator {
365 type Error = ();
366
367 fn try_from(expression: &TSXToken) -> Result<Self, Self::Error> {
368 match expression {
369 TSXToken::Add => Ok(BinaryOperator::Add),
370 TSXToken::Subtract => Ok(BinaryOperator::Subtract),
371 TSXToken::Multiply => Ok(BinaryOperator::Multiply),
372 TSXToken::Divide => Ok(BinaryOperator::Divide),
373 TSXToken::Exponent => Ok(BinaryOperator::Exponent),
374 TSXToken::Modulo => Ok(BinaryOperator::Modulo),
375 TSXToken::Equal => Ok(BinaryOperator::Equal),
376 TSXToken::NotEqual => Ok(BinaryOperator::NotEqual),
377 TSXToken::StrictEqual => Ok(BinaryOperator::StrictEqual),
378 TSXToken::StrictNotEqual => Ok(BinaryOperator::StrictNotEqual),
379 TSXToken::LogicalOr => Ok(BinaryOperator::LogicalOr),
380 TSXToken::LogicalAnd => Ok(BinaryOperator::LogicalAnd),
381 TSXToken::OpenChevron => Ok(BinaryOperator::LessThan),
382 TSXToken::LessThanEqual => Ok(BinaryOperator::LessThanEqual),
383 TSXToken::CloseChevron => Ok(BinaryOperator::GreaterThan),
384 TSXToken::GreaterThanEqual => Ok(BinaryOperator::GreaterThanEqual),
385 TSXToken::BitwiseAnd => Ok(BinaryOperator::BitwiseAnd),
386 TSXToken::BitwiseOr => Ok(BinaryOperator::BitwiseOr),
387 TSXToken::BitwiseXOr => Ok(BinaryOperator::BitwiseXOr),
388 TSXToken::BitwiseShiftLeft => Ok(BinaryOperator::BitwiseShiftLeft),
389 TSXToken::BitwiseShiftRight => Ok(BinaryOperator::BitwiseShiftRight),
390 TSXToken::BitwiseShiftRightUnsigned => Ok(BinaryOperator::BitwiseShiftRightUnsigned),
391 TSXToken::NullishCoalescing => Ok(BinaryOperator::NullCoalescing),
392 #[cfg(feature = "extras")]
393 TSXToken::ComposeOperator => Ok(BinaryOperator::Compose),
394 #[cfg(feature = "extras")]
395 TSXToken::PipeOperator => Ok(BinaryOperator::Pipe),
396 _ => Err(()),
397 }
398 }
399}
400
401impl TryFrom<&TSXToken> for UnaryOperator {
403 type Error = ();
404
405 fn try_from(expression: &TSXToken) -> Result<Self, Self::Error> {
406 match expression {
407 TSXToken::Keyword(TSXKeyword::TypeOf) => Ok(UnaryOperator::TypeOf),
408 TSXToken::Keyword(TSXKeyword::Await) => Ok(UnaryOperator::Await),
409 TSXToken::Keyword(TSXKeyword::Void) => Ok(UnaryOperator::Void),
410 TSXToken::Keyword(TSXKeyword::Delete) => Ok(UnaryOperator::Delete),
411 TSXToken::LogicalNot => Ok(UnaryOperator::LogicalNot),
412 TSXToken::BitwiseNot => Ok(UnaryOperator::BitwiseNot),
413 TSXToken::Subtract => Ok(UnaryOperator::Negation),
414 TSXToken::Add => Ok(UnaryOperator::Plus),
415 _ => Err(()),
416 }
417 }
418}
419
420impl TryFrom<&TSXToken> for IncrementOrDecrement {
421 type Error = ();
422
423 fn try_from(token: &TSXToken) -> Result<Self, Self::Error> {
424 match token {
425 TSXToken::Increment => Ok(Self::Increment),
426 TSXToken::Decrement => Ok(Self::Decrement),
427 _ => Err(()),
428 }
429 }
430}
431
432impl TryFrom<&TSXToken> for UnaryPostfixAssignmentOperator {
433 type Error = ();
434
435 fn try_from(token: &TSXToken) -> Result<Self, Self::Error> {
436 IncrementOrDecrement::try_from(token).map(Self)
437 }
438}
439
440impl TryFrom<&TSXToken> for UnaryPrefixAssignmentOperator {
441 type Error = ();
442
443 fn try_from(token: &TSXToken) -> Result<Self, Self::Error> {
444 #[cfg(feature = "extras")]
445 if *token == TSXToken::InvertAssign {
446 Ok(Self::Invert)
447 } else {
448 IncrementOrDecrement::try_from(token).map(Self::IncrementOrDecrement)
449 }
450 #[cfg(not(feature = "extras"))]
451 IncrementOrDecrement::try_from(token).map(Self::IncrementOrDecrement)
452 }
453}
454
455impl BinaryOperator {
456 #[must_use]
458 pub fn is_rhs_conditional_evaluation(&self) -> bool {
459 matches!(
460 self,
461 BinaryOperator::LogicalAnd | BinaryOperator::LogicalOr | BinaryOperator::NullCoalescing
462 )
463 }
464}
465
466pub(crate) const COMMA_PRECEDENCE: u8 = 1;
468pub(crate) const MEMBER_ACCESS_PRECEDENCE: u8 = 18;
469pub(crate) const INDEX_PRECEDENCE: u8 = 18;
470pub(crate) const CONDITIONAL_TERNARY_PRECEDENCE: u8 = 2;
471pub(crate) const FUNCTION_CALL_PRECEDENCE: u8 = 18;
472pub(crate) const CONSTRUCTOR_PRECEDENCE: u8 = 18;
473pub(crate) const CONSTRUCTOR_WITHOUT_PARENTHESIS_PRECEDENCE: u8 = 17;
474pub(crate) const RELATION_PRECEDENCE: u8 = 10;
475pub(crate) const PARENTHESIZED_EXPRESSION_AND_LITERAL_PRECEDENCE: u8 = 19;
476pub(crate) const ARROW_FUNCTION_PRECEDENCE: u8 = 2;
477pub(crate) const ASSIGNMENT_PRECEDENCE: u8 = 2;