Skip to content

Commit 637379a

Browse files
committed
fixup! Add loop_parser
1 parent 0af270c commit 637379a

File tree

1 file changed

+96
-17
lines changed

1 file changed

+96
-17
lines changed

src/parser/sequence.rs

Lines changed: 96 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -895,13 +895,96 @@ where
895895
#[derive(Copy, Clone)]
896896
pub struct Loop<F, S>(F, S);
897897

898-
impl<Input, F, P, G, S> Parser<Input> for Loop<F, S>
898+
impl<Input, F, S, P, G> Parser<Input> for Loop<F, S>
899+
where
900+
Input: Stream,
901+
F: FnMut(&mut S) -> P,
902+
S: Clone,
903+
P: Parser<Input, Output = G>,
904+
G: FnOnce(&mut S)
905+
{
906+
type Output = S;
907+
type PartialState = (Option<S>, Option<P>, bool, P::PartialState);
908+
909+
parse_mode!(Input);
910+
#[inline]
911+
fn parse_mode_impl<M>(
912+
&mut self,
913+
mode: M,
914+
input: &mut Input,
915+
state: &mut Self::PartialState,
916+
) -> ParseResult<Self::Output, <Input as StreamOnce>::Error>
917+
where
918+
M: ParseMode,
919+
{
920+
let Self(ref mut next_func, ref init_state) = *self;
921+
LoopGen(next_func, || init_state.clone()).parse_mode_impl(mode, input, state)
922+
}
923+
}
924+
925+
// Takes a function `func` and initial `state`. Function is applied to current
926+
// state and generates a parser outputting function to update the state. This
927+
// is repeated until the generated parser fails.
928+
//
929+
/// ```
930+
/// # extern crate combine;
931+
/// # use std::collections::HashMap;
932+
/// # use combine::{Parser, Stream, many1, token, value, unexpected_any, optional, choice};
933+
/// # use combine::parser::char::digit;
934+
/// # use combine::parser::sequence::loop_parser;
935+
/// # fn main() {
936+
/// // Parses 'a', 'b' and 'c' such that there is no consecutive letters returning their count
937+
/// #[derive(PartialEq, Eq, Clone, Hash)]
938+
/// enum Token { A, B, C }
939+
/// fn token_parser<Input>(last_token: &Option<Token>) -> impl Parser<Input, Output = Token>
940+
/// where
941+
/// Input: Stream<Token = char>
942+
/// {
943+
/// let mut choices = vec![];
944+
/// if *last_token != Some(Token::A) {
945+
/// choices.push(token('a').map(|_| Token::A).left());
946+
/// }
947+
/// if *last_token != Some(Token::B) {
948+
/// choices.push(token('b').map(|_| Token::B).left().right());
949+
/// }
950+
/// if *last_token != Some(Token::C) {
951+
/// choices.push(token('c').map(|_| Token::C).right().right());
952+
/// }
953+
/// choice(choices)
954+
/// }
955+
/// let result = loop_parser((HashMap::<Token, usize>::new(), None), |(_, last_token)| {
956+
/// token_parser(last_token).map(|current_token| move |(ref mut acc, ref mut last_token): &mut (HashMap::<Token, usize>, Option<Token>)| {
957+
/// *acc.entry(current_token.clone()).or_insert(0) += 1;
958+
/// *last_token = Some(current_token);
959+
/// })
960+
/// }).map(|x| x.0).parse("ababacbcbcaa");
961+
/// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::A)), Ok(Some(&4)));
962+
/// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::B)), Ok(Some(&4)));
963+
/// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::C)), Ok(Some(&3)));
964+
/// assert_eq!(result.as_ref().map(|x| x.1), Ok("a"));
965+
/// # }
966+
/// ```
967+
pub fn loop_parser<Input, F, P, G, S>(state: S, func: F) -> Loop<F, S>
899968
where
900969
Input: Stream,
901970
F: FnMut(&mut S) -> P,
902971
P: Parser<Input, Output = G>,
903972
G: FnOnce(&mut S),
904973
S: Clone
974+
{
975+
Loop(func, state)
976+
}
977+
978+
#[derive(Copy, Clone)]
979+
pub struct LoopGen<F, G>(F, G);
980+
981+
impl<Input, F, G, S, P, H> Parser<Input> for LoopGen<F, G>
982+
where
983+
Input: Stream,
984+
F: FnMut(&mut S) -> P,
985+
G: FnMut() -> S,
986+
P: Parser<Input, Output = H>,
987+
H: FnOnce(&mut S)
905988
{
906989
type Output = S;
907990
type PartialState = (Option<S>, Option<P>, bool, P::PartialState);
@@ -917,13 +1000,13 @@ where
9171000
where
9181001
M: ParseMode,
9191002
{
920-
let Self(ref mut next_func, ref init_state) = *self;
1003+
let Self(ref mut next_func, ref mut state_gen) = *self;
9211004
let (ref mut state, ref mut parser, ref mut committed, ref mut partial_state) = *state;
9221005
if mode.is_first() {
9231006
debug_assert!(state.is_none());
9241007
debug_assert!(parser.is_none());
9251008
debug_assert!(!*committed);
926-
*state = Some(init_state.clone());
1009+
*state = Some(state_gen());
9271010
*parser = Some(next_func(state.as_mut().unwrap()));
9281011
}
9291012
let parser = parser.as_mut().unwrap();
@@ -957,20 +1040,16 @@ where
9571040
}
9581041
}
9591042

