:- op(500,xfx,--->).
:- op(600,xfy,===).
:- op(500,xfy,'~').

W ---> [mary] :-               
   W~[cat]     === np,            
   W~[agr,per] === third,         
   W~[agr,num] === sing.          
                                
S ---> [NP,VP] :-            
   S~[cat]   === s,                
   NP~[cat]  === np,               
   VP~[cat]  === vp,               
   NP~[agr]  === VP~[agr].

W ---> [left] :-                                            
   W~[cat]     === vp,                                                
   W~[agr,per] === third,                                                
   W~[agr,num] === sing.                                                

X === Y :- 
   denotes(X,Z),
   denotes(Y,Z).
           
denotes(Var,Var) :-
   var(Var),!.
denotes(Atom,Atom) :-
   atomic(Atom),!.
denotes(FS~Path,Value) :-
   pathval(Path,FS,Value).

pathval([Feat|RestPath],FS,Value) :-
   featval(FS,Feat,FeatVal,_),
   (  RestPath==[]
   -> Value=FeatVal
   ;  pathval(RestPath,FeatVal,Value) ).


fs_unify(FS,FS) :- !.

fs_unify([Feat:Val | Rest1], FS) :-
   featval(FS,Feat,Val,Rest2),
   fs_unify(Rest1,Rest2).

featval([Feat:Val1 | Rest], Feat, Val2, Rest) :-
   !, fs_unify(Val1,Val2).

featval([FS | Rest], Feat, Val, [FS | Rest2]) :-
   featval(Rest,Feat,Val,Rest2).



% ?- recognize(s,<list(word)>,[]).
recognize(PhraseFS,[Word|S1],S) :- 
   (CatFS ---> [Word]),
   lc(CatFS,PhraseFS,S1,S).

lc(Phrase1FS,Phrase2FS,S,S) :- 
   fs_unify(Phrase1FS,Phrase2FS).

lc(SubPhraseFS,SuperPhraseFS,S0,S) :-
    PhraseFS ---> [LeftFS,RightFS],
    fs_unify(LeftFS,SubPhraseFS),
    recognise(RightFS,S0,S1),
    lc(PhraseFS,SuperPhraseFS,S1,S).
