// Abstract ------------------------------------------------------------------------------------------------------------------------------

This sample uses the 'link-grammar' service available in fizz to parse string as sentence. It uses the link-grammar OSS library from CMU to do so.

// Examples ------------------------------------------------------------------------------------------------------------------------------

?- #nlp.parse("The dog ran by then it barked at the black cat who was passing by.",:c,:l)
-> ( cons(S, [word([n], "dog"), cons(VP, [word([v, d], "ran"), cons(PRT, [word([], "by")])]), cons(SBAR, [cons(S, [word([r], "then"), cons(S, [cons(NP, [word([], "it")]), cons(VP, [word([v, d], "bark"), cons(PP, [word([], "at"), cons(NP, [cons(NP, [word([a], "black"), word([n], "cat")]), cons(SBAR, [cons(WHNP, [word([], "who")]), cons(S, [cons(VP, [word([v, d], "was"), cons(VP, [word([v], "pass"), cons(PRT, [word([], "by")])])])])])])])])])])])]) , link(X, [s], link(W, [d], nil, link(S, [s, s], word([n], "dog"), link(MV, [s], word([v, d], "ran by"), link(CV, [], link(C, [s], word([r], "then"), link(S, [s], word([], "it"), link(MV, [p], word([v, d], "bark"), link(J, [s], word([], "at"), link(A, [], word([a], "black"), link(B, [s], link(R, [], word([n], "cat"), link(RS, [], word([], "who"), link(P, [g, b], word([v, d], "was"), word([v], "pass by")))), word([v, d], "was"))))))), word([v, d], "bark"))))), word([r], "then")) ) := 1.00 (0.362) 1
 
// Code ----------------------------------------------------------------------------------------------------------------------------------

lgr.parse { // define a link-grammar powered processor elemental
    class           = FZZCLGRProcessor,
    datapath        = "./etc/data/lgr",
    language        = "us",
    load.on.attach  = yes
} {}

nlp.string.prep { // prepare a string from processing by 'link-grammar'

    (:so,:sp) :- str.swap(:so,[["+","plus"],["-","minus"]],:sp);

}

nlp.word.stemming { // attempt to transform a word (e.g. a verb finishing with 'ed') into its stem

    (_?[lst.incl([v,d])],"lived","live")^   :- true;

    (_?[lst.incl([v])],:w?[is.string],:s)   :- str.tail(:w,"ing")^, str.trim.tail(:w,:s,"ing");
    (_?[lst.incl([v,d])],:w?[is.string],:s) :- str.tail(:w,"ed")^,  str.trim.tail(:w,:s,"ed");
    (_,:w?[is.string],:s)                   :- str.tail(:w,"ly")^,  str.trim.tail(:w,:s,"ly");
    (_,:w?[is.string],:w)                   :- true;

}

nlp.word.symbolify { // substitue a few common characters into symbols

    ("\"",quote)^   :- true;
    (",",comma)^    :- true;
    (".",dot)^      :- true;
    (";",semicolon)^:- true;
    (:w,:w)         :- true;

}

nlp.word.to.func { // transform a list containing a word definition into a functor (also perform stemming and symbol subsitution)

    ([[],nil],word([],nil))^  :- true;
    ([:l,:s],:f)              :- #nlp.word.stemming(:l,:s,:stem), #nlp.word.symbolify(:stem,:symb), fun.make(word,[:l,:symb],:f);

}

