mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
refactor(parser): use function instead of trait to parse normal lists (#4003)
To reduce boilerplate and code noise. relates #3887
This commit is contained in:
parent
0b147062c6
commit
d0eac46fc8
8 changed files with 66 additions and 162 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -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);
|
||||
|
|
@ -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 ...
|
||||
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
@ -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() {
|
||||
|
|
@ -340,7 +342,7 @@ impl<'a> ParserImpl<'a> {
|
|||
self.error(diagnostics::static_prototype(span));
|
||||
}
|
||||
}
|
||||
Ok(definition)
|
||||
Ok(Some(definition))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
@ -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>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
@ -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 => {
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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>>,
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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() {
|
||||
|
|
@ -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:`
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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>> {
|
||||
|
|
|
|||
Loading…
Reference in a new issue