Browse Source

Reduced boilerplate code in the parser (#2410)

This PR adds an `OrAbrupt` trait, with the `or_abrupt()` function. This function is equivalent to the previous `?.ok_or(ParseError::AbruptEnd)`, but it's cleaner. It's implemented for the parser cursor results types.

It also adds an `advance()` function to the parser cursor (which might be possible to optimize further), that just advances the cursor without returning any token. This shows a clearer intent in many places where it's being used.

I also used `ParseResult` in more places, since we were not using it in many places.
pull/2414/head
Iban Eguia Moraza 2 years ago
parent
commit
23f0335bf1
  1. 14
      boa_engine/src/syntax/parser/cursor/buffered_lexer/mod.rs
  2. 67
      boa_engine/src/syntax/parser/cursor/mod.rs
  3. 4
      boa_engine/src/syntax/parser/error.rs
  4. 13
      boa_engine/src/syntax/parser/expression/assignment/arrow_function.rs
  5. 12
      boa_engine/src/syntax/parser/expression/assignment/async_arrow_function.rs
  6. 2
      boa_engine/src/syntax/parser/expression/assignment/conditional.rs
  7. 7
      boa_engine/src/syntax/parser/expression/assignment/exponentiation.rs
  8. 44
      boa_engine/src/syntax/parser/expression/assignment/mod.rs
  9. 6
      boa_engine/src/syntax/parser/expression/assignment/yield.rs
  10. 8
      boa_engine/src/syntax/parser/expression/identifiers.rs
  11. 8
      boa_engine/src/syntax/parser/expression/left_hand_side/arguments.rs
  12. 10
      boa_engine/src/syntax/parser/expression/left_hand_side/call.rs
  13. 16
      boa_engine/src/syntax/parser/expression/left_hand_side/member.rs
  14. 2
      boa_engine/src/syntax/parser/expression/left_hand_side/mod.rs
  15. 12
      boa_engine/src/syntax/parser/expression/left_hand_side/optional/mod.rs
  16. 6
      boa_engine/src/syntax/parser/expression/left_hand_side/template.rs
  17. 30
      boa_engine/src/syntax/parser/expression/mod.rs
  18. 16
      boa_engine/src/syntax/parser/expression/primary/array_initializer/mod.rs
  19. 9
      boa_engine/src/syntax/parser/expression/primary/async_function_expression/mod.rs
  20. 8
      boa_engine/src/syntax/parser/expression/primary/async_generator_expression/mod.rs
  21. 4
      boa_engine/src/syntax/parser/expression/primary/class_expression/mod.rs
  22. 8
      boa_engine/src/syntax/parser/expression/primary/function_expression/mod.rs
  23. 8
      boa_engine/src/syntax/parser/expression/primary/generator_expression/mod.rs
  24. 74
      boa_engine/src/syntax/parser/expression/primary/mod.rs
  25. 79
      boa_engine/src/syntax/parser/expression/primary/object_initializer/mod.rs
  26. 24
      boa_engine/src/syntax/parser/expression/unary.rs
  27. 4
      boa_engine/src/syntax/parser/expression/update.rs
  28. 29
      boa_engine/src/syntax/parser/function/mod.rs
  29. 25
      boa_engine/src/syntax/parser/mod.rs
  30. 12
      boa_engine/src/syntax/parser/statement/block/mod.rs
  31. 2
      boa_engine/src/syntax/parser/statement/break_stm/mod.rs
  32. 4
      boa_engine/src/syntax/parser/statement/continue_stm/mod.rs
  33. 77
      boa_engine/src/syntax/parser/statement/declaration/hoistable/class_decl/mod.rs
  34. 13
      boa_engine/src/syntax/parser/statement/declaration/hoistable/mod.rs
  35. 12
      boa_engine/src/syntax/parser/statement/declaration/lexical.rs
  36. 4
      boa_engine/src/syntax/parser/statement/declaration/mod.rs
  37. 8
      boa_engine/src/syntax/parser/statement/expression/mod.rs
  38. 8
      boa_engine/src/syntax/parser/statement/if_stm/mod.rs
  39. 12
      boa_engine/src/syntax/parser/statement/iteration/do_while_statement.rs
  40. 37
      boa_engine/src/syntax/parser/statement/iteration/for_statement.rs
  41. 8
      boa_engine/src/syntax/parser/statement/iteration/while_statement.rs
  42. 4
      boa_engine/src/syntax/parser/statement/labelled_stm/mod.rs
  43. 47
      boa_engine/src/syntax/parser/statement/mod.rs
  44. 2
      boa_engine/src/syntax/parser/statement/return_stm/mod.rs
  45. 10
      boa_engine/src/syntax/parser/statement/switch/mod.rs
  46. 2
      boa_engine/src/syntax/parser/statement/throw/mod.rs
  47. 17
      boa_engine/src/syntax/parser/statement/try_stm/catch.rs
  48. 6
      boa_engine/src/syntax/parser/statement/try_stm/mod.rs
  49. 4
      boa_engine/src/syntax/parser/statement/variable/mod.rs

14
boa_engine/src/syntax/parser/cursor/buffered_lexer/mod.rs

@ -1,6 +1,6 @@
use crate::syntax::{ use crate::syntax::{
lexer::{InputElement, Lexer, Token, TokenKind}, lexer::{InputElement, Lexer, Token, TokenKind},
parser::error::ParseError, parser::{error::ParseError, ParseResult},
}; };
use boa_ast::Position; use boa_ast::Position;
use boa_interner::Interner; use boa_interner::Interner;
@ -83,7 +83,7 @@ where
&mut self, &mut self,
start: Position, start: Position,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Token, ParseError> { ) -> ParseResult<Token> {
let _timer = Profiler::global().start_event("cursor::lex_regex()", "Parsing"); let _timer = Profiler::global().start_event("cursor::lex_regex()", "Parsing");
self.set_goal(InputElement::RegExp); self.set_goal(InputElement::RegExp);
self.lexer self.lexer
@ -97,7 +97,7 @@ where
&mut self, &mut self,
start: Position, start: Position,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Token, ParseError> { ) -> ParseResult<Token> {
self.lexer self.lexer
.lex_template(start, interner) .lex_template(start, interner)
.map_err(ParseError::from) .map_err(ParseError::from)
@ -116,7 +116,7 @@ where
/// Fills the peeking buffer with the next token. /// Fills the peeking buffer with the next token.
/// ///
/// It will not fill two line terminators one after the other. /// It will not fill two line terminators one after the other.
fn fill(&mut self, interner: &mut Interner) -> Result<(), ParseError> { fn fill(&mut self, interner: &mut Interner) -> ParseResult<()> {
debug_assert!( debug_assert!(
self.write_index < PEEK_BUF_SIZE, self.write_index < PEEK_BUF_SIZE,
"write index went out of bounds" "write index went out of bounds"
@ -166,12 +166,12 @@ where
/// ///
/// This follows iterator semantics in that a `peek(0, false)` followed by a `next(false)` will /// This follows iterator semantics in that a `peek(0, false)` followed by a `next(false)` will
/// return the same value. Note that because a `peek(n, false)` may return a line terminator a /// return the same value. Note that because a `peek(n, false)` may return a line terminator a
// subsequent `next(true)` may not return the same value. /// subsequent `next(true)` may not return the same value.
pub(super) fn next( pub(super) fn next(
&mut self, &mut self,
skip_line_terminators: bool, skip_line_terminators: bool,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Option<Token>, ParseError> { ) -> ParseResult<Option<Token>> {
if self.read_index == self.write_index { if self.read_index == self.write_index {
self.fill(interner)?; self.fill(interner)?;
} }
@ -217,7 +217,7 @@ where
skip_n: usize, skip_n: usize,
skip_line_terminators: bool, skip_line_terminators: bool,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Option<&Token>, ParseError> { ) -> ParseResult<Option<&Token>> {
assert!( assert!(
skip_n <= MAX_PEEK_SKIP, skip_n <= MAX_PEEK_SKIP,
"you cannot skip more than {} elements", "you cannot skip more than {} elements",

67
boa_engine/src/syntax/parser/cursor/mod.rs

@ -1,7 +1,7 @@
//! Cursor implementation for the parser. //! Cursor implementation for the parser.
mod buffered_lexer; mod buffered_lexer;
use super::{statement::PrivateElement, ParseError}; use super::{statement::PrivateElement, OrAbrupt, ParseError, ParseResult};
use crate::syntax::lexer::{InputElement, Lexer, Token, TokenKind}; use crate::syntax::lexer::{InputElement, Lexer, Token, TokenKind};
use boa_ast::{Position, Punctuator}; use boa_ast::{Position, Punctuator};
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
@ -54,7 +54,7 @@ where
&mut self, &mut self,
start: Position, start: Position,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Token, ParseError> { ) -> ParseResult<Token> {
self.buffered_lexer.lex_regex(start, interner) self.buffered_lexer.lex_regex(start, interner)
} }
@ -63,35 +63,55 @@ where
&mut self, &mut self,
start: Position, start: Position,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Token, ParseError> { ) -> ParseResult<Token> {
self.buffered_lexer.lex_template(start, interner) self.buffered_lexer.lex_template(start, interner)
} }
/// Advances the cursor and returns the next token.
#[inline] #[inline]
pub(super) fn next(&mut self, interner: &mut Interner) -> Result<Option<Token>, ParseError> { pub(super) fn next(&mut self, interner: &mut Interner) -> ParseResult<Option<Token>> {
self.buffered_lexer.next(true, interner) self.buffered_lexer.next(true, interner)
} }
/// Advances the cursor without returning the next token.
///
/// # Panics
///
/// This function will panic if there is no further token in the cursor.
#[inline]
#[track_caller]
#[allow(clippy::let_underscore_drop)]
pub(super) fn advance(&mut self, interner: &mut Interner) {
let _ = self
.next(interner)
.expect("tried to advance cursor, but the buffer was empty");
}
/// Peeks a future token, without consuming it or advancing the cursor.
///
/// You can skip some tokens with the `skip_n` option.
#[inline] #[inline]
pub(super) fn peek( pub(super) fn peek(
&mut self, &mut self,
skip_n: usize, skip_n: usize,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Option<&Token>, ParseError> { ) -> ParseResult<Option<&Token>> {
self.buffered_lexer.peek(skip_n, true, interner) self.buffered_lexer.peek(skip_n, true, interner)
} }
/// Gets the current strict mode for the cursor.
#[inline] #[inline]
pub(super) fn strict_mode(&self) -> bool { pub(super) fn strict_mode(&self) -> bool {
self.buffered_lexer.strict_mode() self.buffered_lexer.strict_mode()
} }
/// Sets the strict mode to strict or non-strict.
#[inline] #[inline]
pub(super) fn set_strict_mode(&mut self, strict_mode: bool) { pub(super) fn set_strict_mode(&mut self, strict_mode: bool) {
self.buffered_lexer.set_strict_mode(strict_mode); self.buffered_lexer.set_strict_mode(strict_mode);
} }
/// Returns if the cursor is currently in a arrow function declaration. /// Returns if the cursor is currently in an arrow function declaration.
#[inline] #[inline]
pub(super) fn arrow(&self) -> bool { pub(super) fn arrow(&self) -> bool {
self.arrow self.arrow
@ -116,7 +136,7 @@ where
&mut self, &mut self,
identifier: Sym, identifier: Sym,
position: Position, position: Position,
) -> Result<(), ParseError> { ) -> ParseResult<()> {
if let Some(env) = self.private_environments_stack.last_mut() { if let Some(env) = self.private_environments_stack.last_mut() {
env.entry(identifier).or_insert(position); env.entry(identifier).or_insert(position);
Ok(()) Ok(())
@ -136,7 +156,7 @@ where
pub(super) fn pop_private_environment( pub(super) fn pop_private_environment(
&mut self, &mut self,
identifiers: &FxHashMap<Sym, PrivateElement>, identifiers: &FxHashMap<Sym, PrivateElement>,
) -> Result<(), ParseError> { ) -> ParseResult<()> {
let last = self let last = self
.private_environments_stack .private_environments_stack
.pop() .pop()
@ -163,11 +183,11 @@ where
kind: K, kind: K,
context: &'static str, context: &'static str,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Token, ParseError> ) -> ParseResult<Token>
where where
K: Into<TokenKind>, K: Into<TokenKind>,
{ {
let next_token = self.next(interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = self.next(interner).or_abrupt()?;
let kind = kind.into(); let kind = kind.into();
if next_token.kind() == &kind { if next_token.kind() == &kind {
@ -191,7 +211,7 @@ where
pub(super) fn peek_semicolon( pub(super) fn peek_semicolon(
&mut self, &mut self,
interner: &mut Interner, interner: &mut Interner,
) -> Result<SemicolonResult<'_>, ParseError> { ) -> ParseResult<SemicolonResult<'_>> {
match self.buffered_lexer.peek(0, false, interner)? { match self.buffered_lexer.peek(0, false, interner)? {
Some(tk) => match tk.kind() { Some(tk) => match tk.kind() {
TokenKind::Punctuator(Punctuator::Semicolon | Punctuator::CloseBlock) TokenKind::Punctuator(Punctuator::Semicolon | Punctuator::CloseBlock)
@ -212,7 +232,7 @@ where
&mut self, &mut self,
context: &'static str, context: &'static str,
interner: &mut Interner, interner: &mut Interner,
) -> Result<(), ParseError> { ) -> ParseResult<()> {
match self.peek_semicolon(interner)? { match self.peek_semicolon(interner)? {
SemicolonResult::Found(Some(tk)) => match *tk.kind() { SemicolonResult::Found(Some(tk)) => match *tk.kind() {
TokenKind::Punctuator(Punctuator::Semicolon) | TokenKind::LineTerminator => { TokenKind::Punctuator(Punctuator::Semicolon) | TokenKind::LineTerminator => {
@ -243,19 +263,20 @@ where
skip_n: usize, skip_n: usize,
context: &'static str, context: &'static str,
interner: &mut Interner, interner: &mut Interner,
) -> Result<&Token, ParseError> { ) -> ParseResult<&Token> {
if let Some(t) = self.buffered_lexer.peek(skip_n, false, interner)? { let tok = self
if t.kind() == &TokenKind::LineTerminator { .buffered_lexer
.peek(skip_n, false, interner)
.or_abrupt()?;
if tok.kind() == &TokenKind::LineTerminator {
Err(ParseError::unexpected( Err(ParseError::unexpected(
t.to_string(interner), tok.to_string(interner),
t.span(), tok.span(),
context, context,
)) ))
} else { } else {
Ok(t) Ok(tok)
}
} else {
Err(ParseError::AbruptEnd)
} }
} }
@ -265,7 +286,7 @@ where
&mut self, &mut self,
skip_n: usize, skip_n: usize,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Option<bool>, ParseError> { ) -> ParseResult<Option<bool>> {
if let Some(t) = self.buffered_lexer.peek(skip_n, false, interner)? { if let Some(t) = self.buffered_lexer.peek(skip_n, false, interner)? {
Ok(Some(t.kind() == &TokenKind::LineTerminator)) Ok(Some(t.kind() == &TokenKind::LineTerminator))
} else { } else {
@ -283,7 +304,7 @@ where
&mut self, &mut self,
kind: K, kind: K,
interner: &mut Interner, interner: &mut Interner,
) -> Result<Option<Token>, ParseError> ) -> ParseResult<Option<Token>>
where where
K: Into<TokenKind>, K: Into<TokenKind>,
{ {

4
boa_engine/src/syntax/parser/error.rs

@ -12,13 +12,15 @@ pub(crate) trait ErrorContext {
fn context(self, context: &'static str) -> Self; fn context(self, context: &'static str) -> Self;
} }
impl<T> ErrorContext for Result<T, ParseError> { impl<T> ErrorContext for ParseResult<T> {
#[inline]
fn context(self, context: &'static str) -> Self { fn context(self, context: &'static str) -> Self {
self.map_err(|e| e.context(context)) self.map_err(|e| e.context(context))
} }
} }
impl From<LexError> for ParseError { impl From<LexError> for ParseError {
#[inline]
fn from(e: LexError) -> Self { fn from(e: LexError) -> Self {
Self::lex(e) Self::lex(e)
} }

13
boa_engine/src/syntax/parser/expression/assignment/arrow_function.rs

@ -14,7 +14,8 @@ use crate::syntax::{
error::{ErrorContext, ParseError, ParseResult}, error::{ErrorContext, ParseError, ParseResult},
expression::BindingIdentifier, expression::BindingIdentifier,
function::{FormalParameters, FunctionBody}, function::{FormalParameters, FunctionBody},
name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, TokenParser, name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, OrAbrupt,
TokenParser,
}, },
}; };
use ast::operations::{bound_names, top_level_lexically_declared_names}; use ast::operations::{bound_names, top_level_lexically_declared_names};
@ -78,7 +79,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("ArrowFunction", "Parsing"); let _timer = Profiler::global().start_event("ArrowFunction", "Parsing");
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
let (params, params_start_position) = if let TokenKind::Punctuator(Punctuator::OpenParen) = let (params, params_start_position) = if let TokenKind::Punctuator(Punctuator::OpenParen) =
&next_token.kind() &next_token.kind()
@ -191,13 +192,9 @@ where
type Output = StatementList; type Output = StatementList;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {
let _next = cursor.next(interner)?; cursor.advance(interner);
let body = FunctionBody::new(false, false).parse(cursor, interner)?; let body = FunctionBody::new(false, false).parse(cursor, interner)?;
cursor.expect(Punctuator::CloseBlock, "arrow function", interner)?; cursor.expect(Punctuator::CloseBlock, "arrow function", interner)?;
Ok(body) Ok(body)

12
boa_engine/src/syntax/parser/expression/assignment/async_arrow_function.rs

@ -14,7 +14,7 @@ use crate::syntax::{
error::{ErrorContext, ParseError, ParseResult}, error::{ErrorContext, ParseError, ParseResult},
expression::BindingIdentifier, expression::BindingIdentifier,
function::{FormalParameters, FunctionBody}, function::{FormalParameters, FunctionBody},
name_in_lexically_declared_names, AllowIn, AllowYield, Cursor, TokenParser, name_in_lexically_declared_names, AllowIn, AllowYield, Cursor, OrAbrupt, TokenParser,
}, },
}; };
use ast::{ use ast::{
@ -76,7 +76,7 @@ where
cursor.expect((Keyword::Async, false), "async arrow function", interner)?; cursor.expect((Keyword::Async, false), "async arrow function", interner)?;
cursor.peek_expect_no_lineterminator(0, "async arrow function", interner)?; cursor.peek_expect_no_lineterminator(0, "async arrow function", interner)?;
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
let (params, params_start_position) = if let TokenKind::Punctuator(Punctuator::OpenParen) = let (params, params_start_position) = if let TokenKind::Punctuator(Punctuator::OpenParen) =
&next_token.kind() &next_token.kind()
{ {
@ -180,13 +180,9 @@ where
type Output = StatementList; type Output = StatementList;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {
cursor.next(interner)?; cursor.advance(interner);
let body = FunctionBody::new(false, true).parse(cursor, interner)?; let body = FunctionBody::new(false, true).parse(cursor, interner)?;
cursor.expect(Punctuator::CloseBlock, "async arrow function", interner)?; cursor.expect(Punctuator::CloseBlock, "async arrow function", interner)?;
Ok(body) Ok(body)

2
boa_engine/src/syntax/parser/expression/assignment/conditional.rs

@ -79,7 +79,7 @@ where
if let Some(tok) = cursor.peek(0, interner)? { if let Some(tok) = cursor.peek(0, interner)? {
if tok.kind() == &TokenKind::Punctuator(Punctuator::Question) { if tok.kind() == &TokenKind::Punctuator(Punctuator::Question) {
cursor.next(interner)?.expect("? character vanished"); // Consume the token. cursor.advance(interner);
let then_clause = let then_clause =
AssignmentExpression::new(None, true, self.allow_yield, self.allow_await) AssignmentExpression::new(None, true, self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;

7
boa_engine/src/syntax/parser/expression/assignment/exponentiation.rs

@ -7,12 +7,11 @@
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation
//! [spec]: https://tc39.es/ecma262/#sec-exp-operator //! [spec]: https://tc39.es/ecma262/#sec-exp-operator
use super::ParseError;
use crate::syntax::{ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
expression::{unary::UnaryExpression, update::UpdateExpression}, expression::{unary::UnaryExpression, update::UpdateExpression},
AllowAwait, AllowYield, Cursor, ParseResult, TokenParser, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -70,7 +69,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("ExponentiationExpression", "Parsing"); let _timer = Profiler::global().start_event("ExponentiationExpression", "Parsing");
let next = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next = cursor.peek(0, interner).or_abrupt()?;
match next.kind() { match next.kind() {
TokenKind::Keyword((Keyword::Delete | Keyword::Void | Keyword::TypeOf, _)) TokenKind::Keyword((Keyword::Delete | Keyword::Void | Keyword::TypeOf, _))
| TokenKind::Punctuator( | TokenKind::Punctuator(
@ -90,7 +89,7 @@ where
.parse(cursor, interner)?; .parse(cursor, interner)?;
if let Some(tok) = cursor.peek(0, interner)? { if let Some(tok) = cursor.peek(0, interner)? {
if let TokenKind::Punctuator(Punctuator::Exp) = tok.kind() { if let TokenKind::Punctuator(Punctuator::Exp) = tok.kind() {
cursor.next(interner)?.expect("** token vanished"); // Consume the token. cursor.advance(interner);
return Ok(Binary::new( return Ok(Binary::new(
ArithmeticOp::Exp.into(), ArithmeticOp::Exp.into(),
lhs, lhs,

44
boa_engine/src/syntax/parser/expression/assignment/mod.rs

@ -22,17 +22,16 @@ use crate::syntax::{
conditional::ConditionalExpression, conditional::ConditionalExpression,
r#yield::YieldExpression, r#yield::YieldExpression,
}, },
name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, ParseError, name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, OrAbrupt,
ParseResult, TokenParser, ParseError, ParseResult, TokenParser,
}, },
}; };
use ast::operations::{bound_names, contains, top_level_lexically_declared_names, ContainsSymbol};
use boa_ast::{ use boa_ast::{
self as ast,
expression::{ expression::{
operator::assign::{Assign, AssignOp, AssignTarget}, operator::assign::{Assign, AssignOp, AssignTarget},
Identifier, Identifier,
}, },
operations::{bound_names, contains, top_level_lexically_declared_names, ContainsSymbol},
Expression, Keyword, Punctuator, Expression, Keyword, Punctuator,
}; };
use boa_interner::Interner; use boa_interner::Interner;
@ -102,11 +101,7 @@ where
let _timer = Profiler::global().start_event("AssignmentExpression", "Parsing"); let _timer = Profiler::global().start_event("AssignmentExpression", "Parsing");
cursor.set_goal(InputElement::RegExp); cursor.set_goal(InputElement::RegExp);
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
// [+Yield]YieldExpression[?In, ?Await] // [+Yield]YieldExpression[?In, ?Await]
TokenKind::Keyword((Keyword::Yield, _)) if self.allow_yield.0 => { TokenKind::Keyword((Keyword::Yield, _)) if self.allow_yield.0 => {
return YieldExpression::new(self.allow_in, self.allow_await) return YieldExpression::new(self.allow_in, self.allow_await)
@ -118,10 +113,7 @@ where
// Because we already peeked the identifier token, there may be a line terminator before the identifier token. // Because we already peeked the identifier token, there may be a line terminator before the identifier token.
// In that case we have to skip an additional token on the next peek. // In that case we have to skip an additional token on the next peek.
let skip_n = if cursor let skip_n = if cursor.peek_is_line_terminator(0, interner).or_abrupt()? {
.peek_is_line_terminator(0, interner)?
.ok_or(ParseError::AbruptEnd)?
{
2 2
} else { } else {
1 1
@ -143,23 +135,17 @@ where
} }
// AsyncArrowFunction[?In, ?Yield, ?Await] // AsyncArrowFunction[?In, ?Yield, ?Await]
TokenKind::Keyword((Keyword::Async, _)) => { TokenKind::Keyword((Keyword::Async, _)) => {
let skip_n = if cursor let skip_n = if cursor.peek_is_line_terminator(0, interner).or_abrupt()? {
.peek_is_line_terminator(0, interner)?
.ok_or(ParseError::AbruptEnd)?
{
2 2
} else { } else {
1 1
}; };
if !cursor if !cursor
.peek_is_line_terminator(skip_n, interner)? .peek_is_line_terminator(skip_n, interner)
.ok_or(ParseError::AbruptEnd)? .or_abrupt()?
&& matches!( && matches!(
cursor cursor.peek(1, interner).or_abrupt()?.kind(),
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind(),
TokenKind::Identifier(_) TokenKind::Identifier(_)
| TokenKind::Keyword((Keyword::Yield | Keyword::Await, _)) | TokenKind::Keyword((Keyword::Yield | Keyword::Await, _))
| TokenKind::Punctuator(Punctuator::OpenParen) | TokenKind::Punctuator(Punctuator::OpenParen)
@ -177,11 +163,7 @@ where
cursor.set_goal(InputElement::Div); cursor.set_goal(InputElement::Div);
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let mut lhs = ConditionalExpression::new( let mut lhs = ConditionalExpression::new(
self.name, self.name,
self.allow_in, self.allow_in,
@ -247,7 +229,7 @@ where
position, position,
)?; )?;
return Ok(ast::function::ArrowFunction::new(self.name, parameters, body).into()); return Ok(boa_ast::function::ArrowFunction::new(self.name, parameters, body).into());
} }
// Review if we are trying to assign to an invalid left hand side expression. // Review if we are trying to assign to an invalid left hand side expression.
@ -260,7 +242,7 @@ where
} }
} }
cursor.next(interner)?.expect("= token vanished"); cursor.advance(interner);
cursor.set_goal(InputElement::RegExp); cursor.set_goal(InputElement::RegExp);
if let Some(target) = if let Some(target) =
@ -285,7 +267,7 @@ where
} }
} }
cursor.next(interner)?.expect("token vanished"); cursor.advance(interner);
if let Some(target) = if let Some(target) =
AssignTarget::from_expression(&lhs, cursor.strict_mode(), false) AssignTarget::from_expression(&lhs, cursor.strict_mode(), false)
{ {

6
boa_engine/src/syntax/parser/expression/assignment/yield.rs

@ -10,7 +10,7 @@
use super::AssignmentExpression; use super::AssignmentExpression;
use crate::syntax::{ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{AllowAwait, AllowIn, Cursor, ParseError, ParseResult, TokenParser}, parser::{AllowAwait, AllowIn, Cursor, OrAbrupt, ParseResult, TokenParser},
}; };
use boa_ast::{expression::Yield, Expression, Keyword, Punctuator}; use boa_ast::{expression::Yield, Expression, Keyword, Punctuator};
use boa_interner::Interner; use boa_interner::Interner;
@ -67,10 +67,10 @@ where
return Ok(Yield::new(None, false).into()); return Ok(Yield::new(None, false).into());
} }
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::Mul) => { TokenKind::Punctuator(Punctuator::Mul) => {
cursor.next(interner)?.expect("token disappeared"); cursor.advance(interner);
let expr = AssignmentExpression::new(None, self.allow_in, true, self.allow_await) let expr = AssignmentExpression::new(None, self.allow_in, true, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
Ok(Yield::new(Some(expr), true).into()) Ok(Yield::new(Some(expr), true).into())

8
boa_engine/src/syntax/parser/expression/identifiers.rs

@ -7,7 +7,9 @@
use crate::syntax::{ use crate::syntax::{
lexer::{Error as LexError, TokenKind}, lexer::{Error as LexError, TokenKind},
parser::{cursor::Cursor, AllowAwait, AllowYield, ParseError, ParseResult, TokenParser}, parser::{
cursor::Cursor, AllowAwait, AllowYield, OrAbrupt, ParseError, ParseResult, TokenParser,
},
}; };
use boa_ast::{expression::Identifier, Keyword}; use boa_ast::{expression::Identifier, Keyword};
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
@ -61,7 +63,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("IdentifierReference", "Parsing"); let _timer = Profiler::global().start_event("IdentifierReference", "Parsing");
let token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.next(interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Identifier(ident) TokenKind::Identifier(ident)
@ -153,7 +155,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("BindingIdentifier", "Parsing"); let _timer = Profiler::global().start_event("BindingIdentifier", "Parsing");
let next_token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.next(interner).or_abrupt()?;
match next_token.kind() { match next_token.kind() {
TokenKind::Identifier(Sym::ARGUMENTS) if cursor.strict_mode() => { TokenKind::Identifier(Sym::ARGUMENTS) if cursor.strict_mode() => {

8
boa_engine/src/syntax/parser/expression/left_hand_side/arguments.rs

@ -10,8 +10,8 @@
use crate::syntax::{ use crate::syntax::{
lexer::{InputElement, TokenKind}, lexer::{InputElement, TokenKind},
parser::{ parser::{
expression::AssignmentExpression, AllowAwait, AllowYield, Cursor, ParseError, ParseResult, expression::AssignmentExpression, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError,
TokenParser, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{expression::Spread, Expression, Punctuator}; use boa_ast::{expression::Spread, Expression, Punctuator};
@ -60,11 +60,11 @@ where
let mut args = Vec::new(); let mut args = Vec::new();
loop { loop {
cursor.set_goal(InputElement::RegExp); cursor.set_goal(InputElement::RegExp);
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
match next_token.kind() { match next_token.kind() {
TokenKind::Punctuator(Punctuator::CloseParen) => { TokenKind::Punctuator(Punctuator::CloseParen) => {
cursor.next(interner)?.expect(") token vanished"); // Consume the token. cursor.advance(interner);
break; break;
} }
TokenKind::Punctuator(Punctuator::Comma) => { TokenKind::Punctuator(Punctuator::Comma) => {

10
boa_engine/src/syntax/parser/expression/left_hand_side/call.rs

@ -12,7 +12,7 @@ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
expression::{left_hand_side::template::TaggedTemplateLiteral, Expression}, expression::{left_hand_side::template::TaggedTemplateLiteral, Expression},
AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -68,7 +68,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("CallExpression", "Parsing"); let _timer = Profiler::global().start_event("CallExpression", "Parsing");
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let mut lhs = if token.kind() == &TokenKind::Punctuator(Punctuator::OpenParen) { let mut lhs = if token.kind() == &TokenKind::Punctuator(Punctuator::OpenParen) {
let args = let args =
@ -93,9 +93,9 @@ where
lhs = ast::Expression::from(Call::new(lhs, args)); lhs = ast::Expression::from(Call::new(lhs, args));
} }
TokenKind::Punctuator(Punctuator::Dot) => { TokenKind::Punctuator(Punctuator::Dot) => {
cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; // We move the parser forward. cursor.advance(interner);
let access = match cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?.kind() { let access = match cursor.next(interner).or_abrupt()?.kind() {
TokenKind::Identifier(name) => SimplePropertyAccess::new(lhs, *name).into(), TokenKind::Identifier(name) => SimplePropertyAccess::new(lhs, *name).into(),
TokenKind::Keyword((kw, _)) => { TokenKind::Keyword((kw, _)) => {
SimplePropertyAccess::new(lhs, kw.to_sym(interner)).into() SimplePropertyAccess::new(lhs, kw.to_sym(interner)).into()
@ -124,7 +124,7 @@ where
lhs = ast::Expression::PropertyAccess(access); lhs = ast::Expression::PropertyAccess(access);
} }
TokenKind::Punctuator(Punctuator::OpenBracket) => { TokenKind::Punctuator(Punctuator::OpenBracket) => {
let _next = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; // We move the parser. cursor.advance(interner);
let idx = Expression::new(None, true, self.allow_yield, self.allow_await) let idx = Expression::new(None, true, self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
cursor.expect(Punctuator::CloseBracket, "call expression", interner)?; cursor.expect(Punctuator::CloseBracket, "call expression", interner)?;

16
boa_engine/src/syntax/parser/expression/left_hand_side/member.rs

@ -12,7 +12,7 @@ use crate::syntax::{
expression::{ expression::{
left_hand_side::template::TaggedTemplateLiteral, primary::PrimaryExpression, Expression, left_hand_side::template::TaggedTemplateLiteral, primary::PrimaryExpression, Expression,
}, },
AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -69,7 +69,7 @@ where
cursor.set_goal(InputElement::RegExp); cursor.set_goal(InputElement::RegExp);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let mut lhs = match token.kind() { let mut lhs = match token.kind() {
TokenKind::Keyword((Keyword::New | Keyword::Super, true)) => { TokenKind::Keyword((Keyword::New | Keyword::Super, true)) => {
return Err(ParseError::general( return Err(ParseError::general(
@ -78,10 +78,10 @@ where
)); ));
} }
TokenKind::Keyword((Keyword::New, false)) => { TokenKind::Keyword((Keyword::New, false)) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
if cursor.next_if(Punctuator::Dot, interner)?.is_some() { if cursor.next_if(Punctuator::Dot, interner)?.is_some() {
let token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.next(interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Identifier(Sym::TARGET) => { TokenKind::Identifier(Sym::TARGET) => {
return Ok(ast::Expression::NewTarget) return Ok(ast::Expression::NewTarget)
@ -108,11 +108,11 @@ where
ast::Expression::from(New::from(call_node)) ast::Expression::from(New::from(call_node))
} }
TokenKind::Keyword((Keyword::Super, _)) => { TokenKind::Keyword((Keyword::Super, _)) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.next(interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::Dot) => { TokenKind::Punctuator(Punctuator::Dot) => {
let token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.next(interner).or_abrupt()?;
let field = match token.kind() { let field = match token.kind() {
TokenKind::Identifier(name) => { TokenKind::Identifier(name) => {
SuperPropertyAccess::new(PropertyAccessField::from(*name)) SuperPropertyAccess::new(PropertyAccessField::from(*name))
@ -173,7 +173,7 @@ where
.next(interner)? .next(interner)?
.expect("dot punctuator token disappeared"); // We move the parser forward. .expect("dot punctuator token disappeared"); // We move the parser forward.
let token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.next(interner).or_abrupt()?;
let access = match token.kind() { let access = match token.kind() {
TokenKind::Identifier(name) => SimplePropertyAccess::new(lhs, *name).into(), TokenKind::Identifier(name) => SimplePropertyAccess::new(lhs, *name).into(),

2
boa_engine/src/syntax/parser/expression/left_hand_side/mod.rs

@ -101,7 +101,7 @@ where
cursor.set_goal(InputElement::TemplateTail); cursor.set_goal(InputElement::TemplateTail);
let mut lhs = if is_super_call(cursor, interner)? { let mut lhs = if is_super_call(cursor, interner)? {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let args = let args =
Arguments::new(self.allow_yield, self.allow_await).parse(cursor, interner)?; Arguments::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
SuperCall::new(args).into() SuperCall::new(args).into()

12
boa_engine/src/syntax/parser/expression/left_hand_side/optional/mod.rs

@ -9,8 +9,8 @@ use boa_profiler::Profiler;
use crate::syntax::{ use crate::syntax::{
lexer::{Token, TokenKind}, lexer::{Token, TokenKind},
parser::{ parser::{
cursor::Cursor, expression::Expression, AllowAwait, AllowYield, ParseError, ParseResult, cursor::Cursor, expression::Expression, AllowAwait, AllowYield, OrAbrupt, ParseError,
TokenParser, ParseResult, TokenParser,
}, },
}; };
@ -105,13 +105,13 @@ where
while let Some(token) = cursor.peek(0, interner)? { while let Some(token) = cursor.peek(0, interner)? {
let shorted = match token.kind() { let shorted = match token.kind() {
TokenKind::Punctuator(Punctuator::Optional) => { TokenKind::Punctuator(Punctuator::Optional) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
true true
} }
TokenKind::Punctuator(Punctuator::OpenParen | Punctuator::OpenBracket) => false, TokenKind::Punctuator(Punctuator::OpenParen | Punctuator::OpenBracket) => false,
TokenKind::Punctuator(Punctuator::Dot) => { TokenKind::Punctuator(Punctuator::Dot) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let field = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let field = cursor.next(interner).or_abrupt()?;
let item = parse_const_access(cursor, &field, interner)?; let item = parse_const_access(cursor, &field, interner)?;
@ -127,7 +127,7 @@ where
_ => break, _ => break,
}; };
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let item = match token.kind() { let item = match token.kind() {
TokenKind::Punctuator(Punctuator::OpenParen) => { TokenKind::Punctuator(Punctuator::OpenParen) => {

6
boa_engine/src/syntax/parser/expression/left_hand_side/template.rs

@ -1,8 +1,8 @@
use crate::syntax::{ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
cursor::Cursor, expression::Expression, AllowAwait, AllowYield, ParseError, ParseResult, cursor::Cursor, expression::Expression, AllowAwait, AllowYield, OrAbrupt, ParseError,
TokenParser, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{self as ast, expression::TaggedTemplate, Position, Punctuator}; use boa_ast::{self as ast, expression::TaggedTemplate, Position, Punctuator};
@ -58,7 +58,7 @@ where
let mut cookeds = Vec::new(); let mut cookeds = Vec::new();
let mut exprs = Vec::new(); let mut exprs = Vec::new();
let mut token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let mut token = cursor.next(interner).or_abrupt()?;
loop { loop {
match token.kind() { match token.kind() {

30
boa_engine/src/syntax/parser/expression/mod.rs

@ -23,10 +23,9 @@ use crate::syntax::{
lexer::{InputElement, TokenKind}, lexer::{InputElement, TokenKind},
parser::{ parser::{
expression::assignment::ExponentiationExpression, AllowAwait, AllowIn, AllowYield, Cursor, expression::assignment::ExponentiationExpression, AllowAwait, AllowIn, AllowYield, Cursor,
ParseError, ParseResult, TokenParser, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
self as ast, self as ast,
expression::{ expression::{
@ -43,6 +42,7 @@ use boa_profiler::Profiler;
use std::io::Read; use std::io::Read;
pub(super) use self::{assignment::AssignmentExpression, primary::Initializer}; pub(super) use self::{assignment::AssignmentExpression, primary::Initializer};
pub(in crate::syntax::parser) use { pub(in crate::syntax::parser) use {
identifiers::{BindingIdentifier, LabelIdentifier}, identifiers::{BindingIdentifier, LabelIdentifier},
left_hand_side::LeftHandSideExpression, left_hand_side::LeftHandSideExpression,
@ -88,7 +88,7 @@ macro_rules! expression {
while let Some(tok) = cursor.peek(0, interner)? { while let Some(tok) = cursor.peek(0, interner)? {
match *tok.kind() { match *tok.kind() {
TokenKind::Punctuator(op) if $( op == $op )||* => { TokenKind::Punctuator(op) if $( op == $op )||* => {
let _next = cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
lhs = Binary::new( lhs = Binary::new(
op.as_binary_op().expect("Could not get binary operation."), op.as_binary_op().expect("Could not get binary operation."),
lhs, lhs,
@ -159,25 +159,19 @@ where
while let Some(tok) = cursor.peek(0, interner)? { while let Some(tok) = cursor.peek(0, interner)? {
match *tok.kind() { match *tok.kind() {
TokenKind::Punctuator(Punctuator::Comma) => { TokenKind::Punctuator(Punctuator::Comma) => {
if cursor if cursor.peek(1, interner).or_abrupt()?.kind()
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== &TokenKind::Punctuator(Punctuator::CloseParen) == &TokenKind::Punctuator(Punctuator::CloseParen)
{ {
return Ok(lhs); return Ok(lhs);
} }
if cursor if cursor.peek(1, interner).or_abrupt()?.kind()
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== &TokenKind::Punctuator(Punctuator::Spread) == &TokenKind::Punctuator(Punctuator::Spread)
{ {
return Ok(lhs); return Ok(lhs);
} }
let _next = cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
lhs = Binary::new( lhs = Binary::new(
Punctuator::Comma Punctuator::Comma
@ -291,7 +285,7 @@ where
"logical expression (cannot use '??' without parentheses within '||' or '&&')", "logical expression (cannot use '??' without parentheses within '||' or '&&')",
)); ));
} }
let _next = cursor.next(interner)?.expect("'&&' expected"); cursor.advance(interner);
previous = PreviousExpr::Logical; previous = PreviousExpr::Logical;
let rhs = BitwiseORExpression::new( let rhs = BitwiseORExpression::new(
self.name, self.name,
@ -312,7 +306,7 @@ where
"logical expression (cannot use '??' without parentheses within '||' or '&&')", "logical expression (cannot use '??' without parentheses within '||' or '&&')",
)); ));
} }
let _next = cursor.next(interner)?.expect("'||' expected"); cursor.advance(interner);
previous = PreviousExpr::Logical; previous = PreviousExpr::Logical;
let rhs = Self::with_previous( let rhs = Self::with_previous(
self.name, self.name,
@ -334,7 +328,7 @@ where
"cannot use '??' unparenthesized within '||' or '&&'", "cannot use '??' unparenthesized within '||' or '&&'",
)); ));
} }
let _next = cursor.next(interner)?.expect("'??' expected"); cursor.advance(interner);
previous = PreviousExpr::Coalesce; previous = PreviousExpr::Coalesce;
let rhs = BitwiseORExpression::new( let rhs = BitwiseORExpression::new(
self.name, self.name,
@ -580,7 +574,7 @@ where
|| op == Punctuator::LessThanOrEq || op == Punctuator::LessThanOrEq
|| op == Punctuator::GreaterThanOrEq => || op == Punctuator::GreaterThanOrEq =>
{ {
let _next = cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
lhs = Binary::new( lhs = Binary::new(
op.as_binary_op().expect("Could not get binary operation."), op.as_binary_op().expect("Could not get binary operation."),
lhs, lhs,
@ -599,7 +593,7 @@ where
if op == Keyword::InstanceOf if op == Keyword::InstanceOf
|| (op == Keyword::In && self.allow_in == AllowIn(true)) => || (op == Keyword::In && self.allow_in == AllowIn(true)) =>
{ {
let _next = cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
lhs = Binary::new( lhs = Binary::new(
op.as_binary_op().expect("Could not get binary operation."), op.as_binary_op().expect("Could not get binary operation."),
lhs, lhs,
@ -742,7 +736,7 @@ expression!(
); );
/// Returns an error if `arguments` or `eval` are used as identifier in strict mode. /// Returns an error if `arguments` or `eval` are used as identifier in strict mode.
fn check_strict_arguments_or_eval(ident: Identifier, position: Position) -> Result<(), ParseError> { fn check_strict_arguments_or_eval(ident: Identifier, position: Position) -> ParseResult<()> {
match ident.sym() { match ident.sym() {
Sym::ARGUMENTS => Err(ParseError::general( Sym::ARGUMENTS => Err(ParseError::general(
"unexpected identifier 'arguments' in strict mode", "unexpected identifier 'arguments' in strict mode",

16
boa_engine/src/syntax/parser/expression/primary/array_initializer/mod.rs

@ -13,8 +13,8 @@ mod tests;
use crate::syntax::{ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
expression::AssignmentExpression, AllowAwait, AllowYield, Cursor, ParseError, ParseResult, expression::AssignmentExpression, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError,
TokenParser, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -67,17 +67,17 @@ where
let mut last_spread = false; let mut last_spread = false;
loop { loop {
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::CloseBracket) => { TokenKind::Punctuator(Punctuator::CloseBracket) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
break; break;
} }
TokenKind::Punctuator(Punctuator::Comma) if next_comma => { TokenKind::Punctuator(Punctuator::Comma) if next_comma => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
if last_spread { if last_spread {
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
if token.kind() == &TokenKind::Punctuator(Punctuator::CloseBracket) { if token.kind() == &TokenKind::Punctuator(Punctuator::CloseBracket) {
has_trailing_comma_spread = true; has_trailing_comma_spread = true;
} }
@ -86,7 +86,7 @@ where
next_comma = false; next_comma = false;
} }
TokenKind::Punctuator(Punctuator::Comma) => { TokenKind::Punctuator(Punctuator::Comma) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
elements.push(None); elements.push(None);
} }
TokenKind::Punctuator(Punctuator::Spread) if next_comma => { TokenKind::Punctuator(Punctuator::Spread) if next_comma => {
@ -97,7 +97,7 @@ where
)); ));
} }
TokenKind::Punctuator(Punctuator::Spread) => { TokenKind::Punctuator(Punctuator::Spread) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let node = let node =
AssignmentExpression::new(None, true, self.allow_yield, self.allow_await) AssignmentExpression::new(None, true, self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;

9
boa_engine/src/syntax/parser/expression/primary/async_function_expression/mod.rs

@ -6,7 +6,8 @@ use crate::syntax::{
parser::{ parser::{
expression::BindingIdentifier, expression::BindingIdentifier,
function::{FormalParameters, FunctionBody}, function::{FormalParameters, FunctionBody},
name_in_lexically_declared_names, AllowYield, Cursor, ParseError, ParseResult, TokenParser, name_in_lexically_declared_names, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -62,11 +63,7 @@ where
interner, interner,
)?; )?;
let (name, has_binding_identifier) = match cursor let (name, has_binding_identifier) = match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenParen) => (self.name, false), TokenKind::Punctuator(Punctuator::OpenParen) => (self.name, false),
_ => ( _ => (
Some(BindingIdentifier::new(self.allow_yield, true).parse(cursor, interner)?), Some(BindingIdentifier::new(self.allow_yield, true).parse(cursor, interner)?),

8
boa_engine/src/syntax/parser/expression/primary/async_generator_expression/mod.rs

@ -15,7 +15,7 @@ use crate::syntax::{
parser::{ parser::{
expression::BindingIdentifier, expression::BindingIdentifier,
function::{FormalParameters, FunctionBody}, function::{FormalParameters, FunctionBody},
name_in_lexically_declared_names, Cursor, ParseError, ParseResult, TokenParser, name_in_lexically_declared_names, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -71,11 +71,7 @@ where
interner, interner,
)?; )?;
let (name, has_binding_identifier) = match cursor let (name, has_binding_identifier) = match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenParen) => (self.name, false), TokenKind::Punctuator(Punctuator::OpenParen) => (self.name, false),
_ => ( _ => (
Some(BindingIdentifier::new(true, true).parse(cursor, interner)?), Some(BindingIdentifier::new(true, true).parse(cursor, interner)?),

4
boa_engine/src/syntax/parser/expression/primary/class_expression/mod.rs

@ -2,7 +2,7 @@ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
expression::BindingIdentifier, statement::ClassTail, AllowAwait, AllowYield, Cursor, expression::BindingIdentifier, statement::ClassTail, AllowAwait, AllowYield, Cursor,
ParseError, ParseResult, TokenParser, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{expression::Identifier, function::Class, Keyword}; use boa_ast::{expression::Identifier, function::Class, Keyword};
@ -50,7 +50,7 @@ where
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let name = match token.kind() { let name = match token.kind() {
TokenKind::Identifier(_) | TokenKind::Keyword((Keyword::Yield | Keyword::Await, _)) => { TokenKind::Identifier(_) | TokenKind::Keyword((Keyword::Yield | Keyword::Await, _)) => {
BindingIdentifier::new(self.allow_yield, self.allow_await) BindingIdentifier::new(self.allow_yield, self.allow_await)

8
boa_engine/src/syntax/parser/expression/primary/function_expression/mod.rs

@ -15,7 +15,7 @@ use crate::syntax::{
parser::{ parser::{
expression::BindingIdentifier, expression::BindingIdentifier,
function::{FormalParameters, FunctionBody}, function::{FormalParameters, FunctionBody},
name_in_lexically_declared_names, Cursor, ParseError, ParseResult, TokenParser, name_in_lexically_declared_names, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -60,11 +60,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("FunctionExpression", "Parsing"); let _timer = Profiler::global().start_event("FunctionExpression", "Parsing");
let (name, has_binding_identifier) = match cursor let (name, has_binding_identifier) = match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Identifier(_) TokenKind::Identifier(_)
| TokenKind::Keyword(( | TokenKind::Keyword((
Keyword::Yield | Keyword::Await | Keyword::Async | Keyword::Of, Keyword::Yield | Keyword::Await | Keyword::Async | Keyword::Of,

8
boa_engine/src/syntax/parser/expression/primary/generator_expression/mod.rs

@ -15,7 +15,7 @@ use crate::syntax::{
parser::{ parser::{
expression::BindingIdentifier, expression::BindingIdentifier,
function::{FormalParameters, FunctionBody}, function::{FormalParameters, FunctionBody},
name_in_lexically_declared_names, Cursor, ParseError, ParseResult, TokenParser, name_in_lexically_declared_names, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -66,11 +66,7 @@ where
interner, interner,
)?; )?;
let (name, has_binding_identifier) = match cursor let (name, has_binding_identifier) = match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenParen) => (self.name, false), TokenKind::Punctuator(Punctuator::OpenParen) => (self.name, false),
_ => ( _ => (
Some(BindingIdentifier::new(true, false).parse(cursor, interner)?), Some(BindingIdentifier::new(true, false).parse(cursor, interner)?),

74
boa_engine/src/syntax/parser/expression/primary/mod.rs

@ -34,7 +34,7 @@ use crate::syntax::{
BindingIdentifier, Expression, BindingIdentifier, Expression,
}, },
statement::{ArrayBindingPattern, ObjectBindingPattern}, statement::{ArrayBindingPattern, ObjectBindingPattern},
AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -98,7 +98,7 @@ where
// TODO: tok currently consumes the token instead of peeking, so the token // TODO: tok currently consumes the token instead of peeking, so the token
// isn't passed and consumed by parsers according to spec (EX: GeneratorExpression) // isn't passed and consumed by parsers according to spec (EX: GeneratorExpression)
let tok = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let tok = cursor.peek(0, interner).or_abrupt()?;
let tok_position = tok.span().start(); let tok_position = tok.span().start();
match tok.kind() { match tok.kind() {
@ -107,12 +107,12 @@ where
tok_position, tok_position,
)), )),
TokenKind::Keyword((Keyword::This, false)) => { TokenKind::Keyword((Keyword::This, false)) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(ast::Expression::This) Ok(ast::Expression::This)
} }
TokenKind::Keyword((Keyword::Function, _)) => { TokenKind::Keyword((Keyword::Function, _)) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
if next_token.kind() == &TokenKind::Punctuator(Punctuator::Mul) { if next_token.kind() == &TokenKind::Punctuator(Punctuator::Mul) {
GeneratorExpression::new(self.name) GeneratorExpression::new(self.name)
.parse(cursor, interner) .parse(cursor, interner)
@ -124,7 +124,7 @@ where
} }
} }
TokenKind::Keyword((Keyword::Class, _)) => { TokenKind::Keyword((Keyword::Class, _)) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
ClassExpression::new(self.name, self.allow_yield, self.allow_await) ClassExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner) .parse(cursor, interner)
.map(Into::into) .map(Into::into)
@ -139,7 +139,7 @@ where
)) ))
} }
Some(TokenKind::Keyword((Keyword::Function, _))) => { Some(TokenKind::Keyword((Keyword::Function, _))) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
match cursor.peek(1, interner)?.map(Token::kind) { match cursor.peek(1, interner)?.map(Token::kind) {
Some(TokenKind::Punctuator(Punctuator::Mul)) => { Some(TokenKind::Punctuator(Punctuator::Mul)) => {
AsyncGeneratorExpression::new(self.name) AsyncGeneratorExpression::new(self.name)
@ -157,7 +157,7 @@ where
} }
} }
TokenKind::Punctuator(Punctuator::OpenParen) => { TokenKind::Punctuator(Punctuator::OpenParen) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
cursor.set_goal(InputElement::RegExp); cursor.set_goal(InputElement::RegExp);
let expr = CoverParenthesizedExpressionAndArrowParameterList::new( let expr = CoverParenthesizedExpressionAndArrowParameterList::new(
self.name, self.name,
@ -168,14 +168,14 @@ where
Ok(expr) Ok(expr)
} }
TokenKind::Punctuator(Punctuator::OpenBracket) => { TokenKind::Punctuator(Punctuator::OpenBracket) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
cursor.set_goal(InputElement::RegExp); cursor.set_goal(InputElement::RegExp);
ArrayLiteral::new(self.allow_yield, self.allow_await) ArrayLiteral::new(self.allow_yield, self.allow_await)
.parse(cursor, interner) .parse(cursor, interner)
.map(Into::into) .map(Into::into)
} }
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
cursor.set_goal(InputElement::RegExp); cursor.set_goal(InputElement::RegExp);
ObjectLiteral::new(self.allow_yield, self.allow_await) ObjectLiteral::new(self.allow_yield, self.allow_await)
.parse(cursor, interner) .parse(cursor, interner)
@ -183,11 +183,11 @@ where
} }
TokenKind::BooleanLiteral(boolean) => { TokenKind::BooleanLiteral(boolean) => {
let node = Literal::from(*boolean).into(); let node = Literal::from(*boolean).into();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(node) Ok(node)
} }
TokenKind::NullLiteral => { TokenKind::NullLiteral => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(Literal::Null.into()) Ok(Literal::Null.into())
} }
TokenKind::Identifier(_) TokenKind::Identifier(_)
@ -199,7 +199,7 @@ where
.map(Into::into), .map(Into::into),
TokenKind::StringLiteral(lit) => { TokenKind::StringLiteral(lit) => {
let node = Literal::from(*lit).into(); let node = Literal::from(*lit).into();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(node) Ok(node)
} }
TokenKind::TemplateNoSubstitution(template_string) => { TokenKind::TemplateNoSubstitution(template_string) => {
@ -209,22 +209,22 @@ where
.map_err(ParseError::lex)?, .map_err(ParseError::lex)?,
) )
.into(); .into();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(node) Ok(node)
} }
TokenKind::NumericLiteral(Numeric::Integer(num)) => { TokenKind::NumericLiteral(Numeric::Integer(num)) => {
let node = Literal::from(*num).into(); let node = Literal::from(*num).into();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(node) Ok(node)
} }
TokenKind::NumericLiteral(Numeric::Rational(num)) => { TokenKind::NumericLiteral(Numeric::Rational(num)) => {
let node = Literal::from(*num).into(); let node = Literal::from(*num).into();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(node) Ok(node)
} }
TokenKind::NumericLiteral(Numeric::BigInt(num)) => { TokenKind::NumericLiteral(Numeric::BigInt(num)) => {
let node = Literal::from(num.clone()).into(); let node = Literal::from(num.clone()).into();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(node) Ok(node)
} }
TokenKind::RegularExpressionLiteral(body, flags) => { TokenKind::RegularExpressionLiteral(body, flags) => {
@ -232,12 +232,12 @@ where
Identifier::new(Sym::REGEXP).into(), Identifier::new(Sym::REGEXP).into(),
vec![Literal::from(*body).into(), Literal::from(*flags).into()].into(), vec![Literal::from(*body).into(), Literal::from(*flags).into()].into(),
))); )));
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(node) Ok(node)
} }
TokenKind::Punctuator(Punctuator::Div) => { TokenKind::Punctuator(Punctuator::Div) => {
let position = tok.span().start(); let position = tok.span().start();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let tok = cursor.lex_regex(position, interner)?; let tok = cursor.lex_regex(position, interner)?;
if let TokenKind::RegularExpressionLiteral(body, flags) = *tok.kind() { if let TokenKind::RegularExpressionLiteral(body, flags) = *tok.kind() {
@ -263,7 +263,7 @@ where
.to_owned_cooked(interner) .to_owned_cooked(interner)
.map_err(ParseError::lex)?, .map_err(ParseError::lex)?,
); );
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
parser.parse(cursor, interner).map(Into::into) parser.parse(cursor, interner).map(Into::into)
} }
_ => Err(ParseError::unexpected( _ => Err(ParseError::unexpected(
@ -324,24 +324,21 @@ where
"Parsing", "Parsing",
); );
let start_span = cursor let start_span = cursor.peek(0, interner).or_abrupt()?.span();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span();
let mut expressions = Vec::new(); let mut expressions = Vec::new();
let mut tailing_comma = None; let mut tailing_comma = None;
let next = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next = cursor.peek(0, interner).or_abrupt()?;
let span = match next.kind() { let span = match next.kind() {
TokenKind::Punctuator(Punctuator::CloseParen) => { TokenKind::Punctuator(Punctuator::CloseParen) => {
let span = next.span(); let span = next.span();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
span span
} }
TokenKind::Punctuator(Punctuator::Spread) => { TokenKind::Punctuator(Punctuator::Spread) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let next = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next = cursor.peek(0, interner).or_abrupt()?;
match next.kind() { match next.kind() {
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {
let bindings = let bindings =
@ -375,27 +372,26 @@ where
.parse(cursor, interner)?; .parse(cursor, interner)?;
expressions.push(InnerExpression::Expression(expression)); expressions.push(InnerExpression::Expression(expression));
let next = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next = cursor.peek(0, interner).or_abrupt()?;
match next.kind() { match next.kind() {
TokenKind::Punctuator(Punctuator::CloseParen) => { TokenKind::Punctuator(Punctuator::CloseParen) => {
let span = next.span(); let span = next.span();
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
span span
} }
TokenKind::Punctuator(Punctuator::Comma) => { TokenKind::Punctuator(Punctuator::Comma) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let next = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next = cursor.peek(0, interner).or_abrupt()?;
match next.kind() { match next.kind() {
TokenKind::Punctuator(Punctuator::CloseParen) => { TokenKind::Punctuator(Punctuator::CloseParen) => {
let span = next.span(); let span = next.span();
tailing_comma = Some(next.span()); tailing_comma = Some(next.span());
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
span span
} }
TokenKind::Punctuator(Punctuator::Spread) => { TokenKind::Punctuator(Punctuator::Spread) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let next = let next = cursor.peek(0, interner).or_abrupt()?;
cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
match next.kind() { match next.kind() {
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {
let bindings = ObjectBindingPattern::new( let bindings = ObjectBindingPattern::new(
@ -456,9 +452,7 @@ where
let is_arrow = if let Some(TokenKind::Punctuator(Punctuator::Arrow)) = let is_arrow = if let Some(TokenKind::Punctuator(Punctuator::Arrow)) =
cursor.peek(0, interner)?.map(Token::kind) cursor.peek(0, interner)?.map(Token::kind)
{ {
!cursor !cursor.peek_is_line_terminator(0, interner).or_abrupt()?
.peek_is_line_terminator(0, interner)?
.ok_or(ParseError::AbruptEnd)?
} else { } else {
false false
}; };
@ -557,7 +551,7 @@ fn expression_to_formal_parameters(
parameters: &mut Vec<FormalParameter>, parameters: &mut Vec<FormalParameter>,
strict: bool, strict: bool,
span: Span, span: Span,
) -> Result<(), ParseError> { ) -> ParseResult<()> {
match node { match node {
ast::Expression::Identifier(identifier) if strict && *identifier == Sym::EVAL => { ast::Expression::Identifier(identifier) if strict && *identifier == Sym::EVAL => {
return Err(ParseError::general( return Err(ParseError::general(

79
boa_engine/src/syntax/parser/expression/primary/object_initializer/mod.rs

@ -15,8 +15,8 @@ use crate::syntax::{
parser::{ parser::{
expression::{identifiers::IdentifierReference, AssignmentExpression}, expression::{identifiers::IdentifierReference, AssignmentExpression},
function::{FormalParameter, FormalParameters, FunctionBody, UniqueFormalParameters}, function::{FormalParameter, FormalParameters, FunctionBody, UniqueFormalParameters},
name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, ParseError, name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, OrAbrupt,
ParseResult, TokenParser, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -89,7 +89,7 @@ where
} }
if cursor.next_if(Punctuator::Comma, interner)?.is_none() { if cursor.next_if(Punctuator::Comma, interner)?.is_none() {
let next_token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.next(interner).or_abrupt()?;
return Err(ParseError::expected( return Err(ParseError::expected(
[",".to_owned(), "}".to_owned()], [",".to_owned(), "}".to_owned()],
next_token.to_string(interner), next_token.to_string(interner),
@ -138,11 +138,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("PropertyDefinition", "Parsing"); let _timer = Profiler::global().start_event("PropertyDefinition", "Parsing");
match cursor match cursor.peek(1, interner).or_abrupt()?.kind() {
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::CloseBlock | Punctuator::Comma) => { TokenKind::Punctuator(Punctuator::CloseBlock | Punctuator::Comma) => {
let ident = IdentifierReference::new(self.allow_yield, self.allow_await) let ident = IdentifierReference::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -167,13 +163,10 @@ where
//Async [AsyncMethod, AsyncGeneratorMethod] object methods //Async [AsyncMethod, AsyncGeneratorMethod] object methods
let is_keyword = !matches!( let is_keyword = !matches!(
cursor cursor.peek(1, interner).or_abrupt()?.kind(),
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind(),
TokenKind::Punctuator(Punctuator::OpenParen | Punctuator::Colon) TokenKind::Punctuator(Punctuator::OpenParen | Punctuator::Colon)
); );
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Keyword((Keyword::Async, true)) if is_keyword => { TokenKind::Keyword((Keyword::Async, true)) if is_keyword => {
return Err(ParseError::general( return Err(ParseError::general(
@ -182,10 +175,10 @@ where
)); ));
} }
TokenKind::Keyword((Keyword::Async, false)) if is_keyword => { TokenKind::Keyword((Keyword::Async, false)) if is_keyword => {
cursor.next(interner)?.expect("token disappeared"); cursor.advance(interner);
cursor.peek_expect_no_lineterminator(0, "Async object methods", interner)?; cursor.peek_expect_no_lineterminator(0, "Async object methods", interner)?;
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let position = token.span().start(); let position = token.span().start();
if let TokenKind::Punctuator(Punctuator::Mul) = token.kind() { if let TokenKind::Punctuator(Punctuator::Mul) = token.kind() {
@ -238,17 +231,8 @@ where
_ => {} _ => {}
} }
if cursor if cursor.peek(0, interner).or_abrupt()?.kind() == &TokenKind::Punctuator(Punctuator::Mul) {
.peek(0, interner)? let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.ok_or(ParseError::AbruptEnd)?
.kind()
== &TokenKind::Punctuator(Punctuator::Mul)
{
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let (class_element_name, method) = let (class_element_name, method) =
GeneratorMethod::new(self.allow_yield, self.allow_await).parse(cursor, interner)?; GeneratorMethod::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
@ -283,20 +267,13 @@ where
return Ok(property::PropertyDefinition::Property(property_name, value)); return Ok(property::PropertyDefinition::Property(property_name, value));
} }
let ordinary_method = cursor let ordinary_method = cursor.peek(0, interner).or_abrupt()?.kind()
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== &TokenKind::Punctuator(Punctuator::OpenParen); == &TokenKind::Punctuator(Punctuator::OpenParen);
match property_name { match property_name {
// MethodDefinition[?Yield, ?Await] -> get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] } // MethodDefinition[?Yield, ?Await] -> get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] }
property::PropertyName::Literal(str) if str == Sym::GET && !ordinary_method => { property::PropertyName::Literal(str) if str == Sym::GET && !ordinary_method => {
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
property_name = PropertyName::new(self.allow_yield, self.allow_await) property_name = PropertyName::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -507,10 +484,10 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("PropertyName", "Parsing"); let _timer = Profiler::global().start_event("PropertyName", "Parsing");
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let name = match token.kind() { let name = match token.kind() {
TokenKind::Punctuator(Punctuator::OpenBracket) => { TokenKind::Punctuator(Punctuator::OpenBracket) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let node = let node =
AssignmentExpression::new(None, false, self.allow_yield, self.allow_await) AssignmentExpression::new(None, false, self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -534,7 +511,7 @@ where
}, },
_ => return Err(ParseError::AbruptEnd), _ => return Err(ParseError::AbruptEnd),
}; };
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(name) Ok(name)
} }
} }
@ -574,14 +551,10 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("ClassElementName", "Parsing"); let _timer = Profiler::global().start_event("ClassElementName", "Parsing");
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::PrivateIdentifier(ident) => { TokenKind::PrivateIdentifier(ident) => {
let ident = *ident; let ident = *ident;
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(property::ClassElementName::PrivateIdentifier(ident)) Ok(property::ClassElementName::PrivateIdentifier(ident))
} }
_ => Ok(property::ClassElementName::PropertyName( _ => Ok(property::ClassElementName::PropertyName(
@ -682,11 +655,7 @@ where
let class_element_name = let class_element_name =
ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?; ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let params_start_position = cursor let params_start_position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let params = UniqueFormalParameters::new(true, false).parse(cursor, interner)?; let params = UniqueFormalParameters::new(true, false).parse(cursor, interner)?;
@ -778,11 +747,7 @@ where
let name = let name =
ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?; ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let params_start_position = cursor let params_start_position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let params = UniqueFormalParameters::new(true, true).parse(cursor, interner)?; let params = UniqueFormalParameters::new(true, true).parse(cursor, interner)?;
@ -888,11 +853,7 @@ where
let class_element_name = let class_element_name =
ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?; ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let params_start_position = cursor let params_start_position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let params = UniqueFormalParameters::new(false, true).parse(cursor, interner)?; let params = UniqueFormalParameters::new(false, true).parse(cursor, interner)?;

24
boa_engine/src/syntax/parser/expression/unary.rs

@ -11,7 +11,7 @@ use crate::syntax::{
lexer::{Error as LexError, TokenKind}, lexer::{Error as LexError, TokenKind},
parser::{ parser::{
expression::{await_expr::AwaitExpression, update::UpdateExpression}, expression::{await_expr::AwaitExpression, update::UpdateExpression},
AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -66,19 +66,15 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("UnaryExpression", "Parsing"); let _timer = Profiler::global().start_event("UnaryExpression", "Parsing");
let tok = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let tok = cursor.peek(0, interner).or_abrupt()?;
let token_start = tok.span().start(); let token_start = tok.span().start();
match tok.kind() { match tok.kind() {
TokenKind::Keyword((Keyword::Delete | Keyword::Void | Keyword::TypeOf, true)) => Err( TokenKind::Keyword((Keyword::Delete | Keyword::Void | Keyword::TypeOf, true)) => Err(
ParseError::general("Keyword must not contain escaped characters", token_start), ParseError::general("Keyword must not contain escaped characters", token_start),
), ),
TokenKind::Keyword((Keyword::Delete, false)) => { TokenKind::Keyword((Keyword::Delete, false)) => {
cursor.next(interner)?.expect("Delete keyword vanished"); cursor.advance(interner);
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let val = self.parse(cursor, interner)?; let val = self.parse(cursor, interner)?;
match val { match val {
@ -100,27 +96,27 @@ where
Ok(Unary::new(UnaryOp::Delete, val).into()) Ok(Unary::new(UnaryOp::Delete, val).into())
} }
TokenKind::Keyword((Keyword::Void, false)) => { TokenKind::Keyword((Keyword::Void, false)) => {
cursor.next(interner)?.expect("Void keyword vanished"); // Consume the token. cursor.advance(interner);
Ok(Unary::new(UnaryOp::Void, self.parse(cursor, interner)?).into()) Ok(Unary::new(UnaryOp::Void, self.parse(cursor, interner)?).into())
} }
TokenKind::Keyword((Keyword::TypeOf, false)) => { TokenKind::Keyword((Keyword::TypeOf, false)) => {
cursor.next(interner)?.expect("TypeOf keyword vanished"); // Consume the token. cursor.advance(interner);
Ok(Unary::new(UnaryOp::TypeOf, self.parse(cursor, interner)?).into()) Ok(Unary::new(UnaryOp::TypeOf, self.parse(cursor, interner)?).into())
} }
TokenKind::Punctuator(Punctuator::Add) => { TokenKind::Punctuator(Punctuator::Add) => {
cursor.next(interner)?.expect("+ token vanished"); // Consume the token. cursor.advance(interner);
Ok(Unary::new(UnaryOp::Plus, self.parse(cursor, interner)?).into()) Ok(Unary::new(UnaryOp::Plus, self.parse(cursor, interner)?).into())
} }
TokenKind::Punctuator(Punctuator::Sub) => { TokenKind::Punctuator(Punctuator::Sub) => {
cursor.next(interner)?.expect("- token vanished"); // Consume the token. cursor.advance(interner);
Ok(Unary::new(UnaryOp::Minus, self.parse(cursor, interner)?).into()) Ok(Unary::new(UnaryOp::Minus, self.parse(cursor, interner)?).into())
} }
TokenKind::Punctuator(Punctuator::Neg) => { TokenKind::Punctuator(Punctuator::Neg) => {
cursor.next(interner)?.expect("~ token vanished"); // Consume the token. cursor.advance(interner);
Ok(Unary::new(UnaryOp::Tilde, self.parse(cursor, interner)?).into()) Ok(Unary::new(UnaryOp::Tilde, self.parse(cursor, interner)?).into())
} }
TokenKind::Punctuator(Punctuator::Not) => { TokenKind::Punctuator(Punctuator::Not) => {
cursor.next(interner)?.expect("! token vanished"); // Consume the token. cursor.advance(interner);
Ok(Unary::new(UnaryOp::Not, self.parse(cursor, interner)?).into()) Ok(Unary::new(UnaryOp::Not, self.parse(cursor, interner)?).into())
} }
TokenKind::Keyword((Keyword::Await, true)) if self.allow_await.0 => { TokenKind::Keyword((Keyword::Await, true)) if self.allow_await.0 => {

4
boa_engine/src/syntax/parser/expression/update.rs

@ -9,7 +9,7 @@ use super::{check_strict_arguments_or_eval, left_hand_side::LeftHandSideExpressi
use crate::syntax::{ use crate::syntax::{
lexer::{Error as LexError, TokenKind}, lexer::{Error as LexError, TokenKind},
parser::{ parser::{
expression::unary::UnaryExpression, AllowAwait, AllowYield, Cursor, ParseError, expression::unary::UnaryExpression, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError,
ParseResult, TokenParser, ParseResult, TokenParser,
}, },
}; };
@ -62,7 +62,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("UpdateExpression", "Parsing"); let _timer = Profiler::global().start_event("UpdateExpression", "Parsing");
let tok = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let tok = cursor.peek(0, interner).or_abrupt()?;
let position = tok.span().start(); let position = tok.span().start();
match tok.kind() { match tok.kind() {
TokenKind::Punctuator(Punctuator::Inc) => { TokenKind::Punctuator(Punctuator::Inc) => {

29
boa_engine/src/syntax/parser/function/mod.rs

@ -29,7 +29,7 @@ use boa_macros::utf16;
use boa_profiler::Profiler; use boa_profiler::Profiler;
use std::io::Read; use std::io::Read;
use super::ParseResult; use super::{OrAbrupt, ParseResult};
/// Formal parameters parsing. /// Formal parameters parsing.
/// ///
@ -71,7 +71,7 @@ where
let mut params = Vec::new(); let mut params = Vec::new();
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
if next_token.kind() == &TokenKind::Punctuator(Punctuator::CloseParen) { if next_token.kind() == &TokenKind::Punctuator(Punctuator::CloseParen) {
return Ok(FormalParameterList::default()); return Ok(FormalParameterList::default());
} }
@ -99,10 +99,7 @@ where
params.push(next_param); params.push(next_param);
if cursor if cursor.peek(0, interner).or_abrupt()?.kind()
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== &TokenKind::Punctuator(Punctuator::CloseParen) == &TokenKind::Punctuator(Punctuator::CloseParen)
{ {
break; break;
@ -118,10 +115,7 @@ where
} }
cursor.expect(Punctuator::Comma, "parameter list", interner)?; cursor.expect(Punctuator::Comma, "parameter list", interner)?;
if cursor if cursor.peek(0, interner).or_abrupt()?.kind()
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== &TokenKind::Punctuator(Punctuator::CloseParen) == &TokenKind::Punctuator(Punctuator::CloseParen)
{ {
break; break;
@ -353,10 +347,7 @@ where
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {
let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await) let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let init = if *cursor let init = if *cursor.peek(0, interner).or_abrupt()?.kind()
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== TokenKind::Punctuator(Punctuator::Assign) == TokenKind::Punctuator(Punctuator::Assign)
{ {
Some( Some(
@ -372,10 +363,7 @@ where
TokenKind::Punctuator(Punctuator::OpenBracket) => { TokenKind::Punctuator(Punctuator::OpenBracket) => {
let bindings = ArrayBindingPattern::new(self.allow_yield, self.allow_await) let bindings = ArrayBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let init = if *cursor let init = if *cursor.peek(0, interner).or_abrupt()?.kind()
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== TokenKind::Punctuator(Punctuator::Assign) == TokenKind::Punctuator(Punctuator::Assign)
{ {
Some( Some(
@ -391,10 +379,7 @@ where
_ => { _ => {
let ident = BindingIdentifier::new(self.allow_yield, self.allow_await) let ident = BindingIdentifier::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let init = if *cursor let init = if *cursor.peek(0, interner).or_abrupt()?.kind()
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== TokenKind::Punctuator(Punctuator::Assign) == TokenKind::Punctuator(Punctuator::Assign)
{ {
Some( Some(

25
boa_engine/src/syntax/parser/mod.rs

@ -133,7 +133,7 @@ impl<R> Parser<R> {
/// The resulting `StatementList` can be compiled into boa bytecode and executed in the boa vm. /// The resulting `StatementList` can be compiled into boa bytecode and executed in the boa vm.
/// ///
/// [spec]: https://tc39.es/ecma262/#prod-Script /// [spec]: https://tc39.es/ecma262/#prod-Script
pub fn parse_all(&mut self, context: &mut Context) -> Result<StatementList, ParseError> pub fn parse_all(&mut self, context: &mut Context) -> ParseResult<StatementList>
where where
R: Read, R: Read,
{ {
@ -149,7 +149,7 @@ impl<R> Parser<R> {
&mut self, &mut self,
direct: bool, direct: bool,
context: &mut Context, context: &mut Context,
) -> Result<StatementList, ParseError> ) -> ParseResult<StatementList>
where where
R: Read, R: Read,
{ {
@ -241,7 +241,7 @@ impl<R> Parser<R> {
interner: &mut Interner, interner: &mut Interner,
allow_yield: bool, allow_yield: bool,
allow_await: bool, allow_await: bool,
) -> Result<StatementList, ParseError> ) -> ParseResult<StatementList>
where where
R: Read, R: Read,
{ {
@ -256,7 +256,7 @@ impl<R> Parser<R> {
interner: &mut Interner, interner: &mut Interner,
allow_yield: bool, allow_yield: bool,
allow_await: bool, allow_await: bool,
) -> Result<FormalParameterList, ParseError> ) -> ParseResult<FormalParameterList>
where where
R: Read, R: Read,
{ {
@ -285,7 +285,7 @@ impl Script {
self, self,
cursor: &mut Cursor<R>, cursor: &mut Cursor<R>,
context: &mut Context, context: &mut Context,
) -> Result<StatementList, ParseError> { ) -> ParseResult<StatementList> {
let mut strict = cursor.strict_mode(); let mut strict = cursor.strict_mode();
match cursor.peek(0, context.interner_mut())? { match cursor.peek(0, context.interner_mut())? {
Some(tok) => { Some(tok) => {
@ -393,7 +393,7 @@ fn name_in_lexically_declared_names(
bound_names: &[Identifier], bound_names: &[Identifier],
lexical_names: &[Identifier], lexical_names: &[Identifier],
position: Position, position: Position,
) -> Result<(), ParseError> { ) -> ParseResult<()> {
for name in bound_names { for name in bound_names {
if lexical_names.contains(name) { if lexical_names.contains(name) {
return Err(ParseError::General { return Err(ParseError::General {
@ -404,3 +404,16 @@ fn name_in_lexically_declared_names(
} }
Ok(()) Ok(())
} }
/// Trait to reduce boilerplate in the parser.
trait OrAbrupt<T> {
/// Will convert an `Ok(None)` to a [`ParseError::AbruptEnd`] or return the inner type if not.
fn or_abrupt(self) -> ParseResult<T>;
}
impl<T> OrAbrupt<T> for ParseResult<Option<T>> {
#[inline]
fn or_abrupt(self) -> ParseResult<T> {
self?.ok_or(ParseError::AbruptEnd)
}
}

12
boa_engine/src/syntax/parser/statement/block/mod.rs

@ -13,7 +13,9 @@ mod tests;
use super::StatementList; use super::StatementList;
use crate::syntax::{ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser}, parser::{
AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
},
}; };
use boa_ast::{ use boa_ast::{
operations::{lexically_declared_names_legacy, var_declared_names}, operations::{lexically_declared_names_legacy, var_declared_names},
@ -77,15 +79,11 @@ where
cursor.expect(Punctuator::OpenBlock, "block", interner)?; cursor.expect(Punctuator::OpenBlock, "block", interner)?;
if let Some(tk) = cursor.peek(0, interner)? { if let Some(tk) = cursor.peek(0, interner)? {
if tk.kind() == &TokenKind::Punctuator(Punctuator::CloseBlock) { if tk.kind() == &TokenKind::Punctuator(Punctuator::CloseBlock) {
cursor.next(interner)?.expect("} token vanished"); cursor.advance(interner);
return Ok(statement::Block::from(vec![])); return Ok(statement::Block::from(vec![]));
} }
} }
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let statement_list = StatementList::new( let statement_list = StatementList::new(
self.allow_yield, self.allow_yield,
self.allow_await, self.allow_await,

2
boa_engine/src/syntax/parser/statement/break_stm/mod.rs

@ -64,7 +64,7 @@ where
let label = if let SemicolonResult::Found(tok) = cursor.peek_semicolon(interner)? { let label = if let SemicolonResult::Found(tok) = cursor.peek_semicolon(interner)? {
match tok { match tok {
Some(tok) if tok.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) => { Some(tok) if tok.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) => {
let _next = cursor.next(interner)?; cursor.advance(interner);
} }
_ => {} _ => {}
} }

4
boa_engine/src/syntax/parser/statement/continue_stm/mod.rs

@ -64,11 +64,11 @@ where
let label = if let SemicolonResult::Found(tok) = cursor.peek_semicolon(interner)? { let label = if let SemicolonResult::Found(tok) = cursor.peek_semicolon(interner)? {
if let Some(token) = tok { if let Some(token) = tok {
if token.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) { if token.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) {
cursor.next(interner)?; cursor.advance(interner);
} else if token.kind() == &TokenKind::LineTerminator { } else if token.kind() == &TokenKind::LineTerminator {
if let Some(token) = cursor.peek(0, interner)? { if let Some(token) = cursor.peek(0, interner)? {
if token.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) { if token.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) {
cursor.next(interner)?; cursor.advance(interner);
} }
} }
} }

77
boa_engine/src/syntax/parser/statement/declaration/hoistable/class_decl/mod.rs

@ -10,7 +10,8 @@ use crate::syntax::{
}, },
function::{FormalParameters, FunctionBody, UniqueFormalParameters, FUNCTION_BREAK_TOKENS}, function::{FormalParameters, FunctionBody, UniqueFormalParameters, FUNCTION_BREAK_TOKENS},
statement::StatementList, statement::StatementList,
AllowAwait, AllowDefault, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowAwait, AllowDefault, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser,
}, },
}; };
use ast::operations::{lexically_declared_names, var_declared_names}; use ast::operations::{lexically_declared_names, var_declared_names};
@ -68,7 +69,7 @@ where
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let name = match token.kind() { let name = match token.kind() {
TokenKind::Identifier(_) | TokenKind::Keyword((Keyword::Yield | Keyword::Await, _)) => { TokenKind::Identifier(_) | TokenKind::Keyword((Keyword::Yield | Keyword::Await, _)) => {
BindingIdentifier::new(self.allow_yield, self.allow_await) BindingIdentifier::new(self.allow_yield, self.allow_await)
@ -130,7 +131,7 @@ where
type Output = Class; type Output = Class;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let super_ref = match token.kind() { let super_ref = match token.kind() {
TokenKind::Keyword((Keyword::Extends, true)) => { TokenKind::Keyword((Keyword::Extends, true)) => {
return Err(ParseError::general( return Err(ParseError::general(
@ -149,22 +150,15 @@ where
// Temporarily disable strict mode because "strict" may be parsed as a keyword. // Temporarily disable strict mode because "strict" may be parsed as a keyword.
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(false); cursor.set_strict_mode(false);
let is_close_block = cursor let is_close_block = cursor.peek(0, interner).or_abrupt()?.kind()
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== &TokenKind::Punctuator(Punctuator::CloseBlock); == &TokenKind::Punctuator(Punctuator::CloseBlock);
cursor.set_strict_mode(strict); cursor.set_strict_mode(strict);
if is_close_block { if is_close_block {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
Ok(Class::new(Some(self.name), super_ref, None, Box::default())) Ok(Class::new(Some(self.name), super_ref, None, Box::default()))
} else { } else {
let body_start = cursor let body_start = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let (constructor, elements) = let (constructor, elements) =
ClassBody::new(self.name, self.allow_yield, self.allow_await) ClassBody::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -290,7 +284,7 @@ where
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(false); cursor.set_strict_mode(false);
loop { loop {
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let position = token.span().start(); let position = token.span().start();
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::CloseBlock) => break, TokenKind::Punctuator(Punctuator::CloseBlock) => break,
@ -550,14 +544,14 @@ where
type Output = (Option<Function>, Option<function::ClassElement>); type Output = (Option<Function>, Option<function::ClassElement>);
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let r#static = match token.kind() { let r#static = match token.kind() {
TokenKind::Punctuator(Punctuator::Semicolon) => { TokenKind::Punctuator(Punctuator::Semicolon) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
return Ok((None, None)); return Ok((None, None));
} }
TokenKind::Identifier(Sym::STATIC) => { TokenKind::Identifier(Sym::STATIC) => {
let token = cursor.peek(1, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(1, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Identifier(_) TokenKind::Identifier(_)
| TokenKind::StringLiteral(_) | TokenKind::StringLiteral(_)
@ -569,7 +563,7 @@ where
Punctuator::OpenBracket | Punctuator::Mul | Punctuator::OpenBlock, Punctuator::OpenBracket | Punctuator::Mul | Punctuator::OpenBlock,
) => { ) => {
// this "static" is a keyword. // this "static" is a keyword.
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
true true
} }
_ => false, _ => false,
@ -579,10 +573,7 @@ where
}; };
let is_keyword = !matches!( let is_keyword = !matches!(
cursor cursor.peek(1, interner).or_abrupt()?.kind(),
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind(),
TokenKind::Punctuator( TokenKind::Punctuator(
Punctuator::Assign Punctuator::Assign
| Punctuator::CloseBlock | Punctuator::CloseBlock
@ -591,11 +582,11 @@ where
) )
); );
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let position = token.span().start(); let position = token.span().start();
let element = match token.kind() { let element = match token.kind() {
TokenKind::Identifier(Sym::CONSTRUCTOR) if !r#static => { TokenKind::Identifier(Sym::CONSTRUCTOR) if !r#static => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);
@ -620,7 +611,7 @@ where
return Ok((Some(Function::new(Some(self.name), parameters, body)), None)); return Ok((Some(Function::new(Some(self.name), parameters, body)), None));
} }
TokenKind::Punctuator(Punctuator::OpenBlock) if r#static => { TokenKind::Punctuator(Punctuator::OpenBlock) if r#static => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let statement_list = if cursor let statement_list = if cursor
.next_if(TokenKind::Punctuator(Punctuator::CloseBlock), interner)? .next_if(TokenKind::Punctuator(Punctuator::CloseBlock), interner)?
.is_some() .is_some()
@ -629,11 +620,7 @@ where
} else { } else {
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let statement_list = let statement_list =
StatementList::new(false, true, false, &FUNCTION_BREAK_TOKENS) StatementList::new(false, true, false, &FUNCTION_BREAK_TOKENS)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -668,7 +655,7 @@ where
function::ClassElement::StaticBlock(statement_list) function::ClassElement::StaticBlock(statement_list)
} }
TokenKind::Punctuator(Punctuator::Mul) => { TokenKind::Punctuator(Punctuator::Mul) => {
let token = cursor.peek(1, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(1, interner).or_abrupt()?;
let name_position = token.span().start(); let name_position = token.span().start();
if let TokenKind::Identifier(Sym::CONSTRUCTOR) = token.kind() { if let TokenKind::Identifier(Sym::CONSTRUCTOR) = token.kind() {
return Err(ParseError::general( return Err(ParseError::general(
@ -717,12 +704,12 @@ where
)); ));
} }
TokenKind::Keyword((Keyword::Async, false)) if is_keyword => { TokenKind::Keyword((Keyword::Async, false)) if is_keyword => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
cursor.peek_expect_no_lineterminator(0, "Async object methods", interner)?; cursor.peek_expect_no_lineterminator(0, "Async object methods", interner)?;
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::Mul) => { TokenKind::Punctuator(Punctuator::Mul) => {
let token = cursor.peek(1, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(1, interner).or_abrupt()?;
let name_position = token.span().start(); let name_position = token.span().start();
match token.kind() { match token.kind() {
TokenKind::Identifier(Sym::CONSTRUCTOR) TokenKind::Identifier(Sym::CONSTRUCTOR)
@ -820,8 +807,8 @@ where
} }
} }
TokenKind::Identifier(Sym::GET) if is_keyword => { TokenKind::Identifier(Sym::GET) if is_keyword => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::PrivateIdentifier(Sym::CONSTRUCTOR) => { TokenKind::PrivateIdentifier(Sym::CONSTRUCTOR) => {
return Err(ParseError::general( return Err(ParseError::general(
@ -831,7 +818,7 @@ where
} }
TokenKind::PrivateIdentifier(name) => { TokenKind::PrivateIdentifier(name) => {
let name = *name; let name = *name;
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);
let params = let params =
@ -941,8 +928,8 @@ where
} }
} }
TokenKind::Identifier(Sym::SET) if is_keyword => { TokenKind::Identifier(Sym::SET) if is_keyword => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::PrivateIdentifier(Sym::CONSTRUCTOR) => { TokenKind::PrivateIdentifier(Sym::CONSTRUCTOR) => {
return Err(ParseError::general( return Err(ParseError::general(
@ -952,7 +939,7 @@ where
} }
TokenKind::PrivateIdentifier(name) => { TokenKind::PrivateIdentifier(name) => {
let name = *name; let name = *name;
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);
let params = let params =
@ -1066,11 +1053,11 @@ where
} }
TokenKind::PrivateIdentifier(name) => { TokenKind::PrivateIdentifier(name) => {
let name = *name; let name = *name;
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::Assign) => { TokenKind::Punctuator(Punctuator::Assign) => {
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);
let rhs = AssignmentExpression::new( let rhs = AssignmentExpression::new(
@ -1141,7 +1128,7 @@ where
let name_position = token.span().start(); let name_position = token.span().start();
let name = PropertyName::new(self.allow_yield, self.allow_await) let name = PropertyName::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::Assign) => { TokenKind::Punctuator(Punctuator::Assign) => {
if let Some(name) = name.prop_name() { if let Some(name) = name.prop_name() {
@ -1159,7 +1146,7 @@ where
)); ));
} }
} }
cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
cursor.set_strict_mode(true); cursor.set_strict_mode(true);
let rhs = AssignmentExpression::new( let rhs = AssignmentExpression::new(

13
boa_engine/src/syntax/parser/statement/declaration/hoistable/mod.rs

@ -26,7 +26,8 @@ use crate::syntax::{
function::{FormalParameters, FunctionBody}, function::{FormalParameters, FunctionBody},
name_in_lexically_declared_names, name_in_lexically_declared_names,
statement::LexError, statement::LexError,
AllowAwait, AllowDefault, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowAwait, AllowDefault, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -78,7 +79,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("HoistableDeclaration", "Parsing"); let _timer = Profiler::global().start_event("HoistableDeclaration", "Parsing");
let tok = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let tok = cursor.peek(0, interner).or_abrupt()?;
match tok.kind() { match tok.kind() {
TokenKind::Keyword((Keyword::Function | Keyword::Async | Keyword::Class, true)) => { TokenKind::Keyword((Keyword::Function | Keyword::Async | Keyword::Class, true)) => {
@ -88,7 +89,7 @@ where
)) ))
} }
TokenKind::Keyword((Keyword::Function, false)) => { TokenKind::Keyword((Keyword::Function, false)) => {
let next_token = cursor.peek(1, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(1, interner).or_abrupt()?;
if let TokenKind::Punctuator(Punctuator::Mul) = next_token.kind() { if let TokenKind::Punctuator(Punctuator::Mul) = next_token.kind() {
GeneratorDeclaration::new(self.allow_yield, self.allow_await, self.is_default) GeneratorDeclaration::new(self.allow_yield, self.allow_await, self.is_default)
.parse(cursor, interner) .parse(cursor, interner)
@ -100,7 +101,7 @@ where
} }
} }
TokenKind::Keyword((Keyword::Async, false)) => { TokenKind::Keyword((Keyword::Async, false)) => {
let next_token = cursor.peek(2, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(2, interner).or_abrupt()?;
if let TokenKind::Punctuator(Punctuator::Mul) = next_token.kind() { if let TokenKind::Punctuator(Punctuator::Mul) = next_token.kind() {
AsyncGeneratorDeclaration::new( AsyncGeneratorDeclaration::new(
self.allow_yield, self.allow_yield,
@ -142,8 +143,8 @@ fn parse_callable_declaration<R: Read, C: CallableDeclaration>(
c: &C, c: &C,
cursor: &mut Cursor<R>, cursor: &mut Cursor<R>,
interner: &mut Interner, interner: &mut Interner,
) -> Result<(Identifier, FormalParameterList, StatementList), ParseError> { ) -> ParseResult<(Identifier, FormalParameterList, StatementList)> {
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
let name = match next_token.kind() { let name = match next_token.kind() {
TokenKind::Punctuator(Punctuator::OpenParen) => { TokenKind::Punctuator(Punctuator::OpenParen) => {
if !c.is_default() { if !c.is_default() {

12
boa_engine/src/syntax/parser/statement/declaration/lexical.rs

@ -13,7 +13,7 @@ use crate::syntax::{
cursor::{Cursor, SemicolonResult}, cursor::{Cursor, SemicolonResult},
expression::Initializer, expression::Initializer,
statement::{ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern}, statement::{ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern},
AllowAwait, AllowIn, AllowYield, ParseError, ParseResult, TokenParser, AllowAwait, AllowIn, AllowYield, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use ast::operations::bound_names; use ast::operations::bound_names;
@ -66,7 +66,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("LexicalDeclaration", "Parsing"); let _timer = Profiler::global().start_event("LexicalDeclaration", "Parsing");
let tok = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let tok = cursor.next(interner).or_abrupt()?;
match tok.kind() { match tok.kind() {
TokenKind::Keyword((Keyword::Const | Keyword::Let, true)) => Err(ParseError::general( TokenKind::Keyword((Keyword::Const | Keyword::Let, true)) => Err(ParseError::general(
@ -159,7 +159,7 @@ where
if init_is_some || self.loop_init { if init_is_some || self.loop_init {
decls.push(decl); decls.push(decl);
} else { } else {
let next = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let next = cursor.next(interner).or_abrupt()?;
return Err(ParseError::general( return Err(ParseError::general(
"Expected initializer for const declaration", "Expected initializer for const declaration",
next.span().start(), next.span().start(),
@ -190,11 +190,11 @@ where
if tk.kind() == &TokenKind::Punctuator(Punctuator::Comma) => if tk.kind() == &TokenKind::Punctuator(Punctuator::Comma) =>
{ {
// We discard the comma // We discard the comma
let _comma = cursor.next(interner)?; cursor.advance(interner);
} }
SemicolonResult::NotFound(_) if self.loop_init => break, SemicolonResult::NotFound(_) if self.loop_init => break,
SemicolonResult::NotFound(_) => { SemicolonResult::NotFound(_) => {
let next = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let next = cursor.next(interner).or_abrupt()?;
return Err(ParseError::expected( return Err(ParseError::expected(
[";".to_owned(), "line terminator".to_owned()], [";".to_owned(), "line terminator".to_owned()],
next.to_string(interner), next.to_string(interner),
@ -254,7 +254,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("LexicalBinding", "Parsing"); let _timer = Profiler::global().start_event("LexicalBinding", "Parsing");
let peek_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let peek_token = cursor.peek(0, interner).or_abrupt()?;
let position = peek_token.span().start(); let position = peek_token.span().start();
match peek_token.kind() { match peek_token.kind() {

4
boa_engine/src/syntax/parser/statement/declaration/mod.rs

@ -20,7 +20,7 @@ pub(in crate::syntax::parser) use lexical::LexicalDeclaration;
use crate::syntax::{ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser}, parser::{AllowAwait, AllowYield, Cursor, OrAbrupt, ParseResult, TokenParser},
}; };
use boa_ast::{self as ast, Keyword}; use boa_ast::{self as ast, Keyword};
use boa_interner::Interner; use boa_interner::Interner;
@ -60,7 +60,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("Declaration", "Parsing"); let _timer = Profiler::global().start_event("Declaration", "Parsing");
let tok = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let tok = cursor.peek(0, interner).or_abrupt()?;
match tok.kind() { match tok.kind() {
TokenKind::Keyword((Keyword::Function | Keyword::Async | Keyword::Class, _)) => { TokenKind::Keyword((Keyword::Function | Keyword::Async | Keyword::Class, _)) => {

8
boa_engine/src/syntax/parser/statement/expression/mod.rs

@ -1,7 +1,7 @@
use crate::syntax::{ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
expression::Expression, AllowAwait, AllowYield, Cursor, ParseError, ParseResult, expression::Expression, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser, TokenParser,
}, },
}; };
@ -45,7 +45,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("ExpressionStatement", "Parsing"); let _timer = Profiler::global().start_event("ExpressionStatement", "Parsing");
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
match next_token.kind() { match next_token.kind() {
TokenKind::Keyword(( TokenKind::Keyword((
Keyword::Function | Keyword::Class | Keyword::Async | Keyword::Let, Keyword::Function | Keyword::Class | Keyword::Async | Keyword::Let,
@ -63,7 +63,7 @@ where
)); ));
} }
TokenKind::Keyword((Keyword::Async, false)) => { TokenKind::Keyword((Keyword::Async, false)) => {
let next_token = cursor.peek(1, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(1, interner).or_abrupt()?;
match next_token.kind() { match next_token.kind() {
TokenKind::Keyword((Keyword::Function, true)) => { TokenKind::Keyword((Keyword::Function, true)) => {
return Err(ParseError::general( return Err(ParseError::general(
@ -81,7 +81,7 @@ where
} }
} }
TokenKind::Keyword((Keyword::Let, false)) => { TokenKind::Keyword((Keyword::Let, false)) => {
let next_token = cursor.peek(1, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(1, interner).or_abrupt()?;
if next_token.kind() == &TokenKind::Punctuator(Punctuator::OpenBracket) { if next_token.kind() == &TokenKind::Punctuator(Punctuator::OpenBracket) {
return Err(ParseError::general( return Err(ParseError::general(
"expected statement", "expected statement",

8
boa_engine/src/syntax/parser/statement/if_stm/mod.rs

@ -5,7 +5,7 @@ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
expression::Expression, statement::declaration::FunctionDeclaration, AllowAwait, expression::Expression, statement::declaration::FunctionDeclaration, AllowAwait,
AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -72,7 +72,7 @@ where
.end(); .end();
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let then_node = match token.kind() { let then_node = match token.kind() {
TokenKind::Keyword((Keyword::Function, _)) => { TokenKind::Keyword((Keyword::Function, _)) => {
// FunctionDeclarations in IfStatement Statement Clauses // FunctionDeclarations in IfStatement Statement Clauses
@ -108,10 +108,10 @@ where
)); ));
} }
TokenKind::Keyword((Keyword::Else, false)) => { TokenKind::Keyword((Keyword::Else, false)) => {
cursor.next(interner)?.expect("token disappeared"); cursor.advance(interner);
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let position = token.span().start(); let position = token.span().start();
let stmt = match token.kind() { let stmt = match token.kind() {
TokenKind::Keyword((Keyword::Function, _)) => { TokenKind::Keyword((Keyword::Function, _)) => {

12
boa_engine/src/syntax/parser/statement/iteration/do_while_statement.rs

@ -11,7 +11,7 @@ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
expression::Expression, statement::Statement, AllowAwait, AllowReturn, AllowYield, Cursor, expression::Expression, statement::Statement, AllowAwait, AllowReturn, AllowYield, Cursor,
ParseError, ParseResult, TokenParser, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{statement::DoWhileLoop, Keyword, Punctuator}; use boa_ast::{statement::DoWhileLoop, Keyword, Punctuator};
@ -65,11 +65,7 @@ where
cursor.expect((Keyword::Do, false), "do while statement", interner)?; cursor.expect((Keyword::Do, false), "do while statement", interner)?;
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return) let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -79,7 +75,7 @@ where
return Err(ParseError::wrong_labelled_function_declaration(position)); return Err(ParseError::wrong_labelled_function_declaration(position));
} }
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
match next_token.kind() { match next_token.kind() {
TokenKind::Keyword((Keyword::While, true)) => { TokenKind::Keyword((Keyword::While, true)) => {
return Err(ParseError::general( return Err(ParseError::general(
@ -112,7 +108,7 @@ where
// https://tc39.es/ecma262/#sec-automatic-semicolon-insertion // https://tc39.es/ecma262/#sec-automatic-semicolon-insertion
if let Some(tok) = cursor.peek(0, interner)? { if let Some(tok) = cursor.peek(0, interner)? {
if let TokenKind::Punctuator(Punctuator::Semicolon) = *tok.kind() { if let TokenKind::Punctuator(Punctuator::Semicolon) = *tok.kind() {
cursor.next(interner)?; cursor.advance(interner);
} }
} }

37
boa_engine/src/syntax/parser/statement/iteration/for_statement.rs

@ -13,7 +13,8 @@ use crate::syntax::{
expression::Expression, expression::Expression,
statement::declaration::LexicalDeclaration, statement::declaration::LexicalDeclaration,
statement::{variable::VariableDeclarationList, Statement}, statement::{variable::VariableDeclarationList, Statement},
AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser,
}, },
}; };
use ast::operations::{bound_names, var_declared_names}; use ast::operations::{bound_names, var_declared_names};
@ -77,7 +78,7 @@ where
let mut r#await = false; let mut r#await = false;
let next = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let next = cursor.next(interner).or_abrupt()?;
let init_position = match next.kind() { let init_position = match next.kind() {
TokenKind::Punctuator(Punctuator::OpenParen) => next.span().end(), TokenKind::Punctuator(Punctuator::OpenParen) => next.span().end(),
TokenKind::Keyword((Keyword::Await, _)) if !self.allow_await.0 => { TokenKind::Keyword((Keyword::Await, _)) if !self.allow_await.0 => {
@ -103,13 +104,9 @@ where
} }
}; };
let init = match cursor let init = match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Keyword((Keyword::Var, _)) => { TokenKind::Keyword((Keyword::Var, _)) => {
let _next = cursor.next(interner)?; cursor.advance(interner);
Some( Some(
VariableDeclarationList::new(false, self.allow_yield, self.allow_await) VariableDeclarationList::new(false, self.allow_yield, self.allow_await)
.parse(cursor, interner)? .parse(cursor, interner)?
@ -122,11 +119,7 @@ where
.into(), .into(),
), ),
TokenKind::Keyword((Keyword::Async, false)) => { TokenKind::Keyword((Keyword::Async, false)) => {
match cursor match cursor.peek(1, interner).or_abrupt()?.kind() {
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Keyword((Keyword::Of, _)) => { TokenKind::Keyword((Keyword::Of, _)) => {
return Err(ParseError::lex(LexError::Syntax( return Err(ParseError::lex(LexError::Syntax(
"invalid left-hand side expression 'async' of a for-of loop".into(), "invalid left-hand side expression 'async' of a for-of loop".into(),
@ -148,7 +141,7 @@ where
), ),
}; };
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
let position = token.span().start(); let position = token.span().start();
let init = match (init, token.kind()) { let init = match (init, token.kind()) {
(Some(_), TokenKind::Keyword((Keyword::In | Keyword::Of, true))) => { (Some(_), TokenKind::Keyword((Keyword::In | Keyword::Of, true))) => {
@ -168,17 +161,13 @@ where
let init = let init =
initializer_to_iterable_loop_initializer(init, position, cursor.strict_mode())?; initializer_to_iterable_loop_initializer(init, position, cursor.strict_mode())?;
let _next = cursor.next(interner)?; cursor.advance(interner);
let expr = Expression::new(None, true, self.allow_yield, self.allow_await) let expr = Expression::new(None, true, self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
cursor.expect(Punctuator::CloseParen, "for in/of statement", interner)?; cursor.expect(Punctuator::CloseParen, "for in/of statement", interner)?;
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return) let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -266,11 +255,7 @@ where
Some(step) Some(step)
}; };
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return) let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -304,7 +289,7 @@ fn initializer_to_iterable_loop_initializer(
initializer: ForLoopInitializer, initializer: ForLoopInitializer,
position: Position, position: Position,
strict: bool, strict: bool,
) -> Result<IterableLoopInitializer, ParseError> { ) -> ParseResult<IterableLoopInitializer> {
match initializer { match initializer {
ForLoopInitializer::Expression(expr) => match expr { ForLoopInitializer::Expression(expr) => match expr {
ast::Expression::Identifier(ident) ast::Expression::Identifier(ident)

8
boa_engine/src/syntax/parser/statement/iteration/while_statement.rs

@ -1,6 +1,6 @@
use crate::syntax::parser::{ use crate::syntax::parser::{
expression::Expression, statement::Statement, AllowAwait, AllowReturn, AllowYield, Cursor, expression::Expression, statement::Statement, AllowAwait, AllowReturn, AllowYield, Cursor,
ParseError, ParseResult, TokenParser, OrAbrupt, ParseError, ParseResult, TokenParser,
}; };
use boa_ast::{statement::WhileLoop, Keyword, Punctuator}; use boa_ast::{statement::WhileLoop, Keyword, Punctuator};
use boa_interner::Interner; use boa_interner::Interner;
@ -59,11 +59,7 @@ where
cursor.expect(Punctuator::CloseParen, "while statement", interner)?; cursor.expect(Punctuator::CloseParen, "while statement", interner)?;
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return) let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?; .parse(cursor, interner)?;

4
boa_engine/src/syntax/parser/statement/labelled_stm/mod.rs

@ -5,7 +5,7 @@ use crate::syntax::{
error::ParseError, error::ParseError,
expression::LabelIdentifier, expression::LabelIdentifier,
statement::{AllowAwait, AllowReturn, Statement}, statement::{AllowAwait, AllowReturn, Statement},
AllowYield, ParseResult, TokenParser, AllowYield, OrAbrupt, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{self as ast, Keyword, Punctuator}; use boa_ast::{self as ast, Keyword, Punctuator};
@ -61,7 +61,7 @@ where
cursor.expect(Punctuator::Colon, "Labelled Statement", interner)?; cursor.expect(Punctuator::Colon, "Labelled Statement", interner)?;
let strict = cursor.strict_mode(); let strict = cursor.strict_mode();
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
let labelled_item = match next_token.kind() { let labelled_item = match next_token.kind() {
// Early Error: It is a Syntax Error if any strict mode source code matches this rule. // Early Error: It is a Syntax Error if any strict mode source code matches this rule.

47
boa_engine/src/syntax/parser/statement/mod.rs

@ -37,8 +37,8 @@ use self::{
variable::VariableStatement, variable::VariableStatement,
}; };
use super::{ use super::{
expression::PropertyName, AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, expression::PropertyName, AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError,
TokenParser, ParseResult, TokenParser,
}; };
use crate::syntax::{ use crate::syntax::{
lexer::{Error as LexError, InputElement, Token, TokenKind}, lexer::{Error as LexError, InputElement, Token, TokenKind},
@ -114,7 +114,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("Statement", "Parsing"); let _timer = Profiler::global().start_event("Statement", "Parsing");
// TODO: add BreakableStatement and divide Whiles, fors and so on to another place. // TODO: add BreakableStatement and divide Whiles, fors and so on to another place.
let tok = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let tok = cursor.peek(0, interner).or_abrupt()?;
match tok.kind() { match tok.kind() {
TokenKind::Keyword((Keyword::If, _)) => { TokenKind::Keyword((Keyword::If, _)) => {
@ -187,7 +187,7 @@ where
} }
TokenKind::Punctuator(Punctuator::Semicolon) => { TokenKind::Punctuator(Punctuator::Semicolon) => {
// parse the EmptyStatement // parse the EmptyStatement
cursor.next(interner).expect("semicolon disappeared"); cursor.advance(interner);
Ok(ast::Statement::Empty) Ok(ast::Statement::Empty)
} }
TokenKind::Identifier(_) => { TokenKind::Identifier(_) => {
@ -336,7 +336,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("StatementListItem", "Parsing"); let _timer = Profiler::global().start_event("StatementListItem", "Parsing");
let tok = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let tok = cursor.peek(0, interner).or_abrupt()?;
match *tok.kind() { match *tok.kind() {
TokenKind::Keyword(( TokenKind::Keyword((
@ -409,12 +409,9 @@ where
let mut property_names = Vec::new(); let mut property_names = Vec::new();
loop { loop {
let next_token_is_colon = *cursor let next_token_is_colon = *cursor.peek(1, interner).or_abrupt()?.kind()
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== TokenKind::Punctuator(Punctuator::Colon); == TokenKind::Punctuator(Punctuator::Colon);
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::CloseBlock) => { TokenKind::Punctuator(Punctuator::CloseBlock) => {
cursor.expect( cursor.expect(
@ -655,11 +652,7 @@ where
let mut last_elision_or_first = true; let mut last_elision_or_first = true;
loop { loop {
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::CloseBracket) => { TokenKind::Punctuator(Punctuator::CloseBracket) => {
cursor.expect( cursor.expect(
TokenKind::Punctuator(Punctuator::CloseBracket), TokenKind::Punctuator(Punctuator::CloseBracket),
@ -688,11 +681,7 @@ where
interner, interner,
)?; )?;
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {
let bindings = let bindings =
ObjectBindingPattern::new(self.allow_yield, self.allow_await) ObjectBindingPattern::new(self.allow_yield, self.allow_await)
@ -732,11 +721,7 @@ where
let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await) let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::Assign) => { TokenKind::Punctuator(Punctuator::Assign) => {
let default_init = let default_init =
Initializer::new(None, true, self.allow_yield, self.allow_await) Initializer::new(None, true, self.allow_yield, self.allow_await)
@ -760,11 +745,7 @@ where
let bindings = let bindings =
Self::new(self.allow_yield, self.allow_await).parse(cursor, interner)?; Self::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::Assign) => { TokenKind::Punctuator(Punctuator::Assign) => {
let default_init = let default_init =
Initializer::new(None, true, self.allow_yield, self.allow_await) Initializer::new(None, true, self.allow_yield, self.allow_await)
@ -787,11 +768,7 @@ where
let ident = BindingIdentifier::new(self.allow_yield, self.allow_await) let ident = BindingIdentifier::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?; .parse(cursor, interner)?;
match cursor match cursor.peek(0, interner).or_abrupt()?.kind() {
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
TokenKind::Punctuator(Punctuator::Assign) => { TokenKind::Punctuator(Punctuator::Assign) => {
let default_init = Initializer::new( let default_init = Initializer::new(
Some(ident), Some(ident),

2
boa_engine/src/syntax/parser/statement/return_stm/mod.rs

@ -52,7 +52,7 @@ where
if let SemicolonResult::Found(tok) = cursor.peek_semicolon(interner)? { if let SemicolonResult::Found(tok) = cursor.peek_semicolon(interner)? {
match tok { match tok {
Some(tok) if tok.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) => { Some(tok) if tok.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) => {
let _next = cursor.next(interner)?; cursor.advance(interner);
} }
_ => {} _ => {}
} }

10
boa_engine/src/syntax/parser/statement/switch/mod.rs

@ -5,7 +5,7 @@ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
expression::Expression, statement::StatementList, AllowAwait, AllowReturn, AllowYield, expression::Expression, statement::StatementList, AllowAwait, AllowReturn, AllowYield,
Cursor, ParseError, ParseResult, TokenParser, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
}, },
}; };
use ast::operations::{lexically_declared_names_legacy, var_declared_names}; use ast::operations::{lexically_declared_names_legacy, var_declared_names};
@ -69,11 +69,7 @@ where
cursor.expect(Punctuator::CloseParen, "switch statement", interner)?; cursor.expect(Punctuator::CloseParen, "switch statement", interner)?;
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let (cases, default) = let (cases, default) =
CaseBlock::new(self.allow_yield, self.allow_await, self.allow_return) CaseBlock::new(self.allow_yield, self.allow_await, self.allow_return)
@ -156,7 +152,7 @@ where
let mut default = None; let mut default = None;
loop { loop {
let token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.next(interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Keyword((Keyword::Case | Keyword::Default, true)) => { TokenKind::Keyword((Keyword::Case | Keyword::Default, true)) => {
return Err(ParseError::general( return Err(ParseError::general(

2
boa_engine/src/syntax/parser/statement/throw/mod.rs

@ -54,7 +54,7 @@ where
.parse(cursor, interner)?; .parse(cursor, interner)?;
if let Some(tok) = cursor.peek(0, interner)? { if let Some(tok) = cursor.peek(0, interner)? {
if tok.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) { if tok.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) {
let _next = cursor.next(interner).expect("token disappeared"); cursor.advance(interner);
} }
} }

17
boa_engine/src/syntax/parser/statement/try_stm/catch.rs

@ -2,7 +2,8 @@ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{ parser::{
statement::{block::Block, ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern}, statement::{block::Block, ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern},
AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser, AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -55,11 +56,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("Catch", "Parsing"); let _timer = Profiler::global().start_event("Catch", "Parsing");
cursor.expect((Keyword::Catch, false), "try statement", interner)?; cursor.expect((Keyword::Catch, false), "try statement", interner)?;
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let catch_param = if cursor.next_if(Punctuator::OpenParen, interner)?.is_some() { let catch_param = if cursor.next_if(Punctuator::OpenParen, interner)?.is_some() {
let catch_param = let catch_param =
CatchParameter::new(self.allow_yield, self.allow_await).parse(cursor, interner)?; CatchParameter::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
@ -88,11 +85,7 @@ where
}) })
.transpose()?; .transpose()?;
let position = cursor let position = cursor.peek(0, interner).or_abrupt()?.span().start();
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let catch_block = Block::new(self.allow_yield, self.allow_await, self.allow_return) let catch_block = Block::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?; .parse(cursor, interner)?;
@ -161,7 +154,7 @@ where
type Output = Binding; type Output = Binding;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {

6
boa_engine/src/syntax/parser/statement/try_stm/mod.rs

@ -8,7 +8,9 @@ use self::{catch::Catch, finally::Finally};
use super::block::Block; use super::block::Block;
use crate::syntax::{ use crate::syntax::{
lexer::TokenKind, lexer::TokenKind,
parser::{AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser}, parser::{
AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
},
}; };
use boa_ast::{ use boa_ast::{
statement::{ErrorHandler, Try}, statement::{ErrorHandler, Try},
@ -63,7 +65,7 @@ where
let try_clause = Block::new(self.allow_yield, self.allow_await, self.allow_return) let try_clause = Block::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?; .parse(cursor, interner)?;
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let next_token = cursor.peek(0, interner).or_abrupt()?;
match next_token.kind() { match next_token.kind() {
TokenKind::Keyword((Keyword::Catch | Keyword::Finally, true)) => { TokenKind::Keyword((Keyword::Catch | Keyword::Finally, true)) => {
return Err(ParseError::general( return Err(ParseError::general(

4
boa_engine/src/syntax/parser/statement/variable/mod.rs

@ -6,7 +6,7 @@ use crate::syntax::{
cursor::Cursor, cursor::Cursor,
expression::Initializer, expression::Initializer,
statement::{ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern}, statement::{ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern},
AllowAwait, AllowIn, AllowYield, ParseError, ParseResult, TokenParser, AllowAwait, AllowIn, AllowYield, OrAbrupt, ParseResult, TokenParser,
}, },
}; };
use boa_ast::{ use boa_ast::{
@ -163,7 +163,7 @@ where
type Output = Variable; type Output = Variable;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> { fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let peek_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?; let peek_token = cursor.peek(0, interner).or_abrupt()?;
match peek_token.kind() { match peek_token.kind() {
TokenKind::Punctuator(Punctuator::OpenBlock) => { TokenKind::Punctuator(Punctuator::OpenBlock) => {

Loading…
Cancel
Save