nlp.link.traverse { // traverse a list of chained links and replace each link into a functor

    ([],_,_,nil)^                                       :- true;

    ([:i,:lt?[is.number],:rt?[is.number]],:w,:l,:f)^    :-  lst.item(:l,:i,:link), lst.item(:link,0,:label), lst.item(:link,1,:subs),
                                                            lst.item(:w,:lt,:lw), #nlp.word.to.func(:lw,:lf),
                                                            lst.item(:w,:rt,:rw), #nlp.word.to.func(:rw,:rf),
                                                            fun.make(link,[:label,:subs,:lf,:rf],:f);

    ([:i,:lt?[is.number],:rt?[is.list]],:w,:l,:f)^      :-  lst.item(:l,:i,:link), lst.item(:link,0,:label), lst.item(:link,1,:subs),
                                                            lst.item(:w,:lt,:lw), #nlp.word.to.func(:lw,:lf),
                                                            #nlp.link.traverse(:rt,:w,:l,:rf),
                                                            fun.make(link,[:label,:subs,:lf,:rf],:f);

    ([:i,:lt?[is.list],:rt?[is.number]],:w,:l,:f)^      :-  lst.item(:l,:i,:link), lst.item(:link,0,:label), lst.item(:link,1,:subs),
                                                            #nlp.link.traverse(:lt,:w,:l,:lf),
                                                            lst.item(:w,:rt,:rw), #nlp.word.to.func(:rw,:rf),
                                                            fun.make(link,[:label,:subs,:lf,:rf],:f);

    ([:i,:lt?[is.list],:rt?[is.list]],:w,:l,:f)^     :-     lst.item(:l,:i,:link), lst.item(:link,0,:label), lst.item(:link,1,:subs),
                                                            #nlp.link.traverse(:lt,:w,:l,:lf),
                                                            #nlp.link.traverse(:rt,:w,:l,:rf),
                                                            fun.make(link,[:label,:subs,:lf,:rf],:f);

}

nlp.link.simplify { // simplify (somewhat) a chained list of links by removing some of the less important links

    (link(D,_?[lst.excl([w])],word(_,_),:rt),:rt2)^                                     :-  #nlp.link.simplify(:rt,:rt2);
    (link(DD,_,word(_,_),:rt),:rt2)^                                                    :-  #nlp.link.simplify(:rt,:rt2);
    (link(DG,_,word(_,_),:rt),:rt2)^                                                    :-  #nlp.link.simplify(:rt,:rt2);
    (link(D,:s?[lst.incl([w])],:lt,:rt),link(D,:s,:lt2,:rt2))^                          :-  #nlp.link.simplify(:lt,:lt2),
                                                                                            #nlp.link.simplify(:rt,:rt2);
    (link(D,_?[lst.excl([w])],link(:l,:s,:lt,:rt),_),:f)^                               :-  #nlp.link.simplify(link(:l,:s,:lt,:rt),:f);
    (link(PH,_,_,:rt),:rt2)^                                                            :-  #nlp.link.simplify(:rt,:rt2);
    (link(WV,_,:lt,:rt),:lt2)^                                                          :-  #nlp.link.simplify(:lt,:lt2);
    (link(RW,_,:lt,word([],nil)),:lt2)^                                                 :-  #nlp.link.simplify(:lt,:lt2);
    (link(X,[p],:lt,_),:lt2)^                                                           :-  #nlp.link.simplify(:lt,:lt2);
    (link(X,[i],:lt,_),:lt2)^                                                           :-  #nlp.link.simplify(:lt,:lt2);
    (link(X,[d],word([],_),:rt),:rt2)^                                                  :-  #nlp.link.simplify(:rt,:rt2);
    (link(IDDX,_,word(:sl,:wl?[is.string]),word(:sr,:wr?[is.string])),word(:slr,:wlr))^ :-  lst.join(:sl,:sr,:slr), str.cat(:wl," ",:wr,:wlr);
    (link(K,_,word(:sl,:wl?[is.string]),word(:sr,:wr?[is.string])),word(:slr,:wlr))^    :-  lst.join(:sl,:sr,:slr), str.cat(:wl," ",:wr,:wlr);
    (link(MV,[p],link(MV,[p],:lt,:rt),word(_,_)),link(MV,[p],:lt2,:rt2))^               :-  #nlp.link.simplify(:lt,:lt2),
                                                                                            #nlp.link.simplify(:rt,:rt2);

    (link(:l,:s,word([],nil),:rt),link(:l,:s,nil,:rt2))^                                :-  #nlp.link.simplify(:rt,:rt2);

    (word(:l,:s),word(:l,:s))^                                                          :-  true;
    (link(:l,:s,:lt,:rt),link(:l,:s,:lt2,:rt2))                                         :-  #nlp.link.simplify(:lt,:lt2),
                                                                                            #nlp.link.simplify(:rt,:rt2);

}

