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#[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(); 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 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 let ctx = (self.ctx() | Context::Module | Context::TopLevel) & !Context::Strict;
241 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 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 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 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}