This project assignment is in two phases. Do not go on to phase II until you have completed phase I.
Phase I: Internal Representation of Lists
Modify your S_Expression() function so that it returns
the underlying "cons-cell" structure of the list that it parses. For example,
if your interpreter reads the list (a b c)
, then
S_Expression() should return the structure:
To complement this, write a function printList()
that, given
a pointer to such a cons-cell structure, will print out the list in
parenthesized form. Thus, given a pointer to the above structure,
printList()
will print out:
(a b c)
Note that what you have now is a way to read the list in and
represent it as the cons-cell structure, and a way to write that cons-cell
structure back out so that the list looked like what you put in. This may
seem silly, but trust me... the alternative is an extremely unwieldy
interpreter. At this point, your interpreter should just take an
s-expression and echo it back out, as in the sample run
given right here. Of course, there
is a trivial way to get the same effect (simply echo the string),
but it's what happens "behind the scenes" that counts in this phase.
A few tips on the cons-cell structure:
List
, that is a pointer to
a cons-cell. If you work this right, you can "think in Scheme" as
you develop your interpreter.#f
is synonymous with ()
, i.e., the empty list. Not all Schemes work
this way, but some do (MIT Scheme for example, as well as other LISPs such
as Common LISP). Thus #f
is the one object that is both a
symbol and a list. One sneaky
trick I have found useful is to create two "constant" cons-cells, one for
#t
and another for #f
, and use them universally
in your program to represent #t
and #f
.
This makes it easy to test to see
if a symbol or list is equal to one or the other, since you'll only need
"==
". '(a b c)
, a list structure that represents
the list using the quote
function, as in
(quote (a b c))
, is created. Don't do this unless you
really know what you're doing. Better to go on to Phase II and
return to it in a later project if you like.Phase II: Interpreting Simple Functions
Add an eval()
function that can evaluate a list, given
its internal representation. For now, just implement the basic functions quote, car, cdr, cons
and symbol?
.
All these functions are one to three lines long with the exception of
cons, which is perhaps 6 or 7 lines long. Each of these functions
(eval, car, cdr, quote
) should have a List
parameter (cons
has two) and return a List
.
When this phase is complete, a sample run might look like
this.
A few tips on evaluation:
quote, car, cdr
,
symbol?
and
cons
in the same file as the parser, since they have to look
into the implementation of the cons-cell struct. In fact, you could
also put eval()
in that same module. But even if you don't
get to it, think of some way of separating
the evaluation from the parsing as much as possible, by putting most
of the evaluation functions (including eval
) in a separate
module.(car (cdr (quote (a b c))))
"),
it should first evaluate the parameters (so in the cited example, we
first have to evaluate "(cdr (quote (a b c)))
"). Thus eval()
should
be recursive. It will bottom out when it gets to the level of a symbol or
an empty list.car
and
cdr
to get at the parameters in a function call.Back to CS170 Assignments.