diff --git a/.travis.yml b/.travis.yml index 1610946d..3dc4d635 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,8 @@ language: rust sudo: false rust: - - stable - - beta + # We require nightly for conservative_impl_trait, unboxed_closures and fn_traits - nightly - # Minimum supported version (bitflags fails on 1.7 due to op_assign_traits not being stable): - - 1.8.0 # necessary for `travis-cargo coveralls --no-sudo` addons: diff --git a/Cargo.toml b/Cargo.toml index 229f4d80..1e2e3d0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,11 +22,11 @@ include = [ ] [dependencies] -bitflags = "0.7.0" +bitflags = "0.9.0" conv = { version = "0.3.3", default-features = false, features = ["std"] } -either = { version = "0.1.7" } +either = { version = "1.1.0" } debugtrace = { version = "0.1.0" } -tendril = { version = "0.2.2", optional = true } +tendril = { version = "0.3.0", optional = true } # Technically a dev-dependency, but dev-dependencies are not allowed to be optional, # compiletest_rs fails to compile on stable and beta diff --git a/README.md b/README.md index 85c71987..f2cc3e22 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Chomp is a fast monadic-style parser combinator library designed to work on stab For its current capabilities, you will find that Chomp performs consistently as well, if not better, than optimized C parsers, while being vastly more expressive. For an example that builds a performant HTTP parser out of smaller parsers, see [http_parser.rs](examples/http_parser.rs). -##Installation +## Installation Add the following line to the dependencies section of your `Cargo.toml`: @@ -24,7 +24,7 @@ Add the following line to the dependencies section of your `Cargo.toml`: chomp = "0.3.1" ``` -##Usage +## Usage Parsers are functions from a slice over an input type `Input` to a `ParseResult`, which may be thought of as either a success resulting in type `T`, an error of type `E`, or a partially completed result which may still consume more input of type `I`. @@ -125,6 +125,6 @@ Unless you explicitly state otherwise, any contribution intentionally submitted the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. -##Contact +## Contact File an issue [here](https://github.com/m4rw3r/chomp/issues/new) on Github or visit [gitter.im/m4rw3r/chomp](https://gitter.im/m4rw3r/chomp). diff --git a/benches/combinators.rs b/benches/combinators.rs index 9ea72105..5c364f2a 100644 --- a/benches/combinators.rs +++ b/benches/combinators.rs @@ -1,3 +1,4 @@ +#![feature(conservative_impl_trait)] #![feature(test)] extern crate test; #[macro_use] @@ -14,12 +15,12 @@ use chomp::buffer::InputBuf; fn count_vec_1k(b: &mut Bencher) { let data = iter::repeat(b'a').take(1024).collect::>(); - fn count_vec(i: I) -> ParseResult, Error> { - count(i, 1024, any) + fn count_vec() -> impl Parser, Error=Error> { + count(1024, any) } b.iter(|| { - parse_only(count_vec, &data) + count_vec().parse(&data[..]) }) } @@ -27,12 +28,12 @@ fn count_vec_1k(b: &mut Bencher) { fn count_vec_10k(b: &mut Bencher) { let data = iter::repeat(b'a').take(10240).collect::>(); - fn count_vec(i: I) -> ParseResult, Error> { - count(i, 10240, any) + fn count_vec() -> impl Parser, Error=Error> { + count(10240, any) } b.iter(|| { - parse_only(count_vec, &data) + count_vec().parse(&data[..]) }) } @@ -40,12 +41,12 @@ fn count_vec_10k(b: &mut Bencher) { fn many_vec_1k(b: &mut Bencher) { let data = iter::repeat(b'a').take(1024).collect::>(); - fn many_vec(i: I) -> ParseResult, Error> { - many(i, any) + fn many_vec() -> impl Parser, Error=Error> { + many(any) } b.iter(|| { - parse_only(many_vec, &data) + many_vec().parse(&data[..]) }) } @@ -53,12 +54,12 @@ fn many_vec_1k(b: &mut Bencher) { fn many_vec_10k(b: &mut Bencher) { let data = iter::repeat(b'a').take(10024).collect::>(); - fn many_vec(i: I) -> ParseResult, Error> { - many(i, any) + fn many_vec() -> impl Parser, Error=Error> { + many(any) } b.iter(|| { - parse_only(many_vec, &data) + many_vec().parse(&data[..]) }) } @@ -66,12 +67,12 @@ fn many_vec_10k(b: &mut Bencher) { fn many1_vec_1k(b: &mut Bencher) { let data = iter::repeat(b'a').take(1024).collect::>(); - fn many1_vec(i: I) -> ParseResult, Error> { - many1(i, any) + fn many1_vec() -> impl Parser, Error=Error> { + many1(any) } b.iter(|| { - parse_only(many1_vec, &data) + many1_vec().parse(&data[..]) }) } @@ -79,12 +80,12 @@ fn many1_vec_1k(b: &mut Bencher) { fn many1_vec_10k(b: &mut Bencher) { let data = iter::repeat(b'a').take(10024).collect::>(); - fn many1_vec(i: I) -> ParseResult, Error> { - many1(i, any) + fn many1_vec() -> impl Parser, Error=Error> { + many1(any) } b.iter(|| { - parse_only(many1_vec, &data) + many1_vec().parse(&data[..]) }) } @@ -92,12 +93,12 @@ fn many1_vec_10k(b: &mut Bencher) { fn count_vec_10k_maybe_incomplete(b: &mut Bencher) { let data = iter::repeat(b'a').take(10024).collect::>(); - fn count_vec(i: I) -> ParseResult, Error> { - count(i, 10024, any) + fn count_vec() -> impl Parser, Error=Error> { + count(10024, any) } b.iter(|| { - count_vec(InputBuf::new(&data)) + count_vec().parse(InputBuf::new(&data)) }) } @@ -105,12 +106,12 @@ fn count_vec_10k_maybe_incomplete(b: &mut Bencher) { fn many_vec_10k_maybe_incomplete(b: &mut Bencher) { let data = iter::repeat(b'a').take(10024).collect::>(); - fn many_vec(i: I) -> ParseResult, Error> { - many(i, any) + fn many_vec() -> impl Parser, Error=Error> { + many(any) } b.iter(|| { - many_vec(InputBuf::new(&data)) + many_vec().parse(InputBuf::new(&data)) }) } @@ -118,11 +119,11 @@ fn many_vec_10k_maybe_incomplete(b: &mut Bencher) { fn many1_vec_10k_maybe_incomplete(b: &mut Bencher) { let data = iter::repeat(b'a').take(10024).collect::>(); - fn many1_vec(i: I) -> ParseResult, Error> { - many1(i, any) + fn many1_vec() -> impl Parser, Error=Error> { + many1(any) } b.iter(|| { - many1_vec(InputBuf::new(&data)) + many1_vec().parse(InputBuf::new(&data)) }) } diff --git a/benches/http_bench.rs b/benches/http_bench.rs index e157990e..c045fd1e 100644 --- a/benches/http_bench.rs +++ b/benches/http_bench.rs @@ -1,4 +1,6 @@ #![feature(test)] +#![feature(trace_macros)] +#![feature(conservative_impl_trait)] extern crate test; #[macro_use] extern crate chomp; @@ -51,65 +53,66 @@ fn is_not_space(c: u8) -> bool { c != b' ' } fn is_end_of_line(c: u8) -> bool { c == b'\r' || c == b'\n' } fn is_http_version(c: u8) -> bool { c >= b'0' && c <= b'9' || c == b'.' } -fn end_of_line(i: I) -> SimpleResult { - parse!{i; (token(b'\r') <|> ret b'\0') >> token(b'\n')} +fn end_of_line>() -> impl Parser> { + parse!{(token(b'\r') <|> ret(b'\0')) >> token(b'\n')} } -fn http_version(i: I) -> SimpleResult { - parse!{i; +fn http_version>() -> impl Parser> { + parse!{ string(b"HTTP/"); take_while1(is_http_version) } } -fn request_line(i: I) -> SimpleResult> { - parse!{i; +fn request_line>() -> impl Parser, Error=Error> { + parse!{ let method = take_while1(is_token); take_while1(is_space); let uri = take_while1(is_not_space); take_while1(is_space); let version = http_version(); - ret Request { + ret(Request { method: method, uri: uri, version: version, - } + }) } } -fn message_header_line(i: I) -> SimpleResult { - parse!{i; +fn message_header_line>() -> impl Parser> { + parse!{ take_while1(is_horizontal_space); let line = take_till(is_end_of_line); end_of_line(); - ret line + ret(line) } } -fn message_header(i: I) -> SimpleResult> { - parse!{i; +fn message_header>() -> impl Parser, Error=Error> { + parse!{ let name = take_while1(is_token); token(b':'); let lines = many1(message_header_line); - ret Header { + ret(Header { name: name, value: lines, - } + }) } } #[inline(never)] -fn request(i: I) -> SimpleResult, Vec>)> { - parse!{i; +fn request>() -> impl Parser, Vec>), Error=Error> + where I::Buffer: ::std::ops::Deref { + parse!{ let r = request_line(); end_of_line(); let h = many(message_header); end_of_line(); - ret (r, h) + ret((r, h)) } } @@ -126,7 +129,7 @@ Connection: keep-alive\r \r"; b.iter(|| { - parse_only(request, data) + request().parse(&data[..]) }) } @@ -138,7 +141,7 @@ Host: localhost\r \r"; b.iter(|| { - parse_only(request, data) + request().parse(&data[..]) }) } @@ -157,7 +160,7 @@ Cookie: azk=ue1-5eb08aeed9a7401c9195cb933eb7c966\r \r"; b.iter(|| { - parse_only(request, data) + request().parse(&data[..]) }) } @@ -166,7 +169,7 @@ fn multiple_requests(b: &mut Bencher) { let data = include_bytes!("./data/http-requests.txt"); b.iter(|| { - let r: Result, _> = parse_only(parser!{many(request)}, data); + let (_, r): (_, Result, _>) = many(request).parse(&data[..]); r }) diff --git a/examples/http_parser.rs b/examples/http_parser.rs index 4deec9cd..965a3568 100644 --- a/examples/http_parser.rs +++ b/examples/http_parser.rs @@ -9,6 +9,7 @@ //! //! ``` +#![feature(conservative_impl_trait)] #[macro_use] extern crate chomp; @@ -64,69 +65,70 @@ fn is_not_space(c: u8) -> bool { c != b' ' } fn is_end_of_line(c: u8) -> bool { c == b'\r' || c == b'\n' } fn is_http_version(c: u8) -> bool { c >= b'0' && c <= b'9' || c == b'.' } -fn end_of_line(i: I) -> SimpleResult { - parse!{i; (token(b'\r') <|> ret b'\0') >> token(b'\n')} +fn end_of_line>() -> impl Parser> { + parse!{(token(b'\r') <|> ret(b'\0')) >> token(b'\n')} } -fn http_version(i: I) -> SimpleResult { - parse!{i; +fn message_header_line>() -> impl Parser> { + parse!{ + take_while1(is_horizontal_space); + let line = take_till(is_end_of_line); + end_of_line(); + + ret(line) + } +} + +fn message_header>() -> impl Parser, Error=Error> { + parse!{ + let name = take_while1(is_token); + token(b':'); + let lines = many1(message_header_line); + + ret(Header { + name: name, + value: lines, + }) + } +} + +fn http_version>() -> impl Parser> { + parse!{ string(b"HTTP/"); take_while1(is_http_version) } } -fn request_line(i: I) -> SimpleResult> { - parse!{i; +fn request_line>() -> impl Parser, Error=Error> { + parse!{ let method = take_while1(is_token); take_while1(is_space); let uri = take_while1(is_not_space); take_while1(is_space); let version = http_version(); - ret Request { + ret(Request { method: method, uri: uri, version: version, - } - } -} - -fn message_header_line(i: I) -> SimpleResult { - parse!{i; - take_while1(is_horizontal_space); - let line = take_till(is_end_of_line); - end_of_line(); - - ret line - } -} - -fn message_header(i: I) -> SimpleResult> { - parse!{i; - let name = take_while1(is_token); - token(b':'); - let lines = many1(message_header_line); - - ret Header { - name: name, - value: lines, - } + }) } } #[inline(never)] -fn request(i: I) -> SimpleResult, Vec>)> +fn request>() -> impl Parser, Vec>), Error=Error> where I::Buffer: ::std::ops::Deref { - parse!{i; + parse!{ let r = request_line(); end_of_line(); let h = many(message_header); end_of_line(); - ret (r, h) + ret((r, h)) } } + fn main() { let file = File::open(env::args().nth(1).expect("File to read")).ok().expect("Failed to open file"); // Use default buffer settings for a Read source @@ -134,7 +136,7 @@ fn main() { let mut n = 0; loop { - match i.parse(request) { + match i.parse(request()) { Ok(_) => n += 1, Err(StreamError::Retry) => {}, // Needed to refill buffer when necessary Err(StreamError::EndOfInput) => break, diff --git a/src/ascii.rs b/src/ascii.rs index 39b8fd33..7b73de06 100644 --- a/src/ascii.rs +++ b/src/ascii.rs @@ -8,14 +8,9 @@ use conv::{ }; use conv::errors::UnwrapOk; -use types::{Buffer, Input}; use combinators::option; -use parsers::{ - SimpleResult, - satisfy, - skip_while, - take_while1, -}; +use parsers::{Error, satisfy, skip_while, take_while1}; +use types::{Buffer, Input, Parser}; /// Lowercase ASCII predicate. #[inline] @@ -84,11 +79,11 @@ pub fn is_alphanumeric(c: u8) -> bool { /// use chomp::parse_only; /// use chomp::ascii::skip_whitespace; /// -/// assert_eq!(parse_only(skip_whitespace, b" \t "), Ok(())); +/// assert_eq!(parse_only(skip_whitespace(), b" \t "), Ok(())); /// ``` #[inline] -pub fn skip_whitespace>(i: I) -> SimpleResult { - skip_while(i, is_whitespace) +pub fn skip_whitespace>() -> impl Parser> { + skip_while(is_whitespace) } /// Parses a single digit. @@ -103,11 +98,11 @@ pub fn skip_whitespace>(i: I) -> SimpleResult { /// use chomp::parse_only; /// use chomp::ascii::digit; /// -/// assert_eq!(parse_only(digit, b"1"), Ok(b'1')); +/// assert_eq!(parse_only(digit(), b"1"), Ok(b'1')); /// ``` #[inline] -pub fn digit>(i: I) -> SimpleResult { - satisfy(i, is_digit) +pub fn digit>() -> impl Parser> { + satisfy(is_digit) } /// Parses a number with an optional leading '+' or '-'. @@ -123,19 +118,18 @@ pub fn digit>(i: I) -> SimpleResult { /// use chomp::parse_only; /// use chomp::ascii::{decimal, signed}; /// -/// let r: Result = parse_only(|i| signed(i, decimal), b"-123"); +/// let r: Result = parse_only(signed(decimal()), b"-123"); /// /// assert_eq!(r, Ok(-123i16)); /// ``` #[inline] -pub fn signed, T, F>(i: I, f: F) -> SimpleResult +pub fn signed, T, F>(f: F) -> impl Parser> where T: Copy + ValueFrom + Add + Mul, - F: FnOnce(I) -> SimpleResult { - option(i, - |i| satisfy(i, |c| c == b'-' || c == b'+') - .map(|s| T::value_from(if s == b'+' { 1 } else { -1 }).unwrap_ok()), - T::value_from(1).unwrap_ok()) - .bind(|i, sign| f(i).map(|num| sign * num)) + F: Parser> { + option( + satisfy(|c| c == b'-' || c == b'+').map(|s| T::value_from(if s == b'+' { 1 } else { -1 }).unwrap_ok()), + T::value_from(1).unwrap_ok()) + .bind(|sign| f.map(move |num| sign * num)) } /// Parses a series of digits and converts them to an integer. @@ -150,13 +144,15 @@ pub fn signed, T, F>(i: I, f: F) -> SimpleResult /// use chomp::parse_only; /// use chomp::ascii::decimal; /// -/// let r = parse_only(decimal::<_, u8>, b"123"); +/// let r = parse_only(decimal::<_, u8>(), b"123"); /// /// assert_eq!(r, Ok(123u8)); /// ``` #[inline] -pub fn decimal, T: Copy + ValueFrom + Add + Mul>(i: I) -> SimpleResult { - take_while1(i, is_digit).map(to_decimal) +pub fn decimal() -> impl Parser> + where I: Input, + T: Copy + ValueFrom + Add + Mul { + take_while1(is_digit).map(to_decimal) } /// Internal function converting a `[u8]` to the given integer type `T`. @@ -170,9 +166,61 @@ fn to_decimal + Add + Mul bool { + (match a { + b'A'...b'Z' => a | 0x20, + x => x + } == match b { + b'A'...b'Z' => b | 0x20, + x => x + }) +} + +/// Matches the given slice against the parser in a case-insensitive manner, returning the matched +/// slice upon success. Only respects ASCII characters for the case-insensitive comparison. +/// +/// If the length of the contained data is shorter than the given slice this parser is considered +/// incomplete. +/// +/// ``` +/// use chomp::prelude::parse_only; +/// use chomp::ascii::string_ci; +/// +/// assert_eq!(parse_only(string_ci(b"abc"), b"abcdef"), Ok(&b"abc"[..])); +/// assert_eq!(parse_only(string_ci(b"abc"), b"aBCdef"), Ok(&b"aBC"[..])); +/// ``` +pub fn string_ci>(s: &'static [u8]) -> impl Parser> { + move |mut i: I| { + let mut n = 0; + let len = s.len(); + + // TODO: There has to be some more efficient way here + let b = i.consume_while(|c| { + if n >= len || !compare_ci(c, s[n]) { + false + } + else { + n += 1; + + true + } + }); + + if n >= len { + (i, Ok(b)) + } else { + (i, Err(Error::expected(s[n]))) + } + } +} + + #[cfg(test)] mod test { - use super::to_decimal; + use super::{compare_ci, to_decimal, string_ci}; + use types::Parser; + use parsers::Error; macro_rules! test_to_decimal { ( $($n:ty),+ ) => { $( @@ -190,4 +238,67 @@ mod test { fn test_to_decimal_u8() { test_to_decimal!(u8, u16, u32, u64, i16, i32, i64); } + + #[test] + fn compare_ci_test() { + assert!(compare_ci(b'a', b'a')); + assert!(compare_ci(b'a', b'A')); + assert!(compare_ci(b'b', b'b')); + assert!(compare_ci(b'b', b'B')); + assert!(compare_ci(b'y', b'y')); + assert!(compare_ci(b'y', b'Y')); + assert!(compare_ci(b'z', b'z')); + assert!(compare_ci(b'z', b'Z')); + + for i in 0..127 { + for j in 0..127 { + let eq = match i { + b'A'...b'Z' => i | 0x20, + x => x + } == match j { + b'A'...b'Z' => j | 0x20, + x => x + }; + + assert_eq!(eq, compare_ci(i, j), "{} {} failed", i, j); + } + } + } + + #[test] + fn string_ci_test() { + assert_eq!(string_ci(b"" ).parse(&b""[..]), (&b""[..], Ok(&b""[..]))); + assert_eq!(string_ci(b"a" ).parse(&b""[..]), (&b""[..], Err(Error::expected(b'a')))); + assert_eq!(string_ci(b"a" ).parse(&b"a"[..]), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(string_ci(b"a" ).parse(&b"b"[..]), (&b"b"[..], Err(Error::expected(b'a')))); + assert_eq!(string_ci(b"a" ).parse(&b"abc"[..]), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(string_ci(b"ab" ).parse(&b"abc"[..]), (&b"c"[..], Ok(&b"ab"[..]))); + assert_eq!(string_ci(b"abc" ).parse(&b"abc"[..]), (&b""[..], Ok(&b"abc"[..]))); + assert_eq!(string_ci(b"abcd" ).parse(&b"abc"[..]), (&b""[..], Err(Error::expected(b'd')))); + assert_eq!(string_ci(b"abcde").parse(&b"abc"[..]), (&b""[..], Err(Error::expected(b'd')))); + assert_eq!(string_ci(b"ac" ).parse(&b"abc"[..]), (&b"bc"[..], Err(Error::expected(b'c')))); + + assert_eq!(string_ci(b"" ).parse(&b""[..]), (&b""[..], Ok(&b""[..]))); + assert_eq!(string_ci(b"a" ).parse(&b""[..]), (&b""[..], Err(Error::expected(b'a')))); + assert_eq!(string_ci(b"a" ).parse(&b"A"[..]), (&b""[..], Ok(&b"A"[..]))); + assert_eq!(string_ci(b"a" ).parse(&b"B"[..]), (&b"B"[..], Err(Error::expected(b'a')))); + assert_eq!(string_ci(b"a" ).parse(&b"ABC"[..]), (&b"BC"[..], Ok(&b"A"[..]))); + assert_eq!(string_ci(b"ab" ).parse(&b"ABC"[..]), (&b"C"[..], Ok(&b"AB"[..]))); + assert_eq!(string_ci(b"abc" ).parse(&b"ABC"[..]), (&b""[..], Ok(&b"ABC"[..]))); + assert_eq!(string_ci(b"abcd" ).parse(&b"ABC"[..]), (&b""[..], Err(Error::expected(b'd')))); + assert_eq!(string_ci(b"abcde").parse(&b"ABC"[..]), (&b""[..], Err(Error::expected(b'd')))); + assert_eq!(string_ci(b"ac" ).parse(&b"ABC"[..]), (&b"BC"[..], Err(Error::expected(b'c')))); + + assert_eq!(string_ci(b"{|}" ).parse(&b"{|}"[..]), (&b""[..], Ok(&b"{|}"[..]))); + assert_eq!(string_ci(b"{|}" ).parse(&b"[\\]"[..]), (&b"[\\]"[..], Err(Error::expected(b'{')))); + assert_eq!(string_ci(b"[\\]" ).parse(&b"[\\]"[..]), (&b""[..], Ok(&b"[\\]"[..]))); + assert_eq!(string_ci(b"[\\]" ).parse(&b"{|}"[..]), (&b"{|}"[..], Err(Error::expected(b'[')))); + + assert_eq!(string_ci("ä".as_bytes() ).parse("äbc".as_bytes()), (&b"bc"[..], Ok("ä".as_bytes()))); + // We need to slice a bit, since the first byte of the two-byte ä and Ä are is the same, + // so that one will match + assert_eq!(string_ci("ä".as_bytes() ).parse("ÄBC".as_bytes()), (&"ÄBC".as_bytes()[1..], Err(Error::expected("ä".as_bytes()[1])))); + + assert_eq!(string_ci(b"125" ).parse(&b"125"[..]), (&b""[..], Ok(&b"125"[..]))); + } } diff --git a/src/buffer/data_source.rs b/src/buffer/data_source.rs index c574d96c..9cb31570 100644 --- a/src/buffer/data_source.rs +++ b/src/buffer/data_source.rs @@ -49,6 +49,45 @@ impl DataSource for ReadDataSource { } } + +/// Implementation of `DataSource` for streams (e.g. network connections) that you can `Read` and +/// `Write`. It's really helpful to have the ability to write through the `DataSource` and `Source` +/// objects, because once created, often they take full ownership of your input stream, and when +/// working with bidirectional connections you still need a way to write to them. +#[derive(Debug)] +pub struct RWDataSource(RW); + +impl RWDataSource { + /// Creates a new `RWDataSource` from a stream (e.g. network connection). + pub fn new(inner: RW) -> Self { + RWDataSource(inner) + } + + /// Consumes self to reveal the underlying stream. + #[inline] + pub fn into_inner(self) -> RW { + self.0 + } +} + +impl DataSource for RWDataSource { + type Item = u8; + + #[inline] + fn read(&mut self, buffer: &mut [u8]) -> io::Result { + self.0.read(buffer) + } +} + +impl io::Write for RWDataSource { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + fn flush(&mut self) -> io::Result<()> { + self.0.flush() + } +} + /// Implementation of `DataSource` for `Iterator`. // TODO: Tests #[derive(Debug)] diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index be21b2c3..393c0e8e 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -9,14 +9,14 @@ //! //! use chomp::buffer; //! use chomp::buffer::Stream; -//! use chomp::prelude::{token, take_while, take_while1}; +//! use chomp::prelude::{Parser, token, take_while, take_while1}; //! use chomp::ascii::is_whitespace; //! //! let f = File::open("./README.md").unwrap(); //! //! let mut b = buffer::Source::from_read(f, buffer::FixedSizeBuffer::new()); //! -//! let r = b.parse(parser!{ +//! let r = b.parse(parse!{ //! take_while(|c| c != b'#'); //! token(b'#'); //! take_while1(is_whitespace); @@ -38,12 +38,11 @@ use std::ptr; use std::cell::Cell; -use types::{Input, ParseResult}; +use types::{Input, Parser}; use types::Buffer as InputBuffer; -use primitives::Guard; pub use self::slice::SliceStream; -pub use self::data_source::DataSource; +pub use self::data_source::{DataSource, RWDataSource}; pub use self::stateful::Source; const DEFAULT_BUFFER_SIZE: usize = 6 * 1024; @@ -89,10 +88,8 @@ pub trait Stream<'a, 'i> { /// If a `StreamError::Retry` is returned the consuming code it should just retry the action /// (the implementation might require a separate call to refill the stream). #[inline] - fn parse(&'a mut self, f: F) -> Result::Buffer, E>> - where F: FnOnce(Self::Input) -> ParseResult, - T: 'i, - E: 'i; + fn parse

