Repository: Marwes/combine (language: rust)

Issue:
Many acts as it is consumed if passed a consumed input
Bug found by @avwhite with a minimal reproducing example.

Should be able to fix this later today.

EDIT: Example is actually wrong since you should expect it to return Consumed due to spaces consuming one char. Updated with correct example (which needs to manually create a state or this wont work).

``` rust
extern crate "parser-combinators" as parser;

use parser::{many, any_char, Parser};
use parser::primitives::{State, Consumed, SourcePosition};

fn main() {
        let state = State { position: SourcePosition { line: 1, column: 1 }, input: "", consumed: Consumed::Consumed };
        let result = many(any_char as fn (_) -> _)
            .parse_state(state);

        assert!(result.is_ok());
        assert_eq!(result.unwrap().1.consumed, Consumed::Empty);

} 
```



Discussion / hints:

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index 09887730..1878b968 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -65,8 +65,7 @@
 //! 
 //! fn main() {
 //!     let result = (expr as fn (_) -> _)
-//!         .parse("[[], hello, [world]]")
-//!         .map(|(x, state)| (x, state.input));
+//!         .parse("[[], hello, [world]]");
 //!     let expr = Expr::Array(vec![
 //!           Expr::Array(Vec::new())
 //!         , Expr::Id("hello".to_string())
@@ -129,21 +128,19 @@ mod tests {
 
     #[test]
     fn test_integer() {
-        let result = (integer as fn(_) -> _).parse("123")
-            .map(|(x, s)| (x, s.input));
+        let result = (integer as fn(_) -> _).parse("123");
         assert_eq!(result, Ok((123i64, "")));
     }
     #[test]
     fn list() {
         let mut p = sep_by(integer as fn(_) -> _, satisfy(|c| c == ','));
-        let result = p.parse("123,4,56")
-            .map(|(x, s)| (x, s.input));
+        let result = p.parse("123,4,56");
         assert_eq!(result, Ok((vec![123, 4, 56], "")));
     }
     #[test]
     fn iterator() {
         let result = (integer as fn(_) -> _).parse("123".chars())
-            .map(|(i, mut state)| (i, state.input.next()));
+            .map(|(i, mut input)| (i, input.next()));
         assert_eq!(result, Ok((123i64, None)));
     }
     #[test]
@@ -156,8 +153,7 @@ mod tests {
             .skip(satisfy(|c| c == ':'))
             .skip(spaces)
             .and(word2)
-            .parse("x: int")
-            .map(|(x, s)| (x, s.input));
+            .parse("x: int");
         assert_eq!(c_decl, Ok((("x".to_string(), "int".to_string()), "")));
     }
     #[test]
@@ -169,12 +165,11 @@ r"
         let result = spaces()
             .with(integer as fn(_) -> _)
             .skip(spaces())
-            .parse(source);
-        let state = State {
+            .parse_state(State::new(source));
+        let state = Consumed::Consumed(State {
             position: SourcePosition { line: 3, column: 1 },
-            consumed: Consumed::Consumed,
             input: ""
-        };
+        });
         assert_eq!(result, Ok((123i64, state)));
     }
 