nlp.postproc { // post process the chain of links

    ([],[],[],link(ERR,[],nil))^    :-  true;
    (:w,:l,:c,:fo)                  :-  #nlp.link.traverse(:c,:w,:l,:f),
                                        #nlp.link.simplify(:f,:fo);

}

nlp.wordify { // transform a constituent list into a functor

    (:w,:n?[is.number],:f)^                 :- lst.item(:w,:n,:word), #nlp.word.to.func(:word,:f);
    (:w,[:i,:l?[is.list]],cons(:i,:wl))     :- #nlp.wordify.args(:w,:l,:wl);

}

nlp.wordify.args { // transform the arguments of a constituent into a list of functors

    (:w,[],[])^             :- true;
    (:w,[:e],[:we])^        :- #nlp.wordify(:w,:e,:we);
    (:w,[:h|:r],[:wh|:wr])  :- #nlp.wordify(:w,:h,:wh), #nlp.wordify.args(:w,:r,:wr);

}

nlp.lessify { // simplify a constituent's functor (mainly by removing some less useful elements)

    (cons(:i?[lst.member([NP,S])],[word([],"the")|:r]),cons(:i,:rl))^   :-  #nlp.lessify.args(:r,:rl);
    (cons(:i?[lst.member([NP,S])],[word([],"this")|:r]),cons(:i,:rl))^  :-  #nlp.lessify.args(:r,:rl);
    (cons(:i?[lst.member([NP,S])],[word([],"that")|:r]),cons(:i,:rl))^  :-  #nlp.lessify.args(:r,:rl);

    (cons(:s,:l?[is.list]),cons(:s,:rl))                                :-  lst.tail(:l,word([],dot))^,
                                                                            lst.init(:l,:r), #nlp.lessify.args(:r,:rl);

    (cons(:i,[:h|:r]),cons(:i,[:hl|:rl]))^                              :- #nlp.lessify(:h,:hl), #nlp.lessify.args(:r,:rl);
    (:w,:w)^                                                            :- true;

}


nlp.lessify.args { // apply the simplification of a constituent's functor to its arguments)

    ([],[])^             :- true;
    ([:e],[:we])^        :- #nlp.lessify(:e,:we);
    ([:h|:r],[:wh|:wr])  :- #nlp.lessify(:h,:wh), #nlp.lessify.args(:r,:wr);

}

nlp.parse { // parse a given string and returns the constituents functor as well as the links functor

    (:s,:c,:l)          :-  #nlp.string.prep(:s,:sp),
                            #lgr.parse(:sp,:ws,:ls,:ln,:cn), // words, links, link, const
                            #nlp.wordify(:ws,:cn,:f0),
                            #nlp.lessify(:f0,:c),
                            #nlp.postproc(:ws,:ls,:ln,:l);

    (:s,:c,:l,trace)    :-  #nlp.string.prep(:s,:sp),
                            #lgr.parse(:sp,:ws,:ls,:ln,:cn), // words, links, link, const
                            console.puts("words: ",:ws),
                            console.puts("links: ",:ls),
                            console.puts("link: ",:ln),
                            console.puts("cons: ",:cn),
                            #nlp.wordify(:ws,:cn,:f0),
                            #nlp.lessify(:f0,:c),
                            #nlp.postproc(:ws,:ls,:ln,:l);

}

nlp.link.find {

    (link(:l,:s,:lt,:rt),link(:l,:s,:lt,:rt),link(:l,:s,:lt,:rt))^  :- true;
    (link(:l,:s,:lt,:rt),:lt,link(:l,:s,:lt,:rt))^                  :- true;
    (link(:l,:s,:lt,:rt),:rt,link(:l,:s,:lt,:rt))^                  :- true;
    (link(:l,:s,:lt,:rt),:w,:f)                                     :- #nlp.link.find(:lt,:w,:f)^;
    (link(:l,:s,:lt,:rt),:w,:f)                                     :- #nlp.link.find(:rt,:w,:f)^;

}

// ---------------------------------------------------------------------------------------------------------------------------------------

[Home] [Email] [Twitter] [LinkedIn]