diff --git a/crates/oxc_parser/src/js/expression.rs b/crates/oxc_parser/src/js/expression.rs index c173facbaab8b..22ee252e3d773 100644 --- a/crates/oxc_parser/src/js/expression.rs +++ b/crates/oxc_parser/src/js/expression.rs @@ -270,14 +270,13 @@ impl<'a> ParserImpl<'a> { let lit = self.parse_literal_null(); Expression::NullLiteral(self.alloc(lit)) } + Kind::DecimalBigInt | Kind::BinaryBigInt | Kind::OctalBigInt | Kind::HexBigInt => { + let lit = self.parse_literal_bigint(); + Expression::BigIntLiteral(self.alloc(lit)) + } kind if kind.is_number() => { - if self.cur_src().ends_with('n') { - let lit = self.parse_literal_bigint(); - Expression::BigIntLiteral(self.alloc(lit)) - } else { - let lit = self.parse_literal_number(); - Expression::NumericLiteral(self.alloc(lit)) - } + let lit = self.parse_literal_number(); + Expression::NumericLiteral(self.alloc(lit)) } _ => self.unexpected(), } @@ -342,17 +341,17 @@ impl<'a> ParserImpl<'a> { let token = self.cur_token(); let kind = token.kind(); let has_separator = token.has_separator(); - let base = match kind { - Kind::Decimal => BigintBase::Decimal, - Kind::Binary => BigintBase::Binary, - Kind::Octal => BigintBase::Octal, - Kind::Hex => BigintBase::Hex, + let (base, number_kind) = match kind { + Kind::DecimalBigInt => (BigintBase::Decimal, Kind::Decimal), + Kind::BinaryBigInt => (BigintBase::Binary, Kind::Binary), + Kind::OctalBigInt => (BigintBase::Octal, Kind::Octal), + Kind::HexBigInt => (BigintBase::Hex, Kind::Hex), _ => return self.unexpected(), }; let span = token.span(); let raw = self.cur_src(); let src = raw.strip_suffix('n').unwrap(); - let value = parse_big_int(src, kind, has_separator, self.ast.allocator); + let value = parse_big_int(src, number_kind, has_separator, self.ast.allocator); self.bump_any(); self.ast.big_int_literal(span, value, Some(Atom::from(raw)), base) diff --git a/crates/oxc_parser/src/lexer/kind.rs b/crates/oxc_parser/src/lexer/kind.rs index f673dfe90074b..c4b7074268533 100644 --- a/crates/oxc_parser/src/lexer/kind.rs +++ b/crates/oxc_parser/src/lexer/kind.rs @@ -179,6 +179,11 @@ pub enum Kind { PositiveExponential, // for `1e-10` NegativeExponential, + // BigInt Literals (numeric literals with 'n' suffix) + DecimalBigInt, + BinaryBigInt, + OctalBigInt, + HexBigInt, // 12.9.4 String Literals /// String Type Str, @@ -210,7 +215,17 @@ impl Kind { pub fn is_number(self) -> bool { matches!( self, - Float | Decimal | Binary | Octal | Hex | PositiveExponential | NegativeExponential + Float + | Decimal + | Binary + | Octal + | Hex + | PositiveExponential + | NegativeExponential + | DecimalBigInt + | BinaryBigInt + | OctalBigInt + | HexBigInt ) } @@ -660,6 +675,10 @@ impl Kind { Binary => "binary", Octal => "octal", Hex => "hex", + DecimalBigInt => "decimal bigint", + BinaryBigInt => "binary bigint", + OctalBigInt => "octal bigint", + HexBigInt => "hex bigint", Str | String => "string", RegExp => "/regexp/", NoSubstitutionTemplate => "${}", diff --git a/crates/oxc_parser/src/lexer/numeric.rs b/crates/oxc_parser/src/lexer/numeric.rs index be050d742af0d..1c2bedd66cb31 100644 --- a/crates/oxc_parser/src/lexer/numeric.rs +++ b/crates/oxc_parser/src/lexer/numeric.rs @@ -21,7 +21,7 @@ impl Lexer<'_> { } Some(b'n') => { self.consume_char(); - self.check_after_numeric_literal(Kind::Decimal) + self.check_after_numeric_literal(Kind::DecimalBigInt) } Some(n) if n.is_ascii_digit() => self.read_legacy_octal(), _ => self.check_after_numeric_literal(Kind::Decimal), @@ -33,7 +33,7 @@ impl Lexer<'_> { if self.next_ascii_byte_eq(b'.') { return self.decimal_literal_after_decimal_point_after_digits(); } else if self.next_ascii_byte_eq(b'n') { - return self.check_after_numeric_literal(Kind::Decimal); + return self.check_after_numeric_literal(Kind::DecimalBigInt); } let kind = self.optional_exponent().map_or(Kind::Decimal, |kind| kind); @@ -78,8 +78,17 @@ impl Lexer<'_> { _ => break, } } - self.next_ascii_byte_eq(b'n'); - self.check_after_numeric_literal(kind) + let final_kind = if self.next_ascii_byte_eq(b'n') { + match kind { + Kind::Binary => Kind::BinaryBigInt, + Kind::Octal => Kind::OctalBigInt, + Kind::Hex => Kind::HexBigInt, + _ => unreachable!(), + } + } else { + kind + }; + self.check_after_numeric_literal(final_kind) } fn read_legacy_octal(&mut self) -> Kind {