mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42: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::{
|
use crate::{
|
||||||
diagnostics,
|
diagnostics,
|
||||||
lexer::{Kind, LexerCheckpoint, LexerContext, Token},
|
lexer::{Kind, LexerCheckpoint, LexerContext, Token},
|
||||||
Context, Parser,
|
Context, ParserImpl,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
|
@ -18,7 +18,7 @@ pub struct ParserCheckpoint<'a> {
|
||||||
errors_pos: usize,
|
errors_pos: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> ParserImpl<'a> {
|
||||||
pub(crate) fn start_span(&self) -> Span {
|
pub(crate) fn start_span(&self) -> Span {
|
||||||
let token = self.cur_token();
|
let token = self.cur_token();
|
||||||
Span::new(token.start, 0)
|
Span::new(token.start, 0)
|
||||||
|
|
@ -266,7 +266,7 @@ impl<'a> Parser<'a> {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
pub(crate) fn try_parse<T>(
|
pub(crate) fn try_parse<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: impl FnOnce(&mut Parser<'a>) -> Result<T>,
|
func: impl FnOnce(&mut ParserImpl<'a>) -> Result<T>,
|
||||||
) -> Result<T> {
|
) -> Result<T> {
|
||||||
let checkpoint = self.checkpoint();
|
let checkpoint = self.checkpoint();
|
||||||
let ctx = self.ctx;
|
let ctx = self.ctx;
|
||||||
|
|
@ -278,7 +278,7 @@ impl<'a> Parser<'a> {
|
||||||
result
|
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 checkpoint = self.checkpoint();
|
||||||
let answer = predicate(self);
|
let answer = predicate(self);
|
||||||
self.rewind(checkpoint);
|
self.rewind(checkpoint);
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ use oxc_diagnostics::Result;
|
||||||
use oxc_span::Span;
|
use oxc_span::Span;
|
||||||
|
|
||||||
use super::list::{ArrayPatternList, ObjectPatternProperties};
|
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
|
/// Destructuring Binding Patterns
|
||||||
/// `LexicalBinding`
|
/// `LexicalBinding`
|
||||||
/// `BindingIdentifier` `Initializer_opt`
|
/// `BindingIdentifier` `Initializer_opt`
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use oxc_diagnostics::Result;
|
||||||
use oxc_span::{GetSpan, Span};
|
use oxc_span::{GetSpan, Span};
|
||||||
|
|
||||||
use super::list::ClassElements;
|
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> =
|
type Extends<'a> =
|
||||||
Vec<'a, (Expression<'a>, Option<Box<'a, TSTypeParameterInstantiation<'a>>>, Span)>;
|
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>>>;
|
type Implements<'a> = Vec<'a, Box<'a, TSClassImplements<'a>>>;
|
||||||
|
|
||||||
/// Section 15.7 Class Definitions
|
/// 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.
|
// `start_span` points at the start of all decoractors and `class` keyword.
|
||||||
pub(crate) fn parse_class_statement(
|
pub(crate) fn parse_class_statement(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use oxc_ast::ast::*;
|
||||||
use oxc_diagnostics::Result;
|
use oxc_diagnostics::Result;
|
||||||
use oxc_span::{GetSpan, Span};
|
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)]
|
#[derive(Clone, Debug, Copy, Eq, PartialEq)]
|
||||||
pub enum VariableDeclarationParent {
|
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>> {
|
pub(crate) fn parse_let(&mut self, stmt_ctx: StatementContext) -> Result<Statement<'a>> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
let peeked = self.peek_kind();
|
let peeked = self.peek_kind();
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,10 @@ use crate::{
|
||||||
diagnostics,
|
diagnostics,
|
||||||
lexer::{parse_big_int, parse_float, parse_int, Kind},
|
lexer::{parse_big_int, parse_float, parse_int, Kind},
|
||||||
list::SeparatedList,
|
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>> {
|
pub(crate) fn parse_paren_expression(&mut self) -> Result<Expression<'a>> {
|
||||||
self.expect(Kind::LParen)?;
|
self.expect(Kind::LParen)?;
|
||||||
let expression = self.parse_expression()?;
|
let expression = self.parse_expression()?;
|
||||||
|
|
@ -977,7 +977,7 @@ impl<'a> Parser<'a> {
|
||||||
let pos = self.cur_token().start;
|
let pos = self.cur_token().start;
|
||||||
if !self.state.not_parenthesized_arrow.contains(&pos) {
|
if !self.state.not_parenthesized_arrow.contains(&pos) {
|
||||||
if let Ok((type_parameters, params, return_type, r#async, span)) =
|
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(
|
return self.parse_arrow_function_body(
|
||||||
span,
|
span,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use oxc_diagnostics::Result;
|
||||||
use oxc_span::{GetSpan, Span};
|
use oxc_span::{GetSpan, Span};
|
||||||
|
|
||||||
use super::list::FormalParameterList;
|
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> = (
|
type ArrowFunctionHead<'a> = (
|
||||||
Option<Box<'a, TSTypeParameterDeclaration<'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 {
|
pub(crate) fn at_function_with_async(&mut self) -> bool {
|
||||||
self.at(Kind::Function)
|
self.at(Kind::Function)
|
||||||
|| self.at(Kind::Async)
|
|| self.at(Kind::Async)
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,14 @@ use oxc_ast::ast::*;
|
||||||
use oxc_diagnostics::Result;
|
use oxc_diagnostics::Result;
|
||||||
use oxc_span::GetSpan;
|
use oxc_span::GetSpan;
|
||||||
|
|
||||||
use crate::{diagnostics, Parser};
|
use crate::{diagnostics, ParserImpl};
|
||||||
|
|
||||||
pub trait CoverGrammar<'a, T>: Sized {
|
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> {
|
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 {
|
match expr {
|
||||||
Expression::ArrayExpression(array_expr) => {
|
Expression::ArrayExpression(array_expr) => {
|
||||||
ArrayAssignmentTarget::cover(array_expr.unbox(), p)
|
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> {
|
impl<'a> CoverGrammar<'a, Expression<'a>> for SimpleAssignmentTarget<'a> {
|
||||||
#[allow(clippy::only_used_in_recursion)]
|
#[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 {
|
match expr {
|
||||||
Expression::Identifier(ident) => {
|
Expression::Identifier(ident) => {
|
||||||
Ok(SimpleAssignmentTarget::AssignmentTargetIdentifier(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> {
|
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 elements = p.ast.new_vec();
|
||||||
let mut rest = None;
|
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> {
|
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 {
|
match expr {
|
||||||
Expression::AssignmentExpression(assignment_expr) => {
|
Expression::AssignmentExpression(assignment_expr) => {
|
||||||
let target = AssignmentTargetWithDefault::cover(assignment_expr.unbox(), p)?;
|
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> {
|
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 })
|
Ok(Self { span: expr.span, binding: expr.left, init: expr.right })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CoverGrammar<'a, ObjectExpression<'a>> for ObjectAssignmentTarget<'a> {
|
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 properties = p.ast.new_vec();
|
||||||
let mut rest = None;
|
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> {
|
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 {
|
if property.shorthand {
|
||||||
let binding = match property.key {
|
let binding = match property.key {
|
||||||
PropertyKey::Identifier(ident) => {
|
PropertyKey::Identifier(ident) => {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
diagnostics,
|
diagnostics,
|
||||||
lexer::Kind,
|
lexer::Kind,
|
||||||
list::{NormalList, SeparatedList},
|
list::{NormalList, SeparatedList},
|
||||||
Parser,
|
ParserImpl,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Error, Diagnostic)]
|
#[derive(Debug, Error, Diagnostic)]
|
||||||
|
|
@ -31,7 +31,7 @@ pub struct ObjectExpressionProperties<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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 }
|
Self { elements: p.ast.new_vec(), trailing_comma: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ impl<'a> SeparatedList<'a> for ObjectExpressionProperties<'a> {
|
||||||
Kind::RCurly
|
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() {
|
let element = match p.cur_kind() {
|
||||||
Kind::Dot3 => p.parse_spread_element().map(ObjectPropertyKind::SpreadProperty),
|
Kind::Dot3 => p.parse_spread_element().map(ObjectPropertyKind::SpreadProperty),
|
||||||
_ => p.parse_property_definition().map(ObjectPropertyKind::ObjectProperty),
|
_ => p.parse_property_definition().map(ObjectPropertyKind::ObjectProperty),
|
||||||
|
|
@ -65,7 +65,7 @@ pub struct ObjectPatternProperties<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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 }
|
Self { elements: p.ast.new_vec(), rest: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ impl<'a> SeparatedList<'a> for ObjectPatternProperties<'a> {
|
||||||
Kind::RCurly
|
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 {
|
if p.cur_kind() == Kind::Dot3 {
|
||||||
let rest = p.parse_rest_element()?;
|
let rest = p.parse_rest_element()?;
|
||||||
if !matches!(&rest.argument.kind, BindingPatternKind::BindingIdentifier(_)) {
|
if !matches!(&rest.argument.kind, BindingPatternKind::BindingIdentifier(_)) {
|
||||||
|
|
@ -101,7 +101,7 @@ pub struct ArrayExpressionList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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 }
|
Self { elements: p.ast.new_vec(), trailing_comma: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,7 +113,7 @@ impl<'a> SeparatedList<'a> for ArrayExpressionList<'a> {
|
||||||
Kind::RBrack
|
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() {
|
let element = match p.cur_kind() {
|
||||||
Kind::Comma => Ok(p.parse_elision()),
|
Kind::Comma => Ok(p.parse_elision()),
|
||||||
Kind::Dot3 => p.parse_spread_element().map(ArrayExpressionElement::SpreadElement),
|
Kind::Dot3 => p.parse_spread_element().map(ArrayExpressionElement::SpreadElement),
|
||||||
|
|
@ -136,7 +136,7 @@ pub struct ArrayPatternList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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 }
|
Self { elements: p.ast.new_vec(), rest: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,7 +148,7 @@ impl<'a> SeparatedList<'a> for ArrayPatternList<'a> {
|
||||||
Kind::RBrack
|
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() {
|
match p.cur_kind() {
|
||||||
Kind::Comma => {
|
Kind::Comma => {
|
||||||
self.elements.push(None);
|
self.elements.push(None);
|
||||||
|
|
@ -175,7 +175,7 @@ pub struct CallArguments<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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 }
|
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
|
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 element = if p.at(Kind::Dot3) {
|
||||||
let result = p.parse_spread_element().map(Argument::SpreadElement);
|
let result = p.parse_spread_element().map(Argument::SpreadElement);
|
||||||
if p.at(Kind::Comma) {
|
if p.at(Kind::Comma) {
|
||||||
|
|
@ -209,7 +209,7 @@ pub struct SequenceExpressionList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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() }
|
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
|
// read everything as expression and map to it to either
|
||||||
// ParenthesizedExpression or ArrowFormalParameters later
|
// 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()?;
|
let element = p.parse_assignment_expression_base()?;
|
||||||
self.elements.push(element);
|
self.elements.push(element);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -238,7 +238,7 @@ pub struct FormalParameterList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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 }
|
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
|
// 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();
|
let span = p.start_span();
|
||||||
p.eat_decorators()?;
|
p.eat_decorators()?;
|
||||||
|
|
||||||
|
|
@ -295,7 +295,7 @@ pub struct AssertEntries<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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() }
|
Self { elements: p.ast.new_vec(), keys: FxHashMap::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,7 +307,7 @@ impl<'a> SeparatedList<'a> for AssertEntries<'a> {
|
||||||
Kind::RCurly
|
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 span = p.start_span();
|
||||||
let key = match p.cur_kind() {
|
let key = match p.cur_kind() {
|
||||||
Kind::Str => ImportAttributeKey::StringLiteral(p.parse_literal_string()?),
|
Kind::Str => ImportAttributeKey::StringLiteral(p.parse_literal_string()?),
|
||||||
|
|
@ -333,7 +333,7 @@ pub struct ExportNamedSpecifiers<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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() }
|
Self { elements: p.ast.new_vec() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,7 +345,7 @@ impl<'a> SeparatedList<'a> for ExportNamedSpecifiers<'a> {
|
||||||
Kind::RCurly
|
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 specifier_span = p.start_span();
|
||||||
let peek_kind = p.peek_kind();
|
let peek_kind = p.peek_kind();
|
||||||
|
|
||||||
|
|
@ -396,13 +396,13 @@ pub struct ClassElements<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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() }
|
Self { elements: p.ast.new_vec(), private_bound_identifiers: FxHashMap::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detect_private_name_conflict(
|
fn detect_private_name_conflict(
|
||||||
&self,
|
&self,
|
||||||
p: &mut Parser,
|
p: &mut ParserImpl,
|
||||||
private_ident: &PrivateIdentifier,
|
private_ident: &PrivateIdentifier,
|
||||||
r#static: bool,
|
r#static: bool,
|
||||||
kind: Option<MethodDefinitionKind>,
|
kind: Option<MethodDefinitionKind>,
|
||||||
|
|
@ -430,7 +430,7 @@ impl<'a> ClassElements<'a> {
|
||||||
|
|
||||||
fn on_declare_private_property(
|
fn on_declare_private_property(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &mut Parser,
|
p: &mut ParserImpl,
|
||||||
private_ident: &PrivateIdentifier,
|
private_ident: &PrivateIdentifier,
|
||||||
r#static: bool,
|
r#static: bool,
|
||||||
kind: Option<MethodDefinitionKind>,
|
kind: Option<MethodDefinitionKind>,
|
||||||
|
|
@ -453,7 +453,7 @@ impl<'a> NormalList<'a> for ClassElements<'a> {
|
||||||
Kind::RCurly
|
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 `;`
|
// skip empty class element `;`
|
||||||
while p.at(Kind::Semicolon) {
|
while p.at(Kind::Semicolon) {
|
||||||
p.bump_any();
|
p.bump_any();
|
||||||
|
|
@ -482,7 +482,7 @@ pub struct SwitchCases<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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() }
|
Self { elements: p.ast.new_vec() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -496,7 +496,7 @@ impl<'a> NormalList<'a> for SwitchCases<'a> {
|
||||||
Kind::RCurly
|
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()?;
|
let element = p.parse_switch_case()?;
|
||||||
self.elements.push(element);
|
self.elements.push(element);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -508,7 +508,7 @@ pub struct ImportSpecifierList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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() }
|
Self { import_specifiers: p.ast.new_vec() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,7 +520,7 @@ impl<'a> SeparatedList<'a> for ImportSpecifierList<'a> {
|
||||||
Kind::RCurly
|
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 import_specifier = p.parse_import_specifier()?;
|
||||||
let specifier = ImportDeclarationSpecifier::ImportSpecifier(import_specifier);
|
let specifier = ImportDeclarationSpecifier::ImportSpecifier(import_specifier);
|
||||||
self.import_specifiers.push(specifier);
|
self.import_specifiers.push(specifier);
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ use super::{
|
||||||
function::FunctionKind,
|
function::FunctionKind,
|
||||||
list::{AssertEntries, ExportNamedSpecifiers, ImportSpecifierList},
|
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)
|
/// [Import Call](https://tc39.es/ecma262/#sec-import-calls)
|
||||||
/// `ImportCall` : import ( `AssignmentExpression` )
|
/// `ImportCall` : import ( `AssignmentExpression` )
|
||||||
pub(crate) fn parse_import_expression(&mut self, span: Span) -> Result<Expression<'a>> {
|
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 oxc_syntax::operator::AssignmentOperator;
|
||||||
|
|
||||||
use super::list::ObjectExpressionProperties;
|
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)
|
/// [Object Expression](https://tc39.es/ecma262/#sec-object-initializer)
|
||||||
/// `ObjectLiteral`[Yield, Await] :
|
/// `ObjectLiteral`[Yield, Await] :
|
||||||
/// { }
|
/// { }
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ use super::{
|
||||||
grammar::CoverGrammar,
|
grammar::CoverGrammar,
|
||||||
list::SwitchCases,
|
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
|
// Section 12
|
||||||
// The InputElementHashbangOrRegExp goal is used at the start of a Script
|
// The InputElementHashbangOrRegExp goal is used at the start of a Script
|
||||||
// or Module.
|
// or Module.
|
||||||
|
|
@ -283,7 +283,7 @@ impl<'a> Parser<'a> {
|
||||||
return self.parse_for_loop(span, None, r#await);
|
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 ..)
|
// for (a.b in ...), for ([a] in ..), for ({a} in ..)
|
||||||
if self.at(Kind::In) || self.at(Kind::Of) {
|
if self.at(Kind::In) || self.at(Kind::Of) {
|
||||||
|
|
@ -359,7 +359,7 @@ impl<'a> Parser<'a> {
|
||||||
) -> Result<Statement<'a>> {
|
) -> Result<Statement<'a>> {
|
||||||
self.expect(Kind::Semicolon)?;
|
self.expect(Kind::Semicolon)?;
|
||||||
let test = if !self.at(Kind::Semicolon) && !self.at(Kind::RParen) {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
@ -367,7 +367,7 @@ impl<'a> Parser<'a> {
|
||||||
let update = if self.at(Kind::RParen) {
|
let update = if self.at(Kind::RParen) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(self.with_context(Context::In, Parser::parse_expression)?)
|
Some(self.with_context(Context::In, ParserImpl::parse_expression)?)
|
||||||
};
|
};
|
||||||
self.expect(Kind::RParen)?;
|
self.expect(Kind::RParen)?;
|
||||||
if r#await {
|
if r#await {
|
||||||
|
|
@ -433,7 +433,7 @@ impl<'a> Parser<'a> {
|
||||||
let argument = if self.eat(Kind::Semicolon) || self.can_insert_semicolon() {
|
let argument = if self.eat(Kind::Semicolon) || self.can_insert_semicolon() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let expr = self.with_context(Context::In, Parser::parse_expression)?;
|
let expr = self.with_context(Context::In, ParserImpl::parse_expression)?;
|
||||||
self.asi()?;
|
self.asi()?;
|
||||||
Some(expr)
|
Some(expr)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ use oxc_ast::ast::*;
|
||||||
use oxc_diagnostics::Result;
|
use oxc_diagnostics::Result;
|
||||||
use oxc_span::{Atom, Span};
|
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>> {
|
pub(crate) fn parse_jsx_expression(&mut self) -> Result<Expression<'a>> {
|
||||||
if self.peek_at(Kind::RAngle) {
|
if self.peek_at(Kind::RAngle) {
|
||||||
self.parse_jsx_fragment(false).map(Expression::JSXFragment)
|
self.parse_jsx_fragment(false).map(Expression::JSXFragment)
|
||||||
|
|
|
||||||
|
|
@ -116,10 +116,70 @@ pub struct ParserReturn<'a> {
|
||||||
pub panicked: bool,
|
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
|
/// Recursive Descent Parser for ECMAScript and TypeScript
|
||||||
///
|
///
|
||||||
/// See [`Parser::parse`] for entry function.
|
/// See [`Parser::parse`] for entry function.
|
||||||
pub struct Parser<'a> {
|
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>,
|
lexer: Lexer<'a>,
|
||||||
|
|
||||||
/// SourceType: JavaScript or TypeScript, Script or Module, jsx support?
|
/// SourceType: JavaScript or TypeScript, Script or Module, jsx support?
|
||||||
|
|
@ -152,9 +212,14 @@ pub struct Parser<'a> {
|
||||||
preserve_parens: bool,
|
preserve_parens: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> ParserImpl<'a> {
|
||||||
/// Create a new parser
|
/// 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 {
|
Self {
|
||||||
lexer: Lexer::new(allocator, source_text, source_type),
|
lexer: Lexer::new(allocator, source_text, source_type),
|
||||||
source_type,
|
source_type,
|
||||||
|
|
@ -163,32 +228,12 @@ impl<'a> Parser<'a> {
|
||||||
token: Token::default(),
|
token: Token::default(),
|
||||||
prev_token_end: 0,
|
prev_token_end: 0,
|
||||||
state: ParserState::new(allocator),
|
state: ParserState::new(allocator),
|
||||||
ctx: Self::default_context(source_type),
|
ctx: Self::default_context(source_type, options),
|
||||||
ast: AstBuilder::new(allocator),
|
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
|
/// Main entry point
|
||||||
///
|
///
|
||||||
/// Returns an empty `Program` on unrecoverable error,
|
/// 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))
|
Ok(self.ast.program(span, self.source_type, directives, hashbang, statements))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_context(source_type: SourceType) -> Context {
|
fn default_context(source_type: SourceType, options: ParserOptions) -> Context {
|
||||||
let ctx = Context::default().and_ambient(source_type.is_typescript_definition());
|
let mut ctx = Context::default().and_ambient(source_type.is_typescript_definition());
|
||||||
match source_type.module_kind() {
|
if source_type.module_kind() == ModuleKind::Module {
|
||||||
ModuleKind::Script => ctx,
|
|
||||||
// for [top-level-await](https://tc39.es/proposal-top-level-await/)
|
// 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.
|
/// Check for Flow declaration if the file cannot be parsed.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use oxc_diagnostics::Result;
|
use oxc_diagnostics::Result;
|
||||||
|
|
||||||
use crate::{lexer::Kind, Parser};
|
use crate::{lexer::Kind, ParserImpl};
|
||||||
|
|
||||||
pub trait NormalList<'a> {
|
pub trait NormalList<'a> {
|
||||||
/// Open element, e.g.. `{` `[` `(`
|
/// Open element, e.g.. `{` `[` `(`
|
||||||
|
|
@ -9,10 +9,10 @@ pub trait NormalList<'a> {
|
||||||
/// Close element, e.g.. `}` `]` `)`
|
/// Close element, e.g.. `}` `]` `)`
|
||||||
fn close(&self) -> Kind;
|
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
|
/// 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())?;
|
p.expect(self.open())?;
|
||||||
while !p.at(self.close()) && !p.at(Kind::Eof) {
|
while !p.at(self.close()) && !p.at(Kind::Eof) {
|
||||||
self.parse_element(p)?;
|
self.parse_element(p)?;
|
||||||
|
|
@ -23,9 +23,9 @@ pub trait NormalList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SeparatedList<'a>: Sized {
|
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);
|
let mut list = Self::new(p);
|
||||||
list.parse_list(p)?;
|
list.parse_list(p)?;
|
||||||
Ok(list)
|
Ok(list)
|
||||||
|
|
@ -42,10 +42,10 @@ pub trait SeparatedList<'a>: Sized {
|
||||||
Kind::Comma
|
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
|
/// 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())?;
|
p.expect(self.open())?;
|
||||||
|
|
||||||
let mut first = true;
|
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
|
/// Check if the parser is at a start of a declaration
|
||||||
fn at_start_of_ts_declaration_worker(&mut self) -> bool {
|
fn at_start_of_ts_declaration_worker(&mut self) -> bool {
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -80,11 +80,12 @@ mod test_is_declaration {
|
||||||
use oxc_span::SourceType;
|
use oxc_span::SourceType;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::ParserOptions;
|
||||||
|
|
||||||
fn run_check(source: &str, expected: bool) {
|
fn run_check(source: &str, expected: bool) {
|
||||||
let alloc = Allocator::default();
|
let alloc = Allocator::default();
|
||||||
let source_type = SourceType::default().with_typescript(true);
|
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.
|
// Get the parser to the first token.
|
||||||
parser.bump_any();
|
parser.bump_any();
|
||||||
assert_eq!(expected, parser.at_start_of_ts_declaration());
|
assert_eq!(expected, parser.at_start_of_ts_declaration());
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use oxc_diagnostics::Result;
|
||||||
use crate::{
|
use crate::{
|
||||||
lexer::Kind,
|
lexer::Kind,
|
||||||
list::{NormalList, SeparatedList},
|
list::{NormalList, SeparatedList},
|
||||||
Parser,
|
ParserImpl,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TSEnumMemberList<'a> {
|
pub struct TSEnumMemberList<'a> {
|
||||||
|
|
@ -13,7 +13,7 @@ pub struct TSEnumMemberList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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() }
|
Self { members: p.ast.new_vec() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ impl<'a> SeparatedList<'a> for TSEnumMemberList<'a> {
|
||||||
Kind::RCurly
|
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()?;
|
let element = p.parse_ts_enum_member()?;
|
||||||
self.members.push(element);
|
self.members.push(element);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -37,7 +37,7 @@ pub struct TSTupleElementList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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() }
|
Self { elements: p.ast.new_vec() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,7 +49,7 @@ impl<'a> SeparatedList<'a> for TSTupleElementList<'a> {
|
||||||
Kind::RBrack
|
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();
|
let span = p.start_span();
|
||||||
if p.is_at_named_tuple_element() {
|
if p.is_at_named_tuple_element() {
|
||||||
let _is_rest = p.eat(Kind::Dot3);
|
let _is_rest = p.eat(Kind::Dot3);
|
||||||
|
|
@ -91,7 +91,7 @@ pub struct TSTypeParameterList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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() }
|
Self { params: p.ast.new_vec() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +103,7 @@ impl<'a> SeparatedList<'a> for TSTypeParameterList<'a> {
|
||||||
Kind::RAngle
|
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()?;
|
let param = p.parse_ts_type_parameter()?;
|
||||||
self.params.push(param);
|
self.params.push(param);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -115,7 +115,7 @@ pub struct TSInterfaceOrObjectBodyList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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() }
|
Self { body: p.ast.new_vec() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,7 +129,7 @@ impl<'a> NormalList<'a> for TSInterfaceOrObjectBodyList<'a> {
|
||||||
Kind::RCurly
|
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()?;
|
let property = p.parse_ts_type_signature()?;
|
||||||
self.body.push(property);
|
self.body.push(property);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -141,7 +141,7 @@ pub struct TSTypeArgumentList<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SeparatedList<'a> for 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() }
|
Self { params: p.ast.new_vec() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,7 +153,7 @@ impl<'a> SeparatedList<'a> for TSTypeArgumentList<'a> {
|
||||||
Kind::RAngle
|
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()?;
|
let ty = p.parse_ts_type()?;
|
||||||
self.params.push(ty);
|
self.params.push(ty);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
lexer::Kind,
|
lexer::Kind,
|
||||||
list::{NormalList, SeparatedList},
|
list::{NormalList, SeparatedList},
|
||||||
Parser, StatementContext,
|
ParserImpl, StatementContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> ParserImpl<'a> {
|
||||||
/** ------------------- Enum ------------------ */
|
/** ------------------- Enum ------------------ */
|
||||||
|
|
||||||
pub(crate) fn is_at_enum_declaration(&mut self) -> bool {
|
pub(crate) fn is_at_enum_declaration(&mut self) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
js::list::{ArrayPatternList, ObjectPatternProperties},
|
js::list::{ArrayPatternList, ObjectPatternProperties},
|
||||||
lexer::Kind,
|
lexer::Kind,
|
||||||
list::{NormalList, SeparatedList},
|
list::{NormalList, SeparatedList},
|
||||||
Context, Parser,
|
Context, ParserImpl,
|
||||||
};
|
};
|
||||||
|
|
||||||
bitflags! {
|
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>> {
|
pub(crate) fn parse_ts_type(&mut self) -> Result<TSType<'a>> {
|
||||||
if self.is_at_constructor_type() {
|
if self.is_at_constructor_type() {
|
||||||
return self.parse_ts_constructor_type();
|
return self.parse_ts_constructor_type();
|
||||||
|
|
@ -323,8 +323,8 @@ impl<'a> Parser<'a> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut left =
|
let mut left = self
|
||||||
self.without_context(Context::DisallowConditionalTypes, Parser::parse_ts_basic_type)?;
|
.without_context(Context::DisallowConditionalTypes, ParserImpl::parse_ts_basic_type)?;
|
||||||
|
|
||||||
while !self.cur_token().is_on_new_line && self.eat(Kind::LBrack) {
|
while !self.cur_token().is_on_new_line && self.eat(Kind::LBrack) {
|
||||||
if self.eat(Kind::RBrack) {
|
if self.eat(Kind::RBrack) {
|
||||||
|
|
@ -828,7 +828,7 @@ impl<'a> Parser<'a> {
|
||||||
let parameter_span = self.start_span();
|
let parameter_span = self.start_span();
|
||||||
let name = self.parse_binding_identifier()?;
|
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(
|
let type_parameter = self.ast.ts_type_parameter(
|
||||||
self.end_span(parameter_span),
|
self.end_span(parameter_span),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue