% Demonstrate
% - how to use difference lists for natural language parsing
%   	both for terms and gaps (gap threading).
% - how to use attribute grammars to make consciousness, number, and tense
%   	consistent. 
% - why unification with occurs checks built into Prova is important

:- eval(test043()).

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

% Declarative sentence
s([s(NP,VP),Num,Tense],S,X,F,G) :-
	np([NP,Num,Tense],S,S1,F,F),
	vp([VP,Num,Tense],S1,X,F,G).
% Subject interrogative
s([s(WH,VP),Num,Tense],S,X,F,F) :-
	wh([WH,Cn],S,S1),
	vp([VP,_Num,Tense],S1,X,F,F).
% Object interrogative
s([s(WH,YN),Num,Tense],S,X,F,F) :-
	wh([WH,Cn],S,S1),
	yes_no([YN,Num,Tense],S1,X,[gap(np)|F],F).
% Yes-No standalone (without object gap)
s([s(YN),Num,Tense],S,X,F,F) :-
	yes_no([YN,Num,Tense],S,X,F,F).

yes_no([yes_no(Aux,NP,VP),Num,Tense],S,X,F,G) :-
	aux([Aux,Num,Tense],S,S1),
	np([NP,Num,Tense],S1,S2,F,F),
	vp([VP,Num,inf],S2,X,F,G).

vp([vp(V),Num,Tense],VP,X,F,F) :-
	v([V,Num,Tense],VP,X,0).
vp([vp(V,O),Num,Tense],VP,X,F,G) :-
	v([V,Num,Tense],VP,Y,1),
	np([O,_,_],Y,X,F,G).
vp([vp(V,O,P),Num,Tense],VP,X,F,G) :-
	v([V,Num,Tense],VP,Y,2),
	% Note how the gap below can be either in np or in pp
	np([O,_,_],Y,Z,F,H),
	pp([P],Z,X,H,G).
vp([vp(V,P),Num,Tense],VP,X,F,G) :-
	v([V,Num,Tense],VP,Y,3),
	pp([P],Y,X,F,G).

np([np(D,N),Num,_],NP,X,F,F) :-
	det([D,Num],NP,S1),
	n([N,Num,Cn],S1,X).
np([np(D,N,R),Num,Tense],NP,X,F,F) :-
	det([D,Num],NP,S1),
	n([N,Num,Cn],S1,S2),
	rel([R,Num,Cn,Tense],S2,X).
np([np(P),Num,_],NP,X,F,F) :-
	pn([P,Num,Cn],NP,X).
np([np(P,R),Num,Tense],NP,X,F,F) :-
	pn([P,Num,Cn],NP,S1),
	rel([R,Num,Cn,Tense],S1,X).
np([gap(np),_,_],NP,NP,[gap(np)|F],F).

rel([rel(Rel,S),Num,Cn,Tense],R,X) :-
	prorel([Rel,Cn,_],R,Y),
	s([S,Num,Tense],Y,X,[gap(np)|F],F).
rel([rel(Rel,V),Num,Cn,Tense],R,X) :-
	prorel([Rel,Cn,fixed],R,Y),
	vp([V,Num,Tense],Y,X,F,F).

pp([pp(P,NP)],PP,X,F,G) :-
	p([P],PP,Y),
	np([NP,_,_],Y,X,F,G).

n([n(L),Num,Cn],[L|X],X) :-
	lex(L,n,[Num,Cn]).

pn([pn(L,Num,Cn),Num,Cn],[L|X],X) :-
	lex(L,pn,[Num,Cn]).

det([det(L),Num],[L|X],X) :-
	lex(L,det,Num).

v([v(L),Num,Tense],[L|X],X,Type) :-
	lex(L,v,[Num,Tense,Type]).

p([p(L)],[L|X],X) :-
	lex(L,p,_).

prorel([prorel(L),Cn,fixed],[L|X],X) :-
	lex(L,prorel,Cn).
