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:                        value(<<"\"Hello\t World\"">>, index()))).
  
  ident_test() ->
      ?memo(?assertMatch({{ident, "true", {1, _}}, <<>>, _}, value(<<"true">>, index()))),
      ?memo(?assertMatch({{ident, "false", {1, _}},  <<>>, _},value(<<"false">>, index()))),
      ?memo(?assertMatch({{symbol, "keyword", {1, _}}, <<>>, _},
                         value(<<":keyword">>, index()))),
      ?memo(?assertMatch({{ident, "*foo*", {1, _}}, <<>>, _}, value(<<"*foo*">>, index()))),
      ?memo(?assertMatch({{ident, "foo-bar", {1, _}}, <<>>, _}, value(<<"foo-bar">>, index()))),
  
negative.code: intermediate_parse(Input) when is_binary(Input) ->
      intermediate_parse(Input, new_index()).
  
  -spec parse(binary()) ->
                     {[{Type::atom(), Value::term(), index()}],
                      jxa_annots:annotations()}.
  parse(Input) ->
      do_parse(jxa_path:new(),
               jxa_annot:new(), [], Input, new_index()).
  
  %%=============================================================================
  %% Internal Functions
  %%=============================================================================
  -spec do_parse(jxa_path:path(), jxa_annots:annotations(), [term()], binary(),
                 index()) ->
                        {[{Type::atom(), Value::term(), index()}],
                         jxa_annots:annotations()}.
  do_parse(_Path0, Annots, Ast, <<>>, _Idx) ->
      {Annots, lists:reverse(Ast)};
  do_parse(Path0, Annots0, Ast, Input, Idx0) ->
      case intermediate_parse(Input, Idx0) of
          {fail,{expected, Expected, Idx}} ->
              ?JXA_THROW({invalid_form, Expected, Idx});
          {IntermediateAst, Rest, Idx1} ->
              {Annots1, FinalAST} =
                  transform_ast(jxa_path:add(Path0), Annots0, IntermediateAst),
              do_parse(jxa_path:incr(Path0), Annots1, [FinalAST | Ast],
                       Rest, Idx1)
  
      end.
  
  -spec transform_ast(jxa_path:state(), 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 == ident ->
      AIdent = list_to_atom(Ident),
      {jxa_annot:add(jxa_path:path(Path0), {Type, Idx}, Annotations),
       AIdent};
  transform_ast(Path0, Annotations, {char, Char, Idx}) ->
      {jxa_annot:add(jxa_path:path(Path0), {char, Idx}, Annotations), Char};
  transform_ast(Path0, Annotations, {string, List, Idx}) ->
      {jxa_annot:add(jxa_path:path(Path0), {string, Idx},
                     Annotations), List};
  transform_ast(Path0, Annotations, {float, Float, Idx}) ->
      {jxa_annot:add(jxa_path:path(Path0), {float, Idx},
                     Annotations), Float};
  transform_ast(Path0, Annotations, {integer, Integer, Idx}) ->
      {jxa_annot:add(jxa_path:path(Path0),
                     {integer, Idx}, Annotations), Integer};
  transform_ast(Path0, Annotations0, {quote, Quote, Idx}) ->
      {Annotations1, Quoted} =
          transform_ast(jxa_path:add(Path0), Annotations0, Quote),
      {jxa_annot:add(jxa_path:path(Path0),
                     {quote, Idx}, Annotations1), [quote, Quoted]};
  transform_ast(Path0, Annotations0, {Type, List, Idx})
    when Type == vector; Type == list ->
         {_, Annotations3, TransformList} =
          lists:foldl(fun(El, {Path1, Annotations1, Elements}) ->
                              {Annotations2, Transformed} =
                                  transform_ast(jxa_path:add(Path1),
                                                Annotations1, El),
                              Path2 = jxa_path:incr(Path1),
                              {Path2, Annotations2, [Transformed | Elements]}
                      end, {Path0, Annotations0, []}, List),
      {jxa_annot:add(jxa_path:path(Path0), {Type, Idx}, Annotations3),
       lists:reverse(TransformList)}.
  
  -spec intermediate_parse(string(), index()) -> intermediate_ast() | fail.
  