Skip to content

Commit

Permalink
Divided function parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Razican committed Apr 18, 2020
1 parent f96f3c9 commit e5072b3
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 92 deletions.
68 changes: 68 additions & 0 deletions boa/src/syntax/parser/function/arrow_function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! Arrow function parsing.
//!
//! More information:
//! - [MDN documentation][mdn]
//! - [ECMAScript specification][spec]
//!
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
//! [spec]: https://tc39.es/ecma262/#sec-arrow-function-definitions

use super::read_formal_parameters;
use crate::syntax::{
ast::{
node::{FormalParameter, Node},
punc::Punctuator,
token::TokenKind,
},
parser::{read_statements, AssignmentExpression, Cursor, ParseError, ParseResult, TokenParser},
};

/// Arrow function parsing.
///
/// More information:
/// - [MDN documentation][mdn]
/// - [ECMAScript specification][spec]
///
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
/// [spec]: https://tc39.es/ecma262/#prod-ArrowFunction
#[derive(Debug, Clone, Copy)]
pub(in crate::syntax::parser) struct ArrowFunction;

impl TokenParser for ArrowFunction {
fn parse(cursor: &mut Cursor<'_>) -> ParseResult {
let next_token = cursor.next().ok_or(ParseError::AbruptEnd)?;
let params = match &next_token.kind {
TokenKind::Punctuator(Punctuator::OpenParen) => read_formal_parameters(cursor)?,
TokenKind::Identifier(param_name) => vec![FormalParameter {
init: None,
name: param_name.clone(),
is_rest_param: false,
}],
_ => {
return Err(ParseError::Expected(
vec![
TokenKind::Punctuator(Punctuator::OpenParen),
TokenKind::identifier("identifier"),
],
next_token.clone(),
"arrow function",
))
}
};

cursor.expect_punc(Punctuator::Arrow, "arrow function")?;

cursor.skip(|tk| tk.kind == TokenKind::LineTerminator);
let body = match cursor.peek(0) {
Some(tk) if tk.kind == TokenKind::Punctuator(Punctuator::OpenBlock) => {
let _ = cursor.next();
let body = read_statements(cursor, true).map(Node::StatementList)?;
cursor.expect_punc(Punctuator::CloseBlock, "arrow function")?;
body
}
_ => Node::return_node(AssignmentExpression::parse(cursor)?),
};

Ok(Node::arrow_function_decl(params, body))
}
}
53 changes: 53 additions & 0 deletions boa/src/syntax/parser/function/function_definition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//! Function definition parsing.
//!
//! More information:
//! - [MDN documentation][mdn]
//! - [ECMAScript specification][spec]
//!
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function
//! [spec]: https://tc39.es/ecma262/#sec-function-definitions

use super::read_formal_parameters;
use crate::syntax::{
ast::{node::Node, punc::Punctuator, token::TokenKind},
parser::{read_statements, Cursor, ParseError, ParseResult, TokenParser},
};

/// Function expression parsing.
///
/// More information:
/// - [MDN documentation][mdn]
/// - [ECMAScript specification][spec]
///
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function
/// [spec]: https://tc39.es/ecma262/#prod-FunctionExpression
#[derive(Debug, Clone, Copy)]
pub(in crate::syntax::parser) struct FunctionExpression;

impl TokenParser for FunctionExpression {
fn parse(cursor: &mut Cursor<'_>) -> ParseResult {
let name = if let TokenKind::Identifier(name) =
&cursor.peek(0).ok_or(ParseError::AbruptEnd)?.kind
{
Some(name)
} else {
None
};
if name.is_some() {
// We move the cursor forward.
let _ = cursor.next().expect("nex token disappeared");
}

cursor.expect_punc(Punctuator::OpenParen, "function expression")?;

let params = read_formal_parameters(cursor)?;

cursor.expect_punc(Punctuator::OpenBlock, "function expression")?;

let body = read_statements(cursor, true).map(Node::StatementList)?;

cursor.expect_punc(Punctuator::CloseBlock, "function expression")?;

Ok(Node::function_decl::<_, &String, _, _>(name, params, body))
}
}
99 changes: 7 additions & 92 deletions boa/src/syntax/parser/function/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Function parsing.
//! Functions and classes parsing.
//!
//! More information:
//! - [MDN documentation][mdn]
Expand All @@ -7,62 +7,16 @@
//! [mdn]: https://developer.mozilla.org/en-US/docs/Glossary/Function
//! [spec]: https://tc39.es/ecma262/#sec-ecmascript-language-functions-and-classes

