anchor.diff:  -type pos()    :: {integer(), integer()}.
   -type token()  :: {atom(), pos(), term()} | {atom(), pos()}.
   -type tokens() :: [token()].
  --type error()  :: {pos(), string()}.
  +-type error()  :: {pos(), string() | no_error}.
   
   -define(lazy(F),     {aeso_parse_lazy, F}).
   -define(fail(Err),   {aeso_parse_fail, Err}).
  
positive.code: current_pos(#ts{ last     = T })       -> end_pos(pos(T)).
  
  -spec mk_error(#ts{}, term()) -> error().
  mk_error(Ts, Err) -> {current_pos(Ts), Err}.
  
  %% Get the next token from a token stream. Inserts layout tokens if necessary.
  -spec next_token(#ts{}) -> false | {token(), #ts{}}.
  
negative.code: -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, 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 ----------------------------------------------------
  
  