11use nom:: {
22 branch:: alt,
3+ bytes:: complete:: tag,
34 character:: complete:: { one_of, space0} ,
45 combinator:: { map_res, opt, recognize} ,
56 multi:: { many0, many1} ,
@@ -13,18 +14,39 @@ use internal_macro::{test_parser, test_parser_error};
1314use nom:: character:: complete:: char;
1415
1516use super :: * ;
16- #[ test_parser_error( "_10" ) ]
1717#[ test_parser( ".10" ) ]
1818#[ test_parser( "10.10" ) ]
1919#[ test_parser( "10" ) ]
20- #[ test_parser( "10_00_3" ) ]
20+ #[ test_parser( "10_00__3" ) ]
21+ #[ test_parser( "0X1a" ) ]
22+ #[ test_parser( "0o17" ) ]
23+ #[ test_parser( "0b101" ) ]
24+ #[ test_parser_error( "_10" ) ]
2125#[ test_parser_error( "10." ) ]
26+ #[ test_parser_error( "0x12g3" ) ]
27+ #[ test_parser_error( "0o12.3" ) ]
28+ #[ test_parser_error( "0b123" ) ]
2229pub fn number ( input : Span ) -> IResult < Span , Box < NodeEnum > > {
2330 let ( input, _) = space0 ( input) ?;
2431 let ( re, value) = alt ( (
2532 map_res ( float, |out| {
2633 Ok :: < Num , ( ) > ( Num :: Float ( out. fragment ( ) . parse :: < f64 > ( ) . unwrap ( ) ) )
2734 } ) ,
35+ map_res ( hexadecimal, |out| {
36+ let res =
37+ u64:: from_str_radix ( out. fragment ( ) . replace ( '_' , "" ) . get ( 2 ..) . unwrap ( ) , 16 ) . unwrap ( ) ;
38+ Ok :: < Num , ( ) > ( Num :: Int ( res) )
39+ } ) ,
40+ map_res ( octal, |out| {
41+ let res =
42+ u64:: from_str_radix ( out. fragment ( ) . replace ( '_' , "" ) . get ( 2 ..) . unwrap ( ) , 8 ) . unwrap ( ) ;
43+ Ok :: < Num , ( ) > ( Num :: Int ( res) )
44+ } ) ,
45+ map_res ( binary, |out| {
46+ let res =
47+ u64:: from_str_radix ( out. fragment ( ) . replace ( '_' , "" ) . get ( 2 ..) . unwrap ( ) , 2 ) . unwrap ( ) ;
48+ Ok :: < Num , ( ) > ( Num :: Int ( res) )
49+ } ) ,
2850 map_res ( decimal, |out| {
2951 // TODO:err tolerate
3052 Ok :: < Num , ( ) > ( Num :: Int (
@@ -73,6 +95,44 @@ fn decimal(input: Span) -> IResult<Span, Span> {
7395 recognize ( many1 ( terminated ( one_of ( "0123456789" ) , many0 ( char ( '_' ) ) ) ) ) ( input)
7496}
7597
98+ #[ test_parser( "0x10" ) ]
99+ #[ test_parser( "0X1a3" ) ]
100+ #[ test_parser( "0x1_2__3" ) ]
101+ #[ test_parser_error( "x123" ) ]
102+ #[ test_parser_error( "0x12g3" ) ]
103+ fn hexadecimal ( input : Span ) -> IResult < Span , Span > {
104+ recognize ( preceded (
105+ alt ( ( tag ( "0x" ) , tag ( "0X" ) ) ) ,
106+ many1 ( terminated (
107+ one_of ( "0123456789abcdefABCDEF" ) ,
108+ many0 ( char ( '_' ) ) ,
109+ ) ) ,
110+ ) ) ( input)
111+ }
112+
113+ #[ test_parser( "0o10" ) ]
114+ #[ test_parser( "0O173" ) ]
115+ #[ test_parser( "0o1_2__3" ) ]
116+ #[ test_parser_error( "o123" ) ]
117+ #[ test_parser_error( "0o1283" ) ]
118+ fn octal ( input : Span ) -> IResult < Span , Span > {
119+ recognize ( preceded (
120+ alt ( ( tag ( "0o" ) , tag ( "0O" ) ) ) ,
121+ many1 ( terminated ( one_of ( "01234567" ) , many0 ( char ( '_' ) ) ) ) ,
122+ ) ) ( input)
123+ }
124+
125+ #[ test_parser( "0b101" ) ]
126+ #[ test_parser( "0B0_01_" ) ]
127+ #[ test_parser_error( "B001" ) ]
128+ #[ test_parser_error( "0b0201" ) ]
129+ fn binary ( input : Span ) -> IResult < Span , Span > {
130+ recognize ( preceded (
131+ alt ( ( tag ( "0b" ) , tag ( "0B" ) ) ) ,
132+ many1 ( terminated ( one_of ( "01" ) , many0 ( char ( '_' ) ) ) ) ,
133+ ) ) ( input)
134+ }
135+
76136#[ test_parser( ".12" ) ]
77137#[ test_parser( ".1_2" ) ]
78138#[ test_parser( ".12e1" ) ]
0 commit comments