Read Sections 5.5, 5.6, and 5.7 of EOPL for background. Feel free to use the parser from the model solution if you have trouble with yours.
e ::= n
| #t
| #f
| ()
| (quote x)
| x
| (if e e e)
| (lambda (x ...) e)
| (let ((x e) ...) e)
| (let* ((x e) ...) e)
| (e e ...)
where n is a number, x is a
variable, and ... means zero or more of the previous
item. Interpret free variables from the following set
as primitives:
+ * - / = not eq? symbol? number? cons car cdr pair?(You may add to this set at your discretion.) Environments should map variables to values. Lambda-expressions should be represented as procedures.
The composition of your parser and this interpreter should be called
eval1 (that is, eval1 takes an S-expression,
parses it, and evaluates it).
eval2.
e ::= ...
| (set! x e)
| (letrec ((x f) ...) e)
| (begin e e ...)
where f must be a lambda-expression.
Environments should now map variables to boxes.
The composition of your parser and this interpreter should
be called eval3.
e ::= ...
| (dynamic-let ((x e) ...) e)
Variables bound by dynamic-let should
have dynamic extent (fluid binding). See EOPL 5.7.2.
There is no need to build a separate interpreter for part 4.
Simply include dynamic-let in eval3.