use super::{read_statements, AssignmentExpression, Cursor, ParseError, ParseResult, TokenParser};
mod arrow_function;
mod function_definition;

use super::{Cursor, ParseError};
use crate::syntax::ast::{
node::{FormalParameter, FormalParameters, Node},
node::{FormalParameter, FormalParameters},
punc::Punctuator,
token::TokenKind,
};

/// Arrow function parsing.
///
/// More information:
/// - [MDN documentation][mdn]
/// - [ECMAScript specification][spec]
///
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
/// [spec]: https://tc39.es/ecma262/#sec-arrow-function-definitions
#[derive(Debug, Clone, Copy)]
pub(super) struct ArrowFunction;

impl TokenParser for ArrowFunction {
fn parse(cursor: &mut Cursor<'_>) -> ParseResult {
let next_token = cursor.next().ok_or(ParseError::AbruptEnd)?;
let params = match &next_token.kind {
TokenKind::Punctuator(Punctuator::OpenParen) => read_formal_parameters(cursor)?,
TokenKind::Identifier(param_name) => vec![FormalParameter {
init: None,
name: param_name.clone(),
is_rest_param: false,
}],
_ => {
return Err(ParseError::Expected(
vec![
TokenKind::Punctuator(Punctuator::OpenParen),
TokenKind::identifier("identifier"),
],
next_token.clone(),
"arrow function",
))
}
};

cursor.expect_punc(Punctuator::Arrow, "arrow function")?;

cursor.skip(|tk| tk.kind == TokenKind::LineTerminator);
let body = match cursor.peek(0) {
Some(tk) if tk.kind == TokenKind::Punctuator(Punctuator::OpenBlock) => {
let _ = cursor.next();
let body = read_statements(cursor, true).map(Node::StatementList)?;
cursor.expect_punc(Punctuator::CloseBlock, "arrow function")?;
body
}
_ => Node::return_node(AssignmentExpression::parse(cursor)?),
};

Ok(Node::arrow_function_decl(params, body))
}
}
pub(super) use {arrow_function::ArrowFunction, function_definition::FunctionExpression};

/// Formal parameters parsing.
///
Expand Down Expand Up @@ -172,42 +126,3 @@ fn read_formal_parameter(cursor: &mut Cursor<'_>) -> Result<FormalParameter, Par
// TODO: Implement initializer.
Ok(FormalParameter::new(name, None, false))
}

/// Function expression parsing.
///
/// More information:
/// - [MDN documentation][mdn]
/// - [ECMAScript specification][spec]
///
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function
/// [spec]: https://tc39.es/ecma262/#prod-FunctionExpression
#[derive(Debug, Clone, Copy)]
pub(super) struct FunctionExpression;

impl TokenParser for FunctionExpression {
fn parse(cursor: &mut Cursor<'_>) -> ParseResult {
let name = if let TokenKind::Identifier(name) =
&cursor.peek(0).ok_or(ParseError::AbruptEnd)?.kind
{
Some(name)
} else {
None
};
if name.is_some() {
// We move the cursor forward.
let _ = cursor.next().expect("nex token disappeared");
}

cursor.expect_punc(Punctuator::OpenParen, "function expression")?;

let params = read_formal_parameters(cursor)?;

cursor.expect_punc(Punctuator::OpenBlock, "function expression")?;

let body = read_statements(cursor, true).map(Node::StatementList)?;

cursor.expect_punc(Punctuator::CloseBlock, "function expression")?;

Ok(Node::function_decl::<_, &String, _, _>(name, params, body))
}
}

0 comments on commit e5072b3

Please sign in to comment.