Article View: comp.lang.prolog
Article #317A phrase generator for Prolog DCG's
From: Ken Johnson
Date: Tue, 12 Sep 1989 16:54
Date: Tue, 12 Sep 1989 16:54
132 lines
5299 bytes
5299 bytes
I've found that the usual way of teaching about grammars with Lisp and
Logo involves generating random phrases freom a grammar whereas Prolog's
DCG mechanism does not allow you to do that: it just checks whether a
given string of non-terminals can be derived from the grammar or not.
Here is a phrase generator that generates phrases at random from a DCG,
which may add a touch of humour to an otherwise forebodingly dull topic.
(That's a value judgement of course and you're free to disagree with
it.) There is a simple DCG attached to this phrase generator; it should
work with other DCGs. If anyone can find a general way to make the code
understand about arguments to non-terminals, I would be interested to
see how it is done. (I mean rules like sentence(Number) -->
nounphrase(Number), verbphrase(Number). where Number is `singular' or
`plural').
*************************************************************************
* H. M. GOVERNMENT HEALTH WARNING... *
* *
* The code ASSUMES that your Prolog stores DCG information *
* in the same way that Edinburgh Prolog does. Not all *
* Prologs store DCG rules that way. *
*************************************************************************
I have tested this code with Edinburgh Prolog (the New Implementation),
version 1.5.04 dated 12 September 1988 (Happy birthday to you, happy
birthday to yooooooooooooooo! :-) and it seemed to work.
To run the program as it stands, give the command
?- repeat,
gen_phrase(insult,Stuff),
write(Stuff),
nl,
fail.
Share, enjoy, and good luck:
Cut here ------------ 8< ------------ cut here ------------ 8< ------------
% Phrase generator: generate a phrase at random from a simple DCG.
% Ken Johnson 12-9-89
% You may make and distribute copies of this code if you want to,
% except that if you sell them at a profit I want a share.
% The top level phrase generator: given a class name it will
% produce a sentence that matches the pattern defined in the DCG.
% Example invocation:
% gen_phrase(insult,Outcome).
% The insults grammar is given after the important bits.
% This generator does not understand about arguments to non-terminals,
% the use of { }, or anything else. Don't say I didn't tell you.
gen_phrase(Class,Outcome) :- % This predicate serves only
gen_1_phrase(Class,Outcome). % to give repeated
% instantiations of Outcome
gen_phrase(Class,Outcome) :- % on backtracking.
gen_phrase(Class,Outcome).
% Generate a single phrase
gen_1_phrase(Class,Outcome) :-
gen_1_phrase(Class,X-X,Outcome-[]). % Call with accumulator X-X
gen_1_phrase(Class,So_far,Outcome) :- % Create a term insult(_,_)
functor(Term,Class,2), % which matches the clauses
setof(Body,clause(Term,Body),Set), % of the DCG, then pick one
pick_one(Set,A_body), % matching clause and
expand(A_body,So_far,Outcome). % expand it
% Expand a non-terminal, or sequence of non-terminals
expand((P,Q),A,C) :- % Expand (P,Q) by expanding
!, % P and then appending the
expand(P,A,B), % expansion of Q
expand(Q,B,C).
expand('C'(_,Word,_),U-[Word|V],U-V). % The predicate `C' processes
% ground atoms; for non-
expand(Term,So_far,Outcome) :- % terminals, use gen_1_phrase
functor(Term,Functor,_), % recursively to expand them
Functor \== 'C',
gen_1_phrase(Functor,So_far,Outcome).
% Pick at random from a list
pick_one(List,Element) :-
length(List,Length),
random(Length,Random_int),
nth(Random_int,List,Element).
nth(0,[X|_],X). % n'th element of a list
nth(N,[_|T],X) :-
N > 0,
M is N - 1,
nth(M,T,X).
random(Modulus,N) :- % Pretty awful random number
recorded(random_seed,Seed,Ref), % generator. If no seed, it
!, % uses 13 so it always goes
erase(Ref), % through the same sequence
random(Modulus,Seed,N).
random(Modulus,N) :-
random(Modulus,13,N).
random(Modulus,Seed,N) :-
New is ((125 * Seed) mod 4093),
record(random_seed,New,_),
N is New mod Modulus.
% ------------------------------------------------------------------------
% An Insults Grammar
% Here is an example DCG with which gen_phrase works
% I first came across this grammar in Alan Bundy's book so I think I
% ought tell you it isn't original to me.
insult --> action, [you], misname.
action --> [sod,off].
action --> [take,a,running,jump].
misname --> [cretin].
misname --> [bum].
misname --> [great,pillock].
--
Ken Johnson, AI Applications Institute, 80 South Bridge, Edinburgh EH1 1HN
E-mail ken@aiai.ed.ac.uk, phone 031-225 4464 extension 212
`I have read your article, Mr. Johnson, and I am no wiser than when I
started.' -- `Possibly not, sir, but far better informed.'
Technical Details
Message-ID:
<873@skye.ed.ac.uk>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!ames!lll-winken!uunet!mcsun!ukc!edcastle!aiai!kenShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!ames!lll-winken!uunet!mcsun!ukc!edcastle!aiai!ken From: ken@aiai.ed.ac.uk (Ken Johnson) Newsgroups: comp.lang.prolog Subject: A phrase generator for Prolog DCG's Keywords: dcg prolog sentences Message-ID: <873@skye.ed.ac.uk> Date: 12 Sep 89 16:54:10 GMT Reply-To: ken@aiai.UUCP (Ken Johnson) Followup-To: comp.lang.prolog Organization: AIAI, University of Edinburgh, Scotland Lines: 132