        reverse(X,Y) :- rev2(X,[],Y). 
        rev2([], L, L) :- !. 
        rev2([X|Y], Z, T):- rev2(Y, [X|Z], T), !. 



% member without cuts 

  mem1(X,[X|_]). 
  mem1(X,[_|R]) :- mem1(X,R).

% member with cuts 

  mem(X,[X|_]) :- !.   
  mem(X,[_|R]) :- mem(X,R).





   gst(Person,10) :- citizen(Person,australia), !. 
   gst(Person,0)  :- citizen(Person,usa).

   citizen(jones,australia). 
   citizen(jones,usa). 


%% naive way to do sentences 

sentence1(X) :- concat(X1,X2,X), 
               nounphrase1(X1), verbphrase1(X2). 
nounphrase1(X) :- concat(X1,X2,T),concat(T,X3,X), 
                 article1(X1),adjective(X2),noun1(X3). 
verbhrase1(X) :- concat(X1,X2,T),verb1(X1),adverb1(X2). 

article1([a]).            adjective1([black]).
article1([the]).          adjective1([brown]).
noun1([cat]).             verb1([runs]).
noun1([dog]).             verb1([swims]).
adverb1([slowly]).        adverb1([quickly]).


% a smarter way to do the same thing 

sentence(S0,S2) :- nounphrase(S0,S1), verbphrase(S1,S2). 
nounphrase(S0,S3) :- article(S0,S1),
                     adjective(S1,S2),noun(S2,S3). 
verbphrase(S0,S2) :- verb(S0,S1),adverb(S1,S2). 

article([a|S],S).            adjective([black|S],S).
article([the|S],S).          adjective([brown|S],S).
noun([cat|S],S).             verb([runs|S],S).
noun([dog|S],S).             verb([swims|S],S).
adverb([slowly|S],S).        adverb([quickly|S],S).



expression(E,S0,S1) :- integer(E,S0,S1).
expression(plus(E1,E2),S0,S5) :- 
     S0 = [`('|S1], expression(E1,S1,S2), 
     S2 = [`+'|S3], expression(E2,S3,S4), 
     S4 = [`)'|S5].
expression(times(E1,E2),S0,S5) :- 
     S0 = [`('|S1], expression(E1,S1,S2), 
     S2 = [`+'|S3], expression(E2,S3,S4), 
     S3 = [`)'|S5].
integer(E,S0,S1) :- digit(E,S0,S1). 

digit(0,[0|S],S).  digit(1,[1|S],S). ...  digit(9,[9|S],S). 






sentence3(S0,S3) :- 
   seq(a,N,S0,S1),seq(b,N,S1,S2),seq(c,N,S2,S3).

seq(L,1,S0,S1) :- letter(L,S0,S1).
seq(L,N,S0,S2) :- letter(L,S0,S1),seq(L,M,S1,S2),N is M+1.

letter(L,[L|S],S). 



%%% the following only works in XSB 

expression1(E) --> integer1(E).
expression1(plus(E1,E2)) --> [`('], expression1(E1), 
                            [`+'], expression1(E2), [`)'].
expression1(times(E1,E2)) -->  [`('], expression1(E1), 
                              [`+'], expression1(E2), [`)'].
integer1(E) :- digit1(E). 

digit1(X) -> [X], {(X=1; X=2; ....; X=9)}. 











