%% -*- prolog -*-

%% Difference List:
%% represent the list of items e1, e2, e3, e4 as a pair: a HEAD and a TAIL, where
%% HEAD = [e1,e2,e3,e4|TAIL], and TAIL can be anything.
%% represent with term: 
%%   '-'([e1,e2,e3,e4|TAIL], TAIL)
%% aka
%%   [e1,e2,e3,e4|TAIL] - TAIL

dlapp(X-Y, Y-Yt, X-Yt).

sentence(X-Xt) :- nounphrase(X-Xnt), verbphrase(Xnt-Xnvt), fullstop(Xnvt-Xt).
sentence(X-Xt) :- nounphrase(X-Xnt), verbphrase(Xnt-Xnvt), nounphrase(Xnvt-Xnvnt), fullstop(Xnvnt-Xt).

nounphrase(X-Xt) :- noun(X-Xt).
nounphrase(X-Xt) :- adjectives(X-Xat), noun(Xat-Xt).
nounphrase(X-Xt) :- article(X-Xat), noun(Xat-Xt).
nounphrase(X-Xt) :- article(X-Xat), adjectives(Xat-Xaat), noun(Xaat-Xt).

noun([N|Xt]-Xt) :- member(N, [dog, cat, wind]).

article([A|Xt]-Xt) :- member(A, [the, a, an]).

adjective([W|Xt]-Xt) :- member(W, [red, slow, angry]).

%% One or more adjectives:
adjectives(X-Xt) :- adjective(X-Xt).
adjectives(X-Xt) :- adjective(X-Xat) , adjectives(Xat-Xt).

verbphrase(X-Xt) :- verb(X-Xt).

verb([V|Xt]-Xt) :- member(V, [eats, runs, wind]).

fullstop(['.'|Xt]-Xt).

%%% How can we make this into a parser, outputting a parse?

%%% make everything take *two* arguments: the "surface syntax", as a
%%% difference list, and a parse tree.

% psentence([the,quick,brown,fox,jumps,'.',|Xt]-Xt,
% 	  sentence(nounphrase(article([the]),
% 			      adjectives([quick,brown]),
% 			      noun([fox])),
% 		   verbphrase(verb([jumps])),
% 		   stop(['.']))).

psentence(X-Xt, sentence(NP,VP,S)) :-
	pnounphrase(X-Xnt, NP),
	pverbphrase(Xnt-Xnvt, VP),
	pfullstop(Xnvt-Xt,S).
psentence(X-Xt, sentence(NP,VP,DO,S)) :-
	pnounphrase(X-Xnt, NP),
	pverbphrase(Xnt-Xnvt, VP),
	pnounphrase(Xnvt-Xnvnt, DO),
	pfullstop(Xnvnt-Xt, S).

pnounphrase(X-Xt, nounphrase(N)) :- pnoun(X-Xt, N).
pnounphrase(X-Xt, nounphrase(A,N)) :- padjectives(X-Xat, A), pnoun(Xat-Xt, N).
pnounphrase(X-Xt, nounphrase(Ar,N)) :- particle(X-Xat, Ar), pnoun(Xat-Xt, N).
pnounphrase(X-Xt, nounphrase(Ar,A,N)) :- particle(X-Xat, Ar), padjectives(Xat-Xaat, A), pnoun(Xaat-Xt, N).

pnoun([N|Xt]-Xt, noun([N])) :- member(N, [dog, cat, wind]).

particle([A|Xt]-Xt, article([A])) :- member(A, [the, a, an]).

padjective([W|Xt]-Xt, adjectives([W])) :- member(W, [red, slow, angry]).

%% One or more adjectives:
padjectives(X-Xt, adjectives(As)) :- padjective(X-Xt, adjectives(As)).
padjectives(X-Xt, adjectives(As)) :-
	padjectives(X-Xat,  adjectives(A1s)),
	padjectives(Xat-Xt, adjectives(A2s)),
	append(A1s, A2s, As).

pverbphrase(X-Xt, verbphrase(V)) :- pverb(X-Xt, V).

pverb([V|Xt]-Xt, verb([V])) :- member(V, [eats, runs, wind]).

pfullstop([S|Xt]-Xt, stop([S])) :- member(S, ['.', '!']).
