swc_ecma_parser/parser/
util.rs1use super::*;
2use crate::token::{IdentLike, Keyword};
3
4impl Context {
5 pub(crate) fn is_reserved(self, word: &Word) -> bool {
6 match *word {
7 Word::Keyword(Keyword::Let) => self.strict,
8 Word::Keyword(Keyword::Await) => self.in_async || self.in_static_block || self.strict,
9 Word::Keyword(Keyword::Yield) => self.in_generator || self.strict,
10
11 Word::Null
12 | Word::True
13 | Word::False
14 | Word::Keyword(Keyword::Break)
15 | Word::Keyword(Keyword::Case)
16 | Word::Keyword(Keyword::Catch)
17 | Word::Keyword(Keyword::Continue)
18 | Word::Keyword(Keyword::Debugger)
19 | Word::Keyword(Keyword::Default_)
20 | Word::Keyword(Keyword::Do)
21 | Word::Keyword(Keyword::Export)
22 | Word::Keyword(Keyword::Else)
23 | Word::Keyword(Keyword::Finally)
24 | Word::Keyword(Keyword::For)
25 | Word::Keyword(Keyword::Function)
26 | Word::Keyword(Keyword::If)
27 | Word::Keyword(Keyword::Return)
28 | Word::Keyword(Keyword::Switch)
29 | Word::Keyword(Keyword::Throw)
30 | Word::Keyword(Keyword::Try)
31 | Word::Keyword(Keyword::Var)
32 | Word::Keyword(Keyword::Const)
33 | Word::Keyword(Keyword::While)
34 | Word::Keyword(Keyword::With)
35 | Word::Keyword(Keyword::New)
36 | Word::Keyword(Keyword::This)
37 | Word::Keyword(Keyword::Super)
38 | Word::Keyword(Keyword::Class)
39 | Word::Keyword(Keyword::Extends)
40 | Word::Keyword(Keyword::Import)
41 | Word::Keyword(Keyword::In)
42 | Word::Keyword(Keyword::InstanceOf)
43 | Word::Keyword(Keyword::TypeOf)
44 | Word::Keyword(Keyword::Void)
45 | Word::Keyword(Keyword::Delete) => true,
46
47 Word::Ident(IdentLike::Known(known_ident!("enum"))) => true,
49
50 Word::Ident(IdentLike::Known(
51 known_ident!("implements")
52 | known_ident!("package")
53 | known_ident!("protected")
54 | known_ident!("interface")
55 | known_ident!("private")
56 | known_ident!("public"),
57 )) if self.strict => true,
58
59 _ => false,
60 }
61 }
62
63 #[cfg_attr(not(feature = "verify"), inline(always))]
64 pub fn is_reserved_word(self, word: &Atom) -> bool {
65 if !cfg!(feature = "verify") {
66 return false;
67 }
68
69 match &**word {
70 "let" => self.strict,
71 "await" => self.in_async || self.in_static_block || self.module,
79 "yield" => self.in_generator || self.strict,
80
81 "null" | "true" | "false" | "break" | "case" | "catch" | "continue" | "debugger"
82 | "default" | "do" | "export" | "else" | "finally" | "for" | "function" | "if"
83 | "return" | "switch" | "throw" | "try" | "var" | "const" | "while" | "with"
84 | "new" | "this" | "super" | "class" | "extends" | "import" | "in" | "instanceof"
85 | "typeof" | "void" | "delete" => true,
86
87 "enum" => true,
89
90 "implements" | "package" | "protected" | "interface" | "private" | "public"
91 if self.strict =>
92 {
93 true
94 }
95
96 _ => false,
97 }
98 }
99}
100
101impl<I: Tokens> Parser<I> {
102 pub(super) fn with_ctx(&mut self, ctx: Context) -> WithCtx<I> {
104 let orig_ctx = self.ctx();
105 self.set_ctx(ctx);
106 WithCtx {
107 orig_ctx,
108 inner: self,
109 }
110 }
111
112 pub(super) fn with_state(&mut self, state: State) -> WithState<I> {
114 let orig_state = std::mem::replace(&mut self.state, state);
115 WithState {
116 orig_state,
117 inner: self,
118 }
119 }
120
121 pub(super) fn set_ctx(&mut self, ctx: Context) {
122 self.input.set_ctx(ctx);
123 }
124
125 pub(super) fn strict_mode(&mut self) -> WithCtx<I> {
126 let ctx = Context {
127 strict: true,
128 ..self.ctx()
129 };
130 self.with_ctx(ctx)
131 }
132
133 pub(super) fn in_type(&mut self) -> WithCtx<I> {
135 let ctx = Context {
136 in_type: true,
137 ..self.ctx()
138 };
139 self.with_ctx(ctx)
140 }
141
142 pub(super) fn include_in_expr(&mut self, include_in_expr: bool) -> WithCtx<I> {
144 let ctx = Context {
145 include_in_expr,
146 ..self.ctx()
147 };
148 self.with_ctx(ctx)
149 }
150
151 #[inline(always)]
153 pub(super) fn parse_with<F, Ret>(&mut self, f: F) -> PResult<Ret>
154 where
155 F: FnOnce(&mut Self) -> PResult<Ret>,
156 {
157 f(self)
158 }
159
160 pub(super) fn syntax(&self) -> Syntax {
161 self.input.syntax()
162 }
163}
164pub trait ParseObject<Obj> {
165 type Prop;
166 fn make_object(
167 &mut self,
168 span: Span,
169 props: Vec<Self::Prop>,
170 trailing_comma: Option<Span>,
171 ) -> PResult<Obj>;
172 fn parse_object_prop(&mut self) -> PResult<Self::Prop>;
173}
174
175pub struct WithState<'w, I: 'w + Tokens> {
176 inner: &'w mut Parser<I>,
177 orig_state: State,
178}
179impl<I: Tokens> Deref for WithState<'_, I> {
180 type Target = Parser<I>;
181
182 fn deref(&self) -> &Parser<I> {
183 self.inner
184 }
185}
186impl<I: Tokens> DerefMut for WithState<'_, I> {
187 fn deref_mut(&mut self) -> &mut Parser<I> {
188 self.inner
189 }
190}
191impl<I: Tokens> Drop for WithState<'_, I> {
192 fn drop(&mut self) {
193 std::mem::swap(&mut self.inner.state, &mut self.orig_state);
194 }
195}
196
197pub struct WithCtx<'w, I: 'w + Tokens> {
198 inner: &'w mut Parser<I>,
199 orig_ctx: Context,
200}
201impl<I: Tokens> Deref for WithCtx<'_, I> {
202 type Target = Parser<I>;
203
204 fn deref(&self) -> &Parser<I> {
205 self.inner
206 }
207}
208impl<I: Tokens> DerefMut for WithCtx<'_, I> {
209 fn deref_mut(&mut self) -> &mut Parser<I> {
210 self.inner
211 }
212}
213
214impl<I: Tokens> Drop for WithCtx<'_, I> {
215 fn drop(&mut self) {
216 self.inner.set_ctx(self.orig_ctx);
217 }
218}
219
220pub(super) trait ExprExt {
221 fn as_expr(&self) -> &Expr;
222
223 fn is_valid_simple_assignment_target(&self, strict: bool) -> bool {
225 match self.as_expr() {
226 Expr::Ident(ident) => {
227 if strict && ident.is_reserved_in_strict_bind() {
228 return false;
229 }
230 true
231 }
232
233 Expr::This(..)
234 | Expr::Lit(..)
235 | Expr::Array(..)
236 | Expr::Object(..)
237 | Expr::Fn(..)
238 | Expr::Class(..)
239 | Expr::Tpl(..)
240 | Expr::TaggedTpl(..) => false,
241 Expr::Paren(ParenExpr { expr, .. }) => expr.is_valid_simple_assignment_target(strict),
242
243 Expr::Member(MemberExpr { obj, .. }) => match obj.as_ref() {
244 Expr::Member(..) => obj.is_valid_simple_assignment_target(strict),
245 Expr::OptChain(..) => false,
246 _ => true,
247 },
248
249 Expr::SuperProp(..) => true,
250
251 Expr::New(..) | Expr::Call(..) => false,
252 Expr::MetaProp(..) => false,
254
255 Expr::Update(..) => false,
256
257 Expr::Unary(..) | Expr::Await(..) => false,
258
259 Expr::Bin(..) => false,
260
261 Expr::Cond(..) => false,
262
263 Expr::Yield(..) | Expr::Arrow(..) | Expr::Assign(..) => false,
264
265 Expr::Seq(..) => false,
266
267 Expr::OptChain(..) => false,
268
269 Expr::PrivateName(..) => false,
271
272 Expr::JSXMember(..)
274 | Expr::JSXNamespacedName(..)
275 | Expr::JSXEmpty(..)
276 | Expr::JSXElement(..)
277 | Expr::JSXFragment(..) => false,
278
279 Expr::TsNonNull(TsNonNullExpr { ref expr, .. })
281 | Expr::TsTypeAssertion(TsTypeAssertion { ref expr, .. })
282 | Expr::TsAs(TsAsExpr { ref expr, .. })
283 | Expr::TsInstantiation(TsInstantiation { ref expr, .. })
284 | Expr::TsSatisfies(TsSatisfiesExpr { ref expr, .. }) => {
285 expr.is_valid_simple_assignment_target(strict)
286 }
287
288 Expr::TsConstAssertion(..) => false,
289
290 Expr::Invalid(..) => false,
291 }
292 }
293}
294
295impl ExprExt for Box<Expr> {
296 fn as_expr(&self) -> &Expr {
297 self
298 }
299}
300impl ExprExt for Expr {
301 fn as_expr(&self) -> &Expr {
302 self
303 }
304}