anchor.diff:      [{'$end',1}].
   
   tree_to_query({and_q,SubTreeL,SubTreeR}, Lang) ->
  -    #and_q{subs = [tree_to_query(SubTreeL, Lang),
  -                   tree_to_query(SubTreeR, Lang)]};
  +    {L, DepthL} = tree_to_query(SubTreeL, Lang),
  +    {R, DepthR} = tree_to_query(SubTreeR, Lang),
  +    {#and_q{l_sub = L,r_sub = R},max(DepthL, DepthR)+1};
   tree_to_query({or_q,SubTreeL,SubTreeR}, Lang) ->
  -    #or_q{subs = [tree_to_query(SubTreeL, Lang),
  -                  tree_to_query(SubTreeR, Lang)]};
  +    {L, DepthL} = tree_to_query(SubTreeL, Lang),
  +    {R, DepthR} = tree_to_query(SubTreeR, Lang),
  +    {#or_q{l_sub = L,r_sub = R},max(DepthL, DepthR)+1};
   tree_to_query({not_q,SubTree},Lang) ->
  -    #not_q{sub = tree_to_query(SubTree, Lang)};
  +    {Sub,Depth} = tree_to_query(SubTree, Lang),
  +    {#not_q{sub = Sub},Depth+1};
   tree_to_query({term_q,{string,Keyword,_}}, Lang) ->
       [Term|_] = dk_pp:terms(Keyword, Lang),
  -    #term_q{term = Term}.
  +    {#term_q{term = Term},0}.
   
  -mv_not_in(#and_q{subs = Qs}) ->
  -    #and_q{subs = [mv_not_in(Q) || Q <- Qs]};
  -mv_not_in(#or_q{subs = Qs}) ->
  -    #or_q{subs = [mv_not_in(Q) || Q <- Qs]};
  -mv_not_in(#not_q{sub = #and_q{subs = Qs}}) ->
  -    #or_q{subs = [mv_not_in(#not_q{sub = Q}) || Q <- Qs]};
  -mv_not_in(#not_q{sub = #or_q{subs = Qs}}) ->
  -    #and_q{subs = [mv_not_in(#not_q{sub = Q}) || Q <- Qs]};
  -mv_not_in(#not_q{sub = #not_q{sub = Q}}) ->
  -    mv_not_in(Q);
  -mv_not_in(Q = #not_q{sub = #term_q{}}) ->
  +dnf(Q, 1) ->
       Q;
  -mv_not_in(Q = #term_q{}) ->
  +dnf(Q, D) ->    
  +    dnf(mv_and(Q), D-1).
  +
  +mv_not({T,L,R}) ->
  +    {T,mv_not(L),mv_not(R)};
  +mv_not({not_q,{and_q,L,R}}) ->
  +    {or_q,mv_not({not_q,L}),mv_not({not_q,R})};
  +mv_not({not_q,{or_q,L,R}}) ->
  +    {and_q,mv_not({not_q,L}),mv_not({not_q,R})};
  +mv_not({not_q,{not_q,Q}}) ->
  +    mv_not(Q);
  +mv_not(Q) ->
       Q.
   
  -denest(#and_q{subs = Qs}) ->
  -    Rs = lists:flatten(lists:map(fun denest/1, Qs)),
  -    {Ands,Rest} = lists:partition(fun (R) -> is_record(R, and_q) end, Rs),
  -    #and_q{subs = lists:flatmap(fun subs/1, Ands) ++ Rest};
  -denest(#or_q{subs = Qs}) ->
  -    Rs = lists:map(fun denest/1, Qs),
  -    {Ors,Rest} = lists:partition(fun (R) -> is_record(R, or_q) end, Rs),
  -    #or_q{subs = lists:flatmap(fun subs/1, Ors) ++ Rest};
  -denest(#not_q{sub = Q}) ->
  -    #not_q{sub = denest(Q)};
  -denest(Q = #term_q{}) ->
  +mv_and({and_q,Q,{or_q,L,R}}) ->
  +    {or_q,mv_and({and_q,Q,mv_and(L)}),mv_and({and_q,Q,mv_and(R)})};
  +mv_and({and_q,{or_q,L,R},Q}) ->
  +    {or_q,mv_and({and_q,Q,mv_and(L)}),mv_and({and_q,Q,mv_and(R)})};
  +mv_and({T,L,R}) ->
  +    {T,mv_and(L),mv_and(R)};
  +mv_and(Q) ->
       Q.
  -
  -distr_and(And = #and_q{subs = Qs}) ->
  -    case lists:partition(fun (Q) -> is_record(Q, or_q) end, Qs) of
  -        {[],_Rest} ->
  -            And;
  -        {Ors,Rest} ->
  -            #or_q{subs = [distr_and(#and_q{subs = Rs})
  -                          || Rs <- product([Q#or_q.subs || Q <-Ors],
  -                                           [Rest])]}
  -    end;
  -distr_and(#or_q{subs = Qs}) ->
  -    #or_q{subs = [distr_and(Q) || Q <- Qs]};
  -distr_and(Q = #not_q{}) ->
  -    Q;
  -distr_and(Q = #term_q{}) ->
  -    Q.
  -
  -subs(#and_q{subs = Qs}) ->
  -    Qs;
  -subs(#or_q{subs = Qs}) ->
  -    Qs.
  -
  -product([], Acc) ->
  -    Acc;
  -product([L|Rest], Acc) ->
  -    product(Rest, [[H|T] || H <- L, T <- Acc]).
   
   %%----------------------------------------------------------------------------
   %% PropErties
   %%----------------------------------------------------------------------------
   
  -prop_not_nested() ->
  -    ?FORALL(X, q(), not nested(denest(X))).
  +prop_all_not_element() ->
  +    ?FORALL(X, q(), not_element(dnf({X,depth(X)}))).
   
  -nested(#and_q{subs = Qs}) ->
  -    case lists:partition(fun (Q) -> is_record(Q, and_q) end, Qs) of
  -        {[],_} -> lists:any(fun nested/1, Qs);
  -        _      -> true
  -    end;
  -nested(#or_q{subs = Qs}) ->
  -    case lists:partition(fun (Q) -> is_record(Q, or_q) end, Qs) of
  -        {[],_} -> lists:any(fun nested/1, Qs);
  -        _      -> true
  -    end;
  -nested(#not_q{sub = #term_q{}}) ->
  +not_element({_, L, R}) ->
  +    not_element(L) and not_element(R);
  +not_element(#not_q{sub = #term_q{}}) ->
  +    true;
  +not_element(#not_q{}) ->
       false;
  -nested(#not_q{sub = Q}) ->
  -    nested(Q);
  -nested(#term_q{}) ->
  -    false.
  -
  -prop_all_nots_elementary() ->
  -    ?FORALL(X, q(), nots_elementary(mv_not_in(X))).
  -
  -nots_elementary(#and_q{subs = Qs}) ->
  -    lists:all(fun nots_elementary/1, Qs);
  -nots_elementary(#or_q{subs = Qs}) ->
  -    lists:all(fun nots_elementary/1, Qs);
  -nots_elementary(#not_q{sub = #term_q{}}) ->
  -    true;
  -nots_elementary(#not_q{}) ->
  -    false;
  -nots_elementary(#term_q{}) ->
  +not_element(#term_q{}) ->
       true.
   
  -prop_dnf() ->
  -    ?FORALL(X,
  -            ?SUCHTHAT(X, q(), not single_subs(X)),
  -            case dnf(X) of
  -                #and_q{subs = Qs} ->
  -                    lists:all(fun elementary/1, Qs);
  -                #or_q{subs = Qs}  ->
  -                    Fun1 = fun (Q) -> is_record(Q, and_q) end,
  -                    {Ands,Rest} = lists:partition(Fun1, Qs),
  -                    Fun2 = fun (#and_q{subs = Rs}) ->
  -                                   lists:all(fun elementary/1, Rs)
  -                           end,
  -                    lists:all(Fun2, Ands) and
  -                        lists:all(fun elementary/1, Rest);
  -                #not_q{} ->
  -                    true;
  -                #term_q{} ->
  -                    true
  -            end).
  +depth({_,L,R}) ->
  +    max(depth(L),depth(R))+1;
  +depth({not_q,Q}) ->
  +    depth(Q)+1;
  +depth(_) ->
  +    0.
   
  -elementary(#term_q{}) ->
  -    true;
  -elementary(#not_q{}) ->
  -    true;
  -elementary(_) ->
  -    false.
  +prop_no_nested_or() ->
  +    ?FORALL(X, q(), not nested_or(dnf({X,depth(X)}))).
   
  -single_subs(#and_q{subs = Qs}) ->
  -    length(Qs) == 1 orelse
  -        lists:any(fun single_subs/1, [Q || Q <- Qs, not elementary(Q)]);
  -single_subs(#or_q{subs = Qs}) ->
  -    length(Qs) == 1 orelse 
  -        lists:any(fun single_subs/1, [Q || Q <- Qs, not elementary(Q)]);
  -single_subs(#not_q{sub = Q}) ->
  -    single_subs(Q);
  -single_subs(#term_q{}) ->
  +nested_or({q,L,R}) ->
  +    (is_record(L, or_q) or is_record(R, or_q))
  +        orelse (nested_or(L) or nested_or(R));
  +nested_or({or_q,L,R}) ->
  +    nested_or(L) or nested_or(R);
  +nested_or({not_q,Q}) ->
  +    nested_or(Q);
  +nested_or(_) ->
       false.
   
   %% Local variables:
  
positive.code: -export([dnf/1]).
  
  %% Record declarations
  -record(and_q,  {subs :: [q(),...]}).
  -record(or_q,   {subs :: [q(),...]}).
  -record(not_q,  {sub  :: q()}).
  -record(term_q, {term :: utf8_str()}).
  
  %% Type definitions
  -type q() :: {and_q,  [q(),...]} |
               {or_q,   [q(),...]} |
               {not_q,  q()}       |
               {term_q, utf8_str()}.
  -type utf8_str() :: unicode:unicode_binary().
  
  
negative.code: %% API
  %%----------------------------------------------------------------------------
  
  from_str(Str, Lang) ->
      {ok,ParseTree} = dk_q_parser:parse(scan(Str)),
      tree_to_query(ParseTree, Lang).
  
  dnf({Q,0}) ->
      Q;
  dnf({Q,D}) ->
      dnf(mv_not(Q), D).
  
  %%----------------------------------------------------------------------------
  %% Internal functions
  