@@ -731,7 +731,7 @@ fn operand_occur_leaf_infallible(
731731 ) ) ( i)
732732}
733733
734- #[ derive( Clone , Copy , Debug ) ]
734+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
735735enum BinaryOperand {
736736 Or ,
737737 And ,
@@ -770,54 +770,118 @@ fn aggregate_binary_expressions(
770770}
771771
772772fn aggregate_infallible_expressions (
773- leafs : Vec < ( Option < BinaryOperand > , Option < Occur > , Option < UserInputAst > ) > ,
773+ input_leafs : Vec < ( Option < BinaryOperand > , Option < Occur > , Option < UserInputAst > ) > ,
774774) -> ( UserInputAst , ErrorList ) {
775- let mut leafs: Vec < ( _ , _ , UserInputAst ) > = leafs
775+ let mut err = Vec :: new ( ) ;
776+ let mut leafs: Vec < ( _ , _ , UserInputAst ) > = input_leafs
776777 . into_iter ( )
777778 . filter_map ( |( operand, occur, ast) | ast. map ( |ast| ( operand, occur, ast) ) )
778779 . collect ( ) ;
779780 if leafs. is_empty ( ) {
780- // TODO should this produce an error?
781- return ( UserInputAst :: empty_query ( ) , Vec :: new ( ) ) ;
781+ return ( UserInputAst :: empty_query ( ) , err) ;
782782 }
783783
784- // if no occur => use binary operand (default = or)
785- // if no binary opearnd => use occur
784+ let use_operand = leafs. iter ( ) . any ( |( operand, _, _) | operand. is_some ( ) ) ;
785+ let all_operand = leafs
786+ . iter ( )
787+ . skip ( 1 )
788+ . all ( |( operand, _, _) | operand. is_some ( ) ) ;
789+ let early_operand = leafs
790+ . iter ( )
791+ . take ( 1 )
792+ . all ( |( operand, _, _) | operand. is_some ( ) ) ;
793+ let use_occur = leafs. iter ( ) . any ( |( _, occur, _) | occur. is_some ( ) ) ;
794+
795+ if use_operand && use_occur {
796+ err. push ( LenientErrorInternal {
797+ pos : 0 ,
798+ message : "Use of mixed occur and boolean operator" . to_string ( ) ,
799+ } ) ;
800+ }
801+
802+ if use_operand && !all_operand {
803+ err. push ( LenientErrorInternal {
804+ pos : 0 ,
805+ message : "Missing boolean operator" . to_string ( ) ,
806+ } ) ;
807+ }
808+
809+ if early_operand {
810+ err. push ( LenientErrorInternal {
811+ pos : 0 ,
812+ message : "Found unexpeted boolean operator before term" . to_string ( ) ,
813+ } ) ;
814+ }
786815
787- if leafs. len ( ) == 1 {
788- match leafs. remove ( 0 ) {
789- ( _, occur, ast) if occur != Some ( Occur :: MustNot ) => return ( ast, Vec :: new ( ) ) ,
790- ( _, occur, ast) => return ( UserInputAst :: Clause ( vec ! [ ( occur, ast) ] ) , Vec :: new ( ) ) ,
816+ let mut clauses: Vec < Vec < ( Option < Occur > , UserInputAst ) > > = vec ! [ ] ;
817+ for ( ( prev_operator, occur, ast) , ( next_operator, _, _) ) in
818+ leafs. iter ( ) . zip ( leafs. iter ( ) . skip ( 1 ) )
819+ {
820+ match prev_operator {
821+ Some ( BinaryOperand :: And ) => {
822+ if let Some ( last) = clauses. last_mut ( ) {
823+ last. push ( ( occur. or ( Some ( Occur :: Must ) ) , ast. clone ( ) ) ) ;
824+ } else {
825+ let mut last = Vec :: new ( ) ;
826+ last. push ( ( occur. or ( Some ( Occur :: Must ) ) , ast. clone ( ) ) ) ;
827+ clauses. push ( last) ;
828+ }
829+ }
830+ Some ( BinaryOperand :: Or ) => {
831+ let default_op = match next_operator {
832+ Some ( BinaryOperand :: And ) => Some ( Occur :: Must ) ,
833+ _ => Some ( Occur :: Should ) ,
834+ } ;
835+ clauses. push ( vec ! [ ( occur. or( default_op) , ast. clone( ) ) ] ) ;
836+ }
837+ None => {
838+ let default_op = match next_operator {
839+ Some ( BinaryOperand :: And ) => Some ( Occur :: Must ) ,
840+ Some ( BinaryOperand :: Or ) => Some ( Occur :: Should ) ,
841+ None => None ,
842+ } ;
843+ clauses. push ( vec ! [ ( occur. or( default_op) , ast. clone( ) ) ] )
844+ }
791845 }
792846 }
793847
794- if leafs. iter ( ) . all ( |( operand, _, _) | operand. is_none ( ) ) {
795- let clauses = leafs
796- . into_iter ( )
797- . map ( |( _, occur, ast) | ( occur, ast) )
798- . collect ( ) ;
799- return ( UserInputAst :: Clause ( clauses) , Vec :: new ( ) ) ;
848+ // leaf isn't empty, so we can unwrap
849+ let ( last_operator, last_occur, last_ast) = leafs. pop ( ) . unwrap ( ) ;
850+ match last_operator {
851+ Some ( BinaryOperand :: And ) => {
852+ if let Some ( last) = clauses. last_mut ( ) {
853+ last. push ( ( last_occur. or ( Some ( Occur :: Must ) ) , last_ast) ) ;
854+ } else {
855+ let mut last = Vec :: new ( ) ;
856+ last. push ( ( last_occur. or ( Some ( Occur :: Must ) ) , last_ast) ) ;
857+ clauses. push ( last) ;
858+ }
859+ }
860+ Some ( BinaryOperand :: Or ) => {
861+ clauses. push ( vec ! [ ( last_occur. or( Some ( Occur :: Should ) ) , last_ast) ] ) ;
862+ }
863+ None => clauses. push ( vec ! [ ( last_occur, last_ast) ] ) ,
800864 }
801865
802- if leafs. iter ( ) . all ( |( _, occur, _) | occur. is_none ( ) ) {
803- let first = leafs. remove ( 0 ) . 2 ;
804- let errors = if leafs. iter ( ) . any ( |( operand, _, _) | operand. is_none ( ) ) {
805- vec ! [ LenientErrorInternal {
806- pos: 0 , // we don't really know the position
807- message: "binary expression with missing binary operator" . to_string( ) ,
808- } ]
866+ if clauses. len ( ) == 1 {
867+ let mut clause = clauses. pop ( ) . unwrap ( ) ;
868+ if clause. len ( ) == 1 && clause[ 0 ] . 0 != Some ( Occur :: MustNot ) {
869+ ( clause. pop ( ) . unwrap ( ) . 1 , err)
809870 } else {
810- Vec :: new ( )
811- } ;
812- let rest = leafs
813- . into_iter ( )
814- . map ( |( operand, _, ast) | ( operand. unwrap_or ( BinaryOperand :: Or ) , ast) )
815- . collect ( ) ;
816- return ( aggregate_binary_expressions ( first, rest) , errors) ;
817- }
871+ ( UserInputAst :: Clause ( clause) , err)
872+ }
873+ } else {
874+ let mut final_clauses: Vec < ( Option < Occur > , UserInputAst ) > = Vec :: new ( ) ;
875+ for mut sub_clauses in clauses {
876+ if sub_clauses. len ( ) == 1 {
877+ final_clauses. push ( sub_clauses. pop ( ) . unwrap ( ) ) ;
878+ } else {
879+ final_clauses. push ( ( Some ( Occur :: Should ) , UserInputAst :: Clause ( sub_clauses) ) ) ;
880+ }
881+ }
818882
819- // TODO a mix of both isn't that easy, will do later
820- todo ! ( )
883+ ( UserInputAst :: Clause ( final_clauses ) , err )
884+ }
821885}
822886
823887fn operand_leaf ( i : & str ) -> IResult < & str , ( BinaryOperand , UserInputAst ) > {
@@ -1048,12 +1112,21 @@ mod test {
10481112 test_parse_query_to_ast_helper ( "a OR b" , "(?a ?b)" ) ;
10491113 test_parse_query_to_ast_helper ( "a OR b AND c" , "(?a ?(+b +c))" ) ;
10501114 test_parse_query_to_ast_helper ( "a AND b AND c" , "(+a +b +c)" ) ;
1051- test_is_parse_err ( "a OR b aaa" , "(?a ?b ?aaa)" ) ;
1052- test_is_parse_err ( "a AND b aaa" , "(?(+a +b) ?aaa)" ) ;
1053- test_is_parse_err ( "aaa a OR b " , "(?aaa ?a ?b)" ) ;
1054- test_is_parse_err ( "aaa ccc a OR b " , "(?aaa ?ccc ?a ?b)" ) ;
1055- test_is_parse_err ( "aaa a AND b " , "(?aaa ?(+a +b))" ) ;
1056- test_is_parse_err ( "aaa ccc a AND b " , "(?aaa ?ccc ?(+a +b))" ) ;
1115+ test_is_parse_err ( "a OR b aaa" , "(?a ?b *aaa)" ) ;
1116+ test_is_parse_err ( "a AND b aaa" , "(?(+a +b) *aaa)" ) ;
1117+ test_is_parse_err ( "aaa a OR b " , "(*aaa ?a ?b)" ) ;
1118+ test_is_parse_err ( "aaa ccc a OR b " , "(*aaa *ccc ?a ?b)" ) ;
1119+ test_is_parse_err ( "aaa a AND b " , "(*aaa ?(+a +b))" ) ;
1120+ test_is_parse_err ( "aaa ccc a AND b " , "(*aaa *ccc ?(+a +b))" ) ;
1121+ }
1122+
1123+ #[ test]
1124+ fn test_parse_mixed_bool_occur ( ) {
1125+ test_is_parse_err ( "a OR b +aaa" , "(?a ?b +aaa)" ) ;
1126+ test_is_parse_err ( "a AND b -aaa" , "(?(+a +b) -aaa)" ) ;
1127+ test_is_parse_err ( "+a OR +b aaa" , "(+a +b *aaa)" ) ;
1128+ test_is_parse_err ( "-a AND -b aaa" , "(?(-a -b) *aaa)" ) ;
1129+ test_is_parse_err ( "-aaa +ccc -a OR b " , "(-aaa +ccc -a ?b)" ) ;
10571130 }
10581131
10591132 #[ test]
0 commit comments