1use super::decl::VarDeclParseMode;
2use super::expr::Asi;
3use super::pattern::is_valid_pattern_identifier;
4use super::ParseCtx;
5use super::Parser;
6use crate::ast::ExportName;
7use crate::ast::ExportNames;
8use crate::ast::ForInit;
9use crate::ast::Node;
10use crate::ast::Syntax;
11use crate::error::SyntaxErrorType;
12use crate::error::SyntaxResult;
13use crate::loc::Loc;
14use crate::token::TokenType;
15
16struct BreakOrContinue {
17 loc: Loc,
18 label: Option<String>,
19}
20
21impl<'a> Parser<'a> {
22 fn parse_import_or_export_name(&mut self, ctx: ParseCtx) -> SyntaxResult<ExportName> {
24 let (target, alias) = match self.consume_if(TokenType::KeywordDefault)?.match_loc() {
25 Some(target) => {
26 self.require(TokenType::KeywordAs)?;
27 let alias = self.require(TokenType::Identifier)?.loc;
28 (target, alias)
29 }
30 None => {
31 let target = self.require(TokenType::Identifier)?.loc;
32 let alias = if self.consume_if(TokenType::KeywordAs)?.is_match() {
33 self.require(TokenType::Identifier)?.loc
34 } else {
35 target
36 };
37 (target, alias)
38 }
39 };
40 let alias_node = Node::new(alias, Syntax::IdentifierPattern {
41 name: self.string(alias),
42 });
43 Ok(ExportName {
44 target: self.string(target),
45 alias: alias_node,
46 })
47 }
48
49 pub fn parse_stmts(&mut self, ctx: ParseCtx, end: TokenType) -> SyntaxResult<Vec<Node>> {
50 let mut body = Vec::new();
51 while self.peek()?.typ != end {
52 body.push(self.parse_stmt(ctx)?);
53 }
54 Ok(body)
55 }
56
57 pub fn parse_stmt(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
58 match self.peek()?.typ {
59 TokenType::BraceOpen => self.parse_stmt_block(ctx),
60 TokenType::KeywordBreak => self.parse_stmt_break(ctx),
61 TokenType::KeywordClass => self.parse_decl_class(ctx, false, false),
62 TokenType::KeywordConst | TokenType::KeywordLet | TokenType::KeywordVar => {
63 self.parse_decl_var(ctx, VarDeclParseMode::Asi, false)
64 }
65 TokenType::KeywordContinue => self.parse_stmt_continue(ctx),
66 TokenType::KeywordDebugger => self.parse_stmt_debugger(ctx),
67 TokenType::KeywordDo => self.parse_stmt_do_while(ctx),
68 TokenType::KeywordExport => self.parse_stmt_export(ctx),
69 TokenType::KeywordFor => self.parse_stmt_for(ctx),
70 TokenType::KeywordAsync | TokenType::KeywordFunction => {
71 self.parse_decl_function(ctx, false, false)
72 }
73 TokenType::KeywordIf => self.parse_stmt_if(ctx),
74 TokenType::KeywordImport => self.parse_stmt_import_or_expr_import(ctx),
75 TokenType::KeywordReturn => self.parse_stmt_return(ctx),
76 TokenType::KeywordSwitch => self.parse_stmt_switch(ctx),
77 TokenType::KeywordThrow => self.parse_stmt_throw(ctx),
78 TokenType::KeywordTry => self.parse_stmt_try(ctx),
79 TokenType::KeywordWhile => self.parse_stmt_while(ctx),
80 TokenType::Semicolon => self.parse_stmt_empty(ctx),
81 t if is_valid_pattern_identifier(t, ctx.rules) => {
82 let checkpoint = self.checkpoint();
83 let label_name = self.next()?.loc;
84 if self.consume_if(TokenType::Colon)?.is_match() {
85 let statement = self.parse_stmt(ctx)?;
86 Ok(Node::new(
87 self.since_checkpoint(checkpoint),
88 Syntax::LabelStmt {
89 name: self.string(label_name),
90 statement,
91 },
92 ))
93 } else {
94 self.restore_checkpoint(checkpoint);
95 self.parse_stmt_expression(ctx)
96 }
97 }
98 _ => self.parse_stmt_expression(ctx),
99 }
100 }
101
102 pub fn parse_stmt_empty(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
103 let loc = self.require(TokenType::Semicolon)?.loc;
104 Ok(Node::new(loc, Syntax::EmptyStmt {}))
105 }
106
107 pub fn parse_stmt_block(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
108 let start = self.require(TokenType::BraceOpen)?;
109 let body = self.parse_stmts(ctx, TokenType::BraceClose)?;
110 let end = self.require(TokenType::BraceClose)?;
111 Ok(Node::new(start.loc + end.loc, Syntax::BlockStmt { body }))
112 }
113
114 fn parse_stmt_break_or_continue(
115 &mut self,
116 ctx: ParseCtx,
117 t: TokenType,
118 ) -> SyntaxResult<BreakOrContinue> {
119 let mut loc = self.require(t)?.loc;
120 let next = self.peek()?;
121 let label =
122 if is_valid_pattern_identifier(next.typ, ctx.rules) && !next.preceded_by_line_terminator {
123 self.consume_peeked();
125 loc.extend(next.loc);
126 Some(self.string(next.loc))
127 } else if next.typ == TokenType::Semicolon {
128 self.consume_peeked();
129 None
130 } else if next.preceded_by_line_terminator || next.typ == TokenType::BraceClose {
131 None
133 } else {
134 return Err(next.error(SyntaxErrorType::ExpectedSyntax("continue label")));
135 };
136 Ok(BreakOrContinue { loc, label })
137 }
138
139 pub fn parse_stmt_break(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
140 let stmt = self.parse_stmt_break_or_continue(ctx, TokenType::KeywordBreak)?;
141 Ok(Node::new(stmt.loc, Syntax::BreakStmt { label: stmt.label }))
142 }
143
144 pub fn parse_stmt_continue(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
145 let stmt = self.parse_stmt_break_or_continue(ctx, TokenType::KeywordContinue)?;
146 Ok(Node::new(stmt.loc, Syntax::ContinueStmt {
147 label: stmt.label,
148 }))
149 }
150
151 pub fn parse_stmt_debugger(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
152 let loc = self.require(TokenType::KeywordDebugger)?.loc;
153 Ok(Node::new(loc, Syntax::DebuggerStmt {}))
154 }
155
156 pub fn parse_stmt_export(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
159 let start = self.require(TokenType::KeywordExport)?;
161 let cp = self.checkpoint();
162 let t = self.next()?;
163 Ok(match t.typ {
164 TokenType::BraceOpen => {
165 let mut names = Vec::<ExportName>::new();
166 loop {
167 if self.consume_if(TokenType::BraceClose)?.is_match() {
168 break;
169 };
170 let name = self.parse_import_or_export_name(ctx)?;
171 names.push(name);
172 if !self.consume_if(TokenType::Comma)?.is_match() {
173 self.require(TokenType::BraceClose)?;
174 break;
175 };
176 }
177 let from = self.consume_if(TokenType::KeywordFrom)?.and_then(|| {
178 let from = self.parse_and_normalise_literal_string(ctx)?;
179 Ok(from)
180 })?;
181 Node::new(start.loc, Syntax::ExportListStmt {
183 names: ExportNames::Specific(names),
184 from,
185 })
186 }
187 TokenType::Asterisk => {
188 let alias = if self.consume_if(TokenType::KeywordAs)?.is_match() {
189 let alias = self.require(TokenType::Identifier)?.loc;
190 let alias_node = Node::new(alias, Syntax::IdentifierPattern {
191 name: self.string(alias),
192 });
193 Some(alias_node)
194 } else {
196 None
197 };
198 self.require(TokenType::KeywordFrom)?;
199 let from = self.parse_and_normalise_literal_string(ctx)?;
200 Node::new(start.loc, Syntax::ExportListStmt {
202 names: ExportNames::All(alias),
203 from: Some(from),
204 })
205 }
206 TokenType::KeywordDefault => match self.peek()?.typ {
207 TokenType::KeywordAsync | TokenType::KeywordFunction => {
209 self.parse_decl_function(ctx, true, true)?
210 }
211 TokenType::KeywordClass => self.parse_decl_class(ctx, true, true)?,
212 _ => {
213 let expression = self.parse_expr(ctx, TokenType::Semicolon)?;
214 Node::new(start.loc + expression.loc, Syntax::ExportDefaultExprStmt {
215 expression,
216 })
217 }
218 },
219 TokenType::KeywordVar | TokenType::KeywordLet | TokenType::KeywordConst => {
220 self.restore_checkpoint(cp);
222 self.parse_decl_var(ctx, VarDeclParseMode::Asi, true)?
223 }
224 TokenType::KeywordFunction => {
225 self.restore_checkpoint(cp);
227 self.parse_decl_function(ctx, true, false)?
228 }
229 TokenType::KeywordClass => {
230 self.restore_checkpoint(cp);
232 self.parse_decl_class(ctx, true, false)?
233 }
234 _ => return Err(t.error(SyntaxErrorType::ExpectedSyntax("exportable"))),
235 })
236 }
237
238 pub fn parse_stmt_expression(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
240 let mut asi = Asi::can();
241 let expression = self.parse_expr_with_asi(ctx, TokenType::Semicolon, &mut asi)?;
242 if !asi.did_end_with_asi {
243 self.require(TokenType::Semicolon)?;
244 };
245 Ok(Node::new(expression.loc, Syntax::ExpressionStmt {
246 expression,
247 }))
248 }
249
250 fn parse_stmt_for_body(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
251 if self.peek()?.typ == TokenType::BraceOpen {
252 let start = self.require(TokenType::BraceOpen)?;
253 let body = self.parse_stmts(ctx, TokenType::BraceClose)?;
254 let end = self.require(TokenType::BraceClose)?;
255 Ok(Node::new(start.loc + end.loc, Syntax::ForBody { body }))
256 } else {
257 self.parse_stmt(ctx)
258 }
259 }
260
261 pub fn parse_stmt_for(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
262 let start = self.require(TokenType::KeywordFor)?;
263 let await_ = self.consume_if(TokenType::KeywordAwait)?;
264 self.require(TokenType::ParenthesisOpen)?;
265 enum LhsRaw {
266 Declaration(Node),
267 Expression(Node),
268 Pattern(Node),
269 Empty,
270 }
271 let lhs_raw = match self.peek()?.typ {
272 TokenType::KeywordVar | TokenType::KeywordLet | TokenType::KeywordConst => {
273 LhsRaw::Declaration(self.parse_decl_var(ctx, VarDeclParseMode::Leftmost, false)?)
274 }
275 TokenType::Semicolon => LhsRaw::Empty,
276 _ => {
277 let checkpoint = self.checkpoint();
279 match if let Ok(node) = self.parse_pattern(ctx) {
280 match self.peek()?.typ {
281 TokenType::KeywordIn | TokenType::KeywordOf => Some(LhsRaw::Pattern(node)),
282 _ => {
283 None
285 }
286 }
287 } else {
288 None
289 } {
290 Some(p) => p,
291 None => {
292 self.restore_checkpoint(checkpoint);
293 LhsRaw::Expression(self.parse_expr(ctx, TokenType::Semicolon)?)
294 }
295 }
296 }
297 };
298 let n = match self.peek()?.typ {
299 TokenType::KeywordOf | TokenType::KeywordIn => {
300 let of = match self.next()?.typ {
302 TokenType::KeywordOf => true,
303 TokenType::KeywordIn => false,
304 _ => unreachable!(),
305 };
306 if !of && await_.is_match() {
307 return Err(await_.error(SyntaxErrorType::RequiredTokenNotFound(
309 TokenType::ParenthesisOpen,
310 )));
311 };
312 let (decl_mode, pat) = match lhs_raw {
313 LhsRaw::Empty => return Err(start.error(SyntaxErrorType::ForLoopHeaderHasNoLhs)),
314 LhsRaw::Declaration(node) => match *node.stx {
315 Syntax::VarDecl {
316 mut declarators,
317 mode,
318 export,
319 } => {
320 if export {
321 return Err(start.error(SyntaxErrorType::ForLoopHeaderHasInvalidLhs));
322 };
323 if declarators.len() != 1 {
324 return Err(start.error(SyntaxErrorType::ForLoopHeaderHasMultipleDeclarators));
325 }
326 let decl = declarators.pop().unwrap();
327 if decl.initializer.is_some() {
328 return Err(start.error(SyntaxErrorType::ForLoopHeaderHasInvalidLhs));
329 };
330 (Some(mode), decl.pattern)
331 }
332 _ => unreachable!(),
333 },
334 LhsRaw::Pattern(pat) => (None, pat),
335 LhsRaw::Expression(_) => {
336 return Err(start.error(SyntaxErrorType::ForLoopHeaderHasInvalidLhs))
337 }
338 };
339 let rhs = self.parse_expr(ctx, TokenType::ParenthesisClose)?;
340 self.require(TokenType::ParenthesisClose)?;
341 let body = self.parse_stmt_for_body(ctx)?;
342 if of {
343 Node::new(start.loc + body.loc, Syntax::ForOfStmt {
344 await_: await_.is_match(),
345 decl_mode,
346 pat,
347 rhs,
348 body,
349 })
350 } else {
351 Node::new(start.loc + body.loc, Syntax::ForInStmt {
352 decl_mode,
353 pat,
354 rhs,
355 body,
356 })
357 }
358 }
359 _ => {
360 if await_.is_match() {
362 return Err(await_.error(SyntaxErrorType::RequiredTokenNotFound(
364 TokenType::ParenthesisOpen,
365 )));
366 }
367 let init = match lhs_raw {
368 LhsRaw::Declaration(decl) => {
369 self.require(TokenType::Semicolon)?;
370 ForInit::Declaration(decl)
371 }
372 LhsRaw::Expression(expr) => {
373 self.require(TokenType::Semicolon)?;
375 ForInit::Expression(expr)
376 }
377 LhsRaw::Empty => {
378 self.require(TokenType::Semicolon)?;
379 ForInit::None
380 }
381 LhsRaw::Pattern(_) => {
382 return Err(start.error(SyntaxErrorType::ForLoopHeaderHasInvalidLhs))
383 }
384 };
385 let condition = if self.consume_if(TokenType::Semicolon)?.is_match() {
386 None
387 } else {
388 let expr = self.parse_expr(ctx, TokenType::Semicolon)?;
389 self.require(TokenType::Semicolon)?;
390 Some(expr)
391 };
392 let post = if self.consume_if(TokenType::ParenthesisClose)?.is_match() {
393 None
394 } else {
395 let expr = self.parse_expr(ctx, TokenType::ParenthesisClose)?;
396 self.require(TokenType::ParenthesisClose)?;
397 Some(expr)
398 };
399 let body = self.parse_stmt_for_body(ctx)?;
400 Node::new(start.loc + body.loc, Syntax::ForStmt {
401 init,
402 condition,
403 post,
404 body,
405 })
406 }
407 };
408 Ok(n)
409 }
410
411 pub fn parse_stmt_if(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
412 let start = self.require(TokenType::KeywordIf)?;
413 self.require(TokenType::ParenthesisOpen)?;
414 let test = self.parse_expr(ctx, TokenType::ParenthesisClose)?;
415 self.require(TokenType::ParenthesisClose)?;
416 let consequent = self.parse_stmt(ctx)?;
417 let alternate = if self.consume_if(TokenType::KeywordElse)?.is_match() {
418 Some(self.parse_stmt(ctx)?)
419 } else {
420 None
421 };
422 let end = alternate.as_ref().unwrap_or(&consequent);
423
424 Ok(Node::new(start.loc + end.loc, Syntax::IfStmt {
425 test,
426 consequent,
427 alternate,
428 }))
429 }
430
431 pub fn parse_stmt_import_or_expr_import(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
432 let cp = self.checkpoint();
433 let start = self.require(TokenType::KeywordImport)?;
434 if self.consume_if(TokenType::ParenthesisOpen)?.is_match() {
435 self.restore_checkpoint(cp);
436 return self.parse_stmt_expression(ctx);
437 };
438
439 let (default, can_have_names) =
442 if let Some(alias) = self.consume_if(TokenType::Identifier)?.match_loc() {
443 let alias_node = Node::new(alias, Syntax::IdentifierPattern {
444 name: self.string(alias),
445 });
446 (
447 Some(alias_node),
448 self.consume_if(TokenType::Comma)?.is_match(),
449 )
450 } else {
451 (None, true)
452 };
453 let names = if !can_have_names {
454 None
455 } else if self.consume_if(TokenType::Asterisk)?.is_match() {
456 self.require(TokenType::KeywordAs)?;
457 let alias = self.require(TokenType::Identifier)?.loc;
458 let alias_node = Node::new(alias, Syntax::IdentifierPattern {
459 name: self.string(alias),
460 });
461 Some(ExportNames::All(Some(alias_node)))
462 } else {
463 self.require(TokenType::BraceOpen)?;
464 let mut names = Vec::<ExportName>::new();
465 while !self.consume_if(TokenType::BraceClose)?.is_match() {
466 let name = self.parse_import_or_export_name(ctx)?;
467 names.push(name);
468 if !self.consume_if(TokenType::Comma)?.is_match() {
469 break;
470 };
471 }
472 self.require(TokenType::BraceClose)?;
473 Some(ExportNames::Specific(names))
474 };
475 self.require(TokenType::KeywordFrom)?;
476 let module = self.parse_and_normalise_literal_string(ctx)?;
477 self.require(TokenType::Semicolon)?;
478 Ok(Node::new(start.loc, Syntax::ImportStmt {
480 default,
481 module,
482 names,
483 }))
484 }
485
486 pub fn parse_stmt_return(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
487 let start = self.require(TokenType::KeywordReturn)?;
488 let mut loc = start.loc;
489 let value =
490 if self.peek()?.preceded_by_line_terminator || self.peek()?.typ == TokenType::BraceClose {
491 None
493 } else if self.consume_if(TokenType::Semicolon)?.is_match() {
494 None
495 } else {
496 let mut asi = Asi::can();
497 let value = self.parse_expr_with_asi(ctx, TokenType::Semicolon, &mut asi)?;
498 if !asi.did_end_with_asi {
499 self.require(TokenType::Semicolon)?;
500 };
501 loc.extend(value.loc);
502 Some(value)
503 };
504 Ok(Node::new(loc, Syntax::ReturnStmt { value }))
505 }
506
507 pub fn parse_stmt_throw(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
508 let start = self.require(TokenType::KeywordThrow)?;
509 if self.peek()?.preceded_by_line_terminator {
510 return Err(start.error(SyntaxErrorType::LineTerminatorAfterThrow));
512 }
513 let mut asi = Asi::can();
514 let value = self.parse_expr_with_asi(ctx, TokenType::Semicolon, &mut asi)?;
515 if !asi.did_end_with_asi {
516 self.require(TokenType::Semicolon)?;
517 };
518 Ok(Node::new(start.loc + value.loc, Syntax::ThrowStmt {
519 value,
520 }))
521 }
522
523 pub fn parse_stmt_try(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
524 let start = self.require(TokenType::KeywordTry)?;
525 let mut loc = start.loc;
526 let wrapped = self.parse_stmt_block(ctx)?;
527 let catch = if self.consume_if(TokenType::KeywordCatch)?.is_match() {
528 let parameter = if self.consume_if(TokenType::ParenthesisOpen)?.is_match() {
529 let pattern = self.parse_pattern(ctx)?;
530 self.require(TokenType::ParenthesisClose)?;
531 Some(pattern)
532 } else {
533 None
534 };
535 let start = self.require(TokenType::BraceOpen)?;
536 let body = self.parse_stmts(ctx, TokenType::BraceClose)?;
537 let end = self.require(TokenType::BraceClose)?;
538 loc += end.loc;
539 Some(Node::new(start.loc + end.loc, Syntax::CatchBlock {
540 parameter,
541 body,
542 }))
543 } else {
544 None
545 };
546 let finally = if self.consume_if(TokenType::KeywordFinally)?.is_match() {
547 let body = self.parse_stmt_block(ctx)?;
548 loc.extend(body.loc);
549 Some(body)
550 } else {
551 None
552 };
553 if catch.is_none() && finally.is_none() {
554 return Err(start.error(SyntaxErrorType::TryStatementHasNoCatchOrFinally));
555 }
556 Ok(Node::new(loc, Syntax::TryStmt {
557 wrapped,
558 catch,
559 finally,
560 }))
561 }
562
563 pub fn parse_stmt_while(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
564 let start = self.require(TokenType::KeywordWhile)?;
565 self.require(TokenType::ParenthesisOpen)?;
566 let condition = self.parse_expr(ctx, TokenType::ParenthesisClose)?;
567 self.require(TokenType::ParenthesisClose)?;
568 let body = self.parse_stmt(ctx)?;
569 Ok(Node::new(start.loc + body.loc, Syntax::WhileStmt {
570 condition,
571 body,
572 }))
573 }
574
575 pub fn parse_stmt_do_while(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
576 let start = self.require(TokenType::KeywordDo)?;
577 let body = self.parse_stmt(ctx)?;
578 self.require(TokenType::KeywordWhile)?;
579 self.require(TokenType::ParenthesisOpen)?;
580 let condition = self.parse_expr(ctx, TokenType::ParenthesisClose)?;
581 let end = self.require(TokenType::ParenthesisClose)?;
582 self.consume_if(TokenType::Semicolon)?;
583 Ok(Node::new(start.loc + end.loc, Syntax::DoWhileStmt {
584 condition,
585 body,
586 }))
587 }
588
589 pub fn parse_stmt_switch(&mut self, ctx: ParseCtx) -> SyntaxResult<Node> {
590 let start = self.require(TokenType::KeywordSwitch)?;
591 self.require(TokenType::ParenthesisOpen)?;
592 let test = self.parse_expr(ctx, TokenType::ParenthesisClose)?;
593 self.require(TokenType::ParenthesisClose)?;
594 self.require(TokenType::BraceOpen)?;
595 let mut branches = Vec::new();
596 while self.peek()?.typ != TokenType::BraceClose {
597 let mut loc = self.peek()?.loc;
598 let case = if self.consume_if(TokenType::KeywordCase)?.is_match() {
599 Some(self.parse_expr(ctx, TokenType::Colon)?)
600 } else {
601 self.require(TokenType::KeywordDefault)?;
602 None
603 };
604 self.require(TokenType::Colon)?;
605 let mut body = Vec::new();
606 loop {
607 match self.peek()?.typ {
608 TokenType::KeywordCase | TokenType::KeywordDefault | TokenType::BraceClose => break,
609 _ => {
610 let stmt = self.parse_stmt(ctx)?;
611 loc.extend(stmt.loc);
612 body.push(stmt);
613 }
614 }
615 }
616 branches.push(Node::new(loc, Syntax::SwitchBranch { case, body }));
617 }
618 let end = self.require(TokenType::BraceClose)?;
619 Ok(Node::new(start.loc + end.loc, Syntax::SwitchStmt {
620 test,
621 branches,
622 }))
623 }
624}