[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Prolog
- To: bob@gnu.ai.mit.edu
- Subject: Re: Prolog
- From: nsn (Nick Nicholas)
- Date: Tue, 20 Jul 1993 13:59:13 +1000 (EST)
- Cc: nsn (Nick Nicholas)
The Seraphim surely rejoiced when bob@gnu.ai.mit.edu spoke thus:
}Hi! I'm back from vacation. I turned off the lojban mailing list
}while I was away, so I missed any messages you may have posted.
Didn't post anything, it turns out :) . I sent my project paper to the list
today, and enclose herein my code. (It's in NU-Prolog).
****
?- pure(bridi_tail_50,4).
?- pure(ask1,2).
?- pure(permuteQ1,3).
?- pure(deleteQ,6).
?- pure(statement_42,3).
?- pure(tail_terms_71,4).
?- pure(terms_80,6).
?- pure(selbri,5).
?- pure(tanru_unit_B_152,5).
?- pure(se_596,3).
?- pure(anaphorise,4).
?- pure(ask,3).
?- dynamic uttered/1.
/* This subsection of lojban grammar implements predications involving
proper names, variable names, or values satisfying predicates as arguments,
also, restrictive relative clauses, conjunctions, and event abstractions;
it implements the following BNF subset of lojban:
text = [I|NIhO...] paragraphs FAhO
paragraphs = paragraph [NIhO paragraphs]
paragraph = paragraph1 [I [jek] paragraph1]...
paragraph1 = sentence
sentence = briditail | sentence1
sentence1 = term... [CU] briditail | gek sentence1 gik sentence
briditail = briditail3 [gihek briditail3 tailterms]
briditail3 = selbri tailterms
tailterms = [term] VAU
term = sumti | (tag | FA ) (sumti | KU)
sumti = sumti_1
sumti_1 = sumti_4 [joik-ek sumti_4] ...
sumti_4 = [quantifier] sumti_5 [relative-clauses]
sumti_5 = KOhA | letteral-string BOI | LA CMENE... | LE sumti-tail KU
sumti-tail = selbri
relative-clauses = relative-clause
relative-clause = NOI sentence KUhO
selbri = tanru_unit_1
tanru_unit_1 = tanru_unit_2 [linkargs]
tanru_unit_2 = BRIVLA | SE tanru_unit_2 | NU sentence KEI
linkargs = BE term [links] BEhO
links = BEI term [links]
number = PA [PA]...
ek = A
gihek = GIhA
joik-ek = ek
gek = GA
gik = GI
quantifier = number BOI
letteral-string = letteral [PA | letteral] ...
letteral = BY
tag = BAI
(A note on vocabulary: bridi is lojban for predication; selbri = predicate;
sumti = argument; cmene = name). */
text_0 --> text_B_2(Answers),
{print('Answers to the questions: '),
print(Answers),nl},
text_B_2_a.
text_B_2_a --> [];[faho].
text_B_2(Answer) --> i_819(_), text_B_2(Answer);
para_mark_410, text_C_3(Answer);
text_C_3(Answer).
text_C_3(Answers) --> paragraphs_4(_,Answers).
paragraphs_4(P,Answers) -->
paragraph_A_10(statement,P,P,Answers1),
{postproc(P,P1),
assert(uttered(P1)),
print(P1),nl},
paragraphs_4_a(Answers2),
{append(Answers1,Answers2,Answers)}.
paragraphs_4_a(Answers) -->
para_mark_410,
paragraphs_4(_,Answers).
paragraphs_4_a([]) --> [].
% statements get added to the database; questions get asked, and are not added
% questions are considered interpolation in text: in text: [sentence1,
% ? question, CONNECTIVE sentence2], sentence1 and sentence2 are considered
% joined by CONNECTIVE
paragraph_A_10(X,Sentence,Para,Answers) -->
paragraph_B_11(P),
paragraph_A_10_a(X,Sentence,P,Para,Answers).
paragraph_A_10_a(statement,c(CONN,PrevSent,NextSent),PrevSent,Para,Answers) -->
i_819(xu),
paragraph_A_10(question(CONN),NextSent,Para,Answers).
paragraph_A_10_a(statement,c(CONN,PrevSent,NextSent),PrevSent,Para,Answers) -->
i_819(CONN),
{CONN \= xu},
paragraph_A_10(statement,NextSent,Para,Answers).
paragraph_A_10_a(question(CONN),NextSent,PrevSent,Para,[Answer|Answers]) -->
i_819(xu),
{ask(PrevSent,Para,Answer)},
paragraph_A_10(question(CONN),NextSent,Para,Answers).
% connective functor: fragments P and T are connected by binary connective CONN
paragraph_A_10_a(question(CONN),NextSent,PrevSent,Para,[Answer|Answers]) -->
i_819(CONN),
{CONN \= xu,
ask(PrevSent,Para,Answer)},
paragraph_A_10(statement,NextSent,Para,Answers).
paragraph_A_10_a(statement,P,P,Para,[]) -->
[].
paragraph_A_10_a(question(seq),[],PrevSent,Para,[Answer]) -->
[],
{ask(PrevSent,Para,Answer)}.
paragraph_B_11(P) --> sentence_40(P).
sentence_40(Predication) -->
bridi_tail_50([],2,Predication);
sentence_A_41(Predication).
sentence_A_41(c(CONN,P1,P2)) -->
gek_807(CONN),sentence_A_41(P1),
gik_816,sentence_40(P2).
sentence_A_41(P) --> statement_42(_,P).
% prolog counts arguments as we go; start at 1. Having read all arguments
% before the bridi_tail, we will be up to the Nth argument --- where
% bridi_tail picks up the count after the predicate itself
% Predication1 is the tail of Predication supplied by bridi_tail
statement_42(Foreargs,Predication) -->
terms_80(Foreargs,1,_,N,Predication,Predication1),
{nonvar(N)},
statement_42_a(Foreargs,N,Predication1).
statement_42_a(Foreargs,N,Predication1) -->
{nonvar(N)},
bridi_tail_50(Foreargs,N,Predication1);
front_gap_451,
{nonvar(N)},
bridi_tail_50(Foreargs,N,Predication1).
bridi_tail_50(Foreargs,N,P) -->
bridi_tail_A_51(Foreargs,N,P).
bridi_tail_A_51(Foreargs,N,P) -->
{append(Foreargs,Tailargs,ArgsIn)},
bridi_tail_C_53(ArgsIn,N,P1),
gihek_818(Conn),
bridi_tail_C_53(ArgsIn,N,P2),
tail_terms_71(Tailargs,N,P,c(Conn,P1,P2)).
bridi_tail_A_51(Foreargs,N,P) -->
bridi_tail_C_53(Foreargs,N,P).
bridi_tail_C_53(Foreargs,N,Predication,SIn,SOut):-
append(Foreargs,Tailargs,ArgsIn),
selbri_130(ArgsIn,Bridi,SIn,SOut1),
tail_terms_71(Tailargs,N,Predication,Bridi,SOut1,SOut2),
SOut2 = SOut.
tail_terms_71([],_,P,P) -->
vau_gap_456.
tail_terms_71(Tailargs,N,P,P1) -->
{nonvar(N)},
terms_80(Tailargs,N,_,_,P,P1), vau_gap_456.
% we anticipate the head of the list to be the Mth argument. We find its
% successor will be the Nth. The successor of the last argument in the list
% (return argument) will be the Xth.
terms_80([Arg|Tail],M,N,X,P,P1) -->
term_81(Arg,M,N,P,P2), terms_80_a(Tail,N,X,P2,P1).
terms_80_a(Tail,N,X,P2,P1) -->
terms_80(Tail,N,_,X,P2,P1).
terms_80_a([],N,N,P1,P1) --> [].
% default: arguments are in seq. x1 x2 x3, so successor of x(n) is x(n+1)
term_81(term(M,Arg),M,N,P,P1) -->
{nonvar(M),N is M + 1},
sumti_90(Arg,P,P1).
% the function of mod_head_490 is to alter this default; thus M is ignored
% in determining the ordinal of the argument
term_81(term(X,Arg),M,N,P,P1) -->
modifier_82(Arg,M,X,N,P,P1).
% for time being, ignore these in building up predication
modifier_82([],M,X,N,P,P) -->
mod_head_490(M,X,N), gap_450.
modifier_82(Arg,M,X,N,P,P1) -->
mod_head_490(M,X,N), sumti_90(Arg,P,P1).
sumti_90(Arg,P,P1) --> sumti_A_91(Arg,P,P1).
sumti_A_91(Arg,P,P1) -->
sumti_D_94(Arg1,P2,P3),
sumti_A_91_a(Arg,P,P1,Arg1,P2,P3).
sumti_A_91_a(c(Conn,X1,X2),q(c(Conn,N1,N2),c(Conn,X1,X2),c(Conn,R1,R2),
c(Conn,M1,M2),P1),P1,X1,q(N1,X1,R1,M1,[]),[]) -->
joik_ek_421(Conn),
sumti_A_91(X2,q(N2,X2,R2,M2,[]),[]).
sumti_A_91_a(Arg,P,P1,Arg,P,P1) -->
[].
sumti_D_94(Arg,P,P1) -->
sumti_E_95(Arg,Clause,P,P1),
sumti_D_94_a(Arg,Clause).
sumti_D_94_a(Arg,Clause) -->
relative_clauses_121(Arg,Clause).
sumti_D_94_a(Arg,_) --> [].
sumti_E_95(Arg,Clause,P,P1) -->
sumti_F_96(Arg,suho(1),Clause,P,P1).
sumti_E_95(Arg,Clause,P,P1) -->
quantifier_300(N),
sumti_F_96(Arg,N,Clause,P,P1).
% for now, ignore numbering of or relative clauses on anaphors and names;
% iota quantification with quantifier "la"
sumti_F_96(Arg,_,_,q(la,Arg,[],[],P),P) -->
anaphora_400(Arg);
la_558, cmene_405(Arg).
% term q is quantifier: number, variable, initial restricting predication,
% further restricting predications, remainder of predication
sumti_F_96(Arg,N,Clause,q(N,Arg,Restrict,Clause,P1),P1) -->
description_110(Arg,Restrict).
description_110(X,Restrict) -->
le_562,
sumti_tail_A_112(X,Restrict),
gap_450.
sumti_tail_A_112(X,Restrict) -->
selbri_130([term(1,X)],Restrict).
relative_clauses_121(X,Clause) -->
relative_clause_122(X,Clause).
relative_clause_122(X,Clause) -->
noi_585, sentence_40(Clause1), kuho_gap_469,
{anaphorise(keha,X,Clause1,Clause)}.
% The instantiation of X will eventually force execution of order_transform
% to delay until ArgsIn is fully known
selbri_130(ArgsIn,Predication) -->
tanru_unit_A_151(ArgsIn,Predication,P1).
/*tanru_unit_A_151(ArgsIn,Predication,Predication) -->
tanru_unit_B_152(ArgsIn,ArgsOut,Selbri),
{functor(Predication,Selbri,5),
fill_in_args(Predication,ArgsOut)}.
tanru_unit_A_151(ArgsIn,P,Predication) -->
tanru_unit_B_152(ArgsIn1,ArgsOut,Selbri),
linkargs_160(ArgsIn2,P,Predication),
{append(ArgsIn2,ArgsIn,ArgsIn1),
functor(Predication,Selbri,5),
fill_in_args(Predication,ArgsOut)}.*/
tanru_unit_A_151(ArgsIn,P,Predication) -->
tanru_unit_B_152(ArgsIn1,ArgsOut,Selbri),
tanru_unit_A_151_a(ArgsIn,P,Predication,ArgsIn1,ArgsOut,Selbri).
tanru_unit_A_151_a(ArgsIn,Predication,Predication,ArgsIn,ArgsOut,Selbri) -->
{functor(Predication,Selbri,5),
fill_in_args(Predication,ArgsOut)}.
tanru_unit_A_151_a(ArgsIn,P,Predication,ArgsIn1,ArgsOut,Selbri) -->
linkargs_160(ArgsIn2,P,Predication),
{append(ArgsIn2,ArgsIn,ArgsIn1),
functor(Predication,Selbri,5),
fill_in_args(Predication,ArgsOut)}.
tanru_unit_B_152(ArgsIn,ArgsIn,Selbri) -->
bridi_valsi_407(ArgsIn,Selbri).
tanru_unit_B_152(ArgsIn,ArgsOut,Selbri) -->
se_480(N), tanru_unit_B_152(ArgsIn1,Args1,Selbri),
{order_transform(Args1,ArgsOut,N),
ArgsIn = ArgsIn1}.
tanru_unit_B_152(ArgsIn,ArgsOut,Nu) -->
nu_425(Nu),sentence_40(P),
{append(ArgsIn,[term(2,P)],ArgsOut)},
kei_gap_453.
linkargs_160([Arg|Tail],P,P1) -->
be_504, term_81(Arg,2,N,P,P2),
linkargs_160_a(Tail,N,P1,P2).
linkargs_160_a([],_,P,P) -->
beho_gap_467.
linkargs_160_a(Tail,N,P1,P2) -->
links_161(Tail,N,_,P2,P1), beho_gap_467.
links_161([Arg|Tail],N,_,P,P1) -->
bei_505, term_80(Arg,N,N1,P,P2),
links_161_a(Tail,N1,P1,P2).
links_161_a([],_,P1,P1) -->
[].
links_161_a(Tail,N1,P1,P2) -->
links_161(Tail,N1,_,P2,P1).
quantifier_300(N) --> number_812(N), boi_gap_461.
anaphora_400(Arg) --> koha_555(Arg).
anaphora_400([]) --> by_string_817, boi_gap_461.
cmene_405([Arg|Tail]) --> cmene_517(Arg),cmene_405_a(Tail).
cmene_405_a(Tail) --> cmene_405(Tail);
[],
{Tail=[]}.
bridi_valsi_407(Args,Selbri) -->
brivla_509(Args,Selbri).
para_mark_410 --> ['niho'].
joik_ek_421(Conn) -->
ek_802(Conn).
nu_425(nu) --> ['nu'].
nu_425(ka) --> ['ka'].
lex_nu_425(X):- var(X),!,fail.
lex_nu_425(nu).
lex_nu_425(ka).
gap_450 --> ['ku'].
front_gap_451 --> ['cu'].
kei_gap_453 --> ['kei'].
vau_gap_456 --> ['vau'].
boi_gap_461 --> ['boi'].
beho_gap_467 --> ['beho'].
kuho_gap_469 --> ['kuho'].
se_480(N) --> se_596(N).
% M is the anticipated ordinal of the current arg; X is the ordinal of the
% current arg; N, that of its successor. for example, at the start of a
% phrase, M is 1. if 'fe' is encountered, then X is 2 and N is 3.
mod_head_490(_,X,N) --> fa_527(X),{N is X + 1}.
mod_head_490(M,0,M) --> modal_C_975.
a_501(a) --> ['a'].
a_501(e) --> ['e'].
bai_502 --> ['bai'].
be_504 --> ['be'].
bei_505 --> ['bei'].
by_513(b) --> ['by'].
by_513(c) --> ['cy'].
fa_527(1) --> ['fa'].
fa_527(2) --> ['fe'].
fa_527(3) --> ['fi'].
fa_527(4) --> ['fo'].
fa_527(5) --> ['fu'].
ga_537(a) --> ['ga'].
ga_537(e) --> ['ge'].
giha_541(a) --> ['giha'].
giha_541(e) --> ['gihe'].
ja_546(a) --> ['ja'].
ja_546(e) --> ['je'].
koha_555(koha) --> ['koha'].
koha_555(kohe) --> ['kohe'].
koha_555(kohi) --> ['kohi'].
koha_555(koho) --> ['koho'].
koha_555(kohu) --> ['kohu'].
koha_555(foha) --> ['foha'].
koha_555(fohe) --> ['fohe'].
koha_555(fohi) --> ['fohi'].
koha_555(foho) --> ['foho'].
koha_555(fohu) --> ['fohu'].
koha_555(mi) --> ['mi'].
koha_555(keha) --> ['keha'].
koha_555(da) --> ['da'].
koha_555(de) --> ['de'].
koha_555(di) --> ['di'].
% and lexical classification of these:
lex_da_555a(X):- var(X),!,fail.
lex_da_555a(da).
lex_da_555a(de).
lex_da_555a(di).
la_558 --> ['la'].
le_562 --> ['lo'];
['le'].
noi_585 --> ['poi'].
se_596(2) --> ['se'].
se_596(3) --> ['te'].
se_596(4) --> ['ve'].
se_596(5) --> ['xe'].
pa_672(0) --> ['no'].
pa_672(1) --> ['pa'].
pa_672(2) --> ['re'].
pa_672(3) --> ['ci'].
pa_672(4) --> ['vo'].
pa_672(5) --> ['mu'].
pa_672(6) --> ['xa'].
pa_672(7) --> ['ze'].
pa_672(8) --> ['bi'].
pa_672(9) --> ['so'].
pa_672(suho(_)) -->
['suho'].
pa_672(ro) --> ['ro'].
ek_802(Conn) --> a_501(Conn).
jek_805(Conn) --> ja_546(Conn).
gek_807(Conn) --> ga_537(Conn).
number_812(N) --> number_root_961(N).
gik_816 --> ['gi'].
by_string_817 --> by_987;
by_987, by_string_817a.
by_string_817a --> by_987, by_string_817a;
pa_672(_), by_string_817a.
gihek_818(Conn) --> giha_541(Conn).
% just plain sequencing
i_819(Conn) --> ['i'],simple_joik_jek_957(Conn).
i_819(xu) --> ['i','xu'].
i_819(seq) --> ['i'].
simple_joik_jek_957(Conn) --> jek_805(Conn).
number_root_961(N) -->
pa_672(N),{isNumber(N)}.
% "at least" defaults to "at least 1".
number_root_961(suho(1)) -->
pa_672(suho(1)).
number_root_961(ro) -->
pa_672(ro).
number_root_961(N) -->
pa_672(N1),
number_root_961(N2),
{isNumber(N1), N3 is N1 * 10 , N is N3 + N2}.
number_root_961(suho(N)) -->
pa_672(suho(N)),
number_root_961(N).
% "all n": ignore n
number_root_961(ro) -->
pa_672(ro),
number_root_961(_).
modal_C_975 --> bai_502;
se_596(_), bai_502.
by_987 --> by_513(_).
% transform list of lists to list of heads of these lists; designed for use
% with getTokenList
select_first([[A|_]|B],[A|C]):-select_first(B,C).
select_first([[_|end_of_file]],[]).
% get declared lexemes out of file (preceding text) and declare them to
% be part of program vocab. Returns text proper, as remainder of list
lexeme_declarations([end_of_lex_list|Text],Text).
lexeme_declarations([cmene|[X|Tail]],Text):-
% assert(cmene_517(_,X) --> [X]),
assert(cmene_517(X,X.SOut,SOut)),
lexeme_declarations(Tail,Text).
lexeme_declarations([brivla|[X|Tail]],Text):-
% assert(brivla_509(X) --> [X]),
assert(brivla_509(_,X,X.SOut,SOut)),
lexeme_declarations(Tail,Text).
% change the order of arguments in a list, exchanging the 1st and Nth
?- order_transform(A,_,_) when (A).
order_transform([term(1,Arg)|X],[term(N,Arg)|Y],N):-
order_transform(X,Y,N).
order_transform([term(N,Arg)|X],[term(1,Arg)|Y],N):-
order_transform(X,Y,N).
order_transform([term(N,Arg)|X],[term(N,Arg)|Y],M):-
N =\= M, order_transform(X,Y,N).
order_transform([],[],_).
% fill in predication with arguments out of Arglist
?- fill_in_args(_,A) when (A).
fill_in_args(Predication,[]).
fill_in_args(Predication,[term(N,Arg)|Tail]) :-
N > 0,arg(N,Predication,Arg),fill_in_args(Predication,Tail).
fill_in_args(Predication,[term(0,Arg)|Tail]) :-
fill_in_args(Predication,Tail).
% substitute all instances of (atom: anaphor) D with (variable: referent) X
% in predication P, giving predication P1.
%?- anaphorise(_,_,A,_) when A.
anaphorise(D,X,A,A) :- D \== A, var(A).
anaphorise(D,X,A,A) :- D \== A, atomic(A).
anaphorise(D,X,D1,X) :- D == D1.
anaphorise(D,X,P,P1) :-
compound(P),
functor(P,F,N),
ilist(1,N,NList),
functor(P1,F,N),
anaph_recurse(NList,D,X,P,P1).
anaph_recurse([],D,X,_,_).
anaph_recurse([N|T],D,X,P,P1) :-
arg(N,P,Q),
anaphorise(D,X,Q,Q1),
arg(N,P1,Q1),
anaph_recurse(T,D,X,P,P1).
postproc(A,B) :- postproc0(A,C),postproc2(C,D,[],[]),postproc1(D,B),!.
% postprocessing: resolve conjunctions
postproc0(A,A) :- (var(A);atomic(A)),!.
postproc0(q(c(C,N1,N2),c(C,X1,X2),c(C,R1,R2),c(C,M1,M2),P),
c(C,q(N1,X1,R1,M1,Q1),q(N2,X2,R2,M2,Q2))) :-
anaphorise(c(C,X1,X2),X1,P,Q1),
anaphorise(c(C,X1,X2),X2,P,Q2),!.
postproc0(P,P1) :-
functor(P,F,N),
ilist(1,N,NList),
functor(P1,F,N),
postproc0_recurse(NList,P,P1).
postproc0_recurse([],_,_).
postproc0_recurse([N|T],P,P1) :-
arg(N,P,Q),
postproc0(Q,Q1),
arg(N,P1,Q1),
postproc0_recurse(T,P,P1).
% further postprocessing:
% kill "la" quantification (anaphors and names; iota q'ntfn is different)
postproc1(A,A) :- (var(A);atomic(A)),!.
postproc1(q(la,X,R,M,Q),Q1) :-
postproc1(Q,Q1),!.
postproc1(P,P1) :-
functor(P,F,N),
ilist(1,N,NList),
functor(P1,F,N),
postproc1_recurse(NList,P,P1).
postproc1_recurse([],_,_).
postproc1_recurse([N|T],P,P1) :-
arg(N,P,Q),
postproc1(Q,Q1),
arg(N,P1,Q1),
postproc1_recurse(T,P,P1).
postproc2(A,A,B,B):-
(var(A);atomic(A)),!.
postproc2(q(la,Da,R,M,P),q(suho(1),X,R1,M1,P1),RestOfPara,RestOfPara1):-
lex_da_555a(Da),
anaphorise(Da,X,P,P2),
anaphorise(Da,X,R,R2),
anaphorise(Da,X,M,M2),
% if da occurs in one phrase, anaphorise it throughout the paragraph!
anaphorise(Da,X,RestOfPara,RestOfPara2),
postproc2(R2,R1,RestOfPara2,RestOfPara3),
postproc2(M2,M1,RestOfPara3,RestOfPara4),
postproc2(P2,P1,RestOfPara4,RestOfPara1),!.
postproc2(q(Q,X,R,M,P),q(Q,X,R1,M1,P1),RestOfPara,RestOfPara1):-
(Q \= la ; not lex_da_555a(X)),
postproc2(R,R1,RestOfPara,RestOfPara2),
postproc2(M,M1,RestOfPara2,RestOfPara3),
postproc2(P,P1,RestOfPara3,RestOfPara1),!.
postproc2(c(C,A,B),c(C,A1,B1),RestOfPara,RestOfPara1):-
postproc2(A,A1,[B|RestOfPara],[B2|RestOfPara2]),
postproc2(B2,B1,RestOfPara2,RestOfPara1),!.
postproc2(A,A1,RestOfPara,RestOfPara1):-
nonvar(A),functor(A,F,N),ilist(1,N,NL),
F \= q, F \= c,
postproc2_recurse(NL,A,A1,RestOfPara,RestOfPara1).
postproc2_recurse([],A,A,B,B).
postproc2_recurse([H|T],A,A1,RestOfPara,RestOfPara1):-
arg(H,A,B),arg(H,A1,B1),
postproc2(B,B1,RestOfPara,RestOfPara2),
postproc2_recurse(T,A,A1,RestOfPara2,RestOfPara1).
% generate list of numbers between A and B
ilist(A,A,[A]).
ilist(A,B,[A|T]):- A < B, C is A + 1,ilist(C,B,T).
transform_semantic(P,Q):-
permuteQ1(_,P,Q);
generalise(P,P1),permuteQ1(_,P1,Q).
% generalise quantifiers: if A then E, etc.
generalise(P,P):- (var(P);atomic(P)),!.
generalise(q(Q,X,R,M,P),q(suho(1),X,R1,M1,P1)):-
(Q = la ; Q = ro ),
generalise(R,R1),
generalise(M,M1),
generalise(P,P1).
generalise(q(Q,X,R,M,P),q(Q,X,R1,M1,P1)):-
generalise(R,R1),
generalise(M,M1),
generalise(P,P1).
generalise(P,Q):-
functor(P,Functor,2),lex_nu_425(Functor),
functor(Q,Functor,2),arg(1,P,X),arg(1,Q,X),
arg(2,P,Sent),generalise(Sent,Sent1),arg(2,Q,Sent1).
generalise(P,P):-
functor(P,F,_),F \= q.
% delete a quantification q(Q,X,R,M,_) from a clause
%?- deleteQ(_,_,_,_,q(_,_,_,_,A),B) when A or B.
deleteQ(Q,X,R,M,q(Q,X,R,M,P),P).
deleteQ(Q,X,R,M,q(Q1,X1,R1,M1,q(Q2,X2,R2,M2,P)),
q(Q1,X1,R1,M1,P1)):-
deleteQ(Q,X,R,M,q(Q2,X2,R2,M2,P),P1).
deleteQ(_,_,_,_,P,P):-
functor(P,Functor,_),Functor \= q.
% return: the subsection of the current clause starting at the first
% quantifier other than the current one; also return the whole clause
% such that this subsection may be permuted in permuteQ1
getnextQ1(Q,q(Q,X,R,M,P),q(Q,X,R,M,P1),P2,P3):-
nonvar(P),getnextQ(Q,P,P1,P2,P3).
getnextQ1(Q,q(Q1,X,R,M,P),P1,q(Q1,X,R,M,P),P1):- nonvar(Q1),Q \= Q1.
getnextQ(Q,P0,P1,P2,P3):- getnextQ1(Q,P0,P1,P2,P3).
getnextQ(Q,P0,P1,P3,P4):-
getnextQ1(Q,P0,P1,q(Q1,X,R,M,P),P2),
getnextQ(Q1,q(Q1,X,R,M,P),P2,P3,P4).
% form all permutations of contiguous quantifications with same quantifier
permuteQ1(_,P,P):- (var(P);atomic(P)),!.
permuteQ1(Q,q(Q,X1,R1,M1,P1),q(Q,X2,R,M,P2)):-
deleteQ(Q,X2,R2,M2,q(Q,X1,R1,M1,P1),P3),
permuteQ1(_,R2,R),permuteQ1(_,M2,M),
permuteQ1(Q,P3,P2).
permuteQ1(Q,q(Q1,X1,R1,M1,P1),q(Q1,X1,R1,M1,P1)):- Q \= Q1.
permuteQ1(_,q(Q,X,R,M,P),WholeSentence):-
getnextQ(Q,q(Q,X,R,M,P),WholeSentence,NewSubSect,NewSubSectPerm),
permuteQ1(_,NewSubSect,NewSubSectPerm).
permuteQ1(_,P,Q):-
functor(P,Functor,2),lex_nu_425(Functor),
functor(Q,Functor,2),arg(1,P,X),arg(1,Q,X),
arg(2,P,Sent),permuteQ1(_,Sent,Sent1),arg(2,Q,Sent1).
permuteQ1(_,P,P):-
functor(P,Functor,_),Functor \= q.
% expand embedded conjunctions in a sentence to the sentence level. e.g.
% ExEy&(EzA,Ew+(EvB,EuC)) expands to &(ExEyEzA,+(ExEyEwEvB,ExEyEzEuC))
% Applying this transformation to a text allows a question concerning a
% possible alternative such as ?ExEyEzA to be answered in the affirmative.
conjexpand(P,P,Pred,Pred):-
var(P),!;
nonvar(P),functor(P,F,_),F \= q, F \= c.
conjexpand(q(Q,X,R,M,P),q(Q,X,R,M,P1),PrenexToDate,Expansion):-
conjexpand(P,P1,PrenexToDate,Expansion).
conjexpand(c(C,A,B),P,PrenexToDate,c(C,Expansion1,Expansion2)):-
nonvar(PrenexToDate),
anaphorise(P,P1,PrenexToDate,PrenexToDate1),
anaphorise(P,P2,PrenexToDate,PrenexToDate2),
conjexpand(A,P1,PrenexToDate1,Expansion1),
conjexpand(B,P2,PrenexToDate2,Expansion2).
conjexpand(c(C,A,B),P,PrenexToDate,c(C,Expansion1,Expansion2)):-
var(PrenexToDate),
conjexpand(A,P1,P1,Expansion1),
conjexpand(B,P2,P2,Expansion2).
% when a para is still being parsed, the next sentence after a question is a
% variable; this disrupts the program by futile delays, so replace it with []
paracutoff(c(C,A,B),c(C,A,[])):- var(B).
paracutoff(c(C,A,B),c(C,A,B)):- nonvar(B).
% unidirectional unification. Thus, is database has car(red) and question
% seeks car(_), unify; but if database has car(_), and question has car(red),
% do not unify for lack of sufficient info
unify(A,B):-
(var(A);nonvar(B),atomic(B)),A = B, !.
unify(A,B):-
nonvar(A),functor(A,F,N),nonvar(B),functor(B,F,N),
ilist(1,N,NL),unify_recurse(NL,A,B).
unify_recurse([],_,_).
unify_recurse([H|T],A,B):-
arg(H,A,A1),arg(H,B,B1),
unify(A1,B1),unify_recurse(T,A,B).
?- ask3(_,c(A,_,_),_) when A.
ask3(P,X,_):- var(X),!,fail.
ask3(P,c(seq,P1,_),Ans):- ask3(P,P1,Ans).
ask3(P,c(seq,_,P2),Ans):- ask3(P,P2,Ans).
ask3(P,c(e,P1,_),Ans):- ask3(P,P1,Ans).
ask3(P,c(e,_,P2),Ans):- ask3(P,P2,Ans).
ask3(X,Y,Y):-
nonvar(X),nonvar(Y),
duplicate(X,X1),duplicate(Y,Y1),
unify(X1,Y1).
?- ask2(_,c(A,_,_)) when A.
ask2(P,X):- conjexpand(P,Q,Q,P1),ask2a(P1,X).
ask2a(P,X):- functor(P,F,_),F \= c,ask3(P,X,_).
ask2a(c(a,A,B),X):- ask2a(A,X);ask2a(B,X).
ask2a(c(a,A,B),X):- ask3(c(a,A,B),X,_);ask3(c(a,B,A),X,_).
ask2a(c(e,A,B),X):-
ask3(A,X,Ans1),ask3(B,X,Ans2),
duplicate(c(e,A,B),c(e,Ans1,Ans2)).
% to guarantee we get any common prenexes right
ask1(P,X):-
conjexpand(X,Q,Q,X1),ask2(P,X1).
ask1(P,_):-
uttered(X),conjexpand(X,Prenex,Prenex,X1),ask2(P,X1).
ask(P,X,Ans):-
transform_semantic(P,P1),
postproc(P1,P2),
paracutoff(X,X1),
postproc(X1,X2),
ask1(P2,X2) -> Ans=yes;
Ans=no_answer.
parse(File) :-
cd('/stude/mundil/n/nsn/603'),
open(File,read,Stream),
getTokenList(Stream,TokList),
select_first(TokList,WordList),
lexeme_declarations(WordList,Text),
phrase(text_0,Text).
---
'Dera me xhama t"e larm"e, T Nick Nicholas, CgS & CS, Melbourne Uni
Dera mbas blerimit | nsn@munagin.ee.mu.oz.au (IRC: nicxjo)
Me xhama t"e larm"e! | Milaw ki ellhnika/Esperanto parolata/
Lumtunia nuk ka ngjyra tjera.' | mi ka'e tavla bau la lojban. je'uru'e
- Martin Camaj, _Nj"e Shp'i e Vetme_ | *d'oh!*