From 9aa6c77b0e29b9dcbf89612e03fec6ae789b8d0f Mon Sep 17 00:00:00 2001 From: Paul Lancaster Date: Sat, 10 Oct 2020 12:40:05 +0100 Subject: [PATCH] Await expression parsing --- boa/src/syntax/ast/node/await_expr/mod.rs | 59 +++++++++++++++++++ boa/src/syntax/ast/node/mod.rs | 7 +++ .../syntax/parser/expression/await_expr.rs | 58 ++++++++++++++++++ boa/src/syntax/parser/expression/mod.rs | 2 + .../primary/object_initializer/mod.rs | 8 +++ boa/src/syntax/parser/expression/unary.rs | 4 +- boa/src/syntax/parser/statement/mod.rs | 4 ++ 7 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 boa/src/syntax/ast/node/await_expr/mod.rs create mode 100644 boa/src/syntax/parser/expression/await_expr.rs diff --git a/boa/src/syntax/ast/node/await_expr/mod.rs b/boa/src/syntax/ast/node/await_expr/mod.rs new file mode 100644 index 0000000000..2d8b3410e5 --- /dev/null +++ b/boa/src/syntax/ast/node/await_expr/mod.rs @@ -0,0 +1,59 @@ +//! Await expression node. + +use super::Node; +use crate::{exec::Executable, BoaProfiler, Context, Result, Value}; +use gc::{Finalize, Trace}; +use std::fmt; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +/// +/// +/// More information: +/// - [ECMAScript reference][spec] +/// - [MDN documentation][mdn] +/// +/// [spec]: +/// [mdn]: +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[derive(Clone, Debug, Trace, Finalize, PartialEq)] +pub struct AwaitExpr { + expr: Box, +} + +impl Executable for AwaitExpr { + fn run(&self, interpreter: &mut Context) -> Result { + let _timer = BoaProfiler::global().start_event("AwaitExpression", "exec"); + unimplemented!("Await expression execution"); + } +} + +impl AwaitExpr { + /// Implements the display formatting with indentation. + pub(super) fn display(&self, f: &mut fmt::Formatter<'_>, indentation: usize) -> fmt::Result { + writeln!(f, "await ")?; + self.expr.display(f, indentation) + } +} + +impl From for AwaitExpr +where + T: Into>, +{ + fn from(e: T) -> Self { + Self { expr: e.into() } + } +} + +impl fmt::Display for AwaitExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.display(f, 0) + } +} + +impl From for Node { + fn from(awaitexpr: AwaitExpr) -> Self { + Self::AwaitExpr(awaitexpr) + } +} diff --git a/boa/src/syntax/ast/node/mod.rs b/boa/src/syntax/ast/node/mod.rs index d65914c9e8..70515bf144 100644 --- a/boa/src/syntax/ast/node/mod.rs +++ b/boa/src/syntax/ast/node/mod.rs @@ -1,6 +1,7 @@ //! This module implements the `Node` structure, which composes the AST. pub mod array; +pub mod await_expr; pub mod block; pub mod break_node; pub mod call; @@ -21,6 +22,7 @@ pub mod try_node; pub use self::{ array::ArrayDecl, + await_expr::AwaitExpr, block::Block, break_node::Break, call::Call, @@ -71,6 +73,9 @@ pub enum Node { /// An async function expression node. [More information](./declaration/struct.AsyncFunctionExpr.html). AsyncFunctionExpr(AsyncFunctionExpr), + /// An await expression node. [More information](./await_expr/struct.AwaitExpression.html). + AwaitExpr(AwaitExpr), + /// A binary operator node. [More information](./operator/struct.BinOp.html). BinOp(BinOp), @@ -251,6 +256,7 @@ impl Node { Self::ConstDeclList(ref decl) => Display::fmt(decl, f), Self::AsyncFunctionDecl(ref decl) => decl.display(f, indentation), Self::AsyncFunctionExpr(ref expr) => expr.display(f, indentation), + Self::AwaitExpr(ref expr) => expr.display(f, indentation), } } } @@ -261,6 +267,7 @@ impl Executable for Node { match *self { Node::AsyncFunctionDecl(ref decl) => decl.run(interpreter), Node::AsyncFunctionExpr(ref function_expr) => function_expr.run(interpreter), + Node::AwaitExpr(ref expr) => expr.run(interpreter), Node::Call(ref call) => call.run(interpreter), Node::Const(Const::Null) => Ok(Value::null()), Node::Const(Const::Num(num)) => Ok(Value::rational(num)), diff --git a/boa/src/syntax/parser/expression/await_expr.rs b/boa/src/syntax/parser/expression/await_expr.rs new file mode 100644 index 0000000000..6dc5b41871 --- /dev/null +++ b/boa/src/syntax/parser/expression/await_expr.rs @@ -0,0 +1,58 @@ +//! Await expression parsing. +//! +//! More information: +//! - [MDN documentation][mdn] +//! - [ECMAScript specification][spec] +//! +//! [mdn]: +//! [spec]: + +use super::unary::UnaryExpression; + +use crate::syntax::{ + ast::{node::AwaitExpr, Keyword}, + lexer::TokenKind, + parser::{AllowYield, Cursor, ParseError, TokenParser}, +}; +use std::io::Read; + +/// Parses a await expression. +/// +/// More information: +/// - [MDN documentation][mdn] +/// - [ECMAScript specification][spec] +/// +/// [mdn]: +/// [spec]: +#[derive(Debug, Clone, Copy)] +pub(in crate::syntax::parser) struct AwaitExpression { + allow_yield: AllowYield, +} + +impl AwaitExpression { + /// Creates a new `AwaitExpression` parser. + pub(in crate::syntax::parser) fn new(allow_yield: Y) -> Self + where + Y: Into, + { + Self { + allow_yield: allow_yield.into(), + } + } +} + +impl TokenParser for AwaitExpression +where + R: Read, +{ + type Output = AwaitExpr; + + fn parse(self, cursor: &mut Cursor) -> Result { + cursor.expect( + TokenKind::Keyword(Keyword::Await), + "Await expression parsing", + )?; + let expr = UnaryExpression::new(self.allow_yield, true).parse(cursor)?; + Ok(expr.into()) + } +} diff --git a/boa/src/syntax/parser/expression/mod.rs b/boa/src/syntax/parser/expression/mod.rs index 66ef2a99de..68ff35d7d2 100644 --- a/boa/src/syntax/parser/expression/mod.rs +++ b/boa/src/syntax/parser/expression/mod.rs @@ -15,6 +15,8 @@ mod tests; mod unary; mod update; +pub(in crate::syntax::parser) mod await_expr; + use self::assignment::ExponentiationExpression; pub(super) use self::{assignment::AssignmentExpression, primary::Initializer}; use super::{AllowAwait, AllowIn, AllowYield, Cursor, ParseResult, TokenParser}; diff --git a/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs b/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs index 7ba38ac3ab..0294d1d0cc 100644 --- a/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs +++ b/boa/src/syntax/parser/expression/primary/object_initializer/mod.rs @@ -141,6 +141,14 @@ where return Ok(node::PropertyDefinition::property(prop_name, val)); } + // TODO GeneratorMethod + + if prop_name.as_str() == "async" { + // TODO - AsyncMethod. + + // TODO - AsyncGeneratorMethod + } + if cursor .next_if(TokenKind::Punctuator(Punctuator::OpenParen))? .is_some() diff --git a/boa/src/syntax/parser/expression/unary.rs b/boa/src/syntax/parser/expression/unary.rs index 6ed9f5378c..ac8da4227e 100644 --- a/boa/src/syntax/parser/expression/unary.rs +++ b/boa/src/syntax/parser/expression/unary.rs @@ -33,14 +33,14 @@ use std::io::Read; /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Unary /// [spec]: https://tc39.es/ecma262/#prod-UnaryExpression #[derive(Debug, Clone, Copy)] -pub(super) struct UnaryExpression { +pub(in crate::syntax::parser) struct UnaryExpression { allow_yield: AllowYield, allow_await: AllowAwait, } impl UnaryExpression { /// Creates a new `UnaryExpression` parser. - pub(super) fn new(allow_yield: Y, allow_await: A) -> Self + pub(in crate::syntax::parser) fn new(allow_yield: Y, allow_await: A) -> Self where Y: Into, A: Into, diff --git a/boa/src/syntax/parser/statement/mod.rs b/boa/src/syntax/parser/statement/mod.rs index 1fab174adf..757d642db9 100644 --- a/boa/src/syntax/parser/statement/mod.rs +++ b/boa/src/syntax/parser/statement/mod.rs @@ -42,6 +42,7 @@ use crate::{ syntax::{ ast::{node, Keyword, Node, Punctuator}, lexer::{Error as LexError, InputElement, TokenKind}, + parser::expression::await_expr::AwaitExpression, }, BoaProfiler, }; @@ -110,6 +111,9 @@ where let tok = cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?; match tok.kind() { + TokenKind::Keyword(Keyword::Await) => AwaitExpression::new(self.allow_yield) + .parse(cursor) + .map(Node::from), TokenKind::Keyword(Keyword::If) => { IfStatement::new(self.allow_yield, self.allow_await, self.allow_return) .parse(cursor)