anchor.diff:          {[], NewCtx3},
           Tos),
       NewCtx5 = Fun(Opts, NewCtx4),
  +    NewCtx6 = case FType of
  +        top_down -> NewCtx5;
  +        bottom_up -> Fun(ST, NewCtx5)
  +    end,
       {"revoke "
        ++ string:join(ObjsStr, ",") ++ " "
        ++ if On =/= <<"">> -> atom_to_list(OnTyp) ++ " " ++ binary_to_list(On) ++ " "; true -> "" end
        ++ if length(Tos) > 0 -> "from " ++ string:join(TosStr, ",") ++ " "; true -> "" end
        ++ atom_to_list(Opts)
  -    , NewCtx5};
  +    , NewCtx6};
   
   %--------------------------------------------------------------------
   % component matching patterns
   %
   
   % Empty list or tuples
  -foldi(X, Fun, Ctx) when is_function(Fun, 2) andalso (X =:= {} orelse X =:= []) -> {"", Ctx};
  +foldi(_FType, X, Fun, Ctx) when is_function(Fun, 2) andalso (X =:= {} orelse X =:= []) -> {"", Ctx};
   
   % All option and optionlist and its variants
  -foldi({'identified globally', E} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  -    {IdStr, NewCtx1} = foldi(E, Fun, NewCtx),
  +foldi(FType, {'identified globally', E} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
  +    {IdStr, NewCtx1} = foldi(FType, E, Fun, NewCtx),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {" identified globally " ++ IdStr
  -    , NewCtx1};
  -foldi({'identified extern', E} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  -    {IdStr, NewCtx1} = foldi(E, Fun, NewCtx),
  +    , NewCtx2};
  +foldi(FType, {'identified extern', E} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
  +    {IdStr, NewCtx1} = foldi(FType, E, Fun, NewCtx),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {" identified externally " ++ IdStr
  -    , NewCtx1};
  -foldi({'identified by', Pswd} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +    , NewCtx2};
  +foldi(FType, {'identified by', Pswd} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       NewCtx1 = Fun(Pswd, NewCtx),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {" identified by " ++ binary_to_list(Pswd)
  -    , NewCtx1};
  -foldi([{'scope', S}|Opts] = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +    , NewCtx2};
  +foldi(FType, [{'scope', S}|Opts] = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       NewCtx1 = Fun(S, NewCtx),
  -    {OptsStr, NewCtx2} = foldi(Opts, Fun, NewCtx1),
  +    {OptsStr, NewCtx2} = foldi(FType, Opts, Fun, NewCtx1),
  +    NewCtx3 = case FType of
  +        top_down -> NewCtx2;
  +        bottom_up -> Fun(ST, NewCtx2)
  +    end,
       {lists:flatten([" ", atom_to_list(S), " ", OptsStr])
  -    , NewCtx2};
  -foldi([{'type', T}|Opts] = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +    , NewCtx3};
  +foldi(FType, [{'type', T}|Opts] = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       NewCtx1 = Fun(T, NewCtx),
  -    {OptsStr, NewCtx2} = foldi(Opts, Fun, NewCtx1),
  +    {OptsStr, NewCtx2} = foldi(FType, Opts, Fun, NewCtx1),
  +    NewCtx3 = case FType of
  +        top_down -> NewCtx2;
  +        bottom_up -> Fun(ST, NewCtx2)
  +    end,
       {lists:flatten([" ", atom_to_list(T), " ", OptsStr])
  -    , NewCtx2};
  -foldi([{'limited', Q, T}|O] = ST, Fun, Ctx)
  +    , NewCtx3};
  +foldi(FType, [{'limited', Q, T}|O] = ST, Fun, Ctx)
    when is_binary(Q), is_binary(T), is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       NewCtx1 = Fun(Q, NewCtx),
       NewCtx2 = Fun(T, NewCtx1),
  -    {Os, NewCtx3} = foldi(O, Fun, NewCtx2),
  +    {Os, NewCtx3} = foldi(FType, O, Fun, NewCtx2),
  +    NewCtx4 = case FType of
  +        top_down -> NewCtx3;
  +        bottom_up -> Fun(ST, NewCtx3)
  +    end,
       {lists:flatten(["quota ", binary_to_list(Q), " on ", binary_to_list(T), " ", Os])
  -    , NewCtx3};
  -foldi([cascade|Opts] = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  -    {OptsStr, NewCtx1} = foldi(Opts, Fun, NewCtx),
  +    , NewCtx4};
  +foldi(FType, [cascade|Opts] = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
  +    {OptsStr, NewCtx1} = foldi(FType, Opts, Fun, NewCtx),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {lists:flatten([" cascade ", OptsStr])
  -    , NewCtx1};
  -foldi([{Tok, T}|Opts] = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  -    if is_binary(T) andalso (Tok =:= 'default tablespace'
  +    , NewCtx2};
  +foldi(FType, [{Tok, T}|Opts] = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
  +    {Str, NewCtx4} = if is_binary(T) andalso (Tok =:= 'default tablespace'
                                orelse Tok =:= 'temporary tablespace'
                                orelse Tok =:= 'profile') ->
               NewCtx1 = Fun(Tok, NewCtx),
               NewCtx2 = Fun(T, NewCtx1),
  -            {OptsStr, NewCtx3} = foldi(Opts, Fun, NewCtx2),
  +            {OptsStr, NewCtx3} = foldi(FType, Opts, Fun, NewCtx2),
               {lists:flatten([atom_to_list(Tok), " ", binary_to_list(T), " ", OptsStr])
               , NewCtx3};
           true ->
               case {Tok, T} of
  -                {'password', 'expire'}                  -> {"password expire ", Fun({Tok, T}, NewCtx)};
  -                {'account', 'lock'}                     -> {"account lock ", Fun({Tok, T}, NewCtx)};
  -                {'account', 'unlock'}                   -> {"account unlock ", Fun({Tok, T}, NewCtx)};
  +                {'password', 'expire'}  -> {"password expire ", Fun({Tok, T}, NewCtx)};
  +                {'account', 'lock'}     -> {"account lock ", Fun({Tok, T}, NewCtx)};
  +                {'account', 'unlock'}   -> {"account unlock ", Fun({Tok, T}, NewCtx)};
                   {'unlimited on', T} when is_binary(T)   ->
                       {lists:flatten(["quota unlimited on ", binary_to_list(T)])
                       , Fun({Tok, T}, NewCtx)};
  -                {'quotas', Qs}                          -> foldi(Qs, Fun, NewCtx);
  -                _                                       -> foldi({Tok, T}, Fun, NewCtx)
  +                {'quotas', Qs} -> foldi(FType, Qs, Fun, NewCtx);
  +                _ -> foldi(FType, {Tok, T}, Fun, NewCtx)
               end
  -    end;
  -foldi({'default', Def} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  -    {DefStr, NewCtx1} = foldi(Def, Fun, NewCtx),
  +    end,
  +    NewCtx5 = case FType of
  +        top_down -> NewCtx4;
  +        bottom_up -> Fun(ST, NewCtx4)
  +    end,
  +    {Str, NewCtx5};
  +foldi(FType, {'default', Def} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
  +    {DefStr, NewCtx1} = foldi(FType, Def, Fun, NewCtx),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {lists:flatten([" default ", 
           case Def of
               Def when is_binary(Def) -> binary_to_list(Def);
               Def -> DefStr
           end, "\n "])
  -    , NewCtx1};
  +    , NewCtx2};
   
   % select sub-part patterns
  -foldi({hints, Hints} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +foldi(FType, {hints, Hints} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       Size = byte_size(Hints),
       NewCtx1 = Fun(Hints, NewCtx),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {if Size > 0 -> binary_to_list(Hints);
        true        -> ""
        end
  -    , NewCtx1};
  -foldi({opt, Opt} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +    , NewCtx2};
  +foldi(FType, {opt, Opt} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       Size = byte_size(Opt),
       NewCtx1 = Fun(Opt, NewCtx),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {if Size > 0 -> binary_to_list(Opt) ++ " ";
        true        -> ""
        end
  -    , NewCtx1};
  -foldi({fields, Fields} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +    , NewCtx2};
  +foldi(FType, {fields, Fields} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       {FieldsStr, NewCtx1} = lists:foldl(fun(F, {Acc, CtxAcc}) ->
               case F of
                   F when is_binary(F) -> {Acc++[binary_to_list(F)], Fun(F, CtxAcc)};
                   {'select', _} = F   ->
  -                    {SubAcc, CtxAcc1} = foldi(F, Fun, CtxAcc),
  +                    {SubAcc, CtxAcc1} = foldi(FType, F, Fun, CtxAcc),
                       {Acc++[lists:flatten(["(", SubAcc, ")"])], CtxAcc1};
                   Other ->
  -                    {SubAcc, CtxAcc1} = foldi(Other, Fun, CtxAcc),
  +                    {SubAcc, CtxAcc1} = foldi(FType, Other, Fun, CtxAcc),
                       {Acc++[SubAcc], CtxAcc1}
               end
           end,
           {[], NewCtx},
           Fields),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {string:join(FieldsStr, ", ")
  -    , NewCtx1};
  -foldi({into, Into} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +    , NewCtx2};
  +foldi(FType, {into, Into} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       {IntoStr, NewCtx1} = lists:foldl(fun(I, {Acc, CtxAcc}) ->
               {Acc++[binary_to_list(I)], Fun(I, CtxAcc)}
           end,
           {[], NewCtx},
           Into),
  +    NewCtx2 = case FType of
  +        top_down -> NewCtx1;
  +        bottom_up -> Fun(ST, NewCtx1)
  +    end,
       {string:join(IntoStr, ", ") ++ " "
  -    , NewCtx1};
  -foldi({from, Forms} = ST, Fun, Ctx)
  - when is_function(Fun,2) ->
  -    NewCtx = Fun(ST, Ctx),
  +    , NewCtx2};
  +foldi(FType, {from, Forms} = ST, Fun, Ctx)
  + when is_function(Fun,2) ->
  +    NewCtx = case FType of
  +        top_down -> Fun(ST, Ctx);
  +        bottom_up -> Ctx
  +    end,
       {FormStr, NewCtx1} = case Forms of
           Forms when is_list(Forms) ->
               {FrmStr, NewCtx2} = lists:foldl(fun(F, {Acc, CtxAcc}) ->
                       case F of
                           F when is_binary(F) -> {Acc++[binary_to_list(F)], Fun(F,CtxAcc)};
                           {'select', _} = F   ->
  -                            {FoldFStr, CtxAcc1} = foldi(F, Fun, Ctx),
  +                            {FoldFStr, CtxAcc1} = foldi(FType, F, Fun, Ctx),
                               {lists:flatten(["(", FoldFStr, ")"])
                               , CtxAcc1};
                           Other               ->
  -                            {SubAcc, CtxAcc1} = foldi(Other, Fun, Ctx),
  +                            {SubAcc, CtxAcc1} = foldi(FType, Other, Fun, Ctx),
                               {Acc++[SubAcc], CtxAcc1}
                       end
                   end,
  
positive.code:                     CtxAcc1 = Fun(C, CtxAcc),
                      CtxAcc2 = Fun(T, CtxAcc1),
                      CtxAcc3 = Fun(N, CtxAcc2),
                      {SubAcc, CtxAcc4} = foldi(O, Fun, CtxAcc3),
                      {Acc ++ [lists:flatten([binary_to_list(C), " ", atom_to_list(T), "(", N, ") ", SubAcc])]
                      , CtxAcc4};
                  {C, {T, N, N1}, O} when is_binary(C) ->
  
negative.code:         end,
          {[], NewCtx},
          OrderBy),
      NewCtx2 = case FType of
          top_down -> NewCtx1;
          bottom_up -> Fun(ST, NewCtx1)
      end,
      {if Size > 0 ->
          " order by " ++ string:join(OrderByStr, ", ")
          ++ " ";
          true -> ""
       end
      , NewCtx2};
  
  % joins
  foldi(FType, {JoinType, Tab} = ST, Fun, Ctx)
   when (is_function(Fun,2) andalso (
          (JoinType =:= cross_join) orelse
          (JoinType =:= natural_join) orelse
          (JoinType =:= natural_inner_join)
       )) ->
      NewCtx = case FType of
          top_down -> Fun(ST, Ctx);
          bottom_up -> Ctx
      end,
      NewCtx1 = Fun(JoinType, NewCtx),
      {TabStr, NewCtx2} = foldi(FType, Tab, Fun, NewCtx1),
      NewCtx3 = case FType of
          top_down -> NewCtx2;
          bottom_up -> Fun(ST, NewCtx2)
      end,
      {case JoinType of
          cross_join          -> " cross join ";
          natural_join        -> " natural join ";
          natural_inner_join  -> " natural inner join "
       end ++ TabStr
      , NewCtx3};
  foldi(FType, {{JoinType,OptPartition,OptNatural},Tab,OptPartition1,OnOrUsing} = ST, Fun, Ctx)
   when (is_function(Fun,2) andalso (
          (JoinType =:= full) orelse
          (JoinType =:= left) orelse
  