%% INPUT ACQUISITION IN A CONVENIENT FORMAT chat :- repeat, readLine(Sentence), parse(Clause, Sentence, _), respondTo(Clause), Clause = stop. %% read text as a list (words) of lists of ASCII (word) until LF terminator an split off word suffixes readLine(Sentence) :- readCharLists(Words), morphs(Words, Sentence), ! . %% read text as a list (words) of lists of ASCII (word) until LF terminator readCharLists([Word | Words]) :- readWord(Word, Term), ( Term = 10, Words = [] ; readCharLists(Words)). %% read a word as a list of ASCII readWord(W, Term) :- get0(C), ((C = 10 ; C = 32), Term = C, W = [] ; readWord(Chars, Term), W = [C | Chars]). %% split suffixes on elements of a list that are lists of ASCII and convert them to atoms (result is a list of atoms) morphs([], []). morphs([Word | Rest], Atoms) :- morph(Word, Atom), morphs(Rest, Atoms2), append(Atom, Atoms2, Atoms). %% split core/suffix on a word (list of ASCII) and convert it to a list of atoms morph([], []). morph(Word, Atoms) :- morphrules(Word, Comps), maplist(name, Atoms, Comps). %% the "split suffix" rule for now, others can be plugged in later morphrules(Chars, Comps) :- append(X1, X2, Chars), suffix(X2), Comps = [X1, X2]. morphrules(Chars, [Chars]). %% used by the (only) "split suffix" rule suffix("?"). suffix("."). suffix("'s"). %% utility to slap a pericate to all elements of a list quickly mapcar(_, [], []). mapcar(P, [H1 | T1], [H2 | T2]) :- Q =..[P, H1, H2], call(Q), mapcar(P, T1, T2). %% THE LANGUAGE UNDERSTANDING %% parse(Clause, S, Srem) :- det1(S, S0), det2(S0, S1), det3(S1, S2), det4(S2, Srem). %% [P] aka det1([P | St], St). %% type(T, S, Srem) :- det8(S, Strem). %% det8([ T | St ], St). parse(stop, ['Stop', '.'], []). parse(C) --> thing(Name), [is], particle(a), type(T), ['.'], {C=..[T, Name], !}. parse(C) --> particle('A'), type(T1), [is], particle(a), type(T2), ['.'], {Head=..[T2, X], Condition=..[T1,X], C = (Head :- Condition), !}. parse(C) --> ['Is'], thing(Name), particle(a), type(T), ['?'], {G=..[T, Name], C = '?-'(G), !}. parse(C) --> particle('A'), type(T1), [is], particle(a), type(T2), ['.'], {Head=..[T2, X], Condition=..[T1,X], C = (Head :- Condition), !}. parse(C) --> ['List', 'all'], type(T), ['.'], {C = '?-2'(T), !}. parse(noparse, _ , _). particle(a) --> [a]. particle(a) --> [an]. particle('A') --> ['A']. particle('A') --> ['An']. thing(N) --> [N], {capital(N)}. capital(N) :- name(N, [F|_]), F < 96. type(T) --> [T], {not(capital(T))}. %% THE ACTIONS FOR UNDERSTOOD PARTS respondTo(stop) :- write('All done.'), nl, !. respondTo(noparse) :- write( 'I don''t understand that.') , nl, !. respondTo( '?-'(G)) :- (G -> write('Yes') ; write('No')), !, nl, nl. respondTo( '?-2'(T)) :- P=..[T,X], write(P), bagof(X,P,XS), write(XS), !, nl, nl. respondTo(C) :- asserta(C), write('Ok'), nl, !.