@@ -891,3 +891,123 @@ where
891
891
{
892
892
ThenRef ( p, f)
893
893
}
894
+
895
+ #[ derive( Copy , Clone ) ]
896
+ pub struct While < P , F , S > ( Option < P > , F , S ) ;
897
+
898
+ impl < Input , P , F , S > Parser < Input > for While < P , F , S >
899
+ where
900
+ Input : Stream ,
901
+ P : Parser < Input > ,
902
+ F : FnMut ( & mut S , P :: Output ) -> Option < P > ,
903
+ S : Clone
904
+ {
905
+ type Output = S ;
906
+ type PartialState = ( Option < S > , Option < P > , bool , P :: PartialState ) ;
907
+
908
+ parse_mode ! ( Input ) ;
909
+ #[ inline]
910
+ fn parse_mode_impl < M > (
911
+ & mut self ,
912
+ mut mode : M ,
913
+ input : & mut Input ,
914
+ state : & mut Self :: PartialState ,
915
+ ) -> ParseResult < Self :: Output , <Input as StreamOnce >:: Error >
916
+ where
917
+ M : ParseMode ,
918
+ {
919
+ let While ( ref mut init_parser, ref mut func, ref init_state) = * self ;
920
+ let ( ref mut state, ref mut parser, ref mut committed, ref mut partial_state) = * state;
921
+ // state == None means we haven't run func yet so we need to depend on init_parser
922
+ let mut current_parser_opt: & mut Option < P > = if mode. is_first ( ) || state. is_none ( ) {
923
+ debug_assert ! ( state. is_none( ) ) ;
924
+ debug_assert ! ( parser. is_none( ) ) ;
925
+ init_parser
926
+ } else {
927
+ debug_assert ! ( state. is_some( ) ) ;
928
+ parser
929
+ } ;
930
+ while let Some ( ref mut current_parser) = * current_parser_opt {
931
+ let result = current_parser. parse_mode_impl ( mode, input, partial_state) ;
932
+ let value = match result {
933
+ CommitOk ( next_value) => {
934
+ * committed = true ;
935
+ next_value
936
+ } ,
937
+ PeekOk ( next_value) => next_value,
938
+ CommitErr ( e) => return CommitErr ( e) ,
939
+ PeekErr ( e) => if * committed {
940
+ return CommitErr ( e. error )
941
+ } else {
942
+ return PeekErr ( e)
943
+ }
944
+ } ;
945
+ if state. is_none ( ) {
946
+ * state = Some ( init_state. clone ( ) ) ;
947
+ }
948
+ * parser = func ( state. as_mut ( ) . unwrap ( ) , value) ;
949
+ current_parser_opt = parser;
950
+ mode. set_first ( ) ;
951
+ }
952
+ let result = state. as_ref ( ) . unwrap_or ( init_state) . clone ( ) ;
953
+ if * committed {
954
+ CommitOk ( result)
955
+ } else {
956
+ PeekOk ( result)
957
+ }
958
+ }
959
+ }
960
+
961
+
962
+ // If `init` is not `None` it parses using it first. Than subsequently
963
+ // applies `func` to result until `None` is returned. The result is
964
+ // the last state.
965
+ //
966
+ // Otherwise, if `init` is `None`, it returns the `state` without
967
+ // consuming any input.
968
+ //
969
+ /// ```
970
+ /// # extern crate combine;
971
+ /// # use std::collections::HashMap;
972
+ /// # use combine::{Parser, Stream, many1, token, value, unexpected_any, optional, choice};
973
+ /// # use combine::parser::char::digit;
974
+ /// # use combine::parser::sequence::while_parser;
975
+ /// # fn main() {
976
+ /// // Parses 'a', 'b' and 'c' such that there is no consecutive letters returning their count
977
+ /// #[derive(PartialEq, Eq, Copy, Clone, Hash)]
978
+ /// enum Token { A, B, C }
979
+ /// fn token_parser<Input>(last_token: Option<Token>) -> impl Parser<Input, Output = Option<Token>>
980
+ /// where
981
+ /// Input: Stream<Token = char>
982
+ /// {
983
+ /// let mut choices = vec![];
984
+ /// if last_token != Some(Token::A) {
985
+ /// choices.push(token('a').map(|_| Token::A).left());
986
+ /// }
987
+ /// if last_token != Some(Token::B) {
988
+ /// choices.push(token('b').map(|_| Token::B).left().right());
989
+ /// }
990
+ /// if last_token != Some(Token::C) {
991
+ /// choices.push(token('c').map(|_| Token::C).right().right());
992
+ /// }
993
+ /// optional(choice(choices))
994
+ /// }
995
+ /// let result = while_parser(Some(token_parser(None)), |acc, token_opt| token_opt.map(|token| {
996
+ /// *acc.entry(token).or_insert(0) += 1;
997
+ /// token_parser(token_opt)
998
+ /// }), HashMap::<Token, usize>::new()).parse("ababacbcbcaa");
999
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::A)), Ok(Some(&4)));
1000
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::B)), Ok(Some(&4)));
1001
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::C)), Ok(Some(&3)));
1002
+ /// assert_eq!(result.as_ref().map(|x| x.1), Ok("a"));
1003
+ /// # }
1004
+ /// ```
1005
+ pub fn while_parser < Input , P , F , S > ( init : Option < P > , func : F , state : S ) -> While < P , F , S >
1006
+ where
1007
+ Input : Stream ,
1008
+ P : Parser < Input > ,
1009
+ F : FnMut ( & mut S , P :: Output ) -> Option < P > ,
1010
+ S : Clone
1011
+ {
1012
+ While ( init, func, state)
1013
+ }
0 commit comments