Mercurial > lbo > hg > rcombinators
changeset 31:ecfdbe1d1acb
Make JSON parser more lazy.
Not constructing parsers when they are not needed saves a lot of time.
author | Lewin Bormann <lewin@lewin-bormann.info> |
---|---|
date | Thu, 06 Jun 2019 23:53:28 +0200 |
parents | 9ef50316b2e7 |
children | 769ee1b73f31 |
files | examples/json/src/lib.rs src/combinators.rs |
diffstat | 2 files changed, 44 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/examples/json/src/lib.rs Thu Jun 06 23:52:51 2019 +0200 +++ b/examples/json/src/lib.rs Thu Jun 06 23:53:28 2019 +0200 @@ -34,7 +34,7 @@ ) -> ParseResult<Self::Result> { let dict = combinators::Lazy::new(dict); let list = combinators::Lazy::new(list); - combinators::Alternative::new((string(), number(), dict, list)).parse(st) + combinators::Alternative::new((string(), number(), list, dict)).parse(st) } } @@ -44,7 +44,7 @@ fn string() -> impl Parser<Result = Value> { let quote = primitives::StringParser::new("\""); - let middle = primitives::string_none_of("\"", combinators::RepeatSpec::Any); + let middle = combinators::Lazy::new(|| primitives::string_none_of("\"", combinators::RepeatSpec::Any)); let string_with_quotes = combinators::Sequence::new((quote.clone(), middle, quote)); let string = string_with_quotes.apply(|(_, s, _)| Ok(Value::String(s))); string @@ -55,18 +55,21 @@ primitives::StringParser::new("["), primitives::StringParser::new("]"), ); - let val = ValueParser; - let comma = primitives::StringParser::new(","); - let separated_element = combinators::Sequence::new(( - primitives::whitespace(), - val, - primitives::whitespace(), - combinators::Maybe::new(comma), - )); - let separated_element = separated_element.apply(|(_, v, _, _)| Ok(v)); - let separated_elements = - combinators::Repeat::new(separated_element, combinators::RepeatSpec::Any); - let list = combinators::Sequence::new((open, separated_elements, close)) + let inner = || { + let val = ValueParser; + let comma = primitives::StringParser::new(","); + let separated_element = combinators::Sequence::new(( + primitives::whitespace(), + val, + primitives::whitespace(), + combinators::Maybe::new(comma), + )); + let separated_element = separated_element.apply(|(_, v, _, _)| Ok(v)); + let separated_elements = + combinators::Repeat::new(separated_element, combinators::RepeatSpec::Any); + separated_elements + }; + let list = combinators::Sequence::new((open, combinators::Lazy::new(inner), close)) .apply(|(_, es, _)| Ok(Value::List(es))); list } @@ -76,28 +79,32 @@ primitives::StringParser::new("{"), primitives::StringParser::new("}"), ); - let comma = primitives::StringParser::new(","); - let sep = primitives::StringParser::new(":"); - let key = string().apply(|v| match v { - Value::String(s) => Ok(s), - _ => panic!("unexpected value type in string position"), - }); - let value = ValueParser; - let separated_element = combinators::Sequence::new(( - primitives::whitespace(), - key, - primitives::whitespace(), - sep, - primitives::whitespace(), - value, - primitives::whitespace(), - combinators::Maybe::new(comma), - )); - let separated_element = - separated_element.apply(|(_ws1, k, _ws2, _sep, _ws3, v, _ws4, _comma)| Ok((k, v))); - let separated_elements = - combinators::Repeat::new(separated_element, combinators::RepeatSpec::Any); - let dict = combinators::Sequence::new((open, separated_elements, close)) + + let inner = || { + let comma = primitives::StringParser::new(","); + let sep = primitives::StringParser::new(":"); + let key = string().apply(|v| match v { + Value::String(s) => Ok(s), + _ => panic!("unexpected value type in string position"), + }); + let value = ValueParser; + let separated_element = combinators::Sequence::new(( + primitives::whitespace(), + key, + primitives::whitespace(), + sep, + primitives::whitespace(), + value, + primitives::whitespace(), + combinators::Maybe::new(comma), + )); + let separated_element = + separated_element.apply(|(_ws1, k, _ws2, _sep, _ws3, v, _ws4, _comma)| Ok((k, v))); + let separated_elements = + combinators::Repeat::new(separated_element, combinators::RepeatSpec::Any); + separated_elements + }; + let dict = combinators::Sequence::new((open, combinators::Lazy::new(inner), close)) .apply(|(_, es, _)| Ok(Value::Dict(HashMap::from_iter(es.into_iter())))); dict }
--- a/src/combinators.rs Thu Jun 06 23:52:51 2019 +0200 +++ b/src/combinators.rs Thu Jun 06 23:53:28 2019 +0200 @@ -573,7 +573,7 @@ fn test_lazy3() { let mut i = 0; let mut ps = ParseState::new("123 124"); - let mut lzy = || { + let lzy = || { assert_eq!(0, i); i += 1; string_of("0123456789", RepeatSpec::Min(1))