@@ -511,28 +511,41 @@ pub fn raw_str_lit(lit: &str) -> String {
511
511
res
512
512
}
513
513
514
- pub fn float_lit ( s : & str ) -> ast:: Lit_ {
515
- debug ! ( "float_lit: {}" , s) ;
516
- // FIXME #2252: bounds checking float literals is defered until trans
517
- let s2 = s. chars ( ) . filter ( |& c| c != '_' ) . collect :: < String > ( ) ;
518
- let s = s2. as_slice ( ) ;
519
-
520
- let mut ty = None ;
521
-
522
- if s. ends_with ( "f32" ) {
523
- ty = Some ( ast:: TyF32 ) ;
524
- } else if s. ends_with ( "f64" ) {
525
- ty = Some ( ast:: TyF64 ) ;
526
- }
514
+ // check if `s` looks like i32 or u1234 etc.
515
+ fn looks_like_width_suffix ( first_chars : & [ char ] , s : & str ) -> bool {
516
+ s. len ( ) > 1 &&
517
+ first_chars. contains ( & s. char_at ( 0 ) ) &&
518
+ s. slice_from ( 1 ) . chars ( ) . all ( |c| '0' <= c && c <= '9' )
519
+ }
527
520
521
+ fn filtered_float_lit ( data : token:: InternedString , suffix : Option < & str > ,
522
+ sd : & SpanHandler , sp : Span ) -> ast:: Lit_ {
523
+ debug ! ( "filtered_float_lit: {}, {}" , data, suffix) ;
524
+ match suffix {
525
+ Some ( "f32" ) => ast:: LitFloat ( data, ast:: TyF32 ) ,
526
+ Some ( "f64" ) => ast:: LitFloat ( data, ast:: TyF64 ) ,
527
+ Some ( suf) => {
528
+ if suf. len ( ) >= 2 && looks_like_width_suffix ( & [ 'f' ] , suf) {
529
+ // if it looks like a width, lets try to be helpful.
530
+ sd. span_err ( sp, & * format ! ( "illegal width `{}` for float literal, \
531
+ valid widths are 32 and 64", suf. slice_from( 1 ) ) ) ;
532
+ } else {
533
+ sd. span_err ( sp, & * format ! ( "illegal suffix `{}` for float literal, \
534
+ valid suffixes are `f32` and `f64`", suf) ) ;
535
+ }
528
536
529
- match ty {
530
- Some ( t) => {
531
- ast:: LitFloat ( token:: intern_and_get_ident ( s. slice_to ( s. len ( ) - t. suffix_len ( ) ) ) , t)
532
- } ,
533
- None => ast:: LitFloatUnsuffixed ( token:: intern_and_get_ident ( s) )
537
+ ast:: LitFloatUnsuffixed ( data)
538
+ }
539
+ None => ast:: LitFloatUnsuffixed ( data)
534
540
}
535
541
}
542
+ pub fn float_lit ( s : & str , suffix : Option < & str > , sd : & SpanHandler , sp : Span ) -> ast:: Lit_ {
543
+ debug ! ( "float_lit: {}, {}" , s, suffix) ;
544
+ // FIXME #2252: bounds checking float literals is defered until trans
545
+ let s = s. chars ( ) . filter ( |& c| c != '_' ) . collect :: < String > ( ) ;
546
+ let data = token:: intern_and_get_ident ( & * s) ;
547
+ filtered_float_lit ( data, suffix, sd, sp)
548
+ }
536
549
537
550
/// Parse a string representing a byte literal into its final form. Similar to `char_lit`
538
551
pub fn byte_lit ( lit : & str ) -> ( u8 , uint ) {
@@ -626,24 +639,19 @@ pub fn binary_lit(lit: &str) -> Rc<Vec<u8>> {
626
639
Rc :: new ( res)
627
640
}
628
641
629
- pub fn integer_lit ( s : & str , sd : & SpanHandler , sp : Span ) -> ast:: Lit_ {
642
+ pub fn integer_lit ( s : & str , suffix : Option < & str > , sd : & SpanHandler , sp : Span ) -> ast:: Lit_ {
630
643
// s can only be ascii, byte indexing is fine
631
644
632
645
let s2 = s. chars ( ) . filter ( |& c| c != '_' ) . collect :: < String > ( ) ;
633
646
let mut s = s2. as_slice ( ) ;
634
647
635
- debug ! ( "parse_integer_lit: {}" , s) ;
636
-
637
- if s. len ( ) == 1 {
638
- let n = ( s. char_at ( 0 ) ) . to_digit ( 10 ) . unwrap ( ) ;
639
- return ast:: LitInt ( n as u64 , ast:: UnsuffixedIntLit ( ast:: Sign :: new ( n) ) ) ;
640
- }
648
+ debug ! ( "integer_lit: {}, {}" , s, suffix) ;
641
649
642
650
let mut base = 10 ;
643
651
let orig = s;
644
652
let mut ty = ast:: UnsuffixedIntLit ( ast:: Plus ) ;
645
653
646
- if s. char_at ( 0 ) == '0' {
654
+ if s. char_at ( 0 ) == '0' && s . len ( ) > 1 {
647
655
match s. char_at ( 1 ) {
648
656
'x' => base = 16 ,
649
657
'o' => base = 8 ,
@@ -652,57 +660,56 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
652
660
}
653
661
}
654
662
663
+ // 1f64 and 2f32 etc. are valid float literals.
664
+ match suffix {
665
+ Some ( suf) if looks_like_width_suffix ( & [ 'f' ] , suf) => {
666
+ match base {
667
+ 16 u => sd. span_err ( sp, "hexadecimal float literal is not supported" ) ,
668
+ 8 u => sd. span_err ( sp, "octal float literal is not supported" ) ,
669
+ 2 u => sd. span_err ( sp, "binary float literal is not supported" ) ,
670
+ _ => ( )
671
+ }
672
+ let ident = token:: intern_and_get_ident ( & * s) ;
673
+ return filtered_float_lit ( ident, suffix, sd, sp)
674
+ }
675
+ _ => { }
676
+ }
677
+
655
678
if base != 10 {
656
679
s = s. slice_from ( 2 ) ;
657
680
}
658
681
659
- let last = s. len ( ) - 1 ;
660
- match s. char_at ( last) {
661
- 'i' => ty = ast:: SignedIntLit ( ast:: TyI , ast:: Plus ) ,
662
- 'u' => ty = ast:: UnsignedIntLit ( ast:: TyU ) ,
663
- '8' => {
664
- if s. len ( ) > 2 {
665
- match s. char_at ( last - 1 ) {
666
- 'i' => ty = ast:: SignedIntLit ( ast:: TyI8 , ast:: Plus ) ,
667
- 'u' => ty = ast:: UnsignedIntLit ( ast:: TyU8 ) ,
668
- _ => { }
669
- }
670
- }
671
- } ,
672
- '6' => {
673
- if s. len ( ) > 3 && s. char_at ( last - 1 ) == '1' {
674
- match s. char_at ( last - 2 ) {
675
- 'i' => ty = ast:: SignedIntLit ( ast:: TyI16 , ast:: Plus ) ,
676
- 'u' => ty = ast:: UnsignedIntLit ( ast:: TyU16 ) ,
677
- _ => { }
678
- }
679
- }
680
- } ,
681
- '2' => {
682
- if s. len ( ) > 3 && s. char_at ( last - 1 ) == '3' {
683
- match s. char_at ( last - 2 ) {
684
- 'i' => ty = ast:: SignedIntLit ( ast:: TyI32 , ast:: Plus ) ,
685
- 'u' => ty = ast:: UnsignedIntLit ( ast:: TyU32 ) ,
686
- _ => { }
687
- }
688
- }
689
- } ,
690
- '4' => {
691
- if s. len ( ) > 3 && s. char_at ( last - 1 ) == '6' {
692
- match s. char_at ( last - 2 ) {
693
- 'i' => ty = ast:: SignedIntLit ( ast:: TyI64 , ast:: Plus ) ,
694
- 'u' => ty = ast:: UnsignedIntLit ( ast:: TyU64 ) ,
695
- _ => { }
682
+ if let Some ( suf) = suffix {
683
+ if suf. is_empty ( ) { sd. span_bug ( sp, "found empty literal suffix in Some" ) }
684
+ ty = match suf {
685
+ "i" => ast:: SignedIntLit ( ast:: TyI , ast:: Plus ) ,
686
+ "i8" => ast:: SignedIntLit ( ast:: TyI8 , ast:: Plus ) ,
687
+ "i16" => ast:: SignedIntLit ( ast:: TyI16 , ast:: Plus ) ,
688
+ "i32" => ast:: SignedIntLit ( ast:: TyI32 , ast:: Plus ) ,
689
+ "i64" => ast:: SignedIntLit ( ast:: TyI64 , ast:: Plus ) ,
690
+ "u" => ast:: UnsignedIntLit ( ast:: TyU ) ,
691
+ "u8" => ast:: UnsignedIntLit ( ast:: TyU8 ) ,
692
+ "u16" => ast:: UnsignedIntLit ( ast:: TyU16 ) ,
693
+ "u32" => ast:: UnsignedIntLit ( ast:: TyU32 ) ,
694
+ "u64" => ast:: UnsignedIntLit ( ast:: TyU64 ) ,
695
+ _ => {
696
+ // i<digits> and u<digits> look like widths, so lets
697
+ // give an error message along those lines
698
+ if looks_like_width_suffix ( & [ 'i' , 'u' ] , suf) {
699
+ sd. span_err ( sp, & * format ! ( "illegal width `{}` for integer literal; \
700
+ valid widths are 8, 16, 32 and 64",
701
+ suf. slice_from( 1 ) ) ) ;
702
+ } else {
703
+ sd. span_err ( sp, & * format ! ( "illegal suffix `{}` for numeric literal" , suf) ) ;
696
704
}
705
+
706
+ ty
697
707
}
698
- } ,
699
- _ => { }
708
+ }
700
709
}
701
710
702
- debug ! ( "The suffix is {}, base {}, the new string is {}, the original \
703
- string was {}", ty, base, s, orig) ;
704
-
705
- s = s. slice_to ( s. len ( ) - ty. suffix_len ( ) ) ;
711
+ debug ! ( "integer_lit: the type is {}, base {}, the new string is {}, the original \
712
+ string was {}, the original suffix was {}", ty, base, s, orig, suffix) ;
706
713
707
714
let res: u64 = match :: std:: num:: from_str_radix ( s, base) {
708
715
Some ( r) => r,
0 commit comments