;;;; First Interpreter (require-library "drscheme-init.scm" "eopl") (load "environmentSupport.scm") ;; Define the initial environment (define init-env (lambda () (extend-env '(i v x) '(1 5 10) (empty-env)))) ;; Define the lexical specification and grammar (define the-lexical-spec '((whitespace (whitespace) skip) (comment ("%" (arbno (not #\newline))) skip) (identifier (letter (arbno (or letter digit "_" "-" "?"))) symbol) (number (digit (arbno digit)) number))) (define the-grammar '((program (expression) a-program) (expression (number) lit-exp) (expression (identifier) var-exp) ; book calls this (expression (primitive "(" (separated-list expression ",") ")") primapp-exp) (primitive ("+") add-prim) (primitive ("-") subtract-prim) (primitive ("*") mult-prim) (primitive ("add1") incr-prim) (primitive ("sub1") decr-prim) )) ;; The actual interpreter (define eval-program (lambda (pgm) (cases program pgm (a-program (body) (eval-expression body (init-env)))))) (define eval-expression (lambda (exp env) (cases expression exp (lit-exp (datum) datum) (var-exp (id) (apply-env env id)) (primapp-exp (prim rands) (let ((args (eval-rands rands env))) (apply-primitive prim args))) (else (error "Invalid abstract syntax: " exp))))) (define eval-rands (lambda (rands env) (map (lambda (x) (eval-rand x env)) rands))) (define eval-rand (lambda (rand env) (eval-expression rand env))) (define apply-primitive (lambda (prim args) (cases primitive prim (add-prim () (+ (car args) (cadr args))) (subtract-prim () (- (car args) (cadr args))) (mult-prim () (* (car args) (cadr args))) (incr-prim () (+ (car args) 1)) (decr-prim () (- (car args) 1)) (else (error "Invalid prim-op name:" prim))))) ;; The function sllgen:make-define-datatypes will generate the appropriate ;; define-datatypes commands. (Or one could generate them by hand.) ;; The function sllgen:list-define-datatypes returns the define-database ;; expressions in list form instead of executing them. ;; ;; The function sllgen:make-string-parser is used to construct a scanner and a ;; parser. ;; ;; (define scan&parse ;; (sllgen:make-string-parser the-lexical-spec the-grammar)) ;; ;; (sllgen:make-define-datatypes the-lexical-spec the-grammar) ;; (sllgen:list-define-datatypes the-lexical-spec the-grammar) ;; ;; (define run ;; (lambda (string) ;; (eval-program (scan&parse string)))) ;; ;; ;; The function sllgen:make-stream-parser is the same as ;; sllgen:make-string-parser only it works on the input stream so that if used ;; in conjuction with sllgen-make-rep-loop one can create a read-eval-print ;; environment for running interpreted programs. ;; ;; (define read-eval-print ;; (sllgen:make-rep-loop "--> " eval-program ;; (sllgen:make-stream-parser the-lexical-spec the-grammar)))