@@ -891,3 +891,125 @@ where
891
891
{
892
892
ThenRef ( p, f)
893
893
}
894
+
895
+ #[ derive( Copy , Clone ) ]
896
+ pub struct Loop < F , S > ( F , S ) ;
897
+
898
+ impl < Input , F , P , G , S > Parser < Input > for Loop < F , S >
899
+ where
900
+ Input : Stream ,
901
+ F : FnMut ( & mut S ) -> P ,
902
+ P : Parser < Input , Output = G > ,
903
+ G : FnOnce ( & mut S ) ,
904
+ S : Clone
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
+ mut 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
+ let ( ref mut state, ref mut parser, ref mut committed, ref mut partial_state) = * state;
922
+ if mode. is_first ( ) {
923
+ debug_assert ! ( state. is_none( ) ) ;
924
+ debug_assert ! ( parser. is_none( ) ) ;
925
+ debug_assert ! ( !* committed) ;
926
+ * state = Some ( init_state. clone ( ) ) ;
927
+ * parser = Some ( next_func ( state. as_mut ( ) . unwrap ( ) ) ) ;
928
+ }
929
+ let parser = parser. as_mut ( ) . unwrap ( ) ;
930
+ loop {
931
+ let before = input. checkpoint ( ) ;
932
+ let result = parser. parse_mode_impl ( mode, input, partial_state) ;
933
+ let mutator = match result {
934
+ CommitOk ( next_mutator) => {
935
+ * committed = true ;
936
+ next_mutator
937
+ } ,
938
+ PeekOk ( next_mutator) => next_mutator,
939
+ CommitErr ( e) => return CommitErr ( e) ,
940
+ PeekErr ( _) => {
941
+ match input. reset ( before) {
942
+ Ok ( _) => if * committed {
943
+ return CommitOk ( state. take ( ) . unwrap ( ) )
944
+ } else {
945
+ return PeekOk ( state. take ( ) . unwrap ( ) )
946
+ } ,
947
+ Err ( err) => return CommitErr ( err)
948
+ } ;
949
+ }
950
+ } ;
951
+ let state = state. as_mut ( ) . unwrap ( ) ;
952
+ mutator ( state) ;
953
+ * parser = next_func ( state) ;
954
+ * partial_state = Default :: default ( ) ;
955
+ mode. set_first ( ) ;
956
+ }
957
+ }
958
+ }
959
+
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.
967
+ //
968
+ /// ```
969
+ /// # extern crate combine;
970
+ /// # use std::collections::HashMap;
971
+ /// # use combine::{Parser, Stream, many1, token, value, unexpected_any, optional, choice};
972
+ /// # use combine::parser::char::digit;
973
+ /// # use combine::parser::sequence::loop_parser;
974
+ /// # fn main() {
975
+ /// // Parses 'a', 'b' and 'c' such that there is no consecutive letters returning their count
976
+ /// #[derive(PartialEq, Eq, Clone, Hash)]
977
+ /// enum Token { A, B, C }
978
+ /// fn token_parser<Input>(last_token: &Option<Token>) -> impl Parser<Input, Output = Token>
979
+ /// where
980
+ /// Input: Stream<Token = char>
981
+ /// {
982
+ /// let mut choices = vec![];
983
+ /// if *last_token != Some(Token::A) {
984
+ /// choices.push(token('a').map(|_| Token::A).left());
985
+ /// }
986
+ /// if *last_token != Some(Token::B) {
987
+ /// choices.push(token('b').map(|_| Token::B).left().right());
988
+ /// }
989
+ /// if *last_token != Some(Token::C) {
990
+ /// choices.push(token('c').map(|_| Token::C).right().right());
991
+ /// }
992
+ /// choice(choices)
993
+ /// }
994
+ /// let result = loop_parser((HashMap::<Token, usize>::new(), None), |(_, last_token)| {
995
+ /// token_parser(last_token).map(|current_token| move |(ref mut acc, ref mut last_token): &mut (HashMap::<Token, usize>, Option<Token>)| {
996
+ /// *acc.entry(current_token.clone()).or_insert(0) += 1;
997
+ /// *last_token = Some(current_token);
998
+ /// })
999
+ /// }).map(|x| x.0).parse("ababacbcbcaa");
1000
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::A)), Ok(Some(&4)));
1001
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::B)), Ok(Some(&4)));
1002
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::C)), Ok(Some(&3)));
1003
+ /// assert_eq!(result.as_ref().map(|x| x.1), Ok("a"));
1004
+ /// # }
1005
+ /// ```
1006
+ pub fn loop_parser < Input , F , P , G , S > ( state : S , func : F ) -> Loop < F , S >
1007
+ where
1008
+ Input : Stream ,
1009
+ F : FnMut ( & mut S ) -> P ,
1010
+ P : Parser < Input , Output = G > ,
1011
+ G : FnOnce ( & mut S ) ,
1012
+ S : Clone
1013
+ {
1014
+ Loop ( func, state)
1015
+ }
0 commit comments