anchor.diff:  -include_lib("proper/include/proper.hrl").
   
   %% API
  --export([from_str/2]).
  --export([dnf/1]).
   -export([clauses/1]).
  --export([depth/1]).
   
   %% Record declarations
   -record(and_q,  {l_sub :: q(), r_sub :: q()}).
   -record(or_q,   {l_sub :: q(), r_sub :: q()}).
  --record(not_q,  {sub  :: q()}).
  --record(term_q, {term :: utf8_str()}).
  +-record(not_q,  {sub   :: q()}).
  +-record(term_q, {kw    :: utf8_str()}).
   
   %% Type definitions
   -type q() :: {and_q,  q(), q()} |
  
positive.code: scan(<<>>) ->
      [{'$end',1}].
  
  tree_to_query({and_q,SubTreeL,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) ->
      {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) ->
      {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},0}.
  
  dnf(Q, 1) ->
      Q;
  
negative.code: %% API
  %%----------------------------------------------------------------------------
  
  clauses(Str) ->
      [flatten(X) || X <- and_subs(dnf(from_str(Str)))].
  
  %%----------------------------------------------------------------------------
  %% Internal functions
  %%----------------------------------------------------------------------------
  
  from_str(Str) ->
      {ok,ParseTree} = dk_q_parser:parse(scan(Str)),
      tree_to_query(ParseTree).
  
  scan(<<C/utf8,Rest/bytes>>) ->
      case C of
  