Due: November 29, Midnight

50 Pts.

For this assignment, you will use lisp to generate random
strings from a context-free grammar. The grammar will
be represented in an alist bound to the name `curr-grammar`

. For
instance,

```
(setq curr-grammar '(
(Expr . (
(Expr + Prod)
(Prod) )
)
(Prod . (
(Prod * Term)
(Term) )
)
(Term . ((id) ( "(" Expr ")" )))
(id . ((a) (b) (c)))
))
```

corresponds to the grammar

<*expr*> --> <*expr*> + <*prod*> | <*prod*>

<*prod*> --> <*prod*> * <*term*> | <*term*>

<*term*> --> <*id*> | ( <*expr*> )

<*id*> --> **a** | **b** | **c**

In `curr-grammar`

, each dot pair represents one
replacement. The left item of each pair is a nonterminal
symbol, and the right side is a list of replacements. Each member
of the list represents one alternative which may replace the
right side. Each alternative is itself a list of the items of
the replacement. Each replacement is a list, even if if it contains
only a single item.

You are to write a lisp function `(speak)`

which generates a
sentence from the grammar at random. It should assume that `curr-grammar`

has been `setq`

ed to the CFG upon which it should operate. For instance,
using the above grammar, we could produce something like this:

```
[1]> (load "grammar.lisp")
;; Loading file grammar.lisp ...
;; Loading of file grammar.lisp is finished.
T
[2]> (load "rsent.lisp")
;; Loading file rsent.lisp ...
;; Loading of file rsent.lisp is finished.
T
[3]> (speak)
(C + "(" A * "(" A + "(" "(" A * C + "(" B + C + "(" C * "(" B * B + A ")" * C
+ B ")" + "(" "(" B + B * "(" A ")" * B * B ")" + B ")" * "(" B * A ")" * C *
A * A * A * "(" "(" "(" B + C * B * A * B * B + C ")" ")" * C + B + "(" "(" C
* "(" "(" A ")" * B * C + C ")" * "(" "(" C * B * A * A ")" ")" * "(" C ")" *
C + "(" "(" C ")" + B + "(" B * C * A ")" * A * "(" A ")" * C * C + A + C ")"
* C * C * A * C ")" * B + C + C * A * "(" "(" C * C ")" * B * B ")" * C + C *
B * B * A * A * C * A + C * B * "(" A + C + A + A ")" ")" * C + "(" C * C + B
+ C ")" * "(" B * B + C + B + A * B * "(" B + B * C ")" ")" + "(" A + C * B
")" ")" * A + A * B * A ")" + B ")" * B ")" * "(" "(" "(" A ")" ")" + B * C *
C ")" ")" + "(" A * "(" C * B + A * B * A ")" * B * A + "(" A ")" * A * C * B
* A + A ")" + A * "(" B ")" * B * A ")" + A + C
)
[4]> (speak)
("(" "(" "(" A * B * A * A + "(" C * A + B * B + B ")" + B * A * C * C * A ")"
* "(" B + "(" B * A * C ")" * C + A + C * C * B * "(" B * A * C * A * A ")"
")" + C + A * A * B + C ")" ")" * A
)
[5]> (speak)
(B)
[6]> (speak)
(A)
[7]> (speak)
(A * B)
[8]> (speak)
(B)
[9]> (speak)
(B + A * B + C * "(" A * C ")")
[10]> (speak)
(B * C + A * B)
[11]> (speak)
(B * "(" C + C * "(" A * B * B + B * "(" A * C + B * "(" B ")" ")" * B * B + B
+ A + B + A * A + A + B * "(" "(" C ")" + C * C * B ")" * A + A + "(" B ")" *
A * C * A * B * "(" B ")" * B ")" ")" * "(" C * B ")"
)
```

Your `(speak)`

function should start with the list consisting of the
start symbol for the grammar. The start symbol is the left side of
the first rule (`Expr`

in the current example). Your function should
then repeatedly replace each non-terminal symbol in the list with
a randomly-selected replacement. It repeats this process until
the list contains only terminal symbols.

**Bits and Pieces**

Here are some useful bits of Lisp you may want to use.

`(assoc`

*x**alist*)-
Search the
*alist*for the first member starting with*x*. If there is none, return`null`

. `(random`

*n*)-
Generate a random number from 0 up to, excluding
*n*. `(nth`

*n**list*)-
Return the
*n*member of the list, numbering from zero.^{th}

`random`

function will return the same sequence
of random numbers each time you run the program.
This is very useful for
testing.
To get different sequences of random numbers, run:

```
(setq *random-state* (make-random-state t))
```

**Too Much**

If you're unlucky, the program can keep making the wrong choices, and never reach a sentence (terminal symbols). The essentially puts the program into an infinite loop. To fix this, the grammar which generated the above example actually contained the line

```
(Term . ((id) (id) (id) (id) ( "(" Expr ")" )))
```

Since alternatives are chosen with equal probability,
this line makes it much more likely that
a `Term`

will be replaced with `id`

rather than `(Expr)`

.
That reduces the change that the program will increase the
length of the sentence generated.

**Submission**

Submit your program using the form
here.
Submit a file which can be `load`

ed into clisp and
contains a correct definition of the function `speak`

.