where <symbol>
is any string of non-whitespace
characters that
does not begin with "#", or "'" (the single quote), and that
does not contain "(" or ")". In the
grammar, terminals are in boldface, and all other symbols (e.g., the
brackets { and }) are meta-linguistic symbols. The
parsing of <symbol> will be handled by a lexical analyzer, which
has already been written (see below for further information).
Your program should be capable of reading any number of Scheme s-expressions (as specified by the above syntax) and outputting the "parse tree" as represented by the appropriately indented recursive calls to the s_expression function, which you will write in C.
A sample output is given here.
In the sample run, everything is program ouput,
including the prompt "scheme>
",
except for the one-line lists (e.g., "(a b c)
"),
which are user input. Note that your program should continue to prompt for, accept, and parse user input until the user types ctrl-c. That mode of
termination is not very elegant, of course. We'll take care of a more
graceful exit in a later stage of the project.
The lexical analyzer is given in two files,
lexer.h and lexer.c.
The header file lexer.h provides sufficient documentation for
using the code. To illustrate how it may be used, here
is a file lextester.c that scans keyboard
input, and an appropriate Makefile for
compiling and linking the three (lexer.h, lexer.c, and lextester.c)
and producing an executable named scheme
.
Note that the lexical analyzer returns the empty list "()
" as
if it were one token (this makes life easier for the parser).
It also recognizes the single quote, but don't try having the parser
deal with it at this point. It will be easier to handle
the single quote later in the project.
Keep your code modular, now and for the remainder of
this project. Separate the different functions of your project
into natural units. For this assignment, it would make sense to
create a file parser.h
, containing the parser
interface and another file parser.c
for the
parser implementation The interface file could be quite
simple (HINT: "could" means
"should" where simplicity is concerned!) at this point, e.g.,
#ifndef PARSER #define PARSER #include <stdlib.h> void S_Expression (); #endifAll your main program would then have to do would be to
#include parser.h
, and call S_Expression()
(inside a loop of course, as
implied by the sample run). Hide as many
details as you can from the client modules in general.
You may develop your project using any IDE (or none) according
to taste. However, when the project is submitted, you must submit
a zip file of a folder containing
only the source files and a Makefile that will allow me to
build the project using
"make" at the command line on Linux.
The executable must be named scheme
as in
the code you are given. This means you will almost
certainly have to write your own Makefile different than the
automatically generated one used by (say) Netbeans or Eclipse. Use
the given Makefile
as a model (which will be lightly
adapted for this assignment).
Your Makefile will undoubtedly be modified
as the project progresses.
Submission location here.
Back to CS170 Assignments.