Skip to content

Commit

Permalink
refactor(parser): use function instead of trait to parse normal lists (
Browse files Browse the repository at this point in the history
…#4003)

To reduce boilerplate and code noise.

relates #3887
  • Loading branch information
Boshen committed Jul 1, 2024
1 parent 0b14706 commit d0eac46
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 162 deletions.
26 changes: 26 additions & 0 deletions crates/oxc_parser/src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,30 @@ impl<'a> ParserImpl<'a> {
let decorators = std::mem::take(&mut self.state.decorators);
self.ast.new_vec_from_iter(decorators)
}

pub(crate) fn parse_normal_list<F, T>(
&mut self,
open: Kind,
close: Kind,
f: F,
) -> Result<oxc_allocator::Vec<'a, T>>
where
F: Fn(&mut Self) -> Result<Option<T>>,
{
let mut list = self.ast.new_vec();
self.expect(open)?;
loop {
let kind = self.cur_kind();
if kind == close || kind == Kind::Eof {
break;
}
if let Some(e) = f(self)? {
list.push(e);
} else {
break;
}
}
self.expect(close)?;
Ok(list)
}
}
38 changes: 20 additions & 18 deletions crates/oxc_parser/src/js/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ use oxc_ast::{ast::*, syntax_directed_operations::PropName};
use oxc_diagnostics::Result;
use oxc_span::{GetSpan, Span};

use super::list::ClassElements;
use crate::{
diagnostics,
lexer::Kind,
list::NormalList,
modifiers::{ModifierFlags, ModifierKind, Modifiers},
Context, ParserImpl, StatementContext,
};
Expand Down Expand Up @@ -170,13 +168,20 @@ impl<'a> ParserImpl<'a> {

fn parse_class_body(&mut self) -> Result<Box<'a, ClassBody<'a>>> {
let span = self.start_span();
let mut class_elements = ClassElements::new(self);
class_elements.parse(self)?;
let body = class_elements.elements;
Ok(self.ast.class_body(self.end_span(span), body))
let class_elements =
self.parse_normal_list(Kind::LCurly, Kind::RCurly, Self::parse_class_element)?;
Ok(self.ast.class_body(self.end_span(span), class_elements))
}

pub(crate) fn parse_class_element(&mut self) -> Result<ClassElement<'a>> {
pub(crate) fn parse_class_element(&mut self) -> Result<Option<ClassElement<'a>>> {
// skip empty class element `;`
while self.at(Kind::Semicolon) {
self.bump_any();
}
if self.at(Kind::RCurly) {
return Ok(None);
}

let span = self.start_span();

let modifiers = self.parse_modifiers(true, false, true);
Expand All @@ -199,7 +204,7 @@ impl<'a> ParserImpl<'a> {
// static { block }
if self.peek_at(Kind::LCurly) {
self.bump(Kind::Static);
return self.parse_class_static_block(span);
return self.parse_class_static_block(span).map(Some);
}

// static ...
Expand All @@ -225,7 +230,7 @@ impl<'a> ParserImpl<'a> {

if self.is_at_ts_index_signature_member() {
if let TSSignature::TSIndexSignature(sig) = self.parse_ts_index_signature_member()? {
return Ok(ClassElement::TSIndexSignature(sig));
return Ok(Some(ClassElement::TSIndexSignature(sig)));
}
}

Expand Down Expand Up @@ -277,13 +282,10 @@ impl<'a> ParserImpl<'a> {

if accessor {
self.parse_ts_type_annotation()?;

return self.parse_class_accessor_property(span, key, computed, r#static, r#abstract);
}

// LAngle for start of type parameters `foo<T>`
// ^
if self.at(Kind::LParen) || self.at(Kind::LAngle) || r#async || generator {
self.parse_class_accessor_property(span, key, computed, r#static, r#abstract).map(Some)
} else if self.at(Kind::LParen) || self.at(Kind::LAngle) || r#async || generator {
// LAngle for start of type parameters `foo<T>`
// ^
let definition = self.parse_class_method_definition(
span,
kind,
Expand Down Expand Up @@ -313,7 +315,7 @@ impl<'a> ParserImpl<'a> {
}
}
}
Ok(definition)
Ok(Some(definition))
} else {
// getter and setter has no ts type annotation
if !kind.is_method() {
Expand All @@ -340,7 +342,7 @@ impl<'a> ParserImpl<'a> {
self.error(diagnostics::static_prototype(span));
}
}
Ok(definition)
Ok(Some(definition))
}
}

Expand Down
68 changes: 1 addition & 67 deletions crates/oxc_parser/src/js/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,7 @@ use oxc_diagnostics::Result;
use oxc_span::{Atom, GetSpan, Span};
use rustc_hash::FxHashMap;

use crate::{
diagnostics,
lexer::Kind,
list::{NormalList, SeparatedList},
modifiers::ModifierFlags,
ParserImpl,
};
use crate::{diagnostics, lexer::Kind, list::SeparatedList, modifiers::ModifierFlags, ParserImpl};

/// ObjectExpression.properties
pub struct ObjectExpressionProperties<'a> {
Expand Down Expand Up @@ -402,66 +396,6 @@ impl<'a> SeparatedList<'a> for ExportNamedSpecifiers<'a> {
}
}

