mirror of https://github.com/boa-dev/boa.git
Browse Source
* Fix catch parsing - move the cursor to next token * Refactor catch and finally parsing into separate modules * Refactor catchparam parsing into separate module and add more tests * Refactoring - use ? instead of matchpull/397/head
abhi
5 years ago
committed by
GitHub
4 changed files with 289 additions and 27 deletions
@ -0,0 +1,99 @@
|
||||
use crate::syntax::{ |
||||
ast::{keyword::Keyword, node::Node, punc::Punctuator}, |
||||
parser::{ |
||||
statement::{block::Block, BindingIdentifier}, |
||||
AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser, |
||||
}, |
||||
}; |
||||
|
||||
/// Catch parsing
|
||||
///
|
||||
/// More information:
|
||||
/// - [MDN documentation][mdn]
|
||||
/// - [ECMAScript specification][spec]
|
||||
///
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-Catch
|
||||
#[derive(Debug, Clone, Copy)] |
||||
pub(super) struct Catch { |
||||
allow_yield: AllowYield, |
||||
allow_await: AllowAwait, |
||||
allow_return: AllowReturn, |
||||
} |
||||
|
||||
impl Catch { |
||||
/// Creates a new `Catch` block parser.
|
||||
pub(super) fn new<Y, A, R>(allow_yield: Y, allow_await: A, allow_return: R) -> Self |
||||
where |
||||
Y: Into<AllowYield>, |
||||
A: Into<AllowAwait>, |
||||
R: Into<AllowReturn>, |
||||
{ |
||||
Self { |
||||
allow_yield: allow_yield.into(), |
||||
allow_await: allow_await.into(), |
||||
allow_return: allow_return.into(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl TokenParser for Catch { |
||||
type Output = (Option<Node>, Option<Node>); |
||||
|
||||
fn parse(self, cursor: &mut Cursor<'_>) -> Result<Self::Output, ParseError> { |
||||
cursor.expect(Keyword::Catch, "try statement")?; |
||||
let catch_param = if cursor.next_if(Punctuator::OpenParen).is_some() { |
||||
let catch_param = |
||||
CatchParameter::new(self.allow_yield, self.allow_await).parse(cursor)?; |
||||
cursor.expect(Punctuator::CloseParen, "catch in try statement")?; |
||||
Some(catch_param) |
||||
} else { |
||||
None |
||||
}; |
||||
|
||||
// Catch block
|
||||
Ok(( |
||||
Some(Block::new(self.allow_yield, self.allow_await, self.allow_return).parse(cursor)?), |
||||
catch_param, |
||||
)) |
||||
} |
||||
} |
||||
|
||||
/// CatchParameter parsing
|
||||
///
|
||||
/// More information:
|
||||
/// - [MDN documentation][mdn]
|
||||
/// - [ECMAScript specification][spec]
|
||||
///
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-CatchParameter
|
||||
#[derive(Debug, Clone, Copy)] |
||||
pub(super) struct CatchParameter { |
||||
allow_yield: AllowYield, |
||||
allow_await: AllowAwait, |
||||
} |
||||
|
||||
impl CatchParameter { |
||||
/// Creates a new `CatchParameter` parser.
|
||||
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self |
||||
where |
||||
Y: Into<AllowYield>, |
||||
A: Into<AllowAwait>, |
||||
{ |
||||
Self { |
||||
allow_yield: allow_yield.into(), |
||||
allow_await: allow_await.into(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl TokenParser for CatchParameter { |
||||
type Output = Node; |
||||
|
||||
fn parse(self, cursor: &mut Cursor<'_>) -> ParseResult { |
||||
// TODO: should accept BindingPattern
|
||||
BindingIdentifier::new(self.allow_yield, self.allow_await) |
||||
.parse(cursor) |
||||
.map(Node::local) |
||||
} |
||||
} |
@ -0,0 +1,47 @@
|
||||
use crate::syntax::{ |
||||
ast::{keyword::Keyword, node::Node}, |
||||
parser::{ |
||||
statement::block::Block, AllowAwait, AllowReturn, AllowYield, Cursor, ParseResult, |
||||
TokenParser, |
||||
}, |
||||
}; |
||||
|
||||
/// Finally parsing
|
||||
///
|
||||
/// More information:
|
||||
/// - [MDN documentation][mdn]
|
||||
/// - [ECMAScript specification][spec]
|
||||
///
|
||||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
|
||||
/// [spec]: https://tc39.es/ecma262/#prod-Finally
|
||||
#[derive(Debug, Clone, Copy)] |
||||
pub(super) struct Finally { |
||||
allow_yield: AllowYield, |
||||
allow_await: AllowAwait, |
||||
allow_return: AllowReturn, |
||||
} |
||||
|
||||
impl Finally { |
||||
/// Creates a new `Finally` block parser.
|
||||
pub(super) fn new<Y, A, R>(allow_yield: Y, allow_await: A, allow_return: R) -> Self |
||||
where |
||||
Y: Into<AllowYield>, |
||||
A: Into<AllowAwait>, |
||||
R: Into<AllowReturn>, |
||||
{ |
||||
Self { |
||||
allow_yield: allow_yield.into(), |
||||
allow_await: allow_await.into(), |
||||
allow_return: allow_return.into(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl TokenParser for Finally { |
||||
type Output = Node; |
||||
|
||||
fn parse(self, cursor: &mut Cursor<'_>) -> ParseResult { |
||||
cursor.expect(Keyword::Finally, "try statement")?; |
||||
Ok(Block::new(self.allow_yield, self.allow_await, self.allow_return).parse(cursor)?) |
||||
} |
||||
} |
@ -1 +1,125 @@
|
||||
use crate::syntax::{ |
||||
ast::node::Node, |
||||
parser::tests::{check_invalid, check_parser}, |
||||
}; |
||||
|
||||
#[test] |
||||
fn check_inline_with_empty_try_catch() { |
||||
check_parser( |
||||
"try { } catch(e) {}", |
||||
vec![Node::try_node::<_, _, _, _, Node, Node, Node>( |
||||
Node::block(vec![]), |
||||
Node::block(vec![]), |
||||
Node::local("e"), |
||||
None, |
||||
)], |
||||
); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_with_var_decl_inside_try() { |
||||
check_parser( |
||||
"try { var x = 1; } catch(e) {}", |
||||
vec![Node::try_node::<_, _, _, _, Node, Node, Node>( |
||||
Node::block(vec![Node::var_decl(vec![( |
||||
String::from("x"), |
||||
Some(Node::const_node(1)), |
||||
)])]), |
||||
Node::block(vec![]), |
||||
Node::local("e"), |
||||
None, |
||||
)], |
||||
); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_with_var_decl_inside_catch() { |
||||
check_parser( |
||||
"try { var x = 1; } catch(e) { var x = 1; }", |
||||
vec![Node::try_node::<_, _, _, _, Node, Node, Node>( |
||||
Node::block(vec![Node::var_decl(vec![( |
||||
String::from("x"), |
||||
Some(Node::const_node(1)), |
||||
)])]), |
||||
Node::block(vec![Node::var_decl(vec![( |
||||
String::from("x"), |
||||
Some(Node::const_node(1)), |
||||
)])]), |
||||
Node::local("e"), |
||||
None, |
||||
)], |
||||
); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_with_empty_try_catch_finally() { |
||||
check_parser( |
||||
"try {} catch(e) {} finally {}", |
||||
vec![Node::try_node::<_, _, _, _, Node, Node, Node>( |
||||
Node::block(vec![]), |
||||
Node::block(vec![]), |
||||
Node::local("e"), |
||||
Node::block(vec![]), |
||||
)], |
||||
); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_with_empty_try_finally() { |
||||
check_parser( |
||||
"try {} finally {}", |
||||
vec![Node::try_node::<_, _, _, _, Node, Node, Node>( |
||||
Node::block(vec![]), |
||||
None, |
||||
None, |
||||
Node::block(vec![]), |
||||
)], |
||||
); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_with_empty_try_var_decl_in_finally() { |
||||
check_parser( |
||||
"try {} finally { var x = 1; }", |
||||
vec![Node::try_node::<_, _, _, _, Node, Node, Node>( |
||||
Node::block(vec![]), |
||||
None, |
||||
None, |
||||
Node::block(vec![Node::var_decl(vec![( |
||||
String::from("x"), |
||||
Some(Node::const_node(1)), |
||||
)])]), |
||||
)], |
||||
); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_empty_try_paramless_catch() { |
||||
check_parser( |
||||
"try {} catch { var x = 1; }", |
||||
vec![Node::try_node::<_, _, _, _, Node, Node, Node>( |
||||
Node::block(vec![]), |
||||
Node::block(vec![Node::var_decl(vec![( |
||||
String::from("x"), |
||||
Some(Node::const_node(1)), |
||||
)])]), |
||||
None, |
||||
None, |
||||
)], |
||||
); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_invalid_catch() { |
||||
check_invalid("try {} catch"); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_invalid_catch_without_closing_paren() { |
||||
check_invalid("try {} catch(e {}"); |
||||
} |
||||
|
||||
#[test] |
||||
fn check_inline_invalid_catch_parameter() { |
||||
check_invalid("try {} catch(1) {}"); |
||||
} |
||||
|
Loading…
Reference in new issue