@@ -194,7 +194,7 @@ pub enum DocStyle {
194
194
pub enum LiteralKind {
195
195
/// `12_u8`, `0o100`, `0b120i99`, `1f32`.
196
196
Int { base : Base , empty_int : bool } ,
197
- /// `12.34f32`, `1e3`, but not `1f32`.
197
+ /// `12.34f32`, `1e3` and `1e+` , but not `1f32` or `1em `.
198
198
Float { base : Base , empty_exponent : bool } ,
199
199
/// `'a'`, `'\\'`, `'''`, `';`
200
200
Char { terminated : bool } ,
@@ -409,8 +409,8 @@ impl Cursor<'_> {
409
409
410
410
// Numeric literal.
411
411
c @ '0' ..='9' => {
412
- let literal_kind = self . number ( c) ;
413
- let suffix_start = self . pos_within_token ( ) ;
412
+ let ( literal_kind, suffix_start ) = self . number ( c) ;
413
+ let suffix_start = suffix_start . unwrap_or ( self . pos_within_token ( ) ) ;
414
414
self . eat_literal_suffix ( ) ;
415
415
TokenKind :: Literal { kind : literal_kind, suffix_start }
416
416
}
@@ -606,7 +606,9 @@ impl Cursor<'_> {
606
606
}
607
607
}
608
608
609
- fn number ( & mut self , first_digit : char ) -> LiteralKind {
609
+ /// Parses a number and in `.1` returns the offset of the literal suffix if
610
+ /// different from the current position on return.
611
+ fn number ( & mut self , first_digit : char ) -> ( LiteralKind , Option < u32 > ) {
610
612
debug_assert ! ( '0' <= self . prev( ) && self . prev( ) <= '9' ) ;
611
613
let mut base = Base :: Decimal ;
612
614
if first_digit == '0' {
@@ -616,21 +618,21 @@ impl Cursor<'_> {
616
618
base = Base :: Binary ;
617
619
self . bump ( ) ;
618
620
if !self . eat_decimal_digits ( ) {
619
- return Int { base, empty_int : true } ;
621
+ return ( Int { base, empty_int : true } , None ) ;
620
622
}
621
623
}
622
624
'o' => {
623
625
base = Base :: Octal ;
624
626
self . bump ( ) ;
625
627
if !self . eat_decimal_digits ( ) {
626
- return Int { base, empty_int : true } ;
628
+ return ( Int { base, empty_int : true } , None ) ;
627
629
}
628
630
}
629
631
'x' => {
630
632
base = Base :: Hexadecimal ;
631
633
self . bump ( ) ;
632
634
if !self . eat_hexadecimal_digits ( ) {
633
- return Int { base, empty_int : true } ;
635
+ return ( Int { base, empty_int : true } , None ) ;
634
636
}
635
637
}
636
638
// Not a base prefix; consume additional digits.
@@ -642,40 +644,79 @@ impl Cursor<'_> {
642
644
'.' | 'e' | 'E' => { }
643
645
644
646
// Just a 0.
645
- _ => return Int { base, empty_int : false } ,
647
+ _ => return ( Int { base, empty_int : false } , None ) ,
646
648
}
647
649
} else {
648
650
// No base prefix, parse number in the usual way.
649
651
self . eat_decimal_digits ( ) ;
650
652
} ;
651
653
652
- match self . first ( ) {
654
+ match ( self . first ( ) , self . second ( ) ) {
653
655
// Don't be greedy if this is actually an
654
656
// integer literal followed by field/method access or a range pattern
655
657
// (`0..2` and `12.foo()`)
656
- '.' if self . second ( ) != '.' && !is_id_start ( self . second ( ) ) => {
657
- // might have stuff after the ., and if it does, it needs to start
658
- // with a number
658
+ ( '.' , second) if second != '.' && !is_id_start ( second) => {
659
659
self . bump ( ) ;
660
+ self . eat_decimal_digits ( ) ;
661
+
660
662
let mut empty_exponent = false ;
661
- if self . first ( ) . is_ascii_digit ( ) {
662
- self . eat_decimal_digits ( ) ;
663
- match self . first ( ) {
664
- 'e' | 'E' => {
665
- self . bump ( ) ;
666
- empty_exponent = !self . eat_float_exponent ( ) ;
667
- }
668
- _ => ( ) ,
663
+ let suffix_start = match ( self . first ( ) , self . second ( ) ) {
664
+ ( 'e' | 'E' , '_' ) => self . eat_underscore_exponent ( ) ,
665
+ ( 'e' | 'E' , '0' ..='9' | '+' | '-' ) => {
666
+ // Definitely an exponent (which still can be empty).
667
+ self . bump ( ) ;
668
+ empty_exponent = !self . eat_float_exponent ( ) ;
669
+ None
669
670
}
671
+ _ => None ,
672
+ } ;
673
+ ( Float { base, empty_exponent } , suffix_start)
674
+ }
675
+ ( 'e' | 'E' , '_' ) => {
676
+ match self . eat_underscore_exponent ( ) {
677
+ Some ( suffix_start) => {
678
+ // The suffix begins at `e`, meaning the number is an integer.
679
+ ( Int { base, empty_int : false } , Some ( suffix_start) )
680
+ }
681
+ None => ( Float { base, empty_exponent : false } , None ) ,
670
682
}
671
- Float { base, empty_exponent }
672
683
}
673
- 'e' | 'E' => {
684
+ ( 'e' | 'E' , '0' ..='9' | '+' | '-' ) => {
685
+ // Definitely an exponent (which still can be empty).
674
686
self . bump ( ) ;
675
687
let empty_exponent = !self . eat_float_exponent ( ) ;
676
- Float { base, empty_exponent }
688
+ ( Float { base, empty_exponent } , None )
677
689
}
678
- _ => Int { base, empty_int : false } ,
690
+ _ => ( Int { base, empty_int : false } , None ) ,
691
+ }
692
+ }
693
+
694
+ /// Try to find and eat an exponent
695
+ ///
696
+ /// Assumes the first character is `e`/`E` and second is `_`, and consumes
697
+ /// `e`/`E` followed by all consecutive `_`s.
698
+ ///
699
+ /// Returns `Some` if no exponent was found. In this case, the suffix is partially
700
+ /// consumed, and began at the return value.
701
+ fn eat_underscore_exponent ( & mut self ) -> Option < u32 > {
702
+ debug_assert ! ( matches!( self . first( ) , 'e' | 'E' ) ) ;
703
+ debug_assert ! ( matches!( self . second( ) , '_' ) ) ;
704
+ let suffix_start = self . pos_within_token ( ) ;
705
+
706
+ // check if series of `_` is ended by a digit. If yes
707
+ // include it in the number as exponent. If no include
708
+ // it in suffix.
709
+ self . bump ( ) ;
710
+ while matches ! ( self . first( ) , '_' ) {
711
+ self . bump ( ) ;
712
+ }
713
+ // If we find a digit, then the exponential was valid
714
+ // so the suffix will start at the cursor as usual.
715
+ if self . first ( ) . is_ascii_digit ( ) {
716
+ self . eat_decimal_digits ( ) ;
717
+ None
718
+ } else {
719
+ Some ( suffix_start)
679
720
}
680
721
}
681
722
@@ -924,6 +965,7 @@ impl Cursor<'_> {
924
965
}
925
966
}
926
967
968
+ /// Returns `true` if a digit was consumed (rather than just '_'s).
927
969
fn eat_decimal_digits ( & mut self ) -> bool {
928
970
let mut has_digits = false ;
929
971
loop {
@@ -961,20 +1003,20 @@ impl Cursor<'_> {
961
1003
/// Eats the float exponent. Returns true if at least one digit was met,
962
1004
/// and returns false otherwise.
963
1005
fn eat_float_exponent ( & mut self ) -> bool {
964
- debug_assert ! ( self . prev( ) == 'e' || self . prev ( ) == 'E' ) ;
1006
+ debug_assert ! ( matches! ( self . prev( ) , 'e' | 'E' ) ) ;
965
1007
if self . first ( ) == '-' || self . first ( ) == '+' {
966
1008
self . bump ( ) ;
967
1009
}
968
1010
self . eat_decimal_digits ( )
969
1011
}
970
1012
971
- // Eats the suffix of the literal, e.g. "u8".
1013
+ /// Eats the suffix of the literal, e.g. "u8".
972
1014
fn eat_literal_suffix ( & mut self ) {
973
- self . eat_identifier ( ) ;
1015
+ self . eat_identifier ( )
974
1016
}
975
1017
976
- // Eats the identifier. Note: succeeds on `_`, which isn't a valid
977
- // identifier.
1018
+ /// Eats the identifier. Note: succeeds on `_`, which isn't a valid
1019
+ /// identifier.
978
1020
fn eat_identifier ( & mut self ) {
979
1021
if !is_id_start ( self . first ( ) ) {
980
1022
return ;
0 commit comments