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. 73
      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::{
lexer::{InputElement, Lexer, Token, TokenKind},
parser::error::ParseError,
parser::{error::ParseError, ParseResult},
};
use boa_ast::Position;
use boa_interner::Interner;
@ -83,7 +83,7 @@ where
&mut self,
start: Position,
interner: &mut Interner,
) -> Result<Token, ParseError> {
) -> ParseResult<Token> {
let _timer = Profiler::global().start_event("cursor::lex_regex()", "Parsing");
self.set_goal(InputElement::RegExp);
self.lexer
@ -97,7 +97,7 @@ where
&mut self,
start: Position,
interner: &mut Interner,
) -> Result<Token, ParseError> {
) -> ParseResult<Token> {
self.lexer
.lex_template(start, interner)
.map_err(ParseError::from)
@ -116,7 +116,7 @@ where
/// Fills the peeking buffer with the next token.
///
/// 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!(
self.write_index < PEEK_BUF_SIZE,
"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
/// 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(
&mut self,
skip_line_terminators: bool,
interner: &mut Interner,
) -> Result<Option<Token>, ParseError> {
) -> ParseResult<Option<Token>> {
if self.read_index == self.write_index {
self.fill(interner)?;
}
@ -217,7 +217,7 @@ where
skip_n: usize,
skip_line_terminators: bool,
interner: &mut Interner,
) -> Result<Option<&Token>, ParseError> {
) -> ParseResult<Option<&Token>> {
assert!(
skip_n <= MAX_PEEK_SKIP,
"you cannot skip more than {} elements",

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

@ -1,7 +1,7 @@
//! Cursor implementation for the parser.
mod buffered_lexer;
use super::{statement::PrivateElement, ParseError};
use super::{statement::PrivateElement, OrAbrupt, ParseError, ParseResult};
use crate::syntax::lexer::{InputElement, Lexer, Token, TokenKind};
use boa_ast::{Position, Punctuator};
use boa_interner::{Interner, Sym};
@ -54,7 +54,7 @@ where
&mut self,
start: Position,
interner: &mut Interner,
) -> Result<Token, ParseError> {
) -> ParseResult<Token> {
self.buffered_lexer.lex_regex(start, interner)
}
@ -63,35 +63,55 @@ where
&mut self,
start: Position,
interner: &mut Interner,
) -> Result<Token, ParseError> {
) -> ParseResult<Token> {
self.buffered_lexer.lex_template(start, interner)
}
/// Advances the cursor and returns the next token.
#[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)
}
/// 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]
pub(super) fn peek(
&mut self,
skip_n: usize,
interner: &mut Interner,
) -> Result<Option<&Token>, ParseError> {
) -> ParseResult<Option<&Token>> {
self.buffered_lexer.peek(skip_n, true, interner)
}
/// Gets the current strict mode for the cursor.
#[inline]
pub(super) fn strict_mode(&self) -> bool {
self.buffered_lexer.strict_mode()
}
/// Sets the strict mode to strict or non-strict.
#[inline]
pub(super) fn set_strict_mode(&mut self, strict_mode: bool) {
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]
pub(super) fn arrow(&self) -> bool {
self.arrow
@ -116,7 +136,7 @@ where
&mut self,
identifier: Sym,
position: Position,
) -> Result<(), ParseError> {
) -> ParseResult<()> {
if let Some(env) = self.private_environments_stack.last_mut() {
env.entry(identifier).or_insert(position);
Ok(())
@ -136,7 +156,7 @@ where
pub(super) fn pop_private_environment(
&mut self,
identifiers: &FxHashMap<Sym, PrivateElement>,
) -> Result<(), ParseError> {
) -> ParseResult<()> {
let last = self
.private_environments_stack
.pop()
@ -163,11 +183,11 @@ where
kind: K,
context: &'static str,
interner: &mut Interner,
) -> Result<Token, ParseError>
) -> ParseResult<Token>
where
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();
if next_token.kind() == &kind {
@ -191,7 +211,7 @@ where
pub(super) fn peek_semicolon(
&mut self,
interner: &mut Interner,
) -> Result<SemicolonResult<'_>, ParseError> {
) -> ParseResult<SemicolonResult<'_>> {
match self.buffered_lexer.peek(0, false, interner)? {
Some(tk) => match tk.kind() {
TokenKind::Punctuator(Punctuator::Semicolon | Punctuator::CloseBlock)
@ -212,7 +232,7 @@ where
&mut self,
context: &'static str,
interner: &mut Interner,
) -> Result<(), ParseError> {
) -> ParseResult<()> {
match self.peek_semicolon(interner)? {
SemicolonResult::Found(Some(tk)) => match *tk.kind() {
TokenKind::Punctuator(Punctuator::Semicolon) | TokenKind::LineTerminator => {
@ -243,19 +263,20 @@ where
skip_n: usize,
context: &'static str,
interner: &mut Interner,
) -> Result<&Token, ParseError> {
if let Some(t) = self.buffered_lexer.peek(skip_n, false, interner)? {
if t.kind() == &TokenKind::LineTerminator {
Err(ParseError::unexpected(
t.to_string(interner),
t.span(),
context,
))
} else {
Ok(t)
}
) -> ParseResult<&Token> {
let tok = self
.buffered_lexer
.peek(skip_n, false, interner)
.or_abrupt()?;
if tok.kind() == &TokenKind::LineTerminator {
Err(ParseError::unexpected(
tok.to_string(interner),
tok.span(),
context,
))
} else {
Err(ParseError::AbruptEnd)
Ok(tok)
}
}
@ -265,7 +286,7 @@ where
&mut self,
skip_n: usize,
interner: &mut Interner,
) -> Result<Option<bool>, ParseError> {
) -> ParseResult<Option<bool>> {
if let Some(t) = self.buffered_lexer.peek(skip_n, false, interner)? {
Ok(Some(t.kind() == &TokenKind::LineTerminator))
} else {
@ -283,7 +304,7 @@ where
&mut self,
kind: K,
interner: &mut Interner,
) -> Result<Option<Token>, ParseError>
) -> ParseResult<Option<Token>>
where
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;
}
impl<T> ErrorContext for Result<T, ParseError> {
impl<T> ErrorContext for ParseResult<T> {
#[inline]
fn context(self, context: &'static str) -> Self {
self.map_err(|e| e.context(context))
}
}
impl From<LexError> for ParseError {
#[inline]
fn from(e: LexError) -> Self {
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},
expression::BindingIdentifier,
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};
@ -78,7 +79,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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) =
&next_token.kind()
@ -191,13 +192,9 @@ where
type Output = StatementList;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::Punctuator(Punctuator::OpenBlock) => {
let _next = cursor.next(interner)?;
cursor.advance(interner);
let body = FunctionBody::new(false, false).parse(cursor, interner)?;
cursor.expect(Punctuator::CloseBlock, "arrow function", interner)?;
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},
expression::BindingIdentifier,
function::{FormalParameters, FunctionBody},
name_in_lexically_declared_names, AllowIn, AllowYield, Cursor, TokenParser,
name_in_lexically_declared_names, AllowIn, AllowYield, Cursor, OrAbrupt, TokenParser,
},
};
use ast::{
@ -76,7 +76,7 @@ where
cursor.expect((Keyword::Async, false), "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) =
&next_token.kind()
{
@ -180,13 +180,9 @@ where
type Output = StatementList;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::Punctuator(Punctuator::OpenBlock) => {
cursor.next(interner)?;
cursor.advance(interner);
let body = FunctionBody::new(false, true).parse(cursor, interner)?;
cursor.expect(Punctuator::CloseBlock, "async arrow function", interner)?;
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 tok.kind() == &TokenKind::Punctuator(Punctuator::Question) {
cursor.next(interner)?.expect("? character vanished"); // Consume the token.
cursor.advance(interner);
let then_clause =
AssignmentExpression::new(None, true, self.allow_yield, self.allow_await)
.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
//! [spec]: https://tc39.es/ecma262/#sec-exp-operator
use super::ParseError;
use crate::syntax::{
lexer::TokenKind,
parser::{
expression::{unary::UnaryExpression, update::UpdateExpression},
AllowAwait, AllowYield, Cursor, ParseResult, TokenParser,
AllowAwait, AllowYield, Cursor, OrAbrupt, ParseResult, TokenParser,
},
};
use boa_ast::{
@ -70,7 +69,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
TokenKind::Keyword((Keyword::Delete | Keyword::Void | Keyword::TypeOf, _))
| TokenKind::Punctuator(
@ -90,7 +89,7 @@ where
.parse(cursor, interner)?;
if let Some(tok) = cursor.peek(0, interner)? {
if let TokenKind::Punctuator(Punctuator::Exp) = tok.kind() {
cursor.next(interner)?.expect("** token vanished"); // Consume the token.
cursor.advance(interner);
return Ok(Binary::new(
ArithmeticOp::Exp.into(),
lhs,

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

@ -22,17 +22,16 @@ use crate::syntax::{
conditional::ConditionalExpression,
r#yield::YieldExpression,
},
name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, ParseError,
ParseResult, TokenParser,
name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, OrAbrupt,
ParseError, ParseResult, TokenParser,
},
};
use ast::operations::{bound_names, contains, top_level_lexically_declared_names, ContainsSymbol};
use boa_ast::{
self as ast,
expression::{
operator::assign::{Assign, AssignOp, AssignTarget},
Identifier,
},
operations::{bound_names, contains, top_level_lexically_declared_names, ContainsSymbol},
Expression, Keyword, Punctuator,
};
use boa_interner::Interner;
@ -102,11 +101,7 @@ where
let _timer = Profiler::global().start_event("AssignmentExpression", "Parsing");
cursor.set_goal(InputElement::RegExp);
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
// [+Yield]YieldExpression[?In, ?Await]
TokenKind::Keyword((Keyword::Yield, _)) if self.allow_yield.0 => {
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.
// In that case we have to skip an additional token on the next peek.
let skip_n = if cursor
.peek_is_line_terminator(0, interner)?
.ok_or(ParseError::AbruptEnd)?
{
let skip_n = if cursor.peek_is_line_terminator(0, interner).or_abrupt()? {
2
} else {
1
@ -143,23 +135,17 @@ where
}
// AsyncArrowFunction[?In, ?Yield, ?Await]
TokenKind::Keyword((Keyword::Async, _)) => {
let skip_n = if cursor
.peek_is_line_terminator(0, interner)?
.ok_or(ParseError::AbruptEnd)?
{
let skip_n = if cursor.peek_is_line_terminator(0, interner).or_abrupt()? {
2
} else {
1
};
if !cursor
.peek_is_line_terminator(skip_n, interner)?
.ok_or(ParseError::AbruptEnd)?
.peek_is_line_terminator(skip_n, interner)
.or_abrupt()?
&& matches!(
cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind(),
cursor.peek(1, interner).or_abrupt()?.kind(),
TokenKind::Identifier(_)
| TokenKind::Keyword((Keyword::Yield | Keyword::Await, _))
| TokenKind::Punctuator(Punctuator::OpenParen)
@ -177,11 +163,7 @@ where
cursor.set_goal(InputElement::Div);
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let mut lhs = ConditionalExpression::new(
self.name,
self.allow_in,
@ -247,7 +229,7 @@ where
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.
@ -260,7 +242,7 @@ where
}
}
cursor.next(interner)?.expect("= token vanished");
cursor.advance(interner);
cursor.set_goal(InputElement::RegExp);
if let Some(target) =
@ -285,7 +267,7 @@ where
}
}
cursor.next(interner)?.expect("token vanished");
cursor.advance(interner);
if let Some(target) =
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 crate::syntax::{
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_interner::Interner;
@ -67,10 +67,10 @@ where
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() {
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)
.parse(cursor, interner)?;
Ok(Yield::new(Some(expr), true).into())

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

@ -7,7 +7,9 @@
use crate::syntax::{
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_interner::{Interner, Sym};
@ -61,7 +63,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
TokenKind::Identifier(ident)
@ -153,7 +155,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
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::{
lexer::{InputElement, TokenKind},
parser::{
expression::AssignmentExpression, AllowAwait, AllowYield, Cursor, ParseError, ParseResult,
TokenParser,
expression::AssignmentExpression, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError,
ParseResult, TokenParser,
},
};
use boa_ast::{expression::Spread, Expression, Punctuator};
@ -60,11 +60,11 @@ where
let mut args = Vec::new();
loop {
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() {
TokenKind::Punctuator(Punctuator::CloseParen) => {
cursor.next(interner)?.expect(") token vanished"); // Consume the token.
cursor.advance(interner);
break;
}
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,
parser::{
expression::{left_hand_side::template::TaggedTemplateLiteral, Expression},
AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser,
AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{
@ -68,7 +68,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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 args =
@ -93,9 +93,9 @@ where
lhs = ast::Expression::from(Call::new(lhs, args));
}
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::Keyword((kw, _)) => {
SimplePropertyAccess::new(lhs, kw.to_sym(interner)).into()
@ -124,7 +124,7 @@ where
lhs = ast::Expression::PropertyAccess(access);
}
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)
.parse(cursor, 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::{
left_hand_side::template::TaggedTemplateLiteral, primary::PrimaryExpression, Expression,
},
AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser,
AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{
@ -69,7 +69,7 @@ where
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() {
TokenKind::Keyword((Keyword::New | Keyword::Super, true)) => {
return Err(ParseError::general(
@ -78,10 +78,10 @@ where
));
}
TokenKind::Keyword((Keyword::New, false)) => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
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() {
TokenKind::Identifier(Sym::TARGET) => {
return Ok(ast::Expression::NewTarget)
@ -108,11 +108,11 @@ where
ast::Expression::from(New::from(call_node))
}
TokenKind::Keyword((Keyword::Super, _)) => {
cursor.next(interner).expect("token disappeared");
let token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?;
cursor.advance(interner);
let token = cursor.next(interner).or_abrupt()?;
match token.kind() {
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() {
TokenKind::Identifier(name) => {
SuperPropertyAccess::new(PropertyAccessField::from(*name))
@ -173,7 +173,7 @@ where
.next(interner)?
.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() {
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);
let mut lhs = if is_super_call(cursor, interner)? {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
let args =
Arguments::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
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::{
lexer::{Token, TokenKind},
parser::{
cursor::Cursor, expression::Expression, AllowAwait, AllowYield, ParseError, ParseResult,
TokenParser,
cursor::Cursor, expression::Expression, AllowAwait, AllowYield, OrAbrupt, ParseError,
ParseResult, TokenParser,
},
};
@ -105,13 +105,13 @@ where
while let Some(token) = cursor.peek(0, interner)? {
let shorted = match token.kind() {
TokenKind::Punctuator(Punctuator::Optional) => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
true
}
TokenKind::Punctuator(Punctuator::OpenParen | Punctuator::OpenBracket) => false,
TokenKind::Punctuator(Punctuator::Dot) => {
cursor.next(interner).expect("token disappeared");
let field = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?;
cursor.advance(interner);
let field = cursor.next(interner).or_abrupt()?;
let item = parse_const_access(cursor, &field, interner)?;
@ -127,7 +127,7 @@ where
_ => break,
};
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
let token = cursor.peek(0, interner).or_abrupt()?;
let item = match token.kind() {
TokenKind::Punctuator(Punctuator::OpenParen) => {

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

@ -1,8 +1,8 @@
use crate::syntax::{
lexer::TokenKind,
parser::{
cursor::Cursor, expression::Expression, AllowAwait, AllowYield, ParseError, ParseResult,
TokenParser,
cursor::Cursor, expression::Expression, AllowAwait, AllowYield, OrAbrupt, ParseError,
ParseResult, TokenParser,
},
};
use boa_ast::{self as ast, expression::TaggedTemplate, Position, Punctuator};
@ -58,7 +58,7 @@ where
let mut cookeds = 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 {
match token.kind() {

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

@ -23,10 +23,9 @@ use crate::syntax::{
lexer::{InputElement, TokenKind},
parser::{
expression::assignment::ExponentiationExpression, AllowAwait, AllowIn, AllowYield, Cursor,
ParseError, ParseResult, TokenParser,
OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{
self as ast,
expression::{
@ -43,6 +42,7 @@ use boa_profiler::Profiler;
use std::io::Read;
pub(super) use self::{assignment::AssignmentExpression, primary::Initializer};
pub(in crate::syntax::parser) use {
identifiers::{BindingIdentifier, LabelIdentifier},
left_hand_side::LeftHandSideExpression,
@ -88,7 +88,7 @@ macro_rules! expression {
while let Some(tok) = cursor.peek(0, interner)? {
match *tok.kind() {
TokenKind::Punctuator(op) if $( op == $op )||* => {
let _next = cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
lhs = Binary::new(
op.as_binary_op().expect("Could not get binary operation."),
lhs,
@ -159,25 +159,19 @@ where
while let Some(tok) = cursor.peek(0, interner)? {
match *tok.kind() {
TokenKind::Punctuator(Punctuator::Comma) => {
if cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
if cursor.peek(1, interner).or_abrupt()?.kind()
== &TokenKind::Punctuator(Punctuator::CloseParen)
{
return Ok(lhs);
}
if cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
if cursor.peek(1, interner).or_abrupt()?.kind()
== &TokenKind::Punctuator(Punctuator::Spread)
{
return Ok(lhs);
}
let _next = cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
lhs = Binary::new(
Punctuator::Comma
@ -291,7 +285,7 @@ where
"logical expression (cannot use '??' without parentheses within '||' or '&&')",
));
}
let _next = cursor.next(interner)?.expect("'&&' expected");
cursor.advance(interner);
previous = PreviousExpr::Logical;
let rhs = BitwiseORExpression::new(
self.name,
@ -312,7 +306,7 @@ where
"logical expression (cannot use '??' without parentheses within '||' or '&&')",
));
}
let _next = cursor.next(interner)?.expect("'||' expected");
cursor.advance(interner);
previous = PreviousExpr::Logical;
let rhs = Self::with_previous(
self.name,
@ -334,7 +328,7 @@ where
"cannot use '??' unparenthesized within '||' or '&&'",
));
}
let _next = cursor.next(interner)?.expect("'??' expected");
cursor.advance(interner);
previous = PreviousExpr::Coalesce;
let rhs = BitwiseORExpression::new(
self.name,
@ -580,7 +574,7 @@ where
|| op == Punctuator::LessThanOrEq
|| op == Punctuator::GreaterThanOrEq =>
{
let _next = cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
lhs = Binary::new(
op.as_binary_op().expect("Could not get binary operation."),
lhs,
@ -599,7 +593,7 @@ where
if op == Keyword::InstanceOf
|| (op == Keyword::In && self.allow_in == AllowIn(true)) =>
{
let _next = cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
lhs = Binary::new(
op.as_binary_op().expect("Could not get binary operation."),
lhs,
@ -742,7 +736,7 @@ expression!(
);
/// 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() {
Sym::ARGUMENTS => Err(ParseError::general(
"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::{
lexer::TokenKind,
parser::{
expression::AssignmentExpression, AllowAwait, AllowYield, Cursor, ParseError, ParseResult,
TokenParser,
expression::AssignmentExpression, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError,
ParseResult, TokenParser,
},
};
use boa_ast::{
@ -67,17 +67,17 @@ where
let mut last_spread = false;
loop {
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() {
TokenKind::Punctuator(Punctuator::CloseBracket) => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
break;
}
TokenKind::Punctuator(Punctuator::Comma) if next_comma => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
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) {
has_trailing_comma_spread = true;
}
@ -86,7 +86,7 @@ where
next_comma = false;
}
TokenKind::Punctuator(Punctuator::Comma) => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
elements.push(None);
}
TokenKind::Punctuator(Punctuator::Spread) if next_comma => {
@ -97,7 +97,7 @@ where
));
}
TokenKind::Punctuator(Punctuator::Spread) => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
let node =
AssignmentExpression::new(None, true, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;

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

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

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

@ -15,8 +15,8 @@ use crate::syntax::{
parser::{
expression::{identifiers::IdentifierReference, AssignmentExpression},
function::{FormalParameter, FormalParameters, FunctionBody, UniqueFormalParameters},
name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, ParseError,
ParseResult, TokenParser,
name_in_lexically_declared_names, AllowAwait, AllowIn, AllowYield, Cursor, OrAbrupt,
ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{
@ -89,7 +89,7 @@ where
}
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(
[",".to_owned(), "}".to_owned()],
next_token.to_string(interner),
@ -138,11 +138,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("PropertyDefinition", "Parsing");
match cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(1, interner).or_abrupt()?.kind() {
TokenKind::Punctuator(Punctuator::CloseBlock | Punctuator::Comma) => {
let ident = IdentifierReference::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
@ -167,13 +163,10 @@ where
//Async [AsyncMethod, AsyncGeneratorMethod] object methods
let is_keyword = !matches!(
cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind(),
cursor.peek(1, interner).or_abrupt()?.kind(),
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() {
TokenKind::Keyword((Keyword::Async, true)) if is_keyword => {
return Err(ParseError::general(
@ -182,10 +175,10 @@ where
));
}
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)?;
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
let token = cursor.peek(0, interner).or_abrupt()?;
let position = token.span().start();
if let TokenKind::Punctuator(Punctuator::Mul) = token.kind() {
@ -238,17 +231,8 @@ where
_ => {}
}
if cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
== &TokenKind::Punctuator(Punctuator::Mul)
{
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
if cursor.peek(0, interner).or_abrupt()?.kind() == &TokenKind::Punctuator(Punctuator::Mul) {
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let (class_element_name, method) =
GeneratorMethod::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
@ -283,20 +267,13 @@ where
return Ok(property::PropertyDefinition::Property(property_name, value));
}
let ordinary_method = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
let ordinary_method = cursor.peek(0, interner).or_abrupt()?.kind()
== &TokenKind::Punctuator(Punctuator::OpenParen);
match property_name {
// MethodDefinition[?Yield, ?Await] -> get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] }
property::PropertyName::Literal(str) if str == Sym::GET && !ordinary_method => {
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
property_name = PropertyName::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
@ -507,10 +484,10 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
TokenKind::Punctuator(Punctuator::OpenBracket) => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
let node =
AssignmentExpression::new(None, false, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
@ -534,7 +511,7 @@ where
},
_ => return Err(ParseError::AbruptEnd),
};
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
Ok(name)
}
}
@ -574,14 +551,10 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("ClassElementName", "Parsing");
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::PrivateIdentifier(ident) => {
let ident = *ident;
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
Ok(property::ClassElementName::PrivateIdentifier(ident))
}
_ => Ok(property::ClassElementName::PropertyName(
@ -682,11 +655,7 @@ where
let class_element_name =
ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let params_start_position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let params_start_position = cursor.peek(0, interner).or_abrupt()?.span().start();
let params = UniqueFormalParameters::new(true, false).parse(cursor, interner)?;
@ -778,11 +747,7 @@ where
let name =
ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let params_start_position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let params_start_position = cursor.peek(0, interner).or_abrupt()?.span().start();
let params = UniqueFormalParameters::new(true, true).parse(cursor, interner)?;
@ -888,11 +853,7 @@ where
let class_element_name =
ClassElementName::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
let params_start_position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let params_start_position = cursor.peek(0, interner).or_abrupt()?.span().start();
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},
parser::{
expression::{await_expr::AwaitExpression, update::UpdateExpression},
AllowAwait, AllowYield, Cursor, ParseError, ParseResult, TokenParser,
AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{
@ -66,19 +66,15 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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();
match tok.kind() {
TokenKind::Keyword((Keyword::Delete | Keyword::Void | Keyword::TypeOf, true)) => Err(
ParseError::general("Keyword must not contain escaped characters", token_start),
),
TokenKind::Keyword((Keyword::Delete, false)) => {
cursor.next(interner)?.expect("Delete keyword vanished");
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
cursor.advance(interner);
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let val = self.parse(cursor, interner)?;
match val {
@ -100,27 +96,27 @@ where
Ok(Unary::new(UnaryOp::Delete, val).into())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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())
}
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::{
lexer::{Error as LexError, TokenKind},
parser::{
expression::unary::UnaryExpression, AllowAwait, AllowYield, Cursor, ParseError,
expression::unary::UnaryExpression, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError,
ParseResult, TokenParser,
},
};
@ -62,7 +62,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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();
match tok.kind() {
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 std::io::Read;
use super::ParseResult;
use super::{OrAbrupt, ParseResult};
/// Formal parameters parsing.
///
@ -71,7 +71,7 @@ where
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) {
return Ok(FormalParameterList::default());
}
@ -99,10 +99,7 @@ where
params.push(next_param);
if cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
if cursor.peek(0, interner).or_abrupt()?.kind()
== &TokenKind::Punctuator(Punctuator::CloseParen)
{
break;
@ -118,10 +115,7 @@ where
}
cursor.expect(Punctuator::Comma, "parameter list", interner)?;
if cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
if cursor.peek(0, interner).or_abrupt()?.kind()
== &TokenKind::Punctuator(Punctuator::CloseParen)
{
break;
@ -353,10 +347,7 @@ where
TokenKind::Punctuator(Punctuator::OpenBlock) => {
let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let init = if *cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
let init = if *cursor.peek(0, interner).or_abrupt()?.kind()
== TokenKind::Punctuator(Punctuator::Assign)
{
Some(
@ -372,10 +363,7 @@ where
TokenKind::Punctuator(Punctuator::OpenBracket) => {
let bindings = ArrayBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let init = if *cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
let init = if *cursor.peek(0, interner).or_abrupt()?.kind()
== TokenKind::Punctuator(Punctuator::Assign)
{
Some(
@ -391,10 +379,7 @@ where
_ => {
let ident = BindingIdentifier::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let init = if *cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
let init = if *cursor.peek(0, interner).or_abrupt()?.kind()
== TokenKind::Punctuator(Punctuator::Assign)
{
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.
///
/// [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
R: Read,
{
@ -149,7 +149,7 @@ impl<R> Parser<R> {
&mut self,
direct: bool,
context: &mut Context,
) -> Result<StatementList, ParseError>
) -> ParseResult<StatementList>
where
R: Read,
{
@ -241,7 +241,7 @@ impl<R> Parser<R> {
interner: &mut Interner,
allow_yield: bool,
allow_await: bool,
) -> Result<StatementList, ParseError>
) -> ParseResult<StatementList>
where
R: Read,
{
@ -256,7 +256,7 @@ impl<R> Parser<R> {
interner: &mut Interner,
allow_yield: bool,
allow_await: bool,
) -> Result<FormalParameterList, ParseError>
) -> ParseResult<FormalParameterList>
where
R: Read,
{
@ -285,7 +285,7 @@ impl Script {
self,
cursor: &mut Cursor<R>,
context: &mut Context,
) -> Result<StatementList, ParseError> {
) -> ParseResult<StatementList> {
let mut strict = cursor.strict_mode();
match cursor.peek(0, context.interner_mut())? {
Some(tok) => {
@ -393,7 +393,7 @@ fn name_in_lexically_declared_names(
bound_names: &[Identifier],
lexical_names: &[Identifier],
position: Position,
) -> Result<(), ParseError> {
) -> ParseResult<()> {
for name in bound_names {
if lexical_names.contains(name) {
return Err(ParseError::General {
@ -404,3 +404,16 @@ fn name_in_lexically_declared_names(
}
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 crate::syntax::{
lexer::TokenKind,
parser::{AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser},
parser::{
AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{
operations::{lexically_declared_names_legacy, var_declared_names},
@ -77,15 +79,11 @@ where
cursor.expect(Punctuator::OpenBlock, "block", interner)?;
if let Some(tk) = cursor.peek(0, interner)? {
if tk.kind() == &TokenKind::Punctuator(Punctuator::CloseBlock) {
cursor.next(interner)?.expect("} token vanished");
cursor.advance(interner);
return Ok(statement::Block::from(vec![]));
}
}
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let statement_list = StatementList::new(
self.allow_yield,
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)? {
match tok {
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)? {
if let Some(token) = tok {
if token.kind() == &TokenKind::Punctuator(Punctuator::Semicolon) {
cursor.next(interner)?;
cursor.advance(interner);
} else if token.kind() == &TokenKind::LineTerminator {
if let Some(token) = cursor.peek(0, interner)? {
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},
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};
@ -68,7 +69,7 @@ where
let strict = cursor.strict_mode();
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() {
TokenKind::Identifier(_) | TokenKind::Keyword((Keyword::Yield | Keyword::Await, _)) => {
BindingIdentifier::new(self.allow_yield, self.allow_await)
@ -130,7 +131,7 @@ where
type Output = Class;
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() {
TokenKind::Keyword((Keyword::Extends, true)) => {
return Err(ParseError::general(
@ -149,22 +150,15 @@ where
// Temporarily disable strict mode because "strict" may be parsed as a keyword.
let strict = cursor.strict_mode();
cursor.set_strict_mode(false);
let is_close_block = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
let is_close_block = cursor.peek(0, interner).or_abrupt()?.kind()
== &TokenKind::Punctuator(Punctuator::CloseBlock);
cursor.set_strict_mode(strict);
if is_close_block {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
Ok(Class::new(Some(self.name), super_ref, None, Box::default()))
} else {
let body_start = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let body_start = cursor.peek(0, interner).or_abrupt()?.span().start();
let (constructor, elements) =
ClassBody::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
@ -290,7 +284,7 @@ where
let strict = cursor.strict_mode();
cursor.set_strict_mode(false);
loop {
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
let token = cursor.peek(0, interner).or_abrupt()?;
let position = token.span().start();
match token.kind() {
TokenKind::Punctuator(Punctuator::CloseBlock) => break,
@ -550,14 +544,14 @@ where
type Output = (Option<Function>, Option<function::ClassElement>);
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() {
TokenKind::Punctuator(Punctuator::Semicolon) => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
return Ok((None, None));
}
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() {
TokenKind::Identifier(_)
| TokenKind::StringLiteral(_)
@ -569,7 +563,7 @@ where
Punctuator::OpenBracket | Punctuator::Mul | Punctuator::OpenBlock,
) => {
// this "static" is a keyword.
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
true
}
_ => false,
@ -579,10 +573,7 @@ where
};
let is_keyword = !matches!(
cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind(),
cursor.peek(1, interner).or_abrupt()?.kind(),
TokenKind::Punctuator(
Punctuator::Assign
| 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 element = match token.kind() {
TokenKind::Identifier(Sym::CONSTRUCTOR) if !r#static => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
let strict = cursor.strict_mode();
cursor.set_strict_mode(true);
@ -620,7 +611,7 @@ where
return Ok((Some(Function::new(Some(self.name), parameters, body)), None));
}
TokenKind::Punctuator(Punctuator::OpenBlock) if r#static => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
let statement_list = if cursor
.next_if(TokenKind::Punctuator(Punctuator::CloseBlock), interner)?
.is_some()
@ -629,11 +620,7 @@ where
} else {
let strict = cursor.strict_mode();
cursor.set_strict_mode(true);
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let statement_list =
StatementList::new(false, true, false, &FUNCTION_BREAK_TOKENS)
.parse(cursor, interner)?;
@ -668,7 +655,7 @@ where
function::ClassElement::StaticBlock(statement_list)
}
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();
if let TokenKind::Identifier(Sym::CONSTRUCTOR) = token.kind() {
return Err(ParseError::general(
@ -717,12 +704,12 @@ where
));
}
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)?;
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() {
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();
match token.kind() {
TokenKind::Identifier(Sym::CONSTRUCTOR)
@ -820,8 +807,8 @@ where
}
}
TokenKind::Identifier(Sym::GET) if is_keyword => {
cursor.next(interner).expect("token disappeared");
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
cursor.advance(interner);
let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() {
TokenKind::PrivateIdentifier(Sym::CONSTRUCTOR) => {
return Err(ParseError::general(
@ -831,7 +818,7 @@ where
}
TokenKind::PrivateIdentifier(name) => {
let name = *name;
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
let strict = cursor.strict_mode();
cursor.set_strict_mode(true);
let params =
@ -941,8 +928,8 @@ where
}
}
TokenKind::Identifier(Sym::SET) if is_keyword => {
cursor.next(interner).expect("token disappeared");
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
cursor.advance(interner);
let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() {
TokenKind::PrivateIdentifier(Sym::CONSTRUCTOR) => {
return Err(ParseError::general(
@ -952,7 +939,7 @@ where
}
TokenKind::PrivateIdentifier(name) => {
let name = *name;
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
let strict = cursor.strict_mode();
cursor.set_strict_mode(true);
let params =
@ -1066,11 +1053,11 @@ where
}
TokenKind::PrivateIdentifier(name) => {
let name = *name;
cursor.next(interner).expect("token disappeared");
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
cursor.advance(interner);
let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() {
TokenKind::Punctuator(Punctuator::Assign) => {
cursor.next(interner).expect("token disappeared");
cursor.advance(interner);
let strict = cursor.strict_mode();
cursor.set_strict_mode(true);
let rhs = AssignmentExpression::new(
@ -1141,7 +1128,7 @@ where
let name_position = token.span().start();
let name = PropertyName::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() {
TokenKind::Punctuator(Punctuator::Assign) => {
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();
cursor.set_strict_mode(true);
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},
name_in_lexically_declared_names,
statement::LexError,
AllowAwait, AllowDefault, AllowYield, Cursor, ParseError, ParseResult, TokenParser,
AllowAwait, AllowDefault, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser,
},
};
use boa_ast::{
@ -78,7 +79,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
TokenKind::Keyword((Keyword::Function | Keyword::Async | Keyword::Class, true)) => {
@ -88,7 +89,7 @@ where
))
}
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() {
GeneratorDeclaration::new(self.allow_yield, self.allow_await, self.is_default)
.parse(cursor, interner)
@ -100,7 +101,7 @@ where
}
}
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() {
AsyncGeneratorDeclaration::new(
self.allow_yield,
@ -142,8 +143,8 @@ fn parse_callable_declaration<R: Read, C: CallableDeclaration>(
c: &C,
cursor: &mut Cursor<R>,
interner: &mut Interner,
) -> Result<(Identifier, FormalParameterList, StatementList), ParseError> {
let next_token = cursor.peek(0, interner)?.ok_or(ParseError::AbruptEnd)?;
) -> ParseResult<(Identifier, FormalParameterList, StatementList)> {
let next_token = cursor.peek(0, interner).or_abrupt()?;
let name = match next_token.kind() {
TokenKind::Punctuator(Punctuator::OpenParen) => {
if !c.is_default() {

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

@ -13,7 +13,7 @@ use crate::syntax::{
cursor::{Cursor, SemicolonResult},
expression::Initializer,
statement::{ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern},
AllowAwait, AllowIn, AllowYield, ParseError, ParseResult, TokenParser,
AllowAwait, AllowIn, AllowYield, OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use ast::operations::bound_names;
@ -66,7 +66,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
TokenKind::Keyword((Keyword::Const | Keyword::Let, true)) => Err(ParseError::general(
@ -159,7 +159,7 @@ where
if init_is_some || self.loop_init {
decls.push(decl);
} else {
let next = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?;
let next = cursor.next(interner).or_abrupt()?;
return Err(ParseError::general(
"Expected initializer for const declaration",
next.span().start(),
@ -190,11 +190,11 @@ where
if tk.kind() == &TokenKind::Punctuator(Punctuator::Comma) =>
{
// We discard the comma
let _comma = cursor.next(interner)?;
cursor.advance(interner);
}
SemicolonResult::NotFound(_) if self.loop_init => break,
SemicolonResult::NotFound(_) => {
let next = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?;
let next = cursor.next(interner).or_abrupt()?;
return Err(ParseError::expected(
[";".to_owned(), "line terminator".to_owned()],
next.to_string(interner),
@ -254,7 +254,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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();
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::{
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_interner::Interner;
@ -60,7 +60,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
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::{
lexer::TokenKind,
parser::{
expression::Expression, AllowAwait, AllowYield, Cursor, ParseError, ParseResult,
expression::Expression, AllowAwait, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser,
},
};
@ -45,7 +45,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
TokenKind::Keyword((
Keyword::Function | Keyword::Class | Keyword::Async | Keyword::Let,
@ -63,7 +63,7 @@ where
));
}
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() {
TokenKind::Keyword((Keyword::Function, true)) => {
return Err(ParseError::general(
@ -81,7 +81,7 @@ where
}
}
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) {
return Err(ParseError::general(
"expected statement",

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

@ -5,7 +5,7 @@ use crate::syntax::{
lexer::TokenKind,
parser::{
expression::Expression, statement::declaration::FunctionDeclaration, AllowAwait,
AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser,
AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{
@ -72,7 +72,7 @@ where
.end();
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() {
TokenKind::Keyword((Keyword::Function, _)) => {
// FunctionDeclarations in IfStatement Statement Clauses
@ -108,10 +108,10 @@ where
));
}
TokenKind::Keyword((Keyword::Else, false)) => {
cursor.next(interner)?.expect("token disappeared");
cursor.advance(interner);
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 stmt = match token.kind() {
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,
parser::{
expression::Expression, statement::Statement, AllowAwait, AllowReturn, AllowYield, Cursor,
ParseError, ParseResult, TokenParser,
OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{statement::DoWhileLoop, Keyword, Punctuator};
@ -65,11 +65,7 @@ where
cursor.expect((Keyword::Do, false), "do while statement", interner)?;
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?;
@ -79,7 +75,7 @@ where
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() {
TokenKind::Keyword((Keyword::While, true)) => {
return Err(ParseError::general(
@ -112,7 +108,7 @@ where
// https://tc39.es/ecma262/#sec-automatic-semicolon-insertion
if let Some(tok) = cursor.peek(0, interner)? {
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,
statement::declaration::LexicalDeclaration,
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};
@ -77,7 +78,7 @@ where
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() {
TokenKind::Punctuator(Punctuator::OpenParen) => next.span().end(),
TokenKind::Keyword((Keyword::Await, _)) if !self.allow_await.0 => {
@ -103,13 +104,9 @@ where
}
};
let init = match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
let init = match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::Keyword((Keyword::Var, _)) => {
let _next = cursor.next(interner)?;
cursor.advance(interner);
Some(
VariableDeclarationList::new(false, self.allow_yield, self.allow_await)
.parse(cursor, interner)?
@ -122,11 +119,7 @@ where
.into(),
),
TokenKind::Keyword((Keyword::Async, false)) => {
match cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(1, interner).or_abrupt()?.kind() {
TokenKind::Keyword((Keyword::Of, _)) => {
return Err(ParseError::lex(LexError::Syntax(
"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 init = match (init, token.kind()) {
(Some(_), TokenKind::Keyword((Keyword::In | Keyword::Of, true))) => {
@ -168,17 +161,13 @@ where
let init =
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)
.parse(cursor, interner)?;
cursor.expect(Punctuator::CloseParen, "for in/of statement", interner)?;
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?;
@ -266,11 +255,7 @@ where
Some(step)
};
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let body = Statement::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?;
@ -304,7 +289,7 @@ fn initializer_to_iterable_loop_initializer(
initializer: ForLoopInitializer,
position: Position,
strict: bool,
) -> Result<IterableLoopInitializer, ParseError> {
) -> ParseResult<IterableLoopInitializer> {
match initializer {
ForLoopInitializer::Expression(expr) => match expr {
ast::Expression::Identifier(ident)

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

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

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

@ -5,7 +5,7 @@ use crate::syntax::{
error::ParseError,
expression::LabelIdentifier,
statement::{AllowAwait, AllowReturn, Statement},
AllowYield, ParseResult, TokenParser,
AllowYield, OrAbrupt, ParseResult, TokenParser,
},
};
use boa_ast::{self as ast, Keyword, Punctuator};
@ -61,7 +61,7 @@ where
cursor.expect(Punctuator::Colon, "Labelled Statement", interner)?;
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() {
// 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,
};
use super::{
expression::PropertyName, AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult,
TokenParser,
expression::PropertyName, AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError,
ParseResult, TokenParser,
};
use crate::syntax::{
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> {
let _timer = Profiler::global().start_event("Statement", "Parsing");
// 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() {
TokenKind::Keyword((Keyword::If, _)) => {
@ -187,7 +187,7 @@ where
}
TokenKind::Punctuator(Punctuator::Semicolon) => {
// parse the EmptyStatement
cursor.next(interner).expect("semicolon disappeared");
cursor.advance(interner);
Ok(ast::Statement::Empty)
}
TokenKind::Identifier(_) => {
@ -336,7 +336,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
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() {
TokenKind::Keyword((
@ -409,12 +409,9 @@ where
let mut property_names = Vec::new();
loop {
let next_token_is_colon = *cursor
.peek(1, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
let next_token_is_colon = *cursor.peek(1, interner).or_abrupt()?.kind()
== 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() {
TokenKind::Punctuator(Punctuator::CloseBlock) => {
cursor.expect(
@ -655,11 +652,7 @@ where
let mut last_elision_or_first = true;
loop {
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::Punctuator(Punctuator::CloseBracket) => {
cursor.expect(
TokenKind::Punctuator(Punctuator::CloseBracket),
@ -688,11 +681,7 @@ where
interner,
)?;
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::Punctuator(Punctuator::OpenBlock) => {
let bindings =
ObjectBindingPattern::new(self.allow_yield, self.allow_await)
@ -732,11 +721,7 @@ where
let bindings = ObjectBindingPattern::new(self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::Punctuator(Punctuator::Assign) => {
let default_init =
Initializer::new(None, true, self.allow_yield, self.allow_await)
@ -760,11 +745,7 @@ where
let bindings =
Self::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::Punctuator(Punctuator::Assign) => {
let default_init =
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)
.parse(cursor, interner)?;
match cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.kind()
{
match cursor.peek(0, interner).or_abrupt()?.kind() {
TokenKind::Punctuator(Punctuator::Assign) => {
let default_init = Initializer::new(
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)? {
match tok {
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,
parser::{
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};
@ -69,11 +69,7 @@ where
cursor.expect(Punctuator::CloseParen, "switch statement", interner)?;
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let (cases, default) =
CaseBlock::new(self.allow_yield, self.allow_await, self.allow_return)
@ -156,7 +152,7 @@ where
let mut default = None;
loop {
let token = cursor.next(interner)?.ok_or(ParseError::AbruptEnd)?;
let token = cursor.next(interner).or_abrupt()?;
match token.kind() {
TokenKind::Keyword((Keyword::Case | Keyword::Default, true)) => {
return Err(ParseError::general(

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

@ -54,7 +54,7 @@ where
.parse(cursor, interner)?;
if let Some(tok) = cursor.peek(0, interner)? {
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,
parser::{
statement::{block::Block, ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern},
AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser,
AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult,
TokenParser,
},
};
use boa_ast::{
@ -55,11 +56,7 @@ where
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult<Self::Output> {
let _timer = Profiler::global().start_event("Catch", "Parsing");
cursor.expect((Keyword::Catch, false), "try statement", interner)?;
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let catch_param = if cursor.next_if(Punctuator::OpenParen, interner)?.is_some() {
let catch_param =
CatchParameter::new(self.allow_yield, self.allow_await).parse(cursor, interner)?;
@ -88,11 +85,7 @@ where
})
.transpose()?;
let position = cursor
.peek(0, interner)?
.ok_or(ParseError::AbruptEnd)?
.span()
.start();
let position = cursor.peek(0, interner).or_abrupt()?.span().start();
let catch_block = Block::new(self.allow_yield, self.allow_await, self.allow_return)
.parse(cursor, interner)?;
@ -161,7 +154,7 @@ where
type Output = Binding;
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() {
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 crate::syntax::{
lexer::TokenKind,
parser::{AllowAwait, AllowReturn, AllowYield, Cursor, ParseError, ParseResult, TokenParser},
parser::{
AllowAwait, AllowReturn, AllowYield, Cursor, OrAbrupt, ParseError, ParseResult, TokenParser,
},
};
use boa_ast::{
statement::{ErrorHandler, Try},
@ -63,7 +65,7 @@ where
let try_clause = Block::new(self.allow_yield, self.allow_await, self.allow_return)
.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() {
TokenKind::Keyword((Keyword::Catch | Keyword::Finally, true)) => {
return Err(ParseError::general(

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

@ -6,7 +6,7 @@ use crate::syntax::{
cursor::Cursor,
expression::Initializer,
statement::{ArrayBindingPattern, BindingIdentifier, ObjectBindingPattern},
AllowAwait, AllowIn, AllowYield, ParseError, ParseResult, TokenParser,
AllowAwait, AllowIn, AllowYield, OrAbrupt, ParseResult, TokenParser,
},
};
use boa_ast::{
@ -163,7 +163,7 @@ where
type Output = Variable;
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() {
TokenKind::Punctuator(Punctuator::OpenBlock) => {

Loading…
Cancel
Save