From 4f5c94891a9b398711c68ee5834806fcc81f2a37 Mon Sep 17 00:00:00 2001 From: Jordan Santell Date: Fri, 10 Feb 2017 16:03:35 -0800 Subject: [PATCH] Add octal, hexadecimal, and arbitrary base integers to the EDN parser. Fixes #277. r=rnewman (#286) --- edn/src/edn.rustpeg | 22 +++++++++++++++++++++- edn/tests/tests.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/edn/src/edn.rustpeg b/edn/src/edn.rustpeg index 71e95d09..7363f05a 100644 --- a/edn/src/edn.rustpeg +++ b/edn/src/edn.rustpeg @@ -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::().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::().unwrap()).unwrap()) + } + pub integer -> Value = i:$( sign? digit+ ) { Value::Integer(i.parse::().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 } diff --git a/edn/tests/tests.rs b/edn/tests/tests.rs index 04b4ac72..3c5f3693 100644 --- a/edn/tests/tests.rs +++ b/edn/tests/tests.rs @@ -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]