% Demonstrate how to
% - use difference lists for natural language parsing
%   both for terms and gaps (gap threading).

:- eval(test042()).

test042() :-
	println(["==========test042=========="]).

s(S,X,F,G) :-
  np(S,S1,F,F),
%println([S1]),
  vp(S1,X,F,G).

vp(VP,X,F,F) :-
	v(VP,X,0).
vp(VP,X,F,G) :-
	v(VP,Y,1),
	np(Y,X,F,G).
vp(VP,X,F,G) :-
	v(VP,Y,2),
	% Note how the gap here can be in either np or pp
	np(Y,Z,F,H),
	pp(Z,X,H,G).
vp(VP,X,F,G) :-
	v(VP,Y,3),
%println(['###',Y]),
	pp(Y,X,F,G).

np(NP,X,F,F) :-
	det(NP,S1),
	n(S1,X).
np(NP,X,F,F) :-
	det(NP,S1),
	n(S1,S2),
%println(['@@@',S2]),
	rel(S2,X).
np(NP,X,F,F) :-
	pn(NP,X).
np(NP,X,F,F) :-
	pn(NP,S1),
	rel(S1,X).
np(NP,NP,[gap(np)|F],F).

rel(R,X) :-
	prorel(R,Y),
%println(['+++',Y]),
	s(Y,X,[gap(np)|F],F).
rel(R,X) :-
	prorel(R,Y),
%println(['---',Y]),
	vp(Y,X,F,F).

pp(PP,X,F,G) :-
	p(PP,Y),
%println(['[[[',Y]),
	np(Y,X,F,G).

n(['house elf'|X],X).
n([witch|X],X).
n([kitchen|X],X).
n([help|X],X).

pn(['Harry'|X],X).

det([a|X],X).
det([the|X],X).

v([cried|X],X,0).
v([likes|X],X,1).
v([watches|X],X,1).
v([gave|X],X,2).
v([was|X],X,3).

p([to|X],X).
p([in|X],X).
p([for|X],X).

prorel([who|X],X).

test042() :-
	np(['Harry'],[],_,_),
	println(["OK1"]),
	s(['Harry',likes,the,witch],[],_,_),
	println(["OK2"]),
	np([the,witch,who,'Harry',likes],[],_,_),
	println(["OK3"]),
	np(['Harry',who,likes,the,witch],[],_,_),
	println(["OK4"]),
	np([the,witch,who,'Harry',who,likes,the,witch,likes],[],_,_),
	println(["OK5"]),
	s([the,'house elf',cried],[],_,_),
	s([the,'house elf',was,in,the,kitchen],[],_,_),
	vp([was,in,the,kitchen],[],_,_),
	np([the,'house elf',who,was,in,the,kitchen],[],_,_),
	s([the,'house elf',who,was,in,the,kitchen,cried],[],_,_),
	s(['Harry',who,the,witch,gave,the,'house elf',to,likes,the,witch],[],_,_),
	println(["OK6"]).
%================
