
:- op(990,xfy,'<=>').

%'<=>'(X,Y) :- (call(X) -> call(Y) ; \+ call(Y)).
X <=> Y :- if(call(X),call(Y),\+ call(Y)).

h(a). h(b). h(c).  i(b). i(c). j(c). j(d).
hij(X) :-  h(X),  i(X) <=> j(X).

% Goal:
%  Parse expressions using binary + and identifiers x,y,z

% Step 1: find grammar suitable for LL parsing

% Grammar:
%  n --> x | y | z
%  p --> n pc
%  pc --> epsilon | + p

% Step 2: translate to Prolog

n([x]).
n([y]).
n([z]).

pc([]).
pc([+|Rest]) :- p(Rest).

p(String) :- n(S1), append(S1,S2,String), pc(S2).

% Step 3:
% Critique  --> efficiency ?

gen(Nr,[x|T]) :- gen_aux(Nr,T).
gen_aux(0,[]).
gen_aux(N,[+,x|T]) :- N1 is N-1, gen_aux(N1,T).

test(N) :- gen(N,String), statistics(runtime,_),
           p(String),
           statistics(runtime,[_,T]), print(T), print(' ms'),nl,
           dp(String,[]),
           statistics(runtime,[_,T]), print(T), print(' ms'),nl.


dl_app(H1-H2, H2-TP2, H1-TP2).

% Explicit Diff-List Version

dl_n([x|T]-T).
dl_n([y|T]-T).
dl_n([z|T]-T).
dl_pc(X-X).
dl_pc([+|T]-R) :- dl_p(T-R).
dl_p(X-R) :- dl_n(X-X1), dl_pc(X1-R).



dl_n([x|T],T).
dl_n([y|T],T).
dl_n([z|T],T).
dl_pc(X,X).
dl_pc([+|T],R) :- dl_p(T,R).
dl_p(X,R) :- dl_n(X,X1), dl_pc(X1,R).

% DCG version
:- dynamic dp/2, dpc/2, dn/2.
dn --> [x] ; [y] ; [z].
dpc --> [] ; [+],dp.
dp --> dn , {print(n),nl}, dpc.


% DCG Calculator

n(env(X,Y,Z),R) --> [x],{R=X} ; [y],{R=Y} ; [z], {R=Z}.
pc(E,LR,R) --> [], {R=LR} ; [+],p(E,PR),{R is LR+PR}.
p(E,R) --> n(E,NR) , pc(E,NR,R).
calc(Expr,R) :- p(env(1,2,3),R,Expr,[]).





