anchor.diff:  %% for testing purposes
   -export([intermediate_parse/1]).
   
  +-include_lib("joxa/include/joxa.hrl").
  +
   -export_type([ast/0, type_desc/0, annotation/0]).
  -
   
   %%=============================================================================
   %% Types
  
positive.code: intermediate_parse(Input) when is_binary(Input) ->
      intermediate_parse(Input, new_index()).
  
  -spec parse(binary()) -> ast().
  parse(Input) ->
      {IntermediateAst, _, _} = intermediate_parse(Input),
      transform_ast(jxa_annot:new_path(), jxa_annot:new(), IntermediateAst).
  
  %%=============================================================================
  %% Internal Functions
  %%=============================================================================
  -spec transform_ast(jxa_annot:path(), jxa_annot:annotations(), fail | intermediate_ast()) ->
                             {jxa_annot:annotations(), raw_type()}.
  transform_ast(_, _, fail) ->
     erlang:throw(fail);
  transform_ast(Path0, Annotations, {Type, Ident, Idx})
    when Type == symbol; Type == ident ->
      AIdent = list_to_atom(Ident),
      {jxa_annot:add_annot(Path0, {Type, Idx}, Annotations),
       AIdent};
  transform_ast(Path0, Annotations, {char, Char, Idx}) ->
      {jxa_annot:add_annot(Path0, {char, Idx}, Annotations), Char};
  transform_ast(Path0, Annotations, {string, List, Idx}) ->
      {jxa_annot:add_annot(Path0, {string, Idx}, Annotations), List};
  transform_ast(Path0, Annotations, {float, Float, Idx}) ->
      {jxa_annot:add_annot(Path0, {float, Idx}, Annotations), Float};
  transform_ast(Path0, Annotations, {integer, Integer, Idx}) ->
      {jxa_annot:add_annot(Path0, {integer, Idx}, Annotations), Integer};
  transform_ast(Path0, Annotations0, {Type, List, Idx})
    when Type == vector; Type == list ->
         {_, Annotations3, TransformList} =
          lists:foldl(fun(El, {Count0, Annotations1, Elements}) ->
                              Count1 = Count0 + 1,
                              {Annotations2, Transformed} =
                                  transform_ast(jxa_annot:add(Count1, Path0), Annotations1, El),
                              {Count1, Annotations2, [Transformed | Elements]}
                      end, {0, Annotations0, []}, List),
      {jxa_annot:add_annot(Path0, {Type, Idx}, Annotations3),
       lists:reverse(TransformList)}.
  
  -spec intermediate_parse(string(), index()) -> intermediate_ast() | fail.
  
negative.code: parse_test() ->
      Value = list_to_binary("(io:format \n \"~p\" \n '(\n(foo \n bar \n baz 33)))"),
      {Annots, Result} =  parse(Value),
      ?assertMatch(['io:format', "~p",
                    [quote, [[foo, bar, baz, 33]]]], Result),
  
      ?assertMatch({ident, {1, 2}},
                   jxa_annot:get([1], Annots)),
      ?assertMatch({string, {2, 2}},
                   jxa_annot:get([2], Annots)),
      ?assertMatch({quote, {3, 2}},
                   jxa_annot:get([3], Annots)),
      ?assertMatch({ident, {4, 2}},
                   jxa_annot:get([1, 1, 1, 3], Annots)).
  
  -endif.
  