swc_ecma_lexer/common/parser/
mod.rs

1use 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    /// Original context is restored when returned guard is dropped.
126    #[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        // We follow behavior of tsc
289        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            // It is an early Reference Error if LeftHandSideExpression is neither
311            // an ObjectLiteral nor an ArrayLiteral and
312            // IsValidSimpleAssignmentTarget of LeftHandSideExpression is false.
313            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    /// spec: 'PropertyName'
350    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                        //
382                        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    /// AssignmentExpression[+In, ?Yield, ?Await]
409    /// ...AssignmentExpression[+In, ?Yield, ?Await]
410    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}