Now that we have parsing and unparsing down, we can get down to the business of writing an interpreter for a new language, Mini-Scheme.
We will start with a very basic version of Mini-Scheme, and gradually add language features. As we do so, we will update our parser and interpreter to implement the new language features.
As a convention, the parser and interpreter for Mini-Scheme-X will reside in "parse-X.ss" and "interp-X.ss" respectively. When you are asked to write an interpreter, you should turn in (at least) two files - "parse-X.ss" and "interp-X.ss".
Our first Mini-Scheme, Mini-Scheme-A, will be specified by the following concrete and abstract syntax:
<exp> ::= <number> lit (datum)
Admittedly, not very exciting. Our interpreter for Mini-Scheme-A will be very basic as well. It is contained in 2 files:
| parse-a.ss | Datatype and parser definition | |
| interp-a.ss | eval-exp definition |
The parser simply creates an exp-a-lit when it sees a number (and throws an error otherwise). It looks like this
(define parse
(lambda (exp)
(cond
((number? exp) (exp-a-lit exp))
(else (error 'parse "Invalid concrete syntax ~s" exp)))))
As for the interpreter, you know that Scheme evaluates all integers as
themselves. So our evaluation function will be very simple. It looks
like this.
(define eval-exp
(lambda (exp)
(cases exp-a exp
(exp-a-lit (datum) datum)
(else (error 'eval-exp
"Invalid abstract syntax: ~s"
exp)))))
All we need to do to an interpret an expression, then, is pass eval-exp a parsed Mini-Scheme expression. Save parse-a.ss and interp-a.ss to your directories (use the above links) and then try the following in Dr. Scheme:
> (load "parse-a.ss") > (load "interp-a.ss") > (eval-exp (parse '2)) 2
You can tell that it quickly becomes tedious to always invoke your interpreter by specifically calling the interpreter eval-exp after calling the parser parse on the quoted expression. It would be nice if we could write a read-eval-print loop for Mini-Scheme. This is very easily accomplished with the code found in r-e-p.ss. Save r-e-p.ss to your directory and then
> (load "r-e-p.ss") > (load "parse-a.ss") > (load "interp-a.ss") > (read-eval-print) MS> 3 3 MS> 4 4 MS> howdy? parse : Invalid concrete syntax howdy? MS> 7 7 MS> exit returning to Scheme proper