Repository: Marwes/combine (language: rust)

Issue:
take_until with tuple parser
I'm new to parser combinator so pardon if this is a naive question.
This works as expected:
`println!("{:?}", take_until::<String, _>(try(string("ab"))).easy_parse(r#"aaab"#)); // Ok(("aa", "ab"))`
But this behaves surprisingly:
`println!("{:?}", take_until::<String, _>(try((char('a'), char('b')))).easy_parse(r#"aaab"#)); // Ok(("aaa", "b"))`

I want to use tuple because the closing string is calculated at runtime. For example, to parse the closing "quote" of Rust raw string, I count the number of # in `r#"`, but
`take_until::<String, _>(try((char('"'), count_min_max::<String, _>(1, 1, char('#'))))).easy_parse("aa\"ab\"#")`
gives `aa\"ab\"` instead of `aa\"ab`


Discussion / hints:
Fix coming in https://github.com/Marwes/combine/pull/169/commits/b7285e3472cee88b620e6140a6b0eb5c0d3ef53e (going to fix #167 as well before publishing)
Thanks for the immediate fix!
@Marwes 
take_until works fine now, but recognize(skip_until()) is still broken:
```
println!("{:?}", recognize(skip_until(try(string("ab")))).parse("aaab")); // Ok(("aa", "ab"))
println!("{:?}", recognize(skip_until(try((char('a'), char('b'))))).parse("aaab")); // Ok(("aaa", "b"))
```

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 51dee359..e3569173 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+<a name="3.3.4"></a>
+### 3.3.1 (2018-06-30)
+
+* fix: Forward the partial mode through the parser! macro correctly
+
+
+<a name="3.3.3"></a>
+### 3.3.3 (2018-06-29)
+
+#### Bug fixes
+* Parse from the start in sequence parsers in first mode
+
+
 <a name="3.3.1"></a>
 ### 3.3.1 (2018-06-01)
 
diff --git a/Cargo.toml b/Cargo.toml
index 361137f8..06d07c7d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 
 name = "combine"
-version = "3.3.4-alpha.0"
+version = "3.3.5-alpha.0"
 authors = ["Markus Westerlind <marwes91@gmail.com>"]
 
 description = "Fast parser combinators on arbitrary streams with zero-copy support."
diff --git a/release.toml b/release.toml
new file mode 100644
index 00000000..bf431685
--- /dev/null
+++ b/release.toml
@@ -0,0 +1,1 @@
+pre-release-hool = ["clog", "-F"]
diff --git a/src/lib.rs b/src/lib.rs
index 51ed6d6e..254e9414 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -549,14 +549,13 @@ macro_rules! parser {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! combine_parse_partial {
-    ((()) $input:ident $state:ident $parser:block) => {{
+    ((()) $mode:ident $input:ident $state:ident $parser:block) => {{
         let _ = $state;
         let ref mut state = Default::default();
-        $parser.parse_partial($input, state)
+        $parser.parse_mode($mode, $input, state)
     }};
-    (($ignored:ty) $input:ident $state:ident $parser:block) => {
-
-        $parser.parse_partial($input, $state)
+    (($ignored:ty) $mode:ident $input:ident $state:ident $parser:block) => {
+        $parser.parse_mode($mode, $input, $state)
     };
 }
 
@@ -605,15 +604,18 @@ macro_rules! combine_parser_impl {
             type Output = $output_type;
             type PartialState = $($partial_state)*;
 
+            parse_mode!();
             #[inline]
-            fn parse_partial(
+            fn parse_mode_impl<M>(
                 &mut self,
+                mode: M,
                 input: &mut Self::Input,
                 state: &mut Self::PartialState,
                 ) -> $crate::error::ConsumedResult<$output_type, $input_type>
+            where M: $crate::parser::ParseMode
             {
                 let $type_name { $( $arg: ref mut $arg,)* __marker: _ } = *self;
-                combine_parse_partial!(($($partial_state)*) input state $parser)
+                combine_parse_partial!(($($partial_state)*) mode input state $parser)
             }
 
             #[inline]
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 71380cb0..15545209 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -59,7 +59,7 @@ macro_rules! parse_mode {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> $crate::error::ConsumedResult<Self::Output, Self::Input> {
             self.parse_mode($crate::parser::PartialMode::default(), input, state)
         }
 
@@ -68,7 +68,7 @@ macro_rules! parse_mode {
             &mut self,
             input: &mut Self::Input,
             state: &mut Self::PartialState,
-        ) -> ConsumedResult<Self::Output, Self::Input> {
+        ) -> $crate::error::ConsumedResult<Self::Output, Self::Input> {
             self.parse_mode($crate::parser::FirstMode, input, state)
         }
     }


Test patch:
diff --git a/tests/parser.rs b/tests/parser.rs
index 890a70b1..ecd5feea 100644
--- a/tests/parser.rs
+++ b/tests/parser.rs
@@ -1,13 +1,13 @@
 extern crate combine;
 
-use combine::Parser;
 use combine::parser::char::{digit, letter};
 use combine::parser::choice::{choice, optional};
 use combine::parser::combinator::{no_partial, not_followed_by, try};
 use combine::parser::error::unexpected;
 use combine::parser::item::{any, eof, token, value, Token};
 use combine::parser::range::range;
-use combine::parser::repeat::{count_min_max, sep_by, take_until, sep_end_by1};
+use combine::parser::repeat::{count_min_max, sep_by, sep_end_by1, skip_until, take_until};
+use combine::Parser;
 
 #[test]
 fn choice_empty() {
@@ -43,10 +43,10 @@ fn not_followed_by_does_not_consume_any_input() {
 #[cfg(feature = "std")]
 mod tests_std {
     use super::*;
-    use combine::Parser;
     use combine::parser::char::{char, digit, letter};
     use combine::stream::easy::{Error, Errors, ParseError};
     use combine::stream::state::{SourcePosition, State};
+    use combine::Parser;
 
     #[derive(Clone, PartialEq, Debug)]
     struct CloneOnly {
@@ -391,4 +391,12 @@ mod tests_std {
             Ok((String::from("aa"), "ab"))
         );
     }
+
+    #[test]
+    fn parser_macro_must_impl_parse_mode_issue_168() {
+        assert_eq!(
+            skip_until(try((char('a'), char('b')))).parse("aaab"),
+            Ok(((), "ab"))
+        );
+    }
 }