anchor.diff:  not_element(#not_q{}) ->
       false.
   
  -depth({_,L,R}) ->
  +depth({and_q,L,R}) ->
  +    max(depth(L),depth(R))+1;
  +depth({or_q,L,R}) ->
       max(depth(L),depth(R))+1;
   depth({not_q,Q}) ->
       depth(Q)+1;
  
positive.code:                         dict:fetch(any, Dict);
                      _ ->
                          gb_sets:union(
                            [element(2,Y) || X <- ZoneIds,
                                             Y <- dict:find(X, Dict),
                                             Y /= error])
                  end
          end,
      DocIds =
          fun ({Keyword, ZoneIds}) ->
                  io:format("Keyword = ~p~n", [Keyword]),
                  io:format("ZoneIds = ~p~n", [ZoneIds]),
                  case dict:fetch(Keyword, Terms) of
                      stop_word -> gb_sets:empty();
                      Term -> DocIdsForZoneIds(ZoneIds, dict:fetch(Term, Data))
                  end
          end,
      Calculate = fun ({Keywords,NotKeywords}) ->
  
negative.code: -type q() :: {and_q,  q(), q()} |
               {or_q,   q(), q()} |
               {not_q,  q()     } |
               {term_q, string(), list(string())}.
  
  %%----------------------------------------------------------------------------
  %% API
  %%----------------------------------------------------------------------------
  
  -spec execute(atom(), doko_utf8:str()) -> gb_set().
  execute(IndexId, Str) ->
      %% parse and preprocess query
      Clauses = [partition(flatten(X))||X <- clauses(dnf(from_str(Str)))],
  