mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
refactor(parser): wrapper type for parser (#2339)
Split parser into public interface `Parser` and internal implementation `ParserImpl`. This involves no changes to public API. This change is a bit annoying, but justification is that it's required for #2341, which I believe to be very worthwhile. The `ParserOptions` type also makes it a bit clearer what the defaults for `allow_return_outside_function` and `preserve_parens` are. It came as a surprise to me that `preserve_parens` defaults to `true`, and this refactor makes that a bit more obvious when reading the code. All the real changes are in [oxc_parser/src/lib.rs](https://github.com/oxc-project/oxc/pull/2339/files#diff-8e59dfd35fc50b6ac9a9ccd991e25c8b5d30826e006d565a2e01f3d15dc5f7cb). The rest of the diff is basically replacing `Parser` with `ParserImpl` everywhere else.
This commit is contained in:
parent
3268d7d66e
commit
0bdecb5043
18 changed files with 169 additions and 120 deletions
|
|
@ -7,7 +7,7 @@ use oxc_span::Span;
|
|||
use crate::{
|
||||
diagnostics,
|
||||
lexer::{Kind, LexerCheckpoint, LexerContext, Token},
|
||||
Context, Parser,
|
||||
Context, ParserImpl,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
|
@ -18,7 +18,7 @@ pub struct ParserCheckpoint<'a> {
|
|||
errors_pos: usize,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
pub(crate) fn start_span(&self) -> Span {
|
||||
let token = self.cur_token();
|
||||
Span::new(token.start, 0)
|
||||
|
|
@ -266,7 +266,7 @@ impl<'a> Parser<'a> {
|
|||
/// # Errors
|
||||
pub(crate) fn try_parse<T>(
|
||||
&mut self,
|
||||
func: impl FnOnce(&mut Parser<'a>) -> Result<T>,
|
||||
func: impl FnOnce(&mut ParserImpl<'a>) -> Result<T>,
|
||||
) -> Result<T> {
|
||||
let checkpoint = self.checkpoint();
|
||||
let ctx = self.ctx;
|
||||
|
|
@ -278,7 +278,7 @@ impl<'a> Parser<'a> {
|
|||
result
|
||||
}
|
||||
|
||||
pub(crate) fn lookahead<U>(&mut self, predicate: impl Fn(&mut Parser<'a>) -> U) -> U {
|
||||
pub(crate) fn lookahead<U>(&mut self, predicate: impl Fn(&mut ParserImpl<'a>) -> U) -> U {
|
||||
let checkpoint = self.checkpoint();
|
||||
let answer = predicate(self);
|
||||
self.rewind(checkpoint);
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ use oxc_diagnostics::Result;
|
|||
use oxc_span::Span;
|
||||
|
||||
use super::list::{ArrayPatternList, ObjectPatternProperties};
|
||||
use crate::{diagnostics, lexer::Kind, list::SeparatedList, Context, Parser};
|
||||
use crate::{diagnostics, lexer::Kind, list::SeparatedList, Context, ParserImpl};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
/// Destructuring Binding Patterns
|
||||
/// `LexicalBinding`
|
||||
/// `BindingIdentifier` `Initializer_opt`
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use oxc_diagnostics::Result;
|
|||
use oxc_span::{GetSpan, Span};
|
||||
|
||||
use super::list::ClassElements;
|
||||
use crate::{diagnostics, lexer::Kind, list::NormalList, Parser, StatementContext};
|
||||
use crate::{diagnostics, lexer::Kind, list::NormalList, ParserImpl, StatementContext};
|
||||
|
||||
type Extends<'a> =
|
||||
Vec<'a, (Expression<'a>, Option<Box<'a, TSTypeParameterInstantiation<'a>>>, Span)>;
|
||||
|
|
@ -12,7 +12,7 @@ type Extends<'a> =
|
|||
type Implements<'a> = Vec<'a, Box<'a, TSClassImplements<'a>>>;
|
||||
|
||||
/// Section 15.7 Class Definitions
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
// `start_span` points at the start of all decoractors and `class` keyword.
|
||||
pub(crate) fn parse_class_statement(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use oxc_ast::ast::*;
|
|||
use oxc_diagnostics::Result;
|
||||
use oxc_span::{GetSpan, Span};
|
||||
|
||||
use crate::{diagnostics, lexer::Kind, Parser, StatementContext};
|
||||
use crate::{diagnostics, lexer::Kind, ParserImpl, StatementContext};
|
||||
|
||||
#[derive(Clone, Debug, Copy, Eq, PartialEq)]
|
||||
pub enum VariableDeclarationParent {
|
||||
|
|
@ -23,7 +23,7 @@ impl VariableDeclarationContext {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
pub(crate) fn parse_let(&mut self, stmt_ctx: StatementContext) -> Result<Statement<'a>> {
|
||||
let span = self.start_span();
|
||||
let peeked = self.peek_kind();
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ use crate::{
|
|||
diagnostics,
|
||||
lexer::{parse_big_int, parse_float, parse_int, Kind},
|
||||
list::SeparatedList,
|
||||
Context, Parser,
|
||||
Context, ParserImpl,
|
||||
};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
pub(crate) fn parse_paren_expression(&mut self) -> Result<Expression<'a>> {
|
||||
self.expect(Kind::LParen)?;
|
||||
let expression = self.parse_expression()?;
|
||||
|
|
@ -977,7 +977,7 @@ impl<'a> Parser<'a> {
|
|||
let pos = self.cur_token().start;
|
||||
if !self.state.not_parenthesized_arrow.contains(&pos) {
|
||||
if let Ok((type_parameters, params, return_type, r#async, span)) =
|
||||
self.try_parse(Parser::parse_parenthesized_arrow_function_head)
|
||||
self.try_parse(ParserImpl::parse_parenthesized_arrow_function_head)
|
||||
{
|
||||
return self.parse_arrow_function_body(
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use oxc_diagnostics::Result;
|
|||
use oxc_span::{GetSpan, Span};
|
||||
|
||||
use super::list::FormalParameterList;
|
||||
use crate::{diagnostics, lexer::Kind, list::SeparatedList, Context, Parser, StatementContext};
|
||||
use crate::{diagnostics, lexer::Kind, list::SeparatedList, Context, ParserImpl, StatementContext};
|
||||
|
||||
type ArrowFunctionHead<'a> = (
|
||||
Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
|
||||
|
|
@ -41,7 +41,7 @@ impl FunctionKind {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
pub(crate) fn at_function_with_async(&mut self) -> bool {
|
||||
self.at(Kind::Function)
|
||||
|| self.at(Kind::Async)
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ use oxc_ast::ast::*;
|
|||
use oxc_diagnostics::Result;
|
||||
use oxc_span::GetSpan;
|
||||
|
||||
use crate::{diagnostics, Parser};
|
||||
use crate::{diagnostics, ParserImpl};
|
||||
|
||||
pub trait CoverGrammar<'a, T>: Sized {
|
||||
fn cover(value: T, p: &mut Parser<'a>) -> Result<Self>;
|
||||
fn cover(value: T, p: &mut ParserImpl<'a>) -> Result<Self>;
|
||||
}
|
||||
|
||||
impl<'a> CoverGrammar<'a, Expression<'a>> for AssignmentTarget<'a> {
|
||||
fn cover(expr: Expression<'a>, p: &mut Parser<'a>) -> Result<Self> {
|
||||
fn cover(expr: Expression<'a>, p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||
match expr {
|
||||
Expression::ArrayExpression(array_expr) => {
|
||||
ArrayAssignmentTarget::cover(array_expr.unbox(), p)
|
||||
|
|
@ -34,7 +34,7 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for AssignmentTarget<'a> {
|
|||
|
||||
impl<'a> CoverGrammar<'a, Expression<'a>> for SimpleAssignmentTarget<'a> {
|
||||
#[allow(clippy::only_used_in_recursion)]
|
||||
fn cover(expr: Expression<'a>, p: &mut Parser<'a>) -> Result<Self> {
|
||||
fn cover(expr: Expression<'a>, p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||
match expr {
|
||||
Expression::Identifier(ident) => {
|
||||
Ok(SimpleAssignmentTarget::AssignmentTargetIdentifier(ident))
|
||||
|
|
@ -65,7 +65,7 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for SimpleAssignmentTarget<'a> {
|
|||
}
|
||||
|
||||
impl<'a> CoverGrammar<'a, ArrayExpression<'a>> for ArrayAssignmentTarget<'a> {
|
||||
fn cover(expr: ArrayExpression<'a>, p: &mut Parser<'a>) -> Result<Self> {
|
||||
fn cover(expr: ArrayExpression<'a>, p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||
let mut elements = p.ast.new_vec();
|
||||
let mut rest = None;
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ impl<'a> CoverGrammar<'a, ArrayExpression<'a>> for ArrayAssignmentTarget<'a> {
|
|||
}
|
||||
|
||||
impl<'a> CoverGrammar<'a, Expression<'a>> for AssignmentTargetMaybeDefault<'a> {
|
||||
fn cover(expr: Expression<'a>, p: &mut Parser<'a>) -> Result<Self> {
|
||||
fn cover(expr: Expression<'a>, p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||
match expr {
|
||||
Expression::AssignmentExpression(assignment_expr) => {
|
||||
let target = AssignmentTargetWithDefault::cover(assignment_expr.unbox(), p)?;
|
||||
|
|
@ -115,13 +115,13 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for AssignmentTargetMaybeDefault<'a> {
|
|||
}
|
||||
|
||||
impl<'a> CoverGrammar<'a, AssignmentExpression<'a>> for AssignmentTargetWithDefault<'a> {
|
||||
fn cover(expr: AssignmentExpression<'a>, _p: &mut Parser<'a>) -> Result<Self> {
|
||||
fn cover(expr: AssignmentExpression<'a>, _p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||
Ok(Self { span: expr.span, binding: expr.left, init: expr.right })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CoverGrammar<'a, ObjectExpression<'a>> for ObjectAssignmentTarget<'a> {
|
||||
fn cover(expr: ObjectExpression<'a>, p: &mut Parser<'a>) -> Result<Self> {
|
||||
fn cover(expr: ObjectExpression<'a>, p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||
let mut properties = p.ast.new_vec();
|
||||
let mut rest = None;
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ impl<'a> CoverGrammar<'a, ObjectExpression<'a>> for ObjectAssignmentTarget<'a> {
|
|||
}
|
||||
|
||||
impl<'a> CoverGrammar<'a, ObjectProperty<'a>> for AssignmentTargetProperty<'a> {
|
||||
fn cover(property: ObjectProperty<'a>, p: &mut Parser<'a>) -> Result<Self> {
|
||||
fn cover(property: ObjectProperty<'a>, p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||
if property.shorthand {
|
||||
let binding = match property.key {
|
||||
PropertyKey::Identifier(ident) => {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
diagnostics,
|
||||
lexer::Kind,
|
||||
list::{NormalList, SeparatedList},
|
||||
Parser,
|
||||
ParserImpl,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
|
|
@ -31,7 +31,7 @@ pub struct ObjectExpressionProperties<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for ObjectExpressionProperties<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec(), trailing_comma: None }
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ impl<'a> SeparatedList<'a> for ObjectExpressionProperties<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let element = match p.cur_kind() {
|
||||
Kind::Dot3 => p.parse_spread_element().map(ObjectPropertyKind::SpreadProperty),
|
||||
_ => p.parse_property_definition().map(ObjectPropertyKind::ObjectProperty),
|
||||
|
|
@ -65,7 +65,7 @@ pub struct ObjectPatternProperties<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for ObjectPatternProperties<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec(), rest: None }
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ impl<'a> SeparatedList<'a> for ObjectPatternProperties<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
if p.cur_kind() == Kind::Dot3 {
|
||||
let rest = p.parse_rest_element()?;
|
||||
if !matches!(&rest.argument.kind, BindingPatternKind::BindingIdentifier(_)) {
|
||||
|
|
@ -101,7 +101,7 @@ pub struct ArrayExpressionList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for ArrayExpressionList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec(), trailing_comma: None }
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ impl<'a> SeparatedList<'a> for ArrayExpressionList<'a> {
|
|||
Kind::RBrack
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let element = match p.cur_kind() {
|
||||
Kind::Comma => Ok(p.parse_elision()),
|
||||
Kind::Dot3 => p.parse_spread_element().map(ArrayExpressionElement::SpreadElement),
|
||||
|
|
@ -136,7 +136,7 @@ pub struct ArrayPatternList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for ArrayPatternList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec(), rest: None }
|
||||
}
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ impl<'a> SeparatedList<'a> for ArrayPatternList<'a> {
|
|||
Kind::RBrack
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
match p.cur_kind() {
|
||||
Kind::Comma => {
|
||||
self.elements.push(None);
|
||||
|
|
@ -175,7 +175,7 @@ pub struct CallArguments<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for CallArguments<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec(), rest_element_with_trilling_comma: None }
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ impl<'a> SeparatedList<'a> for CallArguments<'a> {
|
|||
Kind::RParen
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let element = if p.at(Kind::Dot3) {
|
||||
let result = p.parse_spread_element().map(Argument::SpreadElement);
|
||||
if p.at(Kind::Comma) {
|
||||
|
|
@ -209,7 +209,7 @@ pub struct SequenceExpressionList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for SequenceExpressionList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec() }
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ impl<'a> SeparatedList<'a> for SequenceExpressionList<'a> {
|
|||
|
||||
// read everything as expression and map to it to either
|
||||
// ParenthesizedExpression or ArrowFormalParameters later
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let element = p.parse_assignment_expression_base()?;
|
||||
self.elements.push(element);
|
||||
Ok(())
|
||||
|
|
@ -238,7 +238,7 @@ pub struct FormalParameterList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for FormalParameterList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec(), rest: None, this_param: None }
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +251,7 @@ impl<'a> SeparatedList<'a> for FormalParameterList<'a> {
|
|||
}
|
||||
|
||||
// Section 15.1 Parameter Lists
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let span = p.start_span();
|
||||
p.eat_decorators()?;
|
||||
|
||||
|
|
@ -295,7 +295,7 @@ pub struct AssertEntries<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for AssertEntries<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec(), keys: FxHashMap::default() }
|
||||
}
|
||||
|
||||
|
|
@ -307,7 +307,7 @@ impl<'a> SeparatedList<'a> for AssertEntries<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let span = p.start_span();
|
||||
let key = match p.cur_kind() {
|
||||
Kind::Str => ImportAttributeKey::StringLiteral(p.parse_literal_string()?),
|
||||
|
|
@ -333,7 +333,7 @@ pub struct ExportNamedSpecifiers<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for ExportNamedSpecifiers<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec() }
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +345,7 @@ impl<'a> SeparatedList<'a> for ExportNamedSpecifiers<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let specifier_span = p.start_span();
|
||||
let peek_kind = p.peek_kind();
|
||||
|
||||
|
|
@ -396,13 +396,13 @@ pub struct ClassElements<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ClassElements<'a> {
|
||||
pub(crate) fn new(p: &Parser<'a>) -> Self {
|
||||
pub(crate) fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec(), private_bound_identifiers: FxHashMap::default() }
|
||||
}
|
||||
|
||||
fn detect_private_name_conflict(
|
||||
&self,
|
||||
p: &mut Parser,
|
||||
p: &mut ParserImpl,
|
||||
private_ident: &PrivateIdentifier,
|
||||
r#static: bool,
|
||||
kind: Option<MethodDefinitionKind>,
|
||||
|
|
@ -430,7 +430,7 @@ impl<'a> ClassElements<'a> {
|
|||
|
||||
fn on_declare_private_property(
|
||||
&mut self,
|
||||
p: &mut Parser,
|
||||
p: &mut ParserImpl,
|
||||
private_ident: &PrivateIdentifier,
|
||||
r#static: bool,
|
||||
kind: Option<MethodDefinitionKind>,
|
||||
|
|
@ -453,7 +453,7 @@ impl<'a> NormalList<'a> for ClassElements<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
// skip empty class element `;`
|
||||
while p.at(Kind::Semicolon) {
|
||||
p.bump_any();
|
||||
|
|
@ -482,7 +482,7 @@ pub struct SwitchCases<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SwitchCases<'a> {
|
||||
pub(crate) fn new(p: &Parser<'a>) -> Self {
|
||||
pub(crate) fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec() }
|
||||
}
|
||||
}
|
||||
|
|
@ -496,7 +496,7 @@ impl<'a> NormalList<'a> for SwitchCases<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let element = p.parse_switch_case()?;
|
||||
self.elements.push(element);
|
||||
Ok(())
|
||||
|
|
@ -508,7 +508,7 @@ pub struct ImportSpecifierList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for ImportSpecifierList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { import_specifiers: p.ast.new_vec() }
|
||||
}
|
||||
|
||||
|
|
@ -520,7 +520,7 @@ impl<'a> SeparatedList<'a> for ImportSpecifierList<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let import_specifier = p.parse_import_specifier()?;
|
||||
let specifier = ImportDeclarationSpecifier::ImportSpecifier(import_specifier);
|
||||
self.import_specifiers.push(specifier);
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ use super::{
|
|||
function::FunctionKind,
|
||||
list::{AssertEntries, ExportNamedSpecifiers, ImportSpecifierList},
|
||||
};
|
||||
use crate::{diagnostics, lexer::Kind, list::SeparatedList, Context, Parser};
|
||||
use crate::{diagnostics, lexer::Kind, list::SeparatedList, Context, ParserImpl};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
/// [Import Call](https://tc39.es/ecma262/#sec-import-calls)
|
||||
/// `ImportCall` : import ( `AssignmentExpression` )
|
||||
pub(crate) fn parse_import_expression(&mut self, span: Span) -> Result<Expression<'a>> {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ use oxc_span::Span;
|
|||
use oxc_syntax::operator::AssignmentOperator;
|
||||
|
||||
use super::list::ObjectExpressionProperties;
|
||||
use crate::{lexer::Kind, list::SeparatedList, Parser};
|
||||
use crate::{lexer::Kind, list::SeparatedList, ParserImpl};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
/// [Object Expression](https://tc39.es/ecma262/#sec-object-initializer)
|
||||
/// `ObjectLiteral`[Yield, Await] :
|
||||
/// { }
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ use super::{
|
|||
grammar::CoverGrammar,
|
||||
list::SwitchCases,
|
||||
};
|
||||
use crate::{diagnostics, lexer::Kind, list::NormalList, Context, Parser, StatementContext};
|
||||
use crate::{diagnostics, lexer::Kind, list::NormalList, Context, ParserImpl, StatementContext};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
// Section 12
|
||||
// The InputElementHashbangOrRegExp goal is used at the start of a Script
|
||||
// or Module.
|
||||
|
|
@ -283,7 +283,7 @@ impl<'a> Parser<'a> {
|
|||
return self.parse_for_loop(span, None, r#await);
|
||||
}
|
||||
|
||||
let init_expression = self.without_context(Context::In, Parser::parse_expression)?;
|
||||
let init_expression = self.without_context(Context::In, ParserImpl::parse_expression)?;
|
||||
|
||||
// for (a.b in ...), for ([a] in ..), for ({a} in ..)
|
||||
if self.at(Kind::In) || self.at(Kind::Of) {
|
||||
|
|
@ -359,7 +359,7 @@ impl<'a> Parser<'a> {
|
|||
) -> Result<Statement<'a>> {
|
||||
self.expect(Kind::Semicolon)?;
|
||||
let test = if !self.at(Kind::Semicolon) && !self.at(Kind::RParen) {
|
||||
Some(self.with_context(Context::In, Parser::parse_expression)?)
|
||||
Some(self.with_context(Context::In, ParserImpl::parse_expression)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -367,7 +367,7 @@ impl<'a> Parser<'a> {
|
|||
let update = if self.at(Kind::RParen) {
|
||||
None
|
||||
} else {
|
||||
Some(self.with_context(Context::In, Parser::parse_expression)?)
|
||||
Some(self.with_context(Context::In, ParserImpl::parse_expression)?)
|
||||
};
|
||||
self.expect(Kind::RParen)?;
|
||||
if r#await {
|
||||
|
|
@ -433,7 +433,7 @@ impl<'a> Parser<'a> {
|
|||
let argument = if self.eat(Kind::Semicolon) || self.can_insert_semicolon() {
|
||||
None
|
||||
} else {
|
||||
let expr = self.with_context(Context::In, Parser::parse_expression)?;
|
||||
let expr = self.with_context(Context::In, ParserImpl::parse_expression)?;
|
||||
self.asi()?;
|
||||
Some(expr)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ use oxc_ast::ast::*;
|
|||
use oxc_diagnostics::Result;
|
||||
use oxc_span::{Atom, Span};
|
||||
|
||||
use crate::{diagnostics, lexer::Kind, Context, Parser};
|
||||
use crate::{diagnostics, lexer::Kind, Context, ParserImpl};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
pub(crate) fn parse_jsx_expression(&mut self) -> Result<Expression<'a>> {
|
||||
if self.peek_at(Kind::RAngle) {
|
||||
self.parse_jsx_fragment(false).map(Expression::JSXFragment)
|
||||
|
|
|
|||
|
|
@ -116,10 +116,70 @@ pub struct ParserReturn<'a> {
|
|||
pub panicked: bool,
|
||||
}
|
||||
|
||||
/// Parser options
|
||||
#[derive(Clone, Copy)]
|
||||
struct ParserOptions {
|
||||
pub allow_return_outside_function: bool,
|
||||
pub preserve_parens: bool,
|
||||
}
|
||||
|
||||
impl Default for ParserOptions {
|
||||
fn default() -> Self {
|
||||
Self { allow_return_outside_function: false, preserve_parens: true }
|
||||
}
|
||||
}
|
||||
|
||||
/// Recursive Descent Parser for ECMAScript and TypeScript
|
||||
///
|
||||
/// See [`Parser::parse`] for entry function.
|
||||
pub struct Parser<'a> {
|
||||
allocator: &'a Allocator,
|
||||
source_text: &'a str,
|
||||
source_type: SourceType,
|
||||
options: ParserOptions,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
/// Create a new parser
|
||||
pub fn new(allocator: &'a Allocator, source_text: &'a str, source_type: SourceType) -> Self {
|
||||
let options = ParserOptions::default();
|
||||
Self { allocator, source_text, source_type, options }
|
||||
}
|
||||
|
||||
/// Allow return outside of function
|
||||
///
|
||||
/// By default, a return statement at the top level raises an error.
|
||||
/// Set this to true to accept such code.
|
||||
#[must_use]
|
||||
pub fn allow_return_outside_function(mut self, allow: bool) -> Self {
|
||||
self.options.allow_return_outside_function = allow;
|
||||
self
|
||||
}
|
||||
|
||||
/// Emit `ParenthesizedExpression` in AST.
|
||||
///
|
||||
/// If this option is true, parenthesized expressions are represented by (non-standard)
|
||||
/// `ParenthesizedExpression` nodes that have a single expression property containing the expression inside parentheses.
|
||||
#[must_use]
|
||||
pub fn preserve_parens(mut self, allow: bool) -> Self {
|
||||
self.options.preserve_parens = allow;
|
||||
self
|
||||
}
|
||||
|
||||
/// Main entry point
|
||||
///
|
||||
/// Returns an empty `Program` on unrecoverable error,
|
||||
/// Recoverable errors are stored inside `errors`.
|
||||
pub fn parse(self) -> ParserReturn<'a> {
|
||||
let parser =
|
||||
ParserImpl::new(self.allocator, self.source_text, self.source_type, self.options);
|
||||
parser.parse()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of parser.
|
||||
/// `Parser` is just a public wrapper, the guts of the implementation is in this type.
|
||||
struct ParserImpl<'a> {
|
||||
lexer: Lexer<'a>,
|
||||
|
||||
/// SourceType: JavaScript or TypeScript, Script or Module, jsx support?
|
||||
|
|
@ -152,9 +212,14 @@ pub struct Parser<'a> {
|
|||
preserve_parens: bool,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
/// Create a new parser
|
||||
pub fn new(allocator: &'a Allocator, source_text: &'a str, source_type: SourceType) -> Self {
|
||||
pub fn new(
|
||||
allocator: &'a Allocator,
|
||||
source_text: &'a str,
|
||||
source_type: SourceType,
|
||||
options: ParserOptions,
|
||||
) -> Self {
|
||||
Self {
|
||||
lexer: Lexer::new(allocator, source_text, source_type),
|
||||
source_type,
|
||||
|
|
@ -163,32 +228,12 @@ impl<'a> Parser<'a> {
|
|||
token: Token::default(),
|
||||
prev_token_end: 0,
|
||||
state: ParserState::new(allocator),
|
||||
ctx: Self::default_context(source_type),
|
||||
ctx: Self::default_context(source_type, options),
|
||||
ast: AstBuilder::new(allocator),
|
||||
preserve_parens: true,
|
||||
preserve_parens: options.preserve_parens,
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow return outside of function
|
||||
///
|
||||
/// By default, a return statement at the top level raises an error.
|
||||
/// Set this to true to accept such code.
|
||||
#[must_use]
|
||||
pub fn allow_return_outside_function(mut self, allow: bool) -> Self {
|
||||
self.ctx = self.ctx.and_return(allow);
|
||||
self
|
||||
}
|
||||
|
||||
/// Emit `ParenthesizedExpression` in AST.
|
||||
///
|
||||
/// If this option is true, parenthesized expressions are represented by (non-standard)
|
||||
/// `ParenthesizedExpression` nodes that have a single expression property containing the expression inside parentheses.
|
||||
#[must_use]
|
||||
pub fn preserve_parens(mut self, allow: bool) -> Self {
|
||||
self.preserve_parens = allow;
|
||||
self
|
||||
}
|
||||
|
||||
/// Main entry point
|
||||
///
|
||||
/// Returns an empty `Program` on unrecoverable error,
|
||||
|
|
@ -228,13 +273,16 @@ impl<'a> Parser<'a> {
|
|||
Ok(self.ast.program(span, self.source_type, directives, hashbang, statements))
|
||||
}
|
||||
|
||||
fn default_context(source_type: SourceType) -> Context {
|
||||
let ctx = Context::default().and_ambient(source_type.is_typescript_definition());
|
||||
match source_type.module_kind() {
|
||||
ModuleKind::Script => ctx,
|
||||
fn default_context(source_type: SourceType, options: ParserOptions) -> Context {
|
||||
let mut ctx = Context::default().and_ambient(source_type.is_typescript_definition());
|
||||
if source_type.module_kind() == ModuleKind::Module {
|
||||
// for [top-level-await](https://tc39.es/proposal-top-level-await/)
|
||||
ModuleKind::Module => ctx.and_await(true),
|
||||
ctx = ctx.and_await(true);
|
||||
}
|
||||
if options.allow_return_outside_function {
|
||||
ctx = ctx.and_return(true);
|
||||
}
|
||||
ctx
|
||||
}
|
||||
|
||||
/// Check for Flow declaration if the file cannot be parsed.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use oxc_diagnostics::Result;
|
||||
|
||||
use crate::{lexer::Kind, Parser};
|
||||
use crate::{lexer::Kind, ParserImpl};
|
||||
|
||||
pub trait NormalList<'a> {
|
||||
/// Open element, e.g.. `{` `[` `(`
|
||||
|
|
@ -9,10 +9,10 @@ pub trait NormalList<'a> {
|
|||
/// Close element, e.g.. `}` `]` `)`
|
||||
fn close(&self) -> Kind;
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()>;
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()>;
|
||||
|
||||
/// Main entry point, parse the list
|
||||
fn parse(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
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)?;
|
||||
|
|
@ -23,9 +23,9 @@ pub trait NormalList<'a> {
|
|||
}
|
||||
|
||||
pub trait SeparatedList<'a>: Sized {
|
||||
fn new(p: &Parser<'a>) -> Self;
|
||||
fn new(p: &ParserImpl<'a>) -> Self;
|
||||
|
||||
fn parse(p: &mut Parser<'a>) -> Result<Self> {
|
||||
fn parse(p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||
let mut list = Self::new(p);
|
||||
list.parse_list(p)?;
|
||||
Ok(list)
|
||||
|
|
@ -42,10 +42,10 @@ pub trait SeparatedList<'a>: Sized {
|
|||
Kind::Comma
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()>;
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()>;
|
||||
|
||||
/// Main entry point, parse the list
|
||||
fn parse_list(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_list(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
p.expect(self.open())?;
|
||||
|
||||
let mut first = true;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{lexer::Kind, Parser};
|
||||
use crate::{lexer::Kind, ParserImpl};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
/// Check if the parser is at a start of a declaration
|
||||
fn at_start_of_ts_declaration_worker(&mut self) -> bool {
|
||||
loop {
|
||||
|
|
@ -80,11 +80,12 @@ mod test_is_declaration {
|
|||
use oxc_span::SourceType;
|
||||
|
||||
use super::*;
|
||||
use crate::ParserOptions;
|
||||
|
||||
fn run_check(source: &str, expected: bool) {
|
||||
let alloc = Allocator::default();
|
||||
let source_type = SourceType::default().with_typescript(true);
|
||||
let mut parser = Parser::new(&alloc, source, source_type);
|
||||
let mut parser = ParserImpl::new(&alloc, source, source_type, ParserOptions::default());
|
||||
// Get the parser to the first token.
|
||||
parser.bump_any();
|
||||
assert_eq!(expected, parser.at_start_of_ts_declaration());
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use oxc_diagnostics::Result;
|
|||
use crate::{
|
||||
lexer::Kind,
|
||||
list::{NormalList, SeparatedList},
|
||||
Parser,
|
||||
ParserImpl,
|
||||
};
|
||||
|
||||
pub struct TSEnumMemberList<'a> {
|
||||
|
|
@ -13,7 +13,7 @@ pub struct TSEnumMemberList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for TSEnumMemberList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { members: p.ast.new_vec() }
|
||||
}
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ impl<'a> SeparatedList<'a> for TSEnumMemberList<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let element = p.parse_ts_enum_member()?;
|
||||
self.members.push(element);
|
||||
Ok(())
|
||||
|
|
@ -37,7 +37,7 @@ pub struct TSTupleElementList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for TSTupleElementList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { elements: p.ast.new_vec() }
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ impl<'a> SeparatedList<'a> for TSTupleElementList<'a> {
|
|||
Kind::RBrack
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let span = p.start_span();
|
||||
if p.is_at_named_tuple_element() {
|
||||
let _is_rest = p.eat(Kind::Dot3);
|
||||
|
|
@ -91,7 +91,7 @@ pub struct TSTypeParameterList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for TSTypeParameterList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { params: p.ast.new_vec() }
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ impl<'a> SeparatedList<'a> for TSTypeParameterList<'a> {
|
|||
Kind::RAngle
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let param = p.parse_ts_type_parameter()?;
|
||||
self.params.push(param);
|
||||
Ok(())
|
||||
|
|
@ -115,7 +115,7 @@ pub struct TSInterfaceOrObjectBodyList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> TSInterfaceOrObjectBodyList<'a> {
|
||||
pub(crate) fn new(p: &Parser<'a>) -> Self {
|
||||
pub(crate) fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { body: p.ast.new_vec() }
|
||||
}
|
||||
}
|
||||
|
|
@ -129,7 +129,7 @@ impl<'a> NormalList<'a> for TSInterfaceOrObjectBodyList<'a> {
|
|||
Kind::RCurly
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let property = p.parse_ts_type_signature()?;
|
||||
self.body.push(property);
|
||||
Ok(())
|
||||
|
|
@ -141,7 +141,7 @@ pub struct TSTypeArgumentList<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SeparatedList<'a> for TSTypeArgumentList<'a> {
|
||||
fn new(p: &Parser<'a>) -> Self {
|
||||
fn new(p: &ParserImpl<'a>) -> Self {
|
||||
Self { params: p.ast.new_vec() }
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ impl<'a> SeparatedList<'a> for TSTypeArgumentList<'a> {
|
|||
Kind::RAngle
|
||||
}
|
||||
|
||||
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
|
||||
fn parse_element(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
|
||||
let ty = p.parse_ts_type()?;
|
||||
self.params.push(ty);
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ use crate::{
|
|||
},
|
||||
lexer::Kind,
|
||||
list::{NormalList, SeparatedList},
|
||||
Parser, StatementContext,
|
||||
ParserImpl, StatementContext,
|
||||
};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
/** ------------------- Enum ------------------ */
|
||||
|
||||
pub(crate) fn is_at_enum_declaration(&mut self) -> bool {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
js::list::{ArrayPatternList, ObjectPatternProperties},
|
||||
lexer::Kind,
|
||||
list::{NormalList, SeparatedList},
|
||||
Context, Parser,
|
||||
Context, ParserImpl,
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
|
|
@ -105,7 +105,7 @@ impl ModifierFlags {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
impl<'a> ParserImpl<'a> {
|
||||
pub(crate) fn parse_ts_type(&mut self) -> Result<TSType<'a>> {
|
||||
if self.is_at_constructor_type() {
|
||||
return self.parse_ts_constructor_type();
|
||||
|
|
@ -323,8 +323,8 @@ impl<'a> Parser<'a> {
|
|||
));
|
||||
}
|
||||
|
||||
let mut left =
|
||||
self.without_context(Context::DisallowConditionalTypes, Parser::parse_ts_basic_type)?;
|
||||
let mut left = self
|
||||
.without_context(Context::DisallowConditionalTypes, ParserImpl::parse_ts_basic_type)?;
|
||||
|
||||
while !self.cur_token().is_on_new_line && self.eat(Kind::LBrack) {
|
||||
if self.eat(Kind::RBrack) {
|
||||
|
|
@ -828,7 +828,7 @@ impl<'a> Parser<'a> {
|
|||
let parameter_span = self.start_span();
|
||||
let name = self.parse_binding_identifier()?;
|
||||
|
||||
let constraint = self.try_parse(Parser::parse_constraint_of_infer_type).unwrap_or(None);
|
||||
let constraint = self.try_parse(ParserImpl::parse_constraint_of_infer_type).unwrap_or(None);
|
||||
|
||||
let type_parameter = self.ast.ts_type_parameter(
|
||||
self.end_span(parameter_span),
|
||||
|
|
|
|||
Loading…
Reference in a new issue