Skip to content

Commit cf77ad2

Browse files
authored
feat: hexadecimal & binary number (#389)
* feat: hexadecimal & binary number * fix: clippy * feat: octal number * tests: add some tests
1 parent a775a65 commit cf77ad2

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

src/nomparser/constval.rs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use 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};
1314
use nom::character::complete::char;
1415

1516
use 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")]
2229
pub 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")]

test/test/simple.pi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,17 @@ pub fn test_primitives() void {
1515
let utest: u8 = 1;
1616
utest = utest + 2;
1717
test = 127;
18+
panic::assert(test == 0x7f);
19+
panic::assert(test == 0o177);
20+
panic::assert(test == 0b0111_1111);
1821
test = -test - 1;
22+
panic::assert(test == 0x80);
23+
panic::assert(test == 0o200);
24+
panic::assert(test == 0b1000_0000);
1925
panic::assert(test as i64 == -128);
26+
panic::assert(test as i64 == 0xffff_ffff_ffff_ff80);
27+
panic::assert(test as i64 == 0o1777777777777777777600);
28+
panic::assert(test as i64 == 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_10000000);
2029
let b = test | 1;
2130
panic::assert(b as i64 == -127);
2231
let c = test & 1;

0 commit comments

Comments
 (0)