swc_ecma_lexer/parser/
mod.rs1#![allow(clippy::let_unit_value)]
2#![deny(non_snake_case)]
3
4use swc_ecma_ast::*;
5
6use crate::{
7 common::{
8 input::Tokens,
9 parser::{
10 buffer::Buffer as BufferTrait,
11 expr::{parse_lhs_expr, parse_primary_expr, parse_tagged_tpl, parse_unary_expr},
12 jsx::parse_jsx_element,
13 module_item::parse_module_item_block_body,
14 parse_shebang,
15 stmt::parse_stmt_block_body,
16 typescript::ts_in_no_context,
17 Parser as ParserTrait,
18 },
19 },
20 error::Error,
21 input::Buffer,
22 token::{Token, TokenAndSpan},
23 Context, *,
24};
25
26#[macro_use]
27mod macros;
28#[cfg(feature = "typescript")]
29mod typescript;
30
31#[derive(Clone)]
33pub struct Parser<I: Tokens<TokenAndSpan>> {
34 state: crate::common::parser::state::State,
35 input: Buffer<I>,
36 found_module_item: bool,
37}
38
39impl<'a, I: Tokens<TokenAndSpan>> crate::common::parser::Parser<'a> for Parser<I> {
40 type Buffer = Buffer<I>;
41 type Checkpoint = Self;
42 type I = I;
43 type Next = TokenAndSpan;
44 type Token = Token;
45 type TokenAndSpan = TokenAndSpan;
46
47 #[inline(always)]
48 fn input(&self) -> &Self::Buffer {
49 &self.input
50 }
51
52 #[inline(always)]
53 fn input_mut(&mut self) -> &mut Self::Buffer {
54 &mut self.input
55 }
56
57 #[inline(always)]
58 fn state(&self) -> &common::parser::state::State {
59 &self.state
60 }
61
62 #[inline(always)]
63 fn state_mut(&mut self) -> &mut common::parser::state::State {
64 &mut self.state
65 }
66
67 fn checkpoint_save(&self) -> Self::Checkpoint {
68 self.clone()
69 }
70
71 fn checkpoint_load(&mut self, checkpoint: Self::Checkpoint) {
72 *self = checkpoint;
73 }
74
75 #[inline(always)]
76 fn mark_found_module_item(&mut self) {
77 self.found_module_item = true;
78 }
79
80 #[inline(always)]
81 fn parse_unary_expr(&mut self) -> PResult<Box<Expr>> {
82 parse_unary_expr(self)
83 }
84
85 #[inline(always)]
86 fn parse_jsx_element(
87 &mut self,
88 _in_expr_context: bool,
89 ) -> PResult<either::Either<JSXFragment, JSXElement>> {
90 parse_jsx_element(self)
91 }
92
93 #[inline(always)]
94 fn parse_primary_expr(&mut self) -> PResult<Box<Expr>> {
95 parse_primary_expr(self)
96 }
97
98 #[inline(always)]
99 fn ts_in_no_context<T>(&mut self, op: impl FnOnce(&mut Self) -> PResult<T>) -> PResult<T> {
100 ts_in_no_context(self, op)
101 }
102
103 fn parse_tagged_tpl(
104 &mut self,
105 tag: Box<Expr>,
106 type_params: Option<Box<TsTypeParamInstantiation>>,
107 ) -> PResult<TaggedTpl> {
108 parse_tagged_tpl(self, tag, type_params)
109 }
110
111 fn parse_tagged_tpl_ty(&mut self) -> PResult<TsLitType> {
112 unreachable!("use `common::parser::expr::parse_ts_tpl_lit_type` directly");
113 }
114
115 fn parse_lhs_expr(&mut self) -> PResult<Box<Expr>> {
116 parse_lhs_expr::<Self, true>(self)
117 }
118}
119
120impl<I: Tokens<TokenAndSpan>> Parser<I> {
121 pub fn new_from(mut input: I) -> Self {
122 let in_declare = input.syntax().dts();
123 let mut ctx = input.ctx() | Context::TopLevel;
124 ctx.set(Context::InDeclare, in_declare);
125 input.set_ctx(ctx);
126
127 let mut p = Parser {
128 state: Default::default(),
129 input: Buffer::new(input),
130 found_module_item: false,
131 };
132 p.input.bump(); p
134 }
135
136 pub fn take_errors(&mut self) -> Vec<Error> {
137 self.input.iter.take_errors()
138 }
139
140 pub fn take_script_module_errors(&mut self) -> Vec<Error> {
141 self.input.iter.take_script_module_errors()
142 }
143
144 pub fn parse_script(&mut self) -> PResult<Script> {
145 trace_cur!(self, parse_script);
146
147 let ctx = (self.ctx() & !Context::Module) | Context::TopLevel;
148 self.set_ctx(ctx);
149
150 let start = self.cur_pos();
151
152 let shebang = parse_shebang(self)?;
153
154 let ret = parse_stmt_block_body(self, true, None).map(|body| Script {
155 span: self.span(start),
156 body,
157 shebang,
158 })?;
159
160 Ok(ret)
161 }
162
163 pub fn parse_commonjs(&mut self) -> PResult<Script> {
164 trace_cur!(self, parse_commonjs);
165
166 let ctx = (self.ctx() & !Context::Module)
168 | Context::InFunction
169 | Context::InsideNonArrowFunctionScope;
170 self.set_ctx(ctx);
171
172 let start = self.cur_pos();
173 let shebang = parse_shebang(self)?;
174
175 let ret = parse_stmt_block_body(self, true, None).map(|body| Script {
176 span: self.span(start),
177 body,
178 shebang,
179 })?;
180
181 debug_assert!(self.input().cur() == &Token::Eof);
182 self.input_mut().bump();
183
184 Ok(ret)
185 }
186
187 #[cfg(test)]
188 pub fn parse_typescript_module(&mut self) -> PResult<Module> {
189 trace_cur!(self, parse_typescript_module);
190
191 debug_assert!(self.syntax().typescript());
192
193 let ctx = (self.ctx() | Context::Module | Context::TopLevel) & !Context::Strict; self.set_ctx(ctx);
196
197 let start = self.cur_pos();
198 let shebang = parse_shebang(self)?;
199
200 let ret = parse_module_item_block_body(self, true, None).map(|body| Module {
201 span: self.span(start),
202 body,
203 shebang,
204 })?;
205
206 debug_assert!(self.input().cur() == &Token::Eof);
207 self.input_mut().bump();
208
209 Ok(ret)
210 }
211
212 pub fn parse_program(&mut self) -> PResult<Program> {
218 let start = self.cur_pos();
219 let shebang = parse_shebang(self)?;
220
221 let body: Vec<ModuleItem> = self
222 .do_inside_of_context(Context::CanBeModule.union(Context::TopLevel), |p| {
223 parse_module_item_block_body(p, true, None)
224 })?;
225 let has_module_item = self.found_module_item
226 || body
227 .iter()
228 .any(|item| matches!(item, ModuleItem::ModuleDecl(..)));
229 if has_module_item && !self.ctx().contains(Context::Module) {
230 let ctx = self.ctx()
231 | Context::Module
232 | Context::CanBeModule
233 | Context::TopLevel
234 | Context::Strict;
235 self.input.set_ctx(ctx);
237 }
238
239 let ret = if has_module_item {
240 Program::Module(Module {
241 span: self.span(start),
242 body,
243 shebang,
244 })
245 } else {
246 let body = body
247 .into_iter()
248 .map(|item| match item {
249 ModuleItem::ModuleDecl(_) => unreachable!(
250 "Module is handled
251 above"
252 ),
253 ModuleItem::Stmt(stmt) => stmt,
254 })
255 .collect();
256 Program::Script(Script {
257 span: self.span(start),
258 body,
259 shebang,
260 })
261 };
262
263 debug_assert!(self.input().cur() == &Token::Eof);
264 self.input_mut().bump();
265
266 Ok(ret)
267 }
268
269 pub fn parse_module(&mut self) -> PResult<Module> {
270 let ctx = self.ctx()
271 | Context::Module
272 | Context::CanBeModule
273 | Context::TopLevel
274 | Context::Strict;
275 self.set_ctx(ctx);
277
278 let start = self.cur_pos();
279 let shebang = parse_shebang(self)?;
280
281 let ret = parse_module_item_block_body(self, true, None).map(|body| Module {
282 span: self.span(start),
283 body,
284 shebang,
285 })?;
286
287 debug_assert!(self.input().cur() == &Token::Eof);
288 self.input_mut().bump();
289
290 Ok(ret)
291 }
292}