ablescript/
parser.rs

1//! AbleScript Parser
2//!
3//! Type of this parser is recursive descent
4
5use crate::ast::*;
6use crate::error::{Error, ErrorKind};
7use crate::lexer::Token;
8use logos::{Lexer, Logos};
9
10/// Parser structure which holds lexer and metadata
11///
12/// Make one using [`Parser::new`] function
13struct Parser<'source> {
14    lexer: Lexer<'source, Token>,
15    tdark: bool,
16}
17
18impl<'source> Parser<'source> {
19    /// Create a new parser from source code
20    fn new(source: &'source str) -> Self {
21        Self {
22            lexer: Token::lexer(source),
23            tdark: false,
24        }
25    }
26
27    /// Start parsing tokens
28    ///
29    /// Loops trough lexer, parses statements, returns AST
30    fn parse(&mut self) -> Result<Block, Error> {
31        let mut ast = vec![];
32        while let Some(token) = self.lexer.next() {
33            match token {
34                // T-Dark block (replace `lang` with `script`)
35                Ok(Token::TDark) => ast.extend(self.tdark_flow()?),
36                Ok(token) => ast.push(self.parse_stmt(token)?),
37
38                // Invalid token
39                Err(()) => return Err(Error::new(ErrorKind::InvalidToken, self.lexer.span())),
40            }
41        }
42        Ok(ast)
43    }
44
45    /// Get next item
46    ///
47    /// If EOF, return Error instead of None
48    fn checked_next(&mut self) -> Result<Token, Error> {
49        match self.lexer.next() {
50            Some(Ok(t)) => Ok(t),
51            Some(Err(())) => Err(Error::new(ErrorKind::InvalidToken, self.lexer.span())),
52            None => Err(Error::unexpected_eoi(self.lexer.span().start)),
53        }
54    }
55
56    /// Parse a token
57    ///
58    /// This function will route to corresponding flow functions
59    /// which may advance the lexer iterator
60    fn parse_stmt(&mut self, token: Token) -> Result<Spanned<Stmt>, Error> {
61        let start = self.lexer.span().start;
62
63        match token {
64            Token::Unless => self.unless_flow(),
65            Token::Functio => self.functio_flow(),
66            Token::Bff => self.bff_flow(),
67            Token::Melo => self.melo_flow(),
68            Token::Loop => self.get_block().map(|body| Stmt::Loop { body }),
69            Token::Enough => self.semicolon_terminated(Stmt::Enough),
70            Token::AndAgain => self.semicolon_terminated(Stmt::AndAgain),
71            Token::Finally => self.get_block().map(Stmt::Finally),
72            Token::Rlyeh => self.semicolon_terminated(Stmt::Rlyeh),
73            Token::Rickroll => self.semicolon_terminated(Stmt::Rickroll),
74
75            Token::Identifier(_)
76            | Token::String(_)
77            | Token::Integer(_)
78            | Token::Char(_)
79            | Token::Aint
80            | Token::LeftBracket
81            | Token::LeftParen => self.value_flow(token),
82
83            t => Err(Error {
84                kind: ErrorKind::UnexpectedToken(t),
85                span: start..self.lexer.span().end,
86            }),
87        }
88        .map(|stmt| Spanned::new(stmt, start..self.lexer.span().end))
89    }
90
91    /// Require statement to be semicolon terminated
92    ///
93    /// Utility function for short statements
94    fn semicolon_terminated(&mut self, stmt_kind: Stmt) -> Result<Stmt, Error> {
95        self.require(Token::Semicolon)?;
96        Ok(stmt_kind)
97    }
98
99    /// Require next item to be equal with expected one
100    fn require(&mut self, required: Token) -> Result<(), Error> {
101        match self.checked_next()? {
102            t if t == required => Ok(()),
103            t => Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
104        }
105    }
106
107    /// Get an Identifier
108    fn get_ident(&mut self) -> Result<Spanned<String>, Error> {
109        match self.checked_next()? {
110            Token::Identifier(ident) => {
111                Ok(Spanned::new(self.tdark_subst(ident), self.lexer.span()))
112            }
113            t => Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
114        }
115    }
116
117    /// Parse an expression
118    ///
119    /// AbleScript strongly separates expressions from statements.
120    /// Expressions do not have any side effects and the are
121    /// only mathematial and logical operations or values.
122    fn parse_expr(
123        &mut self,
124        token: Token,
125        buf: &mut Option<Spanned<Expr>>,
126    ) -> Result<Spanned<Expr>, Error> {
127        let start = match buf {
128            Some(e) => e.span.start,
129            None => self.lexer.span().start,
130        };
131
132        match token {
133            // Values
134            Token::Identifier(i) => Ok(Expr::Variable(self.tdark_subst(i))),
135            Token::Integer(i) => Ok(Expr::Literal(Literal::Int(i))),
136            Token::String(s) => Ok(Expr::Literal(Literal::Str(self.tdark_subst(s)))),
137            Token::Char(c) => Ok(Expr::Literal(Literal::Char(c))),
138            Token::LeftBracket => match buf.take() {
139                Some(buf) => self.index_flow(buf),
140                None => self.cart_flow(),
141            },
142
143            // Operations
144            Token::Aint if buf.is_none() => {
145                let next = self.checked_next()?;
146                Ok(Expr::Aint(Box::new(self.parse_expr(next, buf)?)))
147            }
148
149            Token::Plus
150            | Token::Minus
151            | Token::Star
152            | Token::FwdSlash
153            | Token::Equals
154            | Token::LessThan
155            | Token::GreaterThan
156            | Token::Aint => self.binop_flow(
157                BinOpKind::from_token(token).map_err(|e| Error::new(e, self.lexer.span()))?,
158                buf,
159            ),
160
161            Token::LeftParen => return self.expr_flow(Token::RightParen),
162            t => Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
163        }
164        .map(|expr| Spanned::new(expr, start..self.lexer.span().end))
165    }
166
167    /// Flow for creating carts
168    fn cart_flow(&mut self) -> Result<Expr, Error> {
169        let mut cart = vec![];
170        let mut buf = None;
171
172        match self.checked_next()? {
173            Token::RightBracket => (),
174            t => {
175                buf = Some(self.parse_expr(t, &mut buf)?);
176                'cart: loop {
177                    let value = loop {
178                        match self.checked_next()? {
179                            Token::Arrow => break buf.take(),
180                            t => buf = Some(self.parse_expr(t, &mut buf)?),
181                        }
182                    }
183                    .ok_or_else(|| {
184                        Error::new(ErrorKind::UnexpectedToken(Token::Arrow), self.lexer.span())
185                    })?;
186
187                    let key = loop {
188                        match self.checked_next()? {
189                            Token::RightBracket => {
190                                cart.push((
191                                    value,
192                                    buf.take().ok_or_else(|| {
193                                        Error::unexpected_eoi(self.lexer.span().start)
194                                    })?,
195                                ));
196
197                                break 'cart;
198                            }
199                            Token::Comma => break buf.take(),
200                            t => buf = Some(self.parse_expr(t, &mut buf)?),
201                        }
202                    }
203                    .ok_or_else(|| Error::unexpected_eoi(self.lexer.span().start))?;
204
205                    cart.push((value, key));
206                }
207            }
208        }
209
210        Ok(Expr::Cart(cart))
211    }
212
213    /// Flow for indexing operations
214    ///
215    /// Indexing with empty index resolves to length of expression, else it indexes
216    fn index_flow(&mut self, expr: Spanned<Expr>) -> Result<Expr, Error> {
217        let mut buf = None;
218        Ok(loop {
219            match self.checked_next()? {
220                Token::RightBracket => match buf {
221                    Some(index) => {
222                        break Expr::Index {
223                            expr: Box::new(expr),
224                            index: Box::new(index),
225                        }
226                    }
227                    None => break Expr::Len(Box::new(expr)),
228                },
229                Token::GreaterThan if buf.is_none() => {
230                    self.require(Token::RightBracket)?;
231                    break Expr::Keys(Box::new(expr));
232                }
233                token => buf = Some(self.parse_expr(token, &mut buf)?),
234            }
235        })
236    }
237
238    /// Flow for operators
239    ///
240    /// Generates operation from LHS buffer and next expression as RHS
241    ///
242    /// This is unaware of precedence, as AbleScript do not have it
243    fn binop_flow(
244        &mut self,
245        kind: BinOpKind,
246        lhs: &mut Option<Spanned<Expr>>,
247    ) -> Result<Expr, Error> {
248        Ok(Expr::BinOp {
249            lhs: Box::new(
250                lhs.take()
251                    .ok_or_else(|| Error::new(ErrorKind::MissingLhs, self.lexer.span()))?,
252            ),
253            rhs: {
254                let next = self.checked_next()?;
255                Box::new(self.parse_expr(next, &mut None)?)
256            },
257            kind,
258        })
259    }
260
261    /// Parse expressions until terminate token
262    fn expr_flow(&mut self, terminate: Token) -> Result<Spanned<Expr>, Error> {
263        let mut buf = None;
264        Ok(loop {
265            match self.checked_next()? {
266                t if t == terminate => {
267                    break buf.take().ok_or_else(|| {
268                        Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())
269                    })?
270                }
271                t => buf = Some(self.parse_expr(t, &mut buf)?),
272            }
273        })
274    }
275
276    /// Parse a list of statements between curly braces
277    fn get_block(&mut self) -> Result<Block, Error> {
278        self.require(Token::LeftCurly)?;
279        let mut block = vec![];
280
281        loop {
282            match self.checked_next()? {
283                Token::RightCurly => break,
284                Token::TDark => block.extend(self.tdark_flow()?),
285                t => block.push(self.parse_stmt(t)?),
286            }
287        }
288        Ok(block)
289    }
290
291    /// Parse T-Dark block
292    fn tdark_flow(&mut self) -> Result<Block, Error> {
293        self.tdark = true;
294        let block = self.get_block();
295        self.tdark = false;
296        block
297    }
298
299    /// If Statement parser gets any kind of value (Identifier or Literal)
300    /// It cannot parse it as it do not parse expressions. Instead of it it
301    /// will parse it to function call or print statement.
302    fn value_flow(&mut self, init: Token) -> Result<Stmt, Error> {
303        let mut buf = Some(self.parse_expr(init, &mut None)?);
304        Ok(loop {
305            match self.checked_next()? {
306                // Print to stdout
307                Token::Print => {
308                    break Stmt::Print {
309                        expr: buf.take().ok_or_else(|| {
310                            Error::new(ErrorKind::UnexpectedToken(Token::Print), self.lexer.span())
311                        })?,
312                        newline: match self.checked_next()? {
313                            Token::Semicolon => true,
314                            Token::Minus => {
315                                self.require(Token::Semicolon)?;
316                                false
317                            }
318                            token => {
319                                return Err(Error::new(
320                                    ErrorKind::UnexpectedToken(token),
321                                    self.lexer.span(),
322                                ));
323                            }
324                        },
325                    };
326                }
327
328                // Functio call
329                Token::LeftParen => {
330                    break self.functio_call_flow(buf.take().ok_or_else(|| {
331                        Error::new(
332                            ErrorKind::UnexpectedToken(Token::LeftParen),
333                            self.lexer.span(),
334                        )
335                    })?)?;
336                }
337
338                // Variable declaration
339                Token::Dim => {
340                    return match buf.take() {
341                        Some(Spanned {
342                            item: Expr::Variable(ident),
343                            span,
344                        }) => Ok(Stmt::Dim {
345                            ident: Spanned::new(ident, span),
346                            init: {
347                                let mut init = None;
348                                loop {
349                                    match self.checked_next()? {
350                                        Token::Semicolon => break init,
351                                        token => init = Some(self.parse_expr(token, &mut init)?),
352                                    }
353                                }
354                            },
355                        }),
356                        _ => Err(Error::new(
357                            ErrorKind::UnexpectedToken(Token::Dim),
358                            self.lexer.span(),
359                        )),
360                    }
361                }
362
363                // Variable assignment
364                Token::Assign => {
365                    return match buf.take() {
366                        Some(expr) => self.assignment_flow(expr),
367                        None => Err(Error::new(
368                            ErrorKind::UnexpectedToken(Token::Assign),
369                            self.lexer.span(),
370                        )),
371                    }
372                }
373
374                // Read input
375                Token::Read => {
376                    if let Some(Ok(assignable)) = buf.take().map(Assignable::from_expr) {
377                        self.require(Token::Semicolon)?;
378                        break Stmt::Read(assignable);
379                    } else {
380                        return Err(Error::new(
381                            ErrorKind::UnexpectedToken(Token::Read),
382                            self.lexer.span(),
383                        ));
384                    }
385                }
386
387                t => buf = Some(self.parse_expr(t, &mut buf)?),
388            }
389        })
390    }
391
392    /// Parse Unless flow
393    ///
394    /// Consists of condition and block, there is no else
395    fn unless_flow(&mut self) -> Result<Stmt, Error> {
396        self.require(Token::LeftParen)?;
397        Ok(Stmt::Unless {
398            cond: self.expr_flow(Token::RightParen)?,
399            body: self.get_block()?,
400        })
401    }
402
403    /// Parse functio flow
404    ///
405    /// functio $ident (a, b, c) { ... }
406    fn functio_flow(&mut self) -> Result<Stmt, Error> {
407        let ident = self.get_ident()?;
408        self.require(Token::LeftParen)?;
409
410        let mut params = vec![];
411        loop {
412            match self.checked_next()? {
413                Token::RightParen => break,
414                Token::Identifier(i) => {
415                    params.push(Spanned::new(i, self.lexer.span()));
416
417                    // Require comma (next) or right paren (end) after identifier
418                    match self.checked_next()? {
419                        Token::Comma => continue,
420                        Token::RightParen => break,
421                        t => {
422                            return Err(Error::new(
423                                ErrorKind::UnexpectedToken(t),
424                                self.lexer.span(),
425                            ))
426                        }
427                    }
428                }
429                t => return Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
430            }
431        }
432
433        let body = self.get_block()?;
434
435        Ok(Stmt::Functio {
436            ident,
437            params,
438            body,
439        })
440    }
441
442    /// Parse BF function declaration
443    ///
444    /// `bff $ident ([tapelen]) { ... }`
445    fn bff_flow(&mut self) -> Result<Stmt, Error> {
446        let ident = self.get_ident()?;
447
448        let tape_len = match self.checked_next()? {
449            Token::LeftParen => {
450                let len = Some(self.expr_flow(Token::RightParen)?);
451                self.require(Token::LeftCurly)?;
452                len
453            }
454            Token::LeftCurly => None,
455            token => {
456                return Err(Error::new(
457                    ErrorKind::UnexpectedToken(token),
458                    self.lexer.span(),
459                ))
460            }
461        };
462
463        let mut code: Vec<u8> = vec![];
464        loop {
465            match self.lexer.next() {
466                Some(Ok(Token::RightCurly)) => break,
467                Some(_) => code.push(self.lexer.slice().as_bytes()[0]),
468                None => return Err(Error::unexpected_eoi(self.lexer.span().start)),
469            }
470        }
471
472        Ok(Stmt::BfFunctio {
473            ident,
474            tape_len,
475            code,
476        })
477    }
478
479    /// Parse functio call flow
480    fn functio_call_flow(&mut self, expr: Spanned<Expr>) -> Result<Stmt, Error> {
481        let mut args = vec![];
482        let mut buf = None;
483        loop {
484            match self.checked_next()? {
485                // End of argument list
486                Token::RightParen => {
487                    if let Some(expr) = buf.take() {
488                        args.push(expr)
489                    }
490                    break;
491                }
492
493                // Next argument
494                Token::Comma => match buf.take() {
495                    Some(expr) => args.push(expr),
496                    // Comma alone
497                    None => {
498                        return Err(Error::new(
499                            ErrorKind::UnexpectedToken(Token::Comma),
500                            self.lexer.span(),
501                        ))
502                    }
503                },
504                t => buf = Some(self.parse_expr(t, &mut buf)?),
505            }
506        }
507
508        self.require(Token::Semicolon)?;
509        Ok(Stmt::Call { expr, args })
510    }
511
512    /// Parse assignment to assignable
513    fn assignment_flow(&mut self, value: Spanned<Expr>) -> Result<Stmt, Error> {
514        let ident = self.get_ident()?;
515        let kind = match self.checked_next()? {
516            Token::Semicolon => AssignableKind::Variable,
517            Token::LeftBracket => {
518                let mut indices = vec![];
519                loop {
520                    indices.push(self.expr_flow(Token::RightBracket)?);
521                    match self.checked_next()? {
522                        Token::Semicolon => break AssignableKind::Index { indices },
523                        Token::LeftBracket => (),
524                        t => {
525                            return Err(Error::new(
526                                ErrorKind::UnexpectedToken(t),
527                                self.lexer.span(),
528                            ))
529                        }
530                    }
531                }
532            }
533            t => return Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())),
534        };
535
536        Ok(Stmt::Assign {
537            assignable: Assignable { ident, kind },
538            value,
539        })
540    }
541
542    /// Parse Melo flow
543    fn melo_flow(&mut self) -> Result<Stmt, Error> {
544        let ident = self.get_ident()?;
545        self.semicolon_terminated(Stmt::Melo(ident))
546    }
547
548    /// Perform lang -> script substitution if in T-Dark block
549    fn tdark_subst(&self, mut string: String) -> String {
550        if self.tdark {
551            if let Some(pos) = string.to_lowercase().find("lang") {
552                let range = pos..pos + 4;
553                let mut count_upper = 0_u8;
554                string.replace_range(
555                    range.clone(),
556                    &(string[range]
557                        .chars()
558                        .zip("scri".chars())
559                        .map(|(lc, sc)| {
560                            if lc.is_uppercase() {
561                                count_upper += 1;
562                                sc.to_ascii_uppercase()
563                            } else {
564                                sc.to_ascii_lowercase()
565                            }
566                        })
567                        .collect::<String>()
568                        + match count_upper {
569                            0 | 1 => "pt",
570                            2 if rand::random() => "Pt",
571                            2 => "pT",
572                            _ => "PT",
573                        }),
574                )
575            }
576        }
577
578        string
579    }
580}
581
582/// Parse AbleScript code into AST
583pub fn parse(source: &str) -> Result<Block, Error> {
584    Parser::new(source).parse()
585}
586
587#[cfg(test)]
588mod tests {
589    use super::*;
590
591    #[test]
592    fn simple_math() {
593        let code = "1 * (num + 3) / 666 print;";
594        let expected = &[Spanned {
595            item: Stmt::Print {
596                expr: Spanned {
597                    item: Expr::BinOp {
598                        lhs: Box::new(Spanned {
599                            item: Expr::BinOp {
600                                lhs: Box::new(Spanned {
601                                    item: Expr::Literal(Literal::Int(1)),
602                                    span: 0..1,
603                                }),
604                                rhs: Box::new(Spanned {
605                                    item: Expr::BinOp {
606                                        lhs: Box::new(Spanned {
607                                            item: Expr::Variable("num".to_owned()),
608                                            span: 5..6,
609                                        }),
610                                        rhs: Box::new(Spanned {
611                                            item: Expr::Literal(Literal::Int(3)),
612                                            span: 9..10,
613                                        }),
614                                        kind: BinOpKind::Add,
615                                    },
616                                    span: 5..10,
617                                }),
618                                kind: BinOpKind::Multiply,
619                            },
620                            span: 0..11,
621                        }),
622                        rhs: Box::new(Spanned {
623                            item: Expr::Literal(Literal::Int(666)),
624                            span: 14..17,
625                        }),
626                        kind: BinOpKind::Divide,
627                    },
628                    span: 0..17,
629                },
630                newline: true,
631            },
632            span: 0..24,
633        }];
634
635        let ast = Parser::new(code).parse().unwrap();
636        assert_eq!(ast, expected);
637    }
638
639    #[test]
640    fn variable_declaration() {
641        let code = "var dim 42;";
642        let expected = &[Spanned {
643            item: Stmt::Dim {
644                ident: Spanned {
645                    item: "var".to_owned(),
646                    span: 0..3,
647                },
648                init: Some(Spanned {
649                    item: Expr::Literal(Literal::Int(42)),
650                    span: 4..6,
651                }),
652            },
653            span: 0..11,
654        }];
655
656        let ast = Parser::new(code).parse().unwrap();
657        assert_eq!(ast, expected);
658    }
659
660    #[test]
661    fn unless_flow() {
662        let code = "unless (never + never) { /*Buy Able products!*/ print; }";
663        let expected = &[Spanned {
664            item: Stmt::Unless {
665                cond: Spanned {
666                    item: Expr::BinOp {
667                        lhs: Box::new(Spanned {
668                            item: Expr::Variable("never".to_owned()),
669                            span: 8..13,
670                        }),
671                        rhs: Box::new(Spanned {
672                            item: Expr::Variable("never".to_owned()),
673                            span: 16..21,
674                        }),
675                        kind: BinOpKind::Add,
676                    },
677                    span: 8..21,
678                },
679                body: vec![Spanned {
680                    item: Stmt::Print {
681                        expr: Spanned {
682                            item: Expr::Literal(Literal::Str("Buy Able products!".to_owned())),
683                            span: 25..47,
684                        },
685                        newline: true,
686                    },
687                    span: 25..54,
688                }],
689            },
690            span: 0..56,
691        }];
692
693        let ast = Parser::new(code).parse().unwrap();
694        assert_eq!(ast, expected);
695    }
696
697    #[test]
698    fn tdark() {
699        let code = "T-Dark { lang dim /*lang*/ + lang; }";
700        let expected = &[Spanned {
701            item: Stmt::Dim {
702                ident: Spanned {
703                    item: "script".to_owned(),
704                    span: 9..15,
705                },
706                init: Some(Spanned {
707                    item: Expr::BinOp {
708                        lhs: Box::new(Spanned {
709                            item: Expr::Literal(Literal::Str("script".to_owned())),
710                            span: 20..26,
711                        }),
712                        rhs: Box::new(Spanned {
713                            item: Expr::Variable("script".to_owned()),
714                            span: 29..33,
715                        }),
716                        kind: BinOpKind::Add,
717                    },
718                    span: 20..33,
719                }),
720            },
721            span: 9..34,
722        }];
723
724        let ast = Parser::new(code).parse().unwrap();
725        assert_eq!(ast, expected);
726    }
727
728    #[test]
729    fn cart_construction() {
730        let code = "[/*able*/ <= 1, /*script*/ <= 3 - 1] print;";
731        let expected = &[Spanned {
732            item: Stmt::Print {
733                expr: Spanned {
734                    item: Expr::Cart(vec![
735                        (
736                            Spanned {
737                                item: Expr::Literal(Literal::Str("able".to_owned())),
738                                span: 1..7,
739                            },
740                            Spanned {
741                                item: Expr::Literal(Literal::Int(1)),
742                                span: 11..12,
743                            },
744                        ),
745                        (
746                            Spanned {
747                                item: Expr::Literal(Literal::Str("script".to_owned())),
748                                span: 14..22,
749                            },
750                            Spanned {
751                                item: Expr::BinOp {
752                                    kind: BinOpKind::Subtract,
753                                    lhs: Box::new(Spanned {
754                                        item: Expr::Literal(Literal::Int(3)),
755                                        span: 26..27,
756                                    }),
757                                    rhs: Box::new(Spanned {
758                                        item: Expr::Literal(Literal::Int(1)),
759                                        span: 30..31,
760                                    }),
761                                },
762                                span: 26..31,
763                            },
764                        ),
765                    ]),
766                    span: 0..32,
767                },
768                newline: true,
769            },
770            span: 0..39,
771        }];
772
773        let ast = Parser::new(code).parse().unwrap();
774        assert_eq!(ast, expected);
775    }
776
777    #[test]
778    fn cart_index() {
779        let code = "[/*able*/ <= /*ablecorp*/][/*ablecorp*/] print;";
780        let expected = &[Spanned {
781            item: Stmt::Print {
782                expr: Spanned {
783                    item: Expr::Index {
784                        expr: Box::new(Spanned {
785                            item: Expr::Cart(vec![(
786                                Spanned {
787                                    item: Expr::Literal(Literal::Str("able".to_owned())),
788                                    span: 1..7,
789                                },
790                                Spanned {
791                                    item: Expr::Literal(Literal::Str("ablecorp".to_owned())),
792                                    span: 11..21,
793                                },
794                            )]),
795                            span: 0..22,
796                        }),
797                        index: Box::new(Spanned {
798                            item: Expr::Literal(Literal::Str("ablecorp".to_owned())),
799                            span: 23..33,
800                        }),
801                    },
802                    span: 0..34,
803                },
804                newline: true,
805            },
806            span: 0..41,
807        }];
808
809        let ast = Parser::new(code).parse().unwrap();
810        assert_eq!(ast, expected);
811    }
812}