960-
961-
// If `init` is not `None` it parses using it first. Than subsequently
962-
// applies `func` to result until `None` is returned. The result is
963-
// the last state.
964-
//
965-
// Otherwise, if `init` is `None`, it returns the `state` without
966-
// consuming any input.
1043+
// Takes a function `func` and initial `state`. Function is applied to current
1044+
// state and generates a parser outputting function to update the state. This
1045+
// is repeated until the generated parser fails.
9671046
//
9681047
/// ```
9691048
/// # extern crate combine;
9701049
/// # use std::collections::HashMap;
9711050
/// # use combine::{Parser, Stream, many1, token, value, unexpected_any, optional, choice};
9721051
/// # use combine::parser::char::digit;
973-
/// # use combine::parser::sequence::loop_parser;
1052+
/// # use combine::parser::sequence::loop_gen;
9741053
/// # fn main() {
9751054
/// // Parses 'a', 'b' and 'c' such that there is no consecutive letters returning their count
9761055
/// #[derive(PartialEq, Eq, Clone, Hash)]
@@ -991,7 +1070,7 @@ where
9911070
/// }
9921071
/// choice(choices)
9931072
/// }
994-
/// let result = loop_parser((HashMap::<Token, usize>::new(), None), |(_, last_token)| {
1073+
/// let result = loop_gen(|| (HashMap::<Token, usize>::new(), None), |(_, last_token)| {
9951074
/// token_parser(last_token).map(|current_token| move |(ref mut acc, ref mut last_token): &mut (HashMap::<Token, usize>, Option<Token>)| {
9961075
/// *acc.entry(current_token.clone()).or_insert(0) += 1;
9971076
/// *last_token = Some(current_token);
@@ -1003,13 +1082,13 @@ where
10031082
/// assert_eq!(result.as_ref().map(|x| x.1), Ok("a"));
10041083
/// # }
10051084
/// ```
1006-
pub fn loop_parser<Input, F, P, G, S>(state: S, func: F) -> Loop<F, S>
1085+
pub fn loop_gen<Input, F, G, S, P, H>(state_gen: G, func: F) -> LoopGen<F, G>
10071086
where
10081087
Input: Stream,
10091088
F: FnMut(&mut S) -> P,
1010-
P: Parser<Input, Output = G>,
1011-
G: FnOnce(&mut S),
1012-
S: Clone
1089+
G: FnMut() -> S,
1090+
P: Parser<Input, Output = H>,
1091+
H: FnOnce(&mut S)
10131092
{
1014-
Loop(func, state)
1093+
LoopGen(func, state_gen)
10151094
}

0 commit comments

Comments
 (0)