diff --git a/src/lib.rs b/src/lib.rs index 64a623c..b00a4c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,8 @@ pub use parser::{ParseResult, Parser}; mod tests { use super::*; use crate::choice::choice; - use crate::primitives::literal; + use crate::primitives::{any_char, literal, literal_char, pred}; + use crate::sequence::seq; use std::collections::HashMap; #[test] @@ -42,10 +43,19 @@ mod tests { #[test] fn parse_json() { let json_null = literal("null").to(JsonValue::Null); - let json_true = literal("true").to(JsonValue::Bool(true)); - let json_false = literal("false").to(JsonValue::Bool(false)); + let json_bool = choice(( + literal("true").to(JsonValue::Bool(true)), + literal("false").to(JsonValue::Bool(false)), + )); - let json_value = choice((json_null, json_true, json_false)); + let json_string = seq(( + literal_char('"'), + pred(any_char, |ch| *ch != '"'), + literal_char('"'), + )) + .map(|(_, s, _)| JsonValue::Str(s.to_string())); + + let json_value = choice((json_null, json_bool, json_string)); assert_eq!(json_value.parse("true"), Ok((JsonValue::Bool(true), ""))); } diff --git a/src/primitives.rs b/src/primitives.rs index 2bce7ec..df5c25f 100644 --- a/src/primitives.rs +++ b/src/primitives.rs @@ -1,5 +1,12 @@ use crate::parser::{ParseResult, Parser}; +pub fn literal_char(expected: char) -> impl Fn(&str) -> ParseResult<&str, char, &str> { + move |input| match input.chars().next() { + Some(ch) if ch == expected => Ok((expected, &input[ch.len_utf8()..])), + _ => Err(input), + } +} + pub fn literal(expected: &'static str) -> impl Fn(&str) -> ParseResult<&str, &str, &str> { move |input| match input.get(0..expected.len()) { Some(next) if next == expected => Ok((expected, &input[expected.len()..])),