We can extend this evaluator in the following interesting way. Say we
want to add exponentiation. We introduce a new nonterminal,
factor, for handling exponentiation and make it right
recursive, since exponentiation is right associative.
:- table expr/3, term/3.
expr(Val) --> expr(Eval), [+], term(Tval), {Val is Eval+Tval}.
expr(Val) --> term(Val).
term(Val) --> term(Tval), [*], factor(Fval), {Val is Tval*Fval}.
term(Val) --> factor(Val).
factor(Val) --> primary(Num), [^], factor(Exp),
{Val is floor(exp(log(Num)*Exp)+0.5)}.
factor(Val) --> primary(Val).
primary(Val) --> ['('], expr(Val), [')'].
primary(Int) --> [Int], {integer(Int)}.
However, we don't table the new nonterminal. Prolog's evaluation
strategy handles right recursion in grammars finitely and efficiently.
In fact, Prolog has linear complexity for a simple right-recursive
grammar, but with tabling it would be quadratic. Thus an advantage of
XSB is that it allows tabled and nontabled predicates to be freely
intermixed, so that the programmer can choose the strategy that is
most efficient for the situation at hand.