Add octal, hexadecimal, and arbitrary base integers to the EDN parser. Fixes #277. r=rnewman (#286)

This commit is contained in:
Jordan Santell 2017-02-10 16:03:35 -08:00 committed by GitHub
parent 6ce5d526a3
commit 4f5c94891a
2 changed files with 51 additions and 1 deletions

View file

@ -44,6 +44,10 @@ pub boolean -> Value =
"false" { Value::Boolean(false) }
digit = [0-9]
alphanumeric = [0-9a-zA-Z]
octaldigit = [0-7]
validbase = [3][0-6] / [12][0-9] / [2-9]
hex = [0-9a-fA-F]
sign = "-" / "+"
pub bigint -> Value =
@ -51,6 +55,22 @@ pub bigint -> Value =
Value::BigInteger(b.parse::<BigInt>().unwrap())
}
pub octalinteger -> Value =
"0" i:$( octaldigit+ ) {
Value::Integer(i64::from_str_radix(i, 8).unwrap())
}
pub hexinteger -> Value =
"0x" i:$( hex+ ) {
Value::Integer(i64::from_str_radix(i, 16).unwrap())
}
pub basedinteger -> Value =
// Only allow values 2-36
b:$( validbase ) "r" i:$( alphanumeric+ ) {
Value::Integer(i64::from_str_radix(i, b.parse::<u32>().unwrap()).unwrap())
}
pub integer -> Value =
i:$( sign? digit+ ) {
Value::Integer(i.parse::<i64>().unwrap())
@ -134,7 +154,7 @@ pub map -> Value =
// It's important that float comes before integer or the parser assumes that
// floats are integers and fails to parse
pub value -> Value =
__ v:(nil / nan / infinity / boolean / float / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
__ v:(nil / nan / infinity / boolean / float / octalinteger / hexinteger / basedinteger / bigint / integer / text / keyword / symbol / list / vector / map / set) __ {
v
}

View file

@ -101,6 +101,33 @@ fn test_integer() {
assert!(integer("nil").is_err());
}
#[test]
fn test_hexinteger() {
assert_eq!(hexinteger("0xabc111").unwrap(), Integer(11256081));
assert_eq!(hexinteger("0xABCDEF").unwrap(), Integer(11259375));
assert_eq!(hexinteger("0xabcdef").unwrap(), Integer(11259375));
assert!(hexinteger("nil").is_err());
assert!(hexinteger("0xZZZ").is_err());
}
#[test]
fn test_basedinteger() {
assert_eq!(basedinteger("2r111").unwrap(), Integer(7));
assert_eq!(basedinteger("36r1z").unwrap(), Integer(71));
assert_eq!(basedinteger("36r1Z").unwrap(), Integer(71));
assert_eq!(basedinteger("12r11").unwrap(), Integer(13));
assert_eq!(basedinteger("24r10").unwrap(), Integer(24));
assert!(basedinteger("nil").is_err());
}
#[test]
fn test_octalinteger() {
assert_eq!(octalinteger("011").unwrap(), Integer(9));
assert_eq!(octalinteger("00107").unwrap(), Integer(71));
}
#[test]
fn test_bigint() {
let max_i64 = i64::max_value().to_bigint().unwrap();
@ -186,6 +213,9 @@ fn test_value() {
assert_eq!(value("[1]").unwrap(), Vector(vec![Integer(1)]));
assert_eq!(value("111.222").unwrap(), Float(OrderedFloat(111.222f64)));
assert_eq!(value("85070591730234615847396907784232501249N").unwrap(), BigInteger(bigger));
assert_eq!(value("0xabc111").unwrap(), Integer(11256081));
assert_eq!(value("2r111").unwrap(), Integer(7));
assert_eq!(value("011").unwrap(), Integer(9));
}
#[test]