refactor(parser): improve expression parsing (#3352)

This commit is contained in:
Boshen 2024-05-19 21:28:16 +08:00 committed by GitHub
parent e818fba21c
commit 89a1f97320
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 192 additions and 129 deletions

View file

@ -1770,6 +1770,20 @@ impl<'a> AstBuilder<'a> {
})) }))
} }
#[inline]
pub fn ts_instantiation_expression(
&self,
span: Span,
expression: Expression<'a>,
type_parameters: Box<'a, TSTypeParameterInstantiation<'a>>,
) -> Expression<'a> {
Expression::TSInstantiationExpression(self.alloc(TSInstantiationExpression {
span,
expression,
type_parameters,
}))
}
#[inline] #[inline]
pub fn ts_non_null_expression(&self, span: Span, expression: Expression<'a>) -> Expression<'a> { pub fn ts_non_null_expression(&self, span: Span, expression: Expression<'a>) -> Expression<'a> {
Expression::TSNonNullExpression(self.alloc(TSNonNullExpression { span, expression })) Expression::TSNonNullExpression(self.alloc(TSNonNullExpression { span, expression }))

View file

@ -2,8 +2,9 @@ use oxc_allocator::Box;
use oxc_ast::ast::*; use oxc_ast::ast::*;
use oxc_diagnostics::Result; use oxc_diagnostics::Result;
use oxc_span::{GetSpan, Span}; use oxc_span::{GetSpan, Span};
use oxc_syntax::precedence::Precedence;
use crate::{diagnostics, lexer::Kind, AstBuilder, ParserImpl}; use crate::{diagnostics, lexer::Kind, ParserImpl};
use super::Tristate; use super::Tristate;
@ -34,8 +35,9 @@ impl<'a> ParserImpl<'a> {
{ {
let span = self.start_span(); let span = self.start_span();
self.bump_any(); // bump `async` self.bump_any(); // bump `async`
let expr = self.parse_binary_expression_or_higher(Precedence::lowest())?;
return self return self
.parse_simple_arrow_function_expression(span, /* is_async */ true) .parse_simple_arrow_function_expression(span, expr, /* async */ true)
.map(Some); .map(Some);
} }
Ok(None) Ok(None)
@ -186,7 +188,7 @@ impl<'a> ParserImpl<'a> {
} }
// Check for un-parenthesized AsyncArrowFunction // Check for un-parenthesized AsyncArrowFunction
if first.is_binding_identifier() { if first.is_binding_identifier() {
// Arrow before newline is checkedin `parse_simple_arrow_function_expression` // Arrow before newline is checked in `parse_simple_arrow_function_expression`
if self.nth_at(2, Kind::Arrow) { if self.nth_at(2, Kind::Arrow) {
return Tristate::True; return Tristate::True;
} }
@ -198,24 +200,24 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn parse_simple_arrow_function_expression( pub(crate) fn parse_simple_arrow_function_expression(
&mut self, &mut self,
span: Span, span: Span,
ident: Expression<'a>,
r#async: bool, r#async: bool,
) -> Result<Expression<'a>> { ) -> Result<Expression<'a>> {
let has_await = self.ctx.has_await(); let has_await = self.ctx.has_await();
self.ctx = self.ctx.union_await_if(r#async); self.ctx = self.ctx.union_await_if(r#async);
let params = { let params = {
let params_span = self.start_span(); let ident = match ident {
let param = self.parse_binding_identifier()?; Expression::Identifier(ident) => {
let ident = self.ast.binding_pattern_identifier(param); let name = ident.name.clone();
let params_span = self.end_span(params_span); BindingIdentifier::new(ident.span, name)
let formal_parameter = self.ast.formal_parameter( }
params_span, _ => unreachable!(),
self.ast.binding_pattern(ident, None, false), };
None, let params_span = self.end_span(ident.span);
false, let ident = self.ast.binding_pattern_identifier(ident);
false, let pattern = self.ast.binding_pattern(ident, None, false);
AstBuilder::new_vec(&self.ast), let formal_parameter = self.ast.plain_formal_parameter(params_span, pattern);
);
self.ast.formal_parameters( self.ast.formal_parameters(
params_span, params_span,
FormalParameterKind::ArrowFormalParameters, FormalParameterKind::ArrowFormalParameters,

View file

@ -122,7 +122,7 @@ impl<'a> ParserImpl<'a> {
let mut extends = self.ast.new_vec(); let mut extends = self.ast.new_vec();
let span = self.start_span(); let span = self.start_span();
let mut first_extends = self.parse_lhs_expression()?; let mut first_extends = self.parse_lhs_expression_or_higher()?;
let first_type_argument; let first_type_argument;
if let Expression::TSInstantiationExpression(expr) = first_extends { if let Expression::TSInstantiationExpression(expr) = first_extends {
let expr = expr.unbox(); let expr = expr.unbox();
@ -135,7 +135,7 @@ impl<'a> ParserImpl<'a> {
while self.eat(Kind::Comma) { while self.eat(Kind::Comma) {
let span = self.start_span(); let span = self.start_span();
let mut extend = self.parse_lhs_expression()?; let mut extend = self.parse_lhs_expression_or_higher()?;
let type_argument; let type_argument;
if let Expression::TSInstantiationExpression(expr) = extend { if let Expression::TSInstantiationExpression(expr) = extend {
let expr = expr.unbox(); let expr = expr.unbox();

View file

@ -115,11 +115,11 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn check_identifier(&mut self, span: Span, name: &Atom) { pub(crate) fn check_identifier(&mut self, span: Span, name: &Atom) {
// It is a Syntax Error if this production has an [Await] parameter. // It is a Syntax Error if this production has an [Await] parameter.
if self.ctx.has_await() && *name == "await" { if self.ctx.has_await() && name.as_str() == "await" {
self.error(diagnostics::identifier_async("await", span)); self.error(diagnostics::identifier_async("await", span));
} }
// It is a Syntax Error if this production has a [Yield] parameter. // It is a Syntax Error if this production has a [Yield] parameter.
if self.ctx.has_yield() && *name == "yield" { if self.ctx.has_yield() && name.as_str() == "yield" {
self.error(diagnostics::identifier_generator("yield", span)); self.error(diagnostics::identifier_generator("yield", span));
} }
} }
@ -498,11 +498,11 @@ impl<'a> ParserImpl<'a> {
} }
/// Section 13.3 Left-Hand-Side Expression /// Section 13.3 Left-Hand-Side Expression
pub(crate) fn parse_lhs_expression(&mut self) -> Result<Expression<'a>> { pub(crate) fn parse_lhs_expression_or_higher(&mut self) -> Result<Expression<'a>> {
let span = self.start_span(); let span = self.start_span();
let mut in_optional_chain = false; let mut in_optional_chain = false;
let lhs = self.parse_member_expression_base(&mut in_optional_chain)?; let lhs = self.parse_member_expression_or_higher(&mut in_optional_chain)?;
let lhs = self.parse_call_expression(span, lhs, &mut in_optional_chain)?; let lhs = self.parse_call_expression_rest(span, lhs, &mut in_optional_chain)?;
if in_optional_chain { if in_optional_chain {
let span = self.end_span(span); let span = self.end_span(span);
Ok(self.map_to_chain_expression(span, lhs)) Ok(self.map_to_chain_expression(span, lhs))
@ -525,13 +525,13 @@ impl<'a> ParserImpl<'a> {
} }
/// Section 13.3 Member Expression /// Section 13.3 Member Expression
fn parse_member_expression_base( fn parse_member_expression_or_higher(
&mut self, &mut self,
in_optional_chain: &mut bool, in_optional_chain: &mut bool,
) -> Result<Expression<'a>> { ) -> Result<Expression<'a>> {
let span = self.start_span(); let span = self.start_span();
self.parse_primary_expression() self.parse_primary_expression()
.and_then(|lhs| self.parse_member_expression_rhs(span, lhs, in_optional_chain)) .and_then(|lhs| self.parse_member_expression_rest(span, lhs, in_optional_chain))
} }
/// Section 13.3 Super Call /// Section 13.3 Super Call
@ -554,7 +554,7 @@ impl<'a> ParserImpl<'a> {
} }
/// parse rhs of a member expression, starting from lhs /// parse rhs of a member expression, starting from lhs
fn parse_member_expression_rhs( fn parse_member_expression_rest(
&mut self, &mut self,
lhs_span: Span, lhs_span: Span,
lhs: Expression<'a>, lhs: Expression<'a>,
@ -600,15 +600,15 @@ impl<'a> ParserImpl<'a> {
}; };
self.parse_tagged_template(lhs_span, expr, *in_optional_chain, type_parameters)? self.parse_tagged_template(lhs_span, expr, *in_optional_chain, type_parameters)?
} }
Kind::LAngle | Kind::ShiftLeft if self.ts_enabled() => { Kind::LAngle | Kind::ShiftLeft => {
if let Some(arguments) = self.parse_ts_type_arguments_in_expression() { if let Ok(Some(arguments)) =
lhs = Expression::TSInstantiationExpression(self.ast.alloc( self.try_parse(Self::parse_ts_type_arguments_in_expression)
TSInstantiationExpression { {
span: self.end_span(lhs_span), lhs = self.ast.ts_instantiation_expression(
expression: lhs, self.end_span(lhs_span),
type_parameters: arguments, lhs,
}, arguments,
)); );
continue; continue;
} }
break; break;
@ -667,7 +667,7 @@ impl<'a> ParserImpl<'a> {
let rhs_span = self.start_span(); let rhs_span = self.start_span();
let mut optional = false; let mut optional = false;
let mut callee = self.parse_member_expression_base(&mut optional)?; let mut callee = self.parse_member_expression_or_higher(&mut optional)?;
let mut type_parameter = None; let mut type_parameter = None;
if let Expression::TSInstantiationExpression(instantiation_expr) = callee { if let Expression::TSInstantiationExpression(instantiation_expr) = callee {
@ -699,7 +699,7 @@ impl<'a> ParserImpl<'a> {
} }
/// Section 13.3 Call Expression /// Section 13.3 Call Expression
fn parse_call_expression( fn parse_call_expression_rest(
&mut self, &mut self,
lhs_span: Span, lhs_span: Span,
lhs: Expression<'a>, lhs: Expression<'a>,
@ -708,12 +708,15 @@ impl<'a> ParserImpl<'a> {
let mut lhs = lhs; let mut lhs = lhs;
loop { loop {
let mut type_arguments = None; let mut type_arguments = None;
lhs = self.parse_member_expression_rhs(lhs_span, lhs, in_optional_chain)?; lhs = self.parse_member_expression_rest(lhs_span, lhs, in_optional_chain)?;
let optional_call = self.eat(Kind::QuestionDot); let optional_call = self.eat(Kind::QuestionDot);
*in_optional_chain = if optional_call { true } else { *in_optional_chain }; *in_optional_chain = if optional_call { true } else { *in_optional_chain };
if optional_call { if optional_call {
type_arguments = self.parse_ts_type_arguments_in_expression(); if let Ok(Some(args)) = self.try_parse(Self::parse_ts_type_arguments_in_expression)
{
type_arguments = Some(args);
}
if self.cur_kind().is_template_start_of_tagged_template() { if self.cur_kind().is_template_start_of_tagged_template() {
lhs = lhs =
self.parse_tagged_template(lhs_span, lhs, optional_call, type_arguments)?; self.parse_tagged_template(lhs_span, lhs, optional_call, type_arguments)?;
@ -758,9 +761,31 @@ impl<'a> ParserImpl<'a> {
} }
/// Section 13.4 Update Expression /// Section 13.4 Update Expression
fn parse_update_expression(&mut self) -> Result<Expression<'a>> { fn parse_update_expression(&mut self, lhs_span: Span) -> Result<Expression<'a>> {
let kind = self.cur_kind();
// ++ -- prefix update expressions
if kind.is_update_operator() {
let operator = map_update_operator(kind);
self.bump_any();
let argument = self.parse_unary_expression_or_higher(lhs_span)?;
let argument = SimpleAssignmentTarget::cover(argument, self)?;
return Ok(self.ast.update_expression(
self.end_span(lhs_span),
operator,
true,
argument,
));
}
if self.source_type.is_jsx()
&& kind == Kind::LAngle
&& self.peek_kind().is_identifier_name()
{
return self.parse_jsx_expression();
}
let span = self.start_span(); let span = self.start_span();
let lhs = self.parse_lhs_expression()?; let lhs = self.parse_lhs_expression_or_higher()?;
// ++ -- postfix update expressions // ++ -- postfix update expressions
if self.cur_kind().is_update_operator() && !self.cur_token().is_on_new_line { if self.cur_kind().is_update_operator() && !self.cur_token().is_on_new_line {
let operator = map_update_operator(self.cur_kind()); let operator = map_update_operator(self.cur_kind());
@ -772,50 +797,46 @@ impl<'a> ParserImpl<'a> {
} }
/// Section 13.5 Unary Expression /// Section 13.5 Unary Expression
pub(crate) fn parse_unary_expression_base(&mut self, lhs_span: Span) -> Result<Expression<'a>> { pub(crate) fn parse_unary_expression_or_higher(
// [+Await] AwaitExpression &mut self,
if self.is_await_expression() { lhs_span: Span,
return self.parse_await_expression(lhs_span); ) -> Result<Expression<'a>> {
}
if (self.at(Kind::LAngle) || self.at(Kind::ShiftLeft))
&& !self.source_type.is_jsx()
&& self.ts_enabled()
{
return self.parse_ts_type_assertion();
}
// ++ -- prefix update expressions // ++ -- prefix update expressions
if self.cur_kind().is_update_operator() { if self.is_update_expression() {
let operator = map_update_operator(self.cur_kind()); return self.parse_update_expression(lhs_span);
self.bump_any();
let argument = self.parse_unary_expression_base(lhs_span)?;
let argument = SimpleAssignmentTarget::cover(argument, self)?;
return Ok(self.ast.update_expression(
self.end_span(lhs_span),
operator,
true,
argument,
));
} }
self.parse_simple_unary_expression(lhs_span)
}
// delete void typeof + - ~ ! prefix unary expressions pub(crate) fn parse_simple_unary_expression(
if self.cur_kind().is_unary_operator() { &mut self,
return self.parse_unary_expression(); lhs_span: Span,
) -> Result<Expression<'a>> {
match self.cur_kind() {
kind if kind.is_unary_operator() => self.parse_unary_expression(),
Kind::LAngle => {
if self.source_type.is_jsx() {
return self.parse_jsx_expression();
}
if self.ts_enabled() {
return self.parse_ts_type_assertion();
}
Err(self.unexpected())
}
Kind::Await if self.is_await_expression() => self.parse_await_expression(lhs_span),
_ => self.parse_update_expression(lhs_span),
} }
self.parse_update_expression()
} }
fn parse_unary_expression(&mut self) -> Result<Expression<'a>> { fn parse_unary_expression(&mut self) -> Result<Expression<'a>> {
let span = self.start_span(); let span = self.start_span();
let operator = map_unary_operator(self.cur_kind()); let operator = map_unary_operator(self.cur_kind());
self.bump_any(); self.bump_any();
let argument = self.parse_unary_expression_base(span)?; let argument = self.parse_simple_unary_expression(span)?;
Ok(self.ast.unary_expression(self.end_span(span), operator, argument)) Ok(self.ast.unary_expression(self.end_span(span), operator, argument))
} }
fn parse_binary_or_logical_expression_base( pub(crate) fn parse_binary_expression_or_higher(
&mut self, &mut self,
lhs_precedence: Precedence, lhs_precedence: Precedence,
) -> Result<Expression<'a>> { ) -> Result<Expression<'a>> {
@ -824,7 +845,7 @@ impl<'a> ParserImpl<'a> {
let lhs = if self.ctx.has_in() && self.at(Kind::PrivateIdentifier) { let lhs = if self.ctx.has_in() && self.at(Kind::PrivateIdentifier) {
let left = self.parse_private_identifier(); let left = self.parse_private_identifier();
self.expect(Kind::In)?; self.expect(Kind::In)?;
let right = self.parse_unary_expression_base(lhs_span)?; let right = self.parse_unary_expression_or_higher(lhs_span)?;
Expression::PrivateInExpression(self.ast.alloc(PrivateInExpression { Expression::PrivateInExpression(self.ast.alloc(PrivateInExpression {
span: self.end_span(lhs_span), span: self.end_span(lhs_span),
left, left,
@ -832,14 +853,14 @@ impl<'a> ParserImpl<'a> {
right, right,
})) }))
} else { } else {
self.parse_unary_expression_base(lhs_span)? self.parse_unary_expression_or_higher(lhs_span)?
}; };
self.parse_binary_or_logical_expression_recursive(lhs_span, lhs, lhs_precedence) self.parse_binary_expression_rest(lhs_span, lhs, lhs_precedence)
} }
/// Section 13.6 - 13.13 Binary Expression /// Section 13.6 - 13.13 Binary Expression
fn parse_binary_or_logical_expression_recursive( fn parse_binary_expression_rest(
&mut self, &mut self,
lhs_span: Span, lhs_span: Span,
lhs: Expression<'a>, lhs: Expression<'a>,
@ -888,7 +909,7 @@ impl<'a> ParserImpl<'a> {
} }
self.bump_any(); // bump operator self.bump_any(); // bump operator
let rhs = self.parse_binary_or_logical_expression_base(left_precedence)?; let rhs = self.parse_binary_expression_or_higher(left_precedence)?;
lhs = if kind.is_logical_operator() { lhs = if kind.is_logical_operator() {
self.ast.logical_expression( self.ast.logical_expression(
@ -916,9 +937,11 @@ impl<'a> ParserImpl<'a> {
/// `ConditionalExpression`[In, Yield, Await] : /// `ConditionalExpression`[In, Yield, Await] :
/// `ShortCircuitExpression`[?In, ?Yield, ?Await] /// `ShortCircuitExpression`[?In, ?Yield, ?Await]
/// `ShortCircuitExpression`[?In, ?Yield, ?Await] ? `AssignmentExpression`[+In, ?Yield, ?Await] : `AssignmentExpression`[?In, ?Yield, ?Await] /// `ShortCircuitExpression`[?In, ?Yield, ?Await] ? `AssignmentExpression`[+In, ?Yield, ?Await] : `AssignmentExpression`[?In, ?Yield, ?Await]
fn parse_conditional_expression(&mut self) -> Result<Expression<'a>> { fn parse_conditional_expression_rest(
let span = self.start_span(); &mut self,
let lhs = self.parse_binary_or_logical_expression_base(Precedence::lowest())?; lhs_span: Span,
lhs: Expression<'a>,
) -> Result<Expression<'a>> {
if !self.eat(Kind::Question) { if !self.eat(Kind::Question) {
return Ok(lhs); return Ok(lhs);
} }
@ -929,7 +952,7 @@ impl<'a> ParserImpl<'a> {
)?; )?;
self.expect(Kind::Colon)?; self.expect(Kind::Colon)?;
let alternate = self.parse_assignment_expression_or_higher()?; let alternate = self.parse_assignment_expression_or_higher()?;
Ok(self.ast.conditional_expression(self.end_span(span), lhs, consequent, alternate)) Ok(self.ast.conditional_expression(self.end_span(lhs_span), lhs, consequent, alternate))
} }
/// `AssignmentExpression`[In, Yield, Await] : /// `AssignmentExpression`[In, Yield, Await] :
@ -946,13 +969,21 @@ impl<'a> ParserImpl<'a> {
if let Some(arrow_expr) = self.try_parse_async_simple_arrow_function_expression()? { if let Some(arrow_expr) = self.try_parse_async_simple_arrow_function_expression()? {
return Ok(arrow_expr); return Ok(arrow_expr);
} }
let span = self.start_span(); let span = self.start_span();
let lhs = self.parse_binary_expression_or_higher(Precedence::lowest())?;
let kind = self.cur_kind();
// `x => {}` // `x => {}`
if self.cur_kind().is_binding_identifier() && self.peek_at(Kind::Arrow) { if lhs.is_identifier_reference() && kind == Kind::Arrow {
return self.parse_simple_arrow_function_expression(span, /* r#async */ false); return self.parse_simple_arrow_function_expression(span, lhs, /* async */ false);
} }
let lhs = self.parse_conditional_expression()?;
self.parse_assignment_expression_recursive(span, lhs) if kind.is_assignment_operator() {
return self.parse_assignment_expression_recursive(span, lhs);
}
self.parse_conditional_expression_rest(span, lhs)
} }
fn parse_assignment_expression_recursive( fn parse_assignment_expression_recursive(
@ -960,12 +991,7 @@ impl<'a> ParserImpl<'a> {
span: Span, span: Span,
lhs: Expression<'a>, lhs: Expression<'a>,
) -> Result<Expression<'a>> { ) -> Result<Expression<'a>> {
if !self.cur_kind().is_assignment_operator() {
return Ok(lhs);
}
let operator = map_assignment_operator(self.cur_kind()); let operator = map_assignment_operator(self.cur_kind());
// 13.15.5 Destructuring Assignment // 13.15.5 Destructuring Assignment
// LeftHandSideExpression = AssignmentExpression // LeftHandSideExpression = AssignmentExpression
// is converted to // is converted to
@ -973,9 +999,7 @@ impl<'a> ParserImpl<'a> {
// ObjectAssignmentPattern // ObjectAssignmentPattern
// ArrayAssignmentPattern // ArrayAssignmentPattern
let left = AssignmentTarget::cover(lhs, self)?; let left = AssignmentTarget::cover(lhs, self)?;
self.bump_any(); self.bump_any();
let right = self.parse_assignment_expression_or_higher()?; let right = self.parse_assignment_expression_or_higher()?;
Ok(self.ast.assignment_expression(self.end_span(span), operator, left, right)) Ok(self.ast.assignment_expression(self.end_span(span), operator, left, right))
} }
@ -1004,7 +1028,7 @@ impl<'a> ParserImpl<'a> {
self.error(diagnostics::await_expression(Span::new(span.start, span.start + 5))); self.error(diagnostics::await_expression(Span::new(span.start, span.start + 5)));
} }
let argument = self.context(Context::Await, Context::empty(), |p| { let argument = self.context(Context::Await, Context::empty(), |p| {
p.parse_unary_expression_base(lhs_span) p.parse_simple_unary_expression(lhs_span)
})?; })?;
Ok(self.ast.await_expression(self.end_span(span), argument)) Ok(self.ast.await_expression(self.end_span(span), argument))
} }
@ -1016,18 +1040,38 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn parse_decorator(&mut self) -> Result<Decorator<'a>> { pub(crate) fn parse_decorator(&mut self) -> Result<Decorator<'a>> {
let span = self.start_span(); let span = self.start_span();
self.bump_any(); // bump @ self.bump_any(); // bump @
let expr = let expr = self.context(
self.context(Context::Decorator, Context::empty(), Self::parse_lhs_expression)?; Context::Decorator,
Context::empty(),
Self::parse_lhs_expression_or_higher,
)?;
Ok(self.ast.decorator(self.end_span(span), expr)) Ok(self.ast.decorator(self.end_span(span), expr))
} }
fn is_update_expression(&self) -> bool {
match self.cur_kind() {
kind if kind.is_unary_operator() => false,
Kind::Await => false,
Kind::LAngle => {
if !self.source_type.is_jsx() {
return false;
}
true
}
_ => true,
}
}
fn is_await_expression(&mut self) -> bool { fn is_await_expression(&mut self) -> bool {
if self.at(Kind::Await) { if self.at(Kind::Await) {
let peek_token = self.peek_token();
// Allow arrow expression `await => {}`
if peek_token.kind == Kind::Arrow {
return false;
}
if self.ctx.has_await() { if self.ctx.has_await() {
return true; return true;
} }
let peek_token = self.peek_token();
// The following expressions are ambiguous // The following expressions are ambiguous
// await + 0, await - 0, await ( 0 ), await [ 0 ], await / 0 /u, await ``, await of [] // await + 0, await - 0, await ( 0 ), await [ 0 ], await / 0 /u, await ``, await of []
if matches!( if matches!(
@ -1037,7 +1081,7 @@ impl<'a> ParserImpl<'a> {
return false; return false;
} }
return peek_token.kind.is_after_await_or_yield() && !peek_token.is_on_new_line; return !peek_token.is_on_new_line && peek_token.kind.is_after_await_or_yield();
} }
false false
} }
@ -1045,13 +1089,14 @@ impl<'a> ParserImpl<'a> {
fn is_yield_expression(&mut self) -> bool { fn is_yield_expression(&mut self) -> bool {
if self.at(Kind::Yield) { if self.at(Kind::Yield) {
let peek_token = self.peek_token(); let peek_token = self.peek_token();
// Allow arrow expression `yield => {}`
if peek_token.kind == Kind::Arrow { if peek_token.kind == Kind::Arrow {
return false; return false;
} }
if self.ctx.has_yield() { if self.ctx.has_yield() {
return true; return true;
} }
return peek_token.kind.is_after_await_or_yield() && !peek_token.is_on_new_line; return !peek_token.is_on_new_line && peek_token.kind.is_after_await_or_yield();
} }
false false
} }

View file

@ -359,7 +359,7 @@ impl<'a> ParserImpl<'a> {
let type_annotation = self.parse_ts_type()?; let type_annotation = self.parse_ts_type()?;
self.expect(Kind::RAngle)?; self.expect(Kind::RAngle)?;
let lhs_span = self.start_span(); let lhs_span = self.start_span();
let expression = self.parse_unary_expression_base(lhs_span)?; let expression = self.parse_simple_unary_expression(lhs_span)?;
Ok(self.ast.ts_type_assertion(self.end_span(span), type_annotation, expression)) Ok(self.ast.ts_type_assertion(self.end_span(span), type_annotation, expression))
} }

View file

@ -532,25 +532,26 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn parse_ts_type_arguments_in_expression( pub(crate) fn parse_ts_type_arguments_in_expression(
&mut self, &mut self,
) -> Option<Box<'a, TSTypeParameterInstantiation<'a>>> { ) -> Result<Option<Box<'a, TSTypeParameterInstantiation<'a>>>> {
if !matches!(self.cur_kind(), Kind::LAngle | Kind::ShiftLeft) { if !self.ts_enabled() {
return None; return Ok(None);
} }
let span = self.start_span(); let span = self.start_span();
self.re_lex_ts_l_angle();
if !self.at(Kind::LAngle) {
return Ok(None);
}
self.try_parse(|p| { let params = TSTypeArgumentList::parse(self, /* in_expression */ true)?.params;
p.re_lex_ts_l_angle();
let params = TSTypeArgumentList::parse(p, true)?.params; let token = self.cur_token();
let token = p.cur_token();
if token.is_on_new_line || token.kind.can_follow_type_arguments_in_expr() { if token.is_on_new_line || token.kind.can_follow_type_arguments_in_expr() {
Ok(params) return Ok(Some(self.ast.ts_type_arguments(self.end_span(span), params)));
} else { }
Err(p.unexpected())
} Err(self.unexpected())
})
.ok()
.map(|types| self.ast.ts_type_arguments(self.end_span(span), types))
} }
fn parse_ts_tuple_type(&mut self) -> Result<TSType<'a>> { fn parse_ts_tuple_type(&mut self) -> Result<TSType<'a>> {

View file

@ -3,7 +3,7 @@ commit: 4bd1b2c2
parser_babel Summary: parser_babel Summary:
AST Parsed : 2093/2099 (99.71%) AST Parsed : 2093/2099 (99.71%)
Positive Passed: 2086/2099 (99.38%) Positive Passed: 2086/2099 (99.38%)
Negative Passed: 1363/1501 (90.81%) Negative Passed: 1362/1501 (90.74%)
Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js" Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js"
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions/input.js"
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js"
@ -25,6 +25,7 @@ Expect Syntax Error: "es2015/for-of/invalid-let-as-identifier/input.js"
Expect Syntax Error: "es2015/object/disallow-duplicate-method-params/input.js" Expect Syntax Error: "es2015/object/disallow-duplicate-method-params/input.js"
Expect Syntax Error: "es2015/uncategorised/297/input.js" Expect Syntax Error: "es2015/uncategorised/297/input.js"
Expect Syntax Error: "es2015/uncategorised/335/input.js" Expect Syntax Error: "es2015/uncategorised/335/input.js"
Expect Syntax Error: "es2017/async-functions/async-await-as-arrow-binding-identifier/input.js"
Expect Syntax Error: "es2017/async-functions/await-binding-inside-arrow-params-inside-async-arrow-params/input.js" Expect Syntax Error: "es2017/async-functions/await-binding-inside-arrow-params-inside-async-arrow-params/input.js"
Expect Syntax Error: "es2017/trailing-function-commas/7/input.js" Expect Syntax Error: "es2017/trailing-function-commas/7/input.js"
Expect Syntax Error: "es2018/object-rest-spread/24/input.js" Expect Syntax Error: "es2018/object-rest-spread/24/input.js"
@ -4842,12 +4843,6 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts"
3 │ } 3 │ }
╰──── ╰────
× Cannot use `await` as an identifier in an async context
╭─[es2017/async-functions/async-await-as-arrow-binding-identifier/input.js:1:7]
1 │ async await => {}
· ─────
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none × Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[es2017/async-functions/async-function-and-non-bmp-character/input.js:1:6] ╭─[es2017/async-functions/async-function-and-non-bmp-character/input.js:1:6]
1 │ async function𝐬 f() {} 1 │ async function𝐬 f() {}

View file

@ -3,7 +3,7 @@ commit: 64d2eeea
parser_typescript Summary: parser_typescript Summary:
AST Parsed : 5240/5243 (99.94%) AST Parsed : 5240/5243 (99.94%)
Positive Passed: 5233/5243 (99.81%) Positive Passed: 5233/5243 (99.81%)
Negative Passed: 1064/4879 (21.81%) Negative Passed: 1065/4879 (21.83%)
Expect Syntax Error: "compiler/ClassDeclaration10.ts" Expect Syntax Error: "compiler/ClassDeclaration10.ts"
Expect Syntax Error: "compiler/ClassDeclaration11.ts" Expect Syntax Error: "compiler/ClassDeclaration11.ts"
Expect Syntax Error: "compiler/ClassDeclaration13.ts" Expect Syntax Error: "compiler/ClassDeclaration13.ts"
@ -58,7 +58,6 @@ Expect Syntax Error: "compiler/ambientExternalModuleWithRelativeModuleName.ts"
Expect Syntax Error: "compiler/ambientGetters.ts" Expect Syntax Error: "compiler/ambientGetters.ts"
Expect Syntax Error: "compiler/ambientPropertyDeclarationInJs.ts" Expect Syntax Error: "compiler/ambientPropertyDeclarationInJs.ts"
Expect Syntax Error: "compiler/ambientStatement1.ts" Expect Syntax Error: "compiler/ambientStatement1.ts"
Expect Syntax Error: "compiler/ambiguousGenericAssertion1.ts"
Expect Syntax Error: "compiler/ambiguousOverload.ts" Expect Syntax Error: "compiler/ambiguousOverload.ts"
Expect Syntax Error: "compiler/amdDependencyComment1.ts" Expect Syntax Error: "compiler/amdDependencyComment1.ts"
Expect Syntax Error: "compiler/amdDependencyComment2.ts" Expect Syntax Error: "compiler/amdDependencyComment2.ts"
@ -4123,6 +4122,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
26 │ } 26 │ }
╰──── ╰────
× Unexpected token
╭─[compiler/ambiguousGenericAssertion1.ts:4:10]
3 │ var r2 = < <T>(x: T) => T>f; // valid
4 │ var r3 = <<T>(x: T) => T>f; // ambiguous, appears to the parser as a << operation
· ──
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none × Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[compiler/anonymousModules.ts:1:7] ╭─[compiler/anonymousModules.ts:1:7]
1 │ module { 1 │ module {
@ -5365,10 +5371,10 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
╰──── ╰────
× Unexpected token × Unexpected token
╭─[compiler/conflictMarkerDiff3Trivia2.ts:3:2] ╭─[compiler/conflictMarkerDiff3Trivia2.ts:3:1]
2 │ foo() { 2 │ foo() {
3 │ <<<<<<< B 3 │ <<<<<<< B
· ── · ──
4 │ a(); 4 │ a();
╰──── ╰────
@ -5381,10 +5387,10 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
╰──── ╰────
× Unexpected token × Unexpected token
╭─[compiler/conflictMarkerTrivia2.ts:3:2] ╭─[compiler/conflictMarkerTrivia2.ts:3:1]
2 │ foo() { 2 │ foo() {
3 │ <<<<<<< B 3 │ <<<<<<< B
· ── · ──
4 │ a(); 4 │ a();
╰──── ╰────
@ -5396,10 +5402,10 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
╰──── ╰────
× Unexpected token × Unexpected token
╭─[compiler/conflictMarkerTrivia4.ts:2:2] ╭─[compiler/conflictMarkerTrivia4.ts:2:1]
1 │ const x = <div> 1 │ const x = <div>
2 │ <<<<<<< HEAD 2 │ <<<<<<< HEAD
· ── · ──
╰──── ╰────
× Identifier `y` has already been declared × Identifier `y` has already been declared