I probably should have let you work it out on your own but I remember struggling with these kinds of things so I figure it might be helpful to others.
Edit please see Wouter's comments about my solution: it does not work for non-commutative operations like subtraction and division.
First, I want to translate from postfix to infix because that seems like more fun to me. Also then I can just ask Prolog to evaluate it, I don't have to build a stack explicitly to do the evaluation. I consider this one of the miracles of Prolog, that you can manipulate arithmetic expressions like this without them collapsing into values.
In fact, since we just want to parse from right to left I'm just going to flip it around to a Polish notation list and parse that using the sequence itself as the stack.
postfix_to_infix(Postfix, Infix) :-
reverse(Postfix, Prefix),
prefix_to_infix(Prefix, Infix).
Converting from prefix to infix is not that bad, the trick is threading consumed list around, so we'll need another argument for that. Note that this kind of threading is exactly what DCGs do, so whenever I notice myself doing a lot of this I think "gee, I could probably do this easier with DCGs." On the other hand, of the two helper predicates only one does this threading explicitly, so it might not help that much. Exercise for the reader I suppose.
We're using univ =..
to build a Prolog term on the way out. Evaluation comes later.
prefix_to_infix(Seq, Expr) :-
prefix_to_infix(Seq, Expr, []).
% base case: peel off a number
prefix_to_infix([Val|Xs], Val, Xs) :- number(Val).
% inductive case
prefix_to_infix([Op|Rest], Expr, Remainder) :-
atom(Op),
% threading Rest -> Rem1 -> Remainder
prefix_to_infix(Rest, Left, Rem1),
prefix_to_infix(Rem1, Right, Remainder),
Expr =.. [Op, Left, Right].
Let's see it in action a few times along with evaluation:
?- postfix_to_infix([2,4,3,7,*,+,*],Term), Res is Term.
Term = (7*3+4)*2,
Res = 50 ;
false.
Let's permute the list by moving the operators and literals around in meaning-preserving ways, just to make sure that the parse isn't doing anything completely stupid.
?- postfix_to_infix([2,3,7,*,4,+,*],Term), Res is Term.
Term = (4+7*3)*2,
Res = 50 ;
false.
?- postfix_to_infix([3,7,*,4,+,2,*],Term), Res is Term.
Term = 2* (4+7*3),
Res = 50 ;
false.
Now let's make sure it properly fails when we have too much or too little.
?- postfix_to_infix([3,7,*,4,+,2,*,3],Term), Res is Term.
false.
?- postfix_to_infix([3,7,*,4,+,2,*,+],Term), Res is Term.
false.
?- postfix_to_infix([7,*], Term), Res is Term.
false.
Looks like it works to me.
Hope this helps!