1
1
//! Parsers recognizing numbers, complete input version
2
2
3
+ use core:: { f32, f64} ;
3
4
use crate :: branch:: alt;
4
5
use crate :: bytes:: complete:: tag;
5
6
use crate :: character:: complete:: { char, digit1, sign} ;
@@ -1426,11 +1427,13 @@ where
1426
1427
) ( input)
1427
1428
}
1428
1429
1430
+ ///
1431
+
1429
1432
/// Recognizes a floating point number in text format and returns the integer, fraction and exponent parts of the input data
1430
1433
///
1431
1434
/// *Complete version*: Can parse until the end of input.
1432
1435
///
1433
- pub fn recognize_float_parts < T , E : ParseError < T > > ( input : T ) -> IResult < T , ( bool , T , T , i32 ) , E >
1436
+ pub fn recognize_float_parts < T , E : ParseError < T > > ( input : T ) -> IResult < T , ( T , T , i32 ) , E >
1434
1437
where
1435
1438
T : Slice < RangeFrom < usize > > + Slice < RangeTo < usize > > + Slice < Range < usize > > ,
1436
1439
T : Clone + Offset ,
@@ -1441,8 +1444,7 @@ where
1441
1444
T : for < ' a > Compare < & ' a [ u8 ] > ,
1442
1445
T : AsBytes ,
1443
1446
{
1444
- let ( i, sign) = sign ( input. clone ( ) ) ?;
1445
-
1447
+ let i = input. clone ( ) ;
1446
1448
//let (i, zeroes) = take_while(|c: <T as InputTakeAtPosition>::Item| c.as_char() == '0')(i)?;
1447
1449
let ( i, zeroes) = match i. as_bytes ( ) . iter ( ) . position ( |c| * c != b'0' as u8 ) {
1448
1450
Some ( index) => i. take_split ( index) ,
@@ -1514,7 +1516,79 @@ where
1514
1516
( i2, 0 )
1515
1517
} ;
1516
1518
1517
- Ok ( ( i, ( sign, integer, fraction, exp) ) )
1519
+ Ok ( ( i, ( integer, fraction, exp) ) )
1520
+ }
1521
+
1522
+ macro_rules! float_finite {
1523
+ ( $input: ident, $t: ty) => { {
1524
+ let ( i, ( integer, fraction, exponent) ) = recognize_float_parts( $input) ?;
1525
+
1526
+ let float: $t = minimal_lexical:: parse_float(
1527
+ integer. as_bytes( ) . iter( ) ,
1528
+ fraction. as_bytes( ) . iter( ) ,
1529
+ exponent,
1530
+ ) ;
1531
+
1532
+ Ok ( ( i, float) )
1533
+ } } ;
1534
+ }
1535
+
1536
+ macro_rules! float_nonfinite {
1537
+ ( $input: ident, $t: ty) => { {
1538
+ let b = $input. as_bytes( ) ;
1539
+ let ( float, count) = if b. len( ) >= 3 {
1540
+ if crate :: number:: case_insensitive_cmp( b, b"nan" ) {
1541
+ ( <$t>:: NAN , 3 )
1542
+ } else if b. len( ) >= 8 && crate :: number:: case_insensitive_cmp( b, b"infinity" ) {
1543
+ ( <$t>:: INFINITY , 8 )
1544
+ } else if crate :: number:: case_insensitive_cmp( b, b"inf" ) {
1545
+ ( <$t>:: INFINITY , 3 )
1546
+ } else {
1547
+ return Err ( Err :: Error ( E :: from_error_kind( $input, ErrorKind :: Float ) ) ) ;
1548
+ }
1549
+ } else {
1550
+ return Err ( Err :: Error ( E :: from_error_kind( $input, ErrorKind :: Float ) ) ) ;
1551
+ } ;
1552
+
1553
+ Ok ( ( $input. slice( count..) , float) )
1554
+ } } ;
1555
+ }
1556
+
1557
+ /// Recognizes floating point number in text format and returns a f32.
1558
+ ///
1559
+ /// *Complete version*: Can parse until the end of input. This only handles
1560
+ /// finite (non-special floats).
1561
+ /// ```
1562
+ pub fn float_finite < T , E : ParseError < T > > ( input : T ) -> IResult < T , f32 , E >
1563
+ where
1564
+ T : Slice < RangeFrom < usize > > + Slice < RangeTo < usize > > + Slice < Range < usize > > ,
1565
+ T : Clone + Offset ,
1566
+ T : InputIter + InputLength + InputTake ,
1567
+ <T as InputIter >:: Item : AsChar + Copy ,
1568
+ <T as InputIter >:: IterElem : Clone ,
1569
+ T : InputTakeAtPosition ,
1570
+ <T as InputTakeAtPosition >:: Item : AsChar ,
1571
+ T : AsBytes ,
1572
+ T : for < ' a > Compare < & ' a [ u8 ] > ,
1573
+ {
1574
+ float_finite ! ( input, f32 )
1575
+ }
1576
+
1577
+ /// Recognizes floating point number in text format and returns a f32.
1578
+ /// This only handles non-finite (special) values.
1579
+ pub fn float_nonfinite < T , E : ParseError < T > > ( input : T ) -> IResult < T , f32 , E >
1580
+ where
1581
+ T : Slice < RangeFrom < usize > > + Slice < RangeTo < usize > > + Slice < Range < usize > > ,
1582
+ T : Clone + Offset ,
1583
+ T : InputIter + InputLength + InputTake ,
1584
+ <T as InputIter >:: Item : AsChar + Copy ,
1585
+ <T as InputIter >:: IterElem : Clone ,
1586
+ T : InputTakeAtPosition ,
1587
+ <T as InputTakeAtPosition >:: Item : AsChar ,
1588
+ T : AsBytes ,
1589
+ T : for < ' a > Compare < & ' a [ u8 ] > ,
1590
+ {
1591
+ float_nonfinite ! ( input, f32 )
1518
1592
}
1519
1593
1520
1594
/// Recognizes floating point number in text format and returns a f32.
@@ -1546,30 +1620,62 @@ where
1546
1620
T : AsBytes ,
1547
1621
T : for < ' a > Compare < & ' a [ u8 ] > ,
1548
1622
{
1549
- let ( i, ( sign, integer, fraction, exponent) ) = recognize_float_parts ( input) ?;
1623
+ let ( input, sign) = sign ( input. clone ( ) ) ?;
1624
+ let res = float_finite :: < T , E > ( input. clone ( ) ) ;
1625
+ let ( i, mut float) = res. or ( float_nonfinite :: < T , E > ( input) ) ?;
1550
1626
1551
- let mut float: f32 = minimal_lexical:: parse_float (
1552
- integer. as_bytes ( ) . iter ( ) ,
1553
- fraction. as_bytes ( ) . iter ( ) ,
1554
- exponent,
1555
- ) ;
1556
1627
if !sign {
1557
1628
float = -float;
1558
1629
}
1559
-
1560
1630
Ok ( ( i, float) )
1561
1631
}
1562
1632
1563
- /// Recognizes floating point number in text format and returns a f32.
1633
+ /// Recognizes floating point number in text format and returns a f64.
1634
+ ///
1635
+ /// *Complete version*: Can parse until the end of input. This only handles
1636
+ /// finite (non-special floats).
1637
+ pub fn double_finite < T , E : ParseError < T > > ( input : T ) -> IResult < T , f64 , E >
1638
+ where
1639
+ T : Slice < RangeFrom < usize > > + Slice < RangeTo < usize > > + Slice < Range < usize > > ,
1640
+ T : Clone + Offset ,
1641
+ T : InputIter + InputLength + InputTake ,
1642
+ <T as InputIter >:: Item : AsChar + Copy ,
1643
+ <T as InputIter >:: IterElem : Clone ,
1644
+ T : InputTakeAtPosition ,
1645
+ <T as InputTakeAtPosition >:: Item : AsChar ,
1646
+ T : AsBytes ,
1647
+ T : for < ' a > Compare < & ' a [ u8 ] > ,
1648
+ {
1649
+ float_finite ! ( input, f64 )
1650
+ }
1651
+
1652
+ /// Recognizes floating point number in text format and returns a f64.
1653
+ /// This only handles non-finite (special) values.
1654
+ pub fn double_nonfinite < T , E : ParseError < T > > ( input : T ) -> IResult < T , f64 , E >
1655
+ where
1656
+ T : Slice < RangeFrom < usize > > + Slice < RangeTo < usize > > + Slice < Range < usize > > ,
1657
+ T : Clone + Offset ,
1658
+ T : InputIter + InputLength + InputTake ,
1659
+ <T as InputIter >:: Item : AsChar + Copy ,
1660
+ <T as InputIter >:: IterElem : Clone ,
1661
+ T : InputTakeAtPosition ,
1662
+ <T as InputTakeAtPosition >:: Item : AsChar ,
1663
+ T : AsBytes ,
1664
+ T : for < ' a > Compare < & ' a [ u8 ] > ,
1665
+ {
1666
+ float_nonfinite ! ( input, f64 )
1667
+ }
1668
+
1669
+ /// Recognizes floating point number in text format and returns a f64.
1564
1670
///
1565
1671
/// *Complete version*: Can parse until the end of input.
1566
1672
/// ```rust
1567
1673
/// # use nom::{Err, error::ErrorKind, Needed};
1568
1674
/// # use nom::Needed::Size;
1569
- /// use nom::number::complete::float ;
1675
+ /// use nom::number::complete::double ;
1570
1676
///
1571
1677
/// let parser = |s| {
1572
- /// float (s)
1678
+ /// double (s)
1573
1679
/// };
1574
1680
///
1575
1681
/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
@@ -1589,18 +1695,14 @@ where
1589
1695
T : AsBytes ,
1590
1696
T : for < ' a > Compare < & ' a [ u8 ] > ,
1591
1697
{
1592
- let ( i, ( sign, integer, fraction, exponent) ) = recognize_float_parts ( input) ?;
1698
+ let ( input, sign) = sign ( input. clone ( ) ) ?;
1699
+ let res = double_finite :: < T , E > ( input. clone ( ) ) ;
1700
+ let ( i, mut double) = res. or ( double_nonfinite :: < T , E > ( input) ) ?;
1593
1701
1594
- let mut float: f64 = minimal_lexical:: parse_float (
1595
- integer. as_bytes ( ) . iter ( ) ,
1596
- fraction. as_bytes ( ) . iter ( ) ,
1597
- exponent,
1598
- ) ;
1599
1702
if !sign {
1600
- float = -float ;
1703
+ double = -double ;
1601
1704
}
1602
-
1603
- Ok ( ( i, float) )
1705
+ Ok ( ( i, double) )
1604
1706
}
1605
1707
1606
1708
#[ cfg( test) ]
@@ -1618,6 +1720,23 @@ mod tests {
1618
1720
} ;
1619
1721
) ;
1620
1722
1723
+ // Need more complex logic, since NaN != NaN.
1724
+ macro_rules! assert_float_eq {
1725
+ ( $left: expr, $right: expr) => {
1726
+ let left: $crate:: IResult <_, _, ( _, ErrorKind ) > = $left;
1727
+ let right: $crate:: IResult <_, _, ( _, ErrorKind ) > = $right;
1728
+ if let Ok ( ( _, float) ) = right {
1729
+ if float. is_nan( ) {
1730
+ assert!( left. unwrap( ) . 1 . is_nan( ) ) ;
1731
+ } else {
1732
+ assert_eq!( left, right) ;
1733
+ }
1734
+ } else {
1735
+ assert_eq!( left, right) ;
1736
+ }
1737
+ } ;
1738
+ }
1739
+
1621
1740
#[ test]
1622
1741
fn i8_tests ( ) {
1623
1742
assert_parse ! ( i8 ( & [ 0x00 ] [ ..] ) , Ok ( ( & b"" [ ..] , 0 ) ) ) ;
@@ -1942,6 +2061,8 @@ mod tests {
1942
2061
"12.34" ,
1943
2062
"-1.234E-12" ,
1944
2063
"-1.234e-12" ,
2064
+ "NaN" ,
2065
+ "inf" ,
1945
2066
] ;
1946
2067
1947
2068
for test in test_cases. drain ( ..) {
@@ -1951,15 +2072,24 @@ mod tests {
1951
2072
println ! ( "now parsing: {} -> {}" , test, expected32) ;
1952
2073
1953
2074
let larger = format ! ( "{}" , test) ;
1954
- assert_parse ! ( recognize_float( & larger[ ..] ) , Ok ( ( "" , test) ) ) ;
2075
+ if expected32. is_finite ( ) {
2076
+ assert_parse ! ( recognize_float( & larger[ ..] ) , Ok ( ( "" , test) ) ) ;
2077
+ }
1955
2078
1956
- assert_parse ! ( float( larger. as_bytes( ) ) , Ok ( ( & b"" [ ..] , expected32) ) ) ;
1957
- assert_parse ! ( float( & larger[ ..] ) , Ok ( ( "" , expected32) ) ) ;
2079
+ assert_float_eq ! ( float( larger. as_bytes( ) ) , Ok ( ( & b"" [ ..] , expected32) ) ) ;
2080
+ assert_float_eq ! ( float( & larger[ ..] ) , Ok ( ( "" , expected32) ) ) ;
1958
2081
1959
- assert_parse ! ( double( larger. as_bytes( ) ) , Ok ( ( & b"" [ ..] , expected64) ) ) ;
1960
- assert_parse ! ( double( & larger[ ..] ) , Ok ( ( "" , expected64) ) ) ;
2082
+ assert_float_eq ! ( double( larger. as_bytes( ) ) , Ok ( ( & b"" [ ..] , expected64) ) ) ;
2083
+ assert_float_eq ! ( double( & larger[ ..] ) , Ok ( ( "" , expected64) ) ) ;
1961
2084
}
1962
2085
2086
+ // b"infinity" and case-insensitive floats don't work until recent
2087
+ // rustc versions, so just test they work here.
2088
+ assert_float_eq ! ( float( "nan" . as_bytes( ) ) , Ok ( ( & b"" [ ..] , f32 :: NAN ) ) ) ;
2089
+ assert_float_eq ! ( float( "infinity" . as_bytes( ) ) , Ok ( ( & b"" [ ..] , f32 :: INFINITY ) ) ) ;
2090
+ assert_float_eq ! ( double( "nan" . as_bytes( ) ) , Ok ( ( & b"" [ ..] , f64 :: NAN ) ) ) ;
2091
+ assert_float_eq ! ( double( "infinity" . as_bytes( ) ) , Ok ( ( & b"" [ ..] , f64 :: INFINITY ) ) ) ;
2092
+
1963
2093
let remaining_exponent = "-1.234E-" ;
1964
2094
assert_parse ! (
1965
2095
recognize_float( remaining_exponent) ,
@@ -2051,8 +2181,8 @@ mod tests {
2051
2181
}
2052
2182
2053
2183
fn parse_f64 ( i : & str ) -> IResult < & str , f64 , ( ) > {
2054
- match recognize_float ( i) {
2055
- Err ( e ) => Err ( e ) ,
2184
+ match recognize_float :: < _ , ( ) > ( i) {
2185
+ Err ( _ ) => Err ( Err :: Error ( ( ) ) ) ,
2056
2186
Ok ( ( i, s) ) => {
2057
2187
if s. is_empty ( ) {
2058
2188
return Err ( Err :: Error ( ( ) ) ) ;
0 commit comments