pub struct ClassElements<'a> {
pub elements: Vec<'a, ClassElement<'a>>,
}

impl<'a> ClassElements<'a> {
pub(crate) fn new(p: &ParserImpl<'a>) -> Self {
Self { elements: p.ast.new_vec() }
}
}

impl<'a> NormalList<'a> for ClassElements<'a> {
fn open(&self) -> Kind {
Kind::LCurly
}

fn close(&self) -> Kind {
Kind::RCurly
}

fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
// skip empty class element `;`
while p.at(Kind::Semicolon) {
p.bump_any();
}
if p.at(self.close()) {
return Ok(());
}
let element = p.parse_class_element()?;

self.elements.push(element);
Ok(())
}
}

pub struct SwitchCases<'a> {
pub elements: Vec<'a, SwitchCase<'a>>,
}

impl<'a> SwitchCases<'a> {
pub(crate) fn new(p: &ParserImpl<'a>) -> Self {
Self { elements: p.ast.new_vec() }
}
}

impl<'a> NormalList<'a> for SwitchCases<'a> {
fn open(&self) -> Kind {
Kind::LCurly
}

fn close(&self) -> Kind {
Kind::RCurly
}

fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
let element = p.parse_switch_case()?;
self.elements.push(element);
Ok(())
}
}

pub struct ImportSpecifierList<'a> {
pub import_specifiers: Vec<'a, ImportDeclarationSpecifier<'a>>,
}
Expand Down
17 changes: 5 additions & 12 deletions crates/oxc_parser/src/js/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ use oxc_ast::ast::*;
use oxc_diagnostics::Result;
use oxc_span::{Atom, GetSpan, Span};

use super::{
grammar::CoverGrammar, list::SwitchCases, VariableDeclarationContext, VariableDeclarationParent,
};
use super::{grammar::CoverGrammar, VariableDeclarationContext, VariableDeclarationParent};
use crate::{
diagnostics, lexer::Kind, list::NormalList, modifiers::Modifiers, Context, ParserImpl,
StatementContext,
diagnostics, lexer::Kind, modifiers::Modifiers, Context, ParserImpl, StatementContext,
};

impl<'a> ParserImpl<'a> {
Expand Down Expand Up @@ -441,15 +438,11 @@ impl<'a> ParserImpl<'a> {
let span = self.start_span();
self.bump_any(); // advance `switch`
let discriminant = self.parse_paren_expression()?;
let cases = {
let mut switch_cases = SwitchCases::new(self);
switch_cases.parse(self)?;
switch_cases.elements
};
let cases = self.parse_normal_list(Kind::LCurly, Kind::RCurly, Self::parse_switch_case)?;
Ok(self.ast.switch_statement(self.end_span(span), discriminant, cases))
}

pub(crate) fn parse_switch_case(&mut self) -> Result<SwitchCase<'a>> {
pub(crate) fn parse_switch_case(&mut self) -> Result<Option<SwitchCase<'a>>> {
let span = self.start_span();
let test = match self.cur_kind() {
Kind::Default => {
Expand All @@ -469,7 +462,7 @@ impl<'a> ParserImpl<'a> {
let stmt = self.parse_statement_list_item(StatementContext::StatementList)?;
consequent.push(stmt);
}
Ok(self.ast.switch_case(self.end_span(span), test, consequent))
Ok(Some(self.ast.switch_case(self.end_span(span), test, consequent)))
}

/// Section 14.14 Throw Statement
Expand Down
20 changes: 0 additions & 20 deletions crates/oxc_parser/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,6 @@ use oxc_diagnostics::Result;

use crate::{lexer::Kind, ParserImpl};

pub trait NormalList<'a> {
/// Open element, e.g.. `{` `[` `(`
fn open(&self) -> Kind;

/// Close element, e.g.. `}` `]` `)`
fn close(&self) -> Kind;

fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()>;

/// Main entry point, parse the list
fn parse(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
p.expect(self.open())?;
while !p.at(self.close()) && !p.at(Kind::Eof) {
self.parse_element(p)?;
}
p.expect(self.close())?;
Ok(())
}
}

pub trait SeparatedList<'a>: Sized {
fn new(p: &ParserImpl<'a>) -> Self;

Expand Down
32 changes: 1 addition & 31 deletions crates/oxc_parser/src/ts/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ use oxc_allocator::Vec;
use oxc_ast::ast::*;
use oxc_diagnostics::Result;

use crate::{
lexer::Kind,
list::{NormalList, SeparatedList},
ParserImpl,
};
use crate::{lexer::Kind, list::SeparatedList, ParserImpl};

pub struct TSEnumMemberList<'a> {
pub members: Vec<'a, TSEnumMember<'a>>,
Expand Down Expand Up @@ -80,32 +76,6 @@ impl<'a> SeparatedList<'a> for TSTypeParameterList<'a> {
}
}

