@@ -511,28 +511,41 @@ pub fn raw_str_lit(lit: &str) -> String {
511511 res
512512}
513513
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+ }
527520
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+ }
528536
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)
534540 }
535541}
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+ }
536549
537550/// Parse a string representing a byte literal into its final form. Similar to `char_lit`
538551pub fn byte_lit ( lit : & str ) -> ( u8 , uint ) {
@@ -626,24 +639,19 @@ pub fn binary_lit(lit: &str) -> Rc<Vec<u8>> {
626639 Rc :: new ( res)
627640}
628641
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_ {
630643 // s can only be ascii, byte indexing is fine
631644
632645 let s2 = s. chars ( ) . filter ( |& c| c != '_' ) . collect :: < String > ( ) ;
633646 let mut s = s2. as_slice ( ) ;
634647
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) ;
641649
642650 let mut base = 10 ;
643651 let orig = s;
644652 let mut ty = ast:: UnsuffixedIntLit ( ast:: Plus ) ;
645653
646- if s. char_at ( 0 ) == '0' {
654+ if s. char_at ( 0 ) == '0' && s . len ( ) > 1 {
647655 match s. char_at ( 1 ) {
648656 'x' => base = 16 ,
649657 'o' => base = 8 ,
@@ -652,57 +660,56 @@ pub fn integer_lit(s: &str, sd: &SpanHandler, sp: Span) -> ast::Lit_ {
652660 }
653661 }
654662
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+
655678 if base != 10 {
656679 s = s. slice_from ( 2 ) ;
657680 }
658681
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) ) ;
696704 }
705+
706+ ty
697707 }
698- } ,
699- _ => { }
708+ }
700709 }
701710
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) ;
706713
707714 let res: u64 = match :: std:: num:: from_str_radix ( s, base) {
708715 Some ( r) => r,
0 commit comments