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

S ---> [NP,VP] :-            
   S:cat   === s,                
   NP:cat  === np,               
   VP:cat  === vp,               
   NP:agr  === VP:agr.

W ---> mary :-              
   W:cat     === np, 
   W:agr#per === third,         
   W:agr#num === sing.          
                                
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(FS,Path,Value,_).


pathval(FS1,Feat#Path,Value,FSs) :-
   !,pathval(FS1,Feat,FS2,FSs),
   pathval(FS2,Path,Value,_).

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

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

fs_unify(FS,FS) :- !.
fs_unify([Path-Val|Rest1],FS) :-
   pathval(FS,Path,Val,Rest2),
   fs_unify(Rest1,Rest2).


recognise(MotherFs) --> [Word],
                        {CatFs ---> Word},
                        lc(CatFs,MotherFs).

lc(Fs1,Fs2) --> [],
                {fs_unify(Fs1,Fs2)}.

lc(SubPhraseFs,SuperPhraseFs) -->
    {PhraseFs ---> [SubPhraseFs,RightFs]},
    recognise(RightFs),
    lc(PhraseFs,SuperPhraseFs).