pub struct TSInterfaceOrObjectBodyList<'a> {
pub body: Vec<'a, TSSignature<'a>>,
}

impl<'a> TSInterfaceOrObjectBodyList<'a> {
pub(crate) fn new(p: &ParserImpl<'a>) -> Self {
Self { body: p.ast.new_vec() }
}
}

impl<'a> NormalList<'a> for TSInterfaceOrObjectBodyList<'a> {
fn open(&self) -> Kind {
Kind::LCurly
}

fn close(&self) -> Kind {
Kind::RCurly
}

fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
let property = p.parse_ts_type_signature()?;
self.body.push(property);
Ok(())
}
}

pub struct TSTypeArgumentList<'a> {
pub params: Vec<'a, TSType<'a>>,
in_expression: bool,
Expand Down
15 changes: 8 additions & 7 deletions crates/oxc_parser/src/ts/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use oxc_ast::ast::*;
use oxc_diagnostics::Result;
use oxc_span::Span;

use super::list::{TSEnumMemberList, TSInterfaceOrObjectBodyList};
use super::list::TSEnumMemberList;
use crate::{
diagnostics,
js::{FunctionKind, VariableDeclarationContext, VariableDeclarationParent},
lexer::Kind,
list::{NormalList, SeparatedList},
list::SeparatedList,
modifiers::{ModifierFlags, ModifierKind, Modifiers},
ParserImpl,
};
Expand Down Expand Up @@ -161,9 +161,9 @@ impl<'a> ParserImpl<'a> {

fn parse_ts_interface_body(&mut self) -> Result<Box<'a, TSInterfaceBody<'a>>> {
let span = self.start_span();
let mut body_list = TSInterfaceOrObjectBodyList::new(self);
body_list.parse(self)?;
Ok(self.ast.ts_interface_body(self.end_span(span), body_list.body))
let body_list =
self.parse_normal_list(Kind::LCurly, Kind::RCurly, Self::parse_ts_type_signature)?;
Ok(self.ast.ts_interface_body(self.end_span(span), body_list))
}

pub(crate) fn is_at_interface_declaration(&mut self) -> bool {
Expand All @@ -174,9 +174,9 @@ impl<'a> ParserImpl<'a> {
}
}

pub(crate) fn parse_ts_type_signature(&mut self) -> Result<TSSignature<'a>> {
pub(crate) fn parse_ts_type_signature(&mut self) -> Result<Option<TSSignature<'a>>> {
if self.is_at_ts_index_signature_member() {
return self.parse_ts_index_signature_member();
return self.parse_ts_index_signature_member().map(Some);
}

match self.cur_kind() {
Expand All @@ -192,6 +192,7 @@ impl<'a> ParserImpl<'a> {
}
_ => self.parse_ts_property_or_method_signature_member(),
}
.map(Some)
}

/// Must be at `[ident:` or `<modifiers> [ident:`
Expand Down
12 changes: 5 additions & 7 deletions crates/oxc_parser/src/ts/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ use oxc_diagnostics::Result;
use oxc_span::GetSpan;
use oxc_syntax::operator::UnaryOperator;

use super::list::{
TSInterfaceOrObjectBodyList, TSTupleElementList, TSTypeArgumentList, TSTypeParameterList,
};
use super::list::{TSTupleElementList, TSTypeArgumentList, TSTypeParameterList};
use crate::{
diagnostics,
lexer::Kind,
list::{NormalList, SeparatedList},
list::SeparatedList,
modifiers::{Modifier, ModifierFlags, ModifierKind, Modifiers},
ts::list::TSImportAttributeList,
Context, ParserImpl,
Expand Down Expand Up @@ -618,9 +616,9 @@ impl<'a> ParserImpl<'a> {

fn parse_type_literal(&mut self) -> Result<TSType<'a>> {
let span = self.start_span();
let mut member_list = TSInterfaceOrObjectBodyList::new(self);
member_list.parse(self)?;
Ok(self.ast.ts_type_literal(self.end_span(span), member_list.body))
let member_list =
self.parse_normal_list(Kind::LCurly, Kind::RCurly, Self::parse_ts_type_signature)?;
Ok(self.ast.ts_type_literal(self.end_span(span), member_list))
}

fn parse_type_query(&mut self) -> Result<TSType<'a>> {
Expand Down

0 comments on commit d0eac46

Please sign in to comment.