@@ -340,18 +340,7 @@ where
340340
341341 /// Lex a hex/octal/decimal/binary number without a decimal point.
342342 fn lex_number_radix ( & mut self , start_pos : Location , radix : u32 ) -> LexResult {
343- let mut value_text = String :: new ( ) ;
344-
345- loop {
346- if let Some ( c) = self . take_number ( radix) {
347- value_text. push ( c) ;
348- } else if self . chr0 == Some ( '_' ) {
349- self . next_char ( ) ;
350- } else {
351- break ;
352- }
353- }
354-
343+ let value_text = self . radix_run ( radix) ;
355344 let end_pos = self . get_pos ( ) ;
356345 let value = BigInt :: from_str_radix ( & value_text, radix) . map_err ( |e| LexicalError {
357346 error : LexicalErrorType :: OtherError ( format ! ( "{:?}" , e) ) ,
@@ -360,24 +349,19 @@ where
360349 Ok ( ( start_pos, Tok :: Int { value } , end_pos) )
361350 }
362351
352+ /// Lex a normal number, that is, no octal, hex or binary number.
363353 fn lex_normal_number ( & mut self ) -> LexResult {
364354 let start_pos = self . get_pos ( ) ;
365355
366- let mut value_text = String :: new ( ) ;
367-
368356 // Normal number:
369- while let Some ( c) = self . take_number ( 10 ) {
370- value_text. push ( c) ;
371- }
357+ let mut value_text = self . radix_run ( 10 ) ;
372358
373359 // If float:
374360 if self . chr0 == Some ( '.' ) || self . at_exponent ( ) {
375361 // Take '.':
376362 if self . chr0 == Some ( '.' ) {
377363 value_text. push ( self . next_char ( ) . unwrap ( ) ) ;
378- while let Some ( c) = self . take_number ( 10 ) {
379- value_text. push ( c) ;
380- }
364+ value_text. push_str ( & self . radix_run ( 10 ) ) ;
381365 }
382366
383367 // 1e6 for example:
@@ -389,9 +373,7 @@ where
389373 value_text. push ( self . next_char ( ) . unwrap ( ) ) ;
390374 }
391375
392- while let Some ( c) = self . take_number ( 10 ) {
393- value_text. push ( c) ;
394- }
376+ value_text. push_str ( & self . radix_run ( 10 ) ) ;
395377 }
396378
397379 let value = f64:: from_str ( & value_text) . unwrap ( ) ;
@@ -426,6 +408,57 @@ where
426408 }
427409 }
428410
411+ /// Consume a sequence of numbers with the given radix,
412+ /// the digits can be decorated with underscores
413+ /// like this: '1_2_3_4' == '1234'
414+ fn radix_run ( & mut self , radix : u32 ) -> String {
415+ let mut value_text = String :: new ( ) ;
416+ loop {
417+ if let Some ( c) = self . take_number ( radix) {
418+ value_text. push ( c) ;
419+ } else if self . chr0 == Some ( '_' ) && Lexer :: < T > :: is_digit_of_radix ( self . chr1 , radix) {
420+ self . next_char ( ) ;
421+ } else {
422+ break ;
423+ }
424+ }
425+ value_text
426+ }
427+
428+ /// Consume a single character with the given radix.
429+ fn take_number ( & mut self , radix : u32 ) -> Option < char > {
430+ let take_char = Lexer :: < T > :: is_digit_of_radix ( self . chr0 , radix) ;
431+
432+ if take_char {
433+ Some ( self . next_char ( ) . unwrap ( ) )
434+ } else {
435+ None
436+ }
437+ }
438+
439+ /// Test if a digit is of a certain radix.
440+ fn is_digit_of_radix ( c : Option < char > , radix : u32 ) -> bool {
441+ match radix {
442+ 2 => match c {
443+ Some ( '0' ..='1' ) => true ,
444+ _ => false ,
445+ } ,
446+ 8 => match c {
447+ Some ( '0' ..='7' ) => true ,
448+ _ => false ,
449+ } ,
450+ 10 => match c {
451+ Some ( '0' ..='9' ) => true ,
452+ _ => false ,
453+ } ,
454+ 16 => match c {
455+ Some ( '0' ..='9' ) | Some ( 'a' ..='f' ) | Some ( 'A' ..='F' ) => true ,
456+ _ => false ,
457+ } ,
458+ x => unimplemented ! ( "Radix not implemented: {}" , x) ,
459+ }
460+ }
461+
429462 /// Test if we face '[eE][-+]?[0-9]+'
430463 fn at_exponent ( & self ) -> bool {
431464 match self . chr0 {
@@ -626,34 +659,6 @@ where
626659 }
627660 }
628661
629- fn take_number ( & mut self , radix : u32 ) -> Option < char > {
630- let take_char = match radix {
631- 2 => match self . chr0 {
632- Some ( '0' ..='1' ) => true ,
633- _ => false ,
634- } ,
635- 8 => match self . chr0 {
636- Some ( '0' ..='7' ) => true ,
637- _ => false ,
638- } ,
639- 10 => match self . chr0 {
640- Some ( '0' ..='9' ) => true ,
641- _ => false ,
642- } ,
643- 16 => match self . chr0 {
644- Some ( '0' ..='9' ) | Some ( 'a' ..='f' ) | Some ( 'A' ..='F' ) => true ,
645- _ => false ,
646- } ,
647- x => unimplemented ! ( "Radix not implemented: {}" , x) ,
648- } ;
649-
650- if take_char {
651- Some ( self . next_char ( ) . unwrap ( ) )
652- } else {
653- None
654- }
655- }
656-
657662 /// This is the main entry point. Call this function to retrieve the next token.
658663 /// This function is used by the iterator implementation.
659664 fn inner_next ( & mut self ) -> LexResult {
0 commit comments