anchor.diff:  -spec parse(parser(A), tokens()) -> {ok, A} | {error, term()}.
   parse(P, S) ->
     case parse1(apply_p(P, fun(X) -> {return_plus, X, {fail, no_error}} end), S) of
  -    {[], {Pos, Err}} -> {error, {Pos, parse_error, lists:flatten(Err)}};
  +    {[], {Pos, Err}} -> {error, {Pos, parse_error, flatten_error(Err)}};
       {[A], _}         -> {ok, A};
       {As, _}          -> {error, {{1, 1}, ambiguous_parse, As}}
     end.
  +
  +-spec flatten_error(iolist() | no_error) -> string().
  +flatten_error(no_error) -> "Unspecified error";
  +flatten_error(Err)      -> lists:flatten(Err).
   
   %% -- Derived combinators ----------------------------------------------------
   
  
positive.code:                     %%            y + y)(4)
                      case maps:get(vclose, Map, '$not_found') of
                          '$not_found' ->
                              {Acc, mk_error(Ts, io_lib:format("Unexpected token '~s'.", [tag(T)]))};
                          F ->
                              VClose = {vclose, pos(T)},
                              Ts2    = pop_layout(VClose, Ts#ts{ last = VClose }),
  
negative.code: end_pos({L, _}) -> {L + 1, 1}.
  
  %% Combine two error messages. Discard no_error's otherwise pick the first error.
  add_error(no_error, Err)      -> Err;
  add_error({_, no_error}, Err) -> Err;
  add_error(Err, no_error)      -> Err;
  add_error(Err, {_, no_error}) -> Err;
  add_error(Err, _Err1)         -> Err.
  
  %% For some unfathomable reason the maps module does not have a merge_with function.
  -spec merge_with(fun((term(), term()) -> term()), map(), map()) -> map().
  