@@ -194,7 +194,7 @@ pub enum DocStyle {
194194pub enum LiteralKind {
195195 /// `12_u8`, `0o100`, `0b120i99`, `1f32`.
196196 Int { base : Base , empty_int : bool } ,
197- /// `12.34f32`, `1e3`, but not `1f32`.
197+ /// `12.34f32`, `1e3` and `1e+` , but not `1f32` or `1em `.
198198 Float { base : Base , empty_exponent : bool } ,
199199 /// `'a'`, `'\\'`, `'''`, `';`
200200 Char { terminated : bool } ,
@@ -409,8 +409,8 @@ impl Cursor<'_> {
409409
410410 // Numeric literal.
411411 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 ( ) ) ;
414414 self . eat_literal_suffix ( ) ;
415415 TokenKind :: Literal { kind : literal_kind, suffix_start }
416416 }
@@ -606,7 +606,9 @@ impl Cursor<'_> {
606606 }
607607 }
608608
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 > ) {
610612 debug_assert ! ( '0' <= self . prev( ) && self . prev( ) <= '9' ) ;
611613 let mut base = Base :: Decimal ;
612614 if first_digit == '0' {
@@ -616,21 +618,21 @@ impl Cursor<'_> {
616618 base = Base :: Binary ;
617619 self . bump ( ) ;
618620 if !self . eat_decimal_digits ( ) {
619- return Int { base, empty_int : true } ;
621+ return ( Int { base, empty_int : true } , None ) ;
620622 }
621623 }
622624 'o' => {
623625 base = Base :: Octal ;
624626 self . bump ( ) ;
625627 if !self . eat_decimal_digits ( ) {
626- return Int { base, empty_int : true } ;
628+ return ( Int { base, empty_int : true } , None ) ;
627629 }
628630 }
629631 'x' => {
630632 base = Base :: Hexadecimal ;
631633 self . bump ( ) ;
632634 if !self . eat_hexadecimal_digits ( ) {
633- return Int { base, empty_int : true } ;
635+ return ( Int { base, empty_int : true } , None ) ;
634636 }
635637 }
636638 // Not a base prefix; consume additional digits.
@@ -642,40 +644,79 @@ impl Cursor<'_> {
642644 '.' | 'e' | 'E' => { }
643645
644646 // Just a 0.
645- _ => return Int { base, empty_int : false } ,
647+ _ => return ( Int { base, empty_int : false } , None ) ,
646648 }
647649 } else {
648650 // No base prefix, parse number in the usual way.
649651 self . eat_decimal_digits ( ) ;
650652 } ;
651653
652- match self . first ( ) {
654+ match ( self . first ( ) , self . second ( ) ) {
653655 // Don't be greedy if this is actually an
654656 // integer literal followed by field/method access or a range pattern
655657 // (`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) => {
659659 self . bump ( ) ;
660+ self . eat_decimal_digits ( ) ;
661+
660662 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
669670 }
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 ) ,
670682 }
671- Float { base, empty_exponent }
672683 }
673- 'e' | 'E' => {
684+ ( 'e' | 'E' , '0' ..='9' | '+' | '-' ) => {
685+ // Definitely an exponent (which still can be empty).
674686 self . bump ( ) ;
675687 let empty_exponent = !self . eat_float_exponent ( ) ;
676- Float { base, empty_exponent }
688+ ( Float { base, empty_exponent } , None )
677689 }
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)
679720 }
680721 }
681722
@@ -924,6 +965,7 @@ impl Cursor<'_> {
924965 }
925966 }
926967
968+ /// Returns `true` if a digit was consumed (rather than just '_'s).
927969 fn eat_decimal_digits ( & mut self ) -> bool {
928970 let mut has_digits = false ;
929971 loop {
@@ -961,20 +1003,20 @@ impl Cursor<'_> {
9611003 /// Eats the float exponent. Returns true if at least one digit was met,
9621004 /// and returns false otherwise.
9631005 fn eat_float_exponent ( & mut self ) -> bool {
964- debug_assert ! ( self . prev( ) == 'e' || self . prev ( ) == 'E' ) ;
1006+ debug_assert ! ( matches! ( self . prev( ) , 'e' | 'E' ) ) ;
9651007 if self . first ( ) == '-' || self . first ( ) == '+' {
9661008 self . bump ( ) ;
9671009 }
9681010 self . eat_decimal_digits ( )
9691011 }
9701012
971- // Eats the suffix of the literal, e.g. "u8".
1013+ /// Eats the suffix of the literal, e.g. "u8".
9721014 fn eat_literal_suffix ( & mut self ) {
973- self . eat_identifier ( ) ;
1015+ self . eat_identifier ( )
9741016 }
9751017
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.
9781020 fn eat_identifier ( & mut self ) {
9791021 if !is_id_start ( self . first ( ) ) {
9801022 return ;
0 commit comments