esr/parser/
statement.rs

1use toolshed::list::{ListBuilder, GrowableList};
2use crate::parser::{Parser, Parse, ANY, B0};
3use crate::lexer::Token::*;
4use crate::lexer::Asi;
5use crate::ast::{Node, NodeList, Declarator, DeclarationKind};
6use crate::ast::{Statement, StatementNode, Expression, ExpressionNode, Class, Function, Pattern};
7use crate::ast::expression::BinaryExpression;
8use crate::ast::statement::{ThrowStatement, ContinueStatement, BreakStatement, ReturnStatement};
9use crate::ast::statement::{TryStatement, CatchClause, IfStatement, WhileStatement, DoStatement};
10use crate::ast::statement::{DeclarationStatement, ForStatement, ForInStatement, ForOfStatement};
11use crate::ast::statement::{SwitchStatement, SwitchCase, LabeledStatement, ForInit};
12use crate::ast::OperatorKind::*;
13
14
15type StatementHandler = for<'ast> fn(&mut Parser<'ast>) -> StatementNode<'ast>;
16
17static STMT_HANDLERS: [StatementHandler; 108] = [
18    ____, EMPT, ____, ____, PRN,  ____, ARR,  ____, BLCK, ____, ____, NEW,
19//  EOF   ;     :     ,     (     )     [     ]     {     }     =>    NEW
20
21    OP,   OP,   OP,   OP,   OP,   OP,   OP,   ____, REG,  ____, ____, OP,
22//  ++    --    !     ~     TYPOF VOID  DELET *     /     %     **    +
23
24    OP,   ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
25//  -     <<    >>    >>>   <     <=    >     >=    INSOF IN    ===   !==
26
27    ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____,
28//  ==    !=    &     ^     |     &&    ||    ?     =     +=    -=    **=
29
30    ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, VAR,  LET,
31//  *=    /=    %=    <<=   >>=   >>>=  &=    ^=    |=    ...   VAR   LET
32
33    CONS, BRK,  DO,   ____, ____, ____, ____, CLAS, ____, RET,  WHL,  ____,
34//  CONST BREAK DO    CASE  ELSE  CATCH EXPRT CLASS EXTND RET   WHILE FINLY
35
36    ____, ____, CONT, FOR,  SWCH, ____, ____, FUNC, THIS, ____, IF,   THRW,
37//  SUPER WITH  CONT  FOR   SWTCH YIELD DBGGR FUNCT THIS  DEFLT IF    THROW
38
39    ____, TRY,  ____, TRUE, FALS, NULL, UNDE, STR,  NUM,  BIN,  ____, ____,
40//  IMPRT TRY   STATI TRUE  FALSE NULL  UNDEF STR   NUM   BIN   REGEX ENUM
41
42    ____, ____, ____, ____, ____, ____, LABL, ____, TPLE, TPLS, ____, ____,
43//  IMPL  PCKG  PROT  IFACE PRIV  PUBLI IDENT ACCSS TPL_O TPL_C ERR_T ERR_E
44];
45
46
47macro_rules! create_handlers {
48    ($( const $name:ident = |$par:ident| $code:expr; )*) => {
49        $(
50            #[allow(non_snake_case)]
51            fn $name<'ast>($par: &mut Parser<'ast>) -> StatementNode<'ast> {
52                $code
53            }
54        )*
55    };
56}
57
58/// Shared expression handlers that produce StatementNode<'ast>
59use crate::parser::expression::handlers::{
60    PRN, ARR, OP, NEW, REG, THIS, TRUE, FALS, NULL, UNDE, STR, NUM, BIN, TPLS, TPLE
61};
62
63create_handlers! {
64    const ____ = |par| {
65        let loc = par.lexer.start();
66        par.error::<()>();
67        par.alloc_at_loc(loc, loc, Statement::Empty)
68    };
69    const EMPT = |par| {
70        let stmt = par.alloc_in_loc(Statement::Empty);
71        par.lexer.consume();
72
73        stmt
74    };
75    const BLCK = |par| par.block_statement();
76    const VAR  = |par| par.variable_declaration_statement(DeclarationKind::Var);
77    const LET  = |par| par.variable_declaration_statement(DeclarationKind::Let);
78    const CONS = |par| par.variable_declaration_statement(DeclarationKind::Const);
79    const RET  = |par| par.return_statement();
80    const BRK  = |par| par.break_statement();
81    const THRW = |par| par.throw_statement();
82    const CONT = |par| par.continue_statement();
83    const FUNC = |par| par.function_statement();
84    const CLAS = |par| par.class_statement();
85    const IF   = |par| par.if_statement();
86    const WHL  = |par| par.while_statement();
87    const DO   = |par| par.do_statement();
88    const FOR  = |par| par.for_statement();
89    const TRY  = |par| par.try_statement();
90    const SWCH = |par| par.switch_statement();
91    const LABL = |par| par.labeled_or_expression_statement();
92}
93
94impl<'ast> Parse<'ast> for Statement<'ast> {
95    type Output = Node<'ast, Self>;
96
97    #[inline]
98    fn parse(par: &mut Parser<'ast>) -> Self::Output {
99        par.statement()
100    }
101}
102
103impl<'ast> Parse<'ast> for SwitchCase<'ast> {
104    type Output = Node<'ast, Self>;
105
106    #[inline]
107    fn parse(par: &mut Parser<'ast>) -> Self::Output {
108        let start = par.lexer.start();
109        let test = match par.lexer.token {
110            Case => {
111                par.lexer.consume();
112
113                Some(par.expression::<ANY>())
114            },
115            Default => {
116                par.lexer.consume();
117
118                None
119            },
120            _ => {
121                par.error::<()>();
122
123                None
124            }
125        };
126
127        let mut end = par.lexer.end();
128        expect!(par, Colon);
129
130        let builder = GrowableList::new();
131
132        loop {
133            match par.lexer.token {
134                Case | Default | BraceClose => break,
135                _ => {
136                    let statement = par.statement();
137                    end = statement.end;
138                    builder.push(par.arena, statement);
139                }
140            }
141        }
142
143        par.alloc_at_loc(start, end, SwitchCase {
144            test,
145            consequent: builder.as_list()
146        })
147    }
148}
149
150impl<'ast> Parser<'ast> {
151    #[inline]
152    pub fn statement(&mut self) -> StatementNode<'ast> {
153        unsafe { (*(&STMT_HANDLERS as *const StatementHandler).offset(self.lexer.token as isize))(self) }
154    }
155
156    /// Expect a semicolon to terminate a statement. Will assume a semicolon
157    /// following the ASI rules.
158    #[inline]
159    fn expect_semicolon(&mut self) {
160        match self.asi() {
161            Asi::ExplicitSemicolon => self.lexer.consume(),
162            Asi::ImplicitSemicolon => {},
163            Asi::NoSemicolon       => self.error(),
164        }
165    }
166
167    #[inline]
168    pub fn block_statement(&mut self) -> StatementNode<'ast> {
169        let start = self.lexer.start_then_consume();
170        let block = self.raw_block();
171        let end   = self.lexer.end_then_consume();
172
173        self.alloc_at_loc(start, end, block)
174    }
175
176    #[inline]
177    pub fn expression_statement(&mut self, expression: ExpressionNode<'ast>) -> StatementNode<'ast> {
178        let expression = self.nested_expression::<ANY>(expression);
179
180        self.wrap_expression(expression)
181    }
182
183    #[inline]
184    pub fn wrap_expression(&mut self, expression: ExpressionNode<'ast>) -> StatementNode<'ast> {
185        self.expect_semicolon();
186        self.alloc_at_loc(expression.start, expression.end, expression)
187    }
188
189    #[inline]
190    pub fn labeled_or_expression_statement(&mut self) -> StatementNode<'ast> {
191        let label = self.lexer.token_as_str();
192        let (start, end) = self.lexer.loc();
193
194        self.lexer.consume();
195
196        if self.lexer.token == Colon {
197            self.lexer.consume();
198
199            let body = self.statement();
200
201            return self.alloc_at_loc(start, body.end, LabeledStatement {
202                label,
203                body,
204            });
205        }
206
207        let expression = self.alloc_at_loc(start, end, label);
208        let expression = self.nested_expression::<ANY>(expression);
209
210        self.expect_semicolon();
211
212        self.alloc_at_loc(start, expression.end, expression)
213    }
214
215    #[inline]
216    pub fn function_statement(&mut self) -> StatementNode<'ast> {
217        let start = self.lexer.start_then_consume();
218        let function = Function::parse(self);
219
220        self.alloc_at_loc(start, function.body.end, function)
221    }
222
223    #[inline]
224    fn class_statement(&mut self) -> StatementNode<'ast> {
225        let start = self.lexer.start_then_consume();
226        let class = Class::parse(self);
227
228        self.alloc_at_loc(start, class.body.end, class)
229    }
230
231    #[inline]
232    pub fn variable_declaration_statement(&mut self, kind: DeclarationKind) -> StatementNode<'ast> {
233        let start = self.lexer.start_then_consume();
234        let declarators = self.variable_declarators();
235        let end = self.lexer.end();
236        let declaration = self.alloc_at_loc(start, end, DeclarationStatement {
237            kind,
238            declarators
239        });
240
241        self.expect_semicolon();
242
243        declaration
244    }
245
246    #[inline]
247    pub fn variable_declarator(&mut self) -> Node<'ast, Declarator<'ast>> {
248        let id = Pattern::parse(self);
249
250        let (init, end) = match self.lexer.token {
251            OperatorAssign => {
252                self.lexer.consume();
253                let init = self.expression::<B0>();
254
255                (Some(init), init.end)
256            },
257            _ => (None, id.end)
258        };
259
260        self.alloc_at_loc(id.start, end, Declarator {
261            id,
262            init,
263        })
264    }
265
266    #[inline]
267    pub fn variable_declarators(&mut self) -> NodeList<'ast, Declarator<'ast>> {
268        let builder = ListBuilder::new(self.arena, self.variable_declarator());
269
270        match self.lexer.token {
271            Comma => self.lexer.consume(),
272            _     => return builder.as_list(),
273        }
274
275        loop {
276            builder.push(self.arena, self.variable_declarator());
277
278            match self.lexer.token {
279                Comma => self.lexer.consume(),
280                _     => return builder.as_list(),
281            }
282        }
283    }
284
285    #[inline]
286    pub fn return_statement(&mut self) -> StatementNode<'ast> {
287        let (start, mut end) = self.lexer.loc();
288        self.lexer.consume();
289
290        let value = match self.asi() {
291            Asi::NoSemicolon => {
292                let expression = self.expression::<ANY>();
293                end = expression.end;
294
295                self.expect_semicolon();
296
297                Some(expression)
298            }
299
300            Asi::ImplicitSemicolon => None,
301            Asi::ExplicitSemicolon => {
302                self.lexer.consume();
303
304                None
305            }
306        };
307
308        self.alloc_at_loc(start, end, ReturnStatement { value })
309    }
310
311    #[inline]
312    pub fn break_statement(&mut self) -> StatementNode<'ast> {
313        let (start, mut end) = self.lexer.loc();
314        self.lexer.consume();
315
316        let label = match self.asi() {
317            Asi::ExplicitSemicolon => {
318                self.lexer.consume();
319                None
320            },
321            Asi::ImplicitSemicolon => None,
322            Asi::NoSemicolon => {
323                let label = self.identifier();
324                end = label.end;
325
326                self.expect_semicolon();
327
328                Some(label)
329            }
330        };
331
332        self.alloc_at_loc(start, end, BreakStatement { label })
333    }
334
335    #[inline]
336    pub fn continue_statement(&mut self) -> StatementNode<'ast> {
337        let (start, mut end) = self.lexer.loc();
338        self.lexer.consume();
339
340        let label = match self.asi() {
341            Asi::ExplicitSemicolon => {
342                self.lexer.consume();
343                None
344            },
345            Asi::ImplicitSemicolon => None,
346            Asi::NoSemicolon => {
347                let label = self.identifier();
348                end = label.end;
349
350                self.expect_semicolon();
351
352                Some(label)
353            }
354        };
355
356        self.alloc_at_loc(start, end, ContinueStatement { label })
357    }
358
359    #[inline]
360    pub fn throw_statement(&mut self) -> StatementNode<'ast> {
361        let start = self.lexer.start_then_consume();
362        let value = self.expression::<ANY>();
363
364        self.expect_semicolon();
365
366        self.alloc_at_loc(start, value.end, ThrowStatement { value })
367    }
368
369    #[inline]
370    pub fn try_statement(&mut self) -> StatementNode<'ast> {
371        let start = self.lexer.start_then_consume();
372        let block = self.block();
373
374        let (handler, finalizer, end) = match self.lexer.token {
375            Catch => {
376                let start = self.lexer.start_then_consume();
377                expect!(self, ParenOpen);
378                let param = Pattern::parse(self);
379                expect!(self, ParenClose);
380                let body = self.block();
381
382                let handler = self.alloc_at_loc(start, body.end, CatchClause {
383                    param,
384                    body,
385                });
386
387                match self.lexer.token {
388                    Finally => {
389                        self.lexer.consume();
390                        let block = self.block();
391
392                        (Some(handler), Some(block), block.end)
393                    },
394                    _ => (Some(handler), None, handler.end)
395                }
396            },
397            Finally => {
398                self.lexer.consume();
399                let block = self.block();
400
401                (None, Some(block), block.end)
402            },
403            _ => {
404                self.error::<()>();
405
406                (None, None, block.end)
407            }
408        };
409
410        self.alloc_at_loc(start, end, TryStatement {
411            block,
412            handler,
413            finalizer,
414        })
415    }
416
417    #[inline]
418    pub fn if_statement(&mut self) -> StatementNode<'ast> {
419        let start = self.lexer.start_then_consume();
420        expect!(self, ParenOpen);
421        let test = self.expression::<ANY>();
422        expect!(self, ParenClose);
423
424        let consequent = self.statement();
425
426        let (alternate, end) = match self.lexer.token {
427            Else => {
428                self.lexer.consume();
429                let alternate = self.statement();
430                (Some(alternate), alternate.end)
431            },
432            _ => (None, consequent.end)
433        };
434
435        self.alloc_at_loc(start, end, IfStatement {
436            test,
437            consequent,
438            alternate,
439        })
440    }
441
442    #[inline]
443    pub fn while_statement(&mut self) -> StatementNode<'ast> {
444        let start = self.lexer.start_then_consume();
445        expect!(self, ParenOpen);
446        let test = self.expression::<ANY>();
447        expect!(self, ParenClose);
448
449        let body = self.statement();
450
451        self.alloc_at_loc(start, body.end, WhileStatement {
452            test,
453            body,
454        })
455    }
456
457    #[inline]
458    pub fn do_statement(&mut self) -> StatementNode<'ast> {
459        let start = self.lexer.start_then_consume();
460        let body = self.statement();
461        expect!(self, While);
462        expect!(self, ParenOpen);
463        let test = self.expression::<ANY>();
464        let end = self.lexer.end();
465        expect!(self, ParenClose);
466
467        self.alloc_at_loc(start, end, DoStatement {
468            body,
469            test,
470        })
471    }
472
473    #[inline]
474    fn for_init(&mut self, kind: DeclarationKind) -> Node<'ast, ForInit<'ast>> {
475        let start = self.lexer.start_then_consume();
476        let declarators = self.variable_declarators();
477        let end = self.lexer.end();
478        
479        self.alloc_at_loc(start, end, DeclarationStatement {
480            kind,
481            declarators
482        })
483    }
484
485    #[inline]
486    fn for_statement(&mut self) -> StatementNode<'ast> {
487        let start = self.lexer.start_then_consume();
488        expect!(self, ParenOpen);
489
490        let init = match self.lexer.token {
491            Semicolon => {
492                self.lexer.consume();
493                None
494            },
495            DeclarationVar   => Some(self.for_init(DeclarationKind::Var)),
496            DeclarationLet   => Some(self.for_init(DeclarationKind::Let)),
497            DeclarationConst => Some(self.for_init(DeclarationKind::Const)),
498            _ => {
499                let init = self.expression::<ANY>();
500
501                if let Expression::Binary(BinaryExpression {
502                    operator: In,
503                    left,
504                    right,
505                    ..
506                }) = init.item {
507                    let left = self.alloc_at_loc(left.start, left.end, left);
508
509                    return self.for_in_statement_from_parts(start, left, right);
510                }
511
512                Some(self.alloc_at_loc(init.start, init.end, init))
513            },
514        };
515
516        if let Some(ref init) = init {
517            match self.lexer.token {
518                OperatorIn => {
519                    self.lexer.consume();
520                    return self.for_in_statement(start, *init);
521                },
522                Identifier if self.lexer.token_as_str() == "of" => {
523                    self.lexer.consume();
524                    return self.for_of_statement(start, *init);
525                },
526                _ => expect!(self, Semicolon)
527            }
528        }
529
530        let test = match self.lexer.token {
531            Semicolon => {
532                self.lexer.consume();
533                None
534            },
535            _ => {
536                let test = self.expression::<ANY>();
537                expect!(self, Semicolon);
538
539                Some(test)
540            }
541        };
542
543        let update = match self.lexer.token {
544            ParenClose => {
545                self.lexer.consume();
546                None
547            },
548            _         => {
549                let update = self.expression::<ANY>();
550                expect!(self, ParenClose);
551
552                Some(update)
553            }
554        };
555
556        let body = self.statement();
557
558        self.alloc_at_loc(start, body.end, ForStatement {
559            init,
560            test,
561            update,
562            body,
563        })
564    }
565
566    fn for_in_statement_from_parts(&mut self, start: u32, left: Node<'ast, ForInit<'ast>>, right: ExpressionNode<'ast>) -> StatementNode<'ast> {
567        expect!(self, ParenClose);
568
569        let body = self.statement();
570
571        self.alloc_at_loc(start, body.end, ForInStatement {
572            left,
573            right,
574            body,
575        })
576    }
577
578    fn for_in_statement(&mut self, start: u32, left: Node<'ast, ForInit<'ast>>) -> StatementNode<'ast> {
579        let right = self.expression::<ANY>();
580
581        expect!(self, ParenClose);
582
583        let body = self.statement();
584
585        self.alloc_at_loc(start, body.end, ForInStatement {
586            left,
587            right,
588            body,
589        })
590    }
591
592    fn for_of_statement(&mut self, start: u32, left: Node<'ast, ForInit<'ast>>) -> StatementNode<'ast> {
593        let right = self.expression::<ANY>();
594
595        expect!(self, ParenClose);
596
597        let body = self.statement();
598
599        self.alloc_at_loc(start, body.end, ForOfStatement {
600            left,
601            right,
602            body,
603        })
604    }
605
606    fn switch_statement(&mut self) -> StatementNode<'ast> {
607        let start = self.lexer.start_then_consume();
608        expect!(self, ParenOpen);
609
610        let discriminant = self.expression::<ANY>();
611
612        expect!(self, ParenClose);
613
614        let cases = self.block();
615
616        self.alloc_at_loc(start, cases.end, SwitchStatement {
617            discriminant,
618            cases
619        })
620    }
621}
622
623#[cfg(test)]
624mod test {
625    use super::*;
626    use crate::parser::parse;
627    use crate::parser::mock::Mock;
628    use crate::ast::{NodeList, Literal, Function, Class, OperatorKind, BlockStatement};
629    use crate::ast::expression::*;
630
631    #[test]
632    fn block_statement() {
633        let src = "{ true }";
634        let mock = Mock::new();
635
636        let expected = mock.list([
637            BlockStatement {
638                body: mock.list([
639                    mock.ptr(Literal::True)
640                ])
641            }
642        ]);
643
644        assert_eq!(parse(src).unwrap().body(), expected);
645    }
646
647    #[test]
648    fn labeled_block_statement() {
649        let src = "foobar: { true }";
650        let mock = Mock::new();
651
652        let expected = mock.list([
653            LabeledStatement {
654                label: "foobar",
655                body: mock.ptr(BlockStatement {
656                    body: mock.list([
657                        mock.ptr(Literal::True)
658                    ])
659                })
660            }
661        ]);
662
663        assert_eq!(parse(src).unwrap().body(), expected);
664    }
665
666    #[test]
667    fn if_statement() {
668        let src = "if (true) foo;";
669        let mock = Mock::new();
670
671        let expected = mock.list([
672            IfStatement {
673                test: mock.ptr(Literal::True),
674                consequent: mock.ptr(mock.ptr("foo")),
675                alternate: None
676            }
677        ]);
678
679        assert_eq!(parse(src).unwrap().body(), expected);
680    }
681
682    #[test]
683    fn if_else_statement() {
684        let src = "if (true) foo; else { bar; }";
685        let mock = Mock::new();
686
687        let expected = mock.list([
688            IfStatement {
689                test: mock.ptr(Literal::True),
690                consequent: mock.ptr(mock.ptr("foo")),
691                alternate: Some(mock.ptr(BlockStatement {
692                    body: mock.list([
693                        mock.ptr("bar")
694                    ])
695                }))
696            }
697        ]);
698
699        assert_eq!(parse(src).unwrap().body(), expected);
700    }
701
702    #[test]
703    fn while_statement() {
704        let src = "while (true) foo;";
705        let mock = Mock::new();
706
707        let expected = mock.list([
708            WhileStatement {
709                test: mock.ptr(Literal::True),
710                body: mock.ptr(mock.ptr("foo"))
711            }
712        ]);
713
714        assert_eq!(parse(src).unwrap().body(), expected);
715    }
716
717    #[test]
718    fn while_statement_block() {
719        let src = "while (true) { foo; }";
720        let mock = Mock::new();
721
722        let expected = mock.list([
723            WhileStatement {
724                test: mock.ptr(Literal::True),
725                body: mock.ptr(BlockStatement {
726                    body: mock.list([
727                        mock.ptr("foo")
728                    ])
729                })
730            }
731        ]);
732
733        assert_eq!(parse(src).unwrap().body(), expected);
734    }
735
736    #[test]
737    fn do_statement() {
738        let src = "do foo; while (true)";
739        let mock = Mock::new();
740
741        let expected = mock.list([
742            DoStatement {
743                body: mock.ptr(mock.ptr("foo")),
744                test: mock.ptr(Literal::True)
745            }
746        ]);
747
748        assert_eq!(parse(src).unwrap().body(), expected);
749    }
750
751    #[test]
752    fn break_statement() {
753        let src = "break;";
754        let mock = Mock::new();
755
756        let expected = mock.list([
757            BreakStatement {
758                label: None,
759            }
760        ]);
761
762        assert_eq!(parse(src).unwrap().body(), expected);
763    }
764
765    #[test]
766    fn break_statement_label() {
767        let src = "break foo;";
768        let mock = Mock::new();
769
770        let expected = mock.list([
771            BreakStatement {
772                label: Some(mock.ptr("foo")),
773            }
774        ]);
775
776        assert_eq!(parse(src).unwrap().body(), expected);
777    }
778
779    #[test]
780    fn throw_statement() {
781        let src = "throw '3'";
782        let mock = Mock::new();
783
784        let expected = mock.list([
785            ThrowStatement {
786                value: mock.ptr(Literal::String("'3'")),
787            }
788        ]);
789
790        assert_eq!(parse(src).unwrap().body(), expected);
791    }
792
793    #[test]
794    fn try_statement() {
795        let src = "try {} catch (err) {}";
796        let mock = Mock::new();
797
798        let expected = mock.list([
799            TryStatement {
800                block: mock.empty_block(),
801                handler: Some(mock.ptr(CatchClause {
802                    param: mock.ptr(Pattern::Identifier("err")),
803                    body: mock.empty_block()
804                })),
805                finalizer: None
806            }
807        ]);
808
809        assert_eq!(parse(src).unwrap().body(), expected);
810    }
811
812    #[test]
813    fn try_statement_finally() {
814        let src = "try { foo; } finally { bar; }";
815        let mock = Mock::new();
816
817        let expected = mock.list([
818            TryStatement {
819                block: mock.block([
820                    mock.ptr("foo")
821                ]),
822                handler: None,
823                finalizer: Some(mock.block([
824                    mock.ptr("bar")
825                ])),
826            }
827        ]);
828
829        assert_eq!(parse(src).unwrap().body(), expected);
830    }
831
832    #[test]
833    fn try_statement_full() {
834        let src = "try { foo; } catch (err) { bar; } finally { qux; }";
835        let mock = Mock::new();
836
837        let expected = mock.list([
838            TryStatement {
839                block: mock.block([
840                    mock.ptr("foo")
841                ]),
842                handler: Some(mock.ptr(CatchClause {
843                    param: mock.ptr(Pattern::Identifier("err")),
844                    body: mock.block([
845                        mock.ptr("bar")
846                    ])
847                })),
848                finalizer: Some(mock.block([
849                    mock.ptr("qux")
850                ])),
851            }
852        ]);
853
854        assert_eq!(parse(src).unwrap().body(), expected);
855    }
856
857    #[test]
858    fn try_statement_no_tail() {
859        assert!(parse("try {}").is_err())
860    }
861
862    #[test]
863    fn variable_declaration_statement() {
864        let src = "var x, y, z = 42;";
865        let mock = Mock::new();
866
867        let expected = mock.list([
868            DeclarationStatement {
869                kind: DeclarationKind::Var,
870                declarators: mock.list([
871                    Declarator {
872                        id: mock.ptr(Pattern::Identifier("x")),
873                        init: None,
874                    },
875                    Declarator {
876                        id: mock.ptr(Pattern::Identifier("y")),
877                        init: None,
878                    },
879                    Declarator {
880                        id: mock.ptr(Pattern::Identifier("z")),
881                        init: Some(mock.number("42"))
882                    }
883                ])
884            }
885        ]);
886
887        assert_eq!(parse(src).unwrap().body(), expected);
888    }
889
890    #[test]
891    fn variable_declaration_statement_spread() {
892        let src = "const a = {...foo}";
893        let mock = Mock::new();
894
895        let expected = mock.list([
896            DeclarationStatement {
897                kind: DeclarationKind::Const,
898                declarators: mock.list([
899                    Declarator {
900                        id: mock.ptr(Pattern::Identifier("a")),
901                        init: Some(mock.ptr(ObjectExpression {
902                            body: mock.list([
903                                Property::Spread {
904                                    argument: mock.ptr("foo")
905                                },
906                            ])
907                        }))
908                    }
909                ])
910            }
911        ]);
912
913        assert_eq!(parse(src).unwrap().body(), expected);
914    }
915
916    #[test]
917    fn variable_declaration_statement_destructuring_array() {
918        let src = "let [x, y] = [1, 2];";
919        let mock = Mock::new();
920
921        let expected = mock.list([
922            DeclarationStatement {
923                kind: DeclarationKind::Let,
924                declarators: mock.list([
925                    Declarator {
926                        id: mock.ptr(Pattern::ArrayPattern {
927                            elements: mock.list([
928                                Pattern::Identifier("x"),
929                                Pattern::Identifier("y")
930                            ])
931                        }),
932                        init: Some(mock.ptr(ArrayExpression {
933                            body: mock.list([
934                                Expression::Literal(Literal::Number("1")),
935                                Expression::Literal(Literal::Number("2")),
936                            ])
937                        })),
938                    },
939                ])
940            }
941        ]);
942
943        assert_eq!(parse(src).unwrap().body(), expected);
944    }
945
946    #[test]
947    fn variable_declaration_statement_destructuring_array_sparse() {
948        let src = "let [, foo] = bar;";
949        let mock = Mock::new();
950
951        let expected = mock.list([
952            DeclarationStatement {
953                kind: DeclarationKind::Let,
954                declarators: mock.list([
955                    Declarator {
956                        id: mock.ptr(Pattern::ArrayPattern {
957                            elements: mock.list([
958                                Pattern::Void,
959                                Pattern::Identifier("foo")
960                            ])
961                        }),
962                        init: Some(mock.ptr("bar")),
963                    },
964                ])
965            }
966        ]);
967
968        assert_eq!(parse(src).unwrap().body(), expected);
969    }
970
971    #[test]
972    fn variable_declaration_statement_destructuring_object() {
973        let src = "const { x, y } = { a, b };";
974        let mock = Mock::new();
975
976        let expected = mock.list([
977            DeclarationStatement {
978                kind: DeclarationKind::Const,
979                declarators: mock.list([
980                    Declarator {
981                        id: mock.ptr(Pattern::ObjectPattern {
982                            properties: mock.list([
983                                Property::Shorthand("x"),
984                                Property::Shorthand("y"),
985                            ])
986                        }),
987                        init: Some(mock.ptr(ObjectExpression {
988                            body: mock.list([
989                                Property::Shorthand("a"),
990                                Property::Shorthand("b"),
991                            ])
992                        })),
993                    },
994                ])
995            }
996        ]);
997
998        assert_eq!(parse(src).unwrap().body(), expected);
999    }
1000
1001    #[test]
1002    fn for_statement() {
1003        let src = "for (let i = 0; i < 10; i++) {}";
1004        let mock = Mock::new();
1005
1006        let expected = mock.list([
1007            ForStatement {
1008                init: Some(mock.ptr(DeclarationStatement {
1009                    kind: DeclarationKind::Let,
1010                    declarators: mock.list([
1011                        Declarator {
1012                            id: mock.ptr(Pattern::Identifier("i")),
1013                            init: Some(mock.number("0")),
1014                        }
1015                    ]),
1016                })),
1017                test: Some(mock.ptr(BinaryExpression {
1018                    operator: OperatorKind::Lesser,
1019                    left: mock.ptr("i"),
1020                    right: mock.number("10"),
1021                })),
1022                update: Some(mock.ptr(PostfixExpression {
1023                    operator: OperatorKind::Increment,
1024                    operand: mock.ptr("i")
1025                })),
1026                body: mock.ptr(BlockStatement {
1027                    body: NodeList::empty()
1028                })
1029            }
1030        ]);
1031
1032        assert_eq!(parse(src).unwrap().body(), expected);
1033    }
1034
1035    #[test]
1036    fn empty_for_statement() {
1037        let src = "for (;;) {}";
1038        let mock = Mock::new();
1039
1040        let expected = mock.list([
1041            ForStatement {
1042                init: None,
1043                test: None,
1044                update: None,
1045                body: mock.ptr(BlockStatement {
1046                    body: NodeList::empty()
1047                })
1048            }
1049        ]);
1050
1051        assert_eq!(parse(src).unwrap().body(), expected);
1052    }
1053
1054
1055    #[test]
1056    fn for_statement_continue() {
1057        let src = "for (let i = 0, j = 10; i < 10; i++, j--) { continue; }";
1058        let mock = Mock::new();
1059
1060        let expected = mock.list([
1061            ForStatement {
1062                init: Some(mock.ptr(DeclarationStatement {
1063                    kind: DeclarationKind::Let,
1064                    declarators: mock.list([
1065                        Declarator {
1066                            id: mock.ptr(Pattern::Identifier("i")),
1067                            init: Some(mock.number("0")),
1068                        },
1069                        Declarator {
1070                            id: mock.ptr(Pattern::Identifier("j")),
1071                            init: Some(mock.number("10")),
1072                        }
1073                    ]),
1074                })),
1075                test: Some(mock.ptr(BinaryExpression {
1076                    operator: OperatorKind::Lesser,
1077                    left: mock.ptr("i"),
1078                    right: mock.number("10"),
1079                })),
1080                update: Some(mock.ptr(SequenceExpression {
1081                    body: mock.list([
1082                        Expression::Postfix(PostfixExpression {
1083                            operator: OperatorKind::Increment,
1084                            operand: mock.ptr("i")
1085                        }),
1086                        Expression::Postfix(PostfixExpression {
1087                            operator: OperatorKind::Decrement,
1088                            operand: mock.ptr("j")
1089                        })
1090                    ])
1091                })),
1092                body: mock.ptr(BlockStatement {
1093                    body: mock.list([
1094                        ContinueStatement {
1095                            label: None
1096                        }
1097                    ]),
1098                })
1099            }
1100        ]);
1101
1102        assert_eq!(parse(src).unwrap().body(), expected);
1103    }
1104
1105
1106    #[test]
1107    fn for_statement_sequences() {
1108        let src = "for (let i = 0, j = 10; i < 10; i++, j--) {}";
1109        let mock = Mock::new();
1110
1111        let expected = mock.list([
1112            ForStatement {
1113                init: Some(mock.ptr(DeclarationStatement {
1114                    kind: DeclarationKind::Let,
1115                    declarators: mock.list([
1116                        Declarator {
1117                            id: mock.ptr(Pattern::Identifier("i")),
1118                            init: Some(mock.number("0")),
1119                        },
1120                        Declarator {
1121                            id: mock.ptr(Pattern::Identifier("j")),
1122                            init: Some(mock.number("10")),
1123                        }
1124                    ]),
1125                })),
1126                test: Some(mock.ptr(BinaryExpression {
1127                    operator: OperatorKind::Lesser,
1128                    left: mock.ptr("i"),
1129                    right: mock.number("10"),
1130                })),
1131                update: Some(mock.ptr(SequenceExpression {
1132                    body: mock.list([
1133                        Expression::Postfix(PostfixExpression {
1134                            operator: OperatorKind::Increment,
1135                            operand: mock.ptr("i")
1136                        }),
1137                        Expression::Postfix(PostfixExpression {
1138                            operator: OperatorKind::Decrement,
1139                            operand: mock.ptr("j")
1140                        })
1141                    ])
1142                })),
1143                body: mock.ptr(BlockStatement {
1144                    body: NodeList::empty()
1145                })
1146            }
1147        ]);
1148
1149        assert_eq!(parse(src).unwrap().body(), expected);
1150    }
1151
1152    #[test]
1153    fn function_statement() {
1154        let src = "function foo() {}";
1155        let mock = Mock::new();
1156
1157        let expected = mock.list([
1158            Function {
1159                name: mock.name("foo"),
1160                generator: false,
1161                params: NodeList::empty(),
1162                body: mock.empty_block(),
1163            }
1164        ]);
1165
1166        assert_eq!(parse(src).unwrap().body(), expected);
1167    }
1168
1169    #[test]
1170    fn function_statement_must_have_name() {
1171        assert!(parse("function() {}").is_err());
1172    }
1173
1174    #[test]
1175    fn class_statement() {
1176        let src = "class Foo {}";
1177        let mock = Mock::new();
1178
1179        let expected = mock.list([
1180            Class {
1181                name: mock.name("Foo"),
1182                extends: None,
1183                body: mock.empty_block(),
1184            }
1185        ]);
1186
1187        assert_eq!(parse(src).unwrap().body(), expected);
1188    }
1189
1190    #[test]
1191    #[should_panic]
1192    fn class_statement_must_have_name() {
1193        parse("class {}").unwrap();
1194    }
1195
1196    #[test]
1197    fn switch_statement() {
1198        let src = r#"
1199        switch (times) {
1200            case 3:
1201                break;
1202            case 2:
1203                return b;
1204            case "1":
1205            default:
1206                return false;
1207        }
1208        "#;
1209        let mock = Mock::new();
1210
1211        let expected = mock.list([
1212            SwitchStatement {
1213                discriminant: mock.ptr("times"),
1214                cases: mock.block([
1215                    SwitchCase {
1216                        test: Some(mock.number("3")),
1217                        consequent: mock.list([
1218                            BreakStatement { label: None }
1219                        ])
1220                    },
1221                    SwitchCase {
1222                        test: Some(mock.number("2")),
1223                        consequent: mock.list([
1224                            ReturnStatement { value: Some(mock.ptr("b")) }
1225                        ])
1226                    },
1227                    SwitchCase {
1228                        test: Some(mock.ptr(Expression::Literal(Literal::String("\"1\"")))),
1229                        consequent: NodeList::empty()
1230                    },
1231                    SwitchCase {
1232                        test: None,
1233                        consequent: mock.list([
1234                            ReturnStatement { value: Some(mock.ptr(Expression::Literal(Literal::False))) }
1235                        ])
1236                    },
1237                ])
1238            }
1239        ]);
1240        assert_eq!(parse(src).unwrap().body(), expected);
1241    }
1242}