#.H1 Story.awk
#.H2 Synopsis
#.PRE
#echo Goal | gawk -f story.awk [ -v Grammar=FILE ] [ -v Seed=NUMBER ]
#echo Goal | gawk -f storyp.awk [ -v Grammar=FILE ] [ -v Seed=NUMBER ]
#./PRE
#.H2 Download
#.P
#Download from
#.URL http://lawker.googlecode.com/svn/fridge/lib/awk/grammar LAWKER.
#.H2 Description
#.P
#This code inputs a set of productions
#and outputs a string of words that satisfy the production rules.
#.P
#This page describes two versions of that system:
#story.awk
#and
#storyp.awk.
#The former selects productions at random with equal probability. The latter
#allows the user to bias the selection by adding weights at the end of line, after
#each production.
#.H2 Options
#.DL
#.DT -v Grammar=FILE
#.DD Sets the FILE containing the productions. Defaults to "grammar".
#.DT -v Seed=NUM
#.DD
# Sets the seed for the random number generator. Defaults to "1".
#A useful idiom for generating random text is to use Seed=$RANDOM
#./DL
#.H2 Examples
#.H3 A Short Example
#.P
# This grammar..
#.LISTING eg/english.rules
# ... and this input ...
#.LISTING eg/english
# ... generates these sentences:
#.LISTING eg/english.out
#.H3 A Longer Example
#.P Here is Gahan Wilson's sci-fi plot generator ...
#
#
#
#
#
#.P
#Using the above, we can generate the following stories:
#.LISTING eg/story.out
#.P
#This is generated from the following code:
#.LISTING eg/story
#.P running on the following grammar:
#.LISTING eg/scifi.rules
#.H3 Biasing the Story
#.P
#Here is a grammar suitable for storyp.awk. Note that number at end of line that biases how often a
#production is selected. For example, "runs" and "slowly" are nine times more likely than other Verbs
# and Adverbs.
#.LISTING eg/englishp.rules
#The following code executes the biases story generation:
#.LISTING eg/englishp
#.P
#This produces the following output. Note that, usually, we run slowly.
#.LISTING eg/englishp.out
#.H2 Code
#.H3 Story.awk
#.PRE
BEGIN {
N=1
srand(Seed ? Seed : 1)
Grammar = Grammar ? Grammar : "grammar"
while (getline < Grammar > 0)
if ($2 == "->") {
i = ++lhs[$1] # count lhs
rhscnt[$1, i] = NF-2 # how many in rhs
for (j = 3; j <= NF; j++) # record them
rhslist[$1, i, j-2] = $j
} else
if ($0 !~ /^[ \t]*$/)
print "illegal production: " $0
}
{ if ($1 in lhs) # nonterminal to expand
while(N--) {
printf("\n")
gen($1)
printf("\n")
}
else
print "unknown nonterminal: " $0
}
function gen(sym, i, j) {
if (sym in lhs) { # a nonterminal
i = int(lhs[sym] * rand()) + 1 # random production
for (j = 1; j <= rhscnt[sym, i]; j++) # expand rhs's
gen(rhslist[sym, i, j])
} else {
gsub(/_/," ",sym)
printf("%s ", sym) }
}
#./PRE
#.H3 Storyp.awk
#.P
# Storyp.awk is almost the same as story.awk but it is assumed that each line ends in a number
# that will bias how often that production gets selected.
#.LISTING storyp.awk
#.H2 Author
#.P
#The code comes from
#Alfred Aho, Brian Kernighan, and Peter Weinberger from the
# book "The AWK Programming Language",
#Addison-Wesley, 1988.
#.P
#The scifi grammar was written by Tim Menzies, 2009, and is based on
#Gahan Wilson's sci-fi plot generator:
#"The Science Fiction Horror Movie Pocket Computer"
#( in "The Year's Best Science Fiction No. 5", edited by
#Harry Harrison and Brian Aldiss, Sphere, London, 1972).