boa/syntax/parser/statement/declaration/
mod.rs

1//! Declaration parsing.
2//!
3//! More information:
4//!  - [MDN documentation][mdn]
5//!  - [ECMAScript specification][spec]
6//!
7//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements#Declarations
8//! [spec]:https://tc39.es/ecma262/#sec-declarations-and-the-variable-statement
9
10mod hoistable;
11mod lexical;
12#[cfg(test)]
13mod tests;
14
15use self::{hoistable::HoistableDeclaration, lexical::LexicalDeclaration};
16
17use crate::syntax::lexer::TokenKind;
18use crate::{
19    syntax::{
20        ast::{Keyword, Node},
21        parser::{AllowAwait, AllowYield, Cursor, ParseError, TokenParser},
22    },
23    BoaProfiler,
24};
25
26use std::io::Read;
27
28/// Parses a declaration.
29///
30/// More information:
31///  - [ECMAScript specification][spec]
32///
33/// [spec]: https://tc39.es/ecma262/#prod-Declaration
34#[derive(Debug, Clone, Copy)]
35pub(super) struct Declaration {
36    allow_yield: AllowYield,
37    allow_await: AllowAwait,
38    const_init_required: bool,
39}
40
41impl Declaration {
42    pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A, const_init_required: bool) -> Self
43    where
44        Y: Into<AllowYield>,
45        A: Into<AllowAwait>,
46    {
47        Self {
48            allow_yield: allow_yield.into(),
49            allow_await: allow_await.into(),
50            const_init_required,
51        }
52    }
53}
54
55impl<R> TokenParser<R> for Declaration
56where
57    R: Read,
58{
59    type Output = Node;
60
61    fn parse(self, cursor: &mut Cursor<R>) -> Result<Self::Output, ParseError> {
62        let _timer = BoaProfiler::global().start_event("Declaration", "Parsing");
63        let tok = cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?;
64
65        match tok.kind() {
66            TokenKind::Keyword(Keyword::Function) | TokenKind::Keyword(Keyword::Async) => {
67                HoistableDeclaration::new(self.allow_yield, self.allow_await, false).parse(cursor)
68            }
69            TokenKind::Keyword(Keyword::Const) | TokenKind::Keyword(Keyword::Let) => {
70                LexicalDeclaration::new(
71                    true,
72                    self.allow_yield,
73                    self.allow_await,
74                    self.const_init_required,
75                )
76                .parse(cursor)
77            }
78            _ => unreachable!("unknown token found: {:?}", tok),
79        }
80    }
81}