swc_ecma_parser/parser/
mod.rs

1#![allow(clippy::let_unit_value)]
2#![deny(non_snake_case)]
3
4use swc_common::{comments::Comments, input::StringInput, Span};
5use swc_ecma_ast::*;
6use swc_ecma_lexer::common::parser::{
7    buffer::Buffer as BufferTrait, expr::parse_lhs_expr, module_item::parse_module_item_block_body,
8    parse_shebang, stmt::parse_stmt_block_body, Parser as ParserTrait,
9};
10
11use crate::{
12    lexer::{Token, TokenAndSpan},
13    parser::input::Tokens,
14    Context, Syntax,
15};
16#[cfg(test)]
17extern crate test;
18#[cfg(test)]
19use test::Bencher;
20
21use crate::error::Error;
22
23#[macro_use]
24mod macros;
25mod class_and_fn;
26mod expr;
27pub mod input;
28mod jsx;
29mod pat;
30mod stmt;
31#[cfg(test)]
32mod tests;
33mod tpl;
34#[cfg(feature = "typescript")]
35mod typescript;
36
37pub use swc_ecma_lexer::common::parser::PResult;
38
39pub struct ParserCheckpoint<I: Tokens> {
40    lexer: I::Checkpoint,
41    buffer_prev_span: Span,
42    buffer_cur: TokenAndSpan,
43    buffer_next: Option<crate::lexer::NextTokenAndSpan>,
44}
45
46/// EcmaScript parser.
47#[derive(Clone)]
48pub struct Parser<I: self::input::Tokens> {
49    state: swc_ecma_lexer::common::parser::state::State,
50    input: self::input::Buffer<I>,
51    found_module_item: bool,
52}
53
54impl<'a, I: Tokens> swc_ecma_lexer::common::parser::Parser<'a> for Parser<I> {
55    type Buffer = self::input::Buffer<I>;
56    type Checkpoint = ParserCheckpoint<I>;
57    type I = I;
58    type Next = crate::lexer::NextTokenAndSpan;
59    type Token = Token;
60    type TokenAndSpan = TokenAndSpan;
61
62    #[inline(always)]
63    fn input(&self) -> &Self::Buffer {
64        &self.input
65    }
66
67    #[inline(always)]
68    fn input_mut(&mut self) -> &mut Self::Buffer {
69        &mut self.input
70    }
71
72    #[inline(always)]
73    fn state(&self) -> &swc_ecma_lexer::common::parser::state::State {
74        &self.state
75    }
76
77    #[inline(always)]
78    fn state_mut(&mut self) -> &mut swc_ecma_lexer::common::parser::state::State {
79        &mut self.state
80    }
81
82    fn checkpoint_save(&self) -> Self::Checkpoint {
83        Self::Checkpoint {
84            lexer: self.input.iter.checkpoint_save(),
85            buffer_cur: self.input.cur,
86            buffer_next: self.input.next.clone(),
87            buffer_prev_span: self.input.prev_span,
88        }
89    }
90
91    fn checkpoint_load(&mut self, checkpoint: Self::Checkpoint) {
92        self.input.iter.checkpoint_load(checkpoint.lexer);
93        self.input.cur = checkpoint.buffer_cur;
94        self.input.next = checkpoint.buffer_next;
95        self.input.prev_span = checkpoint.buffer_prev_span;
96    }
97
98    #[inline(always)]
99    fn mark_found_module_item(&mut self) {
100        self.found_module_item = true;
101    }
102
103    #[inline(always)]
104    fn parse_unary_expr(&mut self) -> PResult<Box<Expr>> {
105        self.parse_unary_expr()
106    }
107
108    #[inline(always)]
109    fn parse_jsx_element(
110        &mut self,
111        in_expr_context: bool,
112    ) -> PResult<either::Either<JSXFragment, JSXElement>> {
113        self.parse_jsx_element(in_expr_context)
114    }
115
116    #[inline(always)]
117    fn parse_primary_expr(&mut self) -> PResult<Box<Expr>> {
118        self.parse_primary_expr()
119    }
120
121    #[inline(always)]
122    fn ts_in_no_context<T>(&mut self, op: impl FnOnce(&mut Self) -> PResult<T>) -> PResult<T> {
123        debug_assert!(self.input().syntax().typescript());
124        trace_cur!(self, ts_in_no_context__before);
125        let res = op(self);
126        trace_cur!(self, ts_in_no_context__after);
127        res
128    }
129
130    #[inline(always)]
131    fn parse_tagged_tpl(
132        &mut self,
133        tag: Box<Expr>,
134        type_params: Option<Box<TsTypeParamInstantiation>>,
135    ) -> PResult<TaggedTpl> {
136        self.parse_tagged_tpl(tag, type_params)
137    }
138
139    #[inline(always)]
140    fn parse_tagged_tpl_ty(&mut self) -> PResult<TsLitType> {
141        let start = self.cur_pos();
142        self.parse_tagged_tpl_ty().map(|tpl_ty| {
143            let lit = TsLit::Tpl(tpl_ty);
144            TsLitType {
145                span: self.span(start),
146                lit,
147            }
148        })
149    }
150
151    #[inline(always)]
152    fn parse_lhs_expr(&mut self) -> PResult<Box<Expr>> {
153        parse_lhs_expr::<Self, false>(self)
154    }
155}
156
157impl<'a> Parser<crate::lexer::Lexer<'a>> {
158    pub fn new(syntax: Syntax, input: StringInput<'a>, comments: Option<&'a dyn Comments>) -> Self {
159        let lexer = crate::lexer::Lexer::new(syntax, Default::default(), input, comments);
160        Self::new_from(lexer)
161    }
162}
163
164impl<I: Tokens> Parser<I> {
165    pub fn new_from(mut input: I) -> Self {
166        let in_declare = input.syntax().dts();
167        let mut ctx = input.ctx() | Context::TopLevel;
168        ctx.set(Context::InDeclare, in_declare);
169        input.set_ctx(ctx);
170
171        let mut p = Parser {
172            state: Default::default(),
173            input: crate::parser::input::Buffer::new(input),
174            found_module_item: false,
175        };
176        p.input.bump(); // consume EOF
177        p
178    }
179
180    pub fn take_errors(&mut self) -> Vec<Error> {
181        self.input.iter.take_errors()
182    }
183
184    pub fn take_script_module_errors(&mut self) -> Vec<Error> {
185        self.input.iter.take_script_module_errors()
186    }
187
188    pub fn parse_script(&mut self) -> PResult<Script> {
189        trace_cur!(self, parse_script);
190
191        let ctx = (self.ctx() & !Context::Module) | Context::TopLevel;
192        self.set_ctx(ctx);
193
194        let start = self.cur_pos();
195
196        let shebang = parse_shebang(self)?;
197
198        let ret = parse_stmt_block_body(self, true, None).map(|body| Script {
199            span: self.span(start),
200            body,
201            shebang,
202        })?;
203
204        debug_assert!(self.input().cur() == &Token::Eof);
205        self.input_mut().bump();
206
207        Ok(ret)
208    }
209
210    pub fn parse_commonjs(&mut self) -> PResult<Script> {
211        trace_cur!(self, parse_commonjs);
212
213        // CommonJS module is acctually in a function scope
214        let ctx = (self.ctx() & !Context::Module)
215            | Context::InFunction
216            | Context::InsideNonArrowFunctionScope;
217        self.set_ctx(ctx);
218
219        let start = self.cur_pos();
220        let shebang = parse_shebang(self)?;
221
222        let ret = parse_stmt_block_body(self, true, None).map(|body| Script {
223            span: self.span(start),
224            body,
225            shebang,
226        })?;
227
228        debug_assert!(self.input().cur() == &Token::Eof);
229        self.input_mut().bump();
230
231        Ok(ret)
232    }
233
234    pub fn parse_typescript_module(&mut self) -> PResult<Module> {
235        trace_cur!(self, parse_typescript_module);
236
237        debug_assert!(self.syntax().typescript());
238
239        //TODO: parse() -> PResult<Program>
240        let ctx = (self.ctx() | Context::Module | Context::TopLevel) & !Context::Strict;
241        // Module code is always in strict mode
242        self.set_ctx(ctx);
243
244        let start = self.cur_pos();
245        let shebang = parse_shebang(self)?;
246
247        let ret = parse_module_item_block_body(self, true, None).map(|body| Module {
248            span: self.span(start),
249            body,
250            shebang,
251        })?;
252
253        debug_assert!(self.input().cur() == &Token::Eof);
254        self.input_mut().bump();
255
256        Ok(ret)
257    }
258
259    /// Returns [Module] if it's a module and returns [Script] if it's not a
260    /// module.
261    ///
262    /// Note: This is not perfect yet. It means, some strict mode violations may
263    /// not be reported even if the method returns [Module].
264    pub fn parse_program(&mut self) -> PResult<Program> {
265        let start = self.cur_pos();
266        let shebang = parse_shebang(self)?;
267
268        let body: Vec<ModuleItem> = self
269            .do_inside_of_context(Context::CanBeModule.union(Context::TopLevel), |p| {
270                parse_module_item_block_body(p, true, None)
271            })?;
272        let has_module_item = self.found_module_item
273            || body
274                .iter()
275                .any(|item| matches!(item, ModuleItem::ModuleDecl(..)));
276        if has_module_item && !self.ctx().contains(Context::Module) {
277            let ctx = self.ctx()
278                | Context::Module
279                | Context::CanBeModule
280                | Context::TopLevel
281                | Context::Strict;
282            // Emit buffered strict mode / module code violations
283            self.input.set_ctx(ctx);
284        }
285
286        let ret = if has_module_item {
287            Program::Module(Module {
288                span: self.span(start),
289                body,
290                shebang,
291            })
292        } else {
293            let body = body
294                .into_iter()
295                .map(|item| match item {
296                    ModuleItem::ModuleDecl(_) => unreachable!("Module is handled above"),
297                    ModuleItem::Stmt(stmt) => stmt,
298                })
299                .collect();
300            Program::Script(Script {
301                span: self.span(start),
302                body,
303                shebang,
304            })
305        };
306
307        debug_assert!(self.input().cur() == &Token::Eof);
308        self.input_mut().bump();
309
310        Ok(ret)
311    }
312
313    pub fn parse_module(&mut self) -> PResult<Module> {
314        let ctx = self.ctx()
315            | Context::Module
316            | Context::CanBeModule
317            | Context::TopLevel
318            | Context::Strict;
319        // Module code is always in strict mode
320        self.set_ctx(ctx);
321
322        let start = self.cur_pos();
323        let shebang = parse_shebang(self)?;
324
325        let ret = parse_module_item_block_body(self, true, None).map(|body| Module {
326            span: self.span(start),
327            body,
328            shebang,
329        })?;
330
331        debug_assert!(self.input().cur() == &Token::Eof);
332        self.input_mut().bump();
333
334        Ok(ret)
335    }
336}
337
338#[cfg(test)]
339pub fn test_parser<F, Ret>(s: &'static str, syntax: Syntax, f: F) -> Ret
340where
341    F: FnOnce(&mut Parser<crate::lexer::Lexer>) -> Result<Ret, Error>,
342{
343    crate::with_test_sess(s, |handler, input| {
344        let lexer = crate::lexer::Lexer::new(syntax, EsVersion::Es2019, input, None);
345        let mut p = Parser::new_from(lexer);
346        let ret = f(&mut p);
347        let mut error = false;
348
349        for err in p.take_errors() {
350            error = true;
351            err.into_diagnostic(handler).emit();
352        }
353
354        let res = ret.map_err(|err| err.into_diagnostic(handler).emit())?;
355
356        if error {
357            return Err(());
358        }
359
360        Ok(res)
361    })
362    .unwrap_or_else(|output| panic!("test_parser(): failed to parse \n{s}\n{output}"))
363}
364
365#[cfg(test)]
366pub fn test_parser_comment<F, Ret>(c: &dyn Comments, s: &'static str, syntax: Syntax, f: F) -> Ret
367where
368    F: FnOnce(&mut Parser<crate::lexer::Lexer>) -> Result<Ret, Error>,
369{
370    crate::with_test_sess(s, |handler, input| {
371        let lexer = crate::lexer::Lexer::new(syntax, EsVersion::Es2019, input, Some(&c));
372        let mut p = Parser::new_from(lexer);
373        let ret = f(&mut p);
374
375        for err in p.take_errors() {
376            err.into_diagnostic(handler).emit();
377        }
378
379        ret.map_err(|err| err.into_diagnostic(handler).emit())
380    })
381    .unwrap_or_else(|output| panic!("test_parser(): failed to parse \n{s}\n{output}"))
382}
383
384#[cfg(test)]
385pub fn bench_parser<F>(b: &mut Bencher, s: &'static str, syntax: Syntax, mut f: F)
386where
387    F: for<'a> FnMut(&'a mut Parser<crate::lexer::Lexer<'a>>) -> PResult<()>,
388{
389    b.bytes = s.len() as u64;
390
391    let _ = crate::with_test_sess(s, |handler, input| {
392        b.iter(|| {
393            let lexer = crate::lexer::Lexer::new(syntax, Default::default(), input.clone(), None);
394            let _ =
395                f(&mut Parser::new_from(lexer)).map_err(|err| err.into_diagnostic(handler).emit());
396        });
397
398        Ok(())
399    });
400}