@@ -891,3 +891,204 @@ 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 , 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 >
968
+ where
969
+ Input : Stream ,
970
+ F : FnMut ( & mut S ) -> P ,
971
+ P : Parser < Input , Output = G > ,
972
+ G : FnOnce ( & mut S ) ,
973
+ 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 )
988
+ {
989
+ type Output = S ;
990
+ type PartialState = ( Option < S > , Option < P > , bool , P :: PartialState ) ;
991
+
992
+ parse_mode ! ( Input ) ;
993
+ #[ inline]
994
+ fn parse_mode_impl < M > (
995
+ & mut self ,
996
+ mut mode : M ,
997
+ input : & mut Input ,
998
+ state : & mut Self :: PartialState ,
999
+ ) -> ParseResult < Self :: Output , <Input as StreamOnce >:: Error >
1000
+ where
1001
+ M : ParseMode ,
1002
+ {
1003
+ let Self ( ref mut next_func, ref mut state_gen) = * self ;
1004
+ let ( ref mut state, ref mut parser, ref mut committed, ref mut partial_state) = * state;
1005
+ if mode. is_first ( ) {
1006
+ debug_assert ! ( state. is_none( ) ) ;
1007
+ debug_assert ! ( parser. is_none( ) ) ;
1008
+ debug_assert ! ( !* committed) ;
1009
+ * state = Some ( state_gen ( ) ) ;
1010
+ * parser = Some ( next_func ( state. as_mut ( ) . unwrap ( ) ) ) ;
1011
+ }
1012
+ let parser = parser. as_mut ( ) . unwrap ( ) ;
1013
+ loop {
1014
+ let before = input. checkpoint ( ) ;
1015
+ let result = parser. parse_mode_impl ( mode, input, partial_state) ;
1016
+ let mutator = match result {
1017
+ CommitOk ( next_mutator) => {
1018
+ * committed = true ;
1019
+ next_mutator
1020
+ } ,
1021
+ PeekOk ( next_mutator) => next_mutator,
1022
+ CommitErr ( e) => return CommitErr ( e) ,
1023
+ PeekErr ( _) => {
1024
+ match input. reset ( before) {
1025
+ Ok ( _) => if * committed {
1026
+ return CommitOk ( state. take ( ) . unwrap ( ) )
1027
+ } else {
1028
+ return PeekOk ( state. take ( ) . unwrap ( ) )
1029
+ } ,
1030
+ Err ( err) => return CommitErr ( err)
1031
+ } ;
1032
+ }
1033
+ } ;
1034
+ let state = state. as_mut ( ) . unwrap ( ) ;
1035
+ mutator ( state) ;
1036
+ * parser = next_func ( state) ;
1037
+ * partial_state = Default :: default ( ) ;
1038
+ mode. set_first ( ) ;
1039
+ }
1040
+ }
1041
+ }
1042
+
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.
1046
+ //
1047
+ /// ```
1048
+ /// # extern crate combine;
1049
+ /// # use std::collections::HashMap;
1050
+ /// # use combine::{Parser, Stream, many1, token, value, unexpected_any, optional, choice};
1051
+ /// # use combine::parser::char::digit;
1052
+ /// # use combine::parser::sequence::loop_gen;
1053
+ /// # fn main() {
1054
+ /// // Parses 'a', 'b' and 'c' such that there is no consecutive letters returning their count
1055
+ /// #[derive(PartialEq, Eq, Clone, Hash)]
1056
+ /// enum Token { A, B, C }
1057
+ /// fn token_parser<Input>(last_token: &Option<Token>) -> impl Parser<Input, Output = Token>
1058
+ /// where
1059
+ /// Input: Stream<Token = char>
1060
+ /// {
1061
+ /// let mut choices = vec![];
1062
+ /// if *last_token != Some(Token::A) {
1063
+ /// choices.push(token('a').map(|_| Token::A).left());
1064
+ /// }
1065
+ /// if *last_token != Some(Token::B) {
1066
+ /// choices.push(token('b').map(|_| Token::B).left().right());
1067
+ /// }
1068
+ /// if *last_token != Some(Token::C) {
1069
+ /// choices.push(token('c').map(|_| Token::C).right().right());
1070
+ /// }
1071
+ /// choice(choices)
1072
+ /// }
1073
+ /// let result = loop_gen(|| (HashMap::<Token, usize>::new(), None), |(_, last_token)| {
1074
+ /// token_parser(last_token).map(|current_token| move |(ref mut acc, ref mut last_token): &mut (HashMap::<Token, usize>, Option<Token>)| {
1075
+ /// *acc.entry(current_token.clone()).or_insert(0) += 1;
1076
+ /// *last_token = Some(current_token);
1077
+ /// })
1078
+ /// }).map(|x| x.0).parse("ababacbcbcaa");
1079
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::A)), Ok(Some(&4)));
1080
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::B)), Ok(Some(&4)));
1081
+ /// assert_eq!(result.as_ref().map(|x| x.0.get(&Token::C)), Ok(Some(&3)));
1082
+ /// assert_eq!(result.as_ref().map(|x| x.1), Ok("a"));
1083
+ /// # }
1084
+ /// ```
1085
+ pub fn loop_gen < Input , F , G , S , P , H > ( state_gen : G , func : F ) -> LoopGen < F , G >
1086
+ where
1087
+ Input : Stream ,
1088
+ F : FnMut ( & mut S ) -> P ,
1089
+ G : FnMut ( ) -> S ,
1090
+ P : Parser < Input , Output = H > ,
1091
+ H : FnOnce ( & mut S )
1092
+ {
1093
+ LoopGen ( func, state_gen)
1094
+ }
0 commit comments