Hex, octal, binary integer literals
diff --git a/src/lit.rs b/src/lit.rs
index 131bd73..46f5cd9 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -317,32 +317,50 @@
IResult::Done(&input[len..], input[..len].into())
}
- pub fn digits(input: &str) -> IResult<&str, u64> {
+ pub fn digits(mut input: &str) -> IResult<&str, u64> {
+ let base = if input.starts_with("0x") {
+ input = &input[2..];
+ 16
+ } else if input.starts_with("0o") {
+ input = &input[2..];
+ 8
+ } else if input.starts_with("0b") {
+ input = &input[2..];
+ 2
+ } else {
+ 10
+ };
+
let mut value = 0u64;
let mut len = 0;
let mut empty = true;
for b in input.bytes() {
- match b {
- b'0'...b'9' => {
- value = match value.checked_mul(10) {
- Some(value) => value,
- None => return IResult::Error,
- };
- value = match value.checked_add((b - b'0') as u64) {
- Some(value) => value,
- None => return IResult::Error,
- };
- len += 1;
- empty = false;
- }
+ let digit = match b {
+ b'0'...b'9' => (b - b'0') as u64,
+ b'a'...b'f' => 10 + (b - b'a') as u64,
+ b'A'...b'F' => 10 + (b - b'A') as u64,
b'_' => {
if empty {
return IResult::Error;
}
len += 1;
+ continue;
}
_ => break,
+ };
+ if digit >= base {
+ return IResult::Error;
}
+ value = match value.checked_mul(base) {
+ Some(value) => value,
+ None => return IResult::Error,
+ };
+ value = match value.checked_add(digit) {
+ Some(value) => value,
+ None => return IResult::Error,
+ };
+ len += 1;
+ empty = false;
}
if empty {
IResult::Error