A simple reader, without negative numbers, is a few lines of DCG.
?- reader(X,1200,[-,fx,x0,-,x1,yf,-,x2],[]), write_canonical(X), nl.
-(-(-(fx(x0)), yf(x1)), x2)
X = -fx x0-x1 yf-x2.
Here is the source code, unfortunately only for ISO core standard:
% reader(-Term, +Integer, +List, -List)
reader(X, L) -->
reader_primary(Z, L, K), reader_secondary(Z, X, L, K).
% reader_primary(-Term, +Integer, -Integer, +List, -List)
reader_primary(H, L, R) --> [A], {current_op(R, M, A), is_prefix(M, E)}, !,
{L < R -> throw(error(syntax_error(operator_clash),_)); true},
{T is R-E}, reader(Z, T), {H =.. [A,Z]}.
reader_primary(X, _, 0) --> [X].
% reader_secondary(+Term, -Term, +Integer, +Integer, +List, -List)
reader_secondary(H, X, L, C) --> [A],
{current_op(R, M, A), is_infix(M, D, E), L >= R}, !,
{R-D < C -> throw(error(syntax_error(operator_clash),_)); true},
{T is R-E}, reader(Z, T),
{J =.. [A,H,Z]},
reader_secondary(J, X, L, R).
reader_secondary(H, X, L, C) --> [A],
{current_op(R, M, A), is_postfix(M, D), L >= R}, !,
{R-D < C -> throw(error(syntax_error(operator_clash),_)); true},
{J =.. [A,H]},
reader_secondary(J, X, L, R).
reader_secondary(H, H, _, _) --> [].
% is_infix(-Atom, -Integer, -Imteger)
is_infix(xfx, 1, 1).
is_infix(yfx, 0, 1).
is_infix(xfy, 1, 0).
% is_prefix(-Atom, -Integer)
is_prefix(fx, 1).
is_prefix(fy, 0).
% is_postfix(-Atom, -Integer)
is_postfix(xf, 1).
is_postfix(yf, 0).