diff --git a/src/lib.rs b/src/lib.rs index a127619..0fd4ed5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub use parser::{ParseResult, Parser}; mod tests { use super::*; use crate::choice::choice; + use crate::combinators::{one_or_more, zero_or_more}; use crate::primitives::{any_char, literal, literal_char, one_of, pred}; use crate::sequence::seq; use std::collections::HashMap; @@ -48,8 +49,45 @@ mod tests { literal("false").to(JsonValue::Bool(false)), )); - let digit = one_of("1234567890"); - assert_eq!(digit.parse("3"), Ok(("3", ""))); + let digit = || one_of("1234567890"); + assert_eq!(digit().parse("3"), Ok(("3", ""))); + + let json_number_inner = choice(( + seq(( + one_or_more(digit()), + literal(".").then(zero_or_more(digit())).optional(), + )) + .map(|(mut digits, maybe_more)| { + if let Some((point, more)) = maybe_more { + digits.push(point); + digits.extend(more.into_iter()); + } + digits.into_iter().collect::() + }), + seq((literal("."), one_or_more(digit()))).map(|(_point, digits)| { + let mut d = vec!["."]; + d.extend(digits.into_iter()); + d.into_iter().collect::() + }), + )) + .map(|digits| digits.parse::().unwrap()); + + let json_number = + literal("-") + .optional() + .then(json_number_inner) + .map(|(maybe_sign, val)| { + if maybe_sign.is_some() { + val * -1.0 + } else { + val + } + }); + + assert_eq!(json_number.parse("-383").unwrap().0, -383f64); + assert_eq!(json_number.parse("-.383").unwrap().0, -0.383); + assert_eq!(json_number.parse(".383").unwrap().0, 0.383); + assert_eq!(json_number.parse("-1.383").unwrap().0, -1.383); let json_string = seq(( literal_char('"'),