From 3c4dbbf158eff1be2e8413cd2afeb257539cc9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Fri, 19 Aug 2016 05:41:22 +0200 Subject: [PATCH 01/55] Tests compiling --- examples/http_parser.rs | 66 ++-- src/buffer/mod.rs | 51 ++- src/buffer/slice.rs | 14 +- src/buffer/stateful.rs | 15 +- src/combinators/bounded.rs | 460 ++++++++++++++---------- src/combinators/macros.rs | 140 ++++++++ src/combinators/mod.rs | 165 ++++----- src/lib.rs | 47 +-- src/macros.rs | 331 +++++++++--------- src/parsers.rs | 215 ++++++------ src/types/mod.rs | 698 +++++++++++++++++++------------------ src/types/numbering.rs | 36 +- 12 files changed, 1235 insertions(+), 1003 deletions(-) diff --git a/examples/http_parser.rs b/examples/http_parser.rs index 4deec9cd..be72b625 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,35 +65,12 @@ 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; - string(b"HTTP/"); - take_while1(is_http_version) - } -} - -fn request_line(i: I) -> SimpleResult> { - parse!{i; - 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 { - 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(); @@ -101,8 +79,8 @@ fn message_header_line(i: I) -> SimpleResult { } } -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); @@ -114,10 +92,33 @@ fn message_header(i: I) -> SimpleResult> { } } +fn http_version>() -> impl Parser> { + parse!{ + string(b"HTTP/"); + take_while1(is_http_version) + } +} + +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 { + method: method, + uri: uri, + version: version, + } + } +} + #[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); @@ -127,6 +128,7 @@ fn request(i: I) -> SimpleResult, Vec n += 1, Err(StreamError::Retry) => {}, // Needed to refill buffer when necessary Err(StreamError::EndOfInput) => break, diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index be21b2c3..0789d49a 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -38,9 +38,8 @@ 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; @@ -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..1929f29f 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. @@ -67,17 +65,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..fb345e48 100644 --- a/src/buffer/stateful.rs +++ b/src/buffer/stateful.rs @@ -1,7 +1,6 @@ use std::io; -use types::{Input, ParseResult}; -use primitives::IntoInner; +use types::{Input, Parser}; use buffer::{ Buffer, @@ -202,12 +201,8 @@ impl<'a, S: DataSource, B: Buffer> Stream<'a, 'a> for Source 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 +211,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 +246,7 @@ impl<'a, S: DataSource, B: Buffer> Stream<'a, 'a> for Source } } +/* #[cfg(test)] mod test { use std::io; @@ -524,3 +520,4 @@ mod test { assert_eq!(m, 2); } } +*/ diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 18901b27..c1e46f34 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -26,9 +26,9 @@ use std::ops::{ }; use std::cmp::max; -use types::{Input, ParseResult}; -use primitives::{Primitives, IntoInner}; +use types::{Input, Parser, bind, err, ret, map, inspect, then}; +/* /// 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 @@ -50,8 +50,8 @@ pub trait BoundedRange { /// * 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, + fn parse_many(self, I, F) -> impl Parser + where F: Parser, T: FromIterator; /// Applies the parser `F` multiple times until it fails or the maximum value of the range has @@ -70,8 +70,8 @@ pub trait BoundedRange { /// * 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 skip_many(self, I, F) -> ParseResult - where F: FnMut(I) -> ParseResult; + fn skip_many(self, I, F) -> impl Parser + where F: Parser; // TODO: Fix documentation regarding incomplete /// Applies the parser `P` multiple times until the parser `F` succeeds and returns a value @@ -90,59 +90,61 @@ pub trait BoundedRange { /// * 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 + fn many_till(self, I, R, F) -> impl Parser where T: FromIterator, E: From, - R: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult; + R: Parser, + F: Parser; } +*/ -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))), - - size_hint(self) { - (self.data.0, Some(self.data.1)) - } +#[inline] +pub fn many(start: usize, end: usize, f: F) -> impl Parser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + // Range does not perform this assertion + assert!(start <= end); + + mk_iter!{ + parser: f, + // Range is closed on left side, open on right, ie. [start, end) + state: (usize, usize): (start, max(end, 1) - 1), + + 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; + 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 { + // TODO: Saturating sub? + self.data.0 = if self.data.0 == 0 { 0 } else { self.data.0 - 1 }; + self.data.1 -= 1; } } + + => 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, 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 BoundedRange for Range { #[inline] fn skip_many(self, mut i: I, mut f: F) -> ParseResult where F: FnMut(I) -> ParseResult { @@ -250,39 +252,40 @@ impl BoundedRange for Range { } } } +*/ + +pub fn many_from(start: usize, f: F) -> impl Parser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + mk_iter!{ + parser: f, + // Inclusive + state: usize: start, + + size_hint(self) { + (self.data, None) + } -impl BoundedRange for RangeFrom { - #[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) - } - - next(self) { - pre {} - on { - self.data = self.data.saturating_sub(1); - } + next(self) { + pre {} + on { + self.data = if self.data == 0 { 0 } else { self.data - 1 }; } + } - => 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!(), - } + => result : T { + // 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 BoundedRange for RangeFrom { #[inline] fn skip_many(self, mut i: I, mut f: F) -> ParseResult where F: FnMut(I) -> ParseResult { @@ -354,33 +357,48 @@ impl BoundedRange for RangeFrom { } } } +*/ -impl BoundedRange for RangeFull { - #[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) - } +/// 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`. +/// +/// Propagates errors if the minimum number of iterations has not been met +/// +/// # Panics +/// +/// Will panic if the end of the range is smaller than the start of the range. +/// +/// # Notes +/// +/// * Will allocate depending on the `FromIterator` implementation. +/// * Will never yield more items than the upper bound of the range. +#[inline] +pub fn many_unbounded(f: F) -> impl Parser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + mk_iter!{ + parser: f, + state: (): (), + + size_hint(self) { + (0, None) + } - next(self) { - pre {} - on {} - } + next(self) { + pre {} + on {} + } - => result : T { - (s, (), m, Some(_)) => s.restore(m).ret(result), - (_, _, _, None) => unreachable!(), - } + => result : T { + (s, (), m, Some(_)) => (s.restore(m), Ok(result)), + (_, _, _, None) => unreachable!(), } } +} +/* +impl BoundedRange for RangeFull { #[inline] fn skip_many(self, mut i: I, mut f: F) -> ParseResult where F: FnMut(I) -> ParseResult { @@ -433,44 +451,46 @@ impl BoundedRange for RangeFull { } } } +*/ -impl BoundedRange for RangeTo { - #[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, - - size_hint(self) { - (0, Some(self.data)) - } +#[inline] +pub fn many_to(end: usize, f: F) -> impl Parser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + mk_iter!{ + parser: f, + // Exclusive range [0, end) + state: usize: max(end, 1) - 1, + + size_hint(self) { + (0, Some(self.data)) + } - next(self) { - pre { - if self.data == 0 { - return None; - } - } - on { - self.data -= 1; + 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; } } + + => result : T { + // 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 BoundedRange for RangeTo { #[inline] fn skip_many(self, mut i: I, mut f: F) -> ParseResult where F: FnMut(I) -> ParseResult { @@ -559,44 +579,46 @@ impl BoundedRange for RangeTo { } } } +*/ -impl BoundedRange for usize { - // TODO: Any way to avoid marking for backtracking here? - #[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)) - } +// TODO: Any way to avoid marking for backtracking here? +#[inline] +pub fn many_exact(n: usize, f: F) -> impl Parser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + mk_iter!{ + parser: f, + // Excatly self + state: usize: n, + + size_hint(self) { + (self.data, Some(self.data)) + } - next(self) { - pre { - if self.data == 0 { - return None; - } - } - on { - self.data -= 1; + 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; } } + + => result : T { + // Got exact + (s, 0, _, _) => (s, Ok(result)), + // We have got too few items, propagate error + (s, _, _, Some(e)) => (s, Err(e)), + (_, _, _, None) => unreachable!(), + } } +} +/* +impl BoundedRange for usize { #[inline] fn skip_many(self, mut i: I, mut f: F) -> ParseResult where F: FnMut(I) -> ParseResult { @@ -680,28 +702,9 @@ impl BoundedRange for usize { } } } +*/ -/// 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`. -/// -/// Propagates errors if the minimum number of iterations has not been met -/// -/// # Panics -/// -/// Will panic if the end of the range is smaller than the start of the range. -/// -/// # Notes -/// -/// * Will allocate depending on the `FromIterator` implementation. -/// * Will never yield more items than the upper bound of the range. -#[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) -} - +/* /// Applies the parser `F` multiple times until it fails or the maximum value of the range has /// been reached, throwing away any produced value. /// @@ -743,7 +746,9 @@ pub fn many_till(i: I, r: R, p: P, end: F) -> F: FnMut(I) -> ParseResult { BoundedRange::many_till(r, i, 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 @@ -758,29 +763,101 @@ 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 { +pub fn sep_by_unbounded(mut p: F, mut sep: G) -> impl Parser + where T: FromIterator, + F: FnMut() -> P, + G: FnMut() -> Q, + // E: From, + P: Parser, + Q: Parser { // 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(|_| ()) + let parser = move || inspect(then(|i: I| if item { + match sep().parse(i) { + (i, Ok(_)) => (i, Ok(())), + (i, Err(e)) => (i, Err(e)), + } + } else { + (i, Ok(())) + }, &mut p), |_| item = true); + + many_unbounded(parser) +} + +#[inline] +pub fn sep_by_from(from: usize, mut p: F, mut sep: G) -> impl Parser + where T: FromIterator, + F: FnMut() -> P, + G: FnMut() -> Q, + // E: From, + P: Parser, + Q: Parser { + // 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 = move || inspect(then(|i: I| if item { + match sep().parse(i) { + (i, Ok(_)) => (i, Ok(())), + (i, Err(e)) => (i, Err(e)), + } + } else { + (i, Ok(())) + }, &mut p), |_| item = true); + + many_from(from, parser) +} + +#[inline] +pub fn sep_by_to(to: usize, mut p: F, mut sep: G) -> impl Parser + where T: FromIterator, + F: FnMut() -> P, + G: FnMut() -> Q, + // E: From, + P: Parser, + Q: Parser { + // 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 = move || inspect(then(|i: I| if item { + match sep().parse(i) { + (i, Ok(_)) => (i, Ok(())), + (i, Err(e)) => (i, Err(e)), + } + } else { + (i, Ok(())) + }, &mut p), |_| item = true); + + many_to(to, parser) +} + +#[inline] +pub fn sep_by(from: usize, to: usize, mut p: F, mut sep: G) -> impl Parser + where T: FromIterator, + F: FnMut() -> P, + G: FnMut() -> Q, + // E: From, + P: Parser, + Q: Parser { + // 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 = move || inspect(then(|i: I| if item { + match sep().parse(i) { + (i, Ok(_)) => (i, Ok(())), + (i, Err(e)) => (i, Err(e)), + } } else { - i.ret(()) - }) - .then(&mut p) - .inspect(|_| item = true); + (i, Ok(())) + }, &mut p), |_| item = true); - BoundedRange::parse_many(r, i, parser) + many(from, to, mk_sep_by(p, sep)) } +*/ +/* #[cfg(test)] mod test { - use types::ParseResult; use parsers::{Error, any, token, string}; use primitives::IntoInner; @@ -1108,3 +1185,4 @@ mod test { assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); } } +*/ diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index 11c2722f..d5798485 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -1,3 +1,143 @@ +/// 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! mk_iter { + ( + 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),*$(,)* + } + ) => { { + struct IteratingParser + where F: FnMut() -> P, + P: Parser { + /// Parser to execute once for each iteration + parser_constructor: F, + /// Nested state + data: $data_ty, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData

, + } + + struct ParserIterator + where F: FnMut() -> P, + P: Parser { + /// Last state of the parser + state: Option, + /// Parser constructor function to execute once for each iteration to obtain + /// a new parser to run for each iteration + parser_constructor: 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, + /// Nested state + data: $data_ty, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData

, + } + + impl ParserIterator + where F: FnMut() -> P, + P: Parser { + #[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("ParserIterator.buf was None"), self.data, self.mark, self.state) + } + } + + impl Iterator for ParserIterator + where F: FnMut() -> P, + P: Parser { + type Item = P::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("ParserIterator.buf was None"); + + // TODO: Any way to prevent marking here since it is not used at all times? + $next_self.mark = i.mark(); + + match ($next_self.parser_constructor)().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 = Some(e); + + None + }, + } + } + } + + impl Parser for IteratingParser + where F: FnMut() -> P, + P: Parser, + T: FromIterator { + type Output = T; + type Error = P::Error; + + fn parse(self, i: I) -> (I, Result) { + // TODO: Not always used + let mark = i.mark(); + + let mut iter = ParserIterator::<_, _, _, $t> { + state: None, + parser_constructor: self.parser_constructor, + buf: Some(i), + mark: mark, + data: self.data, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData, + }; + + let $result: T = FromIterator::from_iter(iter.by_ref()); + + match iter.end_state() { + $($pat => $arm),* + } + } + } + + IteratingParser::<_, _, _, $t> { + parser_constructor: $parser, + data: $data, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData, + } + } } +} + /// 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. diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index 6f52ccbf..478b476b 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -7,15 +7,7 @@ pub mod bounded; use std::iter::FromIterator; -use types::{ - ParseResult, - Input, -}; - -use primitives::{ - IntoInner, - Primitives, -}; +use types::{Input, Parser}; /// Applies the parser `p` exactly `num` times collecting all items into `T: FromIterator`. /// @@ -34,10 +26,11 @@ use primitives::{ /// 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_exact(num, p) } /// Tries the parser `f`, on success it yields the parsed value, on failure `default` will be @@ -56,13 +49,15 @@ pub fn count(i: I, num: usize, p: F) -> ParseResult(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), +pub fn option(p: P, default: P::Output) -> impl Parser + where P: Parser { + move |mut i: I| { + let m = i.mark(); + + match p.parse(i) { + (b, Ok(d)) => (b, Ok(d)), + (b, Err(_)) => (b.restore(m), Ok(default)), + } } } @@ -86,14 +81,16 @@ pub fn option(i: I, f: F, default: T) -> ParseResult /// assert_eq!(parse_only(&p, b"cbc"), Err((&b"cbc"[..], Error::expected(b'b')))); /// ``` #[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 or(f: F, g: G) -> impl Parser + where F: Parser, + G: Parser { + move |mut i: I| { + let m = i.mark(); + + match f.parse(i) { + (b, Ok(d)) => (b, Ok(d)), + (b, Err(_)) => g.parse(b.restore(m)), + } } } @@ -114,10 +111,11 @@ pub fn or(i: I, f: F, g: G) -> ParseResult /// 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_unbounded(f) } /// Parses at least one instance of `f` and continues until it does no longer match, collecting @@ -139,12 +137,15 @@ pub fn many(i: I, f: F) -> ParseResult /// 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_from(1, f) } +// FIXME +/* /// Applies the parser `R` zero or more times, separated by the parser `F`. All matches from `R` /// will be collected into the type `T: FromIterator`. /// @@ -162,12 +163,12 @@ pub fn many1(i: I, f: F) -> ParseResult /// 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 T: FromIterator, + //E: From, + R: Parser, + F: Parser { + bounded::sep_by_unbounded(p, sep) } @@ -188,12 +189,12 @@ pub fn sep_by(i: I, p: R, sep: F) -> ParseResult< /// assert_eq!(r, Ok(vec![91, 03, 20])); /// ``` #[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 T: FromIterator, + //E: From, + R: Parser, + F: Parser { + bounded::sep_by_from(1, p, sep) } /// Applies the parser `R` multiple times until the parser `F` succeeds and returns a @@ -211,12 +212,12 @@ pub fn sep_by1(i: I, p: R, sep: F) -> ParseResult /// assert_eq!(r, Ok(vec![b'a', b'b', b'c'])); /// ``` #[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: R, end: F) -> impl Parser + where T: FromIterator, + //E: From, + R: Parser, + F: Parser { + bounded::many_till_unbounded(p, end) } /// Runs the given parser until it fails, discarding matched input. @@ -234,9 +235,9 @@ pub fn many_till(i: I, p: R, end: F) -> ParseResu /// 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 F: Parser { + bounded::skip_many_unbounded(f) } /// Runs the given parser until it fails, discarding matched input, expects at least one match. @@ -258,10 +259,11 @@ pub fn skip_many(i: I, f: F) -> ParseResult /// 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 F: Parser { + bounded::skip_many_from(1, f) } +*/ /// Returns the result of the given parser as well as the slice which matched it. /// @@ -272,17 +274,19 @@ pub fn skip_many1(i: I, f: F) -> ParseResult /// assert_eq!(parse_only(|i| matched_by(i, 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 |mut 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)), + } } } @@ -297,16 +301,20 @@ pub fn matched_by(i: I, f: F) -> ParseResult(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 |mut 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)), + } } } +// FIXME: Update +/* #[cfg(test)] mod test { use types::{Input, ParseResult}; @@ -523,3 +531,4 @@ mod test { 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"))); } } +*/ diff --git a/src/lib.rs b/src/lib.rs index b6f3b2da..2035ebc0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -198,6 +198,7 @@ //! The built-in `chomp::parsers::Error` type is zero-sized and carry no error-information. This //! increases performance somewhat. +#![feature(conservative_impl_trait, specialization)] #![warn(missing_docs, trivial_casts, unused_import_braces, @@ -226,18 +227,18 @@ extern crate debugtrace; #[macro_use] mod macros; -mod parse; +// mod parse; -pub mod ascii; +// pub mod ascii; pub mod buffer; pub mod combinators; pub mod parsers; -pub mod primitives; +// pub mod primitives; pub mod types; -pub use parse::parse_only; -pub use parse::parse_only_str; -pub use parse::run_parser; +// pub use parse::parse_only; +// pub use parse::parse_only_str; +// pub use parse::run_parser; /// Basic prelude. pub mod prelude { @@ -245,7 +246,7 @@ pub mod prelude { any, eof, not_token, - peek, + //peek, peek_next, run_scanner, satisfy, @@ -254,16 +255,13 @@ pub mod prelude { skip_while, string, take, - take_remainder, + //take_remainder, take_till, take_while, take_while1, token, }; - pub use parsers::{ - Error, - SimpleResult, - }; + pub use parsers::Error; pub use combinators::{ count, @@ -271,19 +269,28 @@ pub mod prelude { or, many, many1, - sep_by, - sep_by1, - many_till, - skip_many, - skip_many1, + //sep_by, + //sep_by1, + //many_till, + //skip_many, + //skip_many1, matched_by, }; + pub use types::{ + ret, + err, + map, + inspect, + bind, + then, + from_result, + }; pub use types::{ Buffer, Input, U8Input, - ParseResult, + Parser, }; - pub use parse_only; - pub use parse_only_str; + //pub use parse_only; + //pub use parse_only_str; } diff --git a/src/macros.rs b/src/macros.rs index 3bc8042f..6cfa40cd 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -441,6 +441,8 @@ macro_rules! parse { ( $($t:tt)* ) => { __parse_internal!{ $($t)* } }; } +// FIXME: Update the grammar + /// 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 @@ -448,7 +450,7 @@ macro_rules! parse { #[macro_export] #[doc(hidden)] macro_rules! __parse_internal_or { - ($input:expr, $lhs:expr, $rhs:expr) => { $crate::combinators::or($input, $lhs, $rhs) }; + ($lhs:expr, $rhs:expr) => { $crate::combinators::or($lhs, $rhs) }; } /// Actual implementation of the parse macro, hidden to make the documentation easier to read. @@ -462,10 +464,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)+ ) => { bind(__parse_internal!{@EXPR() $($exp)* }, |_| __parse_internal!{$($tail)* }) }; + ( @BIND(($name:pat) $($exp:tt)+) $($tail:tt)+ ) => { bind(__parse_internal!{@EXPR() $($exp)* }, |$name| __parse_internal!{$($tail)* }) }; + ( @BIND(($name:ident : $name_ty:ty) $($exp:tt)+) $($tail:tt)+ ) => { bind(__parse_internal!{@EXPR() $($exp)* }, |$name : $name_ty| __parse_internal!{$($tail)* }) }; // Term ::= Ret // | Err @@ -473,83 +475,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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)*}, |_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1}, |_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2}, |_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3}, |_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4}, |_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5}, |_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}, |_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}, |_| __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)*}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}, __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)*)}.bind(|l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; // 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)}.bind(|i, l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; + ( @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)}.bind(|i, l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; + ( @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)}.bind(|i, l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; + ( @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)}.bind(|i, l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; + ( @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)*)} }; @@ -585,44 +590,27 @@ 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) => { + ($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)), @@ -697,7 +685,7 @@ mod test { let i = Input(123); // Type annotation necessary since ret leaves E free - let r: Data<_, ()> = parse!{i; ret "foo"}; + let r: Data<_, ()> = parse!{ret "foo"}; assert_eq!(r, Data::Value(123, "foo")); } @@ -706,7 +694,7 @@ mod test { fn ret_typed() { let i = Input(123); - let r = parse!{i; ret @ _, (): "foo"}; + let r = parse!{ret @ _, (): "foo"}; assert_eq!(r, Data::Value(123, "foo")); } @@ -715,7 +703,7 @@ mod test { fn ret_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")); } @@ -725,7 +713,7 @@ mod test { let i = Input(123); // Type annotation necessary since err leaves T free - let r: Data<(), _> = parse!{i; err "foo"}; + let r: Data<(), _> = parse!{err "foo"}; assert_eq!(r, Data::Error(123, "foo")); } @@ -734,7 +722,7 @@ mod test { fn err_typed() { let i = Input(123); - let r = parse!{i; err @(), _: "foo"}; + let r = parse!{err @(), _: "foo"}; assert_eq!(r, Data::Error(123, "foo")); } @@ -743,7 +731,7 @@ mod test { fn err_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")); } @@ -756,7 +744,7 @@ mod test { let i = Input(123); - let r = parse!(i; doit()); + let r = parse!(doit()); assert_eq!(r, Data::Value(123, "doit")); } @@ -769,7 +757,7 @@ mod test { let i = Input(123); - let r = parse!(i; doit("doit")); + let r = parse!(doit("doit")); assert_eq!(r, Data::Value(123, "doit")); } @@ -782,7 +770,7 @@ mod test { 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))); } @@ -802,7 +790,7 @@ mod test { let i = Input(123); - let r = parse!(i; doit(); something()); + let r = parse!(doit(); something()); assert_eq!(r, Data::Value(123, 2)); } @@ -822,7 +810,7 @@ mod test { 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)); } @@ -842,7 +830,7 @@ mod test { 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))); } @@ -881,8 +869,8 @@ mod test { 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: Data<_, ()> = parse!{doit(2); something(4, 5); ret 5}; + let r2 = parse!{doit(2); something(4, 5); ret @ _, (): 5}; assert_eq!(r1, Data::Value(111, 5)); assert_eq!(r2, Data::Value(111, 5)); @@ -899,8 +887,8 @@ mod test { 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: Data<_, ()> = parse!{let n = doit(40); ret n + 2}; + let r2 = parse!{let n = doit(40); ret @ _, (): n + 2}; assert_eq!(r1, Data::Value(321, 42)); assert_eq!(r2, Data::Value(321, 42)); @@ -922,8 +910,8 @@ mod test { 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); + let r1: Data<_, ()> = parse!{let n = doit(40); let x = something(n, 4); ret x + 6}; + let r2 = parse!{let n = doit(40); let x = something(n, 4); ret @ _, (): x + 6}; assert_eq!(r1, Data::Value(111, 42)); @@ -941,8 +929,8 @@ mod test { 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: Data<(), u8> = parse!{let n = doit(40); err n as u8 + 2}; + let r2 = parse!{let n = doit(40); err @ (), u8: n as u8 + 2}; assert_eq!(r1, Data::Error(321, 42)); assert_eq!(r2, Data::Error(321, 42)); @@ -964,8 +952,8 @@ mod test { 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); + let r1: Data<(), u8> = parse!{let n = doit(40); let x = something(n, 4); err x as u8 + 6}; + let r2 = parse!{let n = doit(40); let x = something(n, 4); err @ (), u8: x as u8 + 6}; assert_eq!(r1, Data::Error(111, 42)); @@ -988,8 +976,8 @@ mod test { 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: Data<_, ()> = parse!{let x = something(6, 4); doit(x)}; + let r2 = parse!{let x = something(6, 4); doit(x)}; assert_eq!(r1, Data::Value(321, 2)); assert_eq!(r2, Data::Value(321, 2)); @@ -1011,8 +999,8 @@ mod test { 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: Data<_, ()> = parse!{let _x = something(6, 4); doit(3)}; + let r2 = parse!{let _x = something(6, 4); doit(3)}; assert_eq!(r1, Data::Value(321, 3)); assert_eq!(r2, Data::Value(321, 3)); @@ -1029,8 +1017,8 @@ mod test { 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: Data<_, ()> = parse!{let n: u64 = doit(42); ret n}; + let r2 = parse!{let n: u64 = doit(42); ret @ _, (): n}; assert_eq!(r1, Data::Value(321, 42u64)); assert_eq!(r2, Data::Value(321, 42u64)); @@ -1047,8 +1035,8 @@ mod test { 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: Data<_, ()> = parse!{let (x, y) = something(2, 4); ret x + y}; + let r2 = parse!{let (x, y) = something(2, 4); ret @ _, (): x + y}; assert_eq!(r1, Data::Value(111, 6)); assert_eq!(r2, Data::Value(111, 6)); @@ -1070,9 +1058,9 @@ mod test { let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{i1; let n = doit(40); let (x, y) = something(n, 4); + let r1: Data<_, ()> = parse!{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); + let r2 = parse!{let n = doit(40); let (x, y) = something(n, 4); ret @ _, (): x + y as i32}; assert_eq!(r1, Data::Value(111, 44)); @@ -1113,13 +1101,14 @@ mod test { 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: Data<(), u8> = parse!{doit(2); something(4, 5); err 5}; + let r2 = parse!{doit(2); something(4, 5); err @ (), u8: 5}; assert_eq!(r1, Data::Error(111, 5)); assert_eq!(r2, Data::Error(111, 5)); } + /* #[test] fn inline_action() { let i = Input(123); @@ -1209,14 +1198,15 @@ mod test { assert_eq!(r, Data::Value(321, 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: Data<_, ()> = parse!{let a = ret "test"; ret a}; + let r2: Data<_, ()> = parse!{ret "throwaway"; ret "foo"}; assert_eq!(r1, Data::Value(123, "test")); assert_eq!(r2, Data::Value(123, "foo")); @@ -1227,10 +1217,10 @@ 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: Data<&str, &str> = parse!{let a = err "error"; ret a}; // 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: Data<(), &str> = parse!{err @ (), _: "this"; err "not this"}; assert_eq!(r1, Data::Error(123, "error")); assert_eq!(r2, Data::Error(123, "this")); @@ -1254,10 +1244,12 @@ mod test { 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() }; + trace_macros!(true); + let r1 = parse!{fail() <|> doit()}; + trace_macros!(false); + let r2 = parse!{doit() <|> fail()}; + let r3 = parse!{doit() <|> doit()}; + let r4 = parse!{fail() <|> fail()}; assert_eq!(r1, Data::Value(321, 2)); assert_eq!(r2, Data::Value(321, 2)); @@ -1281,7 +1273,7 @@ mod test { let i = Input(123); - let r1 = parse!{i; fail() <|> fail() <|> doit() }; + let r1 = parse!{fail() <|> fail() <|> doit() }; assert_eq!(r1, Data::Value(321, 2)); } @@ -1309,9 +1301,9 @@ mod test { 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() }; + let r1 = parse!{fail() <|> doit(); next() }; + let r2 = parse!{doit() <|> fail(); next() }; + let r3 = parse!{fail() <|> fail(); next() }; assert_eq!(r1, Data::Value(322, 42)); assert_eq!(r2, Data::Value(322, 42)); @@ -1349,19 +1341,19 @@ mod test { 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 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!{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())}; + 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, Data::Value(323, 2)); assert_eq!(r2, Data::Value(323, 43)); @@ -1415,19 +1407,19 @@ mod test { 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 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!{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())}; + 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, Data::Value(323, 2)); assert_eq!(r2, Data::Value(322, 2)); @@ -1481,19 +1473,19 @@ mod test { 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 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!{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())}; + 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, Data::Value(321, 2)); assert_eq!(r2, Data::Value(323, 43)); @@ -1510,6 +1502,7 @@ mod test { assert_eq!(r12, Data::Value(323, 43)); } + /* #[test] fn alt_inline_action() { let i = Input(123); @@ -1566,6 +1559,7 @@ mod test { assert_eq!(r, Data::Value(333, 21)); } + */ // Test to make sure we do not hit the default macro iteration limit (64) #[test] @@ -1578,8 +1572,9 @@ mod test { 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)); } } +*/ diff --git a/src/parsers.rs b/src/parsers.rs index 10f6f962..acc0837e 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")] @@ -29,10 +25,10 @@ pub use debugtrace::StackFrame; /// 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())), } } @@ -47,11 +43,11 @@ pub fn any(mut i: I) -> SimpleResult { /// assert_eq!(parse_only(|i| satisfy(i, |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())), } } @@ -70,20 +66,20 @@ pub fn satisfy(mut i: I, f: F) -> SimpleResult /// 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())), } } @@ -97,10 +93,10 @@ pub fn satisfy_with(mut i: I, f: F, p: P) -> SimpleRes /// assert_eq!(parse_only(|i| token(i, 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))), } } @@ -114,10 +110,10 @@ pub fn token(mut i: I, t: I::Token) -> SimpleResult { /// assert_eq!(parse_only(|i| not_token(i, 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())), } } @@ -134,10 +130,12 @@ pub fn not_token(mut i: I, t: I::Token) -> SimpleResult { /// 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. @@ -150,10 +148,10 @@ pub fn peek(mut i: I) -> SimpleResult> { /// 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())), } } @@ -167,11 +165,10 @@ pub fn peek_next(mut i: I) -> SimpleResult { /// assert_eq!(parse_only(|i| take(i, 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())), } } @@ -198,11 +195,13 @@ pub fn take(mut i: I, num: usize) -> SimpleResult { /// 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 @@ -219,14 +218,16 @@ pub fn take_while(mut i: I, f: F) -> SimpleResult /// 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)) + } } } @@ -259,24 +260,26 @@ pub fn skip_while(mut i: I, f: F) -> SimpleResult /// 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()) } } @@ -295,13 +298,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. @@ -318,19 +323,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. @@ -341,10 +348,12 @@ pub fn run_scanner(mut i: I, s: S, mut f: F) -> SimpleResu /// 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. @@ -359,27 +368,29 @@ pub fn take_remainder(mut i: I) -> SimpleResult { /// ``` // 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]))) + } } } @@ -393,11 +404,11 @@ pub fn string>(mut i: I, s: &[T]) /// 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())) } } @@ -557,6 +568,7 @@ mod error { } } +/* #[cfg(test)] mod test { use primitives::IntoInner; @@ -712,3 +724,4 @@ mod test { assert!(this.name.as_ref().map(|n| n.contains("parsers::test::backtrace_test")).unwrap_or(false), "Expected trace to contain \"parsers::test::backtrace_test\", got: {:?}", this.name.as_ref()); } } +*/ diff --git a/src/types/mod.rs b/src/types/mod.rs index ca333554..8763a4c9 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -4,8 +4,6 @@ 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` @@ -139,123 +137,76 @@ 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"); - /// - /// assert_eq!(r, Ok("Wohoo, success!")); - /// ``` - #[inline] - fn ret(self, t: T) -> ParseResult { - ParseResult(self, Ok(t)) - } + // Primitive methods - /// 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}; - /// - /// let r = parse_only(|i| - /// // Annotate the value type - /// i.err::<(), _>("Something went wrong"), - /// b"some input"); + /// Peeks at the next token in the input without consuming it. `None` if no more input is + /// available. /// - /// 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 peek(&mut self) -> Option; - /// Converts a `Result` into a `ParseResult`, preserving parser state. - /// - /// 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"); - /// - /// assert_eq!(r, Ok("foo")); + /// Pops a token off the start of the input. `None` if no more input is available. /// - /// let r = parse_only(|i| i.from_result::<(), _>(Err("error message")), b"test"); - /// - /// 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; + fn pop(&mut self) -> Option; - /// **Primitive:** See `Primitives::consume` for documentation. + /// 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] - #[doc(hidden)] - fn _consume(&mut self, Guard, usize) -> Option; + fn consume(&mut self, n: usize) -> Option; - /// **Primitive:** See `Primitives::consume_while` for documentation. + /// 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] - #[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 +215,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 +229,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 +242,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 +260,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 +274,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 +290,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 +309,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 +332,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 +351,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 +365,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,6 +381,97 @@ pub trait U8Input: Input {} impl U8Input for T where T: Input {} +// TODO: More docs +/// A parser. +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 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) + } +} + +/// Returns `t` as a success value in the parsing context. +/// +/// Equivalent to Haskell's `return` function in the `Monad` typeclass. +/// +/// # Example +/// +/// ``` +/// use chomp::types::{Input, parse_only, ret}; +/// +/// let r = parse_only(|i| +/// // Annotate the error type +/// ret::<_, ()>("Wohoo, success!"), +/// b"some input"); +/// +/// assert_eq!(r, Ok("Wohoo, success!")); +/// ``` +#[inline] +pub fn ret(t: T) -> impl Parser { + move |i| (i, Ok(t)) +} + +/// 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}; +/// +/// 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"))); +/// ``` +#[inline] +pub fn err(e: E) -> impl Parser { + move |i| (i, Err(e)) +} + +/// 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::prelude::{Input, parse_only}; +/// +/// let r = parse_only(|i| i.from_result::<_, ()>(Ok("foo")), b"test"); +/// +/// assert_eq!(r, Ok("foo")); +/// +/// let r = parse_only(|i| i.from_result::<(), _>(Err("error message")), b"test"); +/// +/// assert_eq!(r, Err((&b"test"[..], "error message"))); +/// ``` +#[inline] +pub fn from_result(r: Result) -> impl Parser { + move |i| (i, r) +} + +/* /// The basic return type of a parser. /// /// This type satisfies a variant of the `Monad` typeclass. Due to the limitations of Rust's @@ -465,158 +507,172 @@ impl U8Input for T pub struct ParseResult(I, Result); impl ParseResult { - /// Sequentially composes the result with a parse action `f`, passing any produced value as - /// the second parameter. - /// - /// The first parameter to the supplied function `f` is the parser state (`Input`). This - /// state is then passed on to other parsers or used to return a value or an error. - /// - /// # Automatic conversion of `E` - /// - /// The error value `E` will automatically be converted using the `From` trait to the - /// desired type. The downside with this using the current stable version of Rust (1.4) is that - /// the type inferrence will currently not use the default value for the generic `V` and will - /// therefore require extra type hint for the error. - /// - /// # Examples - /// - /// ``` - /// use chomp::prelude::{Input, parse_only}; - /// - /// let r = parse_only(|i| { - /// i.ret("data".to_owned()) - /// // Explicitly state the error type - /// .bind::<_, _, ()>(|i, x| i.ret(x + " here!")) - /// }, - /// b"test"); - /// - /// assert_eq!(r, Ok("data here!".to_owned())); - /// ``` - /// - /// Wrapping the expression in a function will both make it easier to compose and also provides - /// the type-hint for the error in the function signature: - /// - /// ``` - /// use chomp::prelude::{Input, ParseResult, parse_only}; - /// - /// fn parser(i: I, n: i32) -> ParseResult { - /// i.ret(n + 10) - /// } - /// - /// let r = parse_only(|i| i.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))), - } +*/ +/// Sequentially composes the result with a parse action `f`, passing any produced value as +/// the second parameter. +/// +/// The first parameter to the supplied function `f` is the parser state (`Input`). This +/// state is then passed on to other parsers or used to return a value or an error. +/// +/// # Automatic conversion of `E` +/// +/// The error value `E` will automatically be converted using the `From` trait to the +/// desired type. The downside with this using the current stable version of Rust (1.4) is that +/// the type inferrence will currently not use the default value for the generic `V` and will +/// therefore require extra type hint for the error. +/// +/// # Examples +/// +/// ``` +/// use chomp::prelude::{Input, parse_only}; +/// +/// let r = parse_only(|i| { +/// i.ret("data".to_owned()) +/// // Explicitly state the error type +/// .bind::<_, _, ()>(|i, x| i.ret(x + " here!")) +/// }, +/// b"test"); +/// +/// assert_eq!(r, Ok("data here!".to_owned())); +/// ``` +/// +/// Wrapping the expression in a function will both make it easier to compose and also provides +/// the type-hint for the error in the function signature: +/// +/// ``` +/// use chomp::prelude::{Input, ParseResult, parse_only}; +/// +/// fn parser(i: I, n: i32) -> ParseResult { +/// i.ret(n + 10) +/// } +/// +/// let r = parse_only(|i| i.ret(23).bind(parser), b"test"); +/// +/// assert_eq!(r, Ok(33)); +/// ``` +#[inline] +pub fn bind(m: M, f: F) -> impl Parser + where I: Input, + M: Parser, + F: FnOnce(M::Output) -> R, + R: Parser { + move |i| match m.parse(i) { + (i, Ok(t)) => f(t).parse(i), + (i, Err(e)) => (i, Err(e)), } +} - /// Sequentially composes the result with a parse action `f`, discarding any produced value. - /// - /// The first parameter to the supplied function `f` is the parser state (`Input`). This - /// state is then passed on to other parsers or used to return a value or an error. - /// - /// # Relation to `bind` - /// - /// ```text - /// ParseResult::then(g) ≡ ParseResult::bind(|i, _| g(i)) - /// ``` - /// - /// # Example - /// - /// ``` - /// use chomp::prelude::{Input, SimpleResult, parse_only}; - /// - /// fn g(i: I) -> SimpleResult { - /// i.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"); - /// - /// 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)) - } +/// Sequentially composes the result with a parse action `f`, discarding any produced value. +/// +/// The first parameter to the supplied function `f` is the parser state (`Input`). This +/// state is then passed on to other parsers or used to return a value or an error. +/// +/// # Relation to `bind` +/// +/// ```text +/// ParseResult::then(g) ≡ ParseResult::bind(|i, _| g(i)) +/// ``` +/// +/// # Example +/// +/// ``` +/// use chomp::prelude::{Input, SimpleResult, parse_only}; +/// +/// fn g(i: I) -> SimpleResult { +/// i.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"); +/// +/// assert_eq!(r1, Ok("testing!")); +/// assert_eq!(r2, Ok("testing!")); +/// ``` +#[inline] +pub fn then(m: M, f: F) -> impl Parser + where I: Input, + M: Parser, + F: FnOnce() -> R, + R: Parser { + bind(m, |_| f()) +} - /// Applies the function `f` on the contained data if the parser is in a success state. - /// - /// # Example - /// - /// ``` - /// use chomp::prelude::{parse_only, any}; - /// - /// let r = parse_only(|i| any(i).map(|c| c + 12), b"abc"); - /// - /// assert_eq!(r, Ok(b'm')); - /// ``` - #[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)), - } +/// Applies the function `f` on the contained data if the parser is in a success state. +/// +/// # Example +/// +/// ``` +/// use chomp::prelude::{parse_only, any}; +/// +/// let r = parse_only(|i| any(i).map(|c| c + 12), b"abc"); +/// +/// assert_eq!(r, Ok(b'm')); +/// ``` +#[inline] +pub fn map(m: M, f: F) -> impl Parser + where I: Input, + M: Parser, + F: FnOnce(M::Output) -> R { + move |i| match m.parse(i) { + (i, Ok(t)) => (i, Ok(f(t))), + (i, Err(e)) => (i, Err(e)), } +} - /// Applies the function `f` on the contained error if the parser is in an error state. - /// - /// # Example - /// - /// ``` - /// use chomp::prelude::{Input, parse_only}; - /// - /// let r = parse_only(|i| i.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))), - } +/// Applies the function `f` on the contained error if the parser is in an error state. +/// +/// # Example +/// +/// ``` +/// use chomp::prelude::{Input, parse_only}; +/// +/// let r = parse_only(|i| i.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(m: M, f: F) -> impl Parser + where I: Input, + M: Parser, + F: FnOnce(M::Error) -> E { + move |i| match m.parse(i) { + (i, Ok(t)) => (i, Ok(t)), + (i, Err(e)) => (i, Err(f(e))), } +} - /// Calls the function `f` with a reference of the contained data if the parser is in a success - /// state. - /// - /// # Example - /// - /// ``` - /// use chomp::prelude::{parse_only, take_while}; - /// - /// let r = parse_only(|i| take_while(i, |c| c != b' ').inspect(|b| { - /// println!("{:?}", b); // Prints "test" - /// }), b"test and more"); - /// - /// assert_eq!(r, Ok(&b"test"[..])); - /// ``` - #[inline] - pub fn inspect(self, f: F) -> ParseResult - where F: FnOnce(&T) { - if let Ok(ref t) = self.1 { - f(t) - } - - self +/// Calls the function `f` with a reference of the contained data if the parser is in a success +/// state. +/// +/// # Example +/// +/// ``` +/// use chomp::prelude::{parse_only, take_while}; +/// +/// let r = parse_only(|i| take_while(i, |c| c != b' ').inspect(|b| { +/// println!("{:?}", b); // Prints "test" +/// }), b"test and more"); +/// +/// assert_eq!(r, Ok(&b"test"[..])); +/// ``` +#[inline] +pub fn inspect(m: M, f: F) -> impl Parser + where I: Input, + M: Parser, + F: FnOnce(&M::Output) { + move |i| match m.parse(i) { + (i, Ok(t)) => { + f(&t); + + (i, Ok(t)) + }, + (i, Err(e)) => (i, Err(e)), } } +/* /// **Primitive:** Consumes the `ParseResult` and exposes the internal state. /// /// # Primitive @@ -638,160 +694,110 @@ impl IntoInner for ParseResult { (self.0, self.1) } } +*/ #[cfg(test)] pub mod test { - use super::{Buffer, Input, ParseResult}; - use primitives::IntoInner; + use super::{Buffer, Input, Parser, bind, err, ret, from_result, inspect}; 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(i1).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 = bind(ret(a), 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 = bind(m1, 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); + let lhs = bind(bind(lhs_m, f), g); // m >>= (\x -> f x >>= g) - let rhs = rhs_m.bind(|i, x| f(i, x).bind(g)); + let rhs = bind(rhs_m, |x| bind(f(x), 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; - let mut n1 = 0; let mut n2 = 0; - let i1 = b"test ".ret::(23); - let i2 = b"test ".ret::(23); + let i1 = ret::<_, u32, ()>(23); + let i2 = ret::<_, u32, ()>(23); - let r1 = i1.inspect(|d: &u32| { + let r1 = inspect(i1, |d: &u32| { assert_eq!(d, &23); n1 += 1; }); - let r2 = i2.inspect(|d: &u32| { + let r2 = inspect(i2, |d: &u32| { assert_eq!(d, &23); n2 += 1; }); - assert_eq!(r1.into_inner(), (&b"test "[..], Ok(23))); + assert_eq!(r1.parse(&b"test"[..]), (&b"test "[..], Ok(23))); assert_eq!(n1, 1); - assert_eq!(r2.into_inner(), (&b"test "[..], Ok(23))); + assert_eq!(r2.parse(&b"test"[..]), (&b"test "[..], Ok(23))); assert_eq!(n2, 1); } - - #[test] - fn input_propagation() { - let mut n_calls = 0; - - let i = b"test1".ret::<_, ()>(23); - - assert_eq!(i.0, b"test1"); - assert_eq!(i.1, Ok(23)); - - let r: ParseResult<_, _, ()> = i.bind(|i, t| { n_calls += 1; i.ret(t) }); - - assert_eq!((r.0, r.1), (&b"test1"[..], Ok(23))); - assert_eq!(n_calls, 1); - } - - #[test] - fn error_propagation() { - let mut n_calls = 0; - - let i = b"test1".err::<(), _>(23); - - assert_eq!(i.0, b"test1"); - assert_eq!(i.1, Err(23)); - - let r = i.bind(|i, t| { n_calls += 1; i.ret(t) }); - - assert_eq!((r.0, r.1), (&b"test1"[..], Err(23))); - assert_eq!(n_calls, 0); - } - - #[test] - fn slice() { - fn f(i: I, n: u32) -> ParseResult { i.ret(n + 1) } - - let lhs = (&b"test"[..]).ret(123).bind(f); - let rhs = f(&b"test"[..], 123); - - assert_eq!((lhs.0, lhs.1), (&b"test"[..], Ok(124))); - assert_eq!((rhs.0, rhs.1), (&b"test"[..], Ok(124))); - } + */ #[test] fn test_slice() { @@ -807,8 +813,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 053ffe9d..9b12301c 100644 --- a/src/types/numbering.rs +++ b/src/types/numbering.rs @@ -40,7 +40,6 @@ //! # } //! ``` -use primitives::Guard; use types::{Buffer, Input}; /// Trait for managing some kind of numbering over the parsed data. @@ -132,13 +131,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 @@ -146,8 +145,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 @@ -155,9 +154,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); @@ -165,14 +164,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); @@ -180,19 +179,21 @@ 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, } } } +// FIXME +/* #[cfg(test)] mod test { use types::{Input, ParseResult}; @@ -229,3 +230,4 @@ mod test { ('c', LineNumber(3))])); } } +*/ From 0f6fb4afc2ac3dd1e2fdf7e601c0b1577b35cbfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 22 Aug 2016 18:04:38 +0200 Subject: [PATCH 02/55] Implemented Monad, Functor and some MonadPlus methods on Parser type --- src/macros.rs | 959 +++++++++++++++++++++++++---------------------- src/types/mod.rs | 651 +++++++++++++++++++++----------- 2 files changed, 949 insertions(+), 661 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 6cfa40cd..4f3d025a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -443,16 +443,6 @@ macro_rules! parse { // FIXME: Update the grammar -/// 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 { - ($lhs:expr, $rhs:expr) => { $crate::combinators::or($lhs, $rhs) }; -} - /// Actual implementation of the parse macro, hidden to make the documentation easier to read. /// /// Patterns starting with @ symbols are internal rules, used by other parts of the macro. @@ -465,9 +455,9 @@ macro_rules! __parse_internal { // The four versions are needed to allow the empty case (no tailing allowed on the empty // case), _, $pat and $ident:$ty. ( @BIND((_) $($exp:tt)+) ) => { __parse_internal!{@EXPR() $($exp)* } }; - ( @BIND((_) $($exp:tt)+) $($tail:tt)+ ) => { bind(__parse_internal!{@EXPR() $($exp)* }, |_| __parse_internal!{$($tail)* }) }; - ( @BIND(($name:pat) $($exp:tt)+) $($tail:tt)+ ) => { bind(__parse_internal!{@EXPR() $($exp)* }, |$name| __parse_internal!{$($tail)* }) }; - ( @BIND(($name:ident : $name_ty:ty) $($exp:tt)+) $($tail:tt)+ ) => { bind(__parse_internal!{@EXPR() $($exp)* }, |$name : $name_ty| __parse_internal!{$($tail)* }) }; + ( @BIND((_) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(|_| __parse_internal!{$($tail)* }) }; + ( @BIND(($name:pat) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(|$name| __parse_internal!{$($tail)* }) }; + ( @BIND(($name:ident : $name_ty:ty) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(|$name : $name_ty| __parse_internal!{$($tail)* }) }; // Term ::= Ret // | Err @@ -475,13 +465,13 @@ macro_rules! __parse_internal { // | Inline // | Named // Ret ::= "ret" Typed - ( @TERM(ret @ $t_ty:ty , $e_ty:ty : $e:expr) ) => { 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(ret $e:expr) ) => { ret($e) }; + //( @TERM(ret $e:expr) ) => { ret($e) }; // Err ::= "err" Typed - ( @TERM(err @ $t_ty:ty , $e_ty:ty : $e:expr) ) => { 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(err $e:expr) ) => { err($e) }; + //( @TERM(err $e:expr) ) => { err($e) }; // '(' Expr ')' ( @TERM(( $($inner:tt)* )) ) => { __parse_internal!{@EXPR() $($inner)*} }; // Inline ::= $ident "->" $expr @@ -496,64 +486,64 @@ macro_rules! __parse_internal { // Expr ::= ExprAlt ( @EXPR($($lhs:tt)*) ) => { __parse_internal!{@EXPR_ALT() $($lhs)*} }; // | ExprAlt ">>" Expr - ( @EXPR($($lhs:tt)*) >> $($tail:tt)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)*}, |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)*}).bind(|_| __parse_internal!{@EXPR() $($tail)*}) }; // recurse until >> or end // unrolled: // ( @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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1}, |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1}).bind(|_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2}, |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2}).bind(|_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3}, |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3}).bind(|_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4}, |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4}).bind(|_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5}, |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}, |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __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)* ) => { bind(__parse_internal!{@EXPR_ALT() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}, |_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __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($($lhs:tt)*) ) => { __parse_internal!{@EXPR_SKIP() $($lhs)*} }; // | ExprSkip <|> ExprAlt - ( @EXPR_ALT($($lhs:tt)*) <|> $($tail:tt)* ) => { __parse_internal_or!{__parse_internal!{@EXPR_SKIP() $($lhs)*}, __parse_internal!{@EXPR_ALT() $($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($($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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}, __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_or!{__parse_internal!{@EXPR_SKIP() $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}, __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)*} }; + ( @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($($lhs:tt)*) ) => { __parse_internal!{@TERM($($lhs)*)} }; // | Term <* ExprSkip - ( @EXPR_SKIP($($lhs:tt)*) <* $($tail:tt)* ) => { __parse_internal!{@TERM($($lhs)*)}.bind(|l| __parse_internal!{@EXPR_SKIP() $($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($($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)}.bind(|i, l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; + ( @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)}.bind(|i, l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; + ( @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)}.bind(|i, l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; + ( @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)}.bind(|i, l| __parse_internal!{@EXPR_SKIP() $($tail)*}.map(|_| l)) }; + ( @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 ; @@ -596,74 +586,130 @@ macro_rules! __parse_internal { // ::= Expr ';' ( $($tail:tt)+ ) => { __parse_internal!{@STATEMENT((_)) $($tail)+} }; - ( $e:expr ) => { $e }; + //( $e:expr ) => { $e }; // Empty - ( ) => { }; + //( ) => { }; } // 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 { - ($lhs:expr, $rhs:expr) => { - { - 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 err(self, e: E) -> Data { - Data::Error(self.0, e) + 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 } } } - 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 BindParser + where P: Parser, + F: FnOnce(P::Output) -> R, + R: Parser { + p: P, + f: F, + } + + 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)), + } + } + } + + 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), } } + } + + struct SkipParser { + p: P, + q: Q, + } - 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), + 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; @@ -681,433 +727,481 @@ mod test { } #[test] - fn ret() { + fn ret_test() { let i = Input(123); - // Type annotation necessary since ret leaves E free - let r: Data<_, ()> = parse!{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!{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!{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!{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!{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!{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!(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!(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!(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!(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!(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!(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!{doit(2); something(4, 5); ret 5}; - let r2 = parse!{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!{let n = doit(40); ret n + 2}; - let r2 = parse!{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!{let n = doit(40); let x = something(n, 4); ret x + 6}; - let r2 = parse!{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!{let n = doit(40); err n as u8 + 2}; - let r2 = parse!{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!{let n = doit(40); let x = something(n, 4); err x as u8 + 6}; - let r2 = parse!{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!{let x = something(6, 4); doit(x)}; - let r2 = parse!{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!{let _x = something(6, 4); doit(3)}; - let r2 = parse!{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!{let n: u64 = doit(42); ret n}; - let r2 = parse!{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!{let (x, y) = something(2, 4); ret x + y}; - let r2 = parse!{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!{let n = doit(40); let (x, y) = something(n, 4); - ret x + y as i32}; - let r2 = parse!{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!{doit(2); something(4, 5); err 5}; - let r2 = parse!{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() { @@ -1122,15 +1216,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); @@ -1145,7 +1239,7 @@ mod test { } }; - assert_eq!(r, Data::Value(321, 23)); + assert_eq!(r, (321, Ok(23))); } #[test] @@ -1156,7 +1250,7 @@ mod test { s -> s.ret::(23) }; - assert_eq!(r, Data::Value(123, 23)); + assert_eq!(r, (Input(123), Ok(23))); } #[test] @@ -1172,15 +1266,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); @@ -1196,7 +1290,7 @@ mod test { ret @ u32, (): v + 3 }; - assert_eq!(r, Data::Value(321, 28)); + assert_eq!(r, (321, Ok(28))); } */ @@ -1205,11 +1299,11 @@ mod test { let i1 = Input(123); let i2 = Input(123); - let r1: Data<_, ()> = parse!{let a = ret "test"; ret a}; - let r2: Data<_, ()> = parse!{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] @@ -1217,130 +1311,124 @@ mod test { let i1 = Input(123); let i2 = Input(123); - let r1: Data<&str, &str> = parse!{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!{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); - - trace_macros!(true); let r1 = parse!{fail() <|> doit()}; - trace_macros!(false); let r2 = parse!{doit() <|> fail()}; let r3 = parse!{doit() <|> doit()}; let r4 = parse!{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, ())); + 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!{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 i1 = Input(123); - let i2 = Input(123); - let i3 = Input(123); - let r1 = parse!{fail() <|> doit(); next() }; let r2 = parse!{doit() <|> fail(); next() }; let r3 = parse!{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!{a() <* b() <* c()}; let r2 = parse!{a() <* b() >> c()}; let r3 = parse!{a() >> b() <* c()}; @@ -1355,58 +1443,53 @@ mod test { let r11 = parse!{(a() >> b()) >> c()}; let r12 = parse!{ 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)); + 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!{a() <* b() <* c()}; let r2 = parse!{a() <* b() <|> c()}; let r3 = parse!{a() <|> b() <* c()}; @@ -1421,58 +1504,53 @@ mod test { let r11 = parse!{ a() <|> (b() <* c())}; let r12 = parse!{ 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)); + 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!{a() <|> b() <|> c()}; let r2 = parse!{a() <|> b() >> c_a()}; let r3 = parse!{a() >> b() <|> c()}; @@ -1487,19 +1565,19 @@ mod test { let r11 = parse!{ a() >> (b() <|> c())}; let r12 = parse!{ 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)); + 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))); } /* @@ -1515,11 +1593,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] @@ -1530,15 +1608,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] @@ -1549,32 +1627,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!{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/types/mod.rs b/src/types/mod.rs index 8763a4c9..2de1b88e 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,5 +1,7 @@ //! Types which facillitates the chaining of parsers and their results. +use std::marker::PhantomData; + pub mod numbering; #[cfg(feature = "tendril")] pub mod tendril; @@ -382,7 +384,26 @@ impl U8Input for T where T: Input {} // TODO: More docs -/// A parser. +/// The parser monad type. +/// +/// Do-notation is provided by the macro `parse!`. +/// +/// # Equivalence with Haskell's `Monad` typeclass: +/// +/// ```text +/// f >>= g ≡ f().bind(g) +/// f >> g ≡ f().then(g) +/// return a ≡ ret(a) +/// fail a ≡ err(a) +/// ``` +/// +/// It also satisfies the monad laws: +/// +/// ```ignore +/// ret(a).bind(f) = f(a) +/// m.then(ret) = m +/// m.bind(f).bind(g) = m.bind(|x| f(x).bind(g)) +/// ``` pub trait Parser { /// Output type created by the parser, may refer to data owned by `I`. type Output; @@ -391,16 +412,177 @@ pub trait Parser { /// Apply the parser to an input `I`. fn parse(self, I) -> (I, Result); -} -impl Parser for F - where I: Input, - F: FnOnce(I) -> (I, Result) { - type Output = T; - type Error = E; + /// Sequentially composes the result with a parse action `f`, passing any produced value as + /// the second parameter. + /// + /// The first parameter to the supplied function `f` is the parser state (`Input`). This + /// state is then passed on to other parsers or used to return a value or an error. + /// + /// # Automatic conversion of `E` + /// + /// The error value `E` will automatically be converted using the `From` trait to the + /// desired type. The downside with this using the current stable version of Rust (1.4) is that + /// the type inferrence will currently not use the default value for the generic `V` and will + /// therefore require extra type hint for the error. + /// + /// # Examples + /// + /// ``` + /// use chomp::prelude::{Input, parse_only}; + /// + /// let r = parse_only(|i| { + /// i.ret("data".to_owned()) + /// // Explicitly state the error type + /// .bind::<_, _, ()>(|i, x| i.ret(x + " here!")) + /// }, + /// b"test"); + /// + /// assert_eq!(r, Ok("data here!".to_owned())); + /// ``` + /// + /// Wrapping the expression in a function will both make it easier to compose and also provides + /// the type-hint for the error in the function signature: + /// + /// ``` + /// use chomp::prelude::{Input, ParseResult, parse_only}; + /// + /// fn parser(i: I, n: i32) -> ParseResult { + /// i.ret(n + 10) + /// } + /// + /// let r = parse_only(|i| i.ret(23).bind(parser), b"test"); + /// + /// assert_eq!(r, Ok(33)); + /// ``` + #[inline(always)] + // TODO: Add From::from + // TODO: Is it possible to remove I and R here? + fn bind(self, f: F) -> BindParser + where F: FnOnce(Self::Output) -> R, + R: Parser, + Self: Sized { + BindParser { p: self, f: f, _i: PhantomData } + } - fn parse(self, i: I) -> (I, Result) { - (self)(i) + /// Sequentially composes the result with a parse action `f`, discarding any produced value. + /// + /// The first parameter to the supplied function `f` is the parser state (`Input`). This + /// state is then passed on to other parsers or used to return a value or an error. + /// + /// # Relation to `bind` + /// + /// ```text + /// p.then(g) ≡ p.bind(|_| g) + /// ``` + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{Input, SimpleResult, parse_only}; + /// + /// fn g(i: I) -> SimpleResult { + /// i.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"); + /// + /// assert_eq!(r1, Ok("testing!")); + /// assert_eq!(r2, Ok("testing!")); + /// ``` + #[inline(always)] + // TODO: Add From::from + // TODO: Is it possible to use this without I and R in the same way as bind? because bind does + // not seem to work without I and R + // TODO: What are the implications of not exactly mirroring bind? Write down equivalent + // examples and see if they typecheck + // Helps immensely if P already is a parser for eg. sep_by since that solves some lifetime + // issues neatly. + fn then

(self, p: P) -> ThenParser + where P: Parser, + Self: Sized { + ThenParser { p: self, q: p } + } + + /// Applies the function `f` on the contained data if the parser is in a success state. + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{parse_only, any}; + /// + /// let r = parse_only(|i| any(i).map(|c| c + 12), b"abc"); + /// + /// assert_eq!(r, Ok(b'm')); + /// ``` + #[inline] + fn map(self, f: F) -> MapParser + where F: FnOnce(Self::Output) -> R, + Self: Sized { + MapParser { p: self, f: f } + } + + /// Applies the function `f` on the contained error if the parser is in an error state. + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{Input, parse_only}; + /// + /// let r = parse_only(|i| i.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] + fn map_err(self, f: F) -> MapErrParser + where F: FnOnce(Self::Error) -> E, + Self: Sized { + MapErrParser { p: self, f: f } + } + + /// Calls the function `f` with a reference of the contained data if the parser is in a success + /// state. + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{parse_only, take_while}; + /// + /// let r = parse_only(|i| take_while(i, |c| c != b' ').inspect(|b| { + /// println!("{:?}", b); // Prints "test" + /// }), b"test and more"); + /// + /// assert_eq!(r, Ok(&b"test"[..])); + /// ``` + #[inline] + fn inspect(self, f: F) -> InspectParser + where F: FnOnce(&Self::Output), + Self: Sized { + InspectParser { p: self, f: f } + } + + // TODO: Write the laws for MonadPlus, or should satisfy MonadPlus laws (stronger guarantees + // compared to Alternative typeclass laws) + #[inline] + fn or

(self, p: P) -> OrParser + where P: Parser, + Self: Sized { + OrParser { p: self, q: p } + } + + // TODO: Get more of the Applicative instance in here, make tests + // TODO: Docs + #[inline] + 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 } } } @@ -421,8 +603,8 @@ impl Parser for F /// assert_eq!(r, Ok("Wohoo, success!")); /// ``` #[inline] -pub fn ret(t: T) -> impl Parser { - move |i| (i, Ok(t)) +pub fn ret(t: T) -> RetParser { + RetParser { t: t, _e: PhantomData } } /// Returns `e` as an error value in the parsing context. @@ -442,8 +624,8 @@ pub fn ret(t: T) -> impl Parser { /// assert_eq!(r, Err((&b"some input"[..], "Something went wrong"))); /// ``` #[inline] -pub fn err(e: E) -> impl Parser { - move |i| (i, Err(e)) +pub fn err(e: E) -> ErrParser { + ErrParser { e: e, _t: PhantomData } } /// Converts a `Result` into a `Parser`, preserving parser state. @@ -467,250 +649,276 @@ pub fn err(e: E) -> impl Parser { /// assert_eq!(r, Err((&b"test"[..], "error message"))); /// ``` #[inline] -pub fn from_result(r: Result) -> impl Parser { - move |i| (i, r) +pub fn from_result(r: Result) -> FromResultParser { + FromResultParser { r: r } } -/* -/// 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]`). -/// -/// 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) -/// ``` -/// -/// It also satisfies the monad laws: +/// Parser containing a success value. /// -/// ```text -/// return a >>= f ≡ f a -/// m >>= return ≡ m -/// (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) -/// ``` -#[must_use] -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ParseResult(I, Result); +/// This is created by `ret`. +pub struct RetParser { + t: T, + _e: PhantomData, +} -impl ParseResult { -*/ -/// Sequentially composes the result with a parse action `f`, passing any produced value as -/// the second parameter. -/// -/// The first parameter to the supplied function `f` is the parser state (`Input`). This -/// state is then passed on to other parsers or used to return a value or an error. -/// -/// # Automatic conversion of `E` -/// -/// The error value `E` will automatically be converted using the `From` trait to the -/// desired type. The downside with this using the current stable version of Rust (1.4) is that -/// the type inferrence will currently not use the default value for the generic `V` and will -/// therefore require extra type hint for the error. -/// -/// # Examples -/// -/// ``` -/// use chomp::prelude::{Input, parse_only}; -/// -/// let r = parse_only(|i| { -/// i.ret("data".to_owned()) -/// // Explicitly state the error type -/// .bind::<_, _, ()>(|i, x| i.ret(x + " here!")) -/// }, -/// b"test"); -/// -/// assert_eq!(r, Ok("data here!".to_owned())); -/// ``` -/// -/// Wrapping the expression in a function will both make it easier to compose and also provides -/// the type-hint for the error in the function signature: -/// -/// ``` -/// use chomp::prelude::{Input, ParseResult, parse_only}; +impl Parser for RetParser + where I: Input { + type Output = T; + type Error = E; + + #[inline] + fn parse(self, i: I) -> (I, Result) { + (i, Ok(self.t)) + } +} + +/// Parser containing an error value. /// -/// fn parser(i: I, n: i32) -> ParseResult { -/// i.ret(n + 10) -/// } +/// This is created by `err`. +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`. /// -/// let r = parse_only(|i| i.ret(23).bind(parser), b"test"); +/// This is created by `from_result`. +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. /// -/// assert_eq!(r, Ok(33)); -/// ``` -#[inline] -pub fn bind(m: M, f: F) -> impl Parser +/// This is created by the `Parser::bind` method. +pub struct BindParser where I: Input, - M: Parser, - F: FnOnce(M::Output) -> R, - R: Parser { - move |i| match m.parse(i) { - (i, Ok(t)) => f(t).parse(i), - (i, Err(e)) => (i, Err(e)), + 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) { + (i, Ok(t)) => (self.f)(t).parse(i), + (i, Err(e)) => (i, Err(e)), + } } } -/// Sequentially composes the result with a parse action `f`, discarding any produced value. -/// -/// The first parameter to the supplied function `f` is the parser state (`Input`). This -/// state is then passed on to other parsers or used to return a value or an error. -/// -/// # Relation to `bind` -/// -/// ```text -/// ParseResult::then(g) ≡ ParseResult::bind(|i, _| g(i)) -/// ``` -/// -/// # Example -/// -/// ``` -/// use chomp::prelude::{Input, SimpleResult, parse_only}; -/// -/// fn g(i: I) -> SimpleResult { -/// i.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"); +/// Parser for the `Parser::then` chaining operator, allowing to chain parsers. /// -/// assert_eq!(r1, Ok("testing!")); -/// assert_eq!(r2, Ok("testing!")); -/// ``` -#[inline] -pub fn then(m: M, f: F) -> impl Parser +/// This is created by the `Parser::then` method. +pub struct ThenParser { + p: P, + q: Q, +} + +impl Parser for ThenParser where I: Input, - M: Parser, - F: FnOnce() -> R, - R: Parser { - bind(m, |_| f()) + 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) { + (i, Ok(_)) => (self.q).parse(i), + (i, Err(e)) => (i, Err(e)), + } + } } -/// Applies the function `f` on the contained data if the parser is in a success state. -/// -/// # Example +/// Parser for the `Parser::map` combinator. /// -/// ``` -/// use chomp::prelude::{parse_only, any}; -/// -/// let r = parse_only(|i| any(i).map(|c| c + 12), b"abc"); -/// -/// assert_eq!(r, Ok(b'm')); -/// ``` -#[inline] -pub fn map(m: M, f: F) -> impl Parser +/// This is created by the `Parser::map` method. +pub struct MapParser { + p: P, + f: F, +} + +impl Parser for MapParser where I: Input, - M: Parser, - F: FnOnce(M::Output) -> R { - move |i| match m.parse(i) { - (i, Ok(t)) => (i, Ok(f(t))), - (i, Err(e)) => (i, Err(e)), + 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) { + (i, Ok(t)) => (i, Ok((self.f)(t))), + (i, Err(e)) => (i, Err(e)), + } } } -/// Applies the function `f` on the contained error if the parser is in an error state. +/// Parser for the `Parser::map_err` combinator. /// -/// # Example -/// -/// ``` -/// use chomp::prelude::{Input, parse_only}; -/// -/// let r = parse_only(|i| i.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(m: M, f: F) -> impl Parser +/// This is created by the `Parser::map_err` method. +pub struct MapErrParser { + p: P, + f: F, +} + +impl Parser for MapErrParser where I: Input, - M: Parser, - F: FnOnce(M::Error) -> E { - move |i| match m.parse(i) { - (i, Ok(t)) => (i, Ok(t)), - (i, Err(e)) => (i, Err(f(e))), + 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) { + (i, Ok(t)) => (i, Ok(t)), + (i, Err(e)) => (i, Err((self.f)(e))), + } } } -/// Calls the function `f` with a reference of the contained data if the parser is in a success -/// state. +/// Parser for the `Parser::inspect` combinator. /// -/// # Example -/// -/// ``` -/// use chomp::prelude::{parse_only, take_while}; -/// -/// let r = parse_only(|i| take_while(i, |c| c != b' ').inspect(|b| { -/// println!("{:?}", b); // Prints "test" -/// }), b"test and more"); -/// -/// assert_eq!(r, Ok(&b"test"[..])); -/// ``` -#[inline] -pub fn inspect(m: M, f: F) -> impl Parser +/// This is created by `Parser::inspect`. +pub struct InspectParser { + p: P, + f: F, +} + +impl Parser for InspectParser where I: Input, - M: Parser, - F: FnOnce(&M::Output) { - move |i| match m.parse(i) { - (i, Ok(t)) => { - f(&t); + 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) { + (i, Ok(t)) => { + (self.f)(&t); - (i, Ok(t)) - }, - (i, Err(e)) => (i, Err(e)), + (i, Ok(t)) + }, + (i, Err(e)) => (i, Err(e)), + } } } -/* -/// **Primitive:** Consumes the `ParseResult` and exposes the internal state. +/// Parser for the `Parser::or` combinator. /// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -/// -/// # Motivation +/// This is created by `Parser::or`. +pub struct OrParser { + p: P, + q: Q, +} + +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) { + (b, Ok(d)) => (b, Ok(d)), + (b, Err(_)) => self.q.parse(b.restore(m)), + } + } +} + +/// Parser for the `Parser::skip` 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::skip`. +pub struct SkipParser { + p: P, + q: Q, +} - #[inline(always)] - fn into_inner(self) -> Self::Inner { - (self.0, self.1) +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) { + (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 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, Parser, bind, err, ret, from_result, inspect}; + use super::{Buffer, Input, Parser, ret, err, from_result}; use std::fmt::Debug; #[test] 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))); + 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_test() { - assert_eq!(err::<_, (), _>(23u32).parse(&b"in1"[..]), (&b"in1"[..], Err(23u32))); - assert_eq!(err::<_, &str, _>(23i32).parse(&b"in2"[..]), (&b"in2"[..], Err(23i32))); + assert_eq!(err::<(), _>(23u32).parse(&b"in1"[..]), (&b"in1"[..], Err(23u32))); + assert_eq!(err::<&str, _>(23i32).parse(&b"in2"[..]), (&b"in2"[..], Err(23i32))); } #[test] @@ -719,7 +927,7 @@ pub mod test { let i2: Result<&str, &str> = Err("foobar"); assert_eq!(from_result(i1).parse(&b"in1"[..]), (&b"in1"[..], Ok(23u32))); - assert_eq!(from_result(i1).parse(&b"in2"[..]), (&b"in2"[..], Err("foobar"))); + assert_eq!(from_result(i2).parse(&b"in2"[..]), (&b"in2"[..], Err("foobar"))); } #[test] @@ -730,7 +938,7 @@ pub mod test { let a = 123; // return a >>= f - let lhs = bind(ret(a), f); + let lhs = ret(a).bind(f); // f a let rhs = f(a); @@ -740,11 +948,11 @@ pub mod test { #[test] fn monad_right_identity() { - let m1 = ret::<_, _, ()>(1); - let m2 = ret::<_, _, ()>(1); + let m1 = ret::<_, ()>(1); + let m2 = ret::<_, ()>(1); // m1 >>= ret === m2 - let lhs = bind(m1, ret); + let lhs = m1.bind(ret); let rhs = m2; assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok(1))); @@ -761,25 +969,26 @@ pub mod test { ret(num * 2) } - let lhs_m = ret::<_, _, ()>(2); - let rhs_m = ret::<_, _, ()>(2); + let lhs_m = ret::<_, ()>(2); + let rhs_m = ret::<_, ()>(2); // (m >>= f) >>= g - let lhs = bind(bind(lhs_m, f), g); + let lhs = lhs_m.bind(f).bind(g); // m >>= (\x -> f x >>= g) - let rhs = bind(rhs_m, |x| bind(f(x), g)); + let rhs = rhs_m.bind(|x| f(x).bind(g)); assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok(6))); assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok(6))); } + // FIXME: Inspect lifetimes /* #[test] fn parse_result_inspect() { let mut n1 = 0; let mut n2 = 0; - let i1 = ret::<_, u32, ()>(23); - let i2 = ret::<_, u32, ()>(23); + let i1 = ret::(23); + let i2 = ret::(23); let r1 = inspect(i1, |d: &u32| { assert_eq!(d, &23); From f5dab8c4aaa7d8289925ac1d74d2026e84e0887f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 22 Aug 2016 18:11:01 +0200 Subject: [PATCH 03/55] Fixes to warnings, removed or from combinators --- src/combinators/mod.rs | 39 +++------------------------------------ src/lib.rs | 5 ----- src/types/mod.rs | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 41 deletions(-) diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index 478b476b..7098fd06 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -51,7 +51,7 @@ pub fn count(num: usize, p: F) -> impl Parser(p: P, default: P::Output) -> impl Parser where P: Parser { - move |mut i: I| { + move |i: I| { let m = i.mark(); match p.parse(i) { @@ -61,39 +61,6 @@ pub fn option(p: P, default: P::Output) -> impl Parser`). -/// -/// ``` -/// 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')))); -/// ``` -#[inline] -pub fn or(f: F, g: G) -> impl Parser - where F: Parser, - G: Parser { - move |mut i: I| { - let m = i.mark(); - - match f.parse(i) { - (b, Ok(d)) => (b, Ok(d)), - (b, Err(_)) => g.parse(b.restore(m)), - } - } -} - /// Parses many instances of `f` until it does no longer match, collecting all matches into the /// type `T: FromIterator`. /// @@ -276,7 +243,7 @@ pub fn skip_many1(f: F) -> impl Parser(f: F) -> impl Parser where F: Parser { - move |mut i: I| { + move |i: I| { let m = i.mark(); match f.parse(i) { @@ -303,7 +270,7 @@ pub fn matched_by(f: F) -> impl Parser(f: F) -> impl Parser where F: Parser { - move |mut i: I| { + move |i: I| { let m = i.mark(); match f.parse(i) { diff --git a/src/lib.rs b/src/lib.rs index 2035ebc0..3bdb42cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -266,7 +266,6 @@ pub mod prelude { pub use combinators::{ count, option, - or, many, many1, //sep_by, @@ -279,10 +278,6 @@ pub mod prelude { pub use types::{ ret, err, - map, - inspect, - bind, - then, from_result, }; pub use types::{ diff --git a/src/types/mod.rs b/src/types/mod.rs index 2de1b88e..dac4f2dc 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -564,6 +564,25 @@ pub trait Parser { InspectParser { p: self, f: f } } + /// 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')))); + /// ``` // TODO: Write the laws for MonadPlus, or should satisfy MonadPlus laws (stronger guarantees // compared to Alternative typeclass laws) #[inline] From 16f10091cc9cbe8eb17f3599376e407f272fb1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 22 Aug 2016 18:12:20 +0200 Subject: [PATCH 04/55] Updated example and benches --- benches/combinators.rs | 55 +++++++++++++++++++++-------------------- benches/http_bench.rs | 47 ++++++++++++++++++----------------- examples/http_parser.rs | 14 +++++------ 3 files changed, 60 insertions(+), 56 deletions(-) diff --git a/benches/combinators.rs b/benches/combinators.rs index f3a6f55a..51ac3816 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(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(|| { - 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 be72b625..965a3568 100644 --- a/examples/http_parser.rs +++ b/examples/http_parser.rs @@ -66,7 +66,7 @@ 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>() -> impl Parser> { - parse!{(token(b'\r') <|> ret b'\0') >> token(b'\n')} + parse!{(token(b'\r') <|> ret(b'\0')) >> token(b'\n')} } fn message_header_line>() -> impl Parser> { @@ -75,7 +75,7 @@ fn message_header_line>() -> impl Parser>() -> impl Parser>() -> impl Parser>() -> impl Parser, V let h = many(message_header); end_of_line(); - ret (r, h) + ret((r, h)) } } From 7fac29b3a765fa9d3cfe829413ddef2d61a725b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 22 Aug 2016 18:12:34 +0200 Subject: [PATCH 05/55] Buffer: fixed tests --- src/buffer/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index 0789d49a..58ffc2bb 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -507,8 +507,8 @@ mod test { let i1: InputBuf = InputBuf::new(b"in1"); let i2: InputBuf = InputBuf::new(b"in2"); - 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))); + 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] @@ -516,8 +516,8 @@ mod test { let i1: InputBuf = InputBuf::new(b"in1"); let i2: InputBuf = InputBuf::new(b"in2"); - 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))); + 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] From 31ab3603f475359ad54c16ddb9ef7c94bbc405dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 22 Aug 2016 18:13:34 +0200 Subject: [PATCH 06/55] Fixed bounded combinators --- src/combinators/bounded.rs | 258 +++++++++++++++++++++++++++++++------ src/combinators/macros.rs | 77 +++++++---- 2 files changed, 273 insertions(+), 62 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index c1e46f34..aed1ef0f 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -18,19 +18,16 @@ use std::marker::PhantomData; use std::iter::FromIterator; -use std::ops::{ - Range, - RangeFrom, - RangeFull, - RangeTo, -}; use std::cmp::max; -use types::{Input, Parser, bind, err, ret, map, inspect, then}; +use std::ops::{RangeFull, Range}; + +use types::{Input, Parser}; -/* /// Trait for applying a parser multiple times based on a range. -pub trait BoundedRange { +pub trait BoundedMany { + type ManyParser: Parser; + // 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 @@ -50,10 +47,9 @@ pub trait BoundedRange { /// * 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) -> impl Parser - where F: Parser, - T: FromIterator; + fn many(self, f: F) -> Self::ManyParser; + /* /// Applies the parser `F` multiple times until it fails or the maximum value of the range has /// been reached, throwing away any produced value. /// @@ -95,9 +91,82 @@ pub trait BoundedRange { E: From, R: Parser, F: Parser; + */ +} + +many_iter!{ + struct_name: 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 { + // TODO: Saturating sub? + self.data.0 = if self.data.0 == 0 { 0 } else { self.data.0 - 1 }; + self.data.1 -= 1; + } + } + + => 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, 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 BoundedMany for Range + where I: Input, + F: FnMut() -> P, + T: FromIterator, + P: Parser { + type ManyParser = ManyRangeParser; + + #[inline] + fn many(self, f: F) -> Self::ManyParser { + // Range does not perform this assertion + assert!(self.start <= self.end); + + ManyRangeParser { + parser_ctor: f, + // Range is closed on left side, open on right, ie. [start, end) + data: (self.start, max(self.end, 1) - 1), + _i: PhantomData, + _t: PhantomData, + _p: 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`. +/// +/// Propagates errors if the minimum number of iterations has not been met +/// +/// # Panics +/// +/// Will panic if the end of the range is smaller than the start of the range. +/// +/// # 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. +/// * Will only call the parser-constructor `F` once for each iteration, in order #[inline] pub fn many(start: usize, end: usize, f: F) -> impl Parser where F: FnMut() -> P, @@ -107,9 +176,9 @@ pub fn many(start: usize, end: usize, f: F) -> impl Parser { } */ +/// Applies the parser `F` at least `n` times until it fails, collecting the successful values into +/// a `T: FromIterator`. +/// +/// Propagates errors if the minimum number of iterations has not been met. +/// +/// # Notes +/// +/// * Will allocate depending on the `FromIterator` implementation. +/// * Will yield at least `start` number of items upon success. +/// * Will only call the parser-constructor `F` once for each iteration, in order pub fn many_from(start: usize, f: F) -> impl Parser where F: FnMut() -> P, P: Parser, T: FromIterator { mk_iter!{ - parser: f, + parser_ctor: f, // Inclusive - state: usize: start, + state: usize: start, size_hint(self) { (self.data, None) @@ -359,27 +438,64 @@ impl BoundedRange for RangeFrom { } */ +many_iter!{ + struct_name: ManyRangeFullParser, + state: (), + + size_hint(self) { + (0, None) + } + + next(self) { + pre {} + on {} + } + + => result : T { + (s, (), m, Some(_)) => (s.restore(m), Ok(result)), + (_, _, _, None) => unreachable!(), + } +} + +impl BoundedMany for RangeFull + where I: Input, + F: FnMut() -> P, + T: FromIterator, + P: Parser { + type ManyParser = ManyRangeFullParser; + + #[inline] + fn many(self, f: F) -> Self::ManyParser { + ManyRangeFullParser { + parser_ctor: f, + data: (), + _i: PhantomData, + _t: PhantomData, + _p: 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`. /// /// Propagates errors if the minimum number of iterations has not been met /// -/// # Panics -/// -/// Will panic if the end of the range is smaller than the start of the range. -/// /// # Notes /// /// * Will allocate depending on the `FromIterator` implementation. /// * Will never yield more items than the upper bound of the range. +/// * Will only call the parser-constructor `F` once for each iteration, in order #[inline] -pub fn many_unbounded(f: F) -> impl Parser - where F: FnMut() -> P, +pub fn many_unbounded(f: F) -> impl Parser + where I: Input, + F: FnMut() -> P, P: Parser, T: FromIterator { + //BoundedMany::many(.., f) mk_iter!{ - parser: f, - state: (): (), + parser_ctor: f, + state: (): (), size_hint(self) { (0, None) @@ -453,15 +569,25 @@ impl BoundedRange for RangeFull { } */ +/// 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`. +/// +/// Propagates errors if the minimum number of iterations has not been met +/// +/// # Notes +/// +/// * Will allocate depending on the `FromIterator` implementation. +/// * Will never yield more items than the upper bound of the range. +/// * Will only call the parser-constructor `F` once for each iteration, in order #[inline] pub fn many_to(end: usize, f: F) -> impl Parser where F: FnMut() -> P, P: Parser, T: FromIterator { mk_iter!{ - parser: f, + parser_ctor: f, // Exclusive range [0, end) - state: usize: max(end, 1) - 1, + state: usize: max(end, 1) - 1, size_hint(self) { (0, Some(self.data)) @@ -582,15 +708,24 @@ impl BoundedRange for RangeTo { */ // TODO: Any way to avoid marking for backtracking here? +/// Applies the parser `F` exactly `n` times, collecting the successful values into a `T: FromIterator`. +/// +/// Propagates errors if the minimum number of iterations has not been met +/// +/// # Notes +/// +/// * Will allocate depending on the `FromIterator` implementation. +/// * Will yield exactly `n` items upon success. +/// * Will only call the parser-constructor `F` once for each iteration, in order #[inline] pub fn many_exact(n: usize, f: F) -> impl Parser where F: FnMut() -> P, P: Parser, T: FromIterator { mk_iter!{ - parser: f, + parser_ctor: f, // Excatly self - state: usize: n, + state: usize: n, size_hint(self) { (self.data, Some(self.data)) @@ -748,7 +883,6 @@ pub fn many_till(i: I, r: R, p: P, end: F) -> } */ -/* /// 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 @@ -763,28 +897,80 @@ 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_unbounded(mut p: F, mut sep: G) -> impl Parser - where T: FromIterator, +// TODO: look at the From +pub fn sep_by_unbounded(mut f: F, mut sep: G) -> impl Parser + where I: Input, + T: FromIterator, F: FnMut() -> P, G: FnMut() -> Q, // E: From, P: Parser, Q: Parser { + // Ownership: + // + // many('f F) -> Parser<'f> + // sep_by(F, G) -> Parser<'f, 'g> + // + // Parser: many( + + /* // 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 = move || inspect(then(|i: I| if item { + let parser = move || Parser::then(|i: I| if true { match sep().parse(i) { - (i, Ok(_)) => (i, Ok(())), + (i, Ok(_)) => (i, Ok(())), (i, Err(e)) => (i, Err(e)), } } else { (i, Ok(())) - }, &mut p), |_| item = true); + }, || f()).inspect(|_| ());*/ + let mut item = false; - many_unbounded(parser) + many_unbounded(move || if item { + MaybeAParser::parser(sep()) + } else { + item = true; + + MaybeAParser::none() + }.then(f())) } +// TODO: Any benefit making this public? +/// Parser required to unify code of the style of Option

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

(Option

); + +impl

MaybeAParser

{ + fn parser(p: P) -> MaybeAParser

+ where I: Input, + P: Parser { + MaybeAParser(Some(p)) + } + + 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) { + (i, Ok(t)) => (i, Ok(Some(t))), + (i, Err(e)) => (i, Err(e)), + }, + None => (i, Ok(None)), + } + } +} + +/* #[inline] pub fn sep_by_from(from: usize, mut p: F, mut sep: G) -> impl Parser where T: FromIterator, diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index d5798485..bbd5374c 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -1,9 +1,9 @@ -/// Macro to implement and run a parser iterator, it provides the ability to add an extra state +/// Macro to implement, run and create a constructor for 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! mk_iter { ( - parser: $parser:expr, - state: $data_ty:ty : $data:expr, + parser_ctor: $parser_ctor:expr, + state: $data_ty:ty : $data:expr, size_hint($size_hint_self:ident) $size_hint:block next($next_self:ident) { @@ -15,18 +15,6 @@ macro_rules! mk_iter { $($pat:pat => $arm:expr),*$(,)* } ) => { { - struct IteratingParser - where F: FnMut() -> P, - P: Parser { - /// Parser to execute once for each iteration - parser_constructor: F, - /// Nested state - data: $data_ty, - _i: PhantomData, - _t: PhantomData, - _p: PhantomData

, - } - struct ParserIterator where F: FnMut() -> P, P: Parser { @@ -34,7 +22,7 @@ macro_rules! mk_iter { state: Option, /// Parser constructor function to execute once for each iteration to obtain /// a new parser to run for each iteration - parser_constructor: F, + parser_ctor: F, /// Remaining buffer /// /// Wrapped in option to prevent two calls to destructors. @@ -80,7 +68,7 @@ macro_rules! mk_iter { // TODO: Any way to prevent marking here since it is not used at all times? $next_self.mark = i.mark(); - match ($next_self.parser_constructor)().parse(i) { + match ($next_self.parser_ctor)().parse(i) { (b, Ok(v)) => { $next_self.buf = Some(b); @@ -98,6 +86,21 @@ macro_rules! mk_iter { } } + // TODO: Any benefit in keeping this struct? + /* + struct IteratingParser + where F: FnMut() -> P, + T: FromIterator, + P: Parser { + /// Parser to execute once for each iteration + parser_ctor: F, + /// Nested state + data: $data_ty, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData

, + } + impl Parser for IteratingParser where F: FnMut() -> P, P: Parser, @@ -110,14 +113,14 @@ macro_rules! mk_iter { let mark = i.mark(); let mut iter = ParserIterator::<_, _, _, $t> { - state: None, - parser_constructor: self.parser_constructor, - buf: Some(i), - mark: mark, - data: self.data, - _i: PhantomData, - _t: PhantomData, - _p: PhantomData, + state: None, + parser_ctor: self.parser_ctor, + buf: Some(i), + mark: mark, + data: self.data, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData, }; let $result: T = FromIterator::from_iter(iter.by_ref()); @@ -129,11 +132,33 @@ macro_rules! mk_iter { } IteratingParser::<_, _, _, $t> { - parser_constructor: $parser, + parser_ctor: $parser, data: $data, _i: PhantomData, _t: PhantomData, _p: PhantomData, + }*/ + + move |i: I| { + // TODO: Not always used + let mark = i.mark(); + + let mut iter = ParserIterator::<_, _, _, $t> { + state: None, + parser_ctor: $parser_ctor, + buf: Some(i), + mark: mark, + data: $data, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData, + }; + + let $result: T = FromIterator::from_iter(iter.by_ref()); + + match iter.end_state() { + $($pat => $arm),* + } } } } } From 449a4fe4742a4249fb25d6e631b6a247fed9c35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 22 Aug 2016 19:32:57 +0200 Subject: [PATCH 07/55] Unified all many* combinators under one trait --- src/combinators/bounded.rs | 531 +++++++++++++++---------------------- src/combinators/macros.rs | 296 ++++++--------------- src/combinators/mod.rs | 6 +- src/lib.rs | 2 +- src/types/mod.rs | 8 + 5 files changed, 305 insertions(+), 538 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index aed1ef0f..edd8a436 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -20,16 +20,15 @@ use std::marker::PhantomData; use std::iter::FromIterator; use std::cmp::max; -use std::ops::{RangeFull, Range}; +use std::ops::{RangeFrom, RangeFull, RangeTo, Range}; -use types::{Input, Parser}; +use types::{Input, Parser, ThenParser}; /// Trait for applying a parser multiple times based on a range. pub trait BoundedMany { + /// The parser type returned by `many`. type ManyParser: Parser; - // 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`. /// @@ -42,10 +41,9 @@ pub trait BoundedMany { /// # Notes /// /// * Will allocate depending on the `FromIterator` implementation. - /// * 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 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] fn many(self, f: F) -> Self::ManyParser; @@ -95,6 +93,7 @@ pub trait BoundedMany { } many_iter!{ + doc: "Parser iterating over a `Range`, created using `many(n..m, p)`.", struct_name: ManyRangeParser, state: (usize, usize), @@ -129,11 +128,11 @@ many_iter!{ } } -impl BoundedMany for Range +impl BoundedMany for Range where I: Input, F: FnMut() -> P, T: FromIterator, - P: Parser { + P: Parser { type ManyParser = ManyRangeParser; #[inline] @@ -152,66 +151,6 @@ impl BoundedMany for Range } } -/// 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`. -/// -/// Propagates errors if the minimum number of iterations has not been met -/// -/// # Panics -/// -/// Will panic if the end of the range is smaller than the start of the range. -/// -/// # 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. -/// * Will only call the parser-constructor `F` once for each iteration, in order -#[inline] -pub fn many(start: usize, end: usize, f: F) -> impl Parser - where F: FnMut() -> P, - P: Parser, - T: FromIterator { - // Range does not perform this assertion - assert!(start <= end); - - mk_iter!{ - parser_ctor: f, - // Range is closed on left side, open on right, ie. [start, end) - state: (usize, usize): (start, max(end, 1) - 1), - - size_hint(self) { - (self.data.0, Some(self.data.1)) - } - - next(self) { - pre { - if self.data.1 == 0 { - return None; - } - } - on { - // TODO: Saturating sub? - self.data.0 = if self.data.0 == 0 { 0 } else { self.data.0 - 1 }; - self.data.1 -= 1; - } - } - - => 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, 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 BoundedRange for Range { #[inline] @@ -323,42 +262,48 @@ impl BoundedRange for Range { } */ -/// Applies the parser `F` at least `n` times until it fails, collecting the successful values into -/// a `T: FromIterator`. -/// -/// Propagates errors if the minimum number of iterations has not been met. -/// -/// # Notes -/// -/// * Will allocate depending on the `FromIterator` implementation. -/// * Will yield at least `start` number of items upon success. -/// * Will only call the parser-constructor `F` once for each iteration, in order -pub fn many_from(start: usize, f: F) -> impl Parser - where F: FnMut() -> P, - P: Parser, - T: FromIterator { - mk_iter!{ - parser_ctor: f, - // Inclusive - state: usize: start, - - size_hint(self) { - (self.data, None) - } +many_iter!{ + doc: "Parser iterating over a `RangeFrom`, created using `many(n.., p)`.", + struct_name: ManyRangeFromParser, + // Inclusive + state: usize, - next(self) { - pre {} - on { - self.data = if self.data == 0 { 0 } else { self.data - 1 }; - } + size_hint(self) { + (self.data, None) + } + + next(self) { + pre {} + on { + self.data = if self.data == 0 { 0 } else { self.data - 1 }; } + } + + => result : T { + // 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!(), + } +} - => result : T { - // 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 BoundedMany for RangeFrom + where I: Input, + F: FnMut() -> P, + T: FromIterator, + P: Parser { + type ManyParser = ManyRangeFromParser; + + #[inline] + 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, + _p: PhantomData, } } } @@ -439,6 +384,7 @@ impl BoundedRange for RangeFrom { */ many_iter!{ + doc: "Parser iterating over a `RangeFull`, created using `many(.., p)`.", struct_name: ManyRangeFullParser, state: (), @@ -457,11 +403,11 @@ many_iter!{ } } -impl BoundedMany for RangeFull +impl BoundedMany for RangeFull where I: Input, F: FnMut() -> P, T: FromIterator, - P: Parser { + P: Parser { type ManyParser = ManyRangeFullParser; #[inline] @@ -476,43 +422,6 @@ impl BoundedMany for RangeFull } } -/// 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`. -/// -/// Propagates errors if the minimum number of iterations has not been met -/// -/// # Notes -/// -/// * Will allocate depending on the `FromIterator` implementation. -/// * Will never yield more items than the upper bound of the range. -/// * Will only call the parser-constructor `F` once for each iteration, in order -#[inline] -pub fn many_unbounded(f: F) -> impl Parser - where I: Input, - F: FnMut() -> P, - P: Parser, - T: FromIterator { - //BoundedMany::many(.., f) - mk_iter!{ - parser_ctor: f, - state: (): (), - - size_hint(self) { - (0, None) - } - - next(self) { - pre {} - on {} - } - - => result : T { - (s, (), m, Some(_)) => (s.restore(m), Ok(result)), - (_, _, _, None) => unreachable!(), - } - } -} - /* impl BoundedRange for RangeFull { #[inline] @@ -568,49 +477,53 @@ impl BoundedRange for RangeFull { } } */ +many_iter!{ + doc: "Parser iterating over a `RangeTo`, created using `many(..n, p)`.", + struct_name: ManyRangeToParser, + // Exclusive range [0, end) + state: usize, -/// 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`. -/// -/// Propagates errors if the minimum number of iterations has not been met -/// -/// # Notes -/// -/// * Will allocate depending on the `FromIterator` implementation. -/// * Will never yield more items than the upper bound of the range. -/// * Will only call the parser-constructor `F` once for each iteration, in order -#[inline] -pub fn many_to(end: usize, f: F) -> impl Parser - where F: FnMut() -> P, - P: Parser, - T: FromIterator { - mk_iter!{ - parser_ctor: f, - // Exclusive range [0, end) - state: usize: max(end, 1) - 1, - - size_hint(self) { - (0, Some(self.data)) - } + size_hint(self) { + (0, Some(self.data)) + } - next(self) { - pre { - if self.data == 0 { - return None; - } - } - on { - self.data -= 1; + next(self) { + pre { + if self.data == 0 { + return None; } } + on { + self.data -= 1; + } + } - => result : T { - // 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!(), + => result : T { + // 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 BoundedMany for RangeTo + where I: Input, + F: FnMut() -> P, + T: FromIterator, + P: Parser { + type ManyParser = ManyRangeToParser; + + #[inline] + fn many(self, f: F) -> Self::ManyParser { + ManyRangeToParser { + parser_ctor: f, + // Exclusive range [0, end) + data: max(self.end, 1) - 1, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData, } } } @@ -707,47 +620,52 @@ impl BoundedRange for RangeTo { } */ -// TODO: Any way to avoid marking for backtracking here? -/// Applies the parser `F` exactly `n` times, collecting the successful values into a `T: FromIterator`. -/// -/// Propagates errors if the minimum number of iterations has not been met -/// -/// # Notes -/// -/// * Will allocate depending on the `FromIterator` implementation. -/// * Will yield exactly `n` items upon success. -/// * Will only call the parser-constructor `F` once for each iteration, in order -#[inline] -pub fn many_exact(n: usize, f: F) -> impl Parser - where F: FnMut() -> P, - P: Parser, - T: FromIterator { - mk_iter!{ - parser_ctor: f, - // Excatly self - state: usize: n, - - size_hint(self) { - (self.data, Some(self.data)) - } +many_iter!{ + doc: "Parser iterating over a `usize`, created using `many(n, p)`.", + struct_name: ManyExactParser, + // Excatly self + state: usize, - next(self) { - pre { - if self.data == 0 { - return None; - } - } - on { - self.data -= 1; + size_hint(self) { + (self.data, Some(self.data)) + } + + next(self) { + pre { + if self.data == 0 { + return None; } } + on { + self.data -= 1; + } + } - => result : T { - // Got exact - (s, 0, _, _) => (s, Ok(result)), - // We have got too few items, propagate error - (s, _, _, Some(e)) => (s, Err(e)), - (_, _, _, None) => unreachable!(), + => result : T { + // Got exact + (s, 0, _, _) => (s, Ok(result)), + // We have got too few items, propagate error + (s, _, _, Some(e)) => (s, Err(e)), + (_, _, _, None) => unreachable!(), + } +} + +impl BoundedMany for usize + where I: Input, + F: FnMut() -> P, + T: FromIterator, + P: Parser { + type ManyParser = ManyExactParser; + + #[inline] + 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, + _p: PhantomData, } } } @@ -838,6 +756,30 @@ impl BoundedRange for usize { } } */ +/// 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`. +/// +/// Propagates errors if the minimum number of iterations has not been met +/// +/// # Panics +/// +/// Will panic if the end of the range is smaller than the start of the range. +/// +/// # 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. +/// * Will only call the parser-constructor `F` once for each iteration, in order +#[inline] +pub fn many(r: R, f: F) -> R::ManyParser + where I: Input, + F: FnMut() -> P, + T: FromIterator, + P: Parser, + R: BoundedMany { + BoundedMany::many(r, f) +} /* /// Applies the parser `F` multiple times until it fails or the maximum value of the range has @@ -898,57 +840,81 @@ pub fn many_till(i: I, r: R, p: P, end: F) -> /// * Will never yield more items than the upper bound of the range. #[inline] // TODO: look at the From -pub fn sep_by_unbounded(mut f: F, mut sep: G) -> impl Parser +pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser where I: Input, T: FromIterator, F: FnMut() -> P, G: FnMut() -> Q, // E: From, P: Parser, - Q: Parser { - // Ownership: - // - // many('f F) -> Parser<'f> - // sep_by(F, G) -> Parser<'f, 'g> - // - // Parser: many( + Q: Parser, + R: BoundedMany, T, P::Error> { + BoundedMany::many(r, SepByInnerParserCtor { + item: false, + f: f, + sep: sep, + _i: PhantomData, + }) +} - /* - // 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 = move || Parser::then(|i: I| if true { - match sep().parse(i) { - (i, Ok(_)) => (i, Ok(())), - (i, Err(e)) => (i, Err(e)), - } - } else { - (i, Ok(())) - }, || f()).inspect(|_| ());*/ - let mut item = false; +/// Constructor for the inner parser used by `sep_by`. +/// +/// This type is created internally by `sep_by` to construct the appropriate parser from a +/// `BoundedMany` implementation providing the iteration. +// Due to the requirement of BoundedMany 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 +pub struct SepByInnerParserCtor { + item: bool, + f: F, + sep: S, + _i: PhantomData, +} - many_unbounded(move || if item { - MaybeAParser::parser(sep()) - } else { - item = true; +impl FnOnce<()> for SepByInnerParserCtor + where I: Input, + F: FnMut() -> P, + S: FnMut() -> Q, + P: Parser, + Q: Parser { + type Output = ThenParser, P>; + + extern "rust-call" fn call_once(self, _: ()) -> Self::Output { + unimplemented!() + } +} +impl FnMut<()> for SepByInnerParserCtor + where I: Input, + F: FnMut() -> P, + S: FnMut() -> Q, + P: Parser, + Q: Parser { + extern "rust-call" fn call_mut(&mut self, _: ()) -> Self::Output { + if self.item { + MaybeAParser::parser((self.sep)()) + } + else { MaybeAParser::none() - }.then(f())) + }.then((self.f)()) + } } -// TODO: Any benefit making this public? +// TODO: More doc, and probably move /// Parser required to unify code of the style of Option

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

(Option

); +pub struct MaybeAParser

(Option

); impl

MaybeAParser

{ - fn parser(p: P) -> 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)) } - fn none() -> MaybeAParser

{ + /// Creates an empty wrapper plassing the success value. + pub fn none() -> MaybeAParser

{ MaybeAParser(None) } } @@ -970,77 +936,6 @@ impl Parser for MaybeAParser

} } -/* -#[inline] -pub fn sep_by_from(from: usize, mut p: F, mut sep: G) -> impl Parser - where T: FromIterator, - F: FnMut() -> P, - G: FnMut() -> Q, - // E: From, - P: Parser, - Q: Parser { - // 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 = move || inspect(then(|i: I| if item { - match sep().parse(i) { - (i, Ok(_)) => (i, Ok(())), - (i, Err(e)) => (i, Err(e)), - } - } else { - (i, Ok(())) - }, &mut p), |_| item = true); - - many_from(from, parser) -} - -#[inline] -pub fn sep_by_to(to: usize, mut p: F, mut sep: G) -> impl Parser - where T: FromIterator, - F: FnMut() -> P, - G: FnMut() -> Q, - // E: From, - P: Parser, - Q: Parser { - // 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 = move || inspect(then(|i: I| if item { - match sep().parse(i) { - (i, Ok(_)) => (i, Ok(())), - (i, Err(e)) => (i, Err(e)), - } - } else { - (i, Ok(())) - }, &mut p), |_| item = true); - - many_to(to, parser) -} - -#[inline] -pub fn sep_by(from: usize, to: usize, mut p: F, mut sep: G) -> impl Parser - where T: FromIterator, - F: FnMut() -> P, - G: FnMut() -> Q, - // E: From, - P: Parser, - Q: Parser { - // 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 = move || inspect(then(|i: I| if item { - match sep().parse(i) { - (i, Ok(_)) => (i, Ok(())), - (i, Err(e)) => (i, Err(e)), - } - } else { - (i, Ok(())) - }, &mut p), |_| item = true); - - many(from, to, mk_sep_by(p, sep)) -} -*/ - /* #[cfg(test)] mod test { diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index bbd5374c..4081ccbc 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -1,9 +1,8 @@ -/// Macro to implement, run and create a constructor for 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! mk_iter { +macro_rules! many_iter { ( - parser_ctor: $parser_ctor:expr, - state: $data_ty:ty : $data:expr, + doc: $doc:expr, + struct_name: $name:ident, + state: $data_ty:ty, size_hint($size_hint_self:ident) $size_hint:block next($next_self:ident) { @@ -14,81 +13,9 @@ macro_rules! mk_iter { => $result:ident : $t:ty { $($pat:pat => $arm:expr),*$(,)* } - ) => { { - struct ParserIterator - where F: FnMut() -> P, - P: Parser { - /// Last state of the parser - state: Option, - /// 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. - /// - /// Wrapped in option to prevent two calls to destructors. - mark: I::Marker, - /// Nested state - data: $data_ty, - _i: PhantomData, - _t: PhantomData, - _p: PhantomData

, - } - - impl ParserIterator - where F: FnMut() -> P, - P: Parser { - #[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("ParserIterator.buf was None"), self.data, self.mark, self.state) - } - } - - impl Iterator for ParserIterator - where F: FnMut() -> P, - P: Parser { - type Item = P::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("ParserIterator.buf was None"); - - // TODO: Any way to prevent marking here since it is not used at all times? - $next_self.mark = i.mark(); - - match ($next_self.parser_ctor)().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 = Some(e); - - None - }, - } - } - } - - // TODO: Any benefit in keeping this struct? - /* - struct IteratingParser + ) => { + #[doc=$doc] + pub struct $name where F: FnMut() -> P, T: FromIterator, P: Parser { @@ -101,7 +28,7 @@ macro_rules! mk_iter { _p: PhantomData

, } - impl Parser for IteratingParser + impl Parser for $name where F: FnMut() -> P, P: Parser, T: FromIterator { @@ -109,6 +36,77 @@ macro_rules! mk_iter { type Error = P::Error; fn parse(self, i: I) -> (I, Result) { + struct ParserIterator + where F: FnMut() -> P, + P: Parser { + /// Last state of the parser + state: Option, + /// 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. + /// + /// Wrapped in option to prevent two calls to destructors. + mark: I::Marker, + /// Nested state + data: $data_ty, + _i: PhantomData, + _t: PhantomData, + _p: PhantomData

, + } + + impl ParserIterator + where F: FnMut() -> P, + P: Parser { + #[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("ParserIterator.buf was None"), self.data, self.mark, self.state) + } + } + + impl Iterator for ParserIterator + where F: FnMut() -> P, + P: Parser { + type Item = P::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("ParserIterator.buf was None"); + + // TODO: Any way to prevent marking here since it is not used at all times? + $next_self.mark = i.mark(); + + match ($next_self.parser_ctor)().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 = Some(e); + + None + }, + } + } + } + // TODO: Not always used let mark = i.mark(); @@ -130,141 +128,7 @@ macro_rules! mk_iter { } } } - - IteratingParser::<_, _, _, $t> { - parser_ctor: $parser, - data: $data, - _i: PhantomData, - _t: PhantomData, - _p: PhantomData, - }*/ - - move |i: I| { - // TODO: Not always used - let mark = i.mark(); - - let mut iter = ParserIterator::<_, _, _, $t> { - state: None, - parser_ctor: $parser_ctor, - buf: Some(i), - mark: mark, - data: $data, - _i: PhantomData, - _t: PhantomData, - _p: PhantomData, - }; - - let $result: T = FromIterator::from_iter(iter.by_ref()); - - match iter.end_state() { - $($pat => $arm),* - } - } - } } -} - - -/// 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 { - ( - 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),*$(,)* - } - ) => { { - struct Iter - where F: FnMut(I) -> ParseResult { - /// Last state of the parser - state: Option, - /// 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, - /// Nested state - data: $data_ty, - _t: PhantomData, - } - - impl Iter - where F: FnMut(I) -> ParseResult { - #[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) - } - } - - impl Iterator for Iter - where F: FnMut(I) -> ParseResult { - type Item = T; - - #[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"); - - // TODO: Any way to prevent marking here since it is not used at all times? - $next_self.mark = i.mark(); - - match ($next_self.parser)(i).into_inner() { - (b, Ok(v)) => { - $next_self.buf = Some(b); - - $on_next - - Some(v) - }, - (b, Err(e)) => { - $next_self.buf = Some(b); - $next_self.state = Some(e); - - None - }, - } - } - } - - // TODO: Not always used - let mark = $input.mark(); - - let mut iter = Iter { - state: None, - parser: $parser, - buf: Some($input), - mark: mark, - data: $data, - _t: PhantomData, - }; - - let $result: $t = FromIterator::from_iter(iter.by_ref()); - - match iter.end_state() { - $($pat => $arm),* - } - } } + } } /// Version of run_iter which allows for an additional parser to be run which can terminate diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index 7098fd06..9061f20d 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -30,7 +30,7 @@ pub fn count(num: usize, p: F) -> impl Parser P, P: Parser, T: FromIterator { - bounded::many_exact(num, p) + bounded::many(num, p) } /// Tries the parser `f`, on success it yields the parsed value, on failure `default` will be @@ -82,7 +82,7 @@ pub fn many(f: F) -> impl Parser where F: FnMut() -> P, P: Parser, T: FromIterator { - bounded::many_unbounded(f) + bounded::many(.., f) } /// Parses at least one instance of `f` and continues until it does no longer match, collecting @@ -108,7 +108,7 @@ pub fn many1(f: F) -> impl Parser P, P: Parser, T: FromIterator { - bounded::many_from(1, f) + bounded::many(1.., f) } // FIXME diff --git a/src/lib.rs b/src/lib.rs index 3bdb42cb..80644b3d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -198,7 +198,7 @@ //! The built-in `chomp::parsers::Error` type is zero-sized and carry no error-information. This //! increases performance somewhat. -#![feature(conservative_impl_trait, specialization)] +#![feature(conservative_impl_trait, unboxed_closures, fn_traits)] #![warn(missing_docs, trivial_casts, unused_import_braces, diff --git a/src/types/mod.rs b/src/types/mod.rs index dac4f2dc..4420c1d8 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -592,6 +592,14 @@ pub trait Parser { OrParser { p: self, q: p } } + /// 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 #[inline] From 692b50663f8b1370e4e3ca45304774f2baea4f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 22 Aug 2016 21:48:56 +0200 Subject: [PATCH 08/55] skip_many and tests for many and skip_many --- src/combinators/bounded.rs | 556 +++++++++++++++++++++++-------------- src/combinators/macros.rs | 1 + 2 files changed, 348 insertions(+), 209 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index edd8a436..ac15140d 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -46,8 +46,13 @@ pub trait BoundedMany { /// * Will only call the parser-constructor `F` once for each iteration, in order #[inline] fn many(self, f: F) -> Self::ManyParser; +} + +/// Trait for applying a parser multiple times based on a range, ignoring any output. +pub trait BoundedSkipMany { + /// The parser type returned by `skip_many`. + type SkipManyParser: Parser; - /* /// Applies the parser `F` multiple times until it fails or the maximum value of the range has /// been reached, throwing away any produced value. /// @@ -64,9 +69,9 @@ pub trait BoundedMany { /// * 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 skip_many(self, I, F) -> impl Parser - where F: Parser; + 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 @@ -151,46 +156,75 @@ impl BoundedMany for Range } } -/* -impl BoundedRange for Range { - #[inline] - fn skip_many(self, mut i: I, mut f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { - // Range does not perform this assertion - assert!(self.start <= self.end); +/// Parser iterating over a `Range` discarding results, created using `skip_many(n..m, f)`. +pub struct SkipManyRangeParser { + f: F, + max: usize, + min: usize, + _i: PhantomData +} - // Closed on left side, open on right - let (mut min, mut max) = (self.start, max(self.start, self.end.saturating_sub(1))); +impl Parser for SkipManyRangeParser + where I: Input, + F: FnMut() -> P, + P: Parser { + type Output = (); + type Error = P::Error; + #[inline] + fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { loop { - if max == 0 { + if self.max == 0 { break; } let m = i.mark(); - match f(i).into_inner() { + match (self.f)().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 BoundedSkipMany for Range + where I: Input, + F: FnMut() -> P, + P: Parser { + type SkipManyParser = SkipManyRangeParser; + + #[inline] + fn skip_many(self, f: F) -> Self::SkipManyParser { + // Range does not perform this assertion + assert!(self.start <= self.end); + + // Closed on left side, open on right + SkipManyRangeParser { + f: f, + min: self.start, + max: max(self.end, 1) - 1, + _i: PhantomData, + } } +} +/* #[inline] fn many_till(self, i: I, p: R, end: F) -> ParseResult where T: FromIterator, @@ -308,37 +342,65 @@ impl BoundedMany for RangeFrom } } -/* -impl BoundedRange for RangeFrom { - #[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; +/// Parser iterating over a `RangeFrom` discarding results, created using `skip_many(n.., f)`. +pub struct SkipManyRangeFromParser { + f: F, + min: usize, + _i: PhantomData +} +impl Parser for SkipManyRangeFromParser + where I: Input, + F: FnMut() -> P, + P: Parser { + type Output = (); + type Error = P::Error; + + #[inline] + fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { loop { let m = i.mark(); - match f(i).into_inner() { + match (self.f)().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 BoundedSkipMany for RangeFrom + where I: Input, + F: FnMut() -> P, + P: Parser { + type SkipManyParser = SkipManyRangeFromParser; + #[inline] + fn skip_many(self, f: F) -> Self::SkipManyParser { + // Closed on left side + SkipManyRangeFromParser { + f: f, + min: self.start, + _i: PhantomData, + } + } +} + +/* +impl BoundedRange for RangeFrom { #[inline] fn many_till(self, i: I, p: R, end: F) -> ParseResult where T: FromIterator, @@ -422,15 +484,25 @@ impl BoundedMany for RangeFull } } -/* -impl BoundedRange for RangeFull { +/// Parser iterating over a `RangeFull` discarding results, created using `skip_many(.., f)`. +pub struct SkipManyRangeFullParser { + f: F, + _i: PhantomData +} + +impl Parser for SkipManyRangeFullParser + where I: Input, + F: FnMut() -> P, + P: Parser { + type Output = (); + type Error = P::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<(), P::Error>) { loop { let m = i.mark(); - match f(i).into_inner() { + match (self.f)().parse(i) { (b, Ok(_)) => i = b, (b, Err(_)) => { i = b.restore(m); @@ -440,9 +512,28 @@ impl BoundedRange for RangeFull { } } - i.ret(()) + (i, Ok(())) + } +} + +impl BoundedSkipMany for RangeFull + where I: Input, + F: FnMut() -> P, + P: Parser { + type SkipManyParser = SkipManyRangeFullParser; + + #[inline] + fn skip_many(self, f: F) -> Self::SkipManyParser { + // Closed on left side + SkipManyRangeFullParser { + f: f, + _i: PhantomData, + } } +} +/* +impl BoundedRange for RangeFull { #[inline] fn many_till(self, i: I, p: R, end: F) -> ParseResult where T: FromIterator, @@ -528,24 +619,32 @@ impl BoundedMany for RangeTo } } -/* -impl BoundedRange for RangeTo { - #[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; +/// Parser iterating over a `RangeTo` discarding results, created using `skip_many(..n, f)`. +pub struct SkipManyRangeToParser { + f: F, + max: usize, + _i: PhantomData +} + +impl Parser for SkipManyRangeToParser + where I: Input, + F: FnMut() -> P, + P: Parser { + type Output = (); + type Error = P::Error; + #[inline] + fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { loop { - if max == 0 { + if self.max == 0 { break; } let m = i.mark(); - match f(i).into_inner() { + match (self.f)().parse(i) { (b, Ok(_)) => { - max -= 1; + self.max -= 1; i = b }, @@ -558,9 +657,29 @@ impl BoundedRange for RangeTo { } } - i.ret(()) + (i, Ok(())) } +} + +impl BoundedSkipMany for RangeTo + where I: Input, + F: FnMut() -> P, + P: Parser { + type SkipManyParser = SkipManyRangeToParser; + #[inline] + fn skip_many(self, f: F) -> Self::SkipManyParser { + // Open on right side + SkipManyRangeToParser { + f: f, + max: max(self.end, 1) - 1, + _i: PhantomData, + } + } +} + +/* +impl BoundedRange for RangeTo { #[inline] fn many_till(self, i: I, p: R, end: F) -> ParseResult where T: FromIterator, @@ -670,36 +789,64 @@ impl BoundedMany for usize } } -/* -impl BoundedRange for usize { - #[inline] - fn skip_many(self, mut i: I, mut f: F) -> ParseResult - where F: FnMut(I) -> ParseResult { - let mut n = self; +/// Parser iterating `n` times discarding results, created using `skip_many(n, f)`. +pub struct SkipManyUsizeParser { + f: F, + n: usize, + _i: PhantomData +} +impl Parser for SkipManyUsizeParser + where I: Input, + F: FnMut() -> P, + P: Parser { + type Output = (); + type Error = P::Error; + + #[inline] + fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { loop { - if n == 0 { + if self.n == 0 { break; } - match f(i).into_inner() { + match (self.f)().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 BoundedSkipMany for usize + where I: Input, + F: FnMut() -> P, + P: Parser { + type SkipManyParser = SkipManyUsizeParser; + + #[inline] + fn skip_many(self, f: F) -> Self::SkipManyParser { + SkipManyUsizeParser { + f: f, + n: self, + _i: PhantomData, + } + } +} + +/* +impl BoundedRange for usize { #[inline] fn many_till(self, i: I, p: R, end: F) -> ParseResult where T: FromIterator, @@ -781,7 +928,6 @@ pub fn many(r: R, f: F) -> R::ManyParser BoundedMany::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. /// @@ -793,14 +939,19 @@ pub fn many(r: R, f: F) -> R::ManyParser /// /// # 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: FnMut() -> P, + P: Parser, + R: BoundedSkipMany { + BoundedSkipMany::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 @@ -936,124 +1087,125 @@ impl Parser for MaybeAParser

} } -/* #[cfg(test)] mod test { use parsers::{Error, any, token, string}; - use primitives::IntoInner; + use types::Parser; use super::{ many, - many_till, + //many_till, skip_many, }; #[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_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: (_, 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: 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"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..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_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"[..]]))); } + // FIXME + /* #[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')))); @@ -1158,112 +1310,98 @@ mod test { 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'))) ); } + */ #[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"a"[..]), (&b"a"[..], 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(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..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(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(()))); } + // FIXME + /* #[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']))); } + */ } -*/ diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index 4081ccbc..8eb8ccaf 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -35,6 +35,7 @@ macro_rules! many_iter { type Output = T; type Error = P::Error; + #[inline] fn parse(self, i: I) -> (I, Result) { struct ParserIterator where F: FnMut() -> P, From e13e2c8b47ea9be43f44ccfc4143f56ca7f67991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 22 Aug 2016 22:43:02 +0200 Subject: [PATCH 09/55] Travis: only test impl Trait on nightly --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index c835defa..97874a59 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: From 86be71a26a789eb50358be9089b66e02750e9827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Tue, 23 Aug 2016 00:48:09 +0200 Subject: [PATCH 10/55] Clippy --- src/combinators/bounded.rs | 4 ++-- src/types/mod.rs | 34 +++++++++++++++++----------------- src/types/numbering.rs | 4 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index ac15140d..79846e26 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -1079,8 +1079,8 @@ impl Parser for MaybeAParser

fn parse(self, i: I) -> (I, Result) { match self.0 { Some(p) => match p.parse(i) { - (i, Ok(t)) => (i, Ok(Some(t))), - (i, Err(e)) => (i, Err(e)), + (r, Ok(t)) => (r, Ok(Some(t))), + (r, Err(e)) => (r, Err(e)), }, None => (i, Ok(None)), } diff --git a/src/types/mod.rs b/src/types/mod.rs index 4420c1d8..0fb2136d 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -762,8 +762,8 @@ impl Parser for BindParser #[inline] fn parse(self, i: I) -> (I, Result) { match self.p.parse(i) { - (i, Ok(t)) => (self.f)(t).parse(i), - (i, Err(e)) => (i, Err(e)), + (r, Ok(t)) => (self.f)(t).parse(r), + (r, Err(e)) => (r, Err(e)), } } } @@ -786,8 +786,8 @@ impl Parser for ThenParser #[inline] fn parse(self, i: I) -> (I, Result) { match self.p.parse(i) { - (i, Ok(_)) => (self.q).parse(i), - (i, Err(e)) => (i, Err(e)), + (r, Ok(_)) => (self.q).parse(r), + (r, Err(e)) => (r, Err(e)), } } } @@ -810,8 +810,8 @@ impl Parser for MapParser #[inline] fn parse(self, i: I) -> (I, Result) { match self.p.parse(i) { - (i, Ok(t)) => (i, Ok((self.f)(t))), - (i, Err(e)) => (i, Err(e)), + (r, Ok(t)) => (r, Ok((self.f)(t))), + (r, Err(e)) => (r, Err(e)), } } } @@ -834,8 +834,8 @@ impl Parser for MapErrParser #[inline] fn parse(self, i: I) -> (I, Result) { match self.p.parse(i) { - (i, Ok(t)) => (i, Ok(t)), - (i, Err(e)) => (i, Err((self.f)(e))), + (r, Ok(t)) => (r, Ok(t)), + (r, Err(e)) => (r, Err((self.f)(e))), } } } @@ -858,12 +858,12 @@ impl Parser for InspectParser #[inline] fn parse(self, i: I) -> (I, Result) { match self.p.parse(i) { - (i, Ok(t)) => { + (r, Ok(t)) => { (self.f)(&t); - (i, Ok(t)) + (r, Ok(t)) }, - (i, Err(e)) => (i, Err(e)), + (r, Err(e)) => (r, Err(e)), } } } @@ -887,8 +887,8 @@ impl Parser for OrParser let m = i.mark(); match self.p.parse(i) { - (b, Ok(d)) => (b, Ok(d)), - (b, Err(_)) => self.q.parse(b.restore(m)), + (r, Ok(d)) => (r, Ok(d)), + (r, Err(_)) => self.q.parse(r.restore(m)), } } } @@ -911,11 +911,11 @@ impl Parser for SkipParser fn parse(self, i: I) -> (I, 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)), + (r, Ok(t)) => match self.q.parse(r) { + (b, Ok(_)) => (b, Ok(t)), + (b, Err(e)) => (b, Err(e)), }, - (i, Err(e)) => (i, Err(e)), + (r, Err(e)) => (r, Err(e)), } } } diff --git a/src/types/numbering.rs b/src/types/numbering.rs index 9b12301c..8cc34687 100644 --- a/src/types/numbering.rs +++ b/src/types/numbering.rs @@ -49,7 +49,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. @@ -85,7 +85,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; From 2c618dda9990d227faf0ce1ab74976ff754c324e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 11:46:04 +0200 Subject: [PATCH 11/55] Macros: use moving closures since they are all FnOnce --- src/macros.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 4f3d025a..cc42ff03 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -455,9 +455,9 @@ macro_rules! __parse_internal { // The four versions are needed to allow the empty case (no tailing allowed on the empty // case), _, $pat and $ident:$ty. ( @BIND((_) $($exp:tt)+) ) => { __parse_internal!{@EXPR() $($exp)* } }; - ( @BIND((_) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(|_| __parse_internal!{$($tail)* }) }; - ( @BIND(($name:pat) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(|$name| __parse_internal!{$($tail)* }) }; - ( @BIND(($name:ident : $name_ty:ty) $($exp:tt)+) $($tail:tt)+ ) => { (__parse_internal!{@EXPR() $($exp)* }).bind(|$name : $name_ty| __parse_internal!{$($tail)* }) }; + ( @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 @@ -486,24 +486,24 @@ macro_rules! __parse_internal { // Expr ::= ExprAlt ( @EXPR($($lhs:tt)*) ) => { __parse_internal!{@EXPR_ALT() $($lhs)*} }; // | ExprAlt ">>" Expr - ( @EXPR($($lhs:tt)*) >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)*}).bind(|_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @EXPR($($lhs:tt)*) >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT() $($lhs)*}).bind(move |_| __parse_internal!{@EXPR() $($tail)*}) }; // recurse until >> or end // unrolled: // ( @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(|_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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(|_| __parse_internal!{@EXPR() $($tail)*}) }; + ( @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 From 180b67efd51ef9bda077f2a5b8fc6ddb8e1fcca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 11:46:15 +0200 Subject: [PATCH 12/55] Removed unused module --- src/primitives.rs | 125 ---------------------------------------------- 1 file changed, 125 deletions(-) delete mode 100644 src/primitives.rs diff --git a/src/primitives.rs b/src/primitives.rs deleted file mode 100644 index 23879928..00000000 --- a/src/primitives.rs +++ /dev/null @@ -1,125 +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. -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 {} From 581e6303475a60ae98d26377904629c61af33344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 12:11:03 +0200 Subject: [PATCH 13/55] Ascii: Updated ascii module --- src/ascii.rs | 37 +++++++++++++++++-------------------- src/lib.rs | 2 +- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/ascii.rs b/src/ascii.rs index 6c59346e..8a583ef4 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, - take_while, - take_while1, -}; +use parsers::{Error, satisfy, take_while, take_while1}; +use types::{Buffer, Input, Parser}; /// Lowercase ASCII predicate. #[inline] @@ -87,8 +82,9 @@ pub fn is_alphanumeric(c: u8) -> bool { /// assert_eq!(parse_only(skip_whitespace, b" \t "), Ok(())); /// ``` #[inline] -pub fn skip_whitespace>(i: I) -> SimpleResult { - take_while(i, is_whitespace).map(|_| ()) +pub fn skip_whitespace>() -> impl Parser> { + // TODO: More efficient implementation, requires a skip_while parser using Input primitives + take_while(is_whitespace).map(|_| ()) } /// Parses a single digit. @@ -106,8 +102,8 @@ pub fn skip_whitespace>(i: I) -> SimpleResult { /// 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 '-'. @@ -128,14 +124,13 @@ pub fn digit>(i: I) -> SimpleResult { /// 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. @@ -155,8 +150,10 @@ pub fn signed, T, F>(i: I, f: F) -> SimpleResult /// 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`. diff --git a/src/lib.rs b/src/lib.rs index 80644b3d..bb6677a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -229,7 +229,7 @@ extern crate debugtrace; mod macros; // mod parse; -// pub mod ascii; +pub mod ascii; pub mod buffer; pub mod combinators; pub mod parsers; From 5be4d8e3e3410921523e0cce50280172d6fda378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 22:59:03 +0200 Subject: [PATCH 14/55] bounded::sep_by: Fixed missing separator --- src/combinators/bounded.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 79846e26..312cfcb7 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -1046,6 +1046,8 @@ impl FnMut<()> for SepByInnerParserCtor MaybeAParser::parser((self.sep)()) } else { + self.item = true; + MaybeAParser::none() }.then((self.f)()) } From d069a6c5419f9f4b9aaa7177eaaade70e2758096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 23:00:13 +0200 Subject: [PATCH 15/55] Test of bounded many for infinite parsers --- src/combinators/bounded.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 312cfcb7..a8fcd94f 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -1092,7 +1092,7 @@ impl Parser for MaybeAParser

#[cfg(test)] mod test { use parsers::{Error, any, token, string}; - use types::Parser; + use types::{Parser, ret}; use super::{ many, @@ -1135,6 +1135,13 @@ mod test { 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: (_, Result, _>) = many(0.., || token(b'a')).parse(&b""[..]); assert_eq!(r, (&b""[..], Ok(vec![]))); @@ -1182,6 +1189,13 @@ mod test { 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 = many(0, || token(b'a')); assert_eq!(r.parse(&b""[..]), (&b""[..], Ok(vec![]))); From f8673b2bee043f23831c1b19e185673c7d702cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 23:01:00 +0200 Subject: [PATCH 16/55] Updated parse module --- src/lib.rs | 12 +++++------- src/parse.rs | 55 +++++++++++++++++----------------------------------- 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bb6677a1..a84e109f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -227,18 +227,16 @@ extern crate debugtrace; #[macro_use] mod macros; -// mod parse; +mod parse; 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; +pub use parse::parse_only; +pub use parse::parse_only_str; /// Basic prelude. pub mod prelude { @@ -286,6 +284,6 @@ pub mod prelude { U8Input, Parser, }; - //pub use parse_only; - //pub use parse_only_str; + pub use parse_only; + pub use parse_only_str; } diff --git a/src/parse.rs b/src/parse.rs index 4eacea0a..53ffcb7e 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. /// @@ -46,20 +35,21 @@ pub fn run_parser(input: I, parser: F) -> (I, Result) /// 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 +57,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"))); } } From 85102530506d222a90daa27492dcc11014599bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 23:01:34 +0200 Subject: [PATCH 17/55] Uncommented finished items in prelude --- src/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a84e109f..3ef35626 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -244,7 +244,7 @@ pub mod prelude { any, eof, not_token, - //peek, + peek, peek_next, run_scanner, satisfy, @@ -253,7 +253,7 @@ pub mod prelude { skip_while, string, take, - //take_remainder, + take_remainder, take_till, take_while, take_while1, @@ -266,8 +266,9 @@ pub mod prelude { option, many, many1, - //sep_by, - //sep_by1, + sep_by, + sep_by1, + // FIXME //many_till, //skip_many, //skip_many1, From e422346c2b7f44e5a71ec494b18b6769c43d5f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 23:02:10 +0200 Subject: [PATCH 18/55] Moved test for or into types module --- src/types/mod.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index 0fb2136d..b81c42ca 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -493,12 +493,7 @@ pub trait Parser { /// ``` #[inline(always)] // TODO: Add From::from - // TODO: Is it possible to use this without I and R in the same way as bind? because bind does - // not seem to work without I and R - // TODO: What are the implications of not exactly mirroring bind? Write down equivalent - // examples and see if they typecheck - // Helps immensely if P already is a parser for eg. sep_by since that solves some lifetime - // issues neatly. + // TODO: Tests fn then

(self, p: P) -> ThenParser where P: Parser, Self: Sized { @@ -516,6 +511,7 @@ pub trait Parser { /// /// assert_eq!(r, Ok(b'm')); /// ``` + // TODO: Tests #[inline] fn map(self, f: F) -> MapParser where F: FnOnce(Self::Output) -> R, @@ -536,6 +532,7 @@ pub trait Parser { /// /// assert_eq!(r, Err((&b"foo"[..], "this is an error".to_owned()))); /// ``` + // TODO: Tests #[inline] fn map_err(self, f: F) -> MapErrParser where F: FnOnce(Self::Error) -> E, @@ -557,6 +554,7 @@ pub trait Parser { /// /// assert_eq!(r, Ok(&b"test"[..])); /// ``` + // TODO: Tests #[inline] fn inspect(self, f: F) -> InspectParser where F: FnOnce(&Self::Output), @@ -585,6 +583,7 @@ pub trait Parser { /// ``` // TODO: Write the laws for MonadPlus, or should satisfy MonadPlus laws (stronger guarantees // compared to Alternative typeclass laws) + // TODO: Tests #[inline] fn or

(self, p: P) -> OrParser where P: Parser, @@ -602,6 +601,7 @@ pub trait Parser { /// ``` // TODO: Get more of the Applicative instance in here, make tests // TODO: Docs + // TODO: Tests #[inline] fn skip

(self, p: P) -> SkipParser where P: Parser, @@ -1008,6 +1008,21 @@ pub mod test { assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok(6))); } + #[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 + // FIXME: Inspect lifetimes /* #[test] From ea935180f95c2a26a93a02f20ae06ec601bc13a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 23:02:38 +0200 Subject: [PATCH 19/55] combinators: sep_by and sep_by1 --- src/combinators/mod.rs | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index 9061f20d..b5b7f7be 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -111,8 +111,6 @@ pub fn many1(f: F) -> impl Parser(f: F) -> impl Parser(p: R, sep: F) -> impl Parser - where T: FromIterator, +pub fn sep_by(p: R, sep: F) -> impl Parser + where I: Input, + T: FromIterator, //E: From, - R: Parser, - F: Parser { - bounded::sep_by_unbounded(p, sep) + 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`. /// @@ -156,14 +156,19 @@ pub fn sep_by(p: R, sep: F) -> impl Parser(p: R, sep: F) -> impl Parser - where T: FromIterator, +pub fn sep_by1(p: R, sep: F) -> impl Parser + where I: Input, + T: FromIterator, //E: From, - R: Parser, - F: Parser { - bounded::sep_by_from(1, p, sep) + R: FnMut() -> P, + F: FnMut() -> Q, + P: Parser, + Q: Parser { + bounded::sep_by(1.., p, sep) } +// FIXME +/* /// Applies the parser `R` multiple times until the parser `F` succeeds and returns a /// `T: FromIterator` populated by the values yielded by `R`. Consumes the matched part of `F`. /// From 9544443f6ee52f76704e0af554de1ecc307b52e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 Aug 2016 23:02:52 +0200 Subject: [PATCH 20/55] Tests: updated combinator tests --- src/combinators/mod.rs | 229 +++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 148 deletions(-) diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index b5b7f7be..c8a481c6 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -285,99 +285,65 @@ pub fn look_ahead(f: F) -> impl Parser, _>) = 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']))); } +// FIXME: Update +/* #[test] fn skip_many1_test() { assert_eq!(skip_many1(&b"bc"[..], |i| i.err::<(), _>("error")).into_inner(), (&b"bc"[..], Err("error"))); @@ -403,104 +369,71 @@ mod test { 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'@')))); } + */ #[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()))); - - 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(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']))); - 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"))); } } -*/ From 62fd41566835e7ce9dcf01230d3d696de888b2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sun, 28 Aug 2016 19:45:33 +0200 Subject: [PATCH 21/55] Parsers: skip_while --- src/parsers.rs | 12 +++++++----- src/types/mod.rs | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/parsers.rs b/src/parsers.rs index acc0837e..1d4398bd 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -234,16 +234,18 @@ pub fn take_while1(f: F) -> impl Parser(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 diff --git a/src/types/mod.rs b/src/types/mod.rs index b81c42ca..feaf3b4e 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -164,8 +164,9 @@ pub trait Input: Sized { 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. MUST never run the - /// closure more than once on the exact same token. + /// 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. /// From db53877c5eb46168f2e3e8bc21cbd5ef6daffbef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Wed, 31 Aug 2016 15:09:01 +0200 Subject: [PATCH 22/55] combinators: many_till for Range --- src/combinators/bounded.rs | 289 +++++++++++++++++-------------------- src/combinators/macros.rs | 211 +++++++++++++++++---------- 2 files changed, 265 insertions(+), 235 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index a8fcd94f..ea4d68bb 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -43,7 +43,8 @@ pub trait BoundedMany { /// * 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 + /// * Will only call the parser-constructor `F` once for each iteration, in order. + /// * Use `combinators::bounded::many` instead of calling this trait method directly. #[inline] fn many(self, f: F) -> Self::ManyParser; } @@ -64,18 +65,22 @@ pub trait BoundedSkipMany { /// /// # 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, 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 BoundedManyTill { + /// The parser type returned by `many_till`. + type ManyTillParser: Parser; + + /// Applies the parser `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 /// @@ -84,17 +89,11 @@ pub trait BoundedSkipMany { /// # 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) -> impl Parser - where T: FromIterator, - E: From, - R: Parser, - F: Parser; - */ + fn many_till(self, F, G) -> Self::ManyTillParser; } many_iter!{ @@ -224,77 +223,88 @@ impl BoundedSkipMany for Range } } -/* - #[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 { - // 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))), - - size_hint(self) { - (self.data.0, Some(self.data.1)) - } +many_till_iter! { + doc: "Parser iterating over a range and ending with a final parser, created by `many_till(n..m, ...)`", + struct_name: ManyTillRangeParser, + state: (usize, usize), - next(self) { - pre { - if self.data.0 == 0 { - // We have reached minimum, we can attempt to end now + 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(); + // 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; + match (self.data.1, (self.end)().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; + }, + // 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.0 = self.data.0.saturating_sub(1); - // Can't overflow unless we do not quit when self.data.1 == 0 - self.data.1 -= 1; + 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 = if self.data.0 == 0 { 0 } else { self.data.0 - 1 }; + 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!() - } + => result : T { + // 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 BoundedManyTill for Range + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillRangeParser; + + #[inline] + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + // Range does not perform this assertion + assert!(self.start <= self.end); + + ManyTillRangeParser { + p_ctor: f, + q_ctor: g, + // Range is closed on left side, open on right, ie. [self.start, self.end) + data: (self.start, max(self.end, 1) - 1), + _i: PhantomData, + _p: PhantomData, + _q: PhantomData, + _t: PhantomData, } } } -*/ many_iter!{ doc: "Parser iterating over a `RangeFrom`, created using `many(n.., p)`.", @@ -919,11 +929,11 @@ impl BoundedRange for usize { /// * 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(r: R, f: F) -> R::ManyParser +pub fn many(r: R, f: F) -> R::ManyParser where I: Input, F: FnMut() -> P, - T: FromIterator, P: Parser, + T: FromIterator, R: BoundedMany { BoundedMany::many(r, f) } @@ -951,11 +961,9 @@ pub fn skip_many(r: R, f: F) -> R::SkipManyParser BoundedSkipMany::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 `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 /// @@ -965,21 +973,24 @@ pub fn skip_many(r: R, f: F) -> R::SkipManyParser /// /// * 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. #[inline] -pub fn many_till(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: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator, + R: BoundedManyTill { + BoundedManyTill::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. +/// into the range `r` and the separator or parser registers error failure is propagated. /// /// # Panics /// @@ -1096,7 +1107,7 @@ mod test { use super::{ many, - //many_till, + many_till, skip_many, }; @@ -1265,68 +1276,36 @@ mod test { 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')))); } + */ #[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"[..]]))); - } - - #[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..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')))); } - */ #[test] fn skip_range_full() { diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index 8eb8ccaf..d79ebb9c 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -15,8 +15,9 @@ macro_rules! many_iter { } ) => { #[doc=$doc] - pub struct $name - where F: FnMut() -> P, + pub struct $name + where I: Input, + F: FnMut() -> P, T: FromIterator, P: Parser { /// Parser to execute once for each iteration @@ -28,8 +29,9 @@ macro_rules! many_iter { _p: PhantomData

, } - impl Parser for $name - where F: FnMut() -> P, + impl Parser for $name + where I: Input, + F: FnMut() -> P, P: Parser, T: FromIterator { type Output = T; @@ -37,6 +39,7 @@ macro_rules! many_iter { #[inline] fn parse(self, i: I) -> (I, Result) { + /// Iterator used to run the parser multiple times struct ParserIterator where F: FnMut() -> P, P: Parser { @@ -50,8 +53,6 @@ macro_rules! many_iter { /// 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, /// Nested state data: $data_ty, @@ -134,12 +135,11 @@ macro_rules! many_iter { /// 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, + doc: $doc:expr, + struct_name: $name:ident, + state: $data_ty:ty, size_hint($size_hint_self:ident) $size_hint:block next($next_self:ident) { @@ -150,93 +150,144 @@ macro_rules! run_iter_till { => $result:ident : $t:ty { $($pat:pat => $arm:expr),*$(,)* } - ) => { { - enum EndStateTill { - Error(E), - Incomplete, - EndSuccess, - } - - /// 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, + ) => { + #[doc=$doc] + pub struct $name + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator { + /// 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, + _p: PhantomData

, + _q: 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. + impl Parser for $name + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator { + type Output = T; + type Error = P::Error; + #[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) - } - } + fn parse(self, i: I) -> (I, Result) { + enum EndStateTill { + Error(E), + Incomplete, + EndSuccess, + } - impl Iterator for IterTill - where E: From, - P: FnMut(I) -> ParseResult, - F: FnMut(I) -> ParseResult { - type Item = T; + /// Iterator used by `many_till` and `many1`. + struct ParserIterator + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser { + /// Last state of the parser + state: EndStateTill, + /// 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, + _p: PhantomData

, + _q: PhantomData, + } - #[inline] - fn size_hint(&$size_hint_self) -> (usize, Option) { - $size_hint - } + impl ParserIterator + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser { + /// 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) + } + } - #[inline] - fn next(&mut $next_self) -> Option { - $pre_next + impl Iterator for ParserIterator + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser { + type Item = P::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"); + // TODO: Remove the branches here (ie. take + unwrap) + let i = $next_self.buf.take().expect("Iter.buf was None"); - match ($next_self.parser)(i).into_inner() { - (b, Ok(v)) => { - $next_self.buf = Some(b); + match ($next_self.parser)().parse(i) { + (b, Ok(v)) => { + $next_self.buf = Some(b); - $on_next + $on_next - Some(v) - }, - (b, Err(e)) => { - $next_self.buf = Some(b); - $next_self.state = EndStateTill::Error(e); + Some(v) + }, + (b, Err(e)) => { + $next_self.buf = Some(b); + $next_self.state = EndStateTill::Error(e); - None - }, + None + }, + } + } } - } - } - let mut iter = IterTill { - state: EndStateTill::Incomplete, - parser: $parser, - end: $end, - buf: Some($input), - data: $data, - _t: PhantomData, - }; + let mut iter = ParserIterator { + state: EndStateTill::Incomplete, + parser: self.p_ctor, + end: self.q_ctor, + buf: Some(i), + data: self.data, + _i: PhantomData, + _p: PhantomData, + _q: 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),* + } + } } - } } + } } -/// 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. macro_rules! iter_till_end_test { @@ -245,7 +296,7 @@ macro_rules! iter_till_end_test { 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)().parse(i) { (b, Ok(_)) => { $the_self.buf = Some(b); $the_self.state = EndStateTill::EndSuccess; From acd4662213e29efd303571b23d61274a22707bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Wed, 31 Aug 2016 15:42:04 +0200 Subject: [PATCH 23/55] Updated ascii compile-fail to use the monad syntax --- tests/compile-fail/ascii_signed_unsigned_type.rs | 7 ++++--- tests/compile-fail/ascii_signed_unsigned_type1.rs | 7 ++++--- tests/compile-fail/ascii_signed_unsigned_type2.rs | 7 ++++--- tests/compile-fail/ascii_signed_unsigned_type3.rs | 7 ++++--- tests/compile-fail/ascii_signed_unsigned_type4.rs | 9 +++++---- 5 files changed, 21 insertions(+), 16 deletions(-) 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() { From 71499dab29ceb2e014ea1f977d401e0d15551e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Wed, 31 Aug 2016 19:16:22 +0200 Subject: [PATCH 24/55] combinators::bounded: Removed unnecessary generic in macros --- src/combinators/bounded.rs | 13 ++++++------- src/combinators/macros.rs | 16 +++++++--------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index ea4d68bb..360c883a 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -118,7 +118,7 @@ many_iter!{ } } - => result : T { + => result { // Got all occurrences of the parser // First state or reached max => do not restore to mark since it is from last // iteration @@ -266,7 +266,7 @@ many_till_iter! { } } - => result : T { + => result { // Got all occurrences of the parser (s, (0, _), EndStateTill::EndSuccess) => (s, Ok(result)), // Did not reach minimum or a failure, propagate @@ -323,7 +323,7 @@ many_iter!{ } } - => result : T { + => result { // We got at least n items (s, 0, m, Some(_)) => (s.restore(m), Ok(result)), // Items still remaining, propagate @@ -469,7 +469,7 @@ many_iter!{ on {} } - => result : T { + => result { (s, (), m, Some(_)) => (s.restore(m), Ok(result)), (_, _, _, None) => unreachable!(), } @@ -534,7 +534,6 @@ impl BoundedSkipMany for RangeFull #[inline] fn skip_many(self, f: F) -> Self::SkipManyParser { - // Closed on left side SkipManyRangeFullParser { f: f, _i: PhantomData, @@ -599,7 +598,7 @@ many_iter!{ } } - => result : T { + => result { // First state or reached max => do not restore to mark since it is from last // iteration (s, 0, _, _) => (s, Ok(result)), @@ -770,7 +769,7 @@ many_iter!{ } } - => result : T { + => result { // Got exact (s, 0, _, _) => (s, Ok(result)), // We have got too few items, propagate error diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index d79ebb9c..767431bf 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -10,7 +10,7 @@ macro_rules! many_iter { on $on_next:block } - => $result:ident : $t:ty { + => $result:ident { $($pat:pat => $arm:expr),*$(,)* } ) => { @@ -40,7 +40,7 @@ macro_rules! many_iter { #[inline] fn parse(self, i: I) -> (I, Result) { /// Iterator used to run the parser multiple times - struct ParserIterator + struct ParserIterator where F: FnMut() -> P, P: Parser { /// Last state of the parser @@ -57,11 +57,10 @@ macro_rules! many_iter { /// Nested state data: $data_ty, _i: PhantomData, - _t: PhantomData, _p: PhantomData

, } - impl ParserIterator + impl ParserIterator where F: FnMut() -> P, P: Parser { #[inline] @@ -71,7 +70,7 @@ macro_rules! many_iter { } } - impl Iterator for ParserIterator + impl Iterator for ParserIterator where F: FnMut() -> P, P: Parser { type Item = P::Output; @@ -112,14 +111,13 @@ macro_rules! many_iter { // TODO: Not always used let mark = i.mark(); - let mut iter = ParserIterator::<_, _, _, $t> { + let mut iter = ParserIterator { state: None, parser_ctor: self.parser_ctor, buf: Some(i), mark: mark, data: self.data, _i: PhantomData, - _t: PhantomData, _p: PhantomData, }; @@ -147,7 +145,7 @@ macro_rules! many_till_iter { on $on_next:block } - => $result:ident : $t:ty { + => $result:ident { $($pat:pat => $arm:expr),*$(,)* } ) => { @@ -277,7 +275,7 @@ macro_rules! many_till_iter { _q: 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),* From 4f9f1cc59f61c4ba606dd95660b5a36876ff01b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Wed, 31 Aug 2016 23:27:09 +0200 Subject: [PATCH 25/55] types: Input no longer requires the Sized bound --- src/types/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index feaf3b4e..85841e95 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -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; From d5530c53d099b7eb460e2ca29535ffccd86b93d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Wed, 31 Aug 2016 23:27:57 +0200 Subject: [PATCH 26/55] Parser: Added boxed() to turn a parser into a trait object --- src/types/mod.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/types/mod.rs b/src/types/mod.rs index 85841e95..61ceacd4 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -612,6 +612,72 @@ pub trait Parser { // self.bind(|t| p.map(|_| t)) SkipParser{ p: self, q: p } } + + /// 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 parsers::{any, token}; + /// use types::Parser; + /// + /// 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] + 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; + + #[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. From d58bf4c35262205ca63c54050e3100dd174d14a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 1 Sep 2016 00:00:40 +0200 Subject: [PATCH 27/55] Combinators: many_till, converted tests and added a few more --- src/combinators/bounded.rs | 532 ++++++++++++++++++++++--------------- src/combinators/macros.rs | 4 + src/combinators/mod.rs | 66 ++--- src/lib.rs | 7 +- 4 files changed, 362 insertions(+), 247 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 360c883a..09be29ed 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -409,51 +409,64 @@ impl BoundedSkipMany for RangeFrom } } -/* -impl BoundedRange for RangeFrom { - #[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, +many_till_iter! { + doc: "Parser iterating over a `RangeFrom` and ending with a final parser, created by `many_till(n.., ...)`", + struct_name: ManyTillRangeFromParser, + state: usize, - size_hint(self) { - (self.data, None) - } + 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); - } - } - on { - self.data = self.data.saturating_sub(1); - } + next(self) { + pre { + if self.data == 0 { + // We have reached minimum, we can attempt to end now + iter_till_end_test!(self); } + } + on { + // TODO: Replace with saturating sub + self.data = if self.data == 0 { 0 } else { self.data - 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!() - } + => 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 BoundedManyTill for RangeFrom + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillRangeFromParser; + + #[inline] + 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, + _p: PhantomData, + _q: PhantomData, + _t: PhantomData, } } } -*/ many_iter!{ doc: "Parser iterating over a `RangeFull`, created using `many(.., p)`.", @@ -541,42 +554,55 @@ impl BoundedSkipMany for RangeFull } } -/* -impl BoundedRange for RangeFull { - #[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) - } +many_till_iter! { + doc: "Parser iterating over a `RangeFull` and ending with a final parser, created by `many_till(.., ...)`", + struct_name: ManyTillRangeFullParser, + state: (), - next(self) { - pre { - // Can end at any time - iter_till_end_test!(self); - } - on {} - } + size_hint(self) { + (0, None) + } - => 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!() - } + next(self) { + pre { + // Can end at any time + iter_till_end_test!(self); } + on {} + } + + => 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 BoundedManyTill for RangeFull + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillRangeFullParser; + + #[inline] + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + ManyTillRangeFullParser { + p_ctor: f, + q_ctor: g, + data: (), + _i: PhantomData, + _p: PhantomData, + _q: PhantomData, + _t: PhantomData, + } + } +} + many_iter!{ doc: "Parser iterating over a `RangeTo`, created using `many(..n, p)`.", struct_name: ManyRangeToParser, @@ -687,66 +713,79 @@ impl BoundedSkipMany for RangeTo } } -/* -impl BoundedRange for RangeTo { - #[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, +many_till_iter! { + doc: "Parser iterating over a `RangeTo` and ending with a final parser, created by `many_till(..m, ...)`", + struct_name: ManyTillRangeToParser, + state: usize, - size_hint(self) { - (0, Some(self.data)) - } + 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)(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)), - } - } - on { - self.data -= 1; - } - } + 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)().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)); - => 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!(), + 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; + } + } + + => 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 BoundedManyTill for RangeTo + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillRangeToParser; + + #[inline] + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + ManyTillRangeToParser { + p_ctor: f, + q_ctor: g, + // [0, self.end) + // TODO: saturating sub + data: max(self.end, 1) - 1, + _i: PhantomData, + _p: PhantomData, + _q: PhantomData, + _t: PhantomData, + } } } -*/ many_iter!{ doc: "Parser iterating over a `usize`, created using `many(n, p)`.", @@ -854,64 +893,79 @@ impl BoundedSkipMany for usize } } -/* -impl BoundedRange for usize { - #[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)) - } +many_till_iter! { + doc: "Parser iterating `usize` times and ending with a final parser, created by `many_till(n, ...)`", + struct_name: ManyTillUsizeParser, + state: usize, - 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)); - }, - } + size_hint(self) { + (self.data, Some(self.data)) + } - return None; - } - } - on { - self.data -= 1; + 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)().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); + }, } - } - => 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!() + return None; } } + on { + self.data -= 1; + } + } + + => 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)), + (_, n, EndStateTill::Incomplete) => panic!("This is unreachable, incomplete, n: {:?}", n), + // We cannot reach this since we only run the end test once we have reached the + // minimum number of matches + (_, _, EndStateTill::EndSuccess) => unreachable!() } } -*/ + +impl BoundedManyTill for usize + where I: Input, + F: FnMut() -> P, + G: FnMut() -> Q, + P: Parser, + Q: Parser, + T: FromIterator { + /// The parser type returned by `many_till`. + type ManyTillParser = ManyTillUsizeParser; + + #[inline] + fn many_till(self, f: F, g: G) -> Self::ManyTillParser { + ManyTillUsizeParser { + p_ctor: f, + q_ctor: g, + data: self, + _i: PhantomData, + _p: PhantomData, + _q: 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`. /// @@ -1025,6 +1079,7 @@ pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser // Due to the requirement of BoundedMany 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 +// TODO: Implement as a trait for `ParserConstructor`? pub struct SepByInnerParserCtor { item: bool, f: F, @@ -1182,6 +1237,11 @@ mod test { 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']))); @@ -1230,52 +1290,49 @@ mod test { let r: (_, Result, _>) = many(2, || string(b"ab")).parse(&b"ababa"[..]) ; assert_eq!(r, (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); } - // FIXME - /* #[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() { @@ -1304,6 +1361,39 @@ mod test { 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: (_, 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] @@ -1320,8 +1410,15 @@ mod test { #[test] fn skip_range_to() { 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(()))); @@ -1335,6 +1432,10 @@ mod test { #[test] fn skip_range_from() { + 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(()))); @@ -1351,6 +1452,11 @@ mod test { 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(()))); @@ -1366,6 +1472,10 @@ mod test { #[test] fn skip_exact() { + 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(()))); @@ -1389,13 +1499,9 @@ mod test { assert_eq!(skip_many(2..1, || token(b'a')).parse(&b"aaaab"[..]), (&b"ab"[..], Ok(()))); } - // FIXME - /* #[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 767431bf..e78e1927 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -288,6 +288,10 @@ macro_rules! many_till_iter { /// 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) diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index c8a481c6..c59ab46f 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -155,6 +155,7 @@ pub fn sep_by(p: R, sep: F) -> impl Parser(p: R, sep: F) -> impl Parser where I: Input, @@ -167,8 +168,6 @@ pub fn sep_by1(p: R, sep: F) -> impl Parser(p: R, sep: F) -> impl Parser(p: R, end: F) -> impl Parser - where T: FromIterator, +pub fn many_till(p: F, end: G) -> impl Parser + where I: Input, //E: From, - R: Parser, - F: Parser { - bounded::many_till_unbounded(p, end) + 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. @@ -207,9 +210,11 @@ pub fn many_till(p: R, end: F) -> impl Parser(f: F) -> impl Parser - where F: Parser { - bounded::skip_many_unbounded(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. @@ -231,11 +236,12 @@ pub fn skip_many(f: F) -> impl Parser /// assert_eq!(parse_only(&p, b"bc"), Err((&b"bc"[..], Error::expected(b'a')))); /// ``` #[inline] -pub fn skip_many1(f: F) -> impl Parser - where F: Parser { - bounded::skip_many_from(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. /// @@ -342,34 +348,34 @@ mod test { let r: (_, Result, _>) = count(3, || token(b'a')).parse(&b"aaaa"[..]); assert_eq!(r, (&b"a"[..], Ok(vec![b'a', b'a', b'a']))); } -// FIXME: Update -/* #[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() { diff --git a/src/lib.rs b/src/lib.rs index 3ef35626..a8c7024a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -268,10 +268,9 @@ pub mod prelude { many1, sep_by, sep_by1, - // FIXME - //many_till, - //skip_many, - //skip_many1, + many_till, + skip_many, + skip_many1, matched_by, }; pub use types::{ From ee8122b15c0b26ee2bfcf6be8b27b5f05ace4eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 1 Sep 2016 00:42:26 +0200 Subject: [PATCH 28/55] combinators::bounded: Fixed bugs related to Range where start == end --- src/combinators/bounded.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 09be29ed..133eafaa 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -112,8 +112,8 @@ many_iter!{ } } on { - // TODO: Saturating sub? - self.data.0 = if self.data.0 == 0 { 0 } else { self.data.0 - 1 }; + 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; } } @@ -146,8 +146,8 @@ impl BoundedMany for Range ManyRangeParser { parser_ctor: f, - // Range is closed on left side, open on right, ie. [start, end) - data: (self.start, max(self.end, 1) - 1), + // 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, _p: PhantomData, @@ -217,7 +217,7 @@ impl BoundedSkipMany for Range SkipManyRangeParser { f: f, min: self.start, - max: max(self.end, 1) - 1, + max: max(self.start, self.end.saturating_sub(1)), _i: PhantomData, } } @@ -261,7 +261,8 @@ many_till_iter! { } } on { - self.data.0 = if self.data.0 == 0 { 0 } else { self.data.0 - 1 }; + 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; } } @@ -296,8 +297,8 @@ impl BoundedManyTill for Range BoundedMany for RangeTo ManyRangeToParser { parser_ctor: f, // Exclusive range [0, end) - data: max(self.end, 1) - 1, + data: self.end.saturating_sub(1), _i: PhantomData, _t: PhantomData, _p: PhantomData, @@ -707,7 +707,7 @@ impl BoundedSkipMany for RangeTo // Open on right side SkipManyRangeToParser { f: f, - max: max(self.end, 1) - 1, + max: self.end.saturating_sub(1), _i: PhantomData, } } @@ -777,8 +777,7 @@ impl BoundedManyTill for RangeTo< p_ctor: f, q_ctor: g, // [0, self.end) - // TODO: saturating sub - data: max(self.end, 1) - 1, + data: self.end.saturating_sub(1), _i: PhantomData, _p: PhantomData, _q: PhantomData, From 39f42f6819b8ed1c8832a260883e61a31df03400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 1 Sep 2016 02:41:35 +0200 Subject: [PATCH 29/55] types::Parser: Fixed inference issues with basic combinators in case I is not yet bound --- src/combinators/bounded.rs | 2 +- src/types/mod.rs | 83 +++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 133eafaa..d31f4e25 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -1092,7 +1092,7 @@ impl FnOnce<()> for SepByInnerParserCtor S: FnMut() -> Q, P: Parser, Q: Parser { - type Output = ThenParser, P>; + type Output = ThenParser, P>; extern "rust-call" fn call_once(self, _: ()) -> Self::Output { unimplemented!() diff --git a/src/types/mod.rs b/src/types/mod.rs index 61ceacd4..9a58fec1 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -458,7 +458,9 @@ pub trait Parser { /// ``` #[inline(always)] // TODO: Add From::from - // TODO: Is it possible to remove I and R here? + // 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, @@ -494,11 +496,11 @@ pub trait Parser { /// ``` #[inline(always)] // TODO: Add From::from - // TODO: Tests - fn then

(self, p: P) -> ThenParser + // 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 } + ThenParser { p: self, q: p, _i: PhantomData } } /// Applies the function `f` on the contained data if the parser is in a success state. @@ -513,11 +515,11 @@ pub trait Parser { /// assert_eq!(r, Ok(b'm')); /// ``` // TODO: Tests - #[inline] - fn map(self, f: F) -> MapParser + #[inline(always)] + fn map(self, f: F) -> MapParser where F: FnOnce(Self::Output) -> R, Self: Sized { - MapParser { p: self, f: f } + MapParser { p: self, f: f, _i: PhantomData } } /// Applies the function `f` on the contained error if the parser is in an error state. @@ -534,11 +536,12 @@ pub trait Parser { /// assert_eq!(r, Err((&b"foo"[..], "this is an error".to_owned()))); /// ``` // TODO: Tests - #[inline] - fn map_err(self, f: F) -> MapErrParser + // 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 } + 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 @@ -556,11 +559,11 @@ pub trait Parser { /// assert_eq!(r, Ok(&b"test"[..])); /// ``` // TODO: Tests - #[inline] - fn inspect(self, f: F) -> InspectParser + #[inline(always)] + fn inspect(self, f: F) -> InspectParser where F: FnOnce(&Self::Output), Self: Sized { - InspectParser { p: self, f: f } + InspectParser { p: self, f: f, _i: PhantomData } } /// Tries to match the parser `f`, if `f` fails it tries `g`. Returns the success value of @@ -585,11 +588,11 @@ pub trait Parser { // TODO: Write the laws for MonadPlus, or should satisfy MonadPlus laws (stronger guarantees // compared to Alternative typeclass laws) // TODO: Tests - #[inline] - fn or

(self, p: P) -> OrParser + #[inline(always)] + fn or

(self, p: P) -> OrParser where P: Parser, Self: Sized { - OrParser { p: self, q: p } + OrParser { p: self, q: p, _i: PhantomData } } /// Creates a new parser which matches `Self` and if successful tries to match `P`, if `P` is @@ -602,15 +605,15 @@ pub trait Parser { /// ``` // TODO: Get more of the Applicative instance in here, make tests // TODO: Docs - // TODO: Tests - #[inline] - fn skip

(self, p: P) -> SkipParser + // 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 } + SkipParser{ p: self, q: p, _i: PhantomData } } /// Turns the parser into a trait object, using the `BoxedParser` type to provide inference and @@ -633,7 +636,7 @@ pub trait Parser { /// /// assert_eq!(p.parse(&b"bcd"), (&b"bcd", Err(Error::expected(b'a')))); /// ``` - #[inline] + #[inline(always)] fn boxed(self) -> BoxedParser where Self: Sized + 'static { Box::new(self) @@ -838,12 +841,13 @@ impl Parser for BindParser /// Parser for the `Parser::then` chaining operator, allowing to chain parsers. /// /// This is created by the `Parser::then` method. -pub struct ThenParser { +pub struct ThenParser { p: P, q: Q, + _i: PhantomData, } -impl Parser for ThenParser +impl Parser for ThenParser where I: Input, P: Parser, Q: Parser { @@ -862,12 +866,13 @@ impl Parser for ThenParser /// Parser for the `Parser::map` combinator. /// /// This is created by the `Parser::map` method. -pub struct MapParser { +pub struct MapParser { p: P, f: F, + _i: PhantomData, } -impl Parser for MapParser +impl Parser for MapParser where I: Input, P: Parser, F: FnOnce(P::Output) -> R { @@ -886,12 +891,13 @@ impl Parser for MapParser /// Parser for the `Parser::map_err` combinator. /// /// This is created by the `Parser::map_err` method. -pub struct MapErrParser { +pub struct MapErrParser { p: P, f: F, + _i: PhantomData } -impl Parser for MapErrParser +impl Parser for MapErrParser where I: Input, P: Parser, F: FnOnce(P::Error) -> E { @@ -910,12 +916,13 @@ impl Parser for MapErrParser /// Parser for the `Parser::inspect` combinator. /// /// This is created by `Parser::inspect`. -pub struct InspectParser { +pub struct InspectParser { p: P, f: F, + _i: PhantomData, } -impl Parser for InspectParser +impl Parser for InspectParser where I: Input, P: Parser, F: FnOnce(&P::Output) { @@ -938,12 +945,13 @@ impl Parser for InspectParser /// Parser for the `Parser::or` combinator. /// /// This is created by `Parser::or`. -pub struct OrParser { - p: P, - q: Q, +pub struct OrParser { + p: P, + q: Q, + _i: PhantomData, } -impl Parser for OrParser +impl Parser for OrParser where I: Input, P: Parser, Q: Parser { @@ -963,12 +971,13 @@ impl Parser for OrParser /// Parser for the `Parser::skip` combinator. /// /// This is created by `Parser::skip`. -pub struct SkipParser { - p: P, - q: Q, +pub struct SkipParser { + p: P, + q: Q, + _i: PhantomData, } -impl Parser for SkipParser +impl Parser for SkipParser where I: Input, P: Parser, Q: Parser { From ad20f9975e1c1896986bd9b5db83e2f3f8d1c1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 1 Sep 2016 02:45:07 +0200 Subject: [PATCH 30/55] Fixed some doctests --- src/ascii.rs | 13 ++++--- src/buffer/mod.rs | 2 +- src/lib.rs | 15 ++++---- src/parse.rs | 21 +++++------ src/parsers.rs | 38 ++++++++++---------- src/types/mod.rs | 88 +++++++++++++++++++++++++---------------------- 6 files changed, 89 insertions(+), 88 deletions(-) diff --git a/src/ascii.rs b/src/ascii.rs index 8a583ef4..501f642a 100644 --- a/src/ascii.rs +++ b/src/ascii.rs @@ -9,7 +9,7 @@ use conv::{ use conv::errors::UnwrapOk; use combinators::option; -use parsers::{Error, satisfy, take_while, take_while1}; +use parsers::{Error, satisfy, skip_while, take_while1}; use types::{Buffer, Input, Parser}; /// Lowercase ASCII predicate. @@ -79,12 +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>() -> impl Parser> { - // TODO: More efficient implementation, requires a skip_while parser using Input primitives - take_while(is_whitespace).map(|_| ()) + skip_while(is_whitespace).map(|_| ()) } /// Parses a single digit. @@ -99,7 +98,7 @@ pub fn skip_whitespace>() -> impl Parser>() -> impl Parser> { @@ -119,7 +118,7 @@ pub fn digit>() -> impl Parser> /// 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)); /// ``` @@ -145,7 +144,7 @@ pub fn signed, T, F>(f: F) -> impl Parser, b"123"); +/// let r = parse_only(decimal::<_, u8>(), b"123"); /// /// assert_eq!(r, Ok(123u8)); /// ``` diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index 58ffc2bb..76809599 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -16,7 +16,7 @@ //! //! 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); diff --git a/src/lib.rs b/src/lib.rs index a8c7024a..9f76fafc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ //! # Example //! //! ``` +//! #![feature(conservative_impl_trait)] //! # #[macro_use] extern crate chomp; //! # fn main() { //! use chomp::prelude::*; @@ -24,20 +25,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 +94,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')); //! # } //! ``` diff --git a/src/parse.rs b/src/parse.rs index 53ffcb7e..9e7989a2 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -6,10 +6,10 @@ use types::{Input, Parser}; /// 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()))); /// ``` /// @@ -17,21 +17,16 @@ use types::{Input, Parser}; /// 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, Input, Error, SimpleResult, parse_only, string, eof}; -/// -/// fn my_parser(i: I) -> SimpleResult { -/// parse!{i; -/// let r = string(b"pattern"); -/// eof(); +/// use chomp::prelude::{U8Input, 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()))); /// # } /// ``` diff --git a/src/parsers.rs b/src/parsers.rs index 1d4398bd..4623a4fa 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -22,7 +22,7 @@ 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() -> impl Parser> { @@ -40,7 +40,7 @@ pub fn any() -> impl Parser> /// ``` /// 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(f: F) -> impl Parser> @@ -60,7 +60,7 @@ pub fn satisfy(f: F) -> impl Parser(f: F, p: P) -> impl Parser(t: I::Token) -> impl Parser> { @@ -107,7 +107,7 @@ pub fn token(t: I::Token) -> impl Parser(t: I::Token) -> impl Parser> { @@ -125,9 +125,9 @@ pub fn not_token(t: I::Token) -> impl Parser() -> impl Parser, Error=Error> { @@ -145,7 +145,7 @@ pub fn peek() -> impl Parser, Error=Error() -> impl Parser> { @@ -162,7 +162,7 @@ pub fn peek_next() -> impl Parser(num: usize) -> impl Parser> { @@ -180,7 +180,7 @@ pub fn take(num: usize) -> impl Parser(num: usize) -> impl Parser(f: F) -> impl Parser(f: F) -> impl Parser(mut f: F) -> impl Parser None, /// (_, b'*') => Some(true), /// (_, _) => Some(false), @@ -316,7 +316,7 @@ pub fn scan(s: S, mut f: F) -> impl Parser None, /// (_, c) => Some(c), /// }); @@ -347,7 +347,7 @@ pub fn run_scanner(s: S, mut f: F) -> impl Parser() -> impl Parser> { @@ -366,7 +366,7 @@ pub fn take_remainder() -> impl Parser(s: &'static [I::Token]) -> impl Parser { /// # 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())); @@ -446,13 +446,15 @@ pub trait Parser { /// 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)); /// ``` @@ -482,14 +484,16 @@ pub trait Parser { /// # Example /// /// ``` - /// use chomp::prelude::{Input, SimpleResult, parse_only}; + /// #![feature(conservative_impl_trait)] /// - /// fn g(i: I) -> SimpleResult { - /// i.ret("testing!") + /// use chomp::prelude::{Input, Parser, parse_only, ret}; + /// + /// 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!")); @@ -508,11 +512,13 @@ pub trait Parser { /// # 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)); /// ``` // TODO: Tests #[inline(always)] @@ -527,11 +533,10 @@ pub trait Parser { /// # 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()))); /// ``` @@ -550,9 +555,9 @@ pub trait Parser { /// # 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"); /// @@ -575,15 +580,13 @@ pub trait Parser { /// and its alternation operator (`<|>`). /// /// ``` - /// use chomp::prelude::{Error, parse_only, or, token}; + /// use chomp::prelude::{Error, Parser, parse_only, token}; /// - /// let p = |i| or(i, - /// |i| token(i, b'a'), - /// |i| token(i, b'b')); + /// 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')))); + /// 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) @@ -623,8 +626,7 @@ pub trait Parser { /// depending on a condition. /// /// ``` - /// use parsers::{any, token}; - /// use types::Parser; + /// use chomp::prelude::{Parser, Error, any, token}; /// /// let a = 3; /// @@ -634,7 +636,7 @@ pub trait Parser { /// token(b'a').boxed() /// }; /// - /// assert_eq!(p.parse(&b"bcd"), (&b"bcd", Err(Error::expected(b'a')))); + /// assert_eq!(p.parse(&b"bcd"[..]), (&b"bcd"[..], Err(Error::expected(b'a')))); /// ``` #[inline(always)] fn boxed(self) -> BoxedParser @@ -666,6 +668,7 @@ impl BoxParser for P 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) @@ -690,9 +693,10 @@ impl Parser for Box> /// # Example /// /// ``` -/// use chomp::types::{Input, parse_only, ret}; +/// use chomp::types::ret; +/// use chomp::parse_only; /// -/// let r = parse_only(|i| +/// let r = parse_only( /// // Annotate the error type /// ret::<_, ()>("Wohoo, success!"), /// b"some input"); @@ -711,11 +715,12 @@ pub fn ret(t: T) -> RetParser { /// # Example /// /// ``` -/// use chomp::prelude::{Input, parse_only}; +/// use chomp::types::err; +/// use chomp::parse_only; /// -/// let r = parse_only(|i| +/// let r = parse_only( /// // Annotate the value type -/// i.err::<(), _>("Something went wrong"), +/// err::<(), _>("Something went wrong"), /// b"some input"); /// /// assert_eq!(r, Err((&b"some input"[..], "Something went wrong"))); @@ -735,13 +740,14 @@ pub fn err(e: E) -> ErrParser { /// # Examples /// /// ``` -/// use chomp::prelude::{Input, parse_only}; +/// use chomp::types::from_result; +/// use chomp::parse_only; /// -/// let r = parse_only(|i| i.from_result::<_, ()>(Ok("foo")), b"test"); +/// let r = parse_only(from_result::<_, ()>(Ok("foo")), b"test"); /// /// assert_eq!(r, Ok("foo")); /// -/// let r = parse_only(|i| i.from_result::<(), _>(Err("error message")), b"test"); +/// let r = parse_only(from_result::<(), _>(Err("error message")), b"test"); /// /// assert_eq!(r, Err((&b"test"[..], "error message"))); /// ``` From 5c2ef9dc2aea76d02c0949a3b0b34b8e2fd0ba7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 1 Sep 2016 14:44:43 +0200 Subject: [PATCH 31/55] types::numbering: Fixed test and added monad compatible way to obtaining position --- src/types/numbering.rs | 87 ++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/src/types/numbering.rs b/src/types/numbering.rs index 8cc34687..52f35bb7 100644 --- a/src/types/numbering.rs +++ b/src/types/numbering.rs @@ -1,46 +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, Numbering, 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 types::{Buffer, Input}; +use types::{Buffer, Input, Parser}; /// Trait for managing some kind of numbering over the parsed data. pub trait Numbering: Clone { @@ -103,6 +95,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> { @@ -192,13 +194,10 @@ impl> Input for InputPosition { } } -// FIXME -/* #[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() { @@ -207,27 +206,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))])); } } -*/ From 7b61e189c1cfc77a42233cc5c0d9b3753d27d203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 1 Sep 2016 17:47:36 +0200 Subject: [PATCH 32/55] Updated doctests --- src/buffer/mod.rs | 2 +- src/buffer/slice.rs | 8 +++-- src/combinators/bounded.rs | 16 +++++----- src/combinators/mod.rs | 65 ++++++++++++++++++-------------------- src/lib.rs | 14 ++++---- 5 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index 76809599..f97a0e42 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -9,7 +9,7 @@ //! //! 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(); diff --git a/src/buffer/slice.rs b/src/buffer/slice.rs index 1929f29f..0e0b3c6e 100644 --- a/src/buffer/slice.rs +++ b/src/buffer/slice.rs @@ -8,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) /// }); @@ -23,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]])); /// # } diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index d31f4e25..2955077f 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -11,7 +11,7 @@ //! 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'])); //! ``` @@ -837,13 +837,13 @@ impl BoundedMany for usize } /// Parser iterating `n` times discarding results, created using `skip_many(n, f)`. -pub struct SkipManyUsizeParser { +pub struct SkipManyExactParser { f: F, n: usize, _i: PhantomData } -impl Parser for SkipManyUsizeParser +impl Parser for SkipManyExactParser where I: Input, F: FnMut() -> P, P: Parser { @@ -880,11 +880,11 @@ impl BoundedSkipMany for usize where I: Input, F: FnMut() -> P, P: Parser { - type SkipManyParser = SkipManyUsizeParser; + type SkipManyParser = SkipManyExactParser; #[inline] fn skip_many(self, f: F) -> Self::SkipManyParser { - SkipManyUsizeParser { + SkipManyExactParser { f: f, n: self, _i: PhantomData, @@ -894,7 +894,7 @@ impl BoundedSkipMany for usize many_till_iter! { doc: "Parser iterating `usize` times and ending with a final parser, created by `many_till(n, ...)`", - struct_name: ManyTillUsizeParser, + struct_name: ManyTillExactParser, state: usize, size_hint(self) { @@ -949,11 +949,11 @@ impl BoundedManyTill for usize Q: Parser, T: FromIterator { /// The parser type returned by `many_till`. - type ManyTillParser = ManyTillUsizeParser; + type ManyTillParser = ManyTillExactParser; #[inline] fn many_till(self, f: F, g: G) -> Self::ManyTillParser { - ManyTillUsizeParser { + ManyTillExactParser { p_ctor: f, q_ctor: g, data: self, diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index c59ab46f..d6b9b11a 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -14,14 +14,12 @@ use types::{Input, Parser}; /// ``` /// 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']))); /// ``` @@ -39,14 +37,15 @@ pub fn count(num: usize, p: F) -> impl Parser(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')); +/// assert_eq!(parse_only(f(), b"abc"), Ok(b'a')); +/// assert_eq!(parse_only(f(), b"bbc"), Ok(b'd')); /// ``` #[inline] pub fn option(p: P, default: P::Output) -> impl Parser @@ -67,12 +66,10 @@ pub fn option(p: P, default: P::Output) -> impl Parser, _> = 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"[..]])); @@ -94,14 +91,12 @@ pub fn many(f: F) -> impl Parser /// 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(f: F) -> impl Parser @@ -123,7 +118,7 @@ pub fn many1(f: F) -> impl Parser, _> = 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])); /// ``` @@ -151,7 +146,7 @@ pub fn sep_by(p: R, sep: F) -> impl Parser, _> = 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])); /// ``` @@ -178,7 +173,7 @@ pub fn sep_by1(p: R, sep: F) -> impl Parser, _> = 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'])); /// ``` @@ -203,9 +198,9 @@ pub fn many_till(p: F, end: G) -> impl Parser(f: F) -> impl Parser /// `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(f: F) -> impl Parser @@ -249,7 +244,7 @@ pub fn skip_many1(f: F) -> impl Parser /// 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(f: F) -> impl Parser @@ -271,10 +266,10 @@ pub fn matched_by(f: F) -> impl Parser(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))); //! # } //! ``` From edbb26e588956d4f395f78e0166875501297e410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 1 Sep 2016 18:19:33 +0200 Subject: [PATCH 33/55] macro: Updated doctests --- src/macros.rs | 135 +++++++++++++++++++------------------------------- 1 file changed, 50 insertions(+), 85 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index cc42ff03..a73639ba 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, Input, SimpleResult, parse_only, string, token}; +/// use chomp::prelude::{U8Input, Input, 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, Input, token, SimpleResult}; -/// # fn my_parser(i: I) -> SimpleResult { -/// parse!{i; +/// # use chomp::prelude::{parse_only, U8Input, Input, 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, Parser, 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 From 54d8b37d0ae16f7107e56e3f0bc72b4a74675713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 1 Sep 2016 18:52:02 +0200 Subject: [PATCH 34/55] combinators::bounded: Replaced panic! with unreachable! --- src/combinators/bounded.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 2955077f..c37350f6 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -934,10 +934,10 @@ many_till_iter! { (s, 0, EndStateTill::EndSuccess) => (s, Ok(result)), // Did not reach minimum or a failure, propagate (s, _, EndStateTill::Error(e)) => (s, Err(e)), - (_, n, EndStateTill::Incomplete) => panic!("This is unreachable, incomplete, n: {:?}", n), + (_, n, 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!() + (_, _, EndStateTill::EndSuccess) => unreachable!(), } } From e00af1b040ecdb05c081a57c2786d9ca9d10e913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sun, 4 Sep 2016 00:07:51 +0200 Subject: [PATCH 35/55] combinators::either: Adapter to monad --- src/combinators/mod.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index 4cb6aaff..477f018a 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -70,22 +70,27 @@ pub fn option(p: P, default: P::Output) -> impl Parser(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(); + L: Parser, + R: Parser { + move |i: I| { + 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), + 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)) + } + } } } From 666d952f2072d032e74eb10cd27a86883b753f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sun, 4 Sep 2016 00:08:07 +0200 Subject: [PATCH 36/55] combinators::bounded: Removed unused variable --- src/combinators/bounded.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index c37350f6..590ef341 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -934,7 +934,7 @@ many_till_iter! { (s, 0, EndStateTill::EndSuccess) => (s, Ok(result)), // Did not reach minimum or a failure, propagate (s, _, EndStateTill::Error(e)) => (s, Err(e)), - (_, n, EndStateTill::Incomplete) => unreachable!(), + (_, _, 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!(), From ae0ca8d2d0f7239810f9709ee45ff471e3ede0c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sun, 4 Sep 2016 23:44:29 +0200 Subject: [PATCH 37/55] Added missing Debug implementations --- src/combinators/bounded.rs | 6 ++++++ src/lib.rs | 2 ++ src/types/mod.rs | 10 ++++++++++ src/types/numbering.rs | 8 +------- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 590ef341..2876fb59 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -156,6 +156,7 @@ impl BoundedMany for Range } /// Parser iterating over a `Range` discarding results, created using `skip_many(n..m, f)`. +#[derive(Debug)] pub struct SkipManyRangeParser { f: F, max: usize, @@ -354,6 +355,7 @@ impl BoundedMany for RangeFrom } /// Parser iterating over a `RangeFrom` discarding results, created using `skip_many(n.., f)`. +#[derive(Debug)] pub struct SkipManyRangeFromParser { f: F, min: usize, @@ -508,6 +510,7 @@ impl BoundedMany for RangeFull } /// Parser iterating over a `RangeFull` discarding results, created using `skip_many(.., f)`. +#[derive(Debug)] pub struct SkipManyRangeFullParser { f: F, _i: PhantomData @@ -655,6 +658,7 @@ impl BoundedMany for RangeTo } /// Parser iterating over a `RangeTo` discarding results, created using `skip_many(..n, f)`. +#[derive(Debug)] pub struct SkipManyRangeToParser { f: F, max: usize, @@ -837,6 +841,7 @@ impl BoundedMany for usize } /// Parser iterating `n` times discarding results, created using `skip_many(n, f)`. +#[derive(Debug)] pub struct SkipManyExactParser { f: F, n: usize, @@ -1079,6 +1084,7 @@ pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser // parameter we need to have a type we can describe and not a closure for the type of the sep-by // inner parser // TODO: Implement as a trait for `ParserConstructor`? +#[derive(Debug)] pub struct SepByInnerParserCtor { item: bool, f: F, diff --git a/src/lib.rs b/src/lib.rs index 3d2087c1..d5588f9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -203,6 +203,8 @@ #![feature(conservative_impl_trait, unboxed_closures, fn_traits)] #![warn(missing_docs, + missing_debug_implementations, + missing_copy_implementations, trivial_casts, unused_import_braces, unused_qualifications)] diff --git a/src/types/mod.rs b/src/types/mod.rs index 9522a63d..2fce0ba7 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -759,6 +759,7 @@ pub fn from_result(r: Result) -> FromResultParser { /// Parser containing a success value. /// /// This is created by `ret`. +#[derive(Debug)] pub struct RetParser { t: T, _e: PhantomData, @@ -778,6 +779,7 @@ impl Parser for RetParser /// Parser containing an error value. /// /// This is created by `err`. +#[derive(Debug)] pub struct ErrParser { e: E, _t: PhantomData, @@ -797,6 +799,7 @@ impl Parser for ErrParser /// Parser containing a `Result`. /// /// This is created by `from_result`. +#[derive(Debug)] pub struct FromResultParser { r: Result, } @@ -815,6 +818,7 @@ impl Parser for FromResultParser /// 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, @@ -847,6 +851,7 @@ impl Parser for BindParser /// 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, @@ -872,6 +877,7 @@ impl Parser for ThenParser /// Parser for the `Parser::map` combinator. /// /// This is created by the `Parser::map` method. +#[derive(Debug)] pub struct MapParser { p: P, f: F, @@ -897,6 +903,7 @@ impl Parser for MapParser /// Parser for the `Parser::map_err` combinator. /// /// This is created by the `Parser::map_err` method. +#[derive(Debug)] pub struct MapErrParser { p: P, f: F, @@ -922,6 +929,7 @@ impl Parser for MapErrParser /// Parser for the `Parser::inspect` combinator. /// /// This is created by `Parser::inspect`. +#[derive(Debug)] pub struct InspectParser { p: P, f: F, @@ -951,6 +959,7 @@ impl Parser for InspectParser /// Parser for the `Parser::or` combinator. /// /// This is created by `Parser::or`. +#[derive(Debug)] pub struct OrParser { p: P, q: Q, @@ -977,6 +986,7 @@ impl Parser for OrParser /// Parser for the `Parser::skip` combinator. /// /// This is created by `Parser::skip`. +#[derive(Debug)] pub struct SkipParser { p: P, q: Q, diff --git a/src/types/numbering.rs b/src/types/numbering.rs index 52f35bb7..80b64cce 100644 --- a/src/types/numbering.rs +++ b/src/types/numbering.rs @@ -49,18 +49,12 @@ pub trait Numbering: Clone { } /// Struct counting the number of newlines (`b'\n'`). -#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] pub struct LineNumber( /// The current line, zero-indexed. pub u64, ); -impl Clone for LineNumber { - fn clone(&self) -> Self { - LineNumber(self.0) - } -} - impl LineNumber { /// Creates a new line-number counter with zero. pub fn new() -> Self { From 03ea29d1a8e8c8f6dbcaf2a19f0b525bfc125220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sun, 4 Sep 2016 23:57:01 +0200 Subject: [PATCH 38/55] combinators::bounded: Improved macros generating parsers and added Debug implementations --- src/combinators/bounded.rs | 557 +++++++++++++++++++------------------ src/combinators/macros.rs | 52 ++-- 2 files changed, 305 insertions(+), 304 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 2876fb59..4939be41 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -97,39 +97,39 @@ pub trait BoundedManyTill { } many_iter!{ - doc: "Parser iterating over a `Range`, created using `many(n..m, p)`.", - struct_name: ManyRangeParser, - state: (usize, usize), + #[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; + 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 forget to end before self.data.1 == 0 + self.data.1 -= 1; } } - 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!(), } } - - => 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 BoundedMany for Range @@ -225,59 +225,60 @@ impl BoundedSkipMany for Range } many_till_iter! { - doc: "Parser iterating over a range and ending with a final parser, created by `many_till(n..m, ...)`", - struct_name: ManyTillRangeParser, - state: (usize, usize), - - 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)().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)); + #[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), - return None; - }, - // Failed to end, restore and continue since we can parse more - (_, (b, Err(_))) => self.buf = Some(b.restore(m)), + 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)().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.0 = self.data.0.saturating_sub(1); + // Can't overflow unless we forget to end before self.data.1 == 0 + self.data.1 -= 1; + } } - 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!() } } - - => 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 BoundedManyTill for Range @@ -309,28 +310,28 @@ impl BoundedManyTill for Range (s.restore(m), Ok(result)), + // Items still remaining, propagate + (s, _, _, Some(e)) => (s, Err(e)), + (_, _, _, None) => unreachable!(), } - } - - => 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!(), } } @@ -413,36 +414,36 @@ impl BoundedSkipMany for RangeFrom } many_till_iter! { - doc: "Parser iterating over a `RangeFrom` and ending with a final parser, created by `many_till(n.., ...)`", - struct_name: ManyTillRangeFromParser, - state: usize, - - size_hint(self) { - (self.data, None) - } + #[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); + 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); + } + } + on { + self.data = self.data.saturating_sub(1); } } - 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!() } } - - => 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 BoundedManyTill for RangeFrom @@ -471,22 +472,22 @@ impl BoundedManyTill for RangeFro } many_iter!{ - doc: "Parser iterating over a `RangeFull`, created using `many(.., p)`.", - struct_name: ManyRangeFullParser, - state: (), - - size_hint(self) { - (0, None) - } + #[derive(Debug)] + #[doc="Parser iterating over a `RangeFull`, created using `many(.., p)`."] + pub struct ManyRangeFullParser { + state: (), - next(self) { - pre {} - on {} - } - - => result { - (s, (), m, Some(_)) => (s.restore(m), Ok(result)), - (_, _, _, None) => unreachable!(), + size_hint(self) { + (0, None) + } + next(self) { + pre {} + on {} + } + finally(result) { + (s, (), m, Some(_)) => (s.restore(m), Ok(result)), + (_, _, _, None) => unreachable!(), + } } } @@ -558,27 +559,27 @@ impl BoundedSkipMany for RangeFull } many_till_iter! { - doc: "Parser iterating over a `RangeFull` and ending with a final parser, created by `many_till(.., ...)`", - struct_name: ManyTillRangeFullParser, - state: (), - - size_hint(self) { - (0, None) - } + #[derive(Debug)] + #[doc="Parser iterating over a `RangeFull` and ending with a final parser, created by `many_till(.., ...)`"] + pub struct ManyTillRangeFullParser { + state: (), - next(self) { - pre { - // Can end at any time - iter_till_end_test!(self); + 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!() } - on {} - } - - => 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!() } } @@ -607,34 +608,34 @@ impl BoundedManyTill for RangeFul } many_iter!{ - doc: "Parser iterating over a `RangeTo`, created using `many(..n, p)`.", - struct_name: ManyRangeToParser, - // Exclusive range [0, end) - state: usize, - - size_hint(self) { - (0, Some(self.data)) - } - - next(self) { - pre { - if self.data == 0 { - return None; + #[derive(Debug)] + #[doc="Parser iterating over a `RangeTo`, created using `many(..n, p)`."] + pub struct ManyRangeToParser { + // Exclusive range [0, end) + state: usize, + + size_hint(self) { + (0, Some(self.data)) + } + next(self) { + pre { + if self.data == 0 { + return None; + } + } + on { + self.data -= 1; } } - 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!(), } } - - => 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 BoundedMany for RangeTo @@ -718,51 +719,51 @@ impl BoundedSkipMany for RangeTo } many_till_iter! { - doc: "Parser iterating over a `RangeTo` and ending with a final parser, created by `many_till(..m, ...)`", - struct_name: ManyTillRangeToParser, - state: usize, - - size_hint(self) { - (0, Some(self.data)) - } + #[derive(Debug)] + #[doc="Parser iterating over a `RangeTo` and ending with a final parser, created by `many_till(..m, ...)`"] + pub struct ManyTillRangeToParser { + state: usize, - 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(); + 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)().parse(i)) { - // We can always end - (_, (b, Ok(_))) => { - self.buf = Some(b); - self.state = EndStateTill::EndSuccess; + match (self.data, (self.end)().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 + }, + // 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 -= 1; } } - 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!(), } } - - => 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 BoundedManyTill for RangeTo @@ -791,33 +792,33 @@ impl BoundedManyTill for RangeTo< } many_iter!{ - doc: "Parser iterating over a `usize`, created using `many(n, p)`.", - struct_name: ManyExactParser, - // Excatly self - state: usize, - - size_hint(self) { - (self.data, Some(self.data)) - } - - next(self) { - pre { - if self.data == 0 { - return None; + #[derive(Debug)] + #[doc="Parser iterating over a `usize`, 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; + } + } + on { + self.data -= 1; } } - 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!(), } } - - => 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 BoundedMany for usize @@ -898,52 +899,52 @@ impl BoundedSkipMany for usize } many_till_iter! { - doc: "Parser iterating `usize` times and ending with a final parser, created by `many_till(n, ...)`", - struct_name: ManyTillExactParser, - state: usize, + #[derive(Debug)] + #[doc="Parser iterating `usize` times and ending with a final parser, created by `many_till(n, ...)`"] + pub struct ManyTillExactParser { + state: usize, - 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"); + 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)().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); + }, + } - match (self.end)().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); - }, + return None; } - - return None; + } + on { + self.data -= 1; } } - 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!(), } } - - => 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 BoundedManyTill for usize diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index e78e1927..9f6c48b5 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -1,20 +1,20 @@ macro_rules! many_iter { ( - doc: $doc:expr, - struct_name: $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 - } - - => $result:ident { - $($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),*$(,)* + } } ) => { - #[doc=$doc] + $(#[$attr])* pub struct $name where I: Input, F: FnMut() -> P, @@ -135,21 +135,21 @@ macro_rules! many_iter { /// iteration early. macro_rules! many_till_iter { ( - doc: $doc:expr, - struct_name: $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 - } - - => $result:ident { - $($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),*$(,)* + } } ) => { - #[doc=$doc] + $(#[$attr])* pub struct $name where I: Input, F: FnMut() -> P, From f68c26752feb6de895e361a15d19e6e22c035077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 5 Sep 2016 00:25:10 +0200 Subject: [PATCH 39/55] combinators::bounded: Removed Bounded-prefix from the bounded traits --- src/combinators/bounded.rs | 66 ++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 4939be41..5f2df349 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: @@ -25,7 +27,7 @@ use std::ops::{RangeFrom, RangeFull, RangeTo, Range}; use types::{Input, Parser, ThenParser}; /// Trait for applying a parser multiple times based on a range. -pub trait BoundedMany { +pub trait Many { /// The parser type returned by `many`. type ManyParser: Parser; @@ -50,7 +52,7 @@ pub trait BoundedMany { } /// Trait for applying a parser multiple times based on a range, ignoring any output. -pub trait BoundedSkipMany { +pub trait SkipMany { /// The parser type returned by `skip_many`. type SkipManyParser: Parser; @@ -74,7 +76,7 @@ pub trait BoundedSkipMany { } /// Trait for applying a parser multiple times based on a range until another parser succeeds. -pub trait BoundedManyTill { +pub trait ManyTill { /// The parser type returned by `many_till`. type ManyTillParser: Parser; @@ -132,7 +134,7 @@ many_iter!{ } } -impl BoundedMany for Range +impl Many for Range where I: Input, F: FnMut() -> P, T: FromIterator, @@ -203,7 +205,7 @@ impl Parser for SkipManyRangeParser } } -impl BoundedSkipMany for Range +impl SkipMany for Range where I: Input, F: FnMut() -> P, P: Parser { @@ -226,7 +228,7 @@ impl BoundedSkipMany for Range many_till_iter! { #[derive(Debug)] - #[doc="Parser iterating over a range and ending with a final parser, created by `many_till(n..m, ...)`"] + #[doc="Parser iterating over a `Range` and ending with a final parser, created by `many_till(n..m, ...)`"] pub struct ManyTillRangeParser { state: (usize, usize), @@ -281,7 +283,7 @@ many_till_iter! { } } -impl BoundedManyTill for Range +impl ManyTill for Range where I: Input, F: FnMut() -> P, G: FnMut() -> Q, @@ -335,7 +337,7 @@ many_iter!{ } } -impl BoundedMany for RangeFrom +impl Many for RangeFrom where I: Input, F: FnMut() -> P, T: FromIterator, @@ -396,7 +398,7 @@ impl Parser for SkipManyRangeFromParser } } -impl BoundedSkipMany for RangeFrom +impl SkipMany for RangeFrom where I: Input, F: FnMut() -> P, P: Parser { @@ -446,7 +448,7 @@ many_till_iter! { } } -impl BoundedManyTill for RangeFrom +impl ManyTill for RangeFrom where I: Input, F: FnMut() -> P, G: FnMut() -> Q, @@ -491,7 +493,7 @@ many_iter!{ } } -impl BoundedMany for RangeFull +impl Many for RangeFull where I: Input, F: FnMut() -> P, T: FromIterator, @@ -543,7 +545,7 @@ impl Parser for SkipManyRangeFullParser } } -impl BoundedSkipMany for RangeFull +impl SkipMany for RangeFull where I: Input, F: FnMut() -> P, P: Parser { @@ -583,7 +585,7 @@ many_till_iter! { } } -impl BoundedManyTill for RangeFull +impl ManyTill for RangeFull where I: Input, F: FnMut() -> P, G: FnMut() -> Q, @@ -638,7 +640,7 @@ many_iter!{ } } -impl BoundedMany for RangeTo +impl Many for RangeTo where I: Input, F: FnMut() -> P, T: FromIterator, @@ -701,7 +703,7 @@ impl Parser for SkipManyRangeToParser } } -impl BoundedSkipMany for RangeTo +impl SkipMany for RangeTo where I: Input, F: FnMut() -> P, P: Parser { @@ -766,7 +768,7 @@ many_till_iter! { } } -impl BoundedManyTill for RangeTo +impl ManyTill for RangeTo where I: Input, F: FnMut() -> P, G: FnMut() -> Q, @@ -793,7 +795,7 @@ impl BoundedManyTill for RangeTo< many_iter!{ #[derive(Debug)] - #[doc="Parser iterating over a `usize`, created using `many(n, p)`."] + #[doc="Parser iterating `usize` times, created using `many(n, p)`."] pub struct ManyExactParser { // Excatly self state: usize, @@ -821,7 +823,7 @@ many_iter!{ } } -impl BoundedMany for usize +impl Many for usize where I: Input, F: FnMut() -> P, T: FromIterator, @@ -841,7 +843,7 @@ impl BoundedMany for usize } } -/// Parser iterating `n` times discarding results, created using `skip_many(n, f)`. +/// Parser iterating `usize` times discarding results, created using `skip_many(n, f)`. #[derive(Debug)] pub struct SkipManyExactParser { f: F, @@ -882,7 +884,7 @@ impl Parser for SkipManyExactParser } } -impl BoundedSkipMany for usize +impl SkipMany for usize where I: Input, F: FnMut() -> P, P: Parser { @@ -947,7 +949,7 @@ many_till_iter! { } } -impl BoundedManyTill for usize +impl ManyTill for usize where I: Input, F: FnMut() -> P, G: FnMut() -> Q, @@ -992,8 +994,8 @@ pub fn many(r: R, f: F) -> R::ManyParser F: FnMut() -> P, P: Parser, T: FromIterator, - R: BoundedMany { - BoundedMany::many(r, f) + R: Many { + Many::many(r, f) } /// Applies the parser `F` multiple times until it fails or the maximum value of the range has @@ -1015,8 +1017,8 @@ pub fn skip_many(r: R, f: F) -> R::SkipManyParser where I: Input, F: FnMut() -> P, P: Parser, - R: BoundedSkipMany { - BoundedSkipMany::skip_many(r, f) + R: SkipMany { + SkipMany::skip_many(r, f) } /// Applies the parser `F` multiple times until the parser `G` succeeds, collecting the values @@ -1042,8 +1044,8 @@ pub fn many_till(r: R, p: F, end: G) -> R::ManyTillParser P: Parser, Q: Parser, T: FromIterator, - R: BoundedManyTill { - BoundedManyTill::many_till(r, p, end) + R: ManyTill { + ManyTill::many_till(r, p, end) } /// Applies the parser `p` multiple times, separated by the parser `sep` and returns a value @@ -1068,8 +1070,8 @@ pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser // E: From, P: Parser, Q: Parser, - R: BoundedMany, T, P::Error> { - BoundedMany::many(r, SepByInnerParserCtor { + R: Many, T, P::Error> { + Many::many(r, SepByInnerParserCtor { item: false, f: f, sep: sep, @@ -1080,8 +1082,8 @@ pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser /// Constructor for the inner parser used by `sep_by`. /// /// This type is created internally by `sep_by` to construct the appropriate parser from a -/// `BoundedMany` implementation providing the iteration. -// Due to the requirement of BoundedMany to be able to specify a concrete type for the function (F) +/// `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 // TODO: Implement as a trait for `ParserConstructor`? From 08085f27307abe283db65ef1928915d4754aa50c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 5 Sep 2016 00:36:55 +0200 Subject: [PATCH 40/55] parsers: Updated tests --- src/parsers.rs | 114 ++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 62 deletions(-) diff --git a/src/parsers.rs b/src/parsers.rs index 4623a4fa..b0f62780 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -570,12 +570,10 @@ 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() { @@ -583,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))))); + let p = decimal().bind(|real| token(b'.').then(decimal().map(move |frac| (real, frac)))) + .bind(|num| take_remainder().map(move |r| (r, num))); - // 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)))); - - 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] @@ -726,4 +717,3 @@ mod test { assert!(this.name.as_ref().map(|n| n.contains("parsers::test::backtrace_test")).unwrap_or(false), "Expected trace to contain \"parsers::test::backtrace_test\", got: {:?}", this.name.as_ref()); } } -*/ From bb8f0819e863f87e1d3c458af345aa775f9f5e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 5 Sep 2016 00:43:00 +0200 Subject: [PATCH 41/55] types: Fixed test for Parse::inspect --- src/types/mod.rs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index 2fce0ba7..8ef91077 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1115,32 +1115,38 @@ pub mod test { // TODO: More tests for fundamental combinators implemented on Parser - // FIXME: Inspect lifetimes - /* #[test] fn parse_result_inspect() { let mut n1 = 0; let mut n2 = 0; - let i1 = ret::(23); - let i2 = ret::(23); - let r1 = inspect(i1, |d: &u32| { - assert_eq!(d, &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 = inspect(i2, |d: &u32| { - assert_eq!(d, &23); + n1 += 1; + }); + let r2 = i2.inspect(|d: &u32| { + assert_eq!(d, &23); - n2 += 1; - }); + n2 += 1; + }); + let r3 = i3.inspect(|_: &u32| { + panic!("Success value obtained in error branch in inspect!"); + }); + + 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!(r1.parse(&b"test"[..]), (&b"test "[..], Ok(23))); assert_eq!(n1, 1); - assert_eq!(r2.parse(&b"test"[..]), (&b"test "[..], Ok(23))); assert_eq!(n2, 1); } - */ #[test] fn test_slice() { From 35694f4f502c69dc9d7169b14dc14f901dfea19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Tue, 6 Sep 2016 16:03:17 +0200 Subject: [PATCH 42/55] Fixed warnings in doctests --- src/combinators/mod.rs | 2 +- src/lib.rs | 1 + src/macros.rs | 7 ++++--- src/parse.rs | 2 +- src/types/numbering.rs | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index 477f018a..c81abad5 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -68,7 +68,7 @@ pub fn option(p: P, default: P::Output) -> impl Parser() -> impl Parser> { @@ -160,7 +160,7 @@ /// # #[macro_use] extern crate chomp; /// # fn main() { /// # use chomp::ascii::decimal; -/// # use chomp::prelude::{parse_only, U8Input, Input, Error, token, Parser, ret}; +/// # use chomp::prelude::{parse_only, U8Input, Error, token, Parser, ret}; /// # fn my_parser() -> impl Parser> { /// parse!{ /// token(b':'); @@ -224,7 +224,7 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::prelude::{parse_only, Parser, ret}; +/// # use chomp::prelude::{parse_only, ret}; /// let r: Result<_, (_, ())> = parse_only( /// parse!{ ret("some success data") }, /// b"input data" @@ -332,6 +332,7 @@ /// /// ``` /// #![recursion_limit="100"] +/// # fn main() {} /// ``` /// /// # Debugging macro expansion diff --git a/src/parse.rs b/src/parse.rs index 9e7989a2..7973cdef 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -21,7 +21,7 @@ use types::{Input, Parser}; /// /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::prelude::{U8Input, Error, Parser, parse_only, string, eof}; +/// use chomp::prelude::{Error, Parser, parse_only, string, eof}; /// /// let parser = || string(b"pattern").skip(eof()); /// diff --git a/src/types/numbering.rs b/src/types/numbering.rs index 80b64cce..a574ca13 100644 --- a/src/types/numbering.rs +++ b/src/types/numbering.rs @@ -5,7 +5,7 @@ //! # #[macro_use] extern crate chomp; //! # fn main() { //! use chomp::types::{Input, Parser, ret}; -//! use chomp::types::numbering::{InputPosition, LineNumber, Numbering, position}; +//! use chomp::types::numbering::{InputPosition, LineNumber, position}; //! use chomp::combinators::many; //! use chomp::parsers::{Error, any, take_while1, string}; //! From 5760b22722f0543e117e95b7af3b7618e53efd2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Tue, 6 Sep 2016 19:08:07 +0200 Subject: [PATCH 43/55] Tendril: Now compiles also for impl Trait --- src/types/tendril.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/types/tendril.rs b/src/types/tendril.rs index 17f49781..04ed844d 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 } } From 7b39f8a5a6ea70cf983c51ed01f03dbe3bbd7cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Tue, 6 Sep 2016 20:15:53 +0200 Subject: [PATCH 44/55] Updated tests for tendril --- src/types/tendril.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/tendril.rs b/src/types/tendril.rs index 04ed844d..03a893f4 100644 --- a/src/types/tendril.rs +++ b/src/types/tendril.rs @@ -112,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] From 0899e6eaa201e0a235db5e4b07bab542b5a494a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Tue, 6 Sep 2016 21:25:36 +0200 Subject: [PATCH 45/55] Small initial test of Parser::boxed --- src/types/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/types/mod.rs b/src/types/mod.rs index 7bdf5a21..cd4427ed 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1148,6 +1148,18 @@ pub mod test { assert_eq!(n2, 1); } + #[test] + 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 v = vec![ret::<_, ()>("foo").boxed(), err::<(), _>("error")]; + + assert_eq!(v[0].parse(&b"test2"[..]), (&b"test2"[..], Ok("foo"))); + assert_eq!(v[1].parse(&b"test2"[..]), (&b"test2"[..], Err("error"))); + } + #[test] fn test_slice() { run_primitives_test(&b"abc"[..], |x| x); From 15ab521aa6600bda6219fb3f7f94fbc94d8dbf5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 11 Feb 2017 12:53:51 +0100 Subject: [PATCH 46/55] Test: Fixed type error in boxed test --- src/types/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index cd4427ed..a640c53a 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1154,10 +1154,11 @@ pub mod test { assert_eq!(p.parse(&b"test"[..]), (&b"test"[..], Ok("foobar".to_owned()))); - let v = vec![ret::<_, ()>("foo").boxed(), err::<(), _>("error")]; + let v = vec![ret("foo").boxed(), err("error").boxed()]; - assert_eq!(v[0].parse(&b"test2"[..]), (&b"test2"[..], Ok("foo"))); - assert_eq!(v[1].parse(&b"test2"[..]), (&b"test2"[..], Err("error"))); + 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] From a4c6de02e640c985154a3dd79d15825c69d23761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Thu, 18 May 2017 13:32:38 +0200 Subject: [PATCH 47/55] Bumped verisons of bitflags and either --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 229f4d80..fc89797b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,9 @@ include = [ ] [dependencies] -bitflags = "0.7.0" +bitflags = "0.8.1" 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 } From aa8c5912c7968be38cefdc0f9d772b06db10331a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 May 2017 11:47:19 +0200 Subject: [PATCH 48/55] Parser: Added tests for Monad Plus laws --- src/types/mod.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index a640c53a..f89957f7 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -398,13 +398,24 @@ impl U8Input for T /// fail a ≡ err(a) /// ``` /// -/// It also satisfies the monad laws: +/// It also satisfies the Monad laws: /// /// ```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) +/// ``` pub trait Parser { /// Output type created by the parser, may refer to data owned by `I`. type Output; @@ -1100,6 +1111,64 @@ pub mod test { assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok(6))); } + #[test] + fn monad_plus_monoid1() { + let lhs = err("foo").or(ret("a")); + let rhs = ret::<_, ()>("a"); + + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + } + + #[test] + fn monad_plus_monoid2() { + let lhs = ret("a").or(err("foo")); + let rhs = ret::<_, ()>("a"); + + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + } + + #[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)); + } + } + + 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 monad_plus_left_zero() { + let lhs = err("foo").bind(|_: ()| ret("test")); + let rhs = err::<&str, _>("foo"); + + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Err("foo"))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Err("foo"))); + } + + #[test] + fn monad_plus_left_catch() { + let lhs = ret::<_, ()>("a").or(ret("b")); + let rhs = ret::<_, ()>("a"); + + assert_eq!(lhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + assert_eq!(rhs.parse(&b"test"[..]), (&b"test"[..], Ok("a"))); + } + #[test] fn or_test() { use parsers::{Error, any, take, token}; From d56b19a18053e7b686c212eaffd79e63bbb51954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 May 2017 14:12:47 +0200 Subject: [PATCH 49/55] Ascii: Implemented case-insensitive string-comparison --- src/ascii.rs | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/src/ascii.rs b/src/ascii.rs index f9045c61..7b73de06 100644 --- a/src/ascii.rs +++ b/src/ascii.rs @@ -166,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),+ ) => { $( @@ -186,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"[..]))); + } } From 805755665e74acb7f36a129ebdf6dd594aab5887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Sat, 27 May 2017 15:14:01 +0200 Subject: [PATCH 50/55] Updated bitflags and tendril dependencies --- Cargo.toml | 4 ++-- src/buffer/stateful.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fc89797b..1e2e3d0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,11 +22,11 @@ include = [ ] [dependencies] -bitflags = "0.8.1" +bitflags = "0.9.0" conv = { version = "0.3.3", default-features = false, features = ["std"] } 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/src/buffer/stateful.rs b/src/buffer/stateful.rs index fb345e48..cd5ef4cb 100644 --- a/src/buffer/stateful.rs +++ b/src/buffer/stateful.rs @@ -13,15 +13,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; } } From 42dc4eb1aaa2a0f340e839de1471263724f85552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Wernst=C3=A5l?= Date: Mon, 24 Jul 2017 13:02:50 +0200 Subject: [PATCH 51/55] Remove requirement for features and by using a ParserConstructor trait implemented by Fn* traits --- src/combinators/bounded.rs | 362 ++++++++++++++++++------------------- src/combinators/macros.rs | 113 +++++------- src/lib.rs | 2 +- 3 files changed, 220 insertions(+), 257 deletions(-) diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 5f2df349..5860de27 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -26,13 +26,39 @@ 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 Many { +pub trait Many + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { /// The parser type returned by `many`. - type ManyParser: Parser; + type ManyParser: Parser>::Parser as Parser>::Error>; - /// 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 /// @@ -52,12 +78,14 @@ pub trait Many { } /// Trait for applying a parser multiple times based on a range, ignoring any output. -pub trait SkipMany { +pub trait SkipMany + where I: Input, + F: ParserConstructor { /// The parser type returned by `skip_many`. - type SkipManyParser: Parser; + 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 /// @@ -76,13 +104,17 @@ pub trait SkipMany { } /// Trait for applying a parser multiple times based on a range until another parser succeeds. -pub trait ManyTill { +pub trait ManyTill + where I: Input, + F: ParserConstructor, + T: FromIterator<>::Output> { /// The parser type returned by `many_till`. - type ManyTillParser: Parser; + type ManyTillParser: Parser>::Parser as Parser>::Error>; - /// Applies the parser `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`. + /// 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 /// @@ -134,12 +166,11 @@ many_iter!{ } } -impl Many for Range +impl Many for Range where I: Input, - F: FnMut() -> P, - T: FromIterator, - P: Parser { - type ManyParser = ManyRangeParser; + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyRangeParser; #[inline] fn many(self, f: F) -> Self::ManyParser { @@ -152,7 +183,6 @@ impl Many for Range data: (self.start, max(self.start, self.end.saturating_sub(1))), _i: PhantomData, _t: PhantomData, - _p: PhantomData, } } } @@ -166,15 +196,14 @@ pub struct SkipManyRangeParser { _i: PhantomData } -impl Parser for SkipManyRangeParser +impl Parser for SkipManyRangeParser where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type Output = (); - type Error = P::Error; + type Error = >::Error; #[inline] - fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { if self.max == 0 { break; @@ -182,7 +211,7 @@ impl Parser for SkipManyRangeParser let m = i.mark(); - match (self.f)().parse(i) { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => { self.min = self.min.saturating_sub(1); // Can't overflow unless we do not quit when max == 0 @@ -205,10 +234,9 @@ impl Parser for SkipManyRangeParser } } -impl SkipMany for Range +impl SkipMany for Range where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type SkipManyParser = SkipManyRangeParser; #[inline] @@ -244,7 +272,7 @@ many_till_iter! { let i = self.buf.take().expect("Iter.buf was None"); let m = i.mark(); - match (self.data.1, (self.end)().parse(i)) { + match (self.data.1, (self.end).new_parser().parse(i)) { // We can always end (_, (b, Ok(_))) => { self.buf = Some(b); @@ -283,15 +311,14 @@ many_till_iter! { } } -impl ManyTill for Range +impl ManyTill for Range where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser, - T: FromIterator { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { /// The parser type returned by `many_till`. - type ManyTillParser = ManyTillRangeParser; + type ManyTillParser = ManyTillRangeParser; #[inline] fn many_till(self, f: F, g: G) -> Self::ManyTillParser { @@ -304,8 +331,6 @@ impl ManyTill for Range // 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, - _p: PhantomData, - _q: PhantomData, _t: PhantomData, } } @@ -337,12 +362,11 @@ many_iter!{ } } -impl Many for RangeFrom +impl Many for RangeFrom where I: Input, - F: FnMut() -> P, - T: FromIterator, - P: Parser { - type ManyParser = ManyRangeFromParser; + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyRangeFromParser; #[inline] fn many(self, f: F) -> Self::ManyParser { @@ -352,7 +376,6 @@ impl Many for RangeFrom data: self.start, _i: PhantomData, _t: PhantomData, - _p: PhantomData, } } } @@ -365,19 +388,18 @@ pub struct SkipManyRangeFromParser { _i: PhantomData } -impl Parser for SkipManyRangeFromParser +impl Parser for SkipManyRangeFromParser where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type Output = (); - type Error = P::Error; + type Error = >::Error; #[inline] - fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { let m = i.mark(); - match (self.f)().parse(i) { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => { self.min = self.min.saturating_sub(1); @@ -398,10 +420,9 @@ impl Parser for SkipManyRangeFromParser } } -impl SkipMany for RangeFrom +impl SkipMany for RangeFrom where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type SkipManyParser = SkipManyRangeFromParser; #[inline] @@ -448,15 +469,14 @@ many_till_iter! { } } -impl ManyTill for RangeFrom +impl ManyTill for RangeFrom where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser, - T: FromIterator { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { /// The parser type returned by `many_till`. - type ManyTillParser = ManyTillRangeFromParser; + type ManyTillParser = ManyTillRangeFromParser; #[inline] fn many_till(self, f: F, g: G) -> Self::ManyTillParser { @@ -466,8 +486,6 @@ impl ManyTill for RangeFrom Many for RangeFull +impl Many for RangeFull where I: Input, - F: FnMut() -> P, - T: FromIterator, - P: Parser { - type ManyParser = ManyRangeFullParser; + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyRangeFullParser; #[inline] fn many(self, f: F) -> Self::ManyParser { @@ -507,7 +524,6 @@ impl Many for RangeFull data: (), _i: PhantomData, _t: PhantomData, - _p: PhantomData, } } } @@ -519,19 +535,18 @@ pub struct SkipManyRangeFullParser { _i: PhantomData } -impl Parser for SkipManyRangeFullParser +impl Parser for SkipManyRangeFullParser where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type Output = (); - type Error = P::Error; + type Error = >::Error; #[inline] - fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { let m = i.mark(); - match (self.f)().parse(i) { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => i = b, (b, Err(_)) => { i = b.restore(m); @@ -545,10 +560,9 @@ impl Parser for SkipManyRangeFullParser } } -impl SkipMany for RangeFull +impl SkipMany for RangeFull where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type SkipManyParser = SkipManyRangeFullParser; #[inline] @@ -585,15 +599,14 @@ many_till_iter! { } } -impl ManyTill for RangeFull +impl ManyTill for RangeFull where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser, - T: FromIterator { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { /// The parser type returned by `many_till`. - type ManyTillParser = ManyTillRangeFullParser; + type ManyTillParser = ManyTillRangeFullParser; #[inline] fn many_till(self, f: F, g: G) -> Self::ManyTillParser { @@ -602,8 +615,6 @@ impl ManyTill for RangeFull q_ctor: g, data: (), _i: PhantomData, - _p: PhantomData, - _q: PhantomData, _t: PhantomData, } } @@ -640,12 +651,11 @@ many_iter!{ } } -impl Many for RangeTo +impl Many for RangeTo where I: Input, - F: FnMut() -> P, - T: FromIterator, - P: Parser { - type ManyParser = ManyRangeToParser; + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyRangeToParser; #[inline] fn many(self, f: F) -> Self::ManyParser { @@ -655,7 +665,6 @@ impl Many for RangeTo data: self.end.saturating_sub(1), _i: PhantomData, _t: PhantomData, - _p: PhantomData, } } } @@ -668,15 +677,14 @@ pub struct SkipManyRangeToParser { _i: PhantomData } -impl Parser for SkipManyRangeToParser +impl Parser for SkipManyRangeToParser where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type Output = (); - type Error = P::Error; + type Error = >::Error; #[inline] - fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { if self.max == 0 { break; @@ -684,7 +692,7 @@ impl Parser for SkipManyRangeToParser let m = i.mark(); - match (self.f)().parse(i) { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => { self.max -= 1; @@ -703,10 +711,9 @@ impl Parser for SkipManyRangeToParser } } -impl SkipMany for RangeTo +impl SkipMany for RangeTo where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type SkipManyParser = SkipManyRangeToParser; #[inline] @@ -735,7 +742,7 @@ many_till_iter! { let i = self.buf.take().expect("Iter.buf was None"); let m = i.mark(); - match (self.data, (self.end)().parse(i)) { + match (self.data, (self.end).new_parser().parse(i)) { // We can always end (_, (b, Ok(_))) => { self.buf = Some(b); @@ -768,15 +775,14 @@ many_till_iter! { } } -impl ManyTill for RangeTo +impl ManyTill for RangeTo where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser, - T: FromIterator { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { /// The parser type returned by `many_till`. - type ManyTillParser = ManyTillRangeToParser; + type ManyTillParser = ManyTillRangeToParser; #[inline] fn many_till(self, f: F, g: G) -> Self::ManyTillParser { @@ -786,8 +792,6 @@ impl ManyTill for RangeTo // [0, self.end) data: self.end.saturating_sub(1), _i: PhantomData, - _p: PhantomData, - _q: PhantomData, _t: PhantomData, } } @@ -823,12 +827,11 @@ many_iter!{ } } -impl Many for usize +impl Many for usize where I: Input, - F: FnMut() -> P, - T: FromIterator, - P: Parser { - type ManyParser = ManyExactParser; + F: ParserConstructor, + T: FromIterator<>::Output> { + type ManyParser = ManyExactParser; #[inline] fn many(self, f: F) -> Self::ManyParser { @@ -838,7 +841,6 @@ impl Many for usize data: self, _i: PhantomData, _t: PhantomData, - _p: PhantomData, } } } @@ -851,21 +853,20 @@ pub struct SkipManyExactParser { _i: PhantomData } -impl Parser for SkipManyExactParser +impl Parser for SkipManyExactParser where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type Output = (); - type Error = P::Error; + type Error = >::Error; #[inline] - fn parse(mut self, mut i: I) -> (I, Result<(), P::Error>) { + fn parse(mut self, mut i: I) -> (I, Result<(), >::Error>) { loop { if self.n == 0 { break; } - match (self.f)().parse(i) { + match (self.f).new_parser().parse(i) { (b, Ok(_)) => { self.n -= 1; @@ -884,10 +885,9 @@ impl Parser for SkipManyExactParser } } -impl SkipMany for usize +impl SkipMany for usize where I: Input, - F: FnMut() -> P, - P: Parser { + F: ParserConstructor { type SkipManyParser = SkipManyExactParser; #[inline] @@ -917,7 +917,7 @@ many_till_iter! { // TODO: Remove the branches here (ie. take + unwrap) let i = self.buf.take().expect("Iter.buf was None"); - match (self.end)().parse(i) { + match (self.end).new_parser().parse(i) { (b, Ok(_)) => { self.buf = Some(b); self.state = EndStateTill::EndSuccess; @@ -949,15 +949,14 @@ many_till_iter! { } } -impl ManyTill for usize +impl ManyTill for usize where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser, - T: FromIterator { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { /// The parser type returned by `many_till`. - type ManyTillParser = ManyTillExactParser; + type ManyTillParser = ManyTillExactParser; #[inline] fn many_till(self, f: F, g: G) -> Self::ManyTillParser { @@ -966,15 +965,13 @@ impl ManyTill for usize q_ctor: g, data: self, _i: PhantomData, - _p: PhantomData, - _q: 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 /// @@ -989,17 +986,16 @@ impl ManyTill for usize /// * 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(r: R, f: F) -> R::ManyParser +pub fn many(r: R, f: F) -> R::ManyParser where I: Input, - F: FnMut() -> P, - P: Parser, - T: FromIterator, - R: Many { + 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 /// @@ -1013,17 +1009,17 @@ pub fn many(r: R, f: F) -> R::ManyParser /// * 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(r: R, f: F) -> R::SkipManyParser +pub fn skip_many(r: R, f: F) -> R::SkipManyParser where I: Input, - F: FnMut() -> P, - P: Parser, - R: SkipMany { + F: ParserConstructor, + R: SkipMany { SkipMany::skip_many(r, f) } -/// Applies the parser `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`. +/// 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 /// @@ -1036,21 +1032,21 @@ pub fn skip_many(r: R, f: F) -> R::SkipManyParser /// * Will never yield fewer items than the lower bound of the range. /// * Use `combinators::bounded::many_till` instead of calling this trait method directly. #[inline] -pub fn many_till(r: R, p: F, end: G) -> R::ManyTillParser +pub fn many_till(r: R, p: F, end: G) -> R::ManyTillParser where I: Input, //E: From, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser, - T: FromIterator, - R: ManyTill { + 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 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 /// @@ -1062,15 +1058,14 @@ pub fn many_till(r: R, p: F, end: G) -> R::ManyTillParser /// * Will never yield more items than the upper bound of the range. #[inline] // TODO: look at the From -pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser +pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser where I: Input, - T: FromIterator, - F: FnMut() -> P, - G: FnMut() -> Q, // E: From, - P: Parser, - Q: Parser, - R: Many, T, P::Error> { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output>, + R: Many, T> { Many::many(r, SepByInnerParserCtor { item: false, f: f, @@ -1086,7 +1081,6 @@ pub fn sep_by(r: R, f: F, sep: G) -> R::ManyParser // 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 -// TODO: Implement as a trait for `ParserConstructor`? #[derive(Debug)] pub struct SepByInnerParserCtor { item: bool, @@ -1095,34 +1089,22 @@ pub struct SepByInnerParserCtor { _i: PhantomData, } -impl FnOnce<()> for SepByInnerParserCtor +impl ParserConstructor for SepByInnerParserCtor where I: Input, - F: FnMut() -> P, - S: FnMut() -> Q, - P: Parser, - Q: Parser { - type Output = ThenParser, P>; - - extern "rust-call" fn call_once(self, _: ()) -> Self::Output { - unimplemented!() - } -} + F: ParserConstructor, + S: ParserConstructor, + S::Parser: Parser>::Error> { + type Parser = ThenParser, F::Parser>; -impl FnMut<()> for SepByInnerParserCtor - where I: Input, - F: FnMut() -> P, - S: FnMut() -> Q, - P: Parser, - Q: Parser { - extern "rust-call" fn call_mut(&mut self, _: ()) -> Self::Output { + fn new_parser(&mut self) -> Self::Parser { if self.item { - MaybeAParser::parser((self.sep)()) + MaybeAParser::parser((self.sep).new_parser()) } else { self.item = true; MaybeAParser::none() - }.then((self.f)()) + }.then((self.f).new_parser()) } } diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index 9f6c48b5..f3457e42 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -15,36 +15,32 @@ macro_rules! many_iter { } ) => { $(#[$attr])* - pub struct $name + pub struct $name where I: Input, - F: FnMut() -> P, - T: FromIterator, - P: Parser { + F: ParserConstructor, + T: FromIterator<>::Output> { /// Parser to execute once for each iteration parser_ctor: F, /// Nested state data: $data_ty, _i: PhantomData, _t: PhantomData, - _p: PhantomData

, } - impl Parser for $name + impl Parser for $name where I: Input, - F: FnMut() -> P, - P: Parser, - T: FromIterator { + F: ParserConstructor, + T: FromIterator<>::Output> { type Output = T; - type Error = P::Error; + type Error = >::Error; #[inline] - fn parse(self, i: I) -> (I, Result) { + fn parse(self, i: I) -> (I, Result>::Error>) { /// Iterator used to run the parser multiple times - struct ParserIterator - where F: FnMut() -> P, - P: Parser { + struct ParserIterator + where F: ParserConstructor { /// Last state of the parser - state: Option, + 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, @@ -57,23 +53,20 @@ macro_rules! many_iter { /// Nested state data: $data_ty, _i: PhantomData, - _p: PhantomData

, } - impl ParserIterator - where F: FnMut() -> P, - P: Parser { + impl ParserIterator + where F: ParserConstructor { #[inline] - fn end_state(self) -> (I, $data_ty, I::Marker, Option) { + 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) } } - impl Iterator for ParserIterator - where F: FnMut() -> P, - P: Parser { - type Item = P::Output; + impl Iterator for ParserIterator + where F: ParserConstructor { + type Item = >::Output; #[inline] fn size_hint(&$size_hint_self) -> (usize, Option) { @@ -90,7 +83,7 @@ macro_rules! many_iter { // TODO: Any way to prevent marking here since it is not used at all times? $next_self.mark = i.mark(); - match ($next_self.parser_ctor)().parse(i) { + match ($next_self.parser_ctor).new_parser().parse(i) { (b, Ok(v)) => { $next_self.buf = Some(b); @@ -118,7 +111,6 @@ macro_rules! many_iter { mark: mark, data: self.data, _i: PhantomData, - _p: PhantomData, }; let $result: T = FromIterator::from_iter(iter.by_ref()); @@ -150,13 +142,12 @@ macro_rules! many_till_iter { } ) => { $(#[$attr])* - pub struct $name + pub struct $name where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser, - T: FromIterator { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { /// Parser constructor to repeat p_ctor: F, /// Parser constructor for the end @@ -164,23 +155,20 @@ macro_rules! many_till_iter { /// Nested state data: $data_ty, _i: PhantomData, - _p: PhantomData

, - _q: PhantomData, _t: PhantomData, } - impl Parser for $name + impl Parser for $name where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser, - T: FromIterator { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error>, + T: FromIterator<>::Output> { type Output = T; - type Error = P::Error; + type Error = >::Error; #[inline] - fn parse(self, i: I) -> (I, Result) { + fn parse(self, i: I) -> (I, Result>::Error>) { enum EndStateTill { Error(E), Incomplete, @@ -188,14 +176,13 @@ macro_rules! many_till_iter { } /// Iterator used by `many_till` and `many1`. - struct ParserIterator + struct ParserIterator where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser { + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error> { /// Last state of the parser - state: EndStateTill, + state: EndStateTill<>::Error>, /// Parser to repeat parser: F, /// Parser to end @@ -207,32 +194,28 @@ macro_rules! many_till_iter { /// Nested state data: $data_ty, _i: PhantomData, - _p: PhantomData

, - _q: PhantomData, } - impl ParserIterator + impl ParserIterator where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser { + 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) { + 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) } } - impl Iterator for ParserIterator + impl Iterator for ParserIterator where I: Input, - F: FnMut() -> P, - G: FnMut() -> Q, - P: Parser, - Q: Parser { - type Item = P::Output; + F: ParserConstructor, + G: ParserConstructor, + G::Parser: Parser>::Error> { + type Item = >::Output; #[inline] fn size_hint(&$size_hint_self) -> (usize, Option) { @@ -246,7 +229,7 @@ macro_rules! many_till_iter { // TODO: Remove the branches here (ie. take + unwrap) let i = $next_self.buf.take().expect("Iter.buf was None"); - match ($next_self.parser)().parse(i) { + match ($next_self.parser).new_parser().parse(i) { (b, Ok(v)) => { $next_self.buf = Some(b); @@ -271,8 +254,6 @@ macro_rules! many_till_iter { buf: Some(i), data: self.data, _i: PhantomData, - _p: PhantomData, - _q: PhantomData, }; let $result: T = FromIterator::from_iter(iter.by_ref()); @@ -298,7 +279,7 @@ macro_rules! iter_till_end_test { let i = $the_self.buf.take().expect("Iter.buf was None"); let m = i.mark(); - match ($the_self.end)().parse(i) { + match ($the_self.end).new_parser().parse(i) { (b, Ok(_)) => { $the_self.buf = Some(b); $the_self.state = EndStateTill::EndSuccess; diff --git a/src/lib.rs b/src/lib.rs index b7b58ca5..fa8ab2ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -202,7 +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, unboxed_closures, fn_traits)] +#![feature(conservative_impl_trait)] #![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, From 608d5d66fd7b7f73a63b2f3d56e827e464c0a266 Mon Sep 17 00:00:00 2001 From: Matt Kantor - mkantor Date: Wed, 12 Jul 2017 12:43:43 -0400 Subject: [PATCH 52/55] Fix markdown header syntax in README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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). From 14165d206c043e6dcd3b4c7f47a943070d9253f3 Mon Sep 17 00:00:00 2001 From: Johannes Schilling Date: Fri, 14 Jul 2017 13:20:07 +0200 Subject: [PATCH 53/55] buffer/data_source: add RWDataSource struct and impls --- src/buffer/data_source.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) 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)] From 3cca9abdb7aff54b037b54603e7a4efb6361cd22 Mon Sep 17 00:00:00 2001 From: Johannes Schilling Date: Fri, 14 Jul 2017 13:30:32 +0200 Subject: [PATCH 54/55] buffer/stateful: implement Write for Source if RWDataSource --- src/buffer/mod.rs | 2 +- src/buffer/stateful.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index f97a0e42..393c0e8e 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -42,7 +42,7 @@ use types::{Input, Parser}; use types::Buffer as InputBuffer; 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; diff --git a/src/buffer/stateful.rs b/src/buffer/stateful.rs index cd5ef4cb..faf410b3 100644 --- a/src/buffer/stateful.rs +++ b/src/buffer/stateful.rs @@ -5,6 +5,7 @@ use types::{Input, Parser}; use buffer::{ Buffer, DataSource, + RWDataSource, FixedSizeBuffer, InputBuf, Stream, @@ -196,6 +197,17 @@ 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>; From e8835ea8918e2156a169abefd294eb9196a2e7ca Mon Sep 17 00:00:00 2001 From: Johannes Schilling Date: Fri, 14 Jul 2017 14:21:15 +0200 Subject: [PATCH 55/55] buffer/stateful: add RW Source constructor methods --- src/buffer/stateful.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/buffer/stateful.rs b/src/buffer/stateful.rs index faf410b3..7d5755f7 100644 --- a/src/buffer/stateful.rs +++ b/src/buffer/stateful.rs @@ -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.