(&'a mut self, P) -> Result::Buffer, P::Error>> + where P: Parser; } /// Input buffer type which contains a flag which tells if we might need to read more data. @@ -139,7 +136,7 @@ impl<'a, I: Copy + PartialEq> Input for InputBuf<'a, I> { type Buffer = &'a [I]; #[inline] - fn _peek(&mut self, _g: Guard) -> Option { + fn peek(&mut self) -> Option { if let Some(c) = self.1.first() { Some(*c) } else { @@ -150,8 +147,8 @@ impl<'a, I: Copy + PartialEq> Input for InputBuf<'a, I> { } #[inline] - fn _pop(&mut self, g: Guard) -> Option { - self._peek(g).map(|c| { + fn pop(&mut self) -> Option { + self.peek().map(|c| { self.1 = &self.1[1..]; c @@ -159,7 +156,7 @@ impl<'a, I: Copy + PartialEq> Input for InputBuf<'a, I> { } #[inline] - fn _consume(&mut self, _g: Guard, n: usize) -> Option { + fn consume(&mut self, n: usize) -> Option { if n > self.1.len() { self.0 = true; @@ -174,7 +171,7 @@ impl<'a, I: Copy + PartialEq> Input for InputBuf<'a, I> { } #[inline] - fn _consume_while(&mut self, g: Guard, mut f: F) -> Self::Buffer + fn consume_while(&mut self, mut f: F) -> Self::Buffer where F: FnMut(Self::Token) -> bool { if let Some(n) = self.1.iter().position(|c| !f(*c)) { let b = &self.1[..n]; @@ -183,17 +180,17 @@ impl<'a, I: Copy + PartialEq> Input for InputBuf<'a, I> { b } else { - self._consume_remaining(g) + self.consume_remaining() } } #[inline] - fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer { + fn consume_from(&mut self, m: Self::Marker) -> Self::Buffer { &m[..m.len() - self.1.len()] } #[inline] - fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer { + fn consume_remaining(&mut self) -> Self::Buffer { self.0 = true; let b = self.1; @@ -204,14 +201,14 @@ impl<'a, I: Copy + PartialEq> Input for InputBuf<'a, I> { } #[inline] - fn _mark(&self, _g: Guard) -> Self::Marker { + fn mark(&self) -> Self::Marker { // Incomplete state is separate from the parsed state, no matter how we hit incomplete we // want to keep it. self.1 } #[inline] - fn _restore(mut self, _g: Guard, m: Self::Marker) -> Self { + fn restore(mut self, m: Self::Marker) -> Self { self.1 = m; self @@ -500,33 +497,27 @@ impl Buffer for GrowingBuffer { #[cfg(test)] mod test { use super::InputBuf; - use types::{Input, ParseResult}; - use primitives::{IntoInner, Primitives}; + use types::{Input, Parser}; + use types::{ret, err}; use types::test::run_primitives_test; #[test] - fn ret() { + fn ret_test() { let i1: InputBuf = InputBuf::new(b"in1"); let i2: InputBuf = InputBuf::new(b"in2"); - let r1: ParseResult<_, u32, ()> = i1.ret::<_, ()>(23u32); - let r2: ParseResult<_, i32, &str> = i2.ret::<_, &str>(23i32); - - assert_eq!(r1.into_inner(), (InputBuf::new(b"in1"), Ok(23u32))); - assert_eq!(r2.into_inner(), (InputBuf::new(b"in2"), Ok(23i32))); + assert_eq!(ret::<_, ()>(23u32).parse(i1), (InputBuf::new(b"in1"), Ok(23u32))); + assert_eq!(ret::<_, &str>(23i32).parse(i2), (InputBuf::new(b"in2"), Ok(23i32))); } #[test] - fn err() { + fn err_test() { let i1: InputBuf = InputBuf::new(b"in1"); let i2: InputBuf = InputBuf::new(b"in2"); - let r1: ParseResult<_, (), u32> = i1.err::<(), _>(23u32); - let r2: ParseResult<_, &str, i32> = i2.err::<&str, _>(23i32); - - assert_eq!(r1.into_inner(), (InputBuf::new(b"in1"), Err(23u32))); - assert_eq!(r2.into_inner(), (InputBuf::new(b"in2"), Err(23i32))); + assert_eq!(err::<(), _>(23u32).parse(i1), (InputBuf::new(b"in1"), Err(23u32))); + assert_eq!(err::<&str, _>(23i32).parse(i2), (InputBuf::new(b"in2"), Err(23i32))); } #[test] diff --git a/src/buffer/slice.rs b/src/buffer/slice.rs index 35966e40..0e0b3c6e 100644 --- a/src/buffer/slice.rs +++ b/src/buffer/slice.rs @@ -1,6 +1,4 @@ -use primitives::IntoInner; - -use types::{Input, ParseResult}; +use types::{Input, Parser}; use buffer::{InputBuf, StreamError, Stream}; /// Stream implementation for immutable slices. @@ -10,8 +8,9 @@ use buffer::{InputBuf, StreamError, Stream}; /// # fn main() { /// use chomp::parsers::{token, take}; /// use chomp::buffer::{SliceStream, Stream}; +/// use chomp::types::Parser; /// -/// let r = SliceStream::new(b"foo").parse(parser!{ +/// let r = SliceStream::new(b"foo").parse(parse!{ /// token(b'f'); /// take(2) /// }); @@ -25,11 +24,12 @@ use buffer::{InputBuf, StreamError, Stream}; /// # fn main() { /// use chomp::prelude::{token, many, take}; /// use chomp::buffer::{SliceStream, Stream}; +/// use chomp::types::Parser; /// -/// let r = SliceStream::new(b"foofoo").parse(parser!{many(parser!{ +/// let r = SliceStream::new(b"foofoo").parse(many(|| parse!{ /// token(b'f'); /// take(2) -/// })}); +/// })); /// /// assert_eq!(r, Ok(vec![b"oo" as &[u8], b"oo" as &[u8]])); /// # } @@ -67,17 +67,13 @@ impl<'a, 'i, I: 'i + Copy + PartialEq> Stream<'a, 'i> for SliceStream<'i, I> { type Input = InputBuf<'i, I>; #[inline] - fn parse(&'a mut self, f: F) -> Result::Buffer, E>> - where F: FnOnce(Self::Input) -> ParseResult, - T: 'i, - E: 'i { - use primitives::Primitives; - + fn parse

(&'a mut self, p: P) -> Result::Buffer, P::Error>> + where P: Parser { if self.is_empty() { return Err(StreamError::EndOfInput); } - match f(InputBuf::new(&self.slice[self.pos..])).into_inner() { + match p.parse(InputBuf::new(&self.slice[self.pos..])) { (remainder, Ok(data)) => { // TODO: Do something neater with the remainder self.pos += self.len() - remainder.len(); diff --git a/src/buffer/stateful.rs b/src/buffer/stateful.rs index 0f80cf09..7d5755f7 100644 --- a/src/buffer/stateful.rs +++ b/src/buffer/stateful.rs @@ -1,11 +1,11 @@ use std::io; -use types::{Input, ParseResult}; -use primitives::IntoInner; +use types::{Input, Parser}; use buffer::{ Buffer, DataSource, + RWDataSource, FixedSizeBuffer, InputBuf, Stream, @@ -14,15 +14,15 @@ use buffer::{ use buffer::data_source::{IteratorDataSource, ReadDataSource}; bitflags!{ - flags ParserState: u64 { + struct ParserState: u64 { /// The parser which was last run on the buffer did not manage to complete with the data /// available in the buffer. - const INCOMPLETE = 1, + const INCOMPLETE = 1; /// The buffer did not manage to read any more data from the underlying `Read` /// implementation. - const END_OF_INPUT = 2, + const END_OF_INPUT = 2; /// `parse()` should attempt to read more data whenever the `INCOMPLETE` flag is set. - const AUTOMATIC_FILL = 4, + const AUTOMATIC_FILL = 4; } } @@ -55,6 +55,22 @@ impl> Source, B> { } } +impl Source, FixedSizeBuffer> { + /// Creates a new `Source` from `Read`+`Write` with the default `FixedSizeBuffer` settings. + #[inline] + pub fn new_rw(rwsource: RW) -> Self { + Self::with_buffer(RWDataSource::new(rwsource), FixedSizeBuffer::new()) + } +} + +impl> Source, B> { + /// Creates a new `Source` from `Read`+`Write` and buffer instances. + #[inline] + pub fn from_read_write(source: RW, buffer: B) -> Self { + Self::with_buffer(RWDataSource::new(source), buffer) + } +} + impl> Source, B> where I::Item: Copy + PartialEq { /// Creates a new `Source` from `Iterator` and `Buffer` instances. @@ -197,17 +213,24 @@ impl, B: Buffer> io::BufRead for Source { } } +impl> io::Write for Source, B> { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.source.write(buf) + } + #[inline] + fn flush(&mut self) -> io::Result<()> { + self.source.flush() + } +} + impl<'a, S: DataSource, B: Buffer> Stream<'a, 'a> for Source where S::Item: 'a { type Input = InputBuf<'a, S::Item>; #[inline] - fn parse(&'a mut self, f: F) -> Result::Buffer, E>> - where F: FnOnce(Self::Input) -> ParseResult, - T: 'a, - E: 'a { - use primitives::Primitives; - + fn parse

(&'a mut self, p: P) -> Result::Buffer, P::Error>> + where P: Parser { if self.state.contains(INCOMPLETE | AUTOMATIC_FILL) { try!(self.fill().map_err(StreamError::IoError)); } @@ -216,7 +239,7 @@ impl<'a, S: DataSource, B: Buffer> Stream<'a, 'a> for Source return Err(StreamError::EndOfInput); } - match f(InputBuf::new(&self.buffer)).into_inner() { + match p.parse(InputBuf::new(&self.buffer)) { (remainder, Ok(data)) => { if remainder.is_incomplete() && !self.state.contains(END_OF_INPUT) { // We can't accept this since we might have hit a premature end @@ -251,6 +274,7 @@ impl<'a, S: DataSource, B: Buffer> Stream<'a, 'a> for Source } } +/* #[cfg(test)] mod test { use std::io; @@ -524,3 +548,4 @@ mod test { assert_eq!(m, 2); } } +*/ diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 18901b27..5860de27 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -1,6 +1,8 @@ //! Bounded versions of combinators. //! -//! This module provides bounded versions of `many`, `many_till` and `skip_many`. +//! This module provides bounded versions of `many`, `many_till` and `skip_many`. All versions +//! parse into any `T: FromIterator` with guarantees that they will never (successfully) yield +//! fewer items than the range and never more than the range specifies. //! //! The core range types are used to describe a half-open range of successive applications of a //! parser. `usize` is used to specify an exact number of iterations: @@ -11,30 +13,52 @@ //! use chomp::parsers::any; //! //! // Read any character 2 or 3 times -//! let r: Result, _> = parse_only(|i| many(i, 2..4, any), b"abcd"); +//! let r: Result, _> = parse_only(many(2..4, any), b"abcd"); //! //! assert_eq!(r, Ok(vec![b'a', b'b', b'c'])); //! ``` use std::marker::PhantomData; use std::iter::FromIterator; -use std::ops::{ - Range, - RangeFrom, - RangeFull, - RangeTo, -}; use std::cmp::max; -use types::{Input, ParseResult}; -use primitives::{Primitives, IntoInner}; +use std::ops::{RangeFrom, RangeFull, RangeTo, Range}; + +use types::{Input, Parser, ThenParser}; + +/// Trait describing a parser constructor which can construct multiple instances of the same +/// parser. +pub trait ParserConstructor { + /// The parser type created by the constructor instance. + type Parser: Parser; + + /// Creates a new parser instance. + #[inline] + fn new_parser(&mut self) -> Self::Parser; +} + +impl ParserConstructor for F + where I: Input, + F: FnMut() -> P, + P: Parser { + type Parser = P; + + #[inline(always)] + fn new_parser(&mut self) -> Self::Parser { + self() + } +} /// Trait for applying a parser multiple times based on a range. -pub trait BoundedRange { - // TODO: Update documentation regarding input state. Incomplete will point to the last - // successful parsed data. mark a backtrack point to be able to restart parsing. - /// Applies the parser `F` multiple times until it fails or the maximum value of the range has - /// been reached, collecting the successful values into a `T: FromIterator`. +pub trait Many + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { + /// The parser type returned by `many`. + type ManyParser: Parser>::Parser as Parser>::Error>; + + /// Applies the parser constructed by `F` multiple times until it fails or the maximum value of + /// the range has been reached, collecting the successful values into a `T: FromIterator`. /// /// Propagates errors if the minimum number of iterations has not been met /// @@ -45,17 +69,23 @@ pub trait BoundedRange { /// # Notes /// /// * Will allocate depending on the `FromIterator` implementation. - /// * Must never yield more items than the upper bound of the range. + /// * Will never yield more items than the upper bound of the range. + /// * Will never yield fewer items than the lower bound of the range. + /// * Will only call the parser-constructor `F` once for each iteration, in order. /// * Use `combinators::bounded::many` instead of calling this trait method directly. - /// * If the last parser succeeds on the last input item then this parser is still considered - /// incomplete if the input flag END_OF_INPUT is not set as there might be more data to fill. #[inline] - fn parse_many(self, I, F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator; + fn many(self, f: F) -> Self::ManyParser; +} + +/// Trait for applying a parser multiple times based on a range, ignoring any output. +pub trait SkipMany + where I: Input, + F: ParserConstructor { + /// The parser type returned by `skip_many`. + type SkipManyParser: Parser>::Parser as Parser>::Error>; - /// Applies the parser `F` multiple times until it fails or the maximum value of the range has - /// been reached, throwing away any produced value. + /// Applies the parser constructed by `F` multiple times until it fails or the maximum value of + /// the range has been reached, throwing away any produced value. /// /// Propagates errors if the minimum number of iterations has not been met /// @@ -65,18 +95,26 @@ pub trait BoundedRange { /// /// # Notes /// - /// * Must never yield more items than the upper bound of the range. - /// * Use `combinators::bounded::many` instead of calling this trait method directly. - /// * If the last parser succeeds on the last input item then this parser is still considered - /// incomplete if the input flag END_OF_INPUT is not set as there might be more data to fill. + /// * Will never skip more items than the upper bound of the range. + /// * Will never skip fewer items than the lower bound of the range. + /// * Will only call the parser-constructor `F` once for each iteration, in order + /// * Use `combinators::bounded::skip_many` instead of calling this trait method directly. #[inline] - fn skip_many(self, I, F) -> ParseResult - where F: FnMut(I) -> ParseResult; + fn skip_many(self, F) -> Self::SkipManyParser; +} - // TODO: Fix documentation regarding incomplete - /// Applies the parser `P` multiple times until the parser `F` succeeds and returns a value - /// populated by the values yielded by `P`. Consumes the matched part of `F`. If `F` does not - /// succeed within the given range `R` this combinator will propagate any failure from `P`. +/// Trait for applying a parser multiple times based on a range until another parser succeeds. +pub trait ManyTill + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { + /// The parser type returned by `many_till`. + type ManyTillParser: Parser>::Parser as Parser>::Error>; + + /// Applies the parser constructed by `F` multiple times until the parser `G` succeeds, + /// collecting the values from `F` into a `T: FromIterator` Consumes the matched part of `G`. + /// If `F` does not succeed within the given range `R` this combinator will propagate any + /// failure from `G`. /// /// # Panics /// @@ -85,309 +123,430 @@ pub trait BoundedRange { /// # Notes /// /// * Will allocate depending on the `FromIterator` implementation. + /// * Will never yield more items than the upper bound of the range. + /// * Will never yield fewer items than the lower bound of the range. /// * Use `combinators::bounded::many_till` instead of calling this trait method directly. - /// * Must never yield more items than the upper bound of the range. - /// * If the last parser succeeds on the last input item then this combinator is still considered - /// incomplete unless the parser `F` matches or the lower bound has not been met. #[inline] - fn many_till(self, I, R, F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult; + fn many_till(self, F, G) -> Self::ManyTillParser; } -impl BoundedRange for Range { - #[inline] - fn parse_many(self, i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator { - // Range does not perform this assertion - assert!(self.start <= self.end); - - run_iter!{ - input: i, - parser: f, - // Range is closed on left side, open on right, ie. [self.start, self.end) - state: (usize, usize): (self.start, max(self.start, self.end.saturating_sub(1))), +many_iter!{ + #[derive(Debug)] + #[doc="Parser iterating over a `Range`, created using `many(n..m, p)`."] + pub struct ManyRangeParser { + state: (usize, usize), - size_hint(self) { - (self.data.0, Some(self.data.1)) - } - - next(self) { - pre { - if self.data.1 == 0 { - return None; - } - } - on { - self.data.0 = self.data.0.saturating_sub(1); - // Can't overflow unless we do not quit when self.data.1 == 0 - self.data.1 -= 1; + size_hint(self) { + (self.data.0, Some(self.data.1)) + } + next(self) { + pre { + if self.data.1 == 0 { + return None; } } - - => result : T { - // Got all occurrences of the parser - // First state or reached max => do not restore to mark since it is from last - // iteration - (s, (0, 0), _, _) => s.ret(result), - // Ok, last parser failed and we have reached minimum, we have iterated all. - // Return remainder of buffer and the collected result - (s, (0, _), m, Some(_)) => s.restore(m).ret(result), - // Did not reach minimum, propagate - (s, (_, _), _, Some(e)) => s.err(e), - (_, _, _, None) => unreachable!(), + on { + self.data.0 = self.data.0.saturating_sub(1); + // Can't overflow unless we forget to end before self.data.1 == 0 + self.data.1 -= 1; } } + finally(result) { + // Got all occurrences of the parser + // First state or reached max => do not restore to mark since it is from last + // iteration + (s, (0, 0), _, _) => (s, Ok(result)), + // Ok, last parser failed and we have reached minimum, we have iterated all. + // Return remainder of buffer and the collected result + (s, (0, _), m, Some(_)) => (s.restore(m), Ok(result)), + // Did not reach minimum, propagate + (s, (_, _), _, Some(e)) => (s, Err(e)), + (_, _, _, None) => unreachable!(), + } } +} + +impl Many for Range + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyRangeParser; #[inline] - fn skip_many(self, mut i: I, mut f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { + fn many(self, f: F) -> Self::ManyParser { // Range does not perform this assertion assert!(self.start <= self.end); - // Closed on left side, open on right - let (mut min, mut max) = (self.start, max(self.start, self.end.saturating_sub(1))); + ManyRangeParser { + parser_ctor: f, + // Range is closed on left side, open on right, ie. [start, end), but start <= end + data: (self.start, max(self.start, self.end.saturating_sub(1))), + _i: PhantomData, + _t: PhantomData, + } + } +} + +/// Parser iterating over a `Range` discarding results, created using `skip_many(n..m, f)`. +#[derive(Debug)] +pub struct SkipManyRangeParser { + f: F, + max: usize, + min: usize, + _i: PhantomData +} +impl Parser for SkipManyRangeParser + where I: Input, + F: ParserConstructor { + type Output = (); + type Error = >::Error; + + #[inline] + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { - if max == 0 { + if self.max == 0 { break; } let m = i.mark(); - match f(i).into_inner() { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => { - min = min.saturating_sub(1); + self.min = self.min.saturating_sub(1); // Can't overflow unless we do not quit when max == 0 - max -= 1; + self.max -= 1; i = b }, - (b, Err(e)) => if min == 0 { + (b, Err(e)) => if self.min == 0 { i = b.restore(m); break; } else { // Not enough iterations, propagate - return b.err(e); + return (b, Err(e)); }, } } - i.ret(()) + (i, Ok(())) } +} + +impl SkipMany for Range + where I: Input, + F: ParserConstructor { + type SkipManyParser = SkipManyRangeParser; #[inline] - fn many_till(self, i: I, p: R, end: F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { + fn skip_many(self, f: F) -> Self::SkipManyParser { // Range does not perform this assertion assert!(self.start <= self.end); - run_iter_till!{ - input: i, - parser: p, - end: end, - // Range is closed on left side, open on right, ie. [self.start, self.end) - state: (usize, usize): (self.start, max(self.start, self.end.saturating_sub(1))), + // Closed on left side, open on right + SkipManyRangeParser { + f: f, + min: self.start, + max: max(self.start, self.end.saturating_sub(1)), + _i: PhantomData, + } + } +} + +many_till_iter! { + #[derive(Debug)] + #[doc="Parser iterating over a `Range` and ending with a final parser, created by `many_till(n..m, ...)`"] + pub struct ManyTillRangeParser { + state: (usize, usize), - size_hint(self) { - (self.data.0, Some(self.data.1)) - } + size_hint(self) { + (self.data.0, Some(self.data.1)) + } + next(self) { + pre { + if self.data.0 == 0 { + // We have reached minimum, we can attempt to end now + + // TODO: Remove the branches here (ie. take + unwrap) + let i = self.buf.take().expect("Iter.buf was None"); + let m = i.mark(); + + match (self.data.1, (self.end).new_parser().parse(i)) { + // We can always end + (_, (b, Ok(_))) => { + self.buf = Some(b); + self.state = EndStateTill::EndSuccess; + + return None; + }, + // We have reached end, end must match or it is an error + (0, (b, Err(e))) => { + self.buf = Some(b); + self.state = EndStateTill::Error(From::from(e)); - next(self) { - pre { - if self.data.0 == 0 { - // We have reached minimum, we can attempt to end now - - // TODO: Remove the branches here (ie. take + unwrap) - let i = self.buf.take().expect("Iter.buf was None"); - let m = i.mark(); - - match (self.data.1, (self.end)(i).into_inner()) { - // We can always end - (_, (b, Ok(_))) => { - self.buf = Some(b); - self.state = EndStateTill::EndSuccess; - - return None - }, - // We have reached end, end must match or it is an error - (0, (b, Err(e))) => { - self.buf = Some(b); - self.state = EndStateTill::Error(From::from(e)); - - return None; - }, - // Failed to end, restore and continue since we can parse more - (_, (b, Err(_))) => self.buf = Some(b.restore(m)), - } + return None; + }, + // Failed to end, restore and continue since we can parse more + (_, (b, Err(_))) => self.buf = Some(b.restore(m)), } } - on { - self.data.0 = self.data.0.saturating_sub(1); - // Can't overflow unless we do not quit when self.data.1 == 0 - self.data.1 -= 1; - } } - - => result : T { - // Got all occurrences of the parser - (s, (0, _), EndStateTill::EndSuccess) => s.ret(result), - // Did not reach minimum or a failure, propagate - (s, (_, _), EndStateTill::Error(e)) => s.err(e), - (_, (_, _), EndStateTill::Incomplete) => unreachable!(), - // We cannot reach this since we only run the end test once we have reached the - // minimum number of matches - (_, (_, _), EndStateTill::EndSuccess) => unreachable!() + on { + self.data.0 = self.data.0.saturating_sub(1); + // Can't overflow unless we forget to end before self.data.1 == 0 + self.data.1 -= 1; } } + finally(result) { + // Got all occurrences of the parser + (s, (0, _), EndStateTill::EndSuccess) => (s, Ok(result)), + // Did not reach minimum or a failure, propagate + (s, (_, _), EndStateTill::Error(e)) => (s, Err(e)), + (_, (_, _), EndStateTill::Incomplete) => unreachable!(), + // We cannot reach this since we only run the end test once we have reached the + // minimum number of matches + (_, (_, _), EndStateTill::EndSuccess) => unreachable!() + } } } -impl BoundedRange for RangeFrom { +impl ManyTill for Range + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillRangeParser; + #[inline] - fn parse_many(self, i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator { - run_iter!{ - input: i, - parser: f, - // Inclusive - state: usize: self.start, - - size_hint(self) { - (self.data, None) - } + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + // Range does not perform this assertion + assert!(self.start <= self.end); - next(self) { - pre {} - on { - self.data = self.data.saturating_sub(1); - } - } + ManyTillRangeParser { + p_ctor: f, + q_ctor: g, + // Range is closed on left side, open on right, ie. [start, end), but start <= end + data: (self.start, max(self.start, self.end.saturating_sub(1))), + _i: PhantomData, + _t: PhantomData, + } + } +} + +many_iter!{ + #[derive(Debug)] + #[doc="Parser iterating over a `RangeFrom`, created using `many(n.., p)`."] + pub struct ManyRangeFromParser { + // Inclusive + state: usize, - => result : T { - // We got at least n items - (s, 0, m, Some(_)) => s.restore(m).ret(result), - // Items still remaining, propagate - (s, _, _, Some(e)) => s.err(e), - (_, _, _, None) => unreachable!(), + size_hint(self) { + (self.data, None) + } + next(self) { + pre {} + on { + self.data = self.data.saturating_sub(1); } } + finally(result) { + // We got at least n items + (s, 0, m, Some(_)) => (s.restore(m), Ok(result)), + // Items still remaining, propagate + (s, _, _, Some(e)) => (s, Err(e)), + (_, _, _, None) => unreachable!(), + } } +} + +impl Many for RangeFrom + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyRangeFromParser; #[inline] - fn skip_many(self, mut i: I, mut f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { - // Closed on left side, open on right - let mut min = self.start; + fn many(self, f: F) -> Self::ManyParser { + ManyRangeFromParser { + parser_ctor: f, + // Range is closed on left side, open on right, ie. [start, end) + data: self.start, + _i: PhantomData, + _t: PhantomData, + } + } +} +/// Parser iterating over a `RangeFrom` discarding results, created using `skip_many(n.., f)`. +#[derive(Debug)] +pub struct SkipManyRangeFromParser { + f: F, + min: usize, + _i: PhantomData +} + +impl Parser for SkipManyRangeFromParser + where I: Input, + F: ParserConstructor { + type Output = (); + type Error = >::Error; + + #[inline] + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { let m = i.mark(); - match f(i).into_inner() { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => { - min = min.saturating_sub(1); + self.min = self.min.saturating_sub(1); i = b }, - (b, Err(e)) => if min == 0 { + (b, Err(e)) => if self.min == 0 { i = b.restore(m); break; } else { // Not enough iterations, propagate - return b.err(e); + return (b, Err(e)); }, } } - i.ret(()) + (i, Ok(())) } +} + +impl SkipMany for RangeFrom + where I: Input, + F: ParserConstructor { + type SkipManyParser = SkipManyRangeFromParser; #[inline] - fn many_till(self, i: I, p: R, end: F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - run_iter_till!{ - input: i, - parser: p, - end: end, - // Range is closed on left side, unbounded on right - state: usize: self.start, + fn skip_many(self, f: F) -> Self::SkipManyParser { + // Closed on left side + SkipManyRangeFromParser { + f: f, + min: self.start, + _i: PhantomData, + } + } +} - size_hint(self) { - (self.data, None) - } +many_till_iter! { + #[derive(Debug)] + #[doc="Parser iterating over a `RangeFrom` and ending with a final parser, created by `many_till(n.., ...)`"] + pub struct ManyTillRangeFromParser { + state: usize, - next(self) { - pre { - if self.data == 0 { - // We have reached minimum, we can attempt to end now - iter_till_end_test!(self); - } - } - on { - self.data = self.data.saturating_sub(1); + size_hint(self) { + (self.data, None) + } + next(self) { + pre { + if self.data == 0 { + // We have reached minimum, we can attempt to end now + iter_till_end_test!(self); } } - - => result : T { - // Got all occurrences of the parser - (s, 0, EndStateTill::EndSuccess) => s.ret(result), - // Did not reach minimum or a failure, propagate - (s, _, EndStateTill::Error(e)) => s.err(e), - (_, _, EndStateTill::Incomplete) => unreachable!(), - // We cannot reach this since we only run the end test once we have reached the - // minimum number of matches - (_, _, EndStateTill::EndSuccess) => unreachable!() + on { + self.data = self.data.saturating_sub(1); } } + finally(result) { + // Got all occurrences of the parser + (s, 0, EndStateTill::EndSuccess) => (s, Ok(result)), + // Did not reach minimum or a failure, propagate + (s, _, EndStateTill::Error(e)) => (s, Err(e)), + (_, _, EndStateTill::Incomplete) => unreachable!(), + // We cannot reach this since we only run the end test once we have reached the + // minimum number of matches + (_, _, EndStateTill::EndSuccess) => unreachable!() + } } } -impl BoundedRange for RangeFull { +impl ManyTill for RangeFrom + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillRangeFromParser; + #[inline] - fn parse_many(self, i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator { - run_iter!{ - input: i, - parser: f, - state: (): (), - - size_hint(self) { - (0, None) - } + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + ManyTillRangeFromParser { + p_ctor: f, + q_ctor: g, + // Range is closed on left side, unbounded on right + data: self.start, + _i: PhantomData, + _t: PhantomData, + } + } +} - next(self) { - pre {} - on {} - } +many_iter!{ + #[derive(Debug)] + #[doc="Parser iterating over a `RangeFull`, created using `many(.., p)`."] + pub struct ManyRangeFullParser { + state: (), - => result : T { - (s, (), m, Some(_)) => s.restore(m).ret(result), - (_, _, _, None) => unreachable!(), - } + size_hint(self) { + (0, None) + } + next(self) { + pre {} + on {} + } + finally(result) { + (s, (), m, Some(_)) => (s.restore(m), Ok(result)), + (_, _, _, None) => unreachable!(), + } + } +} + +impl Many for RangeFull + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyRangeFullParser; + + #[inline] + fn many(self, f: F) -> Self::ManyParser { + ManyRangeFullParser { + parser_ctor: f, + data: (), + _i: PhantomData, + _t: PhantomData, } } +} + +/// Parser iterating over a `RangeFull` discarding results, created using `skip_many(.., f)`. +#[derive(Debug)] +pub struct SkipManyRangeFullParser { + f: F, + _i: PhantomData +} + +impl Parser for SkipManyRangeFullParser + where I: Input, + F: ParserConstructor { + type Output = (); + type Error = >::Error; #[inline] - fn skip_many(self, mut i: I, mut f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { let m = i.mark(); - match f(i).into_inner() { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => i = b, (b, Err(_)) => { i = b.restore(m); @@ -397,96 +556,145 @@ impl BoundedRange for RangeFull { } } - i.ret(()) + (i, Ok(())) } +} + +impl SkipMany for RangeFull + where I: Input, + F: ParserConstructor { + type SkipManyParser = SkipManyRangeFullParser; #[inline] - fn many_till(self, i: I, p: R, end: F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - run_iter_till!{ - input: i, - parser: p, - end: end, - state: (): (), - - size_hint(self) { - (0, None) - } + fn skip_many(self, f: F) -> Self::SkipManyParser { + SkipManyRangeFullParser { + f: f, + _i: PhantomData, + } + } +} - next(self) { - pre { - // Can end at any time - iter_till_end_test!(self); - } - on {} - } +many_till_iter! { + #[derive(Debug)] + #[doc="Parser iterating over a `RangeFull` and ending with a final parser, created by `many_till(.., ...)`"] + pub struct ManyTillRangeFullParser { + state: (), - => result : T { - (s, (), EndStateTill::EndSuccess) => s.ret(result), - (s, (), EndStateTill::Error(e)) => s.err(e), - // Nested parser incomplete, propagate if not at end - (_, (), EndStateTill::Incomplete) => unreachable!() + size_hint(self) { + (0, None) + } + next(self) { + pre { + // Can end at any time + iter_till_end_test!(self); } + on {} + } + finally(result) { + (s, (), EndStateTill::EndSuccess) => (s, Ok(result)), + (s, (), EndStateTill::Error(e)) => (s, Err(e)), + // Nested parser incomplete, propagate if not at end + (_, (), EndStateTill::Incomplete) => unreachable!() } } } -impl BoundedRange for RangeTo { +impl ManyTill for RangeFull + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillRangeFullParser; + #[inline] - fn parse_many(self, i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator { - run_iter!{ - input: i, - parser: f, - // Exclusive range [0, end) - state: usize: max(self.end, 1) - 1, + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + ManyTillRangeFullParser { + p_ctor: f, + q_ctor: g, + data: (), + _i: PhantomData, + _t: PhantomData, + } + } +} - size_hint(self) { - (0, Some(self.data)) - } +many_iter!{ + #[derive(Debug)] + #[doc="Parser iterating over a `RangeTo`, created using `many(..n, p)`."] + pub struct ManyRangeToParser { + // Exclusive range [0, end) + state: usize, - next(self) { - pre { - if self.data == 0 { - return None; - } - } - on { - self.data -= 1; + size_hint(self) { + (0, Some(self.data)) + } + next(self) { + pre { + if self.data == 0 { + return None; } } - - => result : T { - // First state or reached max => do not restore to mark since it is from last - // iteration - (s, 0, _, _) => s.ret(result), - // Inside of range, never outside - (s, _, m, Some(_)) => s.restore(m).ret(result), - (_, _, _, None) => unreachable!(), + on { + self.data -= 1; } } + finally(result) { + // First state or reached max => do not restore to mark since it is from last + // iteration + (s, 0, _, _) => (s, Ok(result)), + // Inside of range, never outside + (s, _, m, Some(_)) => (s.restore(m), Ok(result)), + (_, _, _, None) => unreachable!(), + } } +} + +impl Many for RangeTo + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyRangeToParser; #[inline] - fn skip_many(self, mut i: I, mut f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { - // [0, n) - let mut max = max(self.end, 1) - 1; + fn many(self, f: F) -> Self::ManyParser { + ManyRangeToParser { + parser_ctor: f, + // Exclusive range [0, end) + data: self.end.saturating_sub(1), + _i: PhantomData, + _t: PhantomData, + } + } +} + +/// Parser iterating over a `RangeTo` discarding results, created using `skip_many(..n, f)`. +#[derive(Debug)] +pub struct SkipManyRangeToParser { + f: F, + max: usize, + _i: PhantomData +} + +impl Parser for SkipManyRangeToParser + where I: Input, + F: ParserConstructor { + type Output = (); + type Error = >::Error; + #[inline] + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { - if max == 0 { + if self.max == 0 { break; } let m = i.mark(); - match f(i).into_inner() { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => { - max -= 1; + self.max -= 1; i = b }, @@ -499,190 +707,271 @@ impl BoundedRange for RangeTo { } } - i.ret(()) + (i, Ok(())) } +} - #[inline] - fn many_till(self, i: I, p: R, end: F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - run_iter_till!{ - input: i, - parser: p, - end: end, - // [0, self.end) - state: usize: max(self.end, 1) - 1, - - size_hint(self) { - (0, Some(self.data)) - } +impl SkipMany for RangeTo + where I: Input, + F: ParserConstructor { + type SkipManyParser = SkipManyRangeToParser; - next(self) { - pre { - // TODO: Remove the branches here (ie. take + unwrap) - let i = self.buf.take().expect("Iter.buf was None"); - let m = i.mark(); + #[inline] + fn skip_many(self, f: F) -> Self::SkipManyParser { + // Open on right side + SkipManyRangeToParser { + f: f, + max: self.end.saturating_sub(1), + _i: PhantomData, + } + } +} - match (self.data, (self.end)(i).into_inner()) { - // We can always end - (_, (b, Ok(_))) => { - self.buf = Some(b); - self.state = EndStateTill::EndSuccess; +many_till_iter! { + #[derive(Debug)] + #[doc="Parser iterating over a `RangeTo` and ending with a final parser, created by `many_till(..m, ...)`"] + pub struct ManyTillRangeToParser { + state: usize, - return None - }, - // We have reached end, end must match or it is an error - (0, (b, Err(e))) => { - self.buf = Some(b); - self.state = EndStateTill::Error(From::from(e)); + size_hint(self) { + (0, Some(self.data)) + } + next(self) { + pre { + // TODO: Remove the branches here (ie. take + unwrap) + let i = self.buf.take().expect("Iter.buf was None"); + let m = i.mark(); + + match (self.data, (self.end).new_parser().parse(i)) { + // We can always end + (_, (b, Ok(_))) => { + self.buf = Some(b); + self.state = EndStateTill::EndSuccess; + + return None + }, + // We have reached end, end must match or it is an error + (0, (b, Err(e))) => { + self.buf = Some(b); + self.state = EndStateTill::Error(From::from(e)); - return None; - }, - // Failed to end, restore and continue since we can parse more - (_, (b, Err(_))) => self.buf = Some(b.restore(m)), - } - } - on { - self.data -= 1; + return None; + }, + // Failed to end, restore and continue since we can parse more + (_, (b, Err(_))) => self.buf = Some(b.restore(m)), } } - - => result : T { - // Got all occurrences of the parser since we have no minimum bound - (s, _, EndStateTill::EndSuccess) => s.ret(result), - // Did not reach minimum or a failure, propagate - (s, _, EndStateTill::Error(e)) => s.err(e), - (_, _, EndStateTill::Incomplete) => unreachable!(), + on { + self.data -= 1; } } + finally(result) { + // Got all occurrences of the parser since we have no minimum bound + (s, _, EndStateTill::EndSuccess) => (s, Ok(result)), + // Did not reach minimum or a failure, propagate + (s, _, EndStateTill::Error(e)) => (s, Err(e)), + (_, _, EndStateTill::Incomplete) => unreachable!(), + } } } -impl BoundedRange for usize { - // TODO: Any way to avoid marking for backtracking here? +impl ManyTill for RangeTo + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillRangeToParser; + #[inline] - fn parse_many(self, i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator { - run_iter!{ - input: i, - parser: f, - // Excatly self - state: usize: self, - - size_hint(self) { - (self.data, Some(self.data)) - } + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + ManyTillRangeToParser { + p_ctor: f, + q_ctor: g, + // [0, self.end) + data: self.end.saturating_sub(1), + _i: PhantomData, + _t: PhantomData, + } + } +} - next(self) { - pre { - if self.data == 0 { - return None; - } - } - on { - self.data -= 1; +many_iter!{ + #[derive(Debug)] + #[doc="Parser iterating `usize` times, created using `many(n, p)`."] + pub struct ManyExactParser { + // Excatly self + state: usize, + + size_hint(self) { + (self.data, Some(self.data)) + } + next(self) { + pre { + if self.data == 0 { + return None; } } - - => result : T { - // Got exact - (s, 0, _, _) => s.ret(result), - // We have got too few items, propagate error - (s, _, _, Some(e)) => s.err(e), - (_, _, _, None) => unreachable!(), + on { + self.data -= 1; } } + finally(result) { + // Got exact + (s, 0, _, _) => (s, Ok(result)), + // We have got too few items, propagate error + (s, _, _, Some(e)) => (s, Err(e)), + (_, _, _, None) => unreachable!(), + } } +} + +impl Many for usize + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyExactParser; #[inline] - fn skip_many(self, mut i: I, mut f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { - let mut n = self; + fn many(self, f: F) -> Self::ManyParser { + ManyExactParser { + parser_ctor: f, + // Range is closed on left side, open on right, ie. [start, end) + data: self, + _i: PhantomData, + _t: PhantomData, + } + } +} + +/// Parser iterating `usize` times discarding results, created using `skip_many(n, f)`. +#[derive(Debug)] +pub struct SkipManyExactParser { + f: F, + n: usize, + _i: PhantomData +} + +impl Parser for SkipManyExactParser + where I: Input, + F: ParserConstructor { + type Output = (); + type Error = >::Error; + #[inline] + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { - if n == 0 { + if self.n == 0 { break; } - match f(i).into_inner() { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => { - n -= 1; + self.n -= 1; i = b }, - (b, Err(e)) => if n == 0 { + (b, Err(e)) => if self.n == 0 { unreachable!(); } else { // Not enough iterations, propagate - return b.err(e); + return (b, Err(e)); }, } } - i.ret(()) + (i, Ok(())) } +} + +impl SkipMany for usize + where I: Input, + F: ParserConstructor { + type SkipManyParser = SkipManyExactParser; #[inline] - fn many_till(self, i: I, p: R, end: F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - run_iter_till!{ - input: i, - parser: p, - end: end, - state: usize: self, - - size_hint(self) { - (self.data, Some(self.data)) - } + fn skip_many(self, f: F) -> Self::SkipManyParser { + SkipManyExactParser { + f: f, + n: self, + _i: PhantomData, + } + } +} - next(self) { - pre { - if self.data == 0 { - // TODO: Remove the branches here (ie. take + unwrap) - let i = self.buf.take().expect("Iter.buf was None"); - - match (self.end)(i).into_inner() { - (b, Ok(_)) => { - self.buf = Some(b); - self.state = EndStateTill::EndSuccess; - }, - // Failed to end, restore and continue - (b, Err(e)) => { - self.buf = Some(b); - self.state = EndStateTill::Error(From::from(e)); - }, - } +many_till_iter! { + #[derive(Debug)] + #[doc="Parser iterating `usize` times and ending with a final parser, created by `many_till(n, ...)`"] + pub struct ManyTillExactParser { + state: usize, - return None; + size_hint(self) { + (self.data, Some(self.data)) + } + next(self) { + pre { + if self.data == 0 { + // Reached exact, MUST end here: + + // TODO: Remove the branches here (ie. take + unwrap) + let i = self.buf.take().expect("Iter.buf was None"); + + match (self.end).new_parser().parse(i) { + (b, Ok(_)) => { + self.buf = Some(b); + self.state = EndStateTill::EndSuccess; + }, + // Failed to end, restore and continue + (b, Err(e)) => { + self.buf = Some(b); + self.state = EndStateTill::Error(e); + }, } - } - on { - self.data -= 1; + + return None; } } - - => result : T { - // Got all occurrences of the parser - (s, 0, EndStateTill::EndSuccess) => s.ret(result), - // Did not reach minimum or a failure, propagate - (s, _, EndStateTill::Error(e)) => s.err(e), - (_, _, EndStateTill::Incomplete) => unreachable!(), - // We cannot reach this since we only run the end test once we have reached the - // minimum number of matches - (_, _, EndStateTill::EndSuccess) => unreachable!() + on { + self.data -= 1; } } + finally(result) { + // Got all occurrences of the parser + (s, 0, EndStateTill::EndSuccess) => (s, Ok(result)), + // Did not reach minimum or a failure, propagate + (s, _, EndStateTill::Error(e)) => (s, Err(e)), + (_, _, EndStateTill::Incomplete) => unreachable!(), + // We cannot reach this since we only run the end test once we have reached the + // minimum number of matches + (_, _, EndStateTill::EndSuccess) => unreachable!(), + } + } +} + +impl ManyTill for usize + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillExactParser; + + #[inline] + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + ManyTillExactParser { + p_ctor: f, + q_ctor: g, + data: self, + _i: PhantomData, + _t: PhantomData, + } } } -/// Applies the parser `F` multiple times until it fails or the maximum value of the range has -/// been reached, collecting the successful values into a `T: FromIterator`. +/// Applies the parser constructed by `F` multiple times until it fails or the maximum value of the +/// range has been reached, collecting the successful values into a `T: FromIterator`. /// /// Propagates errors if the minimum number of iterations has not been met /// @@ -694,16 +983,19 @@ impl BoundedRange for usize { /// /// * Will allocate depending on the `FromIterator` implementation. /// * Will never yield more items than the upper bound of the range. +/// * Will never yield fewer items than the lower bound of the range. +/// * Will only call the parser-constructor `F` once for each iteration, in order #[inline] -pub fn many(i: I, r: R, f: F) -> ParseResult - where R: BoundedRange, - F: FnMut(I) -> ParseResult, - T: FromIterator { - BoundedRange::parse_many(r, i, f) +pub fn many(r: R, f: F) -> R::ManyParser + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output>, + R: Many { + Many::many(r, f) } -/// Applies the parser `F` multiple times until it fails or the maximum value of the range has -/// been reached, throwing away any produced value. +/// Applies the parser constructed by `F` multiple times until it fails or the maximum value of the +/// range has been reached, throwing away any produced value. /// /// Propagates errors if the minimum number of iterations has not been met /// @@ -713,18 +1005,21 @@ pub fn many(i: I, r: R, f: F) -> ParseResult /// /// # Notes /// -/// * Will never yield more items than the upper bound of the range. +/// * Will never parse more items than the upper bound of the range. +/// * Will never parse fewer items than the lower bound of the range. +/// * Will only call the parser-constructor `F` once for each iteration, in order #[inline] -pub fn skip_many(i: I, r: R, f: F) -> ParseResult - where R: BoundedRange, - F: FnMut(I) -> ParseResult { - BoundedRange::skip_many(r, i, f) +pub fn skip_many(r: R, f: F) -> R::SkipManyParser + where I: Input, + F: ParserConstructor, + R: SkipMany { + SkipMany::skip_many(r, f) } -// TODO: Update documentation regarding incomplete behaviour -/// Applies the parser `P` multiple times until the parser `F` succeeds and returns a value -/// populated by the values yielded by `P`. Consumes the matched part of `F`. If `F` does not -/// succeed within the given range `R` this combinator will propagate any failure from `P`. +/// Applies the parser constructed by `F` multiple times until the parser constructed by `G` +/// succeeds, collecting the values from `F` into a `T: FromIterator`. Consumes the matched +/// part of `G`. If `F` does not succeed within the given range `R` this combinator will +/// propagate any failure from `G`. /// /// # Panics /// @@ -734,20 +1029,24 @@ pub fn skip_many(i: I, r: R, f: F) -> ParseResult(i: I, r: R, p: P, end: F) -> ParseResult - where R: BoundedRange, - T: FromIterator, - E: From, - P: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - BoundedRange::many_till(r, i, p, end) +pub fn many_till(r: R, p: F, end: G) -> R::ManyTillParser + where I: Input, + //E: From, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output>, + R: ManyTill { + ManyTill::many_till(r, p, end) } -/// Applies the parser `p` multiple times, separated by the parser `sep` and returns a value -/// populated with the values yielded by `p`. If the number of items yielded by `p` does not fall -/// into the range `r` and the separator or parser registers error or incomplete failure is -/// propagated. +/// Applies the parser constructed by `F` multiple times, separated by the parser constructed by +/// `G` and collects the values matched by `F` into a `T: FromIterator`. If the number of items +/// matched by `F` does not fall into the range `R` then the separator `G` or parser `F` error +/// is propagated. /// /// # Panics /// @@ -758,31 +1057,97 @@ pub fn many_till(i: I, r: R, p: P, end: F) -> /// * Will allocate depending on the `FromIterator` implementation. /// * Will never yield more items than the upper bound of the range. #[inline] -pub fn sep_by(i: I, r: R, mut p: P, mut sep: F) -> ParseResult - where T: FromIterator, - E: From, - R: BoundedRange, - P: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - // If we have parsed at least one item - let mut item = false; - // Add sep in front of p if we have read at least one item - let parser = |i| (if item { - sep(i).map(|_| ()) - } else { - i.ret(()) - }) - .then(&mut p) - .inspect(|_| item = true); - - BoundedRange::parse_many(r, i, parser) +// TODO: look at the From +pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser + where I: Input, + // E: From, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output>, + R: Many, T> { + Many::many(r, SepByInnerParserCtor { + item: false, + f: f, + sep: sep, + _i: PhantomData, + }) +} + +/// Constructor for the inner parser used by `sep_by`. +/// +/// This type is created internally by `sep_by` to construct the appropriate parser from a +/// `Many` implementation providing the iteration. +// Due to the requirement of Many to be able to specify a concrete type for the function (F) +// parameter we need to have a type we can describe and not a closure for the type of the sep-by +// inner parser +#[derive(Debug)] +pub struct SepByInnerParserCtor { + item: bool, + f: F, + sep: S, + _i: PhantomData, +} + +impl ParserConstructor for SepByInnerParserCtor + where I: Input, + F: ParserConstructor, + S: ParserConstructor, + S::Parser: Parser>::Error> { + type Parser = ThenParser, F::Parser>; + + fn new_parser(&mut self) -> Self::Parser { + if self.item { + MaybeAParser::parser((self.sep).new_parser()) + } + else { + self.item = true; + + MaybeAParser::none() + }.then((self.f).new_parser()) + } +} + +// TODO: More doc, and probably move +/// Parser required to unify code of the style of Option

to allow for stack-allocation. +#[derive(Debug)] +pub struct MaybeAParser

(Option

); + +impl

MaybeAParser

{ + /// Creates a new wrapper containing a parser to be run. + pub fn parser(p: P) -> MaybeAParser

+ where I: Input, + P: Parser { + MaybeAParser(Some(p)) + } + + /// Creates an empty wrapper plassing the success value. + pub fn none() -> MaybeAParser

{ + MaybeAParser(None) + } +} + +impl Parser for MaybeAParser

+ where I: Input, + P: Parser { + type Output = Option; + type Error = P::Error; + + fn parse(self, i: I) -> (I, Result) { + match self.0 { + Some(p) => match p.parse(i) { + (r, Ok(t)) => (r, Ok(Some(t))), + (r, Err(e)) => (r, Err(e)), + }, + None => (i, Ok(None)), + } + } } #[cfg(test)] mod test { - use types::ParseResult; use parsers::{Error, any, token, string}; - use primitives::IntoInner; + use types::{Parser, ret}; use super::{ many, @@ -792,319 +1157,341 @@ mod test { #[test] fn many_range_full() { - let r: ParseResult<_, Vec<_>, _> = many(&b"b"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ab"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aab"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a']))); + let r = many(.., || token(b'a')); assert_eq!(r.parse(&b"b"[..]), (&b"b"[..], Ok(vec![]))); + let r = many(.., || token(b'a')); assert_eq!(r.parse(&b"ab"[..]), (&b"b"[..], Ok(vec![b'a']))); + let r = many(.., || token(b'a')); assert_eq!(r.parse(&b"aab"[..]), (&b"b"[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], .., any); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], .., any); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], .., any); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); + let r = many(.., any); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(vec![]))); + let r = many(.., any); assert_eq!(r.parse(&b"a"[..]), (&b""[..], Ok(vec![b'a']))); + let r = many(.., any); assert_eq!(r.parse(&b"aa"[..]), (&b""[..], Ok(vec![b'a', b'a']))); // Test where we error inside of the inner parser - let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], .., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], .., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aba"[..], .., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..]]))); + let r = many(.., || string(b"ab")); assert_eq!(r.parse(&b"abac"[..]), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r = many(.., || string(b"ab")); assert_eq!(r.parse(&b"abac"[..]), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r = many(.., || string(b"ab")); assert_eq!(r.parse(&b"aba"[..]), (&b"a"[..], Ok(vec![&b"ab"[..]]))); } #[test] fn many_range_to() { - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); + let r = many(..0, || token(b'a')); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(vec![]))); + let r = many(..0, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b"a"[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], ..1, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], ..1, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); + let r = many(..1, || token(b'a')); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(vec![]))); + let r = many(..1, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b"a"[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![b'a', b'a']))); + let r = many(..3, || token(b'a')); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(vec![]))); + let r = many(..3, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b""[..], Ok(vec![b'a']))); + let r = many(..3, || token(b'a')); assert_eq!(r.parse(&b"aa"[..]), (&b""[..], Ok(vec![b'a', b'a']))); + let r = many(..3, || token(b'a')); assert_eq!(r.parse(&b"aaa"[..]), (&b"a"[..], Ok(vec![b'a', b'a']))); // Test where we error inside of the inner parser - let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], ..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], ..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aba"[..], ..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..]]))); + let r = many(..3, || string(b"ab")); assert_eq!(r.parse(&b"abac"[..]), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r = many(..3, || string(b"ab")); assert_eq!(r.parse(&b"abac"[..]), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r = many(..3, || string(b"ab")); assert_eq!(r.parse(&b"aba"[..]), (&b"a"[..], Ok(vec![&b"ab"[..]]))); + } + + #[test] + fn many_range_to_limit() { + // Test infinite + let r: (_, Result, ()>) = many(..4, || ret(b'a')).parse(&b"bbbbbbbbbb"[..]); + assert_eq!(r, (&b"bbbbbbbbbb"[..], Ok(vec![b'a', b'a', b'a']))); } #[test] fn many_range_from() { - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a', b'a']))); + let r: (_, Result, _>) = many(0.., || token(b'a')).parse(&b""[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many(0.., || token(b'a')).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many(0.., || token(b'a')).parse(&b"aa"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(0.., || token(b'a')).parse(&b"aaa"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"b"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a', b'a']))); + let r: (_, Result, _>) = many(2.., || token(b'a')).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2.., || token(b'a')).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2.., || token(b'a')).parse(&b"aa"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2.., || token(b'a')).parse(&b"aaa"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a', b'a']))); + + let r: (_, Result, _>) = many(2.., || token(b'a')).parse(&b"b"[..]); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2.., || token(b'a')).parse(&b"ab"[..]); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2.., || token(b'a')).parse(&b"aab"[..]); assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2.., || token(b'a')).parse(&b"aaab"[..]); assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a', b'a']))); // Test where we error inside of the inner parser - let r: ParseResult<_, Vec<_>, _> = many(&b"ababac"[..], 2.., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ababac"[..], 2.., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ababa"[..], 2.., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r = many(2.., || string(b"ab")); assert_eq!(r.parse(&b"ababac"[..]), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r = many(2.., || string(b"ab")); assert_eq!(r.parse(&b"ababac"[..]), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r = many(2.., || string(b"ab")); assert_eq!(r.parse(&b"ababa"[..]), (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); } #[test] fn many_range() { - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); - - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![b'a', b'a']))); - - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaaa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![b'a', b'a', b'a']))); - - let r: ParseResult<_, Vec<_>, _> = many(&b"b"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaaab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); + let r = many(0..0, || token(b'a')); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(vec![]))); + let r = many(0..0, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b"a"[..], Ok(vec![]))); + let r = many(0..0, || token(b'a')); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(vec![]))); + let r = many(0..0, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b"a"[..], Ok(vec![]))); + + let r: (_, Result, _>) = many(2..2, || token(b'a')).parse(&b""[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2..2, || token(b'a')).parse(&b"a"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2..2, || token(b'a')).parse(&b"aa"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2..2, || token(b'a')).parse(&b"aaa"[..]) ; assert_eq!(r, (&b"a"[..], Ok(vec![b'a', b'a']))); + + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b""[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"a"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"aa"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"aaa"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a', b'a']))); + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"aaaa"[..]); assert_eq!(r, (&b"a"[..], Ok(vec![b'a', b'a', b'a']))); + + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"b"[..]) ; assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"ab"[..]) ; assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"aab"[..]) ; assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"aaab"[..]) ; assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a', b'a']))); + let r: (_, Result, _>) = many(2..4, || token(b'a')).parse(&b"aaaab"[..]); assert_eq!(r, (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); // Test where we error inside of the inner parser - let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], 1..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ababac"[..], 1..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r = many(1..3, || string(b"ab")); assert_eq!(r.parse(&b"abac"[..]), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r = many(1..3, || string(b"ab")); assert_eq!(r.parse(&b"ababac"[..]), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + } + + #[test] + fn many_range_limit() { + // Test infinite + let r: (_, Result, ()>) = many(2..4, || ret(b'a')).parse(&b"bbbbbbbbbb"[..]); + assert_eq!(r, (&b"bbbbbbbbbb"[..], Ok(vec![b'a', b'a', b'a']))); } #[test] fn many_exact() { - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"aa"[..], Ok(vec![]))); + let r = many(0, || token(b'a')); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(vec![]))); + let r = many(0, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b"a"[..], Ok(vec![]))); + let r = many(0, || token(b'a')); assert_eq!(r.parse(&b"aa"[..]), (&b"aa"[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2, || token(b'a')).parse(&b""[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2, || token(b'a')).parse(&b"a"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2, || token(b'a')).parse(&b"aa"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2, || token(b'a')).parse(&b"aaa"[..]) ; assert_eq!(r, (&b"a"[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"b"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a']))); - let r: ParseResult<_, Vec<_>, _> = many(&b"aaab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2, || token(b'a')).parse(&b"b"[..]) ; assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2, || token(b'a')).parse(&b"ab"[..]) ; assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many(2, || token(b'a')).parse(&b"aab"[..]) ; assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(2, || token(b'a')).parse(&b"aaab"[..]) ; assert_eq!(r, (&b"ab"[..], Ok(vec![b'a', b'a']))); // Test where we error inside of the inner parser - let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ababa"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ababac"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many(&b"ababa"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many(2, || string(b"ab")).parse(&b"abac"[..]) ; assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many(2, || string(b"ab")).parse(&b"ababa"[..]) ; assert_eq!(r, (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many(2, || string(b"ab")).parse(&b"abac"[..]) ; assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many(2, || string(b"ab")).parse(&b"ababac"[..]) ; assert_eq!(r, (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many(2, || string(b"ab")).parse(&b"ababa"[..]) ; assert_eq!(r, (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); } #[test] fn many_till_range_full() { - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababab"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababa"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(.., || string(b"ab"), || string(b"ac")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(.., || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(.., || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: (_, Result, _>) = many_till(.., || string(b"ab"), || string(b"ac")).parse(&b"ababac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many_till(.., || string(b"ab"), || string(b"ac")).parse(&b"ababab"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(.., || string(b"ab"), || string(b"ac")).parse(&b"abababa"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'b')))); } #[test] fn many_till_range_from() { - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 1.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 1.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 2.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], 2.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababab"[..], 2.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababa"[..], 2.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(0.., || string(b"ab"), || string(b"ac")).parse(&b""[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(0.., || string(b"ab"), || string(b"ac")).parse(&b"a"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(0.., || string(b"ab"), || string(b"ac")).parse(&b"ab"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(0.., || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(1.., || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]) ; assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(0.., || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: (_, Result, _>) = many_till(1.., || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: (_, Result, _>) = many_till(2.., || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]) ; assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(2.., || string(b"ab"), || string(b"ac")).parse(&b"ababac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many_till(2.., || string(b"ab"), || string(b"ac")).parse(&b"ababab"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(2.., || string(b"ab"), || string(b"ac")).parse(&b"abababa"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'b')))); } #[test] fn many_till_range_to() { - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], ..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"b"[..], ..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..], ..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], ..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], ..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], ..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], ..2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababac"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababab"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababa"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababa"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"ba"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(..0, || string(b"ab"), || string(b"ac")).parse(&b""[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(..0, || string(b"ab"), || string(b"ac")).parse(&b"b"[..]) ; assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(..0, || string(b"ab"), || string(b"ac")).parse(&b"a"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(..0, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(..1, || string(b"ab"), || string(b"ac")).parse(&b""[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(..1, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(..2, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: (_, Result, _>) = many_till(..3, || string(b"ab"), || string(b"ac")).parse(&b""[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(..3, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(..3, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: (_, Result, _>) = many_till(..3, || string(b"ab"), || string(b"ac")).parse(&b"ababac"[..]) ; assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many_till(..3, || string(b"ab"), || string(b"ac")).parse(&b"abababac"[..]) ; assert_eq!(r, (&b"bac"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(..3, || string(b"ab"), || string(b"ac")).parse(&b"ababab"[..]) ; assert_eq!(r, (&b"b"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(..3, || string(b"ab"), || string(b"ac")).parse(&b"ababa"[..]) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(..3, || string(b"ab"), || string(b"ac")).parse(&b"abababa"[..]) ; assert_eq!(r, (&b"ba"[..], Err(Error::expected(b'c')))); } #[test] fn many_till_range() { - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0..0, |i| string(i, b"ab"), |i| string(i, b"cd")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..], 0..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..], 0..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 0..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0..2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 0..2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abc"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababac"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababa"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababa"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"ba"[..], Err(Error::expected(b'c')))); - - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 1..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 1..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 2..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], 2..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], 2..2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many_till(0..0, || string(b"ab"), || string(b"ac")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(0..0, || string(b"ab"), || string(b"cd")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0..0, || string(b"ab"), || string(b"ac")).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0..0, || string(b"ab"), || string(b"ac")).parse(&b"ab"[..]); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0..0, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + + let r: (_, Result, _>) = many_till(0..1, || string(b"ab"), || string(b"ac")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(0..1, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(0..1, || string(b"ab"), || string(b"ac")).parse(&b"ab"[..]); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0..1, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b"bac"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0..2, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(0..2, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b"abc"[..]); assert_eq!(r, (&b"c"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b"ababac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b"abababac"[..]); assert_eq!(r, (&b"bac"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b"ababa"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0..3, || string(b"ab"), || string(b"ac")).parse(&b"abababa"[..]); assert_eq!(r, (&b"ba"[..], Err(Error::expected(b'c')))); + + let r: (_, Result, _>) = many_till(1..3, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(1..3, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: (_, Result, _>) = many_till(2..3, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(2..3, || string(b"ab"), || string(b"ac")).parse(&b"ababac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many_till(2..2, || string(b"ab"), || string(b"ac")).parse(&b"ababac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); } #[test] fn many_till_exact() { - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![])) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"aca"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![])) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"acab"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![])) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c'))) ); - - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"aba"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abab"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]])) ); - - let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"aba"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abab"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababa"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]])) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababab"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c'))) ); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababac"[..], 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c'))) ); + let r: (_, Result, _>) = many_till(0, || string(b"ab"), || string(b"ac")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(0, || string(b"ab"), || string(b"ac")).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(0, || string(b"ab"), || string(b"ac")).parse(&b"aca"[..]); assert_eq!(r, (&b"a"[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(0, || string(b"ab"), || string(b"ac")).parse(&b"acab"[..]); assert_eq!(r, (&b"ab"[..], Ok(vec![]))); + let r: (_, Result, _>) = many_till(0, || string(b"ab"), || string(b"ac")).parse(&b"ab"[..]); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(0, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b"bac"[..], Err(Error::expected(b'c')))); + + let r: (_, Result, _>) = many_till(1, || string(b"ab"), || string(b"ac")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(1, || string(b"ab"), || string(b"ac")).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(1, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(1, || string(b"ab"), || string(b"ac")).parse(&b"ab"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(1, || string(b"ab"), || string(b"ac")).parse(&b"aba"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(1, || string(b"ab"), || string(b"ac")).parse(&b"abab"[..]); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(1, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..]]))); + + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"ac"[..]); assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"ab"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"aba"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"abab"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"abac"[..]); assert_eq!(r, (&b"c"[..], Err(Error::expected(b'b')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"ababa"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"ababac"[..]); assert_eq!(r, (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"ababab"[..]); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'c')))); + let r: (_, Result, _>) = many_till(2, || string(b"ab"), || string(b"ac")).parse(&b"abababac"[..]); assert_eq!(r, (&b"bac"[..], Err(Error::expected(b'c')))); } #[test] fn skip_range_full() { - let r = skip_many(&b""[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"a"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aa"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(.., || token(b'a')); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(()))); + let r = skip_many(.., || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b""[..], Ok(()))); + let r = skip_many(.., || token(b'a')); assert_eq!(r.parse(&b"aa"[..]), (&b""[..], Ok(()))); - let r = skip_many(&b"b"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"ab"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"aab"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(.., || token(b'a')); assert_eq!(r.parse(&b"b"[..]) , (&b"b"[..], Ok(()))); + let r = skip_many(.., || token(b'a')); assert_eq!(r.parse(&b"ab"[..]) , (&b"b"[..], Ok(()))); + let r = skip_many(.., || token(b'a')); assert_eq!(r.parse(&b"aab"[..]) , (&b"b"[..], Ok(()))); } #[test] fn skip_range_to() { - let r = skip_many(&b""[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"b"[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"a"[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); - - let r = skip_many(&b""[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"a"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aa"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aaa"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); - - let r = skip_many(&b"b"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"ab"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"aab"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"aaab"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(()))); + let r = skip_many(..0, || token(b'a')); assert_eq!(r.parse(&b""[..] ), (&b""[..], Ok(()))); + let r = skip_many(..0, || token(b'a')); assert_eq!(r.parse(&b"b"[..] ), (&b"b"[..], Ok(()))); + let r = skip_many(..0, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b"a"[..], Ok(()))); + + let r = skip_many(..1, || token(b'a')); assert_eq!(r.parse(&b""[..] ), (&b""[..], Ok(()))); + let r = skip_many(..1, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b"a"[..], Ok(()))); + + let r = skip_many(..2, || token(b'a')); assert_eq!(r.parse(&b""[..] ), (&b""[..], Ok(()))); + let r = skip_many(..2, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b""[..], Ok(()))); + + let r = skip_many(..3, || token(b'a')); assert_eq!(r.parse(&b""[..] ), (&b""[..], Ok(()))); + let r = skip_many(..3, || token(b'a')); assert_eq!(r.parse(&b"a"[..] ), (&b""[..], Ok(()))); + let r = skip_many(..3, || token(b'a')); assert_eq!(r.parse(&b"aa"[..] ), (&b""[..], Ok(()))); + let r = skip_many(..3, || token(b'a')); assert_eq!(r.parse(&b"aaa"[..]), (&b"a"[..], Ok(()))); + + let r = skip_many(..3, || token(b'a')); assert_eq!(r.parse(&b"b"[..] ), (&b"b"[..], Ok(()))); + let r = skip_many(..3, || token(b'a')); assert_eq!(r.parse(&b"ab"[..] ), (&b"b"[..], Ok(()))); + let r = skip_many(..3, || token(b'a')); assert_eq!(r.parse(&b"aab"[..] ), (&b"b"[..], Ok(()))); + let r = skip_many(..3, || token(b'a')); assert_eq!(r.parse(&b"aaab"[..]), (&b"ab"[..], Ok(()))); } #[test] fn skip_range_from() { - let r = skip_many(&b""[..], 0.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"a"[..], 0.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aa"[..], 0.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - - let r = skip_many(&b""[..], 1.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"a"[..], 0.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - - let r = skip_many(&b""[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"a"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"aa"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aaa"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - - let r = skip_many(&b"b"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"ab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"aab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"aaab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(0.., || token(b'a')); assert_eq!(r.parse(&b""[..] ), (&b""[..], Ok(()))); + let r = skip_many(0.., || token(b'a')); assert_eq!(r.parse(&b"a"[..] ), (&b""[..], Ok(()))); + let r = skip_many(0.., || token(b'a')); assert_eq!(r.parse(&b"aa"[..] ), (&b""[..], Ok(()))); + + let r = skip_many(2.., || token(b'a')); assert_eq!(r.parse(&b""[..] ), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(2.., || token(b'a')); assert_eq!(r.parse(&b"a"[..] ), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(2.., || token(b'a')); assert_eq!(r.parse(&b"aa"[..] ), (&b""[..], Ok(()))); + let r = skip_many(2.., || token(b'a')); assert_eq!(r.parse(&b"aaa"[..]), (&b""[..], Ok(()))); + + let r = skip_many(2.., || token(b'a')); assert_eq!(r.parse(&b"b"[..] ), (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(2.., || token(b'a')); assert_eq!(r.parse(&b"ab"[..] ), (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(2.., || token(b'a')); assert_eq!(r.parse(&b"aab"[..] ), (&b"b"[..], Ok(()))); + let r = skip_many(2.., || token(b'a')); assert_eq!(r.parse(&b"aaab"[..]), (&b"b"[..], Ok(()))); } #[test] fn skip_range() { - let r = skip_many(&b""[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"a"[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); - - let r = skip_many(&b""[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"a"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"aa"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aaa"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); - - let r = skip_many(&b""[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"a"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"aa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aaa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aaaa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); - - let r = skip_many(&b"b"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"ab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"aab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"aaab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"aaaab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(()))); + let r = skip_many(0..0, || token(b'a')); assert_eq!(r.parse(&b""[..] ), (&b""[..], Ok(()))); + let r = skip_many(0..0, || token(b'a')); assert_eq!(r.parse(&b"a"[..]), (&b"a"[..], Ok(()))); + + let r = skip_many(2..2, || token(b'a')).parse(&b""[..] ) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(2..2, || token(b'a')).parse(&b"a"[..] ) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(2..2, || token(b'a')).parse(&b"aa"[..] ) ; assert_eq!(r, (&b""[..], Ok(()))); + let r = skip_many(2..2, || token(b'a')).parse(&b"aaa"[..] ) ; assert_eq!(r, (&b"a"[..], Ok(()))); + + let r = skip_many(2..4, || token(b'a')).parse(&b""[..] ) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(2..4, || token(b'a')).parse(&b"a"[..] ) ; assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(2..4, || token(b'a')).parse(&b"aa"[..] ) ; assert_eq!(r, (&b""[..], Ok(()))); + let r = skip_many(2..4, || token(b'a')).parse(&b"aaa"[..] ) ; assert_eq!(r, (&b""[..], Ok(()))); + let r = skip_many(2..4, || token(b'a')).parse(&b"aaaa"[..]) ; assert_eq!(r, (&b"a"[..], Ok(()))); + + let r = skip_many(2..4, || token(b'a')).parse(&b"b"[..] ); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(2..4, || token(b'a')).parse(&b"ab"[..] ); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(2..4, || token(b'a')).parse(&b"aab"[..] ); assert_eq!(r, (&b"b"[..], Ok(()))); + let r = skip_many(2..4, || token(b'a')).parse(&b"aaab"[..] ); assert_eq!(r, (&b"b"[..], Ok(()))); + let r = skip_many(2..4, || token(b'a')).parse(&b"aaaab"[..]); assert_eq!(r, (&b"ab"[..], Ok(()))); } #[test] fn skip_exact() { - let r = skip_many(&b""[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"a"[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); - let r = skip_many(&b""[..], 1, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"a"[..], 1, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b""[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"a"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"aa"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); - let r = skip_many(&b"aaa"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); - let r = skip_many(&b"aaab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(()))); - let r = skip_many(&b"aab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); - let r = skip_many(&b"ab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - let r = skip_many(&b"b"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(0, || token(b'a')).parse(&b""[..] ); assert_eq!(r, (&b""[..], Ok(()))); + let r = skip_many(0, || token(b'a')).parse(&b"a"[..] ); assert_eq!(r, (&b"a"[..], Ok(()))); + let r = skip_many(1, || token(b'a')).parse(&b""[..] ); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(1, || token(b'a')).parse(&b"a"[..] ); assert_eq!(r, (&b""[..], Ok(()))); + let r = skip_many(2, || token(b'a')).parse(&b""[..] ); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(2, || token(b'a')).parse(&b"a"[..] ); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(2, || token(b'a')).parse(&b"aa"[..] ); assert_eq!(r, (&b""[..], Ok(()))); + let r = skip_many(2, || token(b'a')).parse(&b"aaa"[..] ); assert_eq!(r, (&b"a"[..], Ok(()))); + let r = skip_many(2, || token(b'a')).parse(&b"aaab"[..]); assert_eq!(r, (&b"ab"[..], Ok(()))); + let r = skip_many(2, || token(b'a')).parse(&b"aab"[..] ); assert_eq!(r, (&b"b"[..], Ok(()))); + let r = skip_many(2, || token(b'a')).parse(&b"ab"[..] ); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(2, || token(b'a')).parse(&b"b"[..] ); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); } #[test] #[should_panic] fn panic_many_range_lt() { - let r: ParseResult<_, Vec<_>, _> = many(&b"aaaab"[..], 2..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); + let r = many(2..1, || token(b'a')); + assert_eq!(r.parse(&b"aaaab"[..]), (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); } #[test] #[should_panic] fn panic_skip_many_range_lt() { - assert_eq!(skip_many(&b"aaaab"[..], 2..1, |i| token(i, b'a')).into_inner(), (&b"ab"[..], Ok(()))); + assert_eq!(skip_many(2..1, || token(b'a')).parse(&b"aaaab"[..]), (&b"ab"[..], Ok(()))); } #[test] #[should_panic] fn panic_many_till_range_lt() { - let r: ParseResult<_, Vec<_>, _> = many_till(&b"aaaab"[..], 2..1, |i| token(i, b'a'), |i| token(i, b'b')); - assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); + let r: (_, Result, _>) = many_till(2..1, || token(b'a'), || token(b'b')).parse(&b"aaaab"[..]); assert_eq!(r, (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); } } diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index 11c2722f..f3457e42 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -1,221 +1,285 @@ - -/// Macro to implement and run a parser iterator, it provides the ability to add an extra state -/// variable into it and also provide a size_hint as well as a pre- and on-next hooks. -macro_rules! run_iter { +macro_rules! many_iter { ( - input: $input:expr, - parser: $parser:expr, - state: $data_ty:ty : $data:expr, - - size_hint($size_hint_self:ident) $size_hint:block - next($next_self:ident) { - pre $pre_next:block - on $on_next:block - } - - => $result:ident : $t:ty { - $($pat:pat => $arm:expr),*$(,)* + $(#[$attr:meta])* + pub struct $name:ident { + state: $data_ty:ty, + + size_hint($size_hint_self:ident) $size_hint:block + next($next_self:ident) { + pre $pre_next:block + on $on_next:block + } + finally($result:ident) { + $($pat:pat => $arm:expr),*$(,)* + } } - ) => { { - struct Iter - where F: FnMut(I) -> ParseResult { - /// Last state of the parser - state: Option, + ) => { + $(#[$attr])* + pub struct $name + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { /// Parser to execute once for each iteration - parser: F, - /// Remaining buffer - /// - /// Wrapped in option to prevent two calls to destructors. - buf: Option, - /// Last good state. - /// - /// Wrapped in option to prevent two calls to destructors. - mark: I::Marker, + parser_ctor: F, /// Nested state - data: $data_ty, - _t: PhantomData, + data: $data_ty, + _i: PhantomData, + _t: PhantomData, } - impl Iter - where F: FnMut(I) -> ParseResult { + impl Parser for $name + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { + type Output = T; + type Error = >::Error; + #[inline] - fn end_state(self) -> (I, $data_ty, I::Marker, Option) { - // TODO: Avoid branch, check if this can be guaranteed to always be Some(T) - (self.buf.expect("Iter.buf was None"), self.data, self.mark, self.state) - } - } + fn parse(self, i: I) -> (I, Result>::Error>) { + /// Iterator used to run the parser multiple times + struct ParserIterator + where F: ParserConstructor { + /// Last state of the parser + state: Option<>::Error>, + /// Parser constructor function to execute once for each iteration to obtain + /// a new parser to run for each iteration + parser_ctor: F, + /// Remaining buffer + /// + /// Wrapped in option to prevent two calls to destructors. + buf: Option, + /// Last good state. + mark: I::Marker, + /// Nested state + data: $data_ty, + _i: PhantomData, + } - impl Iterator for Iter - where F: FnMut(I) -> ParseResult { - type Item = T; + impl ParserIterator + where F: ParserConstructor { + #[inline] + fn end_state(self) -> (I, $data_ty, I::Marker, Option<>::Error>) { + // TODO: Avoid branch, check if this can be guaranteed to always be Some(T) + (self.buf.expect("ParserIterator.buf was None"), self.data, self.mark, self.state) + } + } - #[inline] - fn size_hint(&$size_hint_self) -> (usize, Option) { - $size_hint - } + impl Iterator for ParserIterator + where F: ParserConstructor { + type Item = >::Output; - #[inline] - fn next(&mut $next_self) -> Option { - $pre_next + #[inline] + fn size_hint(&$size_hint_self) -> (usize, Option) { + $size_hint + } - // TODO: Remove the branches here (ie. take + unwrap) - let i = $next_self.buf.take().expect("Iter.buf was None"); + #[inline] + fn next(&mut $next_self) -> Option { + $pre_next - // TODO: Any way to prevent marking here since it is not used at all times? - $next_self.mark = i.mark(); + // TODO: Remove the branches here (ie. take + unwrap) + let i = $next_self.buf.take().expect("ParserIterator.buf was None"); - match ($next_self.parser)(i).into_inner() { - (b, Ok(v)) => { - $next_self.buf = Some(b); + // TODO: Any way to prevent marking here since it is not used at all times? + $next_self.mark = i.mark(); - $on_next + match ($next_self.parser_ctor).new_parser().parse(i) { + (b, Ok(v)) => { + $next_self.buf = Some(b); - Some(v) - }, - (b, Err(e)) => { - $next_self.buf = Some(b); - $next_self.state = Some(e); + $on_next - None - }, + Some(v) + }, + (b, Err(e)) => { + $next_self.buf = Some(b); + $next_self.state = Some(e); + + None + }, + } + } } - } - } - // TODO: Not always used - let mark = $input.mark(); + // TODO: Not always used + let mark = i.mark(); - let mut iter = Iter { - state: None, - parser: $parser, - buf: Some($input), - mark: mark, - data: $data, - _t: PhantomData, - }; + let mut iter = ParserIterator { + state: None, + parser_ctor: self.parser_ctor, + buf: Some(i), + mark: mark, + data: self.data, + _i: PhantomData, + }; - let $result: $t = FromIterator::from_iter(iter.by_ref()); + let $result: T = FromIterator::from_iter(iter.by_ref()); - match iter.end_state() { - $($pat => $arm),* + match iter.end_state() { + $($pat => $arm),* + } + } } - } } + } } /// Version of run_iter which allows for an additional parser to be run which can terminate /// iteration early. -macro_rules! run_iter_till { +macro_rules! many_till_iter { ( - input: $input:expr, - parser: $parser:expr, - end: $end:expr, - state: $data_ty:ty : $data:expr, - - size_hint($size_hint_self:ident) $size_hint:block - next($next_self:ident) { - pre $pre_next:block - on $on_next:block - } - - => $result:ident : $t:ty { - $($pat:pat => $arm:expr),*$(,)* - } - ) => { { - enum EndStateTill { - Error(E), - Incomplete, - EndSuccess, + $(#[$attr:meta])* + pub struct $name:ident { + state: $data_ty:ty, + + size_hint($size_hint_self:ident) $size_hint:block + next($next_self:ident) { + pre $pre_next:block + on $on_next:block + } + finally($result:ident) { + $($pat:pat => $arm:expr),*$(,)* + } } - - /// Iterator used by `many_till` and `many1`. - struct IterTill - where E: From, - P: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - state: EndStateTill, - parser: P, - end: F, - buf: Option, + ) => { + $(#[$attr])* + pub struct $name + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { + /// Parser constructor to repeat + p_ctor: F, + /// Parser constructor for the end + q_ctor: G, + /// Nested state data: $data_ty, - _t: PhantomData<(T, U, N)>, + _i: PhantomData, + _t: PhantomData, } - impl IterTill - where E: From, - P: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - /// Destructures the iterator returning the position just after the last successful parse as - /// well as the state of the last attempt to parse data. - #[inline] - fn end_state(self) -> (I, $data_ty, EndStateTill) { - // TODO: Avoid branch, check if this can be guaranteed to always be Some(T) - (self.buf.expect("Iter.buf was None"), self.data, self.state) - } - } - - impl Iterator for IterTill - where E: From, - P: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - type Item = T; + impl Parser for $name + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { + type Output = T; + type Error = >::Error; #[inline] - fn size_hint(&$size_hint_self) -> (usize, Option) { - $size_hint - } + fn parse(self, i: I) -> (I, Result>::Error>) { + enum EndStateTill { + Error(E), + Incomplete, + EndSuccess, + } - #[inline] - fn next(&mut $next_self) -> Option { - $pre_next + /// Iterator used by `many_till` and `many1`. + struct ParserIterator + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error> { + /// Last state of the parser + state: EndStateTill<>::Error>, + /// Parser to repeat + parser: F, + /// Parser to end + end: G, + /// Remaining buffer. + /// + /// Wrapped in Option to prevent two calls to destructors. + buf: Option, + /// Nested state + data: $data_ty, + _i: PhantomData, + } - // TODO: Remove the branches here (ie. take + unwrap) - let i = $next_self.buf.take().expect("Iter.buf was None"); + impl ParserIterator + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error> { + /// Destructures the iterator returning the position just after the last successful parse as + /// well as the state of the last attempt to parse data. + #[inline] + fn end_state(self) -> (I, $data_ty, EndStateTill<>::Error>) { + // TODO: Avoid branch, check if this can be guaranteed to always be Some(T) + (self.buf.expect("Iter.buf was None"), self.data, self.state) + } + } - match ($next_self.parser)(i).into_inner() { - (b, Ok(v)) => { - $next_self.buf = Some(b); + impl Iterator for ParserIterator + where I: Input, + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error> { + type Item = >::Output; + + #[inline] + fn size_hint(&$size_hint_self) -> (usize, Option) { + $size_hint + } + + #[inline] + fn next(&mut $next_self) -> Option { + $pre_next + + // TODO: Remove the branches here (ie. take + unwrap) + let i = $next_self.buf.take().expect("Iter.buf was None"); + + match ($next_self.parser).new_parser().parse(i) { + (b, Ok(v)) => { + $next_self.buf = Some(b); + + $on_next + + Some(v) + }, + (b, Err(e)) => { + $next_self.buf = Some(b); + $next_self.state = EndStateTill::Error(e); + + None + }, + } + } + } - $on_next + let mut iter = ParserIterator { + state: EndStateTill::Incomplete, + parser: self.p_ctor, + end: self.q_ctor, + buf: Some(i), + data: self.data, + _i: PhantomData, + }; - Some(v) - }, - (b, Err(e)) => { - $next_self.buf = Some(b); - $next_self.state = EndStateTill::Error(e); + let $result: T = FromIterator::from_iter(iter.by_ref()); - None - }, + match iter.end_state() { + $($pat => $arm),* } } } - - let mut iter = IterTill { - state: EndStateTill::Incomplete, - parser: $parser, - end: $end, - buf: Some($input), - data: $data, - _t: PhantomData, - }; - - let $result: $t = FromIterator::from_iter(iter.by_ref()); - - match iter.end_state() { - $($pat => $arm),* - } - } } + } } -/// Used with `run_iter_till!` macro to attempt to end iteration early. If the test succeeds the +/// Used in `many_till_iter!` macro to attempt to end iteration early. If the test succeeds the /// buffer position will be updated and the state set to `EndStateTill::EndSuccess` and a `None` /// will be returned, stopping the iteration. If the test fails execution continues. +/// +/// NOTE: Only use if ending is optional. +/// +/// TODO: Remove and incorporate in the other items. macro_rules! iter_till_end_test { ( $the_self:ident ) => { { // TODO: Remove the branches here (ie. take + unwrap) let i = $the_self.buf.take().expect("Iter.buf was None"); let m = i.mark(); - match ($the_self.end)(i).into_inner() { + match ($the_self.end).new_parser().parse(i) { (b, Ok(_)) => { $the_self.buf = Some(b); $the_self.state = EndStateTill::EndSuccess; diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index 120bf979..c81abad5 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -9,37 +9,28 @@ use std::iter::FromIterator; use either::Either; -use types::{ - Input, - ParseResult, -}; - -use primitives::{ - IntoInner, - Primitives, -}; +use types::{Input, Parser}; /// Applies the parser `p` exactly `num` times collecting all items into `T: FromIterator`. /// /// ``` /// use chomp::prelude::*; /// -/// fn parse(i: I) -> SimpleResult> { -/// count(i, 2, |i| token(i, b'a')) -/// } +/// let parse = || count(2, || token(b'a')); /// -/// assert_eq!(parse_only(parse, b"a "), Err((&b" "[..], Error::expected(b'a')))); -/// assert_eq!(parse_only(parse, b"aa "), Ok(vec![b'a', b'a'])); +/// assert_eq!(parse_only(parse(), b"a "), Err((&b" "[..], Error::expected(b'a')))); +/// assert_eq!(parse_only(parse(), b"aa "), Ok(vec![b'a', b'a'])); /// -/// let with_remainder = |i| parse(i).bind(|i, d| take_remainder(i).map(|r| (r, d))); +/// let with_remainder = parse().bind(|d| take_remainder().map(|r| (r, d))); /// /// assert_eq!(parse_only(with_remainder, b"aaa"), Ok((&b"a"[..], vec![b'a', b'a']))); /// ``` #[inline] -pub fn count(i: I, num: usize, p: F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator { - bounded::many(i, num, p) +pub fn count(num: usize, p: F) -> impl Parser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + bounded::many(num, p) } /// Tries the parser `f`, on success it yields the parsed value, on failure `default` will be @@ -48,54 +39,26 @@ pub fn count(i: I, num: usize, p: F) -> ParseResult(i: I) -> SimpleResult { -/// option(i, |i| token(i, b'a'), b'd') +/// fn f() -> impl Parser> { +/// option(token(b'a'), b'd') /// } /// -/// assert_eq!(parse_only(f, b"abc"), Ok(b'a')); -/// assert_eq!(parse_only(f, b"bbc"), Ok(b'd')); -/// ``` -#[inline] -pub fn option(i: I, f: F, default: T) -> ParseResult - where F: FnOnce(I) -> ParseResult { - let m = i.mark(); - - match f(i).into_inner() { - (b, Ok(d)) => b.ret(d), - (b, Err(_)) => b.restore(m).ret(default), - } -} - -/// Tries to match the parser `f`, if `f` fails it tries `g`. Returns the success value of -/// the first match, otherwise the error of the last one if both fail. -/// -/// Incomplete state is propagated from the first one to report incomplete. -/// -/// If multiple `or` combinators are used in the same expression, consider using the `parse!` macro -/// and its alternation operator (`<|>`). -/// -/// ``` -/// use chomp::prelude::{Error, parse_only, or, token}; -/// -/// let p = |i| or(i, -/// |i| token(i, b'a'), -/// |i| token(i, b'b')); -/// -/// assert_eq!(parse_only(&p, b"abc"), Ok(b'a')); -/// assert_eq!(parse_only(&p, b"bbc"), Ok(b'b')); -/// assert_eq!(parse_only(&p, b"cbc"), Err((&b"cbc"[..], Error::expected(b'b')))); +/// assert_eq!(parse_only(f(), b"abc"), Ok(b'a')); +/// assert_eq!(parse_only(f(), b"bbc"), Ok(b'd')); /// ``` #[inline] -pub fn or(i: I, f: F, g: G) -> ParseResult - where F: FnOnce(I) -> ParseResult, - G: FnOnce(I) -> ParseResult { - let m = i.mark(); - - match f(i).into_inner() { - (b, Ok(d)) => b.ret(d), - (b, Err(_)) => g(b.restore(m)), +pub fn option(p: P, default: P::Output) -> impl Parser + where P: Parser { + move |i: I| { + let m = i.mark(); + + match p.parse(i) { + (b, Ok(d)) => (b, Ok(d)), + (b, Err(_)) => (b.restore(m), Ok(default)), + } } } @@ -107,22 +70,27 @@ pub fn or(i: I, f: F, g: G) -> ParseResult /// ``` /// use chomp::prelude::{Error, parse_only, either, token, Left, Right}; /// -/// let p = |i| either(i, |i| token(i, b'a'), |i| token(i, b'b')); +/// let p = || either(token(b'a'), token(b'b')); /// -/// assert_eq!(parse_only(&p, b"a"), Ok(Left(b'a'))); -/// assert_eq!(parse_only(&p, b"b"), Ok(Right(b'b'))); -/// assert_eq!(parse_only(&p, b"c"), Err((&b"c"[..], Error::expected(b'b')))); +/// assert_eq!(parse_only(p(), b"a"), Ok(Left(b'a'))); +/// assert_eq!(parse_only(p(), b"b"), Ok(Right(b'b'))); +/// assert_eq!(parse_only(p(), b"c"), Err((&b"c"[..], Error::expected(b'b')))); /// ``` #[inline] -pub fn either(i: I, f: F, g: G) -> ParseResult, E> +pub fn either(l: L, r: R) -> impl Parser, Error=L::Error> where I: Input, - F: FnOnce(I) -> ParseResult, - G: FnOnce(I) -> ParseResult { - let m = i.mark(); - - match f(i).into_inner() { - (b, Ok(d)) => b.ret(Either::Left(d)), - (b, Err(_)) => g(b.restore(m)).map(Either::Right), + L: Parser, + R: Parser { + move |i: I| { + let m = i.mark(); + + match l.parse(i) { + (b, Ok(l_t)) => (b, Ok(Either::Left(l_t))), + (b, Err(_)) => match r.parse(b.restore(m)) { + (c, Ok(r_t)) => (c, Ok(Either::Right(r_t))), + (c, Err(r_e)) => (c, Err(r_e)) + } + } } } @@ -132,21 +100,20 @@ pub fn either(i: I, f: F, g: G) -> ParseResult /// Note: Allocates data. /// /// ``` -/// use chomp::prelude::{parse_only, token, many, take_while1}; +/// use chomp::prelude::{Parser, parse_only, token, many, take_while1}; /// -/// let r: Result, _> = parse_only(|i| many(i, -/// |i| take_while1(i, |c| c != b',' && c != b' ') -/// .bind(|i, c| token(i, b',') -/// .map(|_| c))), +/// let r: Result, _> = parse_only( +/// many(|| take_while1(|c| c != b',' && c != b' ').skip(token(b','))), /// b"a,bc,cd "); /// /// assert_eq!(r, Ok(vec![&b"a"[..], &b"bc"[..]])); /// ``` #[inline] -pub fn many(i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator { - bounded::many(i, .., f) +pub fn many(f: F) -> impl Parser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + bounded::many(.., f) } /// Parses at least one instance of `f` and continues until it does no longer match, collecting @@ -158,20 +125,19 @@ pub fn many(i: I, f: F) -> ParseResult /// Note: Allocates data. /// /// ``` -/// use chomp::prelude::{Error, parse_only, token, many1, take_while1}; +/// use chomp::prelude::{Parser, Error, parse_only, token, many1, take_while1}; /// -/// let p = |i| many1(i, |i| take_while1(i, |c| c != b',' && c != b' ') -/// .bind(|i, c| token(i, b',') -/// .map(|_| c))); +/// let p = || many1(|| take_while1(|c| c != b',' && c != b' ').skip(token(b','))); /// -/// assert_eq!(parse_only(&p, b"a "), Err((&b" "[..], Error::expected(b',')))); -/// assert_eq!(parse_only(&p, b"a, "), Ok(vec![&b"a"[..]])); +/// assert_eq!(parse_only(p(), b"a "), Err((&b" "[..], Error::expected(b',')))); +/// assert_eq!(parse_only(p(), b"a, "), Ok(vec![&b"a"[..]])); /// ``` #[inline] -pub fn many1(i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult, - T: FromIterator { - bounded::many(i, 1.., f) +pub fn many1(f: F) -> impl Parser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + bounded::many(1.., f) } /// Applies the parser `R` zero or more times, separated by the parser `F`. All matches from `R` @@ -186,20 +152,22 @@ pub fn many1(i: I, f: F) -> ParseResult /// use chomp::prelude::{parse_only, sep_by, token}; /// use chomp::ascii::decimal; /// -/// let r: Result, _> = parse_only(|i| sep_by(i, decimal, |i| token(i, b';')), b"91;03;20"); +/// let r: Result, _> = parse_only(sep_by(decimal, || token(b';')), b"91;03;20"); /// /// assert_eq!(r, Ok(vec![91, 03, 20])); /// ``` #[inline] -pub fn sep_by(i: I, p: R, sep: F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - bounded::sep_by(i, .., p, sep) +pub fn sep_by(p: R, sep: F) -> impl Parser + where I: Input, + T: FromIterator, + //E: From, + R: FnMut() -> P, + F: FnMut() -> Q, + P: Parser, + Q: Parser { + bounded::sep_by(.., p, sep) } - /// Applies the parser `R` one or more times, separated by the parser `F`. All matches from `R` /// will be collected into the type `T: FromIterator`. /// @@ -212,17 +180,21 @@ pub fn sep_by(i: I, p: R, sep: F) -> ParseResult< /// use chomp::prelude::{parse_only, sep_by1, token}; /// use chomp::ascii::decimal; /// -/// let r: Result, _> = parse_only(|i| sep_by1(i, decimal, |i| token(i, b';')), b"91;03;20"); +/// let r: Result, _> = parse_only(sep_by1(decimal, || token(b';')), b"91;03;20"); /// /// assert_eq!(r, Ok(vec![91, 03, 20])); /// ``` +// TODO: Conversion of errors? #[inline] -pub fn sep_by1(i: I, p: R, sep: F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - bounded::sep_by(i, 1.., p, sep) +pub fn sep_by1(p: R, sep: F) -> impl Parser + where I: Input, + T: FromIterator, + //E: From, + R: FnMut() -> P, + F: FnMut() -> Q, + P: Parser, + Q: Parser { + bounded::sep_by(1.., p, sep) } /// Applies the parser `R` multiple times until the parser `F` succeeds and returns a @@ -235,17 +207,21 @@ pub fn sep_by1(i: I, p: R, sep: F) -> ParseResult /// ``` /// use chomp::prelude::{parse_only, many_till, any, token}; /// -/// let r: Result, _> = parse_only(|i| many_till(i, any, |i| token(i, b';')), b"abc;def"); +/// let r: Result, _> = parse_only(many_till(any, || token(b';')), b"abc;def"); /// /// assert_eq!(r, Ok(vec![b'a', b'b', b'c'])); /// ``` +// TODO: Conversion of errors? #[inline] -pub fn many_till(i: I, p: R, end: F) -> ParseResult - where T: FromIterator, - E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - bounded::many_till(i, .., p, end) +pub fn many_till(p: F, end: G) -> impl Parser + where I: Input, + //E: From, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator { + bounded::many_till(.., p, end) } /// Runs the given parser until it fails, discarding matched input. @@ -256,16 +232,18 @@ pub fn many_till(i: I, p: R, end: F) -> ParseResu /// `many` allocates a separate data structure to contain the data before proceeding. /// /// ``` -/// use chomp::prelude::{parse_only, skip_many, token}; +/// use chomp::prelude::{Parser, parse_only, skip_many, token}; /// -/// let r = parse_only(|i| skip_many(i, |i| token(i, b'a')).then(|i| token(i, b'b')), b"aaaabc"); +/// let r = parse_only(skip_many(|| token(b'a')).then(token(b'b')), b"aaaabc"); /// /// assert_eq!(r, Ok(b'b')); /// ``` #[inline] -pub fn skip_many(i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { - bounded::skip_many(i, .., f) +pub fn skip_many(f: F) -> impl Parser + where I: Input, + F: FnMut() -> P, + P: Parser { + bounded::skip_many(.., f) } /// Runs the given parser until it fails, discarding matched input, expects at least one match. @@ -277,19 +255,21 @@ pub fn skip_many(i: I, f: F) -> ParseResult /// `many1` allocates a separate data structure to contain the data before proceeding. /// /// ``` -/// use chomp::prelude::{Error, parse_only, skip_many1, token}; +/// use chomp::prelude::{Parser, Error, parse_only, skip_many1, token}; /// -/// let p = |i| skip_many1(i, |i| token(i, b'a')).bind(|i, _| token(i, b'b')); +/// let p = || skip_many1(|| token(b'a')).then(token(b'b')); /// -/// assert_eq!(parse_only(&p, b"aaaabc"), Ok(b'b')); -/// assert_eq!(parse_only(&p, b"abc"), Ok(b'b')); +/// assert_eq!(parse_only(p(), b"aaaabc"), Ok(b'b')); +/// assert_eq!(parse_only(p(), b"abc"), Ok(b'b')); /// -/// assert_eq!(parse_only(&p, b"bc"), Err((&b"bc"[..], Error::expected(b'a')))); +/// assert_eq!(parse_only(p(), b"bc"), Err((&b"bc"[..], Error::expected(b'a')))); /// ``` #[inline] -pub fn skip_many1(i: I, f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { - bounded::skip_many(i, 1.., f) +pub fn skip_many1(f: F) -> impl Parser + where I: Input, + F: FnMut() -> P, + P: Parser { + bounded::skip_many(1.., f) } /// Returns the result of the given parser as well as the slice which matched it. @@ -298,257 +278,197 @@ pub fn skip_many1(i: I, f: F) -> ParseResult /// use chomp::prelude::{parse_only, matched_by}; /// use chomp::ascii::decimal; /// -/// assert_eq!(parse_only(|i| matched_by(i, decimal), b"123"), Ok((&b"123"[..], 123u32))); +/// assert_eq!(parse_only(matched_by(decimal()), b"123"), Ok((&b"123"[..], 123u32))); /// ``` #[inline] -pub fn matched_by(i: I, f: F) -> ParseResult - where F: FnOnce(I) -> ParseResult { - let m = i.mark(); - - match f(i).into_inner() { - (mut b, Ok(t)) => { - let n = b.consume_from(m); - - b.ret((n, t)) - }, - (b, Err(e)) => b.err(e), +pub fn matched_by(f: F) -> impl Parser + where F: Parser { + move |i: I| { + let m = i.mark(); + + match f.parse(i) { + (mut b, Ok(t)) => { + let n = b.consume_from(m); + + (b, Ok((n, t))) + }, + (b, Err(e)) => (b, Err(e)), + } } } /// Applies the parser `F` without consuming any input. /// /// ``` -/// use chomp::prelude::{parse_only, take}; +/// use chomp::prelude::{Parser, parse_only, take}; /// use chomp::combinators::look_ahead; /// -/// let p = |i| look_ahead(i, |i| take(i, 4)).bind(|i, t| take(i, 7).map(|u| (t, u))); +/// let p = look_ahead(take(4)).bind(|t| take(7).map(move |u| (t, u))); /// /// assert_eq!(parse_only(p, b"testing"), Ok((&b"test"[..], &b"testing"[..]))); /// ``` #[inline] -pub fn look_ahead(i: I, f: F) -> ParseResult - where F: FnOnce(I) -> ParseResult { - let m = i.mark(); - - match f(i).into_inner() { - (b, Ok(t)) => b.restore(m).ret(t), - (b, Err(t)) => b.restore(m).err(t), +pub fn look_ahead(f: F) -> impl Parser + where F: Parser { + move |i: I| { + let m = i.mark(); + + match f.parse(i) { + (b, Ok(t)) => (b.restore(m), Ok(t)), + (b, Err(t)) => (b.restore(m), Err(t)), + } } } #[cfg(test)] mod test { - use types::{Input, ParseResult}; - use primitives::IntoInner; + use types::{Parser, err}; use super::*; use parsers::{Error, any, take, token, string}; #[test] fn option_test() { - assert_eq!(option(&b""[..], any, b'-').into_inner(), (&b""[..], Ok(b'-'))); - assert_eq!(option(&b"a"[..], any, b'-').into_inner(), (&b""[..], Ok(b'a'))); - assert_eq!(option(&b""[..], |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), (&b""[..], Ok(vec![]))); - assert_eq!(option(&b"a"[..], |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), (&b"a"[..], Ok(vec![]))); - assert_eq!(option(&b"ab"[..], |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), (&b""[..], Ok(vec![b'a', b'b']))); + assert_eq!(option(any(), b'-').parse(&b""[..]), (&b""[..], Ok(b'-'))); + assert_eq!(option(any(), b'-').parse(&b"a"[..]), (&b""[..], Ok(b'a'))); + assert_eq!(option(take(2), &b""[..]).parse(&b""[..]), (&b""[..], Ok(&b""[..]))); + assert_eq!(option(take(2), &b""[..]).parse(&b"a"[..]), (&b"a"[..], Ok(&b""[..]))); + assert_eq!(option(take(2), &b""[..]).parse(&b"ab"[..]), (&b""[..], Ok(&b"ab"[..]))); - assert_eq!(option(&b"a"[..], |i| token(i, b' ').map_err(|_| "token_err"), b'-').into_inner(), (&b"a"[..], Ok(b'-'))); - } - - #[test] - fn or_test() { - assert_eq!(or(&b""[..], any, any).into_inner(), (&b""[..], Err(Error::unexpected()))); - assert_eq!(or(&b"a"[..], any, any).into_inner(), (&b""[..], Ok(b'a'))); - assert_eq!(or(&b"a"[..], |i| take(i, 2), |i| take(i, 1)).into_inner(), (&b""[..], Ok(&b"a"[..]))); - assert_eq!(or(&b"ab"[..], |i| take(i, 2), |i| take(i, 1)).into_inner(), (&b""[..], Ok(&b"ab"[..]))); - assert_eq!(or(&b"a"[..], |i| token(i, b'a'), |i| token(i, b'b')).into_inner(), (&b""[..], Ok(b'a'))); - assert_eq!(or(&b"b"[..], |i| token(i, b'a'), |i| token(i, b'b')).into_inner(), (&b""[..], Ok(b'b'))); - assert_eq!(or(&b"c"[..], |i| token(i, b'a').map_err(|_| "a err"), |i| token(i, b'b').map_err(|_| "b err")).into_inner(), (&b"c"[..], Err("b err"))); + assert_eq!(option(token(b' ').map_err(|_| "token_err"), b'-').parse(&b"a"[..]), (&b"a"[..], Ok(b'-'))); } #[test] fn many_test() { - let r: (_, Result, _>) = many(&b""[..], |i| i.err("the error")).into_inner(); - assert_eq!(r, (&b""[..], Ok(vec![]))); - let r: (_, Result, _>) = many(&b"abc"[..], |i| i.err("the error")).into_inner(); - assert_eq!(r, (&b"abc"[..], Ok(vec![]))); - - let r: (_, Result, _>) = many(&b""[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Ok(vec![]))); - let r: (_, Result, _>) = many(&b"a"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Ok(vec![b'a']))); - let r: (_, Result, _>) = many(&b"aa"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); - - let r: (_, Result, _>) = many(&b"bbb"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b"bbb"[..], Ok(vec![]))); - let r: (_, Result, _>) = many(&b"abb"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b"bb"[..], Ok(vec![b'a']))); - let r: (_, Result, _>) = many(&b"aab"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many(|| err("the error")).parse(&b""[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many(|| err("the error")).parse(&b"abc"[..]); assert_eq!(r, (&b"abc"[..], Ok(vec![]))); + + let r: (_, Result, _>) = many(|| token(b'a')).parse(&b""[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many(|| token(b'a')).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many(|| token(b'a')).parse(&b"aa"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + + let r: (_, Result, _>) = many(|| token(b'a')).parse(&b"bbb"[..]); assert_eq!(r, (&b"bbb"[..], Ok(vec![]))); + let r: (_, Result, _>) = many(|| token(b'a')).parse(&b"abb"[..]); assert_eq!(r, (&b"bb"[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many(|| token(b'a')).parse(&b"aab"[..]); assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); } #[test] fn many1_test() { - let r: (_, Result, _>) = many1(&b""[..], |i| i.err("the error")).into_inner(); - assert_eq!(r, (&b""[..], Err("the error"))); - let r: (_, Result, _>) = many1(&b"abc"[..], |i| i.err("the error")).into_inner(); - assert_eq!(r, (&b"abc"[..], Err("the error"))); - - let r: (_, Result, _>) = many1(&b""[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); - let r: (_, Result, _>) = many1(&b"a"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Ok(vec![b'a']))); - let r: (_, Result, _>) = many1(&b"aa"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); - - let r: (_, Result, _>) = many1(&b"bbb"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b"bbb"[..], Err(Error::expected(b'a')))); - let r: (_, Result, _>) = many1(&b"abb"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b"bb"[..], Ok(vec![b'a']))); - let r: (_, Result, _>) = many1(&b"aab"[..], |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); + let r: (_, Result, _>) = many1(|| err("the error")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err("the error"))); + let r: (_, Result, _>) = many1(|| err("the error")).parse(&b"abc"[..]); assert_eq!(r, (&b"abc"[..], Err("the error"))); + + let r: (_, Result, _>) = many1(|| token(b'a')).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many1(|| token(b'a')).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many1(|| token(b'a')).parse(&b"aa"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + + let r: (_, Result, _>) = many1(|| token(b'a')).parse(&b"bbb"[..]); assert_eq!(r, (&b"bbb"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many1(|| token(b'a')).parse(&b"abb"[..]); assert_eq!(r, (&b"bb"[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many1(|| token(b'a')).parse(&b"aab"[..]); assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); } #[test] fn count_test() { - let r: (_, Result, _>) = count(&b""[..], 3, |i| i.err("the error")).into_inner(); - assert_eq!(r, (&b""[..], Err("the error"))); - - let r: (_, Result, _>) = count(&b""[..], 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); - let r: (_, Result, _>) = count(&b"a"[..], 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); - let r: (_, Result, _>) = count(&b"aa"[..], 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); - let r: (_, Result, _>) = count(&b"aaa"[..], 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a', b'a']))); - let r: (_, Result, _>) = count(&b"aaaa"[..], 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, (&b"a"[..], Ok(vec![b'a', b'a', b'a']))); + let r: (_, Result, _>) = count(3, || err("the error")).parse(&b""[..]); assert_eq!(r, (&b""[..], Err("the error"))); + + let r: (_, Result, _>) = count(3, || token(b'a')).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = count(3, || token(b'a')).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = count(3, || token(b'a')).parse(&b"aa"[..]); assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = count(3, || token(b'a')).parse(&b"aaa"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a', b'a']))); + let r: (_, Result, _>) = count(3, || token(b'a')).parse(&b"aaaa"[..]); assert_eq!(r, (&b"a"[..], Ok(vec![b'a', b'a', b'a']))); } #[test] fn skip_many1_test() { - assert_eq!(skip_many1(&b"bc"[..], |i| i.err::<(), _>("error")).into_inner(), (&b"bc"[..], Err("error"))); + assert_eq!(skip_many1(|| err::<(), _>("error")).parse(&b"bc"[..]), (&b"bc"[..], Err("error"))); - assert_eq!(skip_many1(&b"aabc"[..], |i| token(i, b'a')).into_inner(), (&b"bc"[..], Ok(()))); - assert_eq!(skip_many1(&b"abc"[..], |i| token(i, b'a')).into_inner(), (&b"bc"[..], Ok(()))); - assert_eq!(skip_many1(&b"bc"[..], |i| token(i, b'a')).into_inner(), (&b"bc"[..], Err(Error::expected(b'a')))); - assert_eq!(skip_many1(&b""[..], |i| token(i, b'a')).into_inner(), (&b""[..], Err(Error::expected(b'a')))); - assert_eq!(skip_many1(&b"aaa"[..], |i| token(i, b'a')).into_inner(), (&b""[..], Ok(()))); + assert_eq!(skip_many1(|| token(b'a')).parse(&b"aabc"[..]), (&b"bc"[..], Ok(()))); + assert_eq!(skip_many1(|| token(b'a')).parse(&b"abc"[..]), (&b"bc"[..], Ok(()))); + assert_eq!(skip_many1(|| token(b'a')).parse(&b"bc"[..]), (&b"bc"[..], Err(Error::expected(b'a')))); + assert_eq!(skip_many1(|| token(b'a')).parse(&b""[..]), (&b""[..], Err(Error::expected(b'a')))); + assert_eq!(skip_many1(|| token(b'a')).parse(&b"aaa"[..]), (&b""[..], Ok(()))); } #[test] fn many_till_test() { - assert_eq!(many_till(&b"abcd"[..], any, |i| token(i, b'c')).into_inner(), (&b"d"[..], Ok(vec![b'a', b'b']))); - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abd"[..], any, |i| token(i, b'c')); - assert_eq!(r.into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(many_till(any, || token(b'c')).parse(&b"abcd"[..]), (&b"d"[..], Ok(vec![b'a', b'b']))); + let r: (_, Result, _>) = many_till(any, || token(b'c')).parse(&b"abd"[..]); assert_eq!(r, (&b""[..], Err(Error::unexpected()))); - let r: ParseResult<_, Vec, _> = many_till(&b"abcd"[..], |i| i.err(Error::expected(b'@')), |i| token(i, b'c')); - assert_eq!(r.into_inner(), (&b"abcd"[..], Err(Error::expected(b'@')))); + let r: (_, Result, _>) = many_till(|| err(Error::expected(b'@')), || token(b'c')).parse(&b"abcd"[..]); assert_eq!(r, (&b"abcd"[..], Err(Error::expected(b'@')))); // Variant to make sure error slice is propagated let mut n = 0; - let r: ParseResult<_, Vec<_>, _> = many_till(&b"abcd"[..], |i| if n == 0 { n += 1; any(i).map_err(|_| Error::expected(b'i')) } else { i.err(Error::expected(b'@')) }, |i| token(i, b'c')); - assert_eq!(r.into_inner(), (&b"bcd"[..], Err(Error::expected(b'@')))); + let r: (_, Result, _>) = many_till(|| if n == 0 { + n += 1; + any().map_err(|_| Error::expected(b'i')).boxed() + } else { + err(Error::expected(b'@')).boxed() + }, || token(b'c')).parse(&b"abcd"[..]); + assert_eq!(r, (&b"bcd"[..], Err(Error::expected(b'@')))); } #[test] fn matched_by_test() { - assert_eq!(matched_by(&b"abc"[..], any).into_inner(), (&b"bc"[..], Ok((&b"a"[..], b'a')))); - assert_eq!(matched_by(&b"abc"[..], |i| i.err::<(), _>("my error")).into_inner(), (&b"abc"[..], Err("my error"))); - assert_eq!(matched_by(&b"abc"[..], |i| any(i).map_err(|_| "any error").then(|i| i.err::<(), _>("my error"))).into_inner(), (&b"bc"[..], Err("my error"))); - assert_eq!(matched_by(&b""[..], any).into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(matched_by(any()).parse(&b"abc"[..]), (&b"bc"[..], Ok((&b"a"[..], b'a')))); + assert_eq!(matched_by(err::<(), _>("my error")).parse(&b"abc"[..], ), (&b"abc"[..], Err("my error"))); + assert_eq!(matched_by(any().map_err(|_| "any error").then(err::<(), _>("my error"))).parse(&b"abc"[..]), (&b"bc"[..], Err("my error"))); + assert_eq!(matched_by(any()).parse(&b""[..]), (&b""[..], Err(Error::unexpected()))); } #[test] fn sep_by_test() { - assert_eq!(sep_by(&b""[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![]))); - assert_eq!(sep_by(&b"a"[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![b'a']))); - assert_eq!(sep_by(&b"a;c"[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![b'a', b'c']))); - assert_eq!(sep_by(&b"a;c;"[..], any, |i| token(i, b';')).into_inner(), (&b";"[..], Ok(vec![b'a', b'c']))); - assert_eq!(sep_by(&b"abc"[..], any, |i| token(i, b';')).into_inner(), (&b"bc"[..], Ok(vec![b'a']))); - assert_eq!(sep_by(&b"a;bc"[..], any, |i| token(i, b';')).into_inner(), (&b"c"[..], Ok(vec![b'a', b'b']))); - assert_eq!(sep_by(&b"abc"[..], any, |i| token(i, b';')).into_inner(), (&b"bc"[..], Ok(vec![b'a']))); - assert_eq!(sep_by(&b"a;bc"[..], any, |i| token(i, b';')).into_inner(), (&b"c"[..], Ok(vec![b'a', b'b']))); - - assert_eq!(sep_by(&b"b"[..], |i| token(i, b'a'), |i| token(i, b';')).into_inner(), (&b"b"[..], Ok(vec![]))); - assert_eq!(sep_by(&b"a--c-"[..], any, |i| string(i, b"--")).into_inner(), (&b"-"[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by(any, || token(b';')).parse(&b""[..]), (&b""[..], Ok(vec![]))); + assert_eq!(sep_by(any, || token(b';')).parse(&b"a"[..]), (&b""[..], Ok(vec![b'a']))); + assert_eq!(sep_by(any, || token(b';')).parse(&b"a;c"[..]), (&b""[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by(any, || token(b';')).parse(&b"a;c;"[..]), (&b";"[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by(any, || token(b';')).parse(&b"abc"[..]), (&b"bc"[..], Ok(vec![b'a']))); + assert_eq!(sep_by(any, || token(b';')).parse(&b"a;bc"[..]), (&b"c"[..], Ok(vec![b'a', b'b']))); + assert_eq!(sep_by(any, || token(b';')).parse(&b"abc"[..]), (&b"bc"[..], Ok(vec![b'a']))); + assert_eq!(sep_by(any, || token(b';')).parse(&b"a;bc"[..]), (&b"c"[..], Ok(vec![b'a', b'b']))); + + assert_eq!(sep_by(|| token(b'a'), || token(b';')).parse(&b"b"[..]), (&b"b"[..], Ok(vec![]))); + assert_eq!(sep_by(any, || string(b"--")).parse(&b"a--c-"[..]), (&b"-"[..], Ok(vec![b'a', b'c']))); // Incomplete becasue there might be another separator or item to be read - let r: ParseResult<_, Vec<_>, _> = sep_by(&b""[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - - let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a"[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a;"[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b";"[..], Ok(vec![b'a']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a;c"[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'c']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a;c;"[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b";"[..], Ok(vec![b'a', b'c']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a--c-"[..], any, |i| string(i, b"--")); - assert_eq!(r.into_inner(), (&b"-"[..], Ok(vec![b'a', b'c']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by(&b"aaa--a"[..], |i| string(i, b"aaa"), |i| string(i, b"--")); - assert_eq!(r.into_inner(), (&b"--a"[..], Ok(vec![&b"aaa"[..]]))); + let r: (_, Result, _>) = sep_by(any, || token(b';')).parse(&b""[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = sep_by(any, || token(b';')).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = sep_by(any, || token(b';')).parse(&b"a;"[..]); assert_eq!(r, (&b";"[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = sep_by(any, || token(b';')).parse(&b"a;c"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'c']))); + let r: (_, Result, _>) = sep_by(any, || token(b';')).parse(&b"a;c;"[..]); assert_eq!(r, (&b";"[..], Ok(vec![b'a', b'c']))); + let r: (_, Result, _>) = sep_by(any, || string(b"--")).parse(&b"a--c-"[..]); assert_eq!(r, (&b"-"[..], Ok(vec![b'a', b'c']))); + let r: (_, Result, _>) = sep_by(|| string(b"aaa"), || string(b"--")).parse(&b"aaa--a"[..]); assert_eq!(r, (&b"--a"[..], Ok(vec![&b"aaa"[..]]))); } #[test] fn sep_by1_test() { - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b""[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b""[..], Err(Error::unexpected()))); - - let r: ParseResult<_, Vec<()>, _> = sep_by1(&b"b"[..], |i| i.err("my err"), |i| token(i, b';').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), (&b"b"[..], Err("my err"))); + let r: (_, Result, _>) = sep_by1(any, || token(b';')).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::unexpected()))); + let r: (_, Result, _>) = sep_by1(|| err("my err"), || token(b';').map_err(|_| "token_err")).parse(&b"b"[..]); assert_eq!(r, (&b"b"[..], Err("my err"))); + let r: (_, Result, _>) = sep_by1(any, || token(b';')).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::unexpected()))); + let r: (_, Result, _>) = sep_by1(|| token(b'a'), || token(b';')).parse(&b"b"[..]); assert_eq!(r, (&b"b"[..], Err(Error::expected(b'a')))); - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b""[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(sep_by1(any, || token(b';')).parse(&b"a"[..]), (&b""[..], Ok(vec![b'a']))); + assert_eq!(sep_by1(any, || token(b';')).parse(&b"a;c"[..]), (&b""[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by1(any, || token(b';')).parse(&b"a;c;"[..]), (&b";"[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by1(any, || string(b"--")).parse(&b"a--c-"[..]), (&b"-"[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by1(any, || token(b';')).parse(&b"abc"[..]), (&b"bc"[..], Ok(vec![b'a']))); + assert_eq!(sep_by1(any, || token(b';')).parse(&b"a;bc"[..]), (&b"c"[..], Ok(vec![b'a', b'b']))); - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"b"[..], |i| token(i, b'a'), |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - - assert_eq!(sep_by1(&b"a"[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![b'a']))); - assert_eq!(sep_by1(&b"a;c"[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![b'a', b'c']))); - assert_eq!(sep_by1(&b"a;c;"[..], any, |i| token(i, b';')).into_inner(), (&b";"[..], Ok(vec![b'a', b'c']))); - assert_eq!(sep_by1(&b"a--c-"[..], any, |i| string(i, b"--")).into_inner(), (&b"-"[..], Ok(vec![b'a', b'c']))); - assert_eq!(sep_by1(&b"abc"[..], any, |i| token(i, b';')).into_inner(), (&b"bc"[..], Ok(vec![b'a']))); - assert_eq!(sep_by1(&b"a;bc"[..], any, |i| token(i, b';')).into_inner(), (&b"c"[..], Ok(vec![b'a', b'b']))); - - assert_eq!(sep_by1(&b"abc"[..], any, |i| token(i, b';')).into_inner(), (&b"bc"[..], Ok(vec![b'a']))); - assert_eq!(sep_by1(&b"a;bc"[..], any, |i| token(i, b';')).into_inner(), (&b"c"[..], Ok(vec![b'a', b'b']))); + assert_eq!(sep_by1(any, || token(b';')).parse(&b"abc"[..]), (&b"bc"[..], Ok(vec![b'a']))); + assert_eq!(sep_by1(any, || token(b';')).parse(&b"a;bc"[..]), (&b"c"[..], Ok(vec![b'a', b'b']))); // Incomplete becasue there might be another separator or item to be read - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b""[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b""[..], Err(Error::unexpected()))); - - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a"[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a;"[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b";"[..], Ok(vec![b'a']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a;c"[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'c']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a;c;"[..], any, |i| token(i, b';')); - assert_eq!(r.into_inner(), (&b";"[..], Ok(vec![b'a', b'c']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a--c-"[..], any, |i| string(i, b"--")); - assert_eq!(r.into_inner(), (&b"-"[..], Ok(vec![b'a', b'c']))); - - let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"aaa--a"[..], |i| string(i, b"aaa"), |i| string(i, b"--")); - assert_eq!(r.into_inner(), (&b"--a"[..], Ok(vec![&b"aaa"[..]]))); + let r: (_, Result, _>) = sep_by1(any, || token(b';')).parse(&b""[..]); assert_eq!(r, (&b""[..], Err(Error::unexpected()))); + let r: (_, Result, _>) = sep_by1(any, || token(b';')).parse(&b"a"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = sep_by1(any, || token(b';')).parse(&b"a;"[..]); assert_eq!(r, (&b";"[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = sep_by1(any, || token(b';')).parse(&b"a;c"[..]); assert_eq!(r, (&b""[..], Ok(vec![b'a', b'c']))); + let r: (_, Result, _>) = sep_by1(any, || token(b';')).parse(&b"a;c;"[..]); assert_eq!(r, (&b";"[..], Ok(vec![b'a', b'c']))); + let r: (_, Result, _>) = sep_by1(any, || string(b"--")).parse(&b"a--c-"[..]); assert_eq!(r, (&b"-"[..], Ok(vec![b'a', b'c']))); + let r: (_, Result, _>) = sep_by1(|| string(b"aaa"), || string(b"--")).parse(&b"aaa--a"[..]); assert_eq!(r, (&b"--a"[..], Ok(vec![&b"aaa"[..]]))); } #[test] fn look_ahead_test() { - assert_eq!(look_ahead(&b"abc"[..], any).into_inner(), (&b"abc"[..], Ok(b'a'))); - assert_eq!(look_ahead(&b"a"[..], |i| string(i, b"abc")).into_inner(), (&b"a"[..], Err(Error::expected(b'b')))); - assert_eq!(look_ahead(&b"aa"[..], |i| token(i, b'a').then(|i| token(i, b'b')).map_err(|_| "err")).into_inner(), (&b"aa"[..], Err("err"))); + assert_eq!(look_ahead(any()).parse(&b"abc"[..]), (&b"abc"[..], Ok(b'a'))); + assert_eq!(look_ahead(string(b"abc")).parse(&b"a"[..]), (&b"a"[..], Err(Error::expected(b'b')))); + assert_eq!(look_ahead(token(b'a').then(token(b'b')).map_err(|_| "err")).parse(&b"aa"[..]), (&b"aa"[..], Err("err"))); } } diff --git a/src/lib.rs b/src/lib.rs index 74a0eca1..fa8ab2ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +// TODO: Rewrite //! Chomp is a fast monadic-style parser combinator library for the Rust programming language. It was //! written as the culmination of the experiments detailed in these blog posts: //! @@ -14,6 +15,7 @@ //! # Example //! //! ``` +//! #![feature(conservative_impl_trait)] //! # #[macro_use] extern crate chomp; //! # fn main() { //! use chomp::prelude::*; @@ -24,20 +26,20 @@ //! last: B, //! } //! -//! fn name(i: I) -> SimpleResult> { -//! parse!{i; +//! fn name() -> impl Parser, Error=Error> { +//! parse!{ //! let first = take_while1(|c| c != b' '); //! token(b' '); // skipping this char //! let last = take_while1(|c| c != b'\n'); //! -//! ret Name{ +//! ret(Name{ //! first: first, //! last: last, -//! } +//! }) //! } //! } //! -//! assert_eq!(parse_only(name, "Martin Wernstål\n".as_bytes()), Ok(Name{ +//! assert_eq!(parse_only(name(), "Martin Wernstål\n".as_bytes()), Ok(Name{ //! first: &b"Martin"[..], //! last: "Wernstål".as_bytes() //! })); @@ -93,14 +95,14 @@ //! # #[macro_use] extern crate chomp; //! # fn main() { //! # use chomp::prelude::*; -//! # let r = parse_only(parser!{ +//! # let r = parse_only( //! satisfy(|c| { //! match c { //! b'c' | b'h' | b'a' | b'r' => true, //! _ => false, //! } //! }) -//! # }, b"h"); +//! # , b"h"); //! # assert_eq!(r, Ok(b'h')); //! # } //! ``` @@ -141,22 +143,23 @@ //! A Chomp parser with a similar structure looks like this: //! //! ``` +//! #![feature(conservative_impl_trait)] //! # #[macro_use] extern crate chomp; //! # use chomp::prelude::*; -//! fn f(i: I) -> SimpleResult { -//! parse!{i; +//! fn f() -> impl Parser> { +//! parse!{ //! let a = digit(); //! let b = digit(); //! string(b"missiles"); -//! ret (a, b, a + b) +//! ret((a, b, a + b)) //! } //! } //! -//! fn digit(i: I) -> SimpleResult { -//! satisfy(i, |c| b'0' <= c && c <= b'9').map(|c| c - b'0') +//! fn digit() -> impl Parser> { +//! satisfy(|c| b'0' <= c && c <= b'9').map(|c| c - b'0') //! } //! # fn main() { -//! # let r = parse_only(f, b"33missiles"); +//! # let r = parse_only(f(), b"33missiles"); //! # assert_eq!(r, Ok((3, 3, 6))); //! # } //! ``` @@ -199,6 +202,7 @@ //! The built-in `chomp::parsers::Error` type is zero-sized and carry no error-information. This //! increases performance somewhat. +#![feature(conservative_impl_trait)] #![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, @@ -236,12 +240,10 @@ pub mod ascii; pub mod buffer; pub mod combinators; pub mod parsers; -pub mod primitives; pub mod types; pub use parse::parse_only; pub use parse::parse_only_str; -pub use parse::run_parser; /// Basic prelude. pub mod prelude { @@ -264,14 +266,11 @@ pub mod prelude { take_while1, token, }; - pub use parsers::{ - Error, - SimpleResult, - }; + pub use parsers::Error; + pub use combinators::{ count, option, - or, either, many, many1, @@ -282,11 +281,16 @@ pub mod prelude { skip_many1, matched_by, }; + pub use types::{ + ret, + err, + from_result, + }; pub use types::{ Buffer, Input, U8Input, - ParseResult, + Parser, }; pub use either::*; diff --git a/src/macros.rs b/src/macros.rs index d3a316d4..7d40ea16 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,27 +1,28 @@ /// Macro emulating `do`-notation for the parser monad, automatically threading the linear type. /// /// ``` +/// # #![feature(conservative_impl_trait)] /// # #[macro_use] extern crate chomp; /// # fn main() { /// # use chomp::prelude::*; -/// # fn parser(i: I, _s: &str) -> ParseResult { i.ret(()) } -/// # fn other_parser(i: I) -> ParseResult { i.ret(23) } +/// # fn parser(_s: &str) -> impl Parser { ret(()) } +/// # fn other_parser() -> impl Parser { ret(23) } /// # fn do_something(_i: u8) -> u32 { 23 } /// # let input = &b"foo"[..]; -/// # let _r: ParseResult<_, _, ()> = -/// parse!{input; +/// # let _r: (_, Result<_, ()>) = +/// parse!{ /// parser("parameter"); /// let value = other_parser(); /// -/// ret do_something(value) +/// ret(do_something(value)) /// } -/// # ; -/// # let _r: ParseResult<_, _, ()> = +/// # .parse(input); +/// # let _r: (_, Result<_, ()>) = /// // is equivalent to: -/// parser(input, "parameter").bind(|i, _| -/// other_parser(i).bind(|i, value| -/// i.ret(do_something(value)))) -/// # ; +/// parser("parameter").bind(|_| +/// other_parser().bind(|value| +/// ret(do_something(value)))) +/// # .parse(input); /// # } /// ``` /// @@ -30,9 +31,10 @@ /// Parsing into a struct using the basic provided parsers: /// /// ``` +/// # #![feature(conservative_impl_trait)] /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::prelude::{Buffer, Error, Input, ParseResult, parse_only, take_while1, token}; +/// use chomp::prelude::{Buffer, Input, Error, Parser, parse_only, take_while1, token, ret}; /// /// #[derive(Debug, Eq, PartialEq)] /// struct Name { @@ -40,20 +42,20 @@ /// last: B, /// } /// -/// fn parser>(i: I) -> ParseResult, Error> { -/// parse!{i; +/// fn parser>() -> impl Parser, Error=Error> { +/// parse!{ /// let first = take_while1(|c| c != b' '); /// token(b' '); /// let last = take_while1(|c| c != b'\n'); /// -/// ret @ _, Error: Name{ +/// ret(Name{ /// first: first, /// last: last, -/// } +/// }) /// } /// } /// -/// assert_eq!(parse_only(parser, "Martin Wernstål\n".as_bytes()), Ok(Name{ +/// assert_eq!(parse_only(parser(), "Martin Wernstål\n".as_bytes()), Ok(Name{ /// first: &b"Martin"[..], /// last: "Wernstål".as_bytes() /// })); @@ -64,24 +66,25 @@ /// operator to make it more succint: /// /// ``` +/// # #![feature(conservative_impl_trait)] /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::prelude::{U8Input, SimpleResult, parse_only, string, token}; +/// use chomp::prelude::{U8Input, Parser, Error, parse_only, string, token, ret}; /// use chomp::ascii::decimal; /// -/// fn parse_ip(i: I) -> SimpleResult { -/// parse!{i; +/// fn parse_ip() -> impl Parser> { +/// parse!{ /// string(b"ip:"); /// let a = decimal() <* token(b'.'); /// let b = decimal() <* token(b'.'); /// let c = decimal() <* token(b'.'); /// let d = decimal(); /// token(b';'); -/// ret (a, b, c, d) +/// ret((a, b, c, d)) /// } /// } /// -/// assert_eq!(parse_only(parse_ip, b"ip:192.168.0.1;"), Ok((192, 168, 0, 1))); +/// assert_eq!(parse_only(parse_ip(), b"ip:192.168.0.1;"), Ok((192, 168, 0, 1))); /// # } /// ``` /// @@ -90,7 +93,7 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::prelude::{parse_only, string}; +/// use chomp::prelude::{Parser, parse_only, string}; /// /// #[derive(Debug, Eq, PartialEq)] /// enum Log { @@ -100,8 +103,8 @@ /// Debug, /// }; /// -/// let level = |i, b, r| string(i, b).map(|_| r); -/// let log_severity = parser!{ +/// let level = |b, r| string(b).map(|_| r); +/// let log_severity = parse!{ /// level(b"ERROR", Log::Error) <|> /// level(b"WARN", Log::Warning) <|> /// level(b"INFO", Log::Info) <|> @@ -153,18 +156,19 @@ /// or by an expression which ends the block. /// /// ``` +/// # #![feature(conservative_impl_trait)] /// # #[macro_use] extern crate chomp; /// # fn main() { /// # use chomp::ascii::decimal; -/// # use chomp::prelude::{parse_only, U8Input, token, SimpleResult}; -/// # fn my_parser(i: I) -> SimpleResult { -/// parse!{i; +/// # use chomp::prelude::{parse_only, U8Input, Error, token, Parser, ret}; +/// # fn my_parser() -> impl Parser> { +/// parse!{ /// token(b':'); /// let n: u32 = decimal(); -/// ret n * 2 +/// ret(n * 2) /// } /// # } -/// # assert_eq!(parse_only(my_parser, b":21"), Ok(42)); +/// # assert_eq!(parse_only(my_parser(), b":21"), Ok(42)); /// # } /// ``` /// @@ -197,17 +201,18 @@ /// by a parameter list within parentheses. The parentheses are mandatory. /// /// ``` +/// # #![feature(conservative_impl_trait)] /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::prelude::{parse_only, U8Input, SimpleResult}; -/// # fn my_parser(i: I) -> SimpleResult { -/// fn do_it<'a, I: U8Input>(i: I, s: &'a str) -> SimpleResult { i.ret(s) } +/// # use chomp::prelude::{parse_only, U8Input, Parser, ret}; +/// # fn my_parser() -> impl Parser { +/// fn do_it<'a, I: U8Input>(s: &'a str) -> impl Parser { ret(s) } /// -/// parse!{i; +/// parse!{ /// do_it("second parameter") /// } /// # } -/// # assert_eq!(parse_only(my_parser, b":21"), Ok("second parameter")); +/// # assert_eq!(parse_only(my_parser(), b":21"), Ok("second parameter")); /// # } /// ``` /// @@ -219,9 +224,9 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::prelude::{parse_only, Input}; +/// # use chomp::prelude::{parse_only, ret}; /// let r: Result<_, (_, ())> = parse_only( -/// parser!{ ret "some success data" }, +/// parse!{ ret("some success data") }, /// b"input data" /// ); /// @@ -237,8 +242,8 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::prelude::{parse_only, Input}; -/// let r = parse_only(parser!{ err @ u32, _: "some error data" }, b"input data"); +/// # use chomp::prelude::{parse_only, err}; +/// let r = parse_only(parse!{ err::("some error data") }, b"input data"); /// /// assert_eq!(r, Err((&b"input data"[..], "some error data"))); /// # } @@ -247,33 +252,6 @@ /// Note that we only declare the success type (`u32` above) and leave out the type of the error /// (by using `_`) since that can be uniquely inferred. /// -/// ### Inline -/// -/// An inline expression is essentially a closure where the parser state (`Input` type) is exposed. -/// This is useful for doing eg. inline `match` statements or to delegate to another parser which -/// requires some plain Rust logic: -/// -/// ``` -/// # #[macro_use] extern crate chomp; -/// # fn main() { -/// # use chomp::prelude::{parse_only, Input, ParseResult}; -/// fn other_parser(i: I) -> ParseResult { -/// i.ret("Success!") -/// } -/// -/// let condition = true; -/// -/// let p = parser!{ -/// state -> match condition { -/// true => other_parser(state), -/// false => Input::err(state, "failure"), -/// } -/// }; -/// -/// assert_eq!(parse_only(p, b""), Ok("Success!")); -/// # } -/// ``` -/// /// ### Operators /// /// Expressions also supports using operators in between sub-expressions to make common actions @@ -291,8 +269,8 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::ascii::decimal; use chomp::prelude::{parse_only, token}; -/// let p = parser!{ decimal() <* token(b';') }; +/// # use chomp::ascii::decimal; use chomp::prelude::{Parser, parse_only, token}; +/// let p = parse!{ decimal() <* token(b';') }; /// /// assert_eq!(parse_only(p, b"123;"), Ok(123u32)); /// # } @@ -306,8 +284,8 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::prelude::{parse_only, token}; -/// let p = parser!{ token(b'a') <|> token(b'b') }; +/// # use chomp::prelude::{Parser, parse_only, token}; +/// let p = parse!{ token(b'a') <|> token(b'b') }; /// /// assert_eq!(parse_only(p, b"b"), Ok(b'b')); /// # } @@ -321,8 +299,8 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::prelude::{parse_only, token}; -/// let p = parser!{ token(b'a') >> token(b';') }; +/// # use chomp::prelude::{Parser, parse_only, token}; +/// let p = parse!{ token(b'a') >> token(b';') }; /// /// assert_eq!(parse_only(p, b"a;"), Ok(b';')); /// # } @@ -332,19 +310,6 @@ /// `Applicative` and `Monad` typeclasses, with the exception of being right-associative (the /// operators are left-associative in Haskell). /// -/// An Inline expression needs to be wrapped in parenthesis to parse (`$expr` pattern in macros -/// require `;` or `,` to be terminated at the same nesting level): -/// -/// ``` -/// # #[macro_use] extern crate chomp; -/// # fn main() { -/// # use chomp::prelude::{Input, parse_only}; -/// let p = parser!{ (i -> Input::err(i, "foo")) <|> (i -> Input::ret(i, "bar")) }; -/// -/// assert_eq!(parse_only(p, b"a;"), Ok("bar")); -/// # } -/// ``` -/// /// # Debugging /// /// Errors in Rust macros can be hard to decipher at times, especially when using very complex @@ -442,15 +407,7 @@ macro_rules! parse { ( $($t:tt)* ) => { __parse_internal!{ $($t)* } }; } -/// Internal rule to create an or-combinator, separate macro so that tests can override it. -/// -/// Cannot make a method on `Input` due to type-inference failures due to the exact implementation -/// of `or` not being fully specified. -#[macro_export] -#[doc(hidden)] -macro_rules! __parse_internal_or { - ($input:expr, $lhs:expr, $rhs:expr) => { $crate::combinators::or($input, $lhs, $rhs) }; -} +// FIXME: Update the grammar /// Actual implementation of the parse macro, hidden to make the documentation easier to read. /// @@ -463,10 +420,10 @@ macro_rules! __parse_internal { // BIND ties an expression together with the following statement // The four versions are needed to allow the empty case (no tailing allowed on the empty // case), _, $pat and $ident:$ty. - ( @BIND(($input:expr ; _) $($exp:tt)+) ) => { __parse_internal!{@EXPR($input;) $($exp)* } }; - ( @BIND(($input:expr ; _) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR($input;) $($exp)* }).bind(|i, _| __parse_internal!{i; $($tail)* }) }; - ( @BIND(($input:expr ; $name:pat) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR($input;) $($exp)* }).bind(|i, $name| __parse_internal!{i; $($tail)* }) }; - ( @BIND(($input:expr ; $name:ident : $name_ty:ty) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR($input;) $($exp)* }).bind(|i, $name : $name_ty| __parse_internal!{i; $($tail)* }) }; + ( @BIND((_) $($exp:tt)+) ) => { __parse_internal!{@EXPR() $($exp)* } }; + ( @BIND((_) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(move |_| __parse_internal!{$($tail)* }) }; + ( @BIND(($name:pat) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(move |$name| __parse_internal!{$($tail)* }) }; + ( @BIND(($name:ident : $name_ty:ty) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(move |$name : $name_ty| __parse_internal!{$($tail)* }) }; // Term ::= Ret // | Err @@ -474,83 +431,86 @@ macro_rules! __parse_internal { // | Inline // | Named // Ret ::= "ret" Typed - ( @TERM($input:expr) ret @ $t_ty:ty , $e_ty:ty : $e:expr ) => { $input.ret::<$t_ty, $e_ty>($e) }; + //( @TERM(ret @ $t_ty:ty , $e_ty:ty : $e:expr) ) => { ret::<_, $t_ty, $e_ty>($e) }; // | "ret" $expr - ( @TERM($input:expr) ret $e:expr ) => { $input.ret($e) }; + //( @TERM(ret $e:expr) ) => { ret($e) }; // Err ::= "err" Typed - ( @TERM($input:expr) err @ $t_ty:ty , $e_ty:ty : $e:expr ) => { $input.err::<$t_ty, $e_ty>($e) }; + //( @TERM(err @ $t_ty:ty , $e_ty:ty : $e:expr) ) => { err::<_, $t_ty, $e_ty>($e) }; // | "err" $expr - ( @TERM($input:expr) err $e:expr ) => { $input.err($e) }; + //( @TERM(err $e:expr) ) => { err($e) }; // '(' Expr ')' - ( @TERM($input:expr) ( $($inner:tt)* ) ) => { __parse_internal!{@EXPR($input;) $($inner)*} }; + ( @TERM(( $($inner:tt)* )) ) => { __parse_internal!{@EXPR() $($inner)*} }; // Inline ::= $ident "->" $expr - ( @TERM($input:expr) $state:ident -> $e:expr ) => { { let $state = $input; $e } }; + //( @TERM() $state:ident -> $e:expr ) => { { let $state = $input; $e } }; // Named ::= $ident '(' ($expr ',')* (',')* ')' - ( @TERM($input:expr) $func:ident ( $($param:expr),* $(,)*) ) => { $func($input, $($param),*) }; + //( @TERM() $func:ident ( $($param:expr),* $(,)*) ) => { $func($($param),*) }; + //( @TERM($parser:expr) ) => { $parser }; + + ( @TERM($($t:tt)*) ) => { $($t)* }; // EXPR groups by lowest priority item first which is then ">>" // Expr ::= ExprAlt - ( @EXPR($input:expr; $($lhs:tt)*) ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)*} }; + ( @EXPR($($lhs:tt)*) ) => { __parse_internal!{@EXPR_ALT() $($lhs)*} }; // | ExprAlt ">>" Expr - ( @EXPR($input:expr; $($lhs:tt)*) >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)*}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; + ( @EXPR($($lhs:tt)*) >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)*}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; // recurse until >> or end // unrolled: - // ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $($tail:tt)* ) => { __parse_internal!{@EXPR($input; $($lhs)* $t1) $($tail)*} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $($tail:tt)* ) => { __parse_internal!{@EXPR($input; $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} }; + // ( @EXPR($($lhs:tt)*) $t1:tt $($tail:tt)* ) => { __parse_internal!{@EXPR($($lhs)* $t1) $($tail)*} }; + ( @EXPR($($lhs:tt)*) $t1:tt ) => { __parse_internal!{@EXPR_ALT() $($lhs)* $t1} }; + ( @EXPR($($lhs:tt)*) $t1:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2} }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3} }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4} }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5} }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6} }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7} }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $($tail:tt)* ) => { __parse_internal!{@EXPR($($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} }; // ExprAlt ::= ExprSkip - ( @EXPR_ALT($input:expr; $($lhs:tt)*) ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)*} }; + ( @EXPR_ALT($($lhs:tt)*) ) => { __parse_internal!{@EXPR_SKIP() $($lhs)*} }; // | ExprSkip <|> ExprAlt - ( @EXPR_ALT($input:expr; $($lhs:tt)*) <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)*}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} }; + ( @EXPR_ALT($($lhs:tt)*) <|> $($tail:tt)* ) => { __parse_internal!{@EXPR_SKIP() $($lhs)*}.or(__parse_internal!{@EXPR_ALT() $($tail)*}) }; // recurse until <|> or end // unrolled: - // ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input; $($lhs)* $t1) $($tail)*} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3 $t4} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3 $t4}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3 $t4 $t5}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt <|> $($tail:tt)* ) => { __parse_internal_or!{$input, |i| __parse_internal!{@EXPR_SKIP(i;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}, |i| __parse_internal!{@EXPR_ALT(i;) $($tail)*}} }; - ( @EXPR_ALT($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input; $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} }; + // ( @EXPR_ALT($($lhs:tt)*) $t1:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($($lhs)* $t1) $($tail)*} }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt ) => { __parse_internal!{@EXPR_SKIP() $($lhs)* $t1} }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt <|> $($tail:tt)* ) => { (__parse_internal!{@EXPR_SKIP() $($lhs)* $t1}).or(__parse_internal!{@EXPR_ALT() $($tail)*}) }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2} }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt <|> $($tail:tt)* ) => { (__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2}).or(__parse_internal!{@EXPR_ALT() $($tail)*}) }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3} }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt <|> $($tail:tt)* ) => { (__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3}).or(__parse_internal!{@EXPR_ALT() $($tail)*}) }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4} }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt <|> $($tail:tt)* ) => { (__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4}).or(__parse_internal!{@EXPR_ALT() $($tail)*}) }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5} }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt <|> $($tail:tt)* ) => { (__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5}).or(__parse_internal!{@EXPR_ALT() $($tail)*}) }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6} }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt <|> $($tail:tt)* ) => { (__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}).or(__parse_internal!{@EXPR_ALT() $($tail)*}) }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7} }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt <|> $($tail:tt)* ) => { (__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}).or(__parse_internal!{@EXPR_ALT() $($tail)*}) }; + ( @EXPR_ALT($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} }; // ExprSkip ::= Term - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) ) => { __parse_internal!{@TERM($input) $($lhs)*} }; + ( @EXPR_SKIP($($lhs:tt)*) ) => { __parse_internal!{@TERM($($lhs)*)} }; // | Term <* ExprSkip - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)*}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) }; + ( @EXPR_SKIP($($lhs:tt)*) <* $($tail:tt)* ) => { __parse_internal!{@TERM($($lhs)*)}.skip(__parse_internal!{@EXPR_SKIP() $($tail)*}) }; // recurse until <* or end // unrolled: - // ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_SKIP($input; $($lhs)* $t1) $($tail)*} }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt ) => { __parse_internal!{@TERM($input) $($lhs)* $t1} }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)* $t1}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2} }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2 $t3} }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2 $t3}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2 $t3 $t4} }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($input) $($lhs)* $t1 $t2 $t3 $t4}.bind(|i, l| __parse_internal!{@EXPR_SKIP(i;) $($tail)*}.map(|_| l)) }; - ( @EXPR_SKIP($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_SKIP($input; $($lhs)* $t1 $t2 $t3 $t4 $t5) $($tail)*} }; + // ( @EXPR_SKIP($($lhs:tt)*) $t1:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_SKIP($($lhs)* $t1) $($tail)*} }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt ) => { __parse_internal!{@TERM($($lhs)* $t1)} }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($($lhs)* $t1)}.skip(__parse_internal!{@EXPR_SKIP() $($tail)*}) }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@TERM($($lhs)* $t1 $t2)} }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt $t2:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($($lhs)* $t1 $t2)}.skip(__parse_internal!{@EXPR_SKIP() $($tail)*}) }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@TERM($($lhs)* $t1 $t2 $t3)} }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt $t2:tt $t3:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($($lhs)* $t1 $t2 $t3)}.skip(__parse_internal!{@EXPR_SKIP() $($tail)*}) }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@TERM($($lhs)* $t1 $t2 $t3 $t4)} }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt <* $($tail:tt)* ) => { __parse_internal!{@TERM($($lhs)* $t1 $t2 $t3 $t4)}.skip(__parse_internal!{@EXPR_SKIP() $($tail)*}) }; + ( @EXPR_SKIP($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $($tail:tt)* ) => { __parse_internal!{@EXPR_SKIP($($lhs)* $t1 $t2 $t3 $t4 $t5) $($tail)*} }; // STATEMENT eats and groups a full parse! expression until the next ; ( @STATEMENT($args:tt $($data:tt)*) ) => { __parse_internal!{@BIND($args $($data)*)} }; @@ -586,97 +546,136 @@ macro_rules! __parse_internal { // Statement ::= Bind ';' // | Expr ';' // ::= 'let' $pat '=' Expr - ( $input:expr ; let $name:pat = $($tail:tt)+ ) => { __parse_internal!{@STATEMENT(($input; $name)) $($tail)+} }; + ( let $name:pat = $($tail:tt)+ ) => { __parse_internal!{@STATEMENT(($name)) $($tail)+} }; // | 'let' $ident ':' $ty '=' Expr - ( $input:expr ; let $name:ident : $name_ty:ty = $($tail:tt)+ ) => { __parse_internal!{@STATEMENT(($input; $name:$name_ty)) $($tail)+} }; + ( let $name:ident : $name_ty:ty = $($tail:tt)+ ) => { __parse_internal!{@STATEMENT(($name:$name_ty)) $($tail)+} }; // ::= Expr ';' - ( $input:expr ; $($tail:tt)+ ) => { __parse_internal!{@STATEMENT(($input; _)) $($tail)+} }; + ( $($tail:tt)+ ) => { __parse_internal!{@STATEMENT((_)) $($tail)+} }; + //( $e:expr ) => { $e }; // Empty - ( $input:expr ) => { $input }; - ( $input:expr ; ) => { $input }; -} - -/// Macro wrapping an invocation to ``parse!`` in a closure, useful for creating parsers inline. -/// -/// ``` -/// # #[macro_use] extern crate chomp; -/// # fn main() { -/// use chomp::prelude::{parse_only, string}; -/// -/// let r = parser!{ string(b"ab") <|> string(b"ac") }; -/// -/// assert_eq!(parse_only(r, b"ac"), Ok(&b"ac"[..])); -/// # } -/// ``` -#[macro_export] -macro_rules! parser { - ( $($t:tt)* ) => { |i| parse!{i; $($t)* } } + //( ) => { }; } +// FIXME: Update #[cfg(test)] mod test { - /// Override the or-combinator used by parse! to make it possible to use the simplified - /// test-types. - macro_rules! __parse_internal_or { - ($input:expr, $lhs:expr, $rhs:expr) => { - { - let Input(i) = $input; - - match ($lhs)(Input(i)) { - Data::Value(j, t) => Data::Value(j, t), - Data::Error(_, _) => ($rhs)(Input(i)), - } - } - }; + /// Simplified implementation of the Input type, no Copy + #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] + struct Input(i64); + + fn ret(t: T) -> impl FnOnce(Input) -> (Input, Result) { + move |i| (i, Ok(t)) } - /// Simplified implementation of the emulated monad using linear types. - #[derive(Debug, Eq, PartialEq)] - struct Input(i64); - /// Simplified implementation of the emulated monad using linear types. - #[derive(Debug, Eq, PartialEq)] - enum Data { - Value(i64, T), - Error(i64, E), + fn err(e: E) -> impl FnOnce(Input) -> (Input, Result) { + move |i| (i, Err(e)) } - impl Input { - fn ret(self, t: T) -> Data { - Data::Value(self.0, t) + trait Parser { + type Output; + type Error; + + fn parse(self, Input) -> (Input, Result); + + fn bind(self, f: F) -> BindParser + where F: FnOnce(Self::Output) -> R, + R: Parser, + Self: Sized { + BindParser { p: self, f: f } + } + + fn or

(self, p: P) -> OrParser + where P: Parser, + Self: Sized { + OrParser{ p: self, q: p } + } + fn skip

(self, p: P) -> SkipParser + where P: Parser, + Self: Sized { + SkipParser{ p: self, q: p } } + } + + struct BindParser + where P: Parser, + F: FnOnce(P::Output) -> R, + R: Parser { + p: P, + f: F, + } - fn err(self, e: E) -> Data { - Data::Error(self.0, e) + impl Parser for BindParser + where P: Parser, + F: FnOnce(P::Output) -> R, + R: Parser { + type Output = R::Output; + type Error = R::Error; + + #[inline] + fn parse(self, i: Input) -> (Input, Result) { + match self.p.parse(i) { + (i, Ok(t)) => (self.f)(t).parse(i), + (i, Err(e)) => (i, Err(e)), + } } } - impl Data { - fn bind(self, f: F) -> Data - where F: FnOnce(Input, T) -> Data, - V: From { - match self { - // Embedded f(Input(i), t).map_err(From::from), - // reason is that the API parse! uses is only ret, err, bind and map (in addition - // to the __parse_internal_or macro). - Data::Value(i, t) => match f(Input(i), t) { - Data::Value(i, t) => Data::Value(i, t), - Data::Error(i, e) => Data::Error(i, From::from(e)), - }, - Data::Error(i, e) => Data::Error(i, From::from(e)), + struct OrParser { + p: P, + q: Q, + } + + impl Parser for OrParser + where P: Parser, + Q: Parser { + type Output = P::Output; + type Error = P::Error; + + fn parse(self, i: Input) -> (Input, Result) { + let m = i.clone(); + + match self.p.parse(i) { + (i, Ok(d)) => (i, Ok(d)), + (_, Err(_)) => self.q.parse(m), } } + } - fn map(self, f: F) -> Data - where F: FnOnce(T) -> U { - match self { - Data::Value(i, t) => Data::Value(i, f(t)), - Data::Error(i, e) => Data::Error(i, e), + struct SkipParser { + p: P, + q: Q, + } + + impl Parser for SkipParser + where P: Parser, + Q: Parser { + type Output = P::Output; + type Error = P::Error; + + fn parse(self, i: Input) -> (Input, Result) { + // Merge of p.bind(|t| q.map(|_| t)) + match self.p.parse(i) { + (i, Ok(t)) => match self.q.parse(i) { + (i, Ok(_)) => (i, Ok(t)), + (i, Err(e)) => (i, Err(e)), + }, + (i, Err(e)) => (i, Err(e)), } } } + impl Parser for F + where F: FnOnce(Input) -> (Input, Result) { + type Output = T; + type Error = E; + + fn parse(self, i: Input) -> (Input, Result) { + self(i) + } + } + #[test] fn empty() { let i = 123; @@ -694,433 +693,482 @@ mod test { } #[test] - fn ret() { + fn ret_test() { let i = Input(123); - // Type annotation necessary since ret leaves E free - let r: Data<_, ()> = parse!{i; ret "foo"}; + let r: (_, Result<_, ()>) = parse!{ret("foo")}.parse(i); - assert_eq!(r, Data::Value(123, "foo")); + assert_eq!(r, (Input(123), Ok("foo"))); } #[test] - fn ret_typed() { + fn ret_test_typed() { let i = Input(123); - let r = parse!{i; ret @ _, (): "foo"}; + let r = parse!{ret::<_, ()>("foo")}; - assert_eq!(r, Data::Value(123, "foo")); + assert_eq!(r.parse(i), (Input(123), Ok("foo"))); } #[test] - fn ret_typed2() { + fn ret_test_typed2() { let i = Input(123); - let r = parse!{i; ret @ &str, (): "foo"}; + let r = parse!{ret::<&str, ()>("foo")}; - assert_eq!(r, Data::Value(123, "foo")); + assert_eq!(r.parse(i), (Input(123), Ok("foo"))); } #[test] - fn err() { + fn err_test() { let i = Input(123); // Type annotation necessary since err leaves T free - let r: Data<(), _> = parse!{i; err "foo"}; + let r: (_, Result<(), _>) = parse!{err("foo")}.parse(i); - assert_eq!(r, Data::Error(123, "foo")); + assert_eq!(r, (Input(123), Err("foo"))); } #[test] - fn err_typed() { + fn err_test_typed() { let i = Input(123); - let r = parse!{i; err @(), _: "foo"}; + let r = parse!{err::<(), _>("foo")}; - assert_eq!(r, Data::Error(123, "foo")); + assert_eq!(r.parse(i), (Input(123), Err("foo"))); } #[test] - fn err_typed2() { + fn err_test_typed2() { let i = Input(123); - let r = parse!{i; err @(), &str: "foo"}; + let r = parse!{err::<(), &str>("foo")}; - assert_eq!(r, Data::Error(123, "foo")); + assert_eq!(r.parse(i), (Input(123), Err("foo"))); } #[test] fn action() { - fn doit(i: Input) -> Data<&'static str, ()> { - Data::Value(i.0, "doit") + fn doit() -> impl Parser { + move |i| (i, Ok("doit")) } let i = Input(123); - let r = parse!(i; doit()); + let r = parse!(doit()); - assert_eq!(r, Data::Value(123, "doit")); + assert_eq!(r.parse(i), (Input(123), Ok("doit"))); } #[test] fn action2() { - fn doit(i: Input, p: &str) -> Data<&str, ()> { - Data::Value(i.0, p) + fn doit<'a>(p: &'a str) -> impl Parser { + move |i| (i, Ok(p)) } let i = Input(123); - let r = parse!(i; doit("doit")); + let r = parse!(doit("doit")); - assert_eq!(r, Data::Value(123, "doit")); + assert_eq!(r.parse(i), (Input(123), Ok("doit"))); } #[test] fn action3() { - fn doit(i: Input, p: &str, u: u32) -> Data<(&str, u32), ()> { - Data::Value(i.0, (p, u)) + fn doit<'a>(p: &'a str, u: u32) -> impl Parser { + move |i| (i, Ok((p, u))) } let i = Input(123); - let r = parse!(i; doit("doit", 1337)); + let r = parse!(doit("doit", 1337)); - assert_eq!(r, Data::Value(123, ("doit", 1337))); + assert_eq!(r.parse(i), (Input(123), Ok(("doit", 1337)))); } #[test] fn two_actions() { - fn doit(i: Input) -> Data { - assert_eq!(i.0, 123); + fn doit() -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, 1) + (Input(321), Ok(1)) + } } - fn something(i: Input) -> Data { - assert_eq!(i.0, 321); + fn something() -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 321); - Data::Value(123, 2) + (Input(123), Ok(2)) + } } let i = Input(123); - let r = parse!(i; doit(); something()); + let r = parse!(doit(); something()); - assert_eq!(r, Data::Value(123, 2)); + assert_eq!(r.parse(i), (Input(123), Ok(2))); } #[test] fn two_actions2() { - fn doit(i: Input, n: u32) -> Data { - assert_eq!(i.0, 123); + fn doit(n: u32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, n) + (Input(321), Ok(n)) + } } - fn something(i: Input, n: u32) -> Data { - assert_eq!(i.0, 321); + fn something(n: u32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 321); - Data::Value(123, n) + (Input(123), Ok(n)) + } } let i = Input(123); - let r = parse!(i; doit(22); something(33)); + let r = parse!(doit(22); something(33)); - assert_eq!(r, Data::Value(123, 33)); + assert_eq!(r.parse(i), (Input(123), Ok(33))); } #[test] fn two_actions3() { - fn doit(i: Input, n: u32, x: i32) -> Data<(u32, i32), ()> { - assert_eq!(i.0, 123); + fn doit(n: u32, x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, (n, x)) + (Input(321), Ok((n, x))) + } } - fn something(i: Input, n: u32, x: i32) -> Data<(u32, i32), ()> { - assert_eq!(i.0, 321); + fn something(n: u32, x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 321); - Data::Value(123, (n, x)) + (Input(123), Ok((n, x))) + } } let i = Input(123); - let r = parse!(i; doit(22, 1); something(33, 2)); + let r = parse!(doit(22, 1); something(33, 2)); - assert_eq!(r, Data::Value(123, (33, 2))); + assert_eq!(r.parse(i), (Input(123), Ok((33, 2)))); } #[test] fn action_ret() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!(i1; doit(2); ret 5); - let r2 = parse!(i2; doit(2); ret @ _, (): 5); + let r1: (_, Result<_, ()>) = parse!(doit(2); ret(5)).parse(i1); + let r2 = parse!(doit(2); ret::<_, ()>(5)).parse(i2); - assert_eq!(r1, Data::Value(321, 5)); - assert_eq!(r2, Data::Value(321, 5)); + assert_eq!(r1, (Input(321), Ok(5))); + assert_eq!(r2, (Input(321), Ok(5))); } #[test] fn action_ret2() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } - fn something(i: Input, n: u32, x: i32) -> Data<(u32, i32), ()> { - assert_eq!(i.0, 321); + fn something(n: u32, x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 321); - Data::Value(111, (n, x)) + (Input(111), Ok((n, x))) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; doit(2); something(4, 5); ret 5}; - let r2 = parse!{i2; doit(2); something(4, 5); ret @ _, (): 5}; + let r1: (_, Result<_, ()>) = parse!{doit(2); something(4, 5); ret(5)}.parse(i1); + let r2 = parse!{doit(2); something(4, 5); ret::<_, ()>(5)}.parse(i2); - assert_eq!(r1, Data::Value(111, 5)); - assert_eq!(r2, Data::Value(111, 5)); + assert_eq!(r1, (Input(111), Ok(5))); + assert_eq!(r2, (Input(111), Ok(5))); } #[test] fn bind() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let n = doit(40); ret n + 2}; - let r2 = parse!{i2; let n = doit(40); ret @ _, (): n + 2}; + let r1: (_, Result<_, ()>) = parse!{let n = doit(40); ret(n + 2)}.parse(i1); + let r2 = parse!{let n = doit(40); ret::<_, ()>(n + 2)}.parse(i2); - assert_eq!(r1, Data::Value(321, 42)); - assert_eq!(r2, Data::Value(321, 42)); + assert_eq!(r1, (Input(321), Ok(42))); + assert_eq!(r2, (Input(321), Ok(42))); } #[test] fn bind2() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } - fn something(i: Input, n: i32, x: u32) -> Data { - assert_eq!(i.0, 321); + fn something(n: i32, x: u32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 321); - Data::Value(111, n - x as i32) + (Input(111), Ok(n - x as i32)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let n = doit(40); let x = something(n, 4); ret x + 6}; - let r2 = parse!{i2; let n = doit(40); let x = something(n, 4); - ret @ _, (): x + 6}; + let r1: (_, Result<_, ()>) = parse!{let n = doit(40); let x = something(n, 4); ret(x + 6)}.parse(i1); + let r2 = parse!{let n = doit(40); let x = something(n, 4); ret::<_, ()>(x + 6)}.parse(i2); - assert_eq!(r1, Data::Value(111, 42)); - assert_eq!(r2, Data::Value(111, 42)); + assert_eq!(r1, (Input(111), Ok(42))); + assert_eq!(r2, (Input(111), Ok(42))); } #[test] fn bind3() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<(), u8> = parse!{i1; let n = doit(40); err n as u8 + 2}; - let r2 = parse!{i2; let n = doit(40); err @ (), u8: n as u8 + 2}; + let r1: (_, Result<(), u8>) = parse!{let n = doit(40); err(n as u8 + 2)}.parse(i1); + let r2 = parse!{let n = doit(40); err::<(), u8>(n as u8 + 2)}.parse(i2); - assert_eq!(r1, Data::Error(321, 42)); - assert_eq!(r2, Data::Error(321, 42)); + assert_eq!(r1, (Input(321), Err(42))); + assert_eq!(r2, (Input(321), Err(42))); } #[test] fn bind4() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } - fn something(i: Input, n: i32, x: u32) -> Data { - assert_eq!(i.0, 321); + fn something(n: i32, x: u32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 321); - Data::Value(111, n - x as i32) + (Input(111), Ok(n - x as i32)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<(), u8> = parse!{i1; let n = doit(40); let x = something(n, 4); err x as u8 + 6}; - let r2 = parse!{i2; let n = doit(40); let x = something(n, 4); - err @ (), u8: x as u8 + 6}; + let r1: (_, Result<(), u8>) = parse!{let n = doit(40); let x = something(n, 4); err(x as u8 + 6)}.parse(i1); + let r2 = parse!{let n = doit(40); let x = something(n, 4); err::<(), u8>(x as u8 + 6)}.parse(i2); - assert_eq!(r1, Data::Error(111, 42)); - assert_eq!(r2, Data::Error(111, 42)); + assert_eq!(r1, (Input(111), Err(42))); + assert_eq!(r2, (Input(111), Err(42))); } #[test] fn bind_then() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 111); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 111); - Data::Value(321, x) + (Input(321), Ok(x)) + } } - fn something(i: Input, n: i32, x: u32) -> Data { - assert_eq!(i.0, 123); + fn something(n: i32, x: u32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(111, n - x as i32) + (Input(111), Ok(n - x as i32)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let x = something(6, 4); doit(x)}; - let r2 = parse!{i2; let x = something(6, 4); doit(x)}; + let r1: (_, Result<_, ()>) = parse!{let x = something(6, 4); doit(x)}.parse(i1); + let r2 = parse!{let x = something(6, 4); doit(x)}.parse(i2); - assert_eq!(r1, Data::Value(321, 2)); - assert_eq!(r2, Data::Value(321, 2)); + assert_eq!(r1, (Input(321), Ok(2))); + assert_eq!(r2, (Input(321), Ok(2))); } #[test] fn bind_then2() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 111); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 111); - Data::Value(321, x) + (Input(321), Ok(x)) + } } - fn something(i: Input, n: i32, x: u32) -> Data { - assert_eq!(i.0, 123); + fn something(n: i32, x: u32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(111, n - x as i32) + (Input(111), Ok(n - x as i32)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let _x = something(6, 4); doit(3)}; - let r2 = parse!{i2; let _x = something(6, 4); doit(3)}; + let r1: (_, Result<_, ()>) = parse!{let _x = something(6, 4); doit(3)}.parse(i1); + let r2 = parse!{let _x = something(6, 4); doit(3)}.parse(i2); - assert_eq!(r1, Data::Value(321, 3)); - assert_eq!(r2, Data::Value(321, 3)); + assert_eq!(r1, (Input(321), Ok(3))); + assert_eq!(r2, (Input(321), Ok(3))); } #[test] fn bind_type() { - fn doit(i: Input, x: N) -> Data { - assert_eq!(i.0, 123); + fn doit(x: N) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let n: u64 = doit(42); ret n}; - let r2 = parse!{i2; let n: u64 = doit(42); ret @ _, (): n}; + let r1: (_, Result<_, ()>) = parse!{let n: u64 = doit(42); ret(n)}.parse(i1); + let r2 = parse!{let n: u64 = doit(42); ret::<_, ()>(n)}.parse(i2); - assert_eq!(r1, Data::Value(321, 42u64)); - assert_eq!(r2, Data::Value(321, 42u64)); + assert_eq!(r1, (Input(321), Ok(42u64))); + assert_eq!(r2, (Input(321), Ok(42u64))); } #[test] fn bind_pattern() { - fn something(i: Input, n: u32, x: u32) -> Data<(u32, u32), ()> { - assert_eq!(i.0, 123); + fn something(n: u32, x: u32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(111, (n, x)) + (Input(111), Ok((n, x))) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let (x, y) = something(2, 4); ret x + y}; - let r2 = parse!{i2; let (x, y) = something(2, 4); ret @ _, (): x + y}; + let r1: (_, Result<_, ()>) = parse!{let (x, y) = something(2, 4); ret(x + y)}.parse(i1); + let r2 = parse!{let (x, y) = something(2, 4); ret::<_, ()>(x + y)}.parse(i2); - assert_eq!(r1, Data::Value(111, 6)); - assert_eq!(r2, Data::Value(111, 6)); + assert_eq!(r1, (Input(111), Ok(6))); + assert_eq!(r2, (Input(111), Ok(6))); } #[test] fn bind_pattern2() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } - fn something(i: Input, n: i32, x: u32) -> Data<(i32, u32), ()> { - assert_eq!(i.0, 321); + fn something(n: i32, x: u32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 321); - Data::Value(111, (n, x)) + (Input(111), Ok((n, x))) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let n = doit(40); let (x, y) = something(n, 4); - ret x + y as i32}; - let r2 = parse!{i2; let n = doit(40); let (x, y) = something(n, 4); - ret @ _, (): x + y as i32}; + let r1: (_, Result<_, ()>) = parse!{let n = doit(40); let (x, y) = something(n, 4); ret(x + y as i32)}.parse(i1); + let r2 = parse!{let n = doit(40); let (x, y) = something(n, 4); ret::<_, ()>(x + y as i32)}.parse(i2); - assert_eq!(r1, Data::Value(111, 44)); - assert_eq!(r2, Data::Value(111, 44)); + assert_eq!(r1, (Input(111), Ok(44))); + assert_eq!(r2, (Input(111), Ok(44))); } #[test] fn action_err() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<(), u8> = parse!(i1; doit(2); err 5); - let r2 = parse!(i2; doit(2); err @ (), u8: 5); + let r1: (_, Result<(), u8>) = parse!(doit(2); err(5)).parse(i1); + let r2 = parse!(doit(2); err::<(), u8>(5)).parse(i2); - assert_eq!(r1, Data::Error(321, 5)); - assert_eq!(r2, Data::Error(321, 5)); + assert_eq!(r1, (Input(321), Err(5))); + assert_eq!(r2, (Input(321), Err(5))); } #[test] fn action_err2() { - fn doit(i: Input, x: i32) -> Data { - assert_eq!(i.0, 123); + fn doit(x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 123); - Data::Value(321, x) + (Input(321), Ok(x)) + } } - fn something(i: Input, n: u32, x: i32) -> Data<(u32, i32), u8> { - assert_eq!(i.0, 321); + fn something(n: u32, x: i32) -> impl Parser { + move |i: Input| { + assert_eq!(i.0, 321); - Data::Value(111, (n, x)) + (Input(111), Ok((n, x))) + } } let i1 = Input(123); let i2 = Input(123); - let r1: Data<(), u8> = parse!{i1; doit(2); something(4, 5); err 5}; - let r2 = parse!{i2; doit(2); something(4, 5); err @ (), u8: 5}; + let r1: (_, Result<(), u8>) = parse!{doit(2); something(4, 5); err(5)}.parse(i1); + let r2 = parse!{doit(2); something(4, 5); err::<(), u8>(5)}.parse(i2); - assert_eq!(r1, Data::Error(111, 5)); - assert_eq!(r2, Data::Error(111, 5)); + assert_eq!(r1, (Input(111), Err(5))); + assert_eq!(r2, (Input(111), Err(5))); } + // TODO: Replace with inline closures + /* #[test] fn inline_action() { let i = Input(123); @@ -1134,15 +1182,15 @@ mod test { } }; - assert_eq!(r, Data::Value(123, 23)); + assert_eq!(r, (Input(123), Ok(23))); } #[test] fn inline_action2() { fn doit(i: Input) -> Data { - assert_eq!(i, Input(123)); + assert_eq!(i.0, Input(123)); - Data::Value(321, 2) + (321, Ok(2)) } let i = Input(123); @@ -1157,7 +1205,7 @@ mod test { } }; - assert_eq!(r, Data::Value(321, 23)); + assert_eq!(r, (321, Ok(23))); } #[test] @@ -1168,7 +1216,7 @@ mod test { s -> s.ret::(23) }; - assert_eq!(r, Data::Value(123, 23)); + assert_eq!(r, (Input(123), Ok(23))); } #[test] @@ -1184,15 +1232,15 @@ mod test { ret @ u32, (): v + 2 }; - assert_eq!(r, Data::Value(123, 25)); + assert_eq!(r, (Input(123), Ok(25))); } #[test] fn inline_action_bind2() { fn doit(i: Input) -> Data { - assert_eq!(i, Input(123)); + assert_eq!(i.0, Input(123)); - Data::Value(321, 2) + (321, Ok(2)) } let i = Input(123); @@ -1208,19 +1256,20 @@ mod test { ret @ u32, (): v + 3 }; - assert_eq!(r, Data::Value(321, 28)); + assert_eq!(r, (321, Ok(28))); } + */ #[test] fn expr_ret() { let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let a = ret "test"; ret a}; - let r2: Data<_, ()> = parse!{i2; ret "throwaway"; ret "foo"}; + let r1: (_, Result<_, ()>) = parse!{let a = ret("test"); ret(a)}.parse(i1); + let r2: (_, Result<_, ()>) = parse!{ret("throwaway"); ret("foo")}.parse(i2); - assert_eq!(r1, Data::Value(123, "test")); - assert_eq!(r2, Data::Value(123, "foo")); + assert_eq!(r1, (Input(123), Ok("test"))); + assert_eq!(r2, (Input(123), Ok("foo"))); } #[test] @@ -1228,289 +1277,276 @@ mod test { let i1 = Input(123); let i2 = Input(123); - let r1: Data<&str, &str> = parse!{i1; let a = err "error"; ret a}; + let r1: (_, Result<&str, &str>) = parse!{let a = err("error"); ret(a)}.parse(i1); // Necessary with type annotation here since the value type is not defined in the first // statement in parse - let r2: Data<(), &str> = parse!{i2; err @ (), _: "this"; err "not this"}; + let r2: (_, Result<(), &str>) = parse!{err::<(), _>("this"); err("not this")}.parse(i2); - assert_eq!(r1, Data::Error(123, "error")); - assert_eq!(r2, Data::Error(123, "this")); + assert_eq!(r1, (Input(123), Err("error"))); + assert_eq!(r2, (Input(123), Err("this"))); } #[test] fn alt() { - fn fail(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn fail() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Error(456, ()) + (Input(456), Err(())) + } } - fn doit(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn doit() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Value(321, 2) + (Input(321), Ok(2)) + } } - let i1 = Input(123); - let i2 = Input(123); - let i3 = Input(123); - let i4 = Input(123); - - let r1 = parse!{i1; fail() <|> doit() }; - let r2 = parse!{i2; doit() <|> fail() }; - let r3 = parse!{i3; doit() <|> doit() }; - let r4 = parse!{i4; fail() <|> fail() }; - - assert_eq!(r1, Data::Value(321, 2)); - assert_eq!(r2, Data::Value(321, 2)); - assert_eq!(r3, Data::Value(321, 2)); - assert_eq!(r4, Data::Error(456, ())); + let r1 = parse!{fail() <|> doit()}; + let r2 = parse!{doit() <|> fail()}; + let r3 = parse!{doit() <|> doit()}; + let r4 = parse!{fail() <|> fail()}; + + assert_eq!(r1.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r2.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r3.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r4.parse(Input(123)), (Input(456), Err(()))); } #[test] fn alt2() { - fn fail(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn fail() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Error(456, ()) + (Input(456), Err(())) + } } - fn doit(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn doit() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Value(321, 2) + (Input(321), Ok(2)) + } } let i = Input(123); + let r1 = parse!{fail() <|> fail() <|> doit() }.parse(i); - let r1 = parse!{i; fail() <|> fail() <|> doit() }; - - assert_eq!(r1, Data::Value(321, 2)); + assert_eq!(r1, (Input(321), Ok(2))); } #[test] fn chain_alt() { - fn fail(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn fail() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Error(456, ()) + (Input(456), Err(())) + } } - fn doit(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn doit() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Value(321, 2) + (Input(321), Ok(2)) + } } - fn next(i: Input) -> Data { - assert_eq!(i, Input(321)); + fn next() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(321)); - Data::Value(322, 42) + (Input(322), Ok(42)) + } } + let r1 = parse!{fail() <|> doit(); next() }; + let r2 = parse!{doit() <|> fail(); next() }; + let r3 = parse!{fail() <|> fail(); next() }; - let i1 = Input(123); - let i2 = Input(123); - let i3 = Input(123); - - let r1 = parse!{i1; fail() <|> doit(); next() }; - let r2 = parse!{i2; doit() <|> fail(); next() }; - let r3 = parse!{i3; fail() <|> fail(); next() }; - - assert_eq!(r1, Data::Value(322, 42)); - assert_eq!(r2, Data::Value(322, 42)); - assert_eq!(r3, Data::Error(456, ())); + assert_eq!(r1.parse(Input(123)), (Input(322), Ok(42))); + assert_eq!(r2.parse(Input(123)), (Input(322), Ok(42))); + assert_eq!(r3.parse(Input(123)), (Input(456), Err(()))); } #[test] fn precedence_skip_then() { - fn a(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn a() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Value(321, 2) + (Input(321), Ok(2)) + } } - fn b(i: Input) -> Data { - assert_eq!(i, Input(321)); + fn b() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(321)); - Data::Value(322, 42) + (Input(322), Ok(42)) + } } - fn c(i: Input) -> Data { - assert_eq!(i, Input(322)); + fn c() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(322)); - Data::Value(323, 43) + (Input(323), Ok(43)) + } } - let i1 = Input(123); - let i2 = Input(123); - let i3 = Input(123); - let i4 = Input(123); - let i5 = Input(123); - let i6 = Input(123); - let i7 = Input(123); - let i_8 = Input(123); - let i9 = Input(123); - let i10 = Input(123); - let i11 = Input(123); - let i12 = Input(123); - - let r1 = parse!{i1; a() <* b() <* c()}; - let r2 = parse!{i2; a() <* b() >> c()}; - let r3 = parse!{i3; a() >> b() <* c()}; - let r4 = parse!{i4; a() >> b() >> c()}; - - let r5 = parse!{i5; (a() <* b()) <* c()}; - let r6 = parse!{i6; a() <* (b() <* c())}; - let r7 = parse!{i7; (a() <* b()) >> c()}; - let r8 = parse!{i_8; a() <* (b() >> c())}; - let r9 = parse!{i9; (a() >> b()) <* c()}; - let r10 = parse!{i10; a() >> (b() <* c())}; - let r11 = parse!{i11; (a() >> b()) >> c()}; - let r12 = parse!{i12; a() >> (b() >> c())}; - - assert_eq!(r1, Data::Value(323, 2)); - assert_eq!(r2, Data::Value(323, 43)); - assert_eq!(r3, Data::Value(323, 42)); - assert_eq!(r4, Data::Value(323, 43)); - - assert_eq!(r5, Data::Value(323, 2)); - assert_eq!(r6, Data::Value(323, 2)); - assert_eq!(r7, Data::Value(323, 43)); - assert_eq!(r8, Data::Value(323, 2)); - assert_eq!(r9, Data::Value(323, 42)); - assert_eq!(r10, Data::Value(323, 42)); - assert_eq!(r11, Data::Value(323, 43)); - assert_eq!(r12, Data::Value(323, 43)); + let r1 = parse!{a() <* b() <* c()}; + let r2 = parse!{a() <* b() >> c()}; + let r3 = parse!{a() >> b() <* c()}; + let r4 = parse!{a() >> b() >> c()}; + + let r5 = parse!{ (a() <* b()) <* c()}; + let r6 = parse!{ a() <* (b() <* c())}; + let r7 = parse!{ (a() <* b()) >> c()}; + let r8 = parse!{ a() <* (b() >> c())}; + let r9 = parse!{ (a() >> b()) <* c()}; + let r10 = parse!{ a() >> (b() <* c())}; + let r11 = parse!{(a() >> b()) >> c()}; + let r12 = parse!{ a() >> (b() >> c())}; + + assert_eq!(r1.parse(Input(123)), (Input(323), Ok(2))); + assert_eq!(r2.parse(Input(123)), (Input(323), Ok(43))); + assert_eq!(r3.parse(Input(123)), (Input(323), Ok(42))); + assert_eq!(r4.parse(Input(123)), (Input(323), Ok(43))); + + assert_eq!(r5.parse(Input(123)), (Input(323), Ok(2))); + assert_eq!(r6.parse(Input(123)), (Input(323), Ok(2))); + assert_eq!(r7.parse(Input(123)), (Input(323), Ok(43))); + assert_eq!(r8.parse(Input(123)), (Input(323), Ok(2))); + assert_eq!(r9.parse(Input(123)), (Input(323), Ok(42))); + assert_eq!(r10.parse(Input(123)), (Input(323), Ok(42))); + assert_eq!(r11.parse(Input(123)), (Input(323), Ok(43))); + assert_eq!(r12.parse(Input(123)), (Input(323), Ok(43))); } #[test] fn precedence_skip_alt() { - fn a(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn a() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Value(321, 2) + (Input(321), Ok(2)) + } } - fn b(i: Input) -> Data { - assert_eq!(i, Input(321)); + fn b() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(321)); - Data::Value(322, 42) + (Input(322), Ok(42)) + } } - fn c(i: Input) -> Data { - assert_eq!(i, Input(322)); + fn c() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(322)); - Data::Value(323, 43) + (Input(323), Ok(43)) + } } // version of c following a: - fn c_a(i: Input) -> Data { - assert_eq!(i, Input(321)); + fn c_a() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(321)); - Data::Value(323, 43) + (Input(323), Ok(43)) + } } - let i1 = Input(123); - let i2 = Input(123); - let i3 = Input(123); - let i4 = Input(123); - let i5 = Input(123); - let i6 = Input(123); - let i7 = Input(123); - let i_8 = Input(123); - let i9 = Input(123); - let i10 = Input(123); - let i11 = Input(123); - let i12 = Input(123); - - let r1 = parse!{i1; a() <* b() <* c()}; - let r2 = parse!{i2; a() <* b() <|> c()}; - let r3 = parse!{i3; a() <|> b() <* c()}; - let r4 = parse!{i4; a() <|> b() <|> c()}; - - let r5 = parse!{i5; (a() <* b()) <* c()}; - let r6 = parse!{i6; (a() <* b()) <|> c()}; - let r7 = parse!{i7; (a() <|> b()) <* c_a()}; - let r8 = parse!{i_8; (a() <|> b()) <|> c()}; - let r9 = parse!{i9; a() <* (b() <* c())}; - let r10 = parse!{i10; a() <* (b() <|> c())}; - let r11 = parse!{i11; a() <|> (b() <* c())}; - let r12 = parse!{i12; a() <|> (b() <|> c())}; - - assert_eq!(r1, Data::Value(323, 2)); - assert_eq!(r2, Data::Value(322, 2)); - assert_eq!(r3, Data::Value(321, 2)); - assert_eq!(r4, Data::Value(321, 2)); - - assert_eq!(r5, Data::Value(323, 2)); - assert_eq!(r6, Data::Value(322, 2)); - assert_eq!(r7, Data::Value(323, 2)); - assert_eq!(r8, Data::Value(321, 2)); - assert_eq!(r9, Data::Value(323, 2)); - assert_eq!(r10, Data::Value(322, 2)); - assert_eq!(r11, Data::Value(321, 2)); - assert_eq!(r12, Data::Value(321, 2)); + let r1 = parse!{a() <* b() <* c()}; + let r2 = parse!{a() <* b() <|> c()}; + let r3 = parse!{a() <|> b() <* c()}; + let r4 = parse!{a() <|> b() <|> c()}; + + let r5 = parse!{ (a() <* b()) <* c()}; + let r6 = parse!{ (a() <* b()) <|> c()}; + let r7 = parse!{ (a() <|> b()) <* c_a()}; + let r8 = parse!{ (a() <|> b()) <|> c()}; + let r9 = parse!{ a() <* (b() <* c())}; + let r10 = parse!{ a() <* (b() <|> c())}; + let r11 = parse!{ a() <|> (b() <* c())}; + let r12 = parse!{ a() <|> (b() <|> c())}; + + assert_eq!(r1.parse(Input(123)), (Input(323), Ok(2))); + assert_eq!(r2.parse(Input(123)), (Input(322), Ok(2))); + assert_eq!(r3.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r4.parse(Input(123)), (Input(321), Ok(2))); + + assert_eq!(r5.parse(Input(123)), (Input(323), Ok(2))); + assert_eq!(r6.parse(Input(123)), (Input(322), Ok(2))); + assert_eq!(r7.parse(Input(123)), (Input(323), Ok(2))); + assert_eq!(r8.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r9.parse(Input(123)), (Input(323), Ok(2))); + assert_eq!(r10.parse(Input(123)), (Input(322), Ok(2))); + assert_eq!(r11.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r12.parse(Input(123)), (Input(321), Ok(2))); } #[test] fn precedence_alt_then() { - fn a(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn a() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Value(321, 2) + (Input(321), Ok(2)) + } } - fn b(i: Input) -> Data { - assert_eq!(i, Input(321)); + fn b() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(321)); - Data::Value(322, 42) + (Input(322), Ok(42)) + } } - fn c(i: Input) -> Data { - assert_eq!(i, Input(322)); + fn c() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(322)); - Data::Value(323, 43) + (Input(323), Ok(43)) + } } // version of c with check for a's state: - fn c_a(i: Input) -> Data { - assert_eq!(i, Input(321)); + fn c_a() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(321)); - Data::Value(323, 43) + (Input(323), Ok(43)) + } } - let i1 = Input(123); - let i2 = Input(123); - let i3 = Input(123); - let i4 = Input(123); - let i5 = Input(123); - let i6 = Input(123); - let i7 = Input(123); - let i_8 = Input(123); - let i9 = Input(123); - let i10 = Input(123); - let i11 = Input(123); - let i12 = Input(123); - - let r1 = parse!{i1; a() <|> b() <|> c()}; - let r2 = parse!{i2; a() <|> b() >> c_a()}; - let r3 = parse!{i3; a() >> b() <|> c()}; - let r4 = parse!{i4; a() >> b() >> c()}; - - let r5 = parse!{i5; (a() <|> b()) <|> c()}; - let r6 = parse!{i6; (a() <|> b()) >> c_a()}; - let r7 = parse!{i7; (a() >> b()) <|> c()}; - let r8 = parse!{i_8; (a() >> b()) >> c()}; - let r9 = parse!{i9; a() <|> (b() <|> c())}; - let r10 = parse!{i10; a() <|> (b() >> c_a())}; - let r11 = parse!{i11; a() >> (b() <|> c())}; - let r12 = parse!{i12; a() >> (b() >> c())}; - - assert_eq!(r1, Data::Value(321, 2)); - assert_eq!(r2, Data::Value(323, 43)); - assert_eq!(r3, Data::Value(322, 42)); - assert_eq!(r4, Data::Value(323, 43)); - - assert_eq!(r5, Data::Value(321, 2)); - assert_eq!(r6, Data::Value(323, 43)); - assert_eq!(r7, Data::Value(322, 42)); - assert_eq!(r8, Data::Value(323, 43)); - assert_eq!(r9, Data::Value(321, 2)); - assert_eq!(r10, Data::Value(321, 2)); - assert_eq!(r11, Data::Value(322, 42)); - assert_eq!(r12, Data::Value(323, 43)); + let r1 = parse!{a() <|> b() <|> c()}; + let r2 = parse!{a() <|> b() >> c_a()}; + let r3 = parse!{a() >> b() <|> c()}; + let r4 = parse!{a() >> b() >> c()}; + + let r5 = parse!{ (a() <|> b()) <|> c()}; + let r6 = parse!{ (a() <|> b()) >> c_a()}; + let r7 = parse!{ (a() >> b()) <|> c()}; + let r8 = parse!{ (a() >> b()) >> c()}; + let r9 = parse!{ a() <|> (b() <|> c())}; + let r10 = parse!{ a() <|> (b() >> c_a())}; + let r11 = parse!{ a() >> (b() <|> c())}; + let r12 = parse!{ a() >> (b() >> c())}; + + assert_eq!(r1.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r2.parse(Input(123)), (Input(323), Ok(43))); + assert_eq!(r3.parse(Input(123)), (Input(322), Ok(42))); + assert_eq!(r4.parse(Input(123)), (Input(323), Ok(43))); + + assert_eq!(r5.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r6.parse(Input(123)), (Input(323), Ok(43))); + assert_eq!(r7.parse(Input(123)), (Input(322), Ok(42))); + assert_eq!(r8.parse(Input(123)), (Input(323), Ok(43))); + assert_eq!(r9.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r10.parse(Input(123)), (Input(321), Ok(2))); + assert_eq!(r11.parse(Input(123)), (Input(322), Ok(42))); + assert_eq!(r12.parse(Input(123)), (Input(323), Ok(43))); } + /* #[test] fn alt_inline_action() { let i = Input(123); @@ -1523,11 +1559,11 @@ mod test { }) <|> (input -> { assert_eq!(input, Input(321)); - Data::Value(333, 42) + (Input(333), Ok(42)) }) }; - assert_eq!(r, Data::Value(321, 21)); + assert_eq!(r, (Input(321), Ok(21))); } #[test] @@ -1538,15 +1574,15 @@ mod test { (input -> { assert_eq!(input, Input(123)); - Data::Value(321, 21) + (Input(321), Ok(21)) }) >> (input -> { assert_eq!(input, Input(321)); - Data::Value(333, 42) + (Input(333), Ok(42)) }) }; - assert_eq!(r, Data::Value(333, 42)); + assert_eq!(r, (Input(333), Ok(42))); } #[test] @@ -1557,30 +1593,33 @@ mod test { (input -> { assert_eq!(input, Input(123)); - Data::Value(321, 21) + (Input(321), Ok(21)) }) <* (input -> { assert_eq!(input, Input(321)); - Data::Value(333, 42) + (Input(333), Ok(42)) }) }; - assert_eq!(r, Data::Value(333, 21)); + assert_eq!(r, (Input(333), Ok(21))); } + */ // Test to make sure we do not hit the default macro iteration limit (64) #[test] fn max_alt() { - fn a(i: Input) -> Data { - assert_eq!(i, Input(123)); + fn a() -> impl Parser { + move |i: Input| { + assert_eq!(i, Input(123)); - Data::Value(321, 2) + (Input(321), Ok(2)) + } } let i = Input(123); - let r = parse!{i; a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a()}; + let r = parse!{a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a() <|> a()}; - assert_eq!(r, Data::Value(321, 2)); + assert_eq!(r.parse(i), (Input(321), Ok(2))); } } diff --git a/src/parse.rs b/src/parse.rs index 665154a4..7973cdef 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,15 +1,4 @@ -use types::{Input, ParseResult}; -use primitives::{ - IntoInner, - Primitives, -}; - -/// Runs the supplied parser over the input. -pub fn run_parser(input: I, parser: F) -> (I, Result) - where I: Input, - F: FnOnce(I) -> ParseResult { - parser(input).into_inner() -} +use types::{Input, Parser}; /// Runs the given parser on the supplied finite input. /// @@ -17,10 +6,10 @@ pub fn run_parser(input: I, parser: F) -> (I, Result) /// use chomp::prelude::{parse_only, Error}; /// use chomp::ascii::decimal; /// -/// assert_eq!(parse_only(decimal, b"123foobar"), Ok(123u32)); +/// assert_eq!(parse_only(decimal(), b"123foobar"), Ok(123u32)); /// /// // Annotation because `decimal` is generic over number types -/// let r: Result = parse_only(decimal, b"foobar"); +/// let r: Result = parse_only(decimal(), b"foobar"); /// assert_eq!(r, Err((&b"foobar"[..], Error::new()))); /// ``` /// @@ -28,38 +17,34 @@ pub fn run_parser(input: I, parser: F) -> (I, Result) /// discarded. To force a parser to consume all its input, use `eof` at the end like this: /// /// ``` +/// #![feature(conservative_impl_trait)] +/// /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::prelude::{U8Input, Error, SimpleResult, parse_only, string, eof}; -/// -/// fn my_parser(i: I) -> SimpleResult { -/// parse!{i; -/// let r = string(b"pattern"); -/// eof(); +/// use chomp::prelude::{Error, Parser, parse_only, string, eof}; /// -/// ret r -/// } -/// } +/// let parser = || string(b"pattern").skip(eof()); /// -/// assert_eq!(parse_only(my_parser, b"pattern"), Ok(&b"pattern"[..])); -/// assert_eq!(parse_only(my_parser, b"pattern and more"), +/// assert_eq!(parse_only(parser(), b"pattern"), Ok(&b"pattern"[..])); +/// assert_eq!(parse_only(parser(), b"pattern and more"), /// Err((&b" and more"[..], Error::new()))); /// # } /// ``` -pub fn parse_only<'a, I, T, E, F>(parser: F, input: &'a [I]) -> Result +#[inline] +pub fn parse_only<'a, I, F>(parser: F, input: &'a [I]) -> Result where I: Copy + PartialEq, - F: FnOnce(&'a [I]) -> ParseResult<&'a [I], T, E> { - match parser(input).into_inner() { - (_, Ok(t)) => Ok(t), + F: Parser<&'a [I]> { + match parser.parse(input) { + (_, Ok(t)) => Ok(t), (mut b, Err(e)) => Err((b.consume_remaining(), e)), } } /// Runs the given parser on the supplied string. -pub fn parse_only_str<'a, T, E, F>(parser: F, input: &'a str) -> Result - where F: FnOnce(&'a str) -> ParseResult<&'a str, T, E> { - match parser(input).into_inner() { - (_, Ok(t)) => Ok(t), +pub fn parse_only_str<'a, F>(parser: F, input: &'a str) -> Result + where F: Parser<&'a str> { + match parser.parse(input) { + (_, Ok(t)) => Ok(t), (mut b, Err(e)) => Err((b.consume_remaining(), e)), } } @@ -67,50 +52,41 @@ pub fn parse_only_str<'a, T, E, F>(parser: F, input: &'a str) -> Result("the result") + (i, Ok::<&'static str, ()>("the result")) }, b"the input"), Ok("the result")); - - assert_eq!(input, Some(b"the input".to_vec())); } #[test] fn err() { assert_eq!(parse_only(|mut i| { - i.consume(4); + Input::consume(&mut i, 4); - i.err::<(), _>("my error") + (i, Err::<(), &'static str>("my error")) }, b"the input"), Err((&b"input"[..], "my error"))); } #[test] fn inspect_input_str() { - let mut input = None; - assert_eq!(parse_only_str(|i| { - input = Some(i.to_owned()); + assert_eq!(i, "the input"); - i.ret::<_, ()>("the result") + (i, Ok::<_, ()>("the result")) }, "the input"), Ok("the result")); - - assert_eq!(input, Some("the input".to_owned())); } #[test] fn err_str() { assert_eq!(parse_only_str(|mut i| { - i.consume(4); + Input::consume(&mut i, 4); - i.err::<(), _>("my error") + (i, Err::<(), _>("my error")) }, "the input"), Err(("input", "my error"))); } } diff --git a/src/parsers.rs b/src/parsers.rs index 10f6f962..b0f62780 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -5,15 +5,11 @@ use std::mem; use types::{ Buffer, Input, - ParseResult, + Parser, }; -use primitives::Primitives; pub use self::error::Error; -/// Result returned from the basic parsers. -pub type SimpleResult = ParseResult::Token>>; - // Only export if we have backtraces enabled, in debug/test profiles the StackFrame is only used // to debug-print. #[cfg(feature="backtrace")] @@ -26,13 +22,13 @@ pub use debugtrace::StackFrame; /// ``` /// use chomp::prelude::{parse_only, any}; /// -/// assert_eq!(parse_only(any, b"abc"), Ok(b'a')); +/// assert_eq!(parse_only(any(), b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn any(mut i: I) -> SimpleResult { - match i.pop() { - Some(c) => i.ret(c), - None => i.err(Error::unexpected()), +pub fn any() -> impl Parser> { + move |mut i: I| match i.pop() { + Some(c) => (i, Ok(c)), + None => (i, Err(Error::unexpected())), } } @@ -44,14 +40,14 @@ pub fn any(mut i: I) -> SimpleResult { /// ``` /// use chomp::prelude::{parse_only, satisfy}; /// -/// assert_eq!(parse_only(|i| satisfy(i, |c| c == b'a'), b"abc"), Ok(b'a')); +/// assert_eq!(parse_only(satisfy(|c| c == b'a'), b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn satisfy(mut i: I, f: F) -> SimpleResult +pub fn satisfy(f: F) -> impl Parser> where F: FnOnce(I::Token) -> bool { - match i.peek() { - Some(c) if f(c) => { i.pop(); i.ret(c) }, - _ => i.err(Error::unexpected()), + move |mut i: I| match i.peek() { + Some(c) if f(c) => { i.pop(); (i, Ok(c)) }, + _ => (i, Err(Error::unexpected())), } } @@ -64,26 +60,26 @@ pub fn satisfy(mut i: I, f: F) -> SimpleResult /// use chomp::prelude::{parse_only, satisfy_with}; /// /// let r = parse_only( -/// |i| satisfy_with(i, |c| AsciiExt::to_ascii_uppercase(&c), |c| c == b'T'), +/// satisfy_with(|c| AsciiExt::to_ascii_uppercase(&c), |c| c == b'T'), /// b"testing"); /// /// assert_eq!(r, Ok(b'T')); /// ``` #[inline] -pub fn satisfy_with(mut i: I, f: F, p: P) -> SimpleResult +pub fn satisfy_with(f: F, p: P) -> impl Parser> where F: FnOnce(I::Token) -> T, P: FnOnce(T) -> bool { - match i.peek().map(f) { + move |mut i: I| match i.peek().map(f) { Some(c) => { if p(c.clone()) { i.pop(); - i.ret(c) + (i, Ok(c)) } else { - i.err(Error::unexpected()) + (i, Err(Error::unexpected())) } }, - _ => i.err(Error::unexpected()), + _ => (i, Err(Error::unexpected())), } } @@ -94,13 +90,13 @@ pub fn satisfy_with(mut i: I, f: F, p: P) -> SimpleRes /// ``` /// use chomp::prelude::{parse_only, token}; /// -/// assert_eq!(parse_only(|i| token(i, b'a'), b"abc"), Ok(b'a')); +/// assert_eq!(parse_only(token(b'a'), b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn token(mut i: I, t: I::Token) -> SimpleResult { - match i.peek() { - Some(c) if c == t => { i.pop(); i.ret(c) }, - _ => i.err(Error::expected(t)), +pub fn token(t: I::Token) -> impl Parser> { + move |mut i: I| match i.peek() { + Some(c) if c == t => { i.pop(); (i, Ok(c)) }, + _ => (i, Err(Error::expected(t))), } } @@ -111,13 +107,13 @@ pub fn token(mut i: I, t: I::Token) -> SimpleResult { /// ``` /// use chomp::prelude::{parse_only, not_token}; /// -/// assert_eq!(parse_only(|i| not_token(i, b'b'), b"abc"), Ok(b'a')); +/// assert_eq!(parse_only(not_token(b'b'), b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn not_token(mut i: I, t: I::Token) -> SimpleResult { - match i.peek() { - Some(c) if c != t => { i.pop(); i.ret(c) }, - _ => i.err(Error::unexpected()), +pub fn not_token(t: I::Token) -> impl Parser> { + move |mut i: I| match i.peek() { + Some(c) if c != t => { i.pop(); (i, Ok(c)) }, + _ => (i, Err(Error::unexpected())), } } @@ -129,15 +125,17 @@ pub fn not_token(mut i: I, t: I::Token) -> SimpleResult { /// ``` /// use chomp::prelude::{parse_only, peek}; /// -/// assert_eq!(parse_only(peek, b"abc"), Ok(Some(b'a'))); +/// assert_eq!(parse_only(peek(), b"abc"), Ok(Some(b'a'))); /// -/// assert_eq!(parse_only(peek, b""), Ok(None)); +/// assert_eq!(parse_only(peek(), b""), Ok(None)); /// ``` #[inline] -pub fn peek(mut i: I) -> SimpleResult> { - let t = i.peek(); +pub fn peek() -> impl Parser, Error=Error> { + |mut i: I| { + let t = i.peek(); - i.ret(t) + (i, Ok(t)) + } } /// Matches any item but does not consume it. @@ -147,13 +145,13 @@ pub fn peek(mut i: I) -> SimpleResult> { /// ``` /// use chomp::prelude::{parse_only, peek_next}; /// -/// assert_eq!(parse_only(peek_next, b"abc"), Ok(b'a')); +/// assert_eq!(parse_only(peek_next(), b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn peek_next(mut i: I) -> SimpleResult { - match i.peek() { - Some(c) => i.ret(c), - None => i.err(Error::unexpected()), +pub fn peek_next() -> impl Parser> { + move |mut i: I| match i.peek() { + Some(c) => (i, Ok(c)), + None => (i, Err(Error::unexpected())), } } @@ -164,14 +162,13 @@ pub fn peek_next(mut i: I) -> SimpleResult { /// ``` /// use chomp::prelude::{parse_only, take}; /// -/// assert_eq!(parse_only(|i| take(i, 3), b"abcd"), Ok(&b"abc"[..])); +/// assert_eq!(parse_only(take(3), b"abcd"), Ok(&b"abc"[..])); /// ``` #[inline] -pub fn take(mut i: I, num: usize) -> SimpleResult { - match i.consume(num) { - Some(b) => i.ret(b), - // TODO: Proper incomplete error here? - None => i.err(Error::unexpected()), +pub fn take(num: usize) -> impl Parser> { + move |mut i: I| match i.consume(num) { + Some(b) => (i, Ok(b)), + None => (i, Err(Error::unexpected())), } } @@ -183,7 +180,7 @@ pub fn take(mut i: I, num: usize) -> SimpleResult { /// ``` /// use chomp::prelude::{parse_only, take_while}; /// -/// let r = parse_only(|i| take_while(i, |c| c == b'a' || c == b'b'), b"abcdcba"); +/// let r = parse_only(take_while(|c| c == b'a' || c == b'b'), b"abcdcba"); /// /// assert_eq!(r, Ok(&b"ab"[..])); /// ``` @@ -193,16 +190,18 @@ pub fn take(mut i: I, num: usize) -> SimpleResult { /// ``` /// use chomp::prelude::{parse_only, take_while}; /// -/// let r = parse_only(|i| take_while(i, |c| c == b'z'), b"abcdcba"); +/// let r = parse_only(take_while(|c| c == b'z'), b"abcdcba"); /// /// assert_eq!(r, Ok(&b""[..])); /// ``` #[inline] -pub fn take_while(mut i: I, f: F) -> SimpleResult +pub fn take_while(f: F) -> impl Parser> where F: FnMut(I::Token) -> bool { - let b = i.consume_while(f); + move |mut i: I| { + let b = i.consume_while(f); - i.ret(b) + (i, Ok(b)) + } } /// Matches all items while ``f`` returns true, if at least one item matched this parser succeeds @@ -214,35 +213,39 @@ pub fn take_while(mut i: I, f: F) -> SimpleResult /// ``` /// use chomp::prelude::{parse_only, take_while1}; /// -/// let r = parse_only(|i| take_while1(i, |c| c == b'a' || c == b'b'), b"abcdcba"); +/// let r = parse_only(take_while1(|c| c == b'a' || c == b'b'), b"abcdcba"); /// /// assert_eq!(r, Ok(&b"ab"[..])); /// ``` #[inline] -pub fn take_while1(mut i: I, f: F) -> SimpleResult +pub fn take_while1(f: F) -> impl Parser> where F: FnMut(I::Token) -> bool { - let b = i.consume_while(f); + move |mut i: I| { + let b = i.consume_while(f); - if b.is_empty() { - i.err(Error::unexpected()) - } else { - i.ret(b) + if b.is_empty() { + (i, Err(Error::unexpected())) + } else { + (i, Ok(b)) + } } } /// Skips over tokens in the input until `f` returns false. /// /// ``` -/// use chomp::prelude::{parse_only, skip_while}; +/// use chomp::prelude::{Parser, skip_while}; /// -/// assert_eq!(parse_only(|i| skip_while(i, |c| c == b'a'), &b"aaabc"[..]), Ok(())); +/// assert_eq!(skip_while(|c| c == b'a').parse(&b"aaabc"[..]), (&b"bc"[..], Ok(()))); /// ``` #[inline] -pub fn skip_while(mut i: I, f: F) -> SimpleResult +pub fn skip_while(f: F) -> impl Parser> where F: FnMut(I::Token) -> bool { - i.skip_while(f); + move |mut i: I| { + i.skip_while(f); - i.ret(()) + (i, Ok(())) + } } /// Matches all items until ``f`` returns true, all items to that point will be returned as a slice @@ -254,29 +257,31 @@ pub fn skip_while(mut i: I, f: F) -> SimpleResult /// ``` /// use chomp::prelude::{parse_only, take_till}; /// -/// let r = parse_only(|i| take_till(i, |c| c == b'd'), b"abcdef"); +/// let r = parse_only(take_till(|c| c == b'd'), b"abcdef"); /// /// assert_eq!(r, Ok(&b"abc"[..])); /// ``` #[inline] -pub fn take_till(mut i: I, mut f: F) -> SimpleResult +pub fn take_till(mut f: F) -> impl Parser> where F: FnMut(I::Token) -> bool { - let mut ok = false; + move |mut i: I| { + let mut ok = false; - let b = i.consume_while(|c| { - if f(c) { - ok = true; + let b = i.consume_while(|c| { + if f(c) { + ok = true; - false + false + } else { + true + } + }); + + if ok { + (i, Ok(b)) } else { - true + (i, Err(Error::unexpected())) } - }); - - if ok { - i.ret(b) - } else { - i.err(Error::unexpected()) } } @@ -286,7 +291,7 @@ pub fn take_till(mut i: I, mut f: F) -> SimpleResult /// ``` /// use chomp::prelude::{parse_only, scan}; /// -/// let p = |i| scan(i, false, |s, c| match (s, c) { +/// let p = scan(false, |s, c| match (s, c) { /// (true, b'/') => None, /// (_, b'*') => Some(true), /// (_, _) => Some(false), @@ -295,13 +300,15 @@ pub fn take_till(mut i: I, mut f: F) -> SimpleResult /// assert_eq!(parse_only(p, b"/*test*of*scan*/ foo"), Ok(&b"/*test*of*scan*"[..])); /// ``` #[inline] -pub fn scan(mut i: I, s: S, mut f: F) -> SimpleResult +pub fn scan(s: S, mut f: F) -> impl Parser> where F: FnMut(S, I::Token) -> Option { - let mut state = Some(s); + move |mut i: I| { + let mut state = Some(s); - let b = i.consume_while(|c| { state = f(mem::replace(&mut state, None).expect("scan: Failed to obtain state, consume_while most likely called closure after end"), c); state.is_some() }); + let b = i.consume_while(|c| { state = f(mem::replace(&mut state, None).expect("scan: Failed to obtain state, consume_while most likely called closure after end"), c); state.is_some() }); - i.ret(b) + (i, Ok(b)) + } } /// Like `scan` but generalized to return the final state of the scanner. @@ -309,7 +316,7 @@ pub fn scan(mut i: I, s: S, mut f: F) -> SimpleResult None, /// (_, c) => Some(c), /// }); @@ -318,19 +325,21 @@ pub fn scan(mut i: I, s: S, mut f: F) -> SimpleResult(mut i: I, s: S, mut f: F) -> SimpleResult +pub fn run_scanner(s: S, mut f: F) -> impl Parser> where F: FnMut(S, I::Token) -> Option { - let mut state = s; - - let b = i.consume_while(|c| { - let t = f(state, c); - match t { - None => false, - Some(v) => { state = v; true } - } - }); + move |mut i: I| { + let mut state = s; + + let b = i.consume_while(|c| { + let t = f(state, c); + match t { + None => false, + Some(v) => { state = v; true } + } + }); - i.ret((b, state)) + (i, Ok((b, state))) + } } /// Matches the remainder of the buffer and returns it, always succeeds. @@ -338,13 +347,15 @@ pub fn run_scanner(mut i: I, s: S, mut f: F) -> SimpleResu /// ``` /// use chomp::prelude::{parse_only, take_remainder}; /// -/// assert_eq!(parse_only(take_remainder, b"abcd"), Ok(&b"abcd"[..])); +/// assert_eq!(parse_only(take_remainder(), b"abcd"), Ok(&b"abcd"[..])); /// ``` #[inline] -pub fn take_remainder(mut i: I) -> SimpleResult { - let b = i.consume_remaining(); +pub fn take_remainder() -> impl Parser> { + move |mut i: I| { + let b = i.consume_remaining(); - i.ret(b) + (i, Ok(b)) + } } /// Matches the given slice against the parser, returning the matched slice upon success. @@ -355,49 +366,51 @@ pub fn take_remainder(mut i: I) -> SimpleResult { /// ``` /// use chomp::prelude::{parse_only, string}; /// -/// assert_eq!(parse_only(|i| string(i, b"abc"), b"abcdef"), Ok(&b"abc"[..])); +/// assert_eq!(parse_only(string(b"abc"), b"abcdef"), Ok(&b"abc"[..])); /// ``` // TODO: Does not actually work with &str yet #[inline] -pub fn string>(mut i: I, s: &[T]) - -> SimpleResult { - let mut n = 0; - let len = s.len(); - - // TODO: There has to be some more efficient way here - let b = i.consume_while(|c| { - if n >= len || c != s[n] { - false - } - else { - n += 1; +// pub fn string<'a, I: Input>(s: &'a [I::Token]) -> impl Parser> { +pub fn string(s: &'static [I::Token]) -> impl Parser> { + move |mut i: I| { + let mut n = 0; + let len = s.len(); + + // TODO: There has to be some more efficient way here + let b = i.consume_while(|c| { + if n >= len || c != s[n] { + false + } + else { + n += 1; - true - } - }); + true + } + }); - if n >= len { - i.ret(b) - } else { - i.err(Error::expected(s[n])) + if n >= len { + (i, Ok(b)) + } else { + (i, Err(Error::expected(s[n]))) + } } } /// Matches the end of the input. /// /// ``` -/// use chomp::prelude::{parse_only, token, eof}; +/// use chomp::prelude::{Parser, parse_only, token, eof}; /// -/// let r = parse_only(|i| token(i, b'a').then(eof), b"a"); +/// let r = parse_only(token(b'a').then(eof()), b"a"); /// /// assert_eq!(r, Ok(())); /// ``` #[inline] -pub fn eof(mut i: I) -> SimpleResult { - if i.peek() == None { - i.ret(()) +pub fn eof() -> impl Parser> { + move |mut i: I| if i.peek() == None { + (i, Ok(())) } else { - i.err(Error::unexpected()) + (i, Err(Error::unexpected())) } } @@ -559,9 +572,8 @@ mod error { #[cfg(test)] mod test { - use primitives::IntoInner; use super::*; - use types::{Input, ParseResult}; + use types::{Buffer, Input, Parser, ret}; #[test] fn parse_decimal() { @@ -569,114 +581,107 @@ mod test { c >= b'0' && c <= b'9' } - fn decimal<'i, I: Input>(i: I) -> SimpleResult { - take_while1(i, is_digit).bind(|i, bytes| - i.ret(bytes.iter().fold(0, |a, b| a * 10 + (b - b'0') as usize))) + fn decimal>() -> impl Parser> { + take_while1(is_digit).bind(|bytes: I::Buffer| + ret(bytes.fold(0, |a, b| a * 10 + (b - b'0') as usize))) } let i = &b"123.4567 "[..]; - let p = decimal(i).bind(|i, real| - token(i, b'.').bind(|i, _| - decimal(i).bind(|i, frac| - i.ret((real, frac))))); - - // ParseResult necessary here due to inference, for some reason is - // `Error<::Token>` not specific enough to actually help inference. - let d: ParseResult<_, _, Error> = p.bind(|i, num| take_remainder(i) - .bind(|i, r| i.ret((r, num)))); + let p = decimal().bind(|real| token(b'.').then(decimal().map(move |frac| (real, frac)))) + .bind(|num| take_remainder().map(move |r| (r, num))); - assert_eq!(d.into_inner(), (&b""[..], Ok((&b" "[..], (123, 4567))))); + assert_eq!(p.parse(i), (&b""[..], Ok((&b" "[..], (123, 4567))))); } #[test] fn parse_remainder_empty() { - assert_eq!(take_remainder(&b""[..]).into_inner(), (&b""[..], Ok(&b""[..]))); + assert_eq!(take_remainder().parse(&b""[..]), (&b""[..], Ok(&b""[..]))); } #[test] fn take_while1_empty() { - assert_eq!(take_while1(&b""[..], |_| true).into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(take_while1(|_| true).parse(&b""[..]), (&b""[..], Err(Error::unexpected()))); } #[test] fn token_test() { - assert_eq!(token(&b""[..], b'a').into_inner(), (&b""[..], Err(Error::expected(b'a')))); - assert_eq!(token(&b"ab"[..], b'a').into_inner(), (&b"b"[..], Ok(b'a'))); - assert_eq!(token(&b"bb"[..], b'a').into_inner(), (&b"bb"[..], Err(Error::expected(b'a')))); + assert_eq!(token(b'a').parse(&b""[..]), (&b""[..], Err(Error::expected(b'a')))); + assert_eq!(token(b'a').parse(&b"ab"[..]), (&b"b"[..], Ok(b'a'))); + assert_eq!(token(b'a').parse(&b"bb"[..]), (&b"bb"[..], Err(Error::expected(b'a')))); } #[test] fn take_test() { - assert_eq!(take(&b""[..], 0).into_inner(), (&b""[..], Ok(&b""[..]))); - assert_eq!(take(&b"a"[..], 0).into_inner(), (&b"a"[..], Ok(&b""[..]))); - assert_eq!(take(&b"a"[..], 1).into_inner(), (&b""[..], Ok(&b"a"[..]))); - assert_eq!(take(&b"a"[..], 2).into_inner(), (&b"a"[..], Err(Error::unexpected()))); - assert_eq!(take(&b"a"[..], 3).into_inner(), (&b"a"[..], Err(Error::unexpected()))); - assert_eq!(take(&b"ab"[..], 1).into_inner(), (&b"b"[..], Ok(&b"a"[..]))); - assert_eq!(take(&b"ab"[..], 2).into_inner(), (&b""[..], Ok(&b"ab"[..]))); + assert_eq!(take(0).parse(&b""[..]), (&b""[..], Ok(&b""[..]))); + assert_eq!(take(0).parse(&b"a"[..]), (&b"a"[..], Ok(&b""[..]))); + assert_eq!(take(1).parse(&b"a"[..]), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(take(2).parse(&b"a"[..]), (&b"a"[..], Err(Error::unexpected()))); + assert_eq!(take(3).parse(&b"a"[..]), (&b"a"[..], Err(Error::unexpected()))); + assert_eq!(take(1).parse(&b"ab"[..]), (&b"b"[..], Ok(&b"a"[..]))); + assert_eq!(take(2).parse(&b"ab"[..]), (&b""[..], Ok(&b"ab"[..]))); } #[test] fn take_while_test() { - assert_eq!(take_while(&b""[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b""[..]))); - assert_eq!(take_while(&b"a"[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b"a"[..]))); - assert_eq!(take_while(&b"b"[..], |c| c != b'b').into_inner(), (&b"b"[..], Ok(&b""[..]))); - assert_eq!(take_while(&b"abc"[..], |c| c != b'b').into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); - assert_eq!(take_while(&b"bbc"[..], |c| c != b'b').into_inner(), (&b"bbc"[..], Ok(&b""[..]))); - assert_eq!(take_while(&b"bbc"[..], |c| c != b'b').into_inner(), (&b"bbc"[..], Ok(&b""[..]))); - assert_eq!(take_while(&b"abc"[..], |c| c != b'b').into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); - assert_eq!(take_while(&b"acc"[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b"acc"[..]))); + assert_eq!(take_while(|c| c != b'b').parse(&b""[..]), (&b""[..], Ok(&b""[..]))); + assert_eq!(take_while(|c| c != b'b').parse(&b"a"[..]), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(take_while(|c| c != b'b').parse(&b"b"[..]), (&b"b"[..], Ok(&b""[..]))); + assert_eq!(take_while(|c| c != b'b').parse(&b"abc"[..]), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(take_while(|c| c != b'b').parse(&b"bbc"[..]), (&b"bbc"[..], Ok(&b""[..]))); + assert_eq!(take_while(|c| c != b'b').parse(&b"bbc"[..]), (&b"bbc"[..], Ok(&b""[..]))); + assert_eq!(take_while(|c| c != b'b').parse(&b"abc"[..]), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(take_while(|c| c != b'b').parse(&b"acc"[..]), (&b""[..], Ok(&b"acc"[..]))); } #[test] fn take_while1_test() { - assert_eq!(take_while1(&b""[..], |c| c != b'b').into_inner(), (&b""[..], Err(Error::unexpected()))); - assert_eq!(take_while1(&b"a"[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b"a"[..]))); - assert_eq!(take_while1(&b"b"[..], |c| c != b'b').into_inner(), (&b"b"[..], Err(Error::unexpected()))); - assert_eq!(take_while1(&b"ab"[..], |c| c != b'b').into_inner(), (&b"b"[..], Ok(&b"a"[..]))); - assert_eq!(take_while1(&b"abc"[..], |c| c != b'b').into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); - assert_eq!(take_while1(&b"bbc"[..], |c| c != b'b').into_inner(), (&b"bbc"[..], Err(Error::unexpected()))); - assert_eq!(take_while1(&b"bbc"[..], |c| c != b'b').into_inner(), (&b"bbc"[..], Err(Error::unexpected()))); - assert_eq!(take_while1(&b"abc"[..], |c| c != b'b').into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); - assert_eq!(take_while1(&b"acc"[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b"acc"[..]))); + assert_eq!(take_while1(|c| c != b'b').parse(&b""[..]), (&b""[..], Err(Error::unexpected()))); + assert_eq!(take_while1(|c| c != b'b').parse(&b"a"[..]), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(take_while1(|c| c != b'b').parse(&b"b"[..]), (&b"b"[..], Err(Error::unexpected()))); + assert_eq!(take_while1(|c| c != b'b').parse(&b"ab"[..]), (&b"b"[..], Ok(&b"a"[..]))); + assert_eq!(take_while1(|c| c != b'b').parse(&b"abc"[..]), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(take_while1(|c| c != b'b').parse(&b"bbc"[..]), (&b"bbc"[..], Err(Error::unexpected()))); + assert_eq!(take_while1(|c| c != b'b').parse(&b"bbc"[..]), (&b"bbc"[..], Err(Error::unexpected()))); + assert_eq!(take_while1(|c| c != b'b').parse(&b"abc"[..]), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(take_while1(|c| c != b'b').parse(&b"acc"[..]), (&b""[..], Ok(&b"acc"[..]))); } #[test] fn peek_next_test() { - assert_eq!(peek_next(&b"abc"[..]).into_inner(), (&b"abc"[..], Ok(b'a'))); - assert_eq!(peek_next(&b"abc"[..]).into_inner(), (&b"abc"[..], Ok(b'a'))); - assert_eq!(peek_next(&b""[..]).into_inner(), (&b""[..], Err(Error::unexpected()))); - assert_eq!(peek_next(&b""[..]).into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(peek_next().parse(&b"abc"[..]), (&b"abc"[..], Ok(b'a'))); + assert_eq!(peek_next().parse(&b"abc"[..]), (&b"abc"[..], Ok(b'a'))); + assert_eq!(peek_next().parse(&b""[..]), (&b""[..], Err(Error::unexpected()))); + assert_eq!(peek_next().parse(&b""[..]), (&b""[..], Err(Error::unexpected()))); } #[test] fn satisfy_with_test() { let mut m1 = 0; let mut n1 = 0; - assert_eq!(satisfy_with(&b"abc"[..], |m| { m1 += 1; m % 8 }, |n| { n1 += 1; n == 1 }).into_inner(), (&b"bc"[..], Ok(1))); + assert_eq!(satisfy_with(|m| { m1 += 1; m % 8 }, |n| { n1 += 1; n == 1 }).parse(&b"abc"[..]), (&b"bc"[..], Ok(1))); assert_eq!(m1, 1); assert_eq!(n1, 1); let mut m2 = 0; let mut n2 = 0; - assert_eq!(satisfy_with(&b""[..], |m| { m2 += 1; m % 8 }, |n| { n2 += 1; n == 1 }).into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(satisfy_with(|m| { m2 += 1; m % 8 }, |n| { n2 += 1; n == 1 }).parse(&b""[..]), (&b""[..], Err(Error::unexpected()))); assert_eq!(m2, 0); assert_eq!(n2, 0); } #[test] fn string_test() { - assert_eq!(string(&b""[..], b"").into_inner(), (&b""[..], Ok(&b""[..]))); - assert_eq!(string(&b""[..], b"a").into_inner(), (&b""[..], Err(Error::expected(b'a')))); - assert_eq!(string(&b"a"[..], b"a").into_inner(), (&b""[..], Ok(&b"a"[..]))); - assert_eq!(string(&b"b"[..], b"a").into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - assert_eq!(string(&b"abc"[..], b"a").into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); - assert_eq!(string(&b"abc"[..], b"ab").into_inner(), (&b"c"[..], Ok(&b"ab"[..]))); - assert_eq!(string(&b"abc"[..], b"abc").into_inner(), (&b""[..], Ok(&b"abc"[..]))); - assert_eq!(string(&b"abc"[..], b"abcd").into_inner(), (&b""[..], Err(Error::expected(b'd')))); - assert_eq!(string(&b"abc"[..], b"abcde").into_inner(), (&b""[..], Err(Error::expected(b'd')))); - assert_eq!(string(&b"abc"[..], b"ac").into_inner(), (&b"bc"[..], Err(Error::expected(b'c')))); + assert_eq!(string(b"" ).parse(&b""[..]), (&b""[..], Ok(&b""[..]))); + assert_eq!(string(b"a" ).parse(&b""[..]), (&b""[..], Err(Error::expected(b'a')))); + assert_eq!(string(b"a" ).parse(&b"a"[..]), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(string(b"a" ).parse(&b"b"[..]), (&b"b"[..], Err(Error::expected(b'a')))); + assert_eq!(string(b"a" ).parse(&b"abc"[..]), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(string(b"ab" ).parse(&b"abc"[..]), (&b"c"[..], Ok(&b"ab"[..]))); + assert_eq!(string(b"abc" ).parse(&b"abc"[..]), (&b""[..], Ok(&b"abc"[..]))); + assert_eq!(string(b"abcd" ).parse(&b"abc"[..]), (&b""[..], Err(Error::expected(b'd')))); + assert_eq!(string(b"abcde").parse(&b"abc"[..]), (&b""[..], Err(Error::expected(b'd')))); + assert_eq!(string(b"ac" ).parse(&b"abc"[..]), (&b"bc"[..], Err(Error::expected(b'c')))); } #[test] diff --git a/src/primitives.rs b/src/primitives.rs deleted file mode 100644 index 437e0a8e..00000000 --- a/src/primitives.rs +++ /dev/null @@ -1,126 +0,0 @@ -//! Module used to construct fundamental parsers and combinators. -//! -//! The `Primitives` trait allows access to the primitive methods of the `Input` trait. These -//! methods are hidden in the documentation to make it easier to read the documentation since the -//! methods are not useful when using the library or writing primitive parsers. - -use types::Input; - -/// Consumes self and reveals the inner state. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -pub trait IntoInner { - /// The inner type to be revealed. - type Inner; - - /// **Primitive:** Consumes self and reveals the inner state. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - #[inline(always)] - fn into_inner(self) -> Self::Inner; -} - -/// This is a zero-sized type used by the `Primitives` trait implementation to guarantee that -/// access to primitive methods on `Input` only happens when the `Primitives` trait has been -/// imported. -/// -/// It cannot be instantiated outside of the `Primitives` trait blanket implementation. -#[allow(missing_debug_implementations, missing_copy_implementations)] -pub struct Guard(()); - -/// Trait enabling primitive actions on an `Input` type. -/// -/// This trait is automatically implemented for all types implementing `Input` and acts as a -/// gatekeeper to the state-modifying methods of `Input`. -pub trait Primitives: Input { - /// Peeks at the next token in the input without consuming it. `None` if no more input is - /// available. - /// - /// Note: Is allowed to refill automatically or any other appropriate action if the input does - /// not contain any more data. - #[inline(always)] - fn peek(&mut self) -> Option { - self._peek(Guard(())) - } - - /// Pops a token off the start of the input. `None` if no more input is available. - /// - /// Note: Is allowed to refill automatically or any other appropriate action if the input does - /// not contain any more data. - #[inline(always)] - fn pop(&mut self) -> Option { - self._pop(Guard(())) - } - - /// Attempt to consume `n` tokens, if it fails do not advance the position but return `None`. - /// - /// Note: Is allowed to refill automatically or any other appropriate action if the input does - /// not contain any more data. - #[inline(always)] - fn consume(&mut self, n: usize) -> Option { - self._consume(Guard(()), n) - } - - /// Runs the closure `F` on the tokens *in order* until it returns false, all tokens up to that - /// token will be returned as a buffer and discarded from the current input. MUST never run the - /// closure more than once on the exact same token. - /// - /// If the end of the input is reached, the whole input is returned. - /// - /// Note: Is allowed to refill automatically or any other appropriate action if the input does - /// not contain any more data. - #[inline(always)] - fn consume_while(&mut self, f: F) -> Self::Buffer - where F: FnMut(Self::Token) -> bool { - self._consume_while(Guard(()), f) - } - - /// Returns the buffer from the marker to the current position, discarding the - /// backtracking position carried by the marker. - #[inline(always)] - fn consume_from(&mut self, m: Self::Marker) -> Self::Buffer { - self._consume_from(Guard(()), m) - } - - /// Returns the remainder of the input in a buffer. - /// - /// Note: Will refill the intenal buffer until no more data is available if the underlying - /// implementation supports it. - #[inline(always)] - fn consume_remaining(&mut self) -> Self::Buffer { - self._consume_remaining(Guard(())) - } - - /// Runs the closure `F` on the tokens *in order* until it returns false, all tokens up to that - /// token will be discarded from the current input. - /// - /// MUST never run the closure more than once on the exact same token. - /// - /// If the end of the input is reached, the whole input is discarded. - /// - /// Note: Default implementation uses `consume_while` and makes the assumption that it will - /// optimize away the resulting `Self::Buffer`. - #[inline(always)] - fn skip_while(&mut self, f: F) - where F: FnMut(Self::Token) -> bool { - self._skip_while(Guard(()), f) - } - - /// Marks the current position to be able to backtrack to it using `restore`. - #[inline(always)] - fn mark(&self) -> Self::Marker { - self._mark(Guard(())) - } - - /// Resumes from a previously marked state. - #[inline(always)] - fn restore(self, m: Self::Marker) -> Self { - self._restore(Guard(()), m) - } -} - -impl Primitives for I {} diff --git a/src/types/mod.rs b/src/types/mod.rs index 5ee9affc..f89957f7 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,11 +1,11 @@ //! Types which facillitates the chaining of parsers and their results. +use std::marker::PhantomData; + pub mod numbering; #[cfg(feature = "tendril")] pub mod tendril; -use primitives::{Guard, IntoInner}; - /// The buffers yielded parsers consuming a sequence of the input. /// /// This could either be an owned type or a slice reference depending on the `Input` @@ -123,7 +123,7 @@ impl<'a> Buffer for &'a str { /// where ``Fn*`` is the appropriate closure/function trait, `I` the input type (can be something /// like `[u8]`), `...` additional parameters to the parser, `T` the carried success type and `E` /// the potential error type. -pub trait Input: Sized { +pub trait Input { /// The token type of the input. type Token: Copy + PartialEq; @@ -139,123 +139,77 @@ pub trait Input: Sized { /// Can eg. provide zero-copy parsing if the input type is built to support it. type Buffer: Buffer; - /// Returns `t` as a success value in the parsing context. - /// - /// Equivalent to Haskell's `return` function in the `Monad` typeclass. - /// - /// # Example - /// - /// ``` - /// use chomp::prelude::{Input, parse_only}; - /// - /// let r = parse_only(|i| - /// // Annotate the error type - /// i.ret::<_, ()>("Wohoo, success!"), - /// b"some input"); + // Primitive methods + + /// Peeks at the next token in the input without consuming it. `None` if no more input is + /// available. /// - /// assert_eq!(r, Ok("Wohoo, success!")); - /// ``` + /// Note: Is allowed to refill automatically or any other appropriate action if the input does + /// not contain any more data. #[inline] - fn ret(self, t: T) -> ParseResult { - ParseResult(self, Ok(t)) - } + fn peek(&mut self) -> Option; - /// Returns `e` as an error value in the parsing context. - /// - /// A more general version of Haskell's `fail` function in the `Monad` typeclass. - /// - /// # Example - /// - /// ``` - /// use chomp::prelude::{Input, parse_only}; + /// Pops a token off the start of the input. `None` if no more input is available. /// - /// let r = parse_only(|i| - /// // Annotate the value type - /// i.err::<(), _>("Something went wrong"), - /// b"some input"); - /// - /// assert_eq!(r, Err((&b"some input"[..], "Something went wrong"))); - /// ``` + /// Note: Is allowed to refill automatically or any other appropriate action if the input does + /// not contain any more data. #[inline] - fn err(self, e: E) -> ParseResult { - ParseResult(self, Err(e)) - } + fn pop(&mut self) -> Option; - /// Converts a `Result` into a `ParseResult`, preserving parser state. + /// Attempt to consume `n` tokens, if it fails do not advance the position but return `None`. /// - /// To convert an `Option` into a `ParseResult` it is recommended to use - /// [`Option::ok_or`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or) - /// or [`Option::ok_or_else`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or_else) - /// in combination with this method. - /// - /// # Examples - /// - /// ``` - /// use chomp::prelude::{Input, parse_only}; - /// - /// let r = parse_only(|i| i.from_result::<_, ()>(Ok("foo")), b"test"); + /// Note: Is allowed to refill automatically or any other appropriate action if the input does + /// not contain any more data. + #[inline] + fn consume(&mut self, n: usize) -> Option; + + /// Runs the closure `F` on the tokens *in order* until it returns false, all tokens up to that + /// token will be returned as a buffer and discarded from the current input. /// - /// assert_eq!(r, Ok("foo")); + /// MUST never run the closure more than once on the exact same token. /// - /// let r = parse_only(|i| i.from_result::<(), _>(Err("error message")), b"test"); + /// If the end of the input is reached, the whole input is returned. /// - /// assert_eq!(r, Err((&b"test"[..], "error message"))); - /// ``` - #[inline] - fn from_result(self, r: Result) -> ParseResult { - ParseResult(self, r) - } - - // Primitive methods - - /// **Primitive:** See `Primitives::peek` for documentation. + /// Note: Is allowed to refill automatically or any other appropriate action if the input does + /// not contain any more data. #[inline] - #[doc(hidden)] - fn _peek(&mut self, Guard) -> Option; - - /// **Primitive:** See `Primitives::pop` for documentation. - #[inline] - #[doc(hidden)] - fn _pop(&mut self, Guard) -> Option; - - /// **Primitive:** See `Primitives::consume` for documentation. - #[inline] - #[doc(hidden)] - fn _consume(&mut self, Guard, usize) -> Option; - - /// **Primitive:** See `Primitives::consume_while` for documentation. - #[inline] - #[doc(hidden)] - fn _consume_while(&mut self, Guard, F) -> Self::Buffer + fn consume_while(&mut self, f: F) -> Self::Buffer where F: FnMut(Self::Token) -> bool; - /// **Primitive:** See `Primitives::consume_from for documentation. + /// Returns the buffer from the marker to the current position, discarding the + /// backtracking position carried by the marker. #[inline] - #[doc(hidden)] - fn _consume_from(&mut self, Guard, Self::Marker) -> Self::Buffer; + fn consume_from(&mut self, m: Self::Marker) -> Self::Buffer; - /// **Primitive:** See `Primitives::consume_remaining` for documentation. + /// Returns the remainder of the input in a buffer. + /// + /// Note: Will refill the intenal buffer until no more data is available if the underlying + /// implementation supports it. #[inline] - #[doc(hidden)] - fn _consume_remaining(&mut self, Guard) -> Self::Buffer; + fn consume_remaining(&mut self) -> Self::Buffer; - /// **Primitive:** See `Primitives::skip_while` for documentation. + /// Runs the closure `F` on the tokens *in order* until it returns false, all tokens up to that + /// token will be discarded from the current input. + /// + /// MUST never run the closure more than once on the exact same token. + /// + /// If the end of the input is reached, the whole input is discarded. + /// + /// Note: Default implementation uses `consume_while` and makes the assumption that it will + /// optimize away the resulting `Self::Buffer`. #[inline] - #[doc(hidden)] - fn _skip_while(&mut self, g: Guard, f: F) + fn skip_while(&mut self, f: F) where F: FnMut(Self::Token) -> bool { - self._consume_while(g, f); + self.consume_while(f); } - /// **Primitive:** See `Primitives::mark` for documentation. + /// Marks the current position to be able to backtrack to it using `restore`. #[inline] - #[doc(hidden)] - fn _mark(&self, Guard) -> Self::Marker; + fn mark(&self) -> Self::Marker; - /// **Primitive:** See `Primitives::restore` for documentation. - #[inline] - #[doc(hidden)] - fn _restore(self, Guard, Self::Marker) -> Self; + /// Resumes from a previously marked state. + #[inline(always)] + fn restore(self, m: Self::Marker) -> Self; } impl<'a, I: Copy + PartialEq> Input for &'a [I] { @@ -264,12 +218,12 @@ impl<'a, I: Copy + PartialEq> Input for &'a [I] { type Buffer = &'a [I]; #[inline] - fn _peek(&mut self, _g: Guard) -> Option { + fn peek(&mut self) -> Option { self.first().cloned() } #[inline] - fn _pop(&mut self, _g: Guard) -> Option { + fn pop(&mut self) -> Option { self.first().cloned().map(|c| { *self = &self[1..]; @@ -278,7 +232,7 @@ impl<'a, I: Copy + PartialEq> Input for &'a [I] { } #[inline] - fn _consume(&mut self, _g: Guard, n: usize) -> Option { + fn consume(&mut self, n: usize) -> Option { if n > self.len() { None } else { @@ -291,7 +245,7 @@ impl<'a, I: Copy + PartialEq> Input for &'a [I] { } #[inline] - fn _consume_while(&mut self, _g: Guard, mut f: F) -> Self::Buffer + fn consume_while(&mut self, mut f: F) -> Self::Buffer where F: FnMut(Self::Token) -> bool { if let Some(n) = self.iter().position(|c| !f(*c)) { let b = &self[..n]; @@ -309,12 +263,12 @@ impl<'a, I: Copy + PartialEq> Input for &'a [I] { } #[inline] - fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer { + fn consume_from(&mut self, m: Self::Marker) -> Self::Buffer { &m[..m.len() - self.len()] } #[inline] - fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer { + fn consume_remaining(&mut self) -> Self::Buffer { let b = &self[..]; *self = &self[..0]; @@ -323,12 +277,12 @@ impl<'a, I: Copy + PartialEq> Input for &'a [I] { } #[inline] - fn _mark(&self, _g: Guard) -> Self::Marker { + fn mark(&self) -> Self::Marker { self } #[inline] - fn _restore(self, _g: Guard, m: Self::Marker) -> Self { + fn restore(self, m: Self::Marker) -> Self { m } } @@ -339,12 +293,12 @@ impl<'a> Input for &'a str { type Buffer = &'a str; #[inline] - fn _peek(&mut self, _g: Guard) -> Option { + fn peek(&mut self) -> Option { self.chars().next() } #[inline] - fn _pop(&mut self, _g: Guard) -> Option { + fn pop(&mut self) -> Option { let mut iter = self.char_indices(); iter.next().map(|(_, c)| { @@ -358,7 +312,7 @@ impl<'a> Input for &'a str { } #[inline] - fn _consume(&mut self, _g: Guard, n: usize) -> Option { + fn consume(&mut self, n: usize) -> Option { match self.char_indices().enumerate().take(n + 1).last() { // num always equal to n if self contains more than n characters Some((num, (pos, _))) if n == num => { @@ -381,7 +335,7 @@ impl<'a> Input for &'a str { } #[inline] - fn _consume_while(&mut self, _g: Guard, mut f: F) -> Self::Buffer + fn consume_while(&mut self, mut f: F) -> Self::Buffer where F: FnMut(Self::Token) -> bool { // We need to find the character following the one which did not match if let Some((pos, _)) = self.char_indices().skip_while(|&(_, c)| f(c)).next() { @@ -400,12 +354,12 @@ impl<'a> Input for &'a str { } #[inline] - fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer { + fn consume_from(&mut self, m: Self::Marker) -> Self::Buffer { &m[..m.len() - self.len()] } #[inline] - fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer { + fn consume_remaining(&mut self) -> Self::Buffer { let b = &self[..]; *self = &self[..0]; @@ -414,12 +368,12 @@ impl<'a> Input for &'a str { } #[inline] - fn _mark(&self, _g: Guard) -> Self::Marker { + fn mark(&self) -> Self::Marker { self } #[inline] - fn _restore(self, _g: Guard, m: Self::Marker) -> Self { + fn restore(self, m: Self::Marker) -> Self { m } } @@ -430,41 +384,47 @@ pub trait U8Input: Input {} impl U8Input for T where T: Input {} -/// The basic return type of a parser. -/// -/// This type satisfies a variant of the `Monad` typeclass. Due to the limitations of Rust's -/// return types closures cannot be returned without boxing which has an unacceptable performance -/// impact. -/// -/// To get around this issue and still provide a simple to use and safe (as in hard to accidentally -/// violate the monad laws or the assumptions taken by the parser type) an `Input` wrapper is -/// provided which ensures that the parser state is carried properly through every call to `bind`. -/// This is also known as a Linear Type (emulated through hiding destructors and using the -/// annotation `#[must_use]`). +// TODO: More docs +/// The parser monad type. /// /// Do-notation is provided by the macro `parse!`. /// /// # Equivalence with Haskell's `Monad` typeclass: /// /// ```text -/// f >>= g ≡ f(m).bind(g) -/// f >> g ≡ f(m).then(g) -/// return a ≡ m.ret(a) -/// fail a ≡ m.err(a) +/// f >>= g ≡ f().bind(g) +/// f >> g ≡ f().then(g) +/// return a ≡ ret(a) +/// fail a ≡ err(a) /// ``` /// -/// It also satisfies the monad laws: +/// It also satisfies the Monad laws: /// -/// ```text -/// return a >>= f ≡ f a -/// m >>= return ≡ m -/// (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) +/// ```ignore +/// ret(a).bind(f) = f(a) +/// m.then(ret) = m +/// m.bind(f).bind(g) = m.bind(|x| f(x).bind(g)) +/// ``` +/// +/// as well as Monad Plus laws using `err` and `or` in the Monoid, Left Zero, and Left Catch +/// laws (equivalent to Haskell's `Control.Applicative.Alternative`): +/// +/// ```ignore +/// err(msg).or(a) = a +/// a.or(err(msg)) = a +/// a.or(b).or(c) = a.or(b.or(c)) +/// err(msg).bind(k) = err(msg) +/// ret(a).or(b) = ret(a) /// ``` -#[must_use] -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ParseResult(I, Result); +pub trait Parser { + /// Output type created by the parser, may refer to data owned by `I`. + type Output; + /// Error type created by the parser, may refer to data owned by `I`. + type Error; + + /// Apply the parser to an input `I`. + fn parse(self, I) -> (I, Result); -impl ParseResult { /// Sequentially composes the result with a parse action `f`, passing any produced value as /// the second parameter. /// @@ -481,13 +441,13 @@ impl ParseResult { /// # Examples /// /// ``` - /// use chomp::prelude::{Input, parse_only}; + /// #![feature(conservative_impl_trait)] /// - /// let r = parse_only(|i| { - /// i.ret("data".to_owned()) - /// // Explicitly state the error type - /// .bind::<_, _, ()>(|i, x| i.ret(x + " here!")) - /// }, + /// use chomp::prelude::{Parser, parse_only, ret}; + /// + /// let r = parse_only(ret("data") + /// // Explicitly state the error type + /// .bind(|x| ret::<_, ()>(x.to_owned() + " here!")), /// b"test"); /// /// assert_eq!(r, Ok("data here!".to_owned())); @@ -497,24 +457,28 @@ impl ParseResult { /// the type-hint for the error in the function signature: /// /// ``` - /// use chomp::prelude::{Input, ParseResult, parse_only}; + /// #![feature(conservative_impl_trait)] + /// + /// use chomp::prelude::{Input, Parser, parse_only, ret}; /// - /// fn parser(i: I, n: i32) -> ParseResult { - /// i.ret(n + 10) + /// fn parser(n: i32) -> impl Parser { + /// ret(n + 10) /// } /// - /// let r = parse_only(|i| i.ret(23).bind(parser), b"test"); + /// let r = parse_only(ret(23).bind(parser), b"test"); /// /// assert_eq!(r, Ok(33)); /// ``` - #[inline] - pub fn bind(self, f: F) -> ParseResult - where F: FnOnce(I, T) -> ParseResult, - V: From { - match self.1 { - Ok(t) => f(self.0, t).map_err(From::from), - Err(e) => ParseResult(self.0, Err(From::from(e))), - } + #[inline(always)] + // TODO: Add From::from + // TODO: Is it possible to remove R here? + // I is required to be a type-parameter to the created parser in case Self does not have + // anything restricting I, then the parser we are binding to needs to provide that. + fn bind(self, f: F) -> BindParser + where F: FnOnce(Self::Output) -> R, + R: Parser, + Self: Sized { + BindParser { p: self, f: f, _i: PhantomData } } /// Sequentially composes the result with a parse action `f`, discarding any produced value. @@ -525,29 +489,33 @@ impl ParseResult { /// # Relation to `bind` /// /// ```text - /// ParseResult::then(g) ≡ ParseResult::bind(|i, _| g(i)) + /// p.then(g) ≡ p.bind(|_| g) /// ``` /// /// # Example /// /// ``` - /// use chomp::prelude::{Input, SimpleResult, parse_only}; + /// #![feature(conservative_impl_trait)] + /// + /// use chomp::prelude::{Input, Parser, parse_only, ret}; /// - /// fn g(i: I) -> SimpleResult { - /// i.ret("testing!") + /// fn g() -> impl Parser { + /// ret("testing!") /// } /// - /// let r1 = parse_only(|i| i.ret("initial state").bind(|i, _| g(i)), b"data"); - /// let r2 = parse_only(|i| i.ret("initial state").then(g), b"data"); + /// let r1 = parse_only(ret("initial state").bind(|_| g()), b"data"); + /// let r2 = parse_only(ret("initial state").then(g()), b"data"); /// /// assert_eq!(r1, Ok("testing!")); /// assert_eq!(r2, Ok("testing!")); /// ``` - #[inline] - pub fn then(self, f: F) -> ParseResult - where F: FnOnce(I) -> ParseResult, - V: From { - self.bind(|i, _| f(i)) + #[inline(always)] + // TODO: Add From::from + // TODO: Tests, also with an unbounded I (from eg. ret or err) + fn then

(self, p: P) -> ThenParser + where P: Parser, + Self: Sized { + ThenParser { p: self, q: p, _i: PhantomData } } /// Applies the function `f` on the contained data if the parser is in a success state. @@ -555,19 +523,20 @@ impl ParseResult { /// # Example /// /// ``` - /// use chomp::prelude::{parse_only, any}; + /// use chomp::prelude::{Parser, parse_only, any, ret}; /// - /// let r = parse_only(|i| any(i).map(|c| c + 12), b"abc"); + /// let r = parse_only(any().map(|c| c + 12), b"abc"); /// /// assert_eq!(r, Ok(b'm')); + /// + /// assert_eq!(parse_only(ret::<_, ()>(123).map(|c| c + 12), b"abc"), Ok(135)); /// ``` - #[inline] - pub fn map(self, f: F) -> ParseResult - where F: FnOnce(T) -> U { - match self { - ParseResult(i, Ok(t)) => ParseResult(i, Ok(f(t))), - ParseResult(i, Err(e)) => ParseResult(i, Err(e)), - } + // TODO: Tests + #[inline(always)] + fn map(self, f: F) -> MapParser + where F: FnOnce(Self::Output) -> R, + Self: Sized { + MapParser { p: self, f: f, _i: PhantomData } } /// Applies the function `f` on the contained error if the parser is in an error state. @@ -575,21 +544,20 @@ impl ParseResult { /// # Example /// /// ``` - /// use chomp::prelude::{Input, parse_only}; + /// use chomp::prelude::{Parser, parse_only, err}; /// - /// let r = parse_only(|i| i.err::<(), _>("this is") - /// .map_err(|e| e.to_owned() + " an error"), - /// b"foo"); + /// let r = parse_only(err::<(), _>("this is") + /// .map_err(|e| e.to_owned() + " an error"), b"foo"); /// /// assert_eq!(r, Err((&b"foo"[..], "this is an error".to_owned()))); /// ``` - #[inline] - pub fn map_err(self, f: F) -> ParseResult - where F: FnOnce(E) -> V { - match self { - ParseResult(i, Ok(t)) => ParseResult(i, Ok(t)), - ParseResult(i, Err(e)) => ParseResult(i, Err(f(e))), - } + // TODO: Tests + // TODO: Make sure to use an unbounded I too first in tests + #[inline(always)] + fn map_err(self, f: F) -> MapErrParser + where F: FnOnce(Self::Error) -> E, + Self: Sized { + MapErrParser { p: self, f: f, _i: PhantomData } } /// Calls the function `f` with a reference of the contained data if the parser is in a success @@ -598,199 +566,668 @@ impl ParseResult { /// # Example /// /// ``` - /// use chomp::prelude::{parse_only, take_while}; + /// use chomp::prelude::{Parser, parse_only, take_while}; /// - /// let r = parse_only(|i| take_while(i, |c| c != b' ').inspect(|b| { + /// let r = parse_only(take_while(|c| c != b' ').inspect(|b| { /// println!("{:?}", b); // Prints "test" /// }), b"test and more"); /// /// assert_eq!(r, Ok(&b"test"[..])); /// ``` + // TODO: Tests + #[inline(always)] + fn inspect(self, f: F) -> InspectParser + where F: FnOnce(&Self::Output), + Self: Sized { + InspectParser { p: self, f: f, _i: PhantomData } + } + + /// Tries to match the parser `f`, if `f` fails it tries `g`. Returns the success value of + /// the first match, otherwise the error of the last one if both fail. + /// + /// Incomplete state is propagated from the first one to report incomplete. + /// + /// If multiple `or` combinators are used in the same expression, consider using the `parse!` macro + /// and its alternation operator (`<|>`). + /// + /// ``` + /// use chomp::prelude::{Error, Parser, parse_only, token}; + /// + /// let p = || token(b'a').or(token(b'b')); + /// + /// assert_eq!(parse_only(p(), b"abc"), Ok(b'a')); + /// assert_eq!(parse_only(p(), b"bbc"), Ok(b'b')); + /// assert_eq!(parse_only(p(), b"cbc"), Err((&b"cbc"[..], Error::expected(b'b')))); + /// ``` + // TODO: Write the laws for MonadPlus, or should satisfy MonadPlus laws (stronger guarantees + // compared to Alternative typeclass laws) + // TODO: Tests + #[inline(always)] + fn or

(self, p: P) -> OrParser + where P: Parser, + Self: Sized { + OrParser { p: self, q: p, _i: PhantomData } + } + + /// Creates a new parser which matches `Self` and if successful tries to match `P`, if `P` is + /// also matched the result of `Self` is yielded. + /// + /// Equivalent to: + /// + /// ```ignore + /// self.bind(|t| p.map(|_| t)) + /// ``` + // TODO: Get more of the Applicative instance in here, make tests + // TODO: Docs + // TODO: Tests, also include test with unbounded existing parser (ret and err) on lhs + #[inline(always)] + fn skip

(self, p: P) -> SkipParser + where P: Parser, + Self: Sized { + // Would be nice to be able to return the following, but conservative impl Trait does not + // work on traits: + // self.bind(|t| p.map(|_| t)) + SkipParser{ p: self, q: p, _i: PhantomData } + } + + /// Turns the parser into a trait object, using the `BoxedParser` type to provide inference and + /// guarantees that it will satisfy any `P: Parser` generic. + /// + /// Useful to unify the types different parsers when eg. returning two different parsers + /// depending on a condition. + /// + /// ``` + /// use chomp::prelude::{Parser, Error, any, token}; + /// + /// let a = 3; + /// + /// let p = if a == 0 { + /// any().boxed() + /// } else { + /// token(b'a').boxed() + /// }; + /// + /// assert_eq!(p.parse(&b"bcd"[..]), (&b"bcd"[..], Err(Error::expected(b'a')))); + /// ``` + #[inline(always)] + fn boxed(self) -> BoxedParser + where Self: Sized + 'static { + Box::new(self) + } +} + +/// The type for boxed parsers, created through `Parser::boxed`. +pub type BoxedParser = Box>; + +/// Trait wrapping a parser to be able to destructure a `Box` in a sized manner. +/// Recommended to use the `BoxedParser` type-alias instead of `BoxParser` directly. +pub trait BoxParser { + /// The output type of the boxed parser, analogous to `Parser::Output`. + type Output; + /// The error type of the boxed parser, analogous to `Parser::Error`. + type Error; + + /// Allows destructuring of the box to be able to consume the wrapped contents, analogous to + /// `Parser::parse`. + #[inline] + fn parse_box(self: Box, i: I) -> (I, Result); +} + +impl BoxParser for P + where I: Input, + P: Parser { + type Output = P::Output; + type Error = P::Error; + + #[cfg_attr(feature="clippy", allow(boxed_local))] + #[inline] + fn parse_box(self: Box, i: I) -> (I, Result) { + (*self).parse(i) + } +} + +impl Parser for Box> + where I: Input { + type Output = T; + type Error = E; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + self.parse_box(i) + } +} + +/// Returns `t` as a success value in the parsing context. +/// +/// Equivalent to Haskell's `return` function in the `Monad` typeclass. +/// +/// # Example +/// +/// ``` +/// use chomp::types::ret; +/// use chomp::parse_only; +/// +/// let r = parse_only( +/// // Annotate the error type +/// ret::<_, ()>("Wohoo, success!"), +/// b"some input"); +/// +/// assert_eq!(r, Ok("Wohoo, success!")); +/// ``` +#[inline] +pub fn ret(t: T) -> RetParser { + RetParser { t: t, _e: PhantomData } +} + +/// Returns `e` as an error value in the parsing context. +/// +/// A more general version of Haskell's `fail` function in the `Monad` typeclass. +/// +/// # Example +/// +/// ``` +/// use chomp::types::err; +/// use chomp::parse_only; +/// +/// let r = parse_only( +/// // Annotate the value type +/// err::<(), _>("Something went wrong"), +/// b"some input"); +/// +/// assert_eq!(r, Err((&b"some input"[..], "Something went wrong"))); +/// ``` +#[inline] +pub fn err(e: E) -> ErrParser { + ErrParser { e: e, _t: PhantomData } +} + +/// Converts a `Result` into a `Parser`, preserving parser state. +/// +/// To convert an `Option` into a `Parser` it is recommended to use +/// [`Option::ok_or`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or) +/// or [`Option::ok_or_else`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or_else) +/// in combination with this method. +/// +/// # Examples +/// +/// ``` +/// use chomp::types::from_result; +/// use chomp::parse_only; +/// +/// let r = parse_only(from_result::<_, ()>(Ok("foo")), b"test"); +/// +/// assert_eq!(r, Ok("foo")); +/// +/// let r = parse_only(from_result::<(), _>(Err("error message")), b"test"); +/// +/// assert_eq!(r, Err((&b"test"[..], "error message"))); +/// ``` +#[inline] +pub fn from_result(r: Result) -> FromResultParser { + FromResultParser { r: r } +} + +/// Parser containing a success value. +/// +/// This is created by `ret`. +#[derive(Debug)] +pub struct RetParser { + t: T, + _e: PhantomData, +} + +impl Parser for RetParser + where I: Input { + type Output = T; + type Error = E; + #[inline] - pub fn inspect(self, f: F) -> ParseResult - where F: FnOnce(&T) { - if let Ok(ref t) = self.1 { - f(t) + fn parse(self, i: I) -> (I, Result) { + (i, Ok(self.t)) + } +} + +/// Parser containing an error value. +/// +/// This is created by `err`. +#[derive(Debug)] +pub struct ErrParser { + e: E, + _t: PhantomData, +} + +impl Parser for ErrParser + where I: Input { + type Output = T; + type Error = E; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + (i, Err(self.e)) + } +} + +/// Parser containing a `Result`. +/// +/// This is created by `from_result`. +#[derive(Debug)] +pub struct FromResultParser { + r: Result, +} + +impl Parser for FromResultParser + where I: Input { + type Output = T; + type Error = E; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + (i, self.r) + } +} + +/// Parser for the `Parser::bind` chaining operator, allowing to chain parsers. +/// +/// This is created by the `Parser::bind` method. +#[derive(Debug)] +pub struct BindParser + where I: Input, + P: Parser, + F: FnOnce(P::Output) -> R, + R: Parser { + p: P, + f: F, + // Necessary for inference, if we do not have I here we cannot describe the return value of `F` + // and this would make it impossible for rustc to infer the type of the created parser. + _i: PhantomData, +} + +impl Parser for BindParser + where I: Input, + P: Parser, + F: FnOnce(P::Output) -> R, + R: Parser { + type Output = R::Output; + type Error = R::Error; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + match self.p.parse(i) { + (r, Ok(t)) => (self.f)(t).parse(r), + (r, Err(e)) => (r, Err(e)), } + } +} - self +/// Parser for the `Parser::then` chaining operator, allowing to chain parsers. +/// +/// This is created by the `Parser::then` method. +#[derive(Debug)] +pub struct ThenParser { + p: P, + q: Q, + _i: PhantomData, +} + +impl Parser for ThenParser + where I: Input, + P: Parser, + Q: Parser { + type Output = Q::Output; + type Error = Q::Error; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + match self.p.parse(i) { + (r, Ok(_)) => (self.q).parse(r), + (r, Err(e)) => (r, Err(e)), + } } } -/// **Primitive:** Consumes the `ParseResult` and exposes the internal state. +/// Parser for the `Parser::map` combinator. /// -/// # Primitive +/// This is created by the `Parser::map` method. +#[derive(Debug)] +pub struct MapParser { + p: P, + f: F, + _i: PhantomData, +} + +impl Parser for MapParser + where I: Input, + P: Parser, + F: FnOnce(P::Output) -> R { + type Output = R; + type Error = P::Error; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + match self.p.parse(i) { + (r, Ok(t)) => (r, Ok((self.f)(t))), + (r, Err(e)) => (r, Err(e)), + } + } +} + +/// Parser for the `Parser::map_err` combinator. /// -/// Only used by fundamental parsers and combinators. +/// This is created by the `Parser::map_err` method. +#[derive(Debug)] +pub struct MapErrParser { + p: P, + f: F, + _i: PhantomData +} + +impl Parser for MapErrParser + where I: Input, + P: Parser, + F: FnOnce(P::Error) -> E { + type Output = P::Output; + type Error = E; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + match self.p.parse(i) { + (r, Ok(t)) => (r, Ok(t)), + (r, Err(e)) => (r, Err((self.f)(e))), + } + } +} + +/// Parser for the `Parser::inspect` combinator. /// -/// # Motivation +/// This is created by `Parser::inspect`. +#[derive(Debug)] +pub struct InspectParser { + p: P, + f: F, + _i: PhantomData, +} + +impl Parser for InspectParser + where I: Input, + P: Parser, + F: FnOnce(&P::Output) { + type Output = P::Output; + type Error = P::Error; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + match self.p.parse(i) { + (r, Ok(t)) => { + (self.f)(&t); + + (r, Ok(t)) + }, + (r, Err(e)) => (r, Err(e)), + } + } +} + +/// Parser for the `Parser::or` combinator. /// -/// The `ParseResult` type is a semi-linear type, supposed to act like a linear type while used in -/// a parsing context to carry the state. Normally it should be as restrictive as the `Input` type -/// in terms of how much it exposes its internals, but the `IntoInner` trait implementation -/// allows fundamental parsers and combinators to expose the inner `Result` of the `ParseResult` -/// and act on this. -impl IntoInner for ParseResult { - type Inner = (I, Result); +/// This is created by `Parser::or`. +#[derive(Debug)] +pub struct OrParser { + p: P, + q: Q, + _i: PhantomData, +} - #[inline(always)] - fn into_inner(self) -> Self::Inner { - (self.0, self.1) +impl Parser for OrParser + where I: Input, + P: Parser, + Q: Parser { + type Output = P::Output; + type Error = P::Error; + + fn parse(self, i: I) -> (I, Result) { + let m = i.mark(); + + match self.p.parse(i) { + (r, Ok(d)) => (r, Ok(d)), + (r, Err(_)) => self.q.parse(r.restore(m)), + } + } +} + +/// Parser for the `Parser::skip` combinator. +/// +/// This is created by `Parser::skip`. +#[derive(Debug)] +pub struct SkipParser { + p: P, + q: Q, + _i: PhantomData, +} + +impl Parser for SkipParser + where I: Input, + P: Parser, + Q: Parser { + type Output = P::Output; + type Error = P::Error; + + fn parse(self, i: I) -> (I, Result) { + // Merge of p.bind(|t| q.map(|_| t)) + match self.p.parse(i) { + (r, Ok(t)) => match self.q.parse(r) { + (b, Ok(_)) => (b, Ok(t)), + (b, Err(e)) => (b, Err(e)), + }, + (r, Err(e)) => (r, Err(e)), + } + } +} + +impl Parser for F + where I: Input, + F: FnOnce(I) -> (I, Result) { + type Output = T; + type Error = E; + + fn parse(self, i: I) -> (I, Result) { + (self)(i) } } #[cfg(test)] pub mod test { - use super::{Buffer, Input, ParseResult}; - use primitives::IntoInner; + use super::{Buffer, Input, Parser, ret, err, from_result}; use std::fmt::Debug; #[test] - fn ret() { - let r1: ParseResult<_, u32, ()> = b"in1".ret::<_, ()>(23u32); - let r2: ParseResult<_, i32, &str> = b"in2".ret::<_, &str>(23i32); - - assert_eq!(r1.into_inner(), (&b"in1"[..], Ok(23u32))); - assert_eq!(r2.into_inner(), (&b"in2"[..], Ok(23i32))); + fn ret_test() { + assert_eq!(ret::<_, ()>(23u32).parse(&b"in1"[..]), (&b"in1"[..], Ok(23u32))); + assert_eq!(ret::<_, &str>(23i32).parse(&b"in2"[..]), (&b"in2"[..], Ok(23i32))); } #[test] - fn err() { - let r1: ParseResult<_, (), u32> = b"in1".err::<(), _>(23u32); - let r2: ParseResult<_, &str, i32> = b"in2".err::<&str, _>(23i32); - - assert_eq!(r1.into_inner(), (&b"in1"[..], Err(23u32))); - assert_eq!(r2.into_inner(), (&b"in2"[..], Err(23i32))); + fn err_test() { + assert_eq!(err::<(), _>(23u32).parse(&b"in1"[..]), (&b"in1"[..], Err(23u32))); + assert_eq!(err::<&str, _>(23i32).parse(&b"in2"[..]), (&b"in2"[..], Err(23i32))); } #[test] - fn from_result() { + fn from_result_test() { let i1: Result = Ok(23); let i2: Result<&str, &str> = Err("foobar"); - let r1 = b"in1".from_result(i1); - let r2 = b"in2".from_result(i2); - - assert_eq!(r1.into_inner(), (&b"in1"[..], Ok(23u32))); - assert_eq!(r2.into_inner(), (&b"in2"[..], Err("foobar"))); + assert_eq!(from_result(i1).parse(&b"in1"[..]), (&b"in1"[..], Ok(23u32))); + assert_eq!(from_result(i2).parse(&b"in2"[..]), (&b"in2"[..], Err("foobar"))); } #[test] fn monad_left_identity() { - fn f(i: I, n: u32) -> ParseResult { - i.ret(n + 1) + fn f(n: u32) -> impl Parser { + ret(n + 1) } let a = 123; // return a >>= f - let lhs = b"test".ret(a).bind(f); + let lhs = ret(a).bind(f); // f a - let rhs = f(&b"test"[..], a); + let rhs = f(a); - assert_eq!((lhs.0, lhs.1), (&b"test"[..], Ok(124))); - assert_eq!((rhs.0, rhs.1), (&b"test"[..], Ok(124))); + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok(124))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok(124))); } #[test] fn monad_right_identity() { - let m1 = b"test".ret::<_, ()>(1); - let m2 = b"test".ret::<_, ()>(1); + let m1 = ret::<_, ()>(1); + let m2 = ret::<_, ()>(1); // m1 >>= ret === m2 - let lhs = m1.bind::<_, _, ()>(Input::ret); + let lhs = m1.bind(ret); let rhs = m2; - assert_eq!((lhs.0, rhs.1), (&b"test"[..], Ok(1))); - assert_eq!((rhs.0, lhs.1), (&b"test"[..], Ok(1))); + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok(1))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok(1))); } #[test] fn monad_associativity() { - fn f(i: I, num: u32) -> ParseResult { - i.ret((num + 1) as u64) + fn f(num: u32) -> impl Parser { + ret((num + 1) as u64) } - fn g(i: I, num: u64) -> ParseResult { - i.ret(num * 2) + fn g(num: u64) -> impl Parser { + ret(num * 2) } - let lhs_m = b"test".ret::<_, ()>(2); - let rhs_m = b"test".ret::<_, ()>(2); + let lhs_m = ret::<_, ()>(2); + let rhs_m = ret::<_, ()>(2); // (m >>= f) >>= g let lhs = lhs_m.bind(f).bind(g); // m >>= (\x -> f x >>= g) - let rhs = rhs_m.bind(|i, x| f(i, x).bind(g)); + let rhs = rhs_m.bind(|x| f(x).bind(g)); - assert_eq!((lhs.0, lhs.1), (&b"test"[..], Ok(6))); - assert_eq!((rhs.0, rhs.1), (&b"test"[..], Ok(6))); + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok(6))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok(6))); } #[test] - fn parse_result_inspect() { - use primitives::IntoInner; + fn monad_plus_monoid1() { + let lhs = err("foo").or(ret("a")); + let rhs = ret::<_, ()>("a"); - let mut n1 = 0; - let mut n2 = 0; - let i1 = b"test ".ret::(23); - let i2 = b"test ".ret::(23); + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + } - let r1 = i1.inspect(|d: &u32| { - assert_eq!(d, &23); + #[test] + fn monad_plus_monoid2() { + let lhs = ret("a").or(err("foo")); + let rhs = ret::<_, ()>("a"); - n1 += 1; - }); - let r2 = i2.inspect(|d: &u32| { - assert_eq!(d, &23); + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + } - n2 += 1; - }); + #[test] + fn monad_plus_monoid3() { + macro_rules! monoid3test { + ($a:expr, $b:expr, $c:expr, $r:expr) => { + let lhs = $a.or($b).or($c); + let rhs = $a.or($b.or($c)); + + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], $r)); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], $r)); + } + } - assert_eq!(r1.into_inner(), (&b"test "[..], Ok(23))); - assert_eq!(n1, 1); - assert_eq!(r2.into_inner(), (&b"test "[..], Ok(23))); - assert_eq!(n2, 1); + monoid3test!(err::<(), _>("foo"), err("bar"), err("baz"), Err("baz")); + monoid3test!(err("foo"), err("bar"), ret("baz"), Ok("baz")); + monoid3test!(err("foo"), ret("bar"), ret("baz"), Ok("bar")); + monoid3test!(err("foo"), ret("bar"), err("baz"), Ok("bar")); + monoid3test!(ret::<_, ()>("foo"), ret("bar"), ret("baz"), Ok("foo")); + monoid3test!(ret("foo"), err("bar"), err("baz"), Ok("foo")); + monoid3test!(ret("foo"), err("bar"), ret("baz"), Ok("foo")); + monoid3test!(ret("foo"), ret("bar"), err("baz"), Ok("foo")); } #[test] - fn input_propagation() { - let mut n_calls = 0; + fn monad_plus_left_zero() { + let lhs = err("foo").bind(|_: ()| ret("test")); + let rhs = err::<&str, _>("foo"); - let i = b"test1".ret::<_, ()>(23); + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Err("foo"))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Err("foo"))); + } - assert_eq!(i.0, b"test1"); - assert_eq!(i.1, Ok(23)); + #[test] + fn monad_plus_left_catch() { + let lhs = ret::<_, ()>("a").or(ret("b")); + let rhs = ret::<_, ()>("a"); - let r: ParseResult<_, _, ()> = i.bind(|i, t| { n_calls += 1; i.ret(t) }); + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + } - assert_eq!((r.0, r.1), (&b"test1"[..], Ok(23))); - assert_eq!(n_calls, 1); + #[test] + fn or_test() { + use parsers::{Error, any, take, token}; + + assert_eq!(any().or(any()).parse(&b""[..]), (&b""[..], Err(Error::unexpected()))); + assert_eq!(any().or(any()).parse(&b"a"[..]), (&b""[..], Ok(b'a'))); + assert_eq!(take(2).or(take(1)).parse(&b"a"[..]), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(take(2).or(take(1)).parse(&b"ab"[..]), (&b""[..], Ok(&b"ab"[..]))); + assert_eq!(token(b'a').or(token(b'b')).parse(&b"a"[..]), (&b""[..], Ok(b'a'))); + assert_eq!(token(b'a').or(token(b'b')).parse(&b"b"[..]), (&b""[..], Ok(b'b'))); + assert_eq!(token(b'a').map_err(|_| "a err").or(token(b'b').map_err(|_| "b err")).parse(&b"c"[..]), (&b"c"[..], Err("b err"))); } + // TODO: More tests for fundamental combinators implemented on Parser + #[test] - fn error_propagation() { - let mut n_calls = 0; + fn parse_result_inspect() { + let mut n1 = 0; + let mut n2 = 0; - let i = b"test1".err::<(), _>(23); + { + let i1 = ret::(23); + let i2 = ret::(23); + let i3 = err::(42); + + let r1 = i1.inspect(|d: &u32| { + assert_eq!(d, &23); + + n1 += 1; + }); + let r2 = i2.inspect(|d: &u32| { + assert_eq!(d, &23); - assert_eq!(i.0, b"test1"); - assert_eq!(i.1, Err(23)); + n2 += 1; + }); + let r3 = i3.inspect(|_: &u32| { + panic!("Success value obtained in error branch in inspect!"); + }); - let r = i.bind(|i, t| { n_calls += 1; i.ret(t) }); + assert_eq!(r1.parse(&b"test"[..]), (&b"test"[..], Ok(23))); + assert_eq!(r2.parse(&b"test"[..]), (&b"test"[..], Ok(23))); + assert_eq!(r3.parse(&b"test"[..]), (&b"test"[..], Err(42))); + } - assert_eq!((r.0, r.1), (&b"test1"[..], Err(23))); - assert_eq!(n_calls, 0); + assert_eq!(n1, 1); + assert_eq!(n2, 1); } #[test] - fn slice() { - fn f(i: I, n: u32) -> ParseResult { i.ret(n + 1) } + fn test_boxed() { + let p = ret::<_, ()>("foo").boxed().bind(|x| ret(x.to_owned() + "bar").boxed()); + + assert_eq!(p.parse(&b"test"[..]), (&b"test"[..], Ok("foobar".to_owned()))); - let lhs = (&b"test"[..]).ret(123).bind(f); - let rhs = f(&b"test"[..], 123); + let v = vec![ret("foo").boxed(), err("error").boxed()]; - assert_eq!((lhs.0, lhs.1), (&b"test"[..], Ok(124))); - assert_eq!((rhs.0, rhs.1), (&b"test"[..], Ok(124))); + let r: Vec<_> = v.into_iter().map(|p| p.parse(&b"test2"[..])).collect(); + + assert_eq!(r, vec![(&b"test2"[..], Ok("foo")), (&b"test2"[..], Err("error"))]); } #[test] @@ -807,8 +1244,6 @@ pub mod test { pub fn run_primitives_test I::Token>(mut s: I, f: F) where I::Token: Debug, I::Buffer: Clone { - use primitives::Primitives; - fn buffer_eq_slice B::Token>(b: B, s: &[u8], f: F) where B::Token: Debug, { assert_eq!(b.len(), s.len()); diff --git a/src/types/numbering.rs b/src/types/numbering.rs index c02ef104..a574ca13 100644 --- a/src/types/numbering.rs +++ b/src/types/numbering.rs @@ -1,47 +1,38 @@ //! Module containing tools for working with position aware parsers. //! //! ``` +//! #![feature(conservative_impl_trait)] //! # #[macro_use] extern crate chomp; //! # fn main() { -//! use chomp::types::{Input, ParseResult}; -//! use chomp::types::numbering::{InputPosition, LineNumber, Numbering}; +//! use chomp::types::{Input, Parser, ret}; +//! use chomp::types::numbering::{InputPosition, LineNumber, position}; //! use chomp::combinators::many; //! use chomp::parsers::{Error, any, take_while1, string}; -//! use chomp::run_parser; //! -//! // Let's count some lines -//! let i = InputPosition::new(&b"test a\ntest b\n\ntest c\n"[..], LineNumber::new()); +//! let i = InputPosition::new(&b"test a\ntest b\n\ntest c\n"[..], Default::default()); //! -//! // We could use a concrete type P too if we want to restrict to a -//! // certain position-aware implementation -//! fn parser, P: Numbering>(i: InputPosition) -//! -> ParseResult, (char, P), Error> { -//! parse!{i; -//! string(b"test"); -//! take_while1(|c| c == b' ' || c == b'\t'); +//! fn parser>() -> impl Parser, Output=(char, LineNumber), Error=Error> { +//! parse!{ +//! string(b"test"); +//! take_while1(|c| c == b' ' || c == b'\t'); //! let t_name = any(); -//! i -> { -//! // Obtain current parser position -//! let p = i.position(); +//! let p = position(); //! -//! i.ret((t_name as char, p)) -//! // We skip the take while below, because we want to determine the line right -//! // after reading the t_name -//! } <* take_while1(|c| c == b'\n'); +//! ret((t_name as char, p)) +//! // We skip the take while below, because we want to determine the line right +//! // after reading the t_name +//! <* take_while1(|c| c == b'\n'); //! } //! } //! -//! let r = run_parser(i, |i| many(i, parser)).1; -//! -//! assert_eq!(r, Ok(vec![('a', LineNumber(0)), -//! ('b', LineNumber(1)), -//! // Note the two linebreaks in a row -//! ('c', LineNumber(3))])); +//! assert_eq!(many(parser).parse(i).1, Ok(vec![('a', LineNumber(0)), +//! ('b', LineNumber(1)), +//! // Note the two linebreaks in a row +//! ('c', LineNumber(3))])); //! # } //! ``` -use primitives::Guard; -use types::{Buffer, Input}; +use types::{Buffer, Input, Parser}; /// Trait for managing some kind of numbering over the parsed data. pub trait Numbering: Clone { @@ -50,7 +41,7 @@ pub trait Numbering: Clone { /// Updates the numbering based on the contents of the buffer, adding it to the current /// numbering. - fn update<'a, B>(&mut self, &'a B) + fn update(&mut self, &B) where B: Buffer; /// Adds the token to the numbering. @@ -80,7 +71,7 @@ impl Default for LineNumber { impl Numbering for LineNumber { type Token = u8; - fn update<'a, B>(&mut self, b: &'a B) + fn update(&mut self, b: &B) where B: Buffer { let mut n = 0; @@ -98,6 +89,16 @@ impl Numbering for LineNumber { } } +/// A parser which obtains the current position while inside of a `Parser` monad provided the input +/// generic of `Parser` is an `InputPosition`. +pub fn position, E>() -> impl Parser, Output=N, Error=E> { + move |i: InputPosition| { + let p = i.position(); + + (i, Ok(p)) + } +} + /// Wrapper around an `Input` implementation providing numbering support. #[derive(Debug)] pub struct InputPosition> { @@ -126,13 +127,13 @@ impl> Input for InputPosition { type Buffer = I::Buffer; #[inline] - fn _peek(&mut self, g: Guard) -> Option { - self.input._peek(g) + fn peek(&mut self) -> Option { + self.input.peek() } #[inline] - fn _pop(&mut self, g: Guard) -> Option { - self.input._pop(g).map(|t| { + fn pop(&mut self) -> Option { + self.input.pop().map(|t| { self.num.add(t); t @@ -140,8 +141,8 @@ impl> Input for InputPosition { } #[inline] - fn _consume(&mut self, g: Guard, n: usize) -> Option { - self.input._consume(g, n).map(|b| { + fn consume(&mut self, n: usize) -> Option { + self.input.consume(n).map(|b| { self.num.update(&b); b @@ -149,9 +150,9 @@ impl> Input for InputPosition { } #[inline] - fn _consume_while(&mut self, g: Guard, f: F) -> Self::Buffer + fn consume_while(&mut self, f: F) -> Self::Buffer where F: FnMut(Self::Token) -> bool { - let b = self.input._consume_while(g, f); + let b = self.input.consume_while(f); self.num.update(&b); @@ -159,14 +160,14 @@ impl> Input for InputPosition { } #[inline] - fn _consume_from(&mut self, g: Guard, m: Self::Marker) -> Self::Buffer { + fn consume_from(&mut self, m: Self::Marker) -> Self::Buffer { // We have already counted to current position, no need to update - self.input._consume_from(g, m.1) + self.input.consume_from(m.1) } #[inline] - fn _consume_remaining(&mut self, g: Guard) -> Self::Buffer { - let b = self.input._consume_remaining(g); + fn consume_remaining(&mut self) -> Self::Buffer { + let b = self.input.consume_remaining(); self.num.update(&b); @@ -174,14 +175,14 @@ impl> Input for InputPosition { } #[inline] - fn _mark(&self, g: Guard) -> Self::Marker { - (self.num.clone(), self.input._mark(g)) + fn mark(&self) -> Self::Marker { + (self.num.clone(), self.input.mark()) } #[inline] - fn _restore(self, g: Guard, m: Self::Marker) -> Self { + fn restore(self, m: Self::Marker) -> Self { InputPosition { - input: self.input._restore(g, m.1), + input: self.input.restore(m.1), num: m.0, } } @@ -189,9 +190,8 @@ impl> Input for InputPosition { #[cfg(test)] mod test { - use types::{Input, ParseResult}; - use super::{InputPosition, LineNumber}; - use primitives::IntoInner; + use types::{Input, Parser, ret}; + use super::{InputPosition, LineNumber, position}; #[test] fn basic_test() { @@ -200,26 +200,23 @@ mod test { let i = InputPosition::new(&b"test a\ntest b\n\ntest c\n"[..], Default::default()); - fn parser>(i: InputPosition) - -> ParseResult, (char, LineNumber), Error> { - parse!{i; + fn parser>() -> impl Parser, Output=(char, LineNumber), Error=Error> { + parse!{ string(b"test"); take_while1(|c| c == b' ' || c == b'\t'); let t_name = any(); - i -> { - let p = i.position(); + let p = position(); - i.ret((t_name as char, p)) - // We skip the take while below, because we want to determine the line right - // after reading the t_name - } <* take_while1(|c| c == b'\n'); + ret((t_name as char, p)) + // We skip the take while below, because we want to determine the line right + // after reading the t_name + <* take_while1(|c| c == b'\n'); } } - assert_eq!(many(i, parser).into_inner().1, Ok(vec![ - ('a', LineNumber(0)), - ('b', LineNumber(1)), - // Note the two linebreaks in a row - ('c', LineNumber(3))])); + assert_eq!(many(parser).parse(i).1, Ok(vec![('a', LineNumber(0)), + ('b', LineNumber(1)), + // Note the two linebreaks in a row + ('c', LineNumber(3))])); } } diff --git a/src/types/tendril.rs b/src/types/tendril.rs index 17f49781..03a893f4 100644 --- a/src/types/tendril.rs +++ b/src/types/tendril.rs @@ -4,7 +4,6 @@ use std::mem; use tendril::ByteTendril; -use primitives::Guard; use types::{Buffer, Input}; // TODO: Impl for more than byte tendril @@ -14,12 +13,12 @@ impl Input for ByteTendril { type Buffer = ByteTendril; #[inline] - fn _peek(&mut self, _g: Guard) -> Option { + fn peek(&mut self) -> Option { self.as_ref().first().cloned() } #[inline] - fn _pop(&mut self, _g: Guard) -> Option { + fn pop(&mut self) -> Option { if self.len32() > 0 { let t = self.as_ref()[0]; @@ -32,7 +31,7 @@ impl Input for ByteTendril { } #[inline] - fn _consume(&mut self, _g: Guard, n: usize) -> Option { + fn consume(&mut self, n: usize) -> Option { if n > self.len32() as usize { None } else { @@ -45,7 +44,7 @@ impl Input for ByteTendril { } #[inline] - fn _consume_while(&mut self, g: Guard, mut f: F) -> Self::Buffer + fn consume_while(&mut self, mut f: F) -> Self::Buffer where F: FnMut(Self::Token) -> bool { match self.iter().position(|c| !f(*c)) { Some(n) => { @@ -55,30 +54,30 @@ impl Input for ByteTendril { b }, - None => self._consume_remaining(g), + None => self.consume_remaining(), } } #[inline] - fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer { + fn consume_from(&mut self, m: Self::Marker) -> Self::Buffer { // Just the tendril analogue of the slice version: m.subtendril(0, m.len32() - self.len32()) } #[inline] - fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer { + fn consume_remaining(&mut self) -> Self::Buffer { let b = self.subtendril(0, 0); mem::replace(self, b) } #[inline] - fn _mark(&self, _g: Guard) -> Self::Marker { + fn mark(&self) -> Self::Marker { self.clone() } #[inline] - fn _restore(self, _g: Guard, m: Self::Marker) -> Self { + fn restore(self, m: Self::Marker) -> Self { m } } @@ -113,14 +112,14 @@ impl Buffer for ByteTendril { #[cfg(test)] mod test { + use types::Parser; use tendril::Tendril; #[test] fn basic() { use ascii::decimal; - use primitives::IntoInner; - assert_eq!(decimal(Tendril::from_slice(&b"123"[..])).into_inner(), (Tendril::from_slice(&b""[..]), Ok(123i32))); + assert_eq!(decimal().parse(Tendril::from_slice(&b"123"[..])), (Tendril::from_slice(&b""[..]), Ok(123i32))); } #[test] diff --git a/tests/compile-fail/ascii_signed_unsigned_type.rs b/tests/compile-fail/ascii_signed_unsigned_type.rs index 0a1777a7..74f71620 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type.rs @@ -1,13 +1,14 @@ // error-pattern:error[E0271]: type mismatch resolving `>::Err == conv::errors::NoError` +#![feature(conservative_impl_trait)] extern crate chomp; -use chomp::prelude::{U8Input, SimpleResult, parse_only}; +use chomp::prelude::{U8Input, Parser, Error, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: I) -> SimpleResult { - signed(i, decimal) +fn parser() -> impl Parser> { + signed(decimal()) } fn main() { diff --git a/tests/compile-fail/ascii_signed_unsigned_type1.rs b/tests/compile-fail/ascii_signed_unsigned_type1.rs index 64320b7f..8a52363e 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type1.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type1.rs @@ -1,13 +1,14 @@ // error-pattern:error[E0271]: type mismatch resolving `>::Err == conv::errors::NoError` +#![feature(conservative_impl_trait)] extern crate chomp; -use chomp::prelude::{U8Input, SimpleResult, parse_only}; +use chomp::prelude::{U8Input, Parser, Error, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: I) -> SimpleResult { - signed(i, decimal) +fn parser() -> impl Parser> { + signed(decimal()) } fn main() { diff --git a/tests/compile-fail/ascii_signed_unsigned_type2.rs b/tests/compile-fail/ascii_signed_unsigned_type2.rs index 5ac7cad7..e3598712 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type2.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type2.rs @@ -1,13 +1,14 @@ // error-pattern:error[E0271]: type mismatch resolving `>::Err == conv::errors::NoError` +#![feature(conservative_impl_trait)] extern crate chomp; -use chomp::prelude::{U8Input, SimpleResult, parse_only}; +use chomp::prelude::{U8Input, Parser, Error, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: I) -> SimpleResult { - signed(i, decimal) +fn parser() -> impl Parser> { + signed(decimal()) } fn main() { diff --git a/tests/compile-fail/ascii_signed_unsigned_type3.rs b/tests/compile-fail/ascii_signed_unsigned_type3.rs index aac295c5..4003314a 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type3.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type3.rs @@ -1,13 +1,14 @@ // error-pattern:error[E0271]: type mismatch resolving `>::Err == conv::errors::NoError` +#![feature(conservative_impl_trait)] extern crate chomp; -use chomp::prelude::{U8Input, SimpleResult, parse_only}; +use chomp::prelude::{U8Input, Parser, Error, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: I) -> SimpleResult { - signed(i, decimal) +fn parser() -> impl Parser> { + signed(decimal()) } fn main() { diff --git a/tests/compile-fail/ascii_signed_unsigned_type4.rs b/tests/compile-fail/ascii_signed_unsigned_type4.rs index 004ea26d..30623645 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type4.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type4.rs @@ -1,13 +1,14 @@ // error-pattern:error[E0271]: type mismatch resolving `>::Err == conv::errors::NoError` +#![feature(conservative_impl_trait)] extern crate chomp; -use chomp::prelude::{U8Input, SimpleResult, parse_only}; +use chomp::prelude::{U8Input, Parser, Error, parse_only}; use chomp::ascii::{signed, decimal}; -// Should not be possible to use unsigned integers with signed -fn parser(i: I) -> SimpleResult { - signed(i, decimal) +// Should not be possible to use unsigned integers with signed equal or smaller +fn parser() -> impl Parser> { + signed(decimal()) } fn main() {