swc_ecma_lexer/common/parser/
mod.rs1use either::Either;
2use expr::{parse_assignment_expr, parse_str_lit};
3use expr_ext::ExprExt;
4use swc_atoms::Atom;
5use swc_common::{BytePos, Span, Spanned};
6use swc_ecma_ast::*;
7
8use self::{
9 buffer::{Buffer, NextTokenAndSpan},
10 state::{State, WithState},
11 token_and_span::TokenAndSpan,
12};
13use super::{context::Context, input::Tokens, lexer::token::TokenFactory};
14use crate::{
15 common::syntax::SyntaxFlags,
16 error::{Error, SyntaxError},
17};
18
19pub type PResult<T> = Result<T, crate::error::Error>;
20
21pub mod buffer;
22pub mod expr_ext;
23pub mod is_directive;
24pub mod is_invalid_class_name;
25pub mod is_simple_param_list;
26#[macro_use]
27mod macros;
28pub mod assign_target_or_spread;
29pub mod class_and_fn;
30pub mod expr;
31pub mod ident;
32pub mod jsx;
33pub mod module_item;
34pub mod object;
35pub mod output_type;
36pub mod pat;
37pub mod pat_type;
38pub mod state;
39pub mod stmt;
40pub mod token_and_span;
41pub mod typescript;
42mod util;
43#[cfg(feature = "verify")]
44pub mod verifier;
45
46pub use util::{
47 get_qualified_jsx_name, has_use_strict, is_constructor, is_not_this, make_decl_declare,
48 unwrap_ts_non_null,
49};
50
51pub trait Parser<'a>: Sized + Clone {
52 type Token: std::fmt::Debug
53 + Clone
54 + TokenFactory<'a, Self::TokenAndSpan, Self::I, Buffer = Self::Buffer>;
55 type Next: NextTokenAndSpan<Token = Self::Token>;
56 type TokenAndSpan: TokenAndSpan<Token = Self::Token>;
57 type I: Tokens<Self::TokenAndSpan>;
58 type Buffer: self::buffer::Buffer<
59 'a,
60 Token = Self::Token,
61 TokenAndSpan = Self::TokenAndSpan,
62 I = Self::I,
63 >;
64 type Checkpoint;
65
66 fn input(&self) -> &Self::Buffer;
67 fn input_mut(&mut self) -> &mut Self::Buffer;
68 fn state(&self) -> &State;
69 fn state_mut(&mut self) -> &mut State;
70 fn checkpoint_save(&self) -> Self::Checkpoint;
71 fn checkpoint_load(&mut self, checkpoint: Self::Checkpoint);
72
73 #[inline(always)]
74 fn with_state<'w>(&'w mut self, state: State) -> WithState<'a, 'w, Self> {
75 let orig_state = std::mem::replace(self.state_mut(), state);
76 WithState {
77 orig_state,
78 inner: self,
79 marker: std::marker::PhantomData,
80 }
81 }
82
83 #[inline(always)]
84 fn ctx(&self) -> Context {
85 self.input().get_ctx()
86 }
87
88 #[inline(always)]
89 fn set_ctx(&mut self, ctx: Context) {
90 self.input_mut().set_ctx(ctx);
91 }
92
93 #[inline]
94 fn do_inside_of_context<T>(&mut self, context: Context, f: impl FnOnce(&mut Self) -> T) -> T {
95 let ctx = self.ctx();
96 let inserted = ctx.complement().intersection(context);
97 if inserted.is_empty() {
98 f(self)
99 } else {
100 self.input_mut().update_ctx(|ctx| ctx.insert(inserted));
101 let result = f(self);
102 self.input_mut().update_ctx(|ctx| ctx.remove(inserted));
103 result
104 }
105 }
106
107 fn do_outside_of_context<T>(&mut self, context: Context, f: impl FnOnce(&mut Self) -> T) -> T {
108 let ctx = self.ctx();
109 let removed = ctx.intersection(context);
110 if !removed.is_empty() {
111 self.input_mut().update_ctx(|ctx| ctx.remove(removed));
112 let result = f(self);
113 self.input_mut().update_ctx(|ctx| ctx.insert(removed));
114 result
115 } else {
116 f(self)
117 }
118 }
119
120 #[inline(always)]
121 fn strict_mode<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
122 self.do_inside_of_context(Context::Strict, f)
123 }
124
125 #[inline(always)]
127 fn in_type<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
128 self.do_inside_of_context(Context::InType, f)
129 }
130
131 #[inline(always)]
132 fn allow_in_expr<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
133 self.do_inside_of_context(Context::IncludeInExpr, f)
134 }
135
136 #[inline(always)]
137 fn disallow_in_expr<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
138 self.do_outside_of_context(Context::IncludeInExpr, f)
139 }
140
141 #[inline(always)]
142 fn syntax(&self) -> SyntaxFlags {
143 self.input().syntax()
144 }
145
146 #[cold]
147 fn emit_err(&mut self, span: Span, error: SyntaxError) {
148 if self.ctx().contains(Context::IgnoreError) || !self.syntax().early_errors() {
149 return;
150 }
151 self.emit_error(crate::error::Error::new(span, error))
152 }
153
154 #[cold]
155 fn emit_error(&mut self, error: crate::error::Error) {
156 if self.ctx().contains(Context::IgnoreError) || !self.syntax().early_errors() {
157 return;
158 }
159 let cur = self.input().cur();
160 if cur.is_error() {
161 let err = self.input_mut().expect_error_token_and_bump();
162 self.input_mut().iter_mut().add_error(err);
163 }
164 self.input_mut().iter_mut().add_error(error);
165 }
166
167 #[cold]
168 fn emit_strict_mode_err(&mut self, span: Span, error: SyntaxError) {
169 if self.ctx().contains(Context::IgnoreError) {
170 return;
171 }
172 let error = crate::error::Error::new(span, error);
173 if self.ctx().contains(Context::Strict) {
174 self.input_mut().iter_mut().add_error(error);
175 } else {
176 self.input_mut().iter_mut().add_module_mode_error(error);
177 }
178 }
179
180 fn verify_expr(&mut self, expr: Box<Expr>) -> PResult<Box<Expr>> {
181 #[cfg(feature = "verify")]
182 {
183 use swc_ecma_visit::Visit;
184 let mut v = self::verifier::Verifier { errors: Vec::new() };
185 v.visit_expr(&expr);
186 for (span, error) in v.errors {
187 self.emit_err(span, error);
188 }
189 }
190 Ok(expr)
191 }
192
193 #[inline(always)]
194 fn cur_pos(&self) -> BytePos {
195 self.input().cur_pos()
196 }
197
198 #[inline(always)]
199 fn last_pos(&self) -> BytePos {
200 self.input().prev_span().hi
201 }
202
203 #[inline]
204 fn is_general_semi(&mut self) -> bool {
205 let cur = self.input().cur();
206 cur.is_semi() || cur.is_rbrace() || cur.is_eof() || self.input().had_line_break_before_cur()
207 }
208
209 fn eat_general_semi(&mut self) -> bool {
210 if cfg!(feature = "debug") {
211 tracing::trace!("eat(';'): cur={:?}", self.input().cur());
212 }
213 let cur = self.input().cur();
214 if cur.is_semi() {
215 self.bump();
216 true
217 } else {
218 cur.is_rbrace() || self.input().had_line_break_before_cur() || cur.is_eof()
219 }
220 }
221
222 #[inline]
223 fn expect_general_semi(&mut self) -> PResult<()> {
224 if !self.eat_general_semi() {
225 let span = self.input().cur_span();
226 let cur = self.input_mut().dump_cur();
227 syntax_error!(self, span, SyntaxError::Expected(";".to_string(), cur))
228 }
229 Ok(())
230 }
231
232 #[inline]
233 fn expect(&mut self, t: &Self::Token) -> PResult<()> {
234 if !self.input_mut().eat(t) {
235 let span = self.input().cur_span();
236 let cur = self.input_mut().dump_cur();
237 syntax_error!(self, span, SyntaxError::Expected(format!("{t:?}"), cur))
238 } else {
239 Ok(())
240 }
241 }
242
243 #[inline(always)]
244 fn expect_without_advance(&mut self, t: &Self::Token) -> PResult<()> {
245 if !self.input_mut().is(t) {
246 let span = self.input().cur_span();
247 let cur = self.input_mut().dump_cur();
248 syntax_error!(self, span, SyntaxError::Expected(format!("{t:?}"), cur))
249 } else {
250 Ok(())
251 }
252 }
253
254 #[inline(always)]
255 fn bump(&mut self) {
256 debug_assert!(
257 !self.input().cur().is_eof(),
258 "parser should not call bump() without knowing current token"
259 );
260 self.input_mut().bump()
261 }
262
263 #[inline]
264 fn span(&self, start: BytePos) -> Span {
265 let end = self.last_pos();
266 debug_assert!(
267 start <= end,
268 "assertion failed: (span.start <= span.end). start = {start:?}, end = {end:?}",
269 );
270 Span::new_with_checked(start, end)
271 }
272
273 #[inline(always)]
274 fn assert_and_bump(&mut self, token: &Self::Token) {
275 debug_assert!(
276 self.input().is(token),
277 "assertion failed: expected {token:?}, got {:?}",
278 self.input().cur()
279 );
280 self.bump();
281 }
282
283 fn check_assign_target(&mut self, expr: &Expr, deny_call: bool) {
284 if !expr.is_valid_simple_assignment_target(self.ctx().contains(Context::Strict)) {
285 self.emit_err(expr.span(), SyntaxError::TS2406);
286 }
287
288 if self.input().syntax().typescript() && self.syntax().early_errors() {
290 let is_eval_or_arguments = match expr {
291 Expr::Ident(i) => i.is_reserved_in_strict_bind(),
292 _ => false,
293 };
294
295 if is_eval_or_arguments {
296 self.emit_strict_mode_err(expr.span(), SyntaxError::TS1100);
297 }
298
299 fn should_deny(e: &Expr, deny_call: bool) -> bool {
300 match e {
301 Expr::Lit(..) => false,
302 Expr::Call(..) => deny_call,
303 Expr::Bin(..) => false,
304 Expr::Paren(ref p) => should_deny(&p.expr, deny_call),
305
306 _ => true,
307 }
308 }
309
310 if !is_eval_or_arguments
314 && !expr.is_valid_simple_assignment_target(self.ctx().contains(Context::Strict))
315 && should_deny(expr, deny_call)
316 {
317 self.emit_err(expr.span(), SyntaxError::TS2406);
318 }
319 }
320 }
321
322 fn parse_tpl_element(&mut self, is_tagged_tpl: bool) -> PResult<TplElement> {
323 let start = self.cur_pos();
324 let cur = self.input().cur();
325 let (raw, cooked) = if cur.is_template() {
326 let (cooked, raw) = self.input_mut().expect_template_token_and_bump();
327 match cooked {
328 Ok(cooked) => (raw, Some(cooked)),
329 Err(err) => {
330 if is_tagged_tpl {
331 (raw, None)
332 } else {
333 return Err(err);
334 }
335 }
336 }
337 } else {
338 unexpected!(self, "template token")
339 };
340 let tail = self.input_mut().is(&Self::Token::BACKQUOTE);
341 Ok(TplElement {
342 span: self.span(start),
343 raw,
344 tail,
345 cooked,
346 })
347 }
348
349 fn parse_prop_name(&mut self) -> PResult<PropName> {
351 trace_cur!(self, parse_prop_name);
352 self.do_inside_of_context(Context::InPropertyName, |p| {
353 let start = p.input().cur_pos();
354 let cur = p.input().cur();
355 let v = if cur.is_str() {
356 PropName::Str(parse_str_lit(p))
357 } else if cur.is_num() {
358 let (value, raw) = p.input_mut().expect_number_token_and_bump();
359 PropName::Num(Number {
360 span: p.span(start),
361 value,
362 raw: Some(raw),
363 })
364 } else if cur.is_bigint() {
365 let (value, raw) = p.input_mut().expect_bigint_token_and_bump();
366 PropName::BigInt(BigInt {
367 span: p.span(start),
368 value,
369 raw: Some(raw),
370 })
371 } else if cur.is_word() {
372 let w = p.input_mut().expect_word_token_and_bump();
373 PropName::Ident(IdentName::new(w, p.span(start)))
374 } else if cur.is_lbracket() {
375 p.bump();
376 let inner_start = p.input().cur_pos();
377 let mut expr = p.allow_in_expr(parse_assignment_expr)?;
378 if p.syntax().typescript() && p.input().is(&Self::Token::COMMA) {
379 let mut exprs = vec![expr];
380 while p.input_mut().eat(&Self::Token::COMMA) {
381 exprs.push(p.allow_in_expr(parse_assignment_expr)?);
383 }
384 p.emit_err(p.span(inner_start), SyntaxError::TS1171);
385 expr = Box::new(
386 SeqExpr {
387 span: p.span(inner_start),
388 exprs,
389 }
390 .into(),
391 );
392 }
393 expect!(p, &Self::Token::RBRACKET);
394 PropName::Computed(ComputedPropName {
395 span: p.span(start),
396 expr,
397 })
398 } else {
399 unexpected!(
400 p,
401 "identifier, string literal, numeric literal or [ for the computed key"
402 )
403 };
404 Ok(v)
405 })
406 }
407
408 fn parse_expr_or_spread(&mut self) -> PResult<ExprOrSpread> {
411 trace_cur!(self, parse_expr_or_spread);
412 let start = self.input().cur_pos();
413 if self.input_mut().eat(&Self::Token::DOTDOTDOT) {
414 let spread_span = self.span(start);
415 let spread = Some(spread_span);
416 self.allow_in_expr(parse_assignment_expr)
417 .map_err(|err| {
418 Error::new(
419 err.span(),
420 SyntaxError::WithLabel {
421 inner: Box::new(err),
422 span: spread_span,
423 note: "An expression should follow '...'",
424 },
425 )
426 })
427 .map(|expr| ExprOrSpread { spread, expr })
428 } else {
429 parse_assignment_expr(self).map(|expr| ExprOrSpread { spread: None, expr })
430 }
431 }
432
433 fn parse_expr(&mut self) -> PResult<Box<Expr>> {
434 trace_cur!(self, parse_expr);
435 debug_tracing!(self, "parse_expr");
436 let expr = parse_assignment_expr(self)?;
437 let start = expr.span_lo();
438
439 if self.input_mut().is(&Self::Token::COMMA) {
440 let mut exprs = vec![expr];
441
442 while self.input_mut().eat(&Self::Token::COMMA) {
443 exprs.push(parse_assignment_expr(self)?);
444 }
445
446 return Ok(SeqExpr {
447 span: self.span(start),
448 exprs,
449 }
450 .into());
451 }
452
453 Ok(expr)
454 }
455
456 fn mark_found_module_item(&mut self);
457
458 #[inline]
459 fn is_ident_ref(&mut self) -> bool {
460 let cur = self.input().cur();
461 cur.is_word() && !cur.is_reserved(self.ctx())
462 }
463
464 #[inline]
465 fn peek_is_ident_ref(&mut self) -> bool {
466 let ctx = self.ctx();
467 peek!(self).is_some_and(|peek| peek.is_word() && !peek.is_reserved(ctx))
468 }
469
470 #[inline(always)]
471 fn eat_ident_ref(&mut self) -> bool {
472 if self.is_ident_ref() {
473 self.bump();
474 true
475 } else {
476 false
477 }
478 }
479
480 fn ts_in_no_context<T>(&mut self, op: impl FnOnce(&mut Self) -> PResult<T>) -> PResult<T>;
481
482 fn parse_jsx_element(
483 &mut self,
484 in_expr_context: bool,
485 ) -> PResult<Either<JSXFragment, JSXElement>>;
486 fn parse_primary_expr(&mut self) -> PResult<Box<Expr>>;
487 fn parse_unary_expr(&mut self) -> PResult<Box<Expr>>;
488 fn parse_tagged_tpl(
489 &mut self,
490 tag: Box<Expr>,
491 type_params: Option<Box<TsTypeParamInstantiation>>,
492 ) -> PResult<TaggedTpl>;
493 fn parse_tagged_tpl_ty(&mut self) -> PResult<TsLitType>;
494 fn parse_lhs_expr(&mut self) -> PResult<Box<Expr>>;
495}
496
497pub fn parse_shebang<'a>(p: &mut impl Parser<'a>) -> PResult<Option<Atom>> {
498 let cur = p.input().cur();
499 Ok(if cur.is_shebang() {
500 let ret = p.input_mut().expect_shebang_token_and_bump();
501 Some(ret)
502 } else {
503 None
504 })
505}
506
507#[cold]
508#[inline(never)]
509pub fn eof_error<'a, P: Parser<'a>>(p: &mut P) -> crate::error::Error {
510 debug_assert!(
511 p.input().cur().is_eof(),
512 "Parser should not call throw_eof_error() without knowing current token"
513 );
514 let pos = p.input().end_pos();
515 let last = Span { lo: pos, hi: pos };
516 crate::error::Error::new(last, crate::error::SyntaxError::Eof)
517}