Skip to content

Commit

Permalink
Continued with expot parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Razican committed Nov 26, 2022
1 parent 0eb350f commit a5698d1
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 72 deletions.
39 changes: 36 additions & 3 deletions boa_ast/src/declaration/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
//! This module contains `export` declaration AST nodes.
//!
//! More information:
//! - [MDN documentation][mdn]
//! - [MDN documentation][mdn]
//! - [ECMAScript specification][spec]
//!
//! [spec]: https://tc39.es/ecma262/#sec-exports
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
use super::FromClause;
use crate::{
function::{AsyncFunction, AsyncGenerator, Class, Function, Generator},
Declaration, Expression, Statement,
};
use boa_interner::Sym;

/// An export declaration AST node.
Expand All @@ -17,10 +22,38 @@ use boa_interner::Sym;
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-ExportDeclaration
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub enum ExportDeclaration {
/// Re-export all exports.
ReExportAll {
/// Alias for the module export.
alias: Option<Sym>,
/// From clause.
from: FromClause,
},
/// List of exports.
ExportList,
List {
/// List of exports.
list: Box<[ExportSpecifier]>,
/// From clause.
from: Option<FromClause>,
},
/// Variable statement export.
VarStatement(Statement),
/// Declaration export.
Declaration(Declaration),
/// Default function export.
DefaultFunction(Function),
/// Default generator export.
DefaultGenerator(Generator),
/// Default async function export.
DefaultAsyncFunction(AsyncFunction),
/// Default async generator export.
DefaultAsyncGenerator(AsyncGenerator),
/// Default class declaration export.
DefaultClassDeclaration(Class),
/// Default assignment expression export.
DefaultAssignmentExpression(Expression),
}

/// Export specifier
Expand Down
39 changes: 5 additions & 34 deletions boa_ast/src/declaration/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use crate::expression::Identifier;
use boa_interner::Sym;

use super::FromClause;

/// An import declaration AST node.
///
/// More information:
Expand All @@ -34,7 +36,7 @@ pub enum ImportDeclaration {
},
/// Import list (`import { export1, export2 as alias2} from "module-name"`), with an optional
/// default export binding.
ImportList {
List {
/// Optional default export for the import list.
default_export: Option<Identifier>,
/// List of imports.
Expand Down Expand Up @@ -64,16 +66,12 @@ impl ImportDeclaration {

/// Creates a new namespace import declaration.
#[inline]
pub fn import_list<L, F>(
default_export: Option<Identifier>,
import_list: L,
from_clause: F,
) -> Self
pub fn list<L, F>(default_export: Option<Identifier>, import_list: L, from_clause: F) -> Self
where
L: Into<Box<[ImportSpecifier]>>,
F: Into<FromClause>,
{
Self::ImportList {
Self::List {
default_export,
import_list: import_list.into(),
from_clause: from_clause.into(),
Expand Down Expand Up @@ -115,30 +113,3 @@ impl ImportSpecifier {
self.alias
}
}

/// From clause AST node.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-FromClause
#[derive(Debug, Clone, Copy)]
pub struct FromClause {
module: Sym,
}

impl FromClause {
/// Gets the module specifier for the from clause.
#[inline]
#[must_use]
pub const fn module(self) -> Sym {
self.module
}
}

impl From<Sym> for FromClause {
#[inline]
fn from(s: Sym) -> Self {
Self { module: s }
}
}
29 changes: 28 additions & 1 deletion boa_ast/src/declaration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//! [diff]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements#difference_between_statements_and_declarations
use super::function::{AsyncFunction, AsyncGenerator, Class, Function, Generator};
use boa_interner::{Interner, ToIndentedString, ToInternedString};
use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};
use core::ops::ControlFlow;

mod export;
Expand Down Expand Up @@ -99,3 +99,30 @@ impl VisitWith for Declaration {
}
}
}

/// From clause AST node.
///
/// More information:
/// - [ECMAScript specification][spec]
///
/// [spec]: https://tc39.es/ecma262/#prod-FromClause
#[derive(Debug, Clone, Copy)]
pub struct FromClause {
module: Sym,
}

impl FromClause {
/// Gets the module specifier for the from clause.
#[inline]
#[must_use]
pub const fn module(self) -> Sym {
self.module
}
}

impl From<Sym> for FromClause {
#[inline]
fn from(s: Sym) -> Self {
Self { module: s }
}
}
60 changes: 52 additions & 8 deletions boa_parser/src/parser/statement/declaration/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use boa_interner::{Interner, Sym};
use boa_profiler::Profiler;
use std::io::Read;

use super::FromClause;

/// Parses an export declaration.
///
/// More information:
Expand All @@ -39,19 +41,47 @@ where

fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("ExportDeclaration", "Parsing");

cursor.expect((Keyword::Export, false), "export declaration", interner)?;

let tok = cursor.peek(0, interner).or_abrupt()?;

let export_clause = match tok.kind() {
let export_clause: Self::Output = match tok.kind() {
TokenKind::Punctuator(Punctuator::Mul) => {
cursor.advance(interner);

let next = cursor.peek(0, interner).or_abrupt()?;

match next.kind() {
TokenKind::IdentifierName(Sym::AS) => todo!("parse alias, then from"),
TokenKind::IdentifierName(Sym::FROM) => todo!("parse from"),
TokenKind::IdentifierName(Sym::AS) => {
cursor.advance(interner);
let tok = cursor.next(interner).or_abrupt()?;

let alias = match tok.kind() {
TokenKind::StringLiteral(export_name)
| TokenKind::IdentifierName(export_name) => *export_name,
_ => {
return Err(Error::expected(
["identifier".to_owned(), "string literal".to_owned()],
tok.to_string(interner),
tok.span(),
"export declaration",
))
}
};

let from = FromClause::new("export declaration").parse(cursor, interner)?;

boa_ast::declaration::ExportDeclaration::ReExportAll {
alias: Some(alias),
from,
}
}
TokenKind::IdentifierName(Sym::FROM) => {
let from = FromClause::new("export declaration").parse(cursor, interner)?;

boa_ast::declaration::ExportDeclaration::ReExportAll { alias: None, from }
}
_ => {
return Err(Error::expected(
["as".to_owned(), "from".to_owned()],
Expand All @@ -64,28 +94,42 @@ where
}
TokenKind::Punctuator(Punctuator::OpenBlock) => {
let list = NamedExports.parse(cursor, interner)?;
todo!("check if there is a from clause")

let next = cursor.peek(0, interner).or_abrupt()?;

if let TokenKind::IdentifierName(Sym::FROM) = next.kind() {
let from = FromClause::new("export declaration").parse(cursor, interner)?;
boa_ast::declaration::ExportDeclaration::List {
list,
from: Some(from),
}
} else {
boa_ast::declaration::ExportDeclaration::List { list, from: None }
}
}
TokenKind::Keyword((Keyword::Var, _)) => VariableStatement::new(false, true)
.parse(cursor, interner)
.map(|s| todo!("variable declaration export"))?,
.map(boa_ast::declaration::ExportDeclaration::VarStatement)?,
TokenKind::Keyword((Keyword::Default, _)) => {
cursor.advance(interner);

let tok = cursor.peek(0, interner).or_abrupt()?;

match tok.kind() {
TokenKind::Keyword((Keyword::Class, _)) => {
let _ = ClassDeclaration::new(false, true, true).parse(cursor, interner)?;
let class_declaration =
ClassDeclaration::new(false, true, true).parse(cursor, interner)?;
todo!("Class")
}
_ => todo!("default export parsing"),
}
}
_ => {}
_ => {
todo!()
}
};

todo!("ExportDeclaration parsing")
Ok(export_clause)
}
}

Expand Down
35 changes: 10 additions & 25 deletions boa_parser/src/parser/statement/declaration/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use crate::{
lexer::TokenKind,
parser::{
cursor::Cursor, statement::BindingIdentifier, Error, OrAbrupt, ParseResult, TokenParser,
cursor::Cursor,
statement::{declaration::FromClause, BindingIdentifier},
Error, OrAbrupt, ParseResult, TokenParser,
},
};
use boa_ast::{expression::Identifier, Keyword, Punctuator};
Expand Down Expand Up @@ -112,29 +114,9 @@ where
}
};

let from_tok = cursor.next(interner).or_abrupt()?;
if from_tok.kind() != &TokenKind::IdentifierName(Sym::FROM) {
return Err(Error::expected(
["from".to_owned()],
from_tok.to_string(interner),
from_tok.span(),
"import declaration",
));
}
let module_identifier = FromClause::new("import declaration").parse(cursor, interner)?;

let module_identifier_tok = cursor.next(interner).or_abrupt()?;
match module_identifier_tok.kind() {
TokenKind::StringLiteral(module_identifier) => {
cursor.expect_semicolon("import declaration", interner)?;
Ok(import_clause.add_from(*module_identifier))
}
_ => Err(Error::expected(
["string literal".to_owned()],
module_identifier_tok.to_string(interner),
module_identifier_tok.span(),
"import declaration",
)),
}
Ok(import_clause.add_from(module_identifier))
}
}

Expand Down Expand Up @@ -237,13 +219,16 @@ enum ImportClause {

impl ImportClause {
#[inline]
fn add_from(self, from_clause: Sym) -> boa_ast::declaration::ImportDeclaration {
fn add_from(
self,
from_clause: boa_ast::declaration::FromClause,
) -> boa_ast::declaration::ImportDeclaration {
match self {
Self::Namespace(default, alias) => {
boa_ast::declaration::ImportDeclaration::namespace(default, alias, from_clause)
}
Self::ImportList(default, list) => {
boa_ast::declaration::ImportDeclaration::import_list(default, list, from_clause)
boa_ast::declaration::ImportDeclaration::list(default, list, from_clause)
}
}
}
Expand Down
Loading

0 comments on commit a5698d1

Please sign in to comment.