symm_op((+)).
symm_op((*)).

asymm_op((-)).
asymm_op((/)).

split(X,Xs,Ys) :-
    member(X,Xs),
    filter_first(X,Xs,Ys).

filter_first(X, [X|Xs], Xs).
filter_first(X, [Y|Xs], [Y|Ys]) :-
    dif(X,Y),
    filter_first(X,Xs,Ys).

expr([N], N).
expr([N1,N2|Ns], E) :-
    split(M,[N1,N2|Ns], Ms),
    expr(Ms,E0),
    symm_op(Op),
    E =.. [Op,M,E0].
expr([N1,N2|Ns], E) :-
    split(M,[N1,N2|Ns], Ms),
    expr(Ms,E0),
    asymm_op(Op),
    E =.. [Op,M,E0].
expr([N1,N2|Ns], E) :-
    split(M,[N1,N2|Ns], Ms),
    expr(Ms,E0),
    asymm_op(Op),
    E =.. [Op,E0,M].

