Skip to content

Commit

Permalink
fix: Propagate the ParseMode in range::recognize
Browse files Browse the repository at this point in the history
I checked all other definitions of `parse_partial` as well and all other seem fine (does not need to be parse_mode instead) as they do not invoke another parser recursively
  • Loading branch information
Marwes committed Jun 30, 2018
1 parent 4a7866a commit c330a73
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 12 deletions.
11 changes: 11 additions & 0 deletions src/lib.rs
Expand Up @@ -230,6 +230,16 @@ macro_rules! impl_token_parser {
self.0.parse_lazy(input)
}

#[inline]
fn parse_first(
&mut self,
input: &mut Self::Input,
state: &mut Self::PartialState,
) -> ConsumedResult<Self::Output, Self::Input>
{
self.0.parse_first(input, state)
}

#[inline]
fn parse_partial(
&mut self,
Expand Down Expand Up @@ -555,6 +565,7 @@ macro_rules! combine_parse_partial {
$parser.parse_mode($mode, $input, state)
}};
(($ignored:ty) $mode:ident $input:ident $state:ident $parser:block) => {

$parser.parse_mode($mode, $input, $state)
};
}
Expand Down
19 changes: 13 additions & 6 deletions src/parser/combinator.rs
Expand Up @@ -636,12 +636,16 @@ where
self.0.parse_lazy(input)
}

parse_mode!();
#[inline]
fn parse_partial(
fn parse_mode<M>(
&mut self,
mode: M,
input: &mut Self::Input,
state: &mut Self::PartialState,
) -> ConsumedResult<Self::Output, Self::Input> {
) -> ConsumedResult<Self::Output, Self::Input>
where M: ParseMode
{
let mut new_child_state;
let result = {
let child_state = if let None = state.0 {
Expand All @@ -652,7 +656,7 @@ where
state.0.as_mut().unwrap().downcast_mut().unwrap()
};

self.0.parse_partial(input, child_state)
self.0.parse_mode(mode, input, child_state)
};

if let ConsumedErr(_) = result {
Expand Down Expand Up @@ -730,11 +734,14 @@ where
}

#[inline]
fn parse_partial(
fn parse_mode<M>(
&mut self,
mode: M,
input: &mut Self::Input,
state: &mut Self::PartialState,
) -> ConsumedResult<Self::Output, Self::Input> {
) -> ConsumedResult<Self::Output, Self::Input>
where M: ParseMode
{
let mut new_child_state;
let result = {
let child_state = if let None = state.0 {
Expand All @@ -745,7 +752,7 @@ where
state.0.as_mut().unwrap().downcast_mut().unwrap()
};

self.0.parse_partial(input, child_state)
self.0.parse_mode(mode, input, child_state)
};

if let ConsumedErr(_) = result {
Expand Down
16 changes: 11 additions & 5 deletions src/parser/range.rs
Expand Up @@ -134,20 +134,26 @@ where
type Output = (<P::Input as StreamOnce>::Range, P::Output);
type PartialState = (usize, P::PartialState);

parse_mode!();
#[inline]
fn parse_partial(
fn parse_mode<M>(
&mut self,
mode: M,
input: &mut Self::Input,
state: &mut Self::PartialState,
) -> ConsumedResult<Self::Output, Self::Input> {
) -> ConsumedResult<Self::Output, Self::Input>
where M: ParseMode
{
let (ref mut distance_state, ref mut child_state) = *state;

let before = input.checkpoint();
if let Err(_) = input.uncons_range(*distance_state) {
panic!("recognize errored when restoring the input stream to its expected state");
if !mode.is_first() {
if let Err(_) = input.uncons_range(*distance_state) {
panic!("recognize errored when restoring the input stream to its expected state");
}
}

let value = match self.0.parse_partial(input, child_state) {
let value = match self.0.parse_mode(mode, input, child_state) {
ConsumedOk(x) | EmptyOk(x) => x,
EmptyErr(err) => return EmptyErr(err),
ConsumedErr(err) => {
Expand Down
10 changes: 9 additions & 1 deletion tests/parser.rs
Expand Up @@ -5,7 +5,7 @@ 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::range::{self, range};
use combine::parser::repeat::{count_min_max, sep_by, sep_end_by1, skip_until, take_until};
use combine::Parser;

Expand Down Expand Up @@ -399,4 +399,12 @@ mod tests_std {
Ok(((), "ab"))
);
}

#[test]
fn recognize_parser_issue_168() {
assert_eq!(
range::recognize(skip_until(try((char('a'), char('b'))))).parse("aaab"),
Ok(("aa", "ab"))
);
}
}

0 comments on commit c330a73

Please sign in to comment.