@@ -203,8 +198,7 @@ r"
     #[test]
     fn expression() {
         let result = sep_by(expr as fn (_) -> _, satisfy(|c| c == ','))
-            .parse("int, 100, [[], 123]")
-            .map(|(x, s)| (x, s.input));
+            .parse("int, 100, [[], 123]");
         let exprs = vec![
               Expr::Id("int".to_string())
             , Expr::Int(100)
@@ -223,7 +217,6 @@ r"
             .parse(input);
         let err = ParseError {
             position: SourcePosition { line: 2, column: 1 },
-            consumed: Consumed::Consumed,
             errors: vec![Error::Unexpected(','), Error::Message("Expected digit".to_string())]
         };
         assert_eq!(result, Err(err));
@@ -260,13 +253,13 @@ r"
         match input.clone().uncons_char() {
             Ok((c, _)) => {
                 if c.is_alphanumeric() {
-                    Err(ParseError::new(input.position, Consumed::Empty, Error::Unexpected(c)))
+                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                 }
                 else {
-                    Ok(((), input))
+                    Ok(((), Consumed::Empty(input)))
                 }
             }
-            Err(_) => Ok(((), input))
+            Err(_) => Ok(((), Consumed::Empty(input)))
         }
     }
     #[test]
@@ -293,7 +286,7 @@ r"(3 * 4) + 2 * 4 * test + 4 * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         let result = (term as fn (_) -> _)
             .parse(LONG_EXPR);
         assert!(result.is_ok()); 
-        assert_eq!(result.unwrap().1.input, "");
+        assert_eq!(result.unwrap().1, "");
         bench.iter(|| {
             let result = (term as fn (_) -> _)
                 .parse(LONG_EXPR);
@@ -332,13 +325,12 @@ r"(3 * 4) + 2 * 4 * test + 4 * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         let error = result
             .map(|x| format!("{:?}", x))
             .unwrap_err();
-        assert_eq!(error.consumed, Consumed::Consumed);
         assert_eq!(error.position, SourcePosition { line: 1, column: 8 });
     }
 
     #[test]
     fn infinite_recursion_in_box_parser() {
-        (many(Box::new(digit())))
+        let _ = (many(Box::new(digit())))
             .parse("1");
     }
 }
diff --git a/src/parser.rs b/src/parser.rs
index a5a87fec..590acf6a 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -56,7 +56,7 @@ impl <I> Parser for Unexpected<I>
     type Input = I;
     type Output = ();
     fn parse_state(&mut self, input: State<I>) -> ParseResult<(), I> {
-        Err(ParseError::new(input.position, Consumed::Empty, Error::Message(self.0.clone())))
+        Err(Consumed::Empty(ParseError::new(input.position, Error::Message(self.0.clone()))))
     }
 }
 ///Always fails with `message` as the error.
@@ -86,7 +86,7 @@ impl <I, T> Parser for Value<I, T>
     type Input = I;
     type Output = T;
     fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
-        Ok((self.0.clone(), input))
+        Ok((self.0.clone(), Consumed::Empty(input)))
     }
 }
 ///Always returns the value `v` without consuming any input.
@@ -142,15 +142,17 @@ impl <P, F> Parser for ConsumeMany<P, F>
         , F: FnMut(<P as Parser>::Output) {
     type Input = <P as Parser>::Input;
     type Output = ();
-    fn parse_state(&mut self, mut input: State<<P as Parser>::Input>) -> ParseResult<(), <P as Parser>::Input> {
+    fn parse_state(&mut self, input: State<<P as Parser>::Input>) -> ParseResult<(), <P as Parser>::Input> {
+        let mut input = Consumed::Empty(input);
         loop {
-            match self.0.parse_state(input.as_empty()) {
+            let was_empty = input.is_empty();
+            let rest = input.clone().into_inner();
+            match self.0.parse_state(rest) {
                 Ok((x, rest)) => {
                     (self.1)(x);
-                    input = rest;
-                    input.consumed = Consumed::Consumed;
+                    input = if was_empty { rest } else { rest.as_consumed() };
                 }
-                Err(err@ParseError { consumed: Consumed::Consumed, .. }) => return Err(err),
+                Err(err@Consumed::Consumed(_)) => return Err(err),
                 Err(_) => break
             }
         }
@@ -195,7 +197,7 @@ impl <P: Parser> Parser for Many1<P> {
     fn parse_state(&mut self, input: State<<P as Parser>::Input>) -> ParseResult<Vec<<P as Parser>::Output>, <P as Parser>::Input> {
         let (first, input) = try!(self.0.parse_state(input));
         let mut result = vec![first];
-        let ((), input) = try!(ConsumeMany(&mut self.0, |x| result.push(x)).parse_state(input));
+        let ((), input) = try!(input.combine(|input| ConsumeMany(&mut self.0, |x| result.push(x)).parse_state(input)));
         Ok((result, input))
     }
 }
@@ -247,7 +249,7 @@ impl <P> Parser for Chars1<P>
         let (first, input) = try!(self.parser.parse_state(input));
         let mut result = String::new();
         result.push(first);
-        let ((), input) = try!(ConsumeMany(&mut self.parser, |x| result.push(x)).parse_state(input));
+        let ((), input) = try!(input.combine(|input| ConsumeMany(&mut self.parser, |x| result.push(x)).parse_state(input)));
         Ok((result, input))
     }
 }
@@ -267,19 +269,22 @@ impl <P, S> Parser for SepBy<P, S>
 
     type Input = <P as Parser>::Input;
     type Output = Vec<<P as Parser>::Output>;
-    fn parse_state(&mut self, mut input: State<<P as Parser>::Input>) -> ParseResult<Vec<<P as Parser>::Output>, <P as Parser>::Input> {
+    fn parse_state(&mut self, input: State<<P as Parser>::Input>) -> ParseResult<Vec<<P as Parser>::Output>, <P as Parser>::Input> {
         let mut result = Vec::new();
-        match self.parser.parse_state(input.as_empty()) {
+        let mut input = Consumed::Empty(input);
+        match input.clone().combine(|input| self.parser.parse_state(input)) {
             Ok((x, rest)) => {
                 result.push(x);
                 input = rest;
             }
-            Err(err@ParseError { consumed: Consumed::Consumed, .. }) => return Err(err),
-            Err(_) => return Ok((result, input))
+            Err(err@Consumed::Consumed(_)) => return Err(err),
+            Err(Consumed::Empty(_)) => return Ok((result, input))
         }
-        let rest = (&mut self.separator)
-            .with(&mut self.parser);
-        let ((), input) = try!(ConsumeMany(rest, |x| result.push(x)).parse_state(input));
+        let ((), input) = try!(input.combine(|input| {
+            let rest = (&mut self.separator)
+                .with(&mut self.parser);
+            ConsumeMany(rest, |x| result.push(x)).parse_state(input)
+        }));
         Ok((result, input))
     }
 }
@@ -344,7 +349,7 @@ impl <I, Pred> Parser for Satisfy<I, Pred>
             Ok((c, s)) => {
                 if (self.pred)(c) { Ok((c, s)) }
                 else {
-                    Err(ParseError::new(input.position, Consumed::Empty, Error::Unexpected(c)))
+                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                 }
             }
             Err(err) => Err(err)
@@ -381,22 +386,23 @@ impl <'a, I> Parser for StringP<'a, I>
     where I: Stream<Item=char> {
     type Input = I;
     type Output = &'a str;
-    fn parse_state(&mut self, mut input: State<I>) -> ParseResult<&'a str, I> {
+    fn parse_state(&mut self, input: State<I>) -> ParseResult<&'a str, I> {
         let start = input.position;
+        let mut input = Consumed::Empty(input);
         for (i, c) in self.s.chars().enumerate() {
-            match input.uncons_char() {
+            match input.combine(|input| input.uncons_char()) {
                 Ok((other, rest)) => {
                     if c != other {
-                        let consumed = if i == 0 { Consumed::Empty } else { Consumed::Consumed };
-                        return Err(ParseError::new(start, consumed, Error::Expected(self.s.to_string())));
+                        let error = ParseError::new(start, Error::Expected(self.s.to_string()));
+                        return Err(if i == 0 { Consumed::Empty(error) } else { Consumed::Consumed(error) });
                     }
                     input = rest;
                 }
-                Err(mut err) => {
-                    let consumed = if i == 0 { Consumed::Empty } else { Consumed::Consumed };
-                    err.consumed = consumed;
-                    err.position = start;
-                    return Err(err)
+                Err(error) => {
+                    return error.combine(move |mut error| {
+                        error.position = start;
+                        Err(if i == 0 { Consumed::Empty(error) } else { Consumed::Consumed(error) })
+                    })
                 }
             }
         }
@@ -430,15 +436,10 @@ impl <I, A, B, P1, P2> Parser for And<P1, P2>
     type Output = (A, B);
     fn parse_state(&mut self, input: State<I>) -> ParseResult<(A, B), I> {
         let (a, rest) = try!(self.0.parse_state(input));
-        let first_consumed = rest.consumed;
-        let (b, rest) = match self.1.parse_state(rest) {
-            Ok(v) => v,
-            Err(mut error) => {
-                error.consumed.combine(first_consumed);
-                return Err(error)
-            }
-        };
-        Ok(((a, b), rest))
+        rest.combine(move |rest| {
+            let (b, rest) = try!(self.1.parse_state(rest));
+            Ok(((a, b), rest))
+        })
     }
 }
 
@@ -451,8 +452,8 @@ impl <P> Parser for Optional<P>
     fn parse_state(&mut self, input: State<<P as Parser>::Input>) -> ParseResult<Option<<P as Parser>::Output>, <P as Parser>::Input> {
         match self.0.parse_state(input.clone()) {
             Ok((x, rest)) => Ok((Some(x), rest)),
-            Err(err@ParseError { consumed: Consumed::Consumed, .. }) => return Err(err),
-            Err(_) => Ok((None, input))
+            Err(err@Consumed::Consumed(_)) => return Err(err),
+            Err(Consumed::Empty(_)) => Ok((None, Consumed::Empty(input)))
         }
     }
 }
@@ -483,7 +484,7 @@ pub fn digit<I>() -> FnParser<I, char, fn (State<I>) -> ParseResult<char, I>>
             Ok((c, rest)) => {
                 if c.is_digit(10) { Ok((c, rest)) }
                 else {
-                    Err(ParseError::new(input.position, Consumed::Empty, Error::Message("Expected digit".to_string())))
+                    Err(Consumed::Empty(ParseError::new(input.position, Error::Message("Expected digit".to_string()))))
                 }
             }
             Err(err) => Err(err)
@@ -550,9 +551,10 @@ impl <I, P> Parser for Message<P>
     fn parse_state(&mut self, input: State<I>) -> ParseResult<<Self as Parser>::Output, I> {
         match self.0.parse_state(input.clone()) {
             Ok(x) => Ok(x),
-            Err(mut err) => {
+            Err(err@Consumed::Consumed(_)) => Err(err),
+            Err(Consumed::Empty(mut err)) => {
                 err.add_message(self.1.clone());
-                Err(err)
+                Err(Consumed::Empty(err))
             }
         }
     }
@@ -568,11 +570,12 @@ impl <I, O, P1, P2> Parser for Or<P1, P2>
     fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I> {
         match self.0.parse_state(input.clone()) {
             Ok(x) => Ok(x),
-            Err(err@ParseError { consumed: Consumed::Consumed, .. }) => Err(err),
-            Err(error1) => {
+            Err(err@Consumed::Consumed(_)) => Err(err),
+            Err(Consumed::Empty(error1)) => {
                 match self.1.parse_state(input) {
                     Ok(x) => Ok(x),
-                    Err(error2) => Err(error1.merge(error2))
+                    Err(err@Consumed::Consumed(_)) => Err(err),
+                    Err(Consumed::Empty(error2)) => Err(Consumed::Empty(error1.merge(error2)))
                 }
             }
         }
@@ -606,14 +609,17 @@ impl <'a, I, O, P, Op> Parser for Chainl1<P, Op>
     fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I> {
         let (mut l, mut input) = try!(self.0.parse_state(input));
         loop {
-            match (&mut self.1).and(&mut self.0).parse_state(input.clone()) {
+            let was_empty = input.is_empty();
+            let rest = input.clone().into_inner();
+            match (&mut self.1).and(&mut self.0).parse_state(rest) {
                 Ok(((mut op, r), rest)) => {
                     l = op(l, r);
-                    input = rest;
+                    input = if was_empty { rest } else { rest.as_consumed() };
                 }
-                Err(err@ParseError { consumed: Consumed::Consumed, .. }) => return Err(err),
+                Err(err@Consumed::Consumed(_)) => return Err(err),
                 Err(_) => break
-            };
+            }
+            
 
         }
         Ok((l, input))
@@ -639,10 +645,7 @@ impl <I, O, P> Parser for Try<P>
     type Output = O;
     fn parse_state(&mut self, input: State<I>) -> ParseResult<O, I> {
         self.0.parse_state(input)
-            .map_err(|mut err| {
-                err.consumed = Consumed::Empty;
-                err
-            })
+            .map_err(Consumed::as_empty)
     }
 }
 
@@ -657,18 +660,10 @@ impl <P, N, F> Parser for Then<P, N, F>
     type Output = <N as Parser>::Output;
     fn parse_state(&mut self, input: State<<Self as Parser>::Input>) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input> {
         let (value, input) = try!(self.0.parse_state(input));
-        let first_consumed = input.consumed;
-        let mut next = (self.1)(value);
-        match next.parse_state(input) {
-            Ok(mut tuple) => {
-                tuple.1.consumed.combine(first_consumed);
-                Ok(tuple)
-            }
-            Err(mut error) => {
-                error.consumed.combine(first_consumed);
-                Err(error)
-            }
-        }
+        input.combine(move |input| {
+            let mut next = (self.1)(value);
+            next.parse_state(input)
+        })
     }
 }
 
diff --git a/src/primitives.rs b/src/primitives.rs
index 0e8c99ca..98a661c0 100644
--- a/src/primitives.rs
+++ b/src/primitives.rs
@@ -36,17 +36,62 @@ pub enum Error {
 
 ///Enum used to indicate if a stream has had any elements consumed
 #[derive(Clone, PartialEq, Debug, Copy)]
-pub enum Consumed {
-    ///Flag indicating that the parser has consumed elements
-    Consumed,
-    ///Flag indicating that the parser did not consume any elements
-    Empty
+pub enum Consumed<T> {
+    ///Constructor indicating that the parser has consumed elements
+    Consumed(T),
+    ///Constructor indicating that the parser did not consume any elements
+    Empty(T)
 }
 
-impl Consumed {
-    pub fn combine(&mut self, other: Consumed) {
-        if other == Consumed::Consumed {
-            *self = Consumed::Consumed;
+impl <T> Consumed<T> {
+
+    ///Returns true if the `self` is empty
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            Consumed::Empty(_) => true,
+            Consumed::Consumed(_) => false
+        }
+    }
+
+    ///Extracts the contained value
+    pub fn into_inner(self) -> T {
+        match self {
+            Consumed::Empty(x) => x,
+            Consumed::Consumed(x) => x
+        }
+    }
+
+    ///Converts the consumed state into the Consumed state
+    pub fn as_consumed(self) -> Consumed<T> {
+        Consumed::Consumed(self.into_inner())
+    }
+
+    ///Converts the consumed state into the Empty state
+    pub fn as_empty(self) -> Consumed<T> {
+        Consumed::Empty(self.into_inner())
+    }
+
+    ///Maps over the contained value without changing the consumed state
+    pub fn map<F, U>(self, f: F) -> Consumed<U>
+        where F: FnOnce(T) -> U {
+        match self {
+            Consumed::Empty(x) => Consumed::Empty(f(x)),
+            Consumed::Consumed(x) => Consumed::Consumed(f(x))
+        }
+    }
+
+    ///Combines the Consumed flags from `self` and the result of `f`
+    pub fn combine<F, U, I>(self, f: F) -> ParseResult<U, I>
+        where F: FnOnce(T) -> ParseResult<U, I> {
+        match self {
+            Consumed::Consumed(x) => {
+                match f(x) {
+                    Ok((v, Consumed::Empty(rest))) => Ok((v, Consumed::Consumed(rest))),
+                    Err(Consumed::Empty(err)) => Err(Consumed::Consumed(err)),
+                    y => y
+                }
+            }
+            Consumed::Empty(x) => f(x)
         }
     }
 }
@@ -56,16 +101,13 @@ impl Consumed {
 pub struct ParseError {
     ///The position where the error occured
     pub position: SourcePosition,
-    ///Flag indicating wether the parser had consumed any elements from the stream before the error
-    ///occured
-    pub consumed: Consumed,
     ///A vector containing specific information on what errors occured at `position`
     pub errors: Vec<Error>
 }
 
 impl ParseError {
-    pub fn new(position: SourcePosition, consumed: Consumed, error: Error) -> ParseError {
-        ParseError { position: position, consumed: consumed, errors: vec![error] }
+    pub fn new(position: SourcePosition, error: Error) -> ParseError {
+        ParseError { position: position, errors: vec![error] }
     }
     pub fn add_message(&mut self, message: String) {
         self.add_error(Error::Message(message));
@@ -120,17 +162,16 @@ impl fmt::Display for Error {
 #[derive(Clone, PartialEq, Debug)]
 pub struct State<I> {
     pub position: SourcePosition,
-    pub input: I,
-    pub consumed: Consumed
+    pub input: I
 }
 
 impl <I: Stream> State<I> {
-    fn new(input: I) -> State<I> {
-        State { position: SourcePosition::start(), input: input, consumed: Consumed::Empty }
+    pub fn new(input: I) -> State<I> {
+        State { position: SourcePosition::start(), input: input }
     }
 
     pub fn as_empty(&self) -> State<I> {
-        State { position: self.position, input: self.input.clone(), consumed: Consumed::Empty }
+        State { position: self.position, input: self.input.clone() }
     }
 
     ///`uncons` is the most general way of extracting and item from a stream
@@ -143,9 +184,9 @@ impl <I: Stream> State<I> {
         match input.uncons() {
             Ok((c, input)) => {
                 f(&mut position, &c);
-                Ok((c, State { position: position, input: input, consumed: Consumed::Consumed }))
+                Ok((c, Consumed::Consumed(State { position: position, input: input })))
             }
-            Err(()) => Err(ParseError::new(position, Consumed::Empty, Error::Message("End of input".to_string())))
+            Err(()) => Err(Consumed::Empty(ParseError::new(position, Error::Message("End of input".to_string()))))
         }
     }
 }
@@ -161,7 +202,7 @@ impl <I: Stream<Item=char>> State<I> {
 ///A type alias over the specific `Result` type used to indicated parser success/failure.
 ///`O` is the type that is output on success
 ///`I` is the specific stream type used in the parser
-pub type ParseResult<O, I> = Result<(O, State<I>), ParseError>;
+pub type ParseResult<O, I> = Result<(O, Consumed<State<I>>), Consumed<ParseError>>;
 
 ///A stream is a sequence of items that can be extracted one by one
 pub trait Stream : Clone {
@@ -212,8 +253,11 @@ pub trait Parser {
 
     ///Entrypoint of the parser
     ///Takes some input and tries to parse it returning a `ParseResult`
-    fn parse(&mut self, input: Self::Input) -> ParseResult<Self::Output, Self::Input> {
-        self.parse_state(State::new(input))
+    fn parse(&mut self, input: Self::Input) -> Result<(Self::Output, Self::Input), ParseError> {
+        match self.parse_state(State::new(input)) {
+            Ok((v, state)) => Ok((v, state.into_inner().input)),
+            Err(error) => Err(error.into_inner())
+        }
     }
     ///Parses using the state `input` by calling Stream::uncons one or more times
     ///On success returns `Ok((value, new_state))` on failure it returns `Err(error)`


Test patch: