Parsing text using a formal grammar: SWIPL Example

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).