/* Mike Hammond, University of Arizona, 1997.
This is the locally encoded syllable parser with
one-pass complete sampling of the input string.
Here candidate syllabifications are indicated
in terms of properties of the current segment. This
method also makes use of a cyclic CON-EVAL procedure.
The doit loop is the 'main'.
The other parsers invoke cyclic constraint
evaluation by itself (mhcyclicparse), an
incremental parse by itself (mhlrparse), and
a cyclic/local parser with a left-to-right
parse (mhlrlocalparse). There is also a parser
that invokes nothing special (mhdumbparse). */
doit :-
babble,
unix(argv([Word|Constraints])),
makelist(Word,Inputlist),
check(Inputlist),
dwrite('acceptable word...'),dnl,
gen(Inputlist,Syllabified),
dwrite('candidates generated...'),dnl,
doconstraints(Syllabified,Constraints,Winners),
dwrite('**********************'),dnl,
printlist(Winners,_).
/* To get annoyingly verbose output, change
false to true. */
mhdebug :- true.
/* byline */
babble :-
write('Locally encoded syllable parser
'),nl,
write('Michael Hammond
'),nl,
write('University of Arizona
'),nl,
write('1997
'),nl.
/* These routines allow for the annoyingly verbose output. */
dwrite(X) :-
mhdebug,
write(X).
dwrite(_).
dnl :-
mhdebug,
write('
'),
nl.
dnl.
dtab(X) :-
mhdebug,
tab(X).
dtab(_).
/* The following routines get an input word from
the user, check it against the alphabet defined
at the end, and convert it into an appropriate
data structure. */
getword(Word) :-
write('word to parse: '),
read(Word).
makelist(Input,Inputlist) :-
name(Input,Templist),
numchar(Templist,Inputlist).
numchar([],[]).
numchar([H|T],[H1|T1]) :-
name(H1,[H]),
numchar(T,T1).
check([]).
check([H|T]) :-
segment(H),
check(T).
/* each segment has four options: unparsed (u), onset (o),
coda (c), nucleus(n). */
gen([],[]).
gen([H|T],[H/[o,n,c,u]|T2]) :- gen(T,T2).
/* 'doconstraints' applies the constraints to the
input one by one. For each parse, first a full
tableau is created, and then eval is called to
select winning candidates to pass on to the next
parse. */
doconstraints(Final,[],Final).
doconstraints(Theparse,[Topcon|Othercons],Final) :-
formal(Theparse,Tempparse),
It =.. [Topcon,Tempparse,Nextparse],
call(It),
dwrite(Topcon),
dwrite(': '),
dwrite(Theparse),
dwrite(': '),
dwrite(Nextparse),dnl,
doconstraints(Nextparse,Othercons,Final).
/* 'formal' does the housekeeping between constraints */
formal(X,W) :-
formali(X,Y),
formalf(Y,Z),
formalmo(Z,A),
formalmc(A,W).
formali([A/X|B],[A/Y|B]) :- remove(X,c,Y).
formali(X,X).
formalf([A/X],[A/Y]) :- remove(X,o,Y).
formalf([],[]).
formalf([H|T],[H|T2]) :- formalf(T,T2).
formalmc([],[]).
formalmc([A/X|B/[c]],[A/Y|B/[c]]) :- remove(X,o,Y).
formalmc([H,H2|T],[H4,H5|T2]) :-
formalmc([H2|T],[H3|T2]),
formalmc([H|H3],[H4|H5]).
formalmc([H|T],[H|T2]) :- formalmc(T,T2).
formalmo([],[]).
formalmo([A/[o],B/X|T],[A/[o],B/Z|T2]) :-
remove(X,c,Y),
formalmo([B/Y|T],[B/Z|T2]).
formalmo([H|T],[H|T2]) :- formalmo(T,T2).
/* Various basic tasks.... */
contains(X,Y) :- append(_,[Y|_],X).
remove(X,Y,Z) :-
append(P,[Y|Q],X),
append(P,Q,Z),
notempty(Z).
notempty([_]).
notempty([_|T]) :- notempty(T).
append([],L,L).
append([H|T],L,[H|T2]) :- append(T,L,T2).
/* The following routines are responsible for
the different constraints. */
parse([],[]).
parse([Left/Options|Right],[Left/Newoptions|Newright]) :-
remove(Options,u,Newoptions),
parse(Right,Newright).
parse([Left|Right],[Left|Newright]) :- parse(Right,Newright).
onset(X,Z) :-
wonset(X,Y),
monset(Y,Z).
wonset([Y/L1|X],[Y/L2|X]) :- remove(L1,n,L2).
wonset(X,X).
monset([],[]).
monset([First/L1,Second/[n]|Rest],[First/[o],Second/[n]|Newrest]) :-
contains(L1,o),
monset(Rest,Newrest).
monset([H|T],[H|T2]) :- monset(T,T2).
nocoda([],[]).
nocoda([First/L1|Right],[First/L2|Newright]) :-
remove(L1,c,L2),
nocoda(Right,Newright).
nocoda([H|T],[H|T2]) :- nocoda(T,T2).
complex([],[]).
complex([First/[c],Second/L2|Right],[First/[c],Second/L3|Newright]) :-
remove(L2,c,L3),
complex(Right,Newright).
complex([First/[o],Second/L2|Right],[First/[o],Second/L3|Newright]) :-
remove(L2,o,L3),
complex(Right,Newright).
complex([First/L2,Second/[c]|Right],[First/L3,Second/[c]|Newright]) :-
remove(L2,c,L3),
complex(Right,Newright).
complex([First/L2,Second/[o]|Right],[First/L3,Second/[o]|Newright]) :-
remove(L2,o,L3),
complex(Right,Newright).
complex([H|T],[H|T2]) :- complex(T,T2).
vmargin([],[]).
vmargin([V/X|T],[V/Y|T2]) :-
vowel(V),
remove(X,o,Z),
remove(Z,c,Y),
vmargin(T,T2).
vmargin([V/X|T],[V/Y|T2]) :-
vowel(V),
remove(X,o,Y),
vmargin(T,T2).
vmargin([V/X|T],[V/Y|T2]) :-
vowel(V),
remove(X,c,Y),
vmargin(T,T2).
vmargin([H|T],[H|T2]) :- vmargin(T,T2).
cpeak([],[]).
cpeak([C/X|T],[C/Y|T2]) :-
consonant(C),
contains(X,n),
remove(X,n,Y),
cpeak(T,T2).
cpeak([H|T],[H|T2]) :- cpeak(T,T2).
/* The following routines massage the winning candidates
into a visually appropriate form and print them out. */
printlist(Realwinners,Biglist) :-
convert(Realwinners,Biglist),
prettyprint(Biglist,_).
convert([],[[]]).
convert([H|T],New) :-
makecans(H,Cans),
convert(T,T2),
cartesian(Cans,T2,New).
makecans(Seg/[X],[Seg/X]).
makecans(Seg/[H|T],[Seg/H|T2]) :- makecans(Seg/T,T2).
cartesian([],_,[]).
cartesian([H|T],X,Done) :-
cartesian(T,X,Postdone),
ractesian(H,X,Predone),
append(Predone,Postdone,Done).
ractesian(_,[],[]).
ractesian(X,[H|T],[H2|T2]) :-
append([X],H,H2),
ractesian(X,T,T2).
prettyprint([],[]).
prettyprint([H|T],[H6|T2]) :-
dwrite(H),dtab(1),
leftedge(H,H2),
rightedge(H2,H3),
stripseg(H3,H4),
listmake(H4,H5),
name(H6,H5),
write(H6),
write('
'),nl,
prettyprint(T,T2).
listmake([],[]).
listmake([H|T],[X|T1]) :-
name(H,[X]),
listmake(T,T1).
stripseg([],[]).
stripseg([X/_|T],[X|T2]) :- stripseg(T,T2).
stripseg([H|T],[H|T2]) :- stripseg(T,T2).
rightedge(X,Y) :-
marknucr(X,Z),
markcod(Z,Y).
marknucr([],[]).
marknucr([X/n|T],[X/n,')'|T2]) :- marknucr(T,T2).
marknucr([H|T],[H|T2]) :- marknucr(T,T2).
markcod(A,B) :-
append(C,[')',D/c|E],A),
append(C,[D/c,')'|E],F),
markcod(F,B).
markcod(A,A).
leftedge(X,Y) :-
marknuc(X,Z),
markons(Z,Y).
marknuc([],[]).
marknuc([X/n|T],['(',X/n|T2]) :- marknuc(T,T2).
marknuc([H|T],[H|T2]) :- marknuc(T,T2).
markons(A,B) :-
append(C,[D/o,'('|E],A),
append(C,['(',D/o|E],F),
markons(F,B).
markons(A,A).
/* The following facts define the acceptable alphabet */
segment(X) :- vowel(X).
segment(X) :- consonant(X).
vowel(a).
consonant(b).
consonant(c).
consonant(d).
vowel(e).
consonant(f).
consonant(g).
consonant(h).
vowel(i).
consonant(j).
consonant(k).
consonant(l).
consonant(m).
consonant(n).
vowel(o).
consonant(p).
consonant(q).
consonant(r).
consonant(s).
consonant(t).
vowel(u).
consonant(v).
consonant(w).
consonant(x).
consonant(y).
consonant(z).
/* That's all! */