parse_js/
operator.rs

1use crate::operator::Arity::*;
2use crate::operator::Associativity::*;
3use crate::operator::OperatorName::*;
4use ahash::AHashMap;
5use once_cell::sync::Lazy;
6use serde::Serialize;
7
8#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize)]
9pub enum OperatorName {
10  Addition,
11  Assignment,
12  AssignmentAddition,
13  AssignmentBitwiseAnd,
14  AssignmentBitwiseLeftShift,
15  AssignmentBitwiseOr,
16  AssignmentBitwiseRightShift,
17  AssignmentBitwiseUnsignedRightShift,
18  AssignmentBitwiseXor,
19  AssignmentDivision,
20  AssignmentExponentiation,
21  AssignmentLogicalAnd,
22  AssignmentLogicalOr,
23  AssignmentMultiplication,
24  AssignmentNullishCoalescing,
25  AssignmentRemainder,
26  AssignmentSubtraction,
27  Await,
28  BitwiseAnd,
29  BitwiseLeftShift,
30  BitwiseNot,
31  BitwiseOr,
32  BitwiseRightShift,
33  BitwiseUnsignedRightShift,
34  BitwiseXor,
35  Call,
36  Comma,
37  ComputedMemberAccess,
38  Conditional,
39  // Only used during parsing.
40  ConditionalAlternate,
41  Delete,
42  Division,
43  Equality,
44  Exponentiation,
45  GreaterThan,
46  GreaterThanOrEqual,
47  In,
48  Inequality,
49  Instanceof,
50  LessThan,
51  LessThanOrEqual,
52  LogicalAnd,
53  LogicalNot,
54  LogicalOr,
55  MemberAccess,
56  Multiplication,
57  New,
58  NullishCoalescing,
59  OptionalChainingMemberAccess,
60  OptionalChainingComputedMemberAccess,
61  OptionalChainingCall,
62  PostfixDecrement,
63  PostfixIncrement,
64  PrefixDecrement,
65  PrefixIncrement,
66  Remainder,
67  StrictEquality,
68  StrictInequality,
69  Subtraction,
70  Typeof,
71  UnaryNegation,
72  UnaryPlus,
73  Void,
74  Yield,
75  YieldDelegated,
76}
77
78impl OperatorName {
79  pub fn is_assignment(self) -> bool {
80    match self {
81      OperatorName::Assignment
82      | OperatorName::AssignmentAddition
83      | OperatorName::AssignmentBitwiseAnd
84      | OperatorName::AssignmentBitwiseLeftShift
85      | OperatorName::AssignmentBitwiseOr
86      | OperatorName::AssignmentBitwiseRightShift
87      | OperatorName::AssignmentBitwiseUnsignedRightShift
88      | OperatorName::AssignmentBitwiseXor
89      | OperatorName::AssignmentDivision
90      | OperatorName::AssignmentExponentiation
91      | OperatorName::AssignmentLogicalAnd
92      | OperatorName::AssignmentLogicalOr
93      | OperatorName::AssignmentMultiplication
94      | OperatorName::AssignmentNullishCoalescing
95      | OperatorName::AssignmentRemainder
96      | OperatorName::AssignmentSubtraction => true,
97      _ => false,
98    }
99  }
100}
101
102#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
103pub enum Arity {
104  Unary,
105  Binary,
106  Ternary,
107}
108
109#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
110pub enum Associativity {
111  Left,
112  Right,
113}
114
115pub struct Operator {
116  pub name: OperatorName,
117  pub arity: Arity,
118  pub associativity: Associativity,
119  pub precedence: u8,
120}
121
122const PRECEDENCE_LEVELS: &[&[(OperatorName, Arity, Associativity)]] = &[
123  &[
124    (MemberAccess, Binary, Left),
125    (ComputedMemberAccess, Binary, Left),
126    (Call, Binary, Left),
127    (New, Unary, Right),
128    (OptionalChainingMemberAccess, Binary, Left),
129    (OptionalChainingComputedMemberAccess, Binary, Left),
130    (OptionalChainingCall, Binary, Left),
131  ],
132  &[
133    (PostfixIncrement, Unary, Left),
134    (PostfixDecrement, Unary, Left),
135  ],
136  &[
137    (LogicalNot, Unary, Right),
138    (BitwiseNot, Unary, Right),
139    (UnaryPlus, Unary, Right),
140    (UnaryNegation, Unary, Right),
141    (PrefixIncrement, Unary, Right),
142    (PrefixDecrement, Unary, Right),
143    (Typeof, Unary, Right),
144    (Void, Unary, Right),
145    (Delete, Unary, Right),
146    (Await, Unary, Right),
147  ],
148  &[(Exponentiation, Binary, Right)],
149  &[
150    (Multiplication, Binary, Left),
151    (Division, Binary, Left),
152    (Remainder, Binary, Left),
153  ],
154  &[(Addition, Binary, Left), (Subtraction, Binary, Left)],
155  &[
156    (BitwiseLeftShift, Binary, Left),
157    (BitwiseRightShift, Binary, Left),
158    (BitwiseUnsignedRightShift, Binary, Left),
159  ],
160  &[
161    (LessThan, Binary, Left),
162    (LessThanOrEqual, Binary, Left),
163    (GreaterThan, Binary, Left),
164    (GreaterThanOrEqual, Binary, Left),
165    (In, Binary, Left),
166    (Instanceof, Binary, Left),
167  ],
168  &[
169    (Equality, Binary, Left),
170    (Inequality, Binary, Left),
171    (StrictEquality, Binary, Left),
172    (StrictInequality, Binary, Left),
173  ],
174  &[(BitwiseAnd, Binary, Left)],
175  &[(BitwiseXor, Binary, Left)],
176  &[(BitwiseOr, Binary, Left)],
177  &[(LogicalAnd, Binary, Left)],
178  &[(LogicalOr, Binary, Left), (NullishCoalescing, Binary, Left)],
179  &[(Conditional, Ternary, Right)],
180  &[
181    (Assignment, Binary, Right),
182    (AssignmentAddition, Binary, Right),
183    (AssignmentBitwiseAnd, Binary, Right),
184    (AssignmentBitwiseLeftShift, Binary, Right),
185    (AssignmentBitwiseOr, Binary, Right),
186    (AssignmentBitwiseRightShift, Binary, Right),
187    (AssignmentBitwiseUnsignedRightShift, Binary, Right),
188    (AssignmentBitwiseXor, Binary, Right),
189    (AssignmentDivision, Binary, Right),
190    (AssignmentExponentiation, Binary, Right),
191    (AssignmentLogicalAnd, Binary, Right),
192    (AssignmentLogicalOr, Binary, Right),
193    (AssignmentMultiplication, Binary, Right),
194    (AssignmentNullishCoalescing, Binary, Right),
195    (AssignmentRemainder, Binary, Right),
196    (AssignmentSubtraction, Binary, Right),
197    (Yield, Unary, Right),
198    (YieldDelegated, Unary, Right),
199  ],
200  // Given `a, b = true ? c : d = e, f`, the evaluation is `a, (b = (true ? c : (d = e))), e`.
201  &[(ConditionalAlternate, Ternary, Right)],
202  &[(Comma, Binary, Left)],
203];
204
205pub static OPERATORS: Lazy<AHashMap<OperatorName, Operator>> = Lazy::new(|| {
206  let mut map = AHashMap::<OperatorName, Operator>::new();
207  for (i, ops) in PRECEDENCE_LEVELS.iter().enumerate() {
208    let precedence = (PRECEDENCE_LEVELS.len() - i) as u8;
209    for &(name, arity, associativity) in ops.iter() {
210      map.insert(name, Operator {
211        name,
212        arity,
213        associativity,
214        precedence,
215      });
216    }
217  }
218  map
219});