Skip to content

Commit 791c72a

Browse files
committed
perf(parser): add separate token kinds for BigInt literals (#14405)
## Summary Add separate token kinds (`DecimalBigInt`, `BinaryBigInt`, `OctalBigInt`, `HexBigInt`) to eliminate the `ends_with('n')` string check when parsing BigInt literals.
1 parent 96663fb commit 791c72a

File tree

3 files changed

+45
-18
lines changed

3 files changed

+45
-18
lines changed

crates/oxc_parser/src/js/expression.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -270,14 +270,13 @@ impl<'a> ParserImpl<'a> {
270270
let lit = self.parse_literal_null();
271271
Expression::NullLiteral(self.alloc(lit))
272272
}
273+
Kind::DecimalBigInt | Kind::BinaryBigInt | Kind::OctalBigInt | Kind::HexBigInt => {
274+
let lit = self.parse_literal_bigint();
275+
Expression::BigIntLiteral(self.alloc(lit))
276+
}
273277
kind if kind.is_number() => {
274-
if self.cur_src().ends_with('n') {
275-
let lit = self.parse_literal_bigint();
276-
Expression::BigIntLiteral(self.alloc(lit))
277-
} else {
278-
let lit = self.parse_literal_number();
279-
Expression::NumericLiteral(self.alloc(lit))
280-
}
278+
let lit = self.parse_literal_number();
279+
Expression::NumericLiteral(self.alloc(lit))
281280
}
282281
_ => self.unexpected(),
283282
}
@@ -342,17 +341,17 @@ impl<'a> ParserImpl<'a> {
342341
let token = self.cur_token();
343342
let kind = token.kind();
344343
let has_separator = token.has_separator();
345-
let base = match kind {
346-
Kind::Decimal => BigintBase::Decimal,
347-
Kind::Binary => BigintBase::Binary,
348-
Kind::Octal => BigintBase::Octal,
349-
Kind::Hex => BigintBase::Hex,
344+
let (base, number_kind) = match kind {
345+
Kind::DecimalBigInt => (BigintBase::Decimal, Kind::Decimal),
346+
Kind::BinaryBigInt => (BigintBase::Binary, Kind::Binary),
347+
Kind::OctalBigInt => (BigintBase::Octal, Kind::Octal),
348+
Kind::HexBigInt => (BigintBase::Hex, Kind::Hex),
350349
_ => return self.unexpected(),
351350
};
352351
let span = token.span();
353352
let raw = self.cur_src();
354353
let src = raw.strip_suffix('n').unwrap();
355-
let value = parse_big_int(src, kind, has_separator, self.ast.allocator);
354+
let value = parse_big_int(src, number_kind, has_separator, self.ast.allocator);
356355

357356
self.bump_any();
358357
self.ast.big_int_literal(span, value, Some(Atom::from(raw)), base)

crates/oxc_parser/src/lexer/kind.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ pub enum Kind {
179179
PositiveExponential,
180180
// for `1e-10`
181181
NegativeExponential,
182+
// BigInt Literals (numeric literals with 'n' suffix)
183+
DecimalBigInt,
184+
BinaryBigInt,
185+
OctalBigInt,
186+
HexBigInt,
182187
// 12.9.4 String Literals
183188
/// String Type
184189
Str,
@@ -210,7 +215,17 @@ impl Kind {
210215
pub fn is_number(self) -> bool {
211216
matches!(
212217
self,
213-
Float | Decimal | Binary | Octal | Hex | PositiveExponential | NegativeExponential
218+
Float
219+
| Decimal
220+
| Binary
221+
| Octal
222+
| Hex
223+
| PositiveExponential
224+
| NegativeExponential
225+
| DecimalBigInt
226+
| BinaryBigInt
227+
| OctalBigInt
228+
| HexBigInt
214229
)
215230
}
216231

@@ -660,6 +675,10 @@ impl Kind {
660675
Binary => "binary",
661676
Octal => "octal",
662677
Hex => "hex",
678+
DecimalBigInt => "decimal bigint",
679+
BinaryBigInt => "binary bigint",
680+
OctalBigInt => "octal bigint",
681+
HexBigInt => "hex bigint",
663682
Str | String => "string",
664683
RegExp => "/regexp/",
665684
NoSubstitutionTemplate => "${}",

crates/oxc_parser/src/lexer/numeric.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl Lexer<'_> {
2121
}
2222
Some(b'n') => {
2323
self.consume_char();
24-
self.check_after_numeric_literal(Kind::Decimal)
24+
self.check_after_numeric_literal(Kind::DecimalBigInt)
2525
}
2626
Some(n) if n.is_ascii_digit() => self.read_legacy_octal(),
2727
_ => self.check_after_numeric_literal(Kind::Decimal),
@@ -33,7 +33,7 @@ impl Lexer<'_> {
3333
if self.next_ascii_byte_eq(b'.') {
3434
return self.decimal_literal_after_decimal_point_after_digits();
3535
} else if self.next_ascii_byte_eq(b'n') {
36-
return self.check_after_numeric_literal(Kind::Decimal);
36+
return self.check_after_numeric_literal(Kind::DecimalBigInt);
3737
}
3838

3939
let kind = self.optional_exponent().map_or(Kind::Decimal, |kind| kind);
@@ -78,8 +78,17 @@ impl Lexer<'_> {
7878
_ => break,
7979
}
8080
}
81-
self.next_ascii_byte_eq(b'n');
82-
self.check_after_numeric_literal(kind)
81+
let final_kind = if self.next_ascii_byte_eq(b'n') {
82+
match kind {
83+
Kind::Binary => Kind::BinaryBigInt,
84+
Kind::Octal => Kind::OctalBigInt,
85+
Kind::Hex => Kind::HexBigInt,
86+
_ => unreachable!(),
87+
}
88+
} else {
89+
kind
90+
};
91+
self.check_after_numeric_literal(final_kind)
8392
}
8493

8594
fn read_legacy_octal(&mut self) -> Kind {

0 commit comments

Comments
 (0)