% Account for missing proposition (that, who, etc.) -> only for objects
prorel([prorel('_'),Cn,_],X,X).

wh([wh(L),Cn],[L|X],X) :-
	lex(L,wh,Cn).

aux([aux(L),Num,Tense],[L|X],X) :-
	lex(L,aux,[Num,Tense]).

lex(does,aux,[sg,pr]).
lex(do,aux,[pl,pr]).
lex(did,aux,[_,pa]).
lex(who,wh,cn).
lex(what,wh,un).
lex('house elf',n,[sg,cn]).
lex(witch,n,[sg,cn]).
lex(kitchen,n,[sg,un]).
lex(house,n,[sg,un]).
lex(help,n,[sg,un]).
lex('Harry',pn,[sg,cn]).
lex(a,det,sg).
lex(the,det,_).
lex(cried,v,[_,pa,0]).
lex(cried,v,[_,pa,3]).
lex(likes,v,[sg,pr,1]).
lex(like,v,[pl,pr,1]).
lex(like,v,[_,inf,1]).
lex(liked,v,[_,pa,1]).
lex(watches,v,[sg,pr,1]).
lex(gave,v,[_,pa,2]).
lex(was,v,[sg,pa,3]).
lex(is,v,[sg,pr,3]).
lex(to,p,_).
lex(in,p,_).
lex(for,p,_).
lex(who,prorel,cn).
lex(that,prorel,un).

test043() :-
	np(NP1,['Harry'],[],[],[]),
	println(["OK1=",NP1]),
	s(S2,['Harry',likes,the,witch],[],[],[]),
	println(["OK2=",S2]),
	np(NP3,[the,witch,who,'Harry',likes],[],_,_),
	println(["OK3=",NP3]),
	np(NP4,['Harry',who,likes,the,witch],[],[],[]),
	println(["OK4=",NP4]),
	np(NP5,[the,witch,who,'Harry',who,likes,the,witch,likes],[],[],[]),
	println(["OK5=",NP5]),
	np(NP6,[the,house,the,'house elf',cried,in],[],[],[]),
	println(["OK6=",NP6]),
	s(S7,[the,'house elf',was,in,the,kitchen],[],[],[]),
	println(["OK7=",S7]),
	vp(VP8,[was,in,the,kitchen],[],[],[]),
	println(["OK8=",VP8]),
	np(NP9,[the,'house elf',who,was,in,the,kitchen],[],[],[]),
	println(["OK9=",NP9]),
	s(S10,[the,'house elf',who,was,in,the,kitchen,cried,in,the,house],[],[],[]),
	println(["OK10=",S10]),
	s(S11,['Harry',who,the,witch,gave,the,'house elf',to,liked,the,witch],[],[],[]),
	println(["OK11=",S11]),
	% Note that below
	% 		'that' cannot be replaced by 'who' (consciousness)
	% 		'liked' cannot be replaced by 'like' (tense)
	s(S12,[the,kitchen,that,'Harry',liked,was,in,the,house],[],[],[]),
	println(["OK12=",S12]),
	s(S13,[who,liked,the,house],[],[],[]),
	println(["OK13=",S13]),
	s(S14,[the,'house elf','Harry',liked,was,in,the,house],[],[],[]),
	println(["OK14=",S14]),
	% Wh-questions
	s(S15,[who,did,'Harry',like],[],[],[]),
	println(["OK15=",S15]),
	% 'was' cannot be replaced by 'is'
	s(S16,[who,did,'Harry',who,was,in,the,house,like],[],[],[]),
	println(["OK16=",S16]),
	s(S17,[who,does,'Harry',who,is,in,the,house,like],[],[],[]),
	println(["OK17=",S17]),
	% yes-no standalone
	s(S18,[does,'Harry',who,is,in,the,house,like,the,'house elf'],[],[],[]),
	println(["OK18=",S18]).
