; XMLScheme (c) Markus Lumpe & EOPL2 (parts)
(define scanner-spec
'(
(white-sp
(whitespace) skip)
(comment
("%" (arbno (not #\newline))) skip)
(identifier
(letter (arbno (or letter digit "?"))) symbol)
(number
(digit (arbno digit)) number)
)
)
;
; Basic syntax:
;
; program ::= expression
;
; declarations ::=
; "" expression "/>"}* "/>"
;
; expression ::=
; ""
; ""
; ""
; ""
; ""
; ""
; ""
; ""
; "<" prim-op arguments "/>"
;
; prim-op ::=
; "add"
; "sub"
; "mul"
; "inc"
; "dec"
;
; arguments ::=
; ""
;
; formals ::=
; ""
;
; param ::=
; ""
;
(define grammar-spec
'(
(program
(expression) a-program)
(formals
("") "/>") param-decls)
(declarations
(""
expression "/>")
"/>") let-decls)
(expression
("") proc-exp)
(expression
("" "/>") app-exp)
(expression
("") let-exp)
(expression
(""
""
"" "/>") if-exp)
(expression
("") lit-exp)
(expression
("") var-exp)
(expression
("<" prim-op "" "/>") primapp-exp)
(prim-op
("add") add-prim)
(prim-op
("sub") sub-prim)
(prim-op
("mul") mult-prim)
(prim-op
("inc") inc-prim)
(prim-op
("dec") dec-prim)
)
)
;; build the scanner and parser
(define front-end
(sllgen:make-string-parser scanner-spec grammar-spec))
;; build the define-datatype definitions
(define-datatype program program?
(a-program
(exp expression?))
)
(define-datatype pdeclarations pdeclarations?
(param-decls
(ids (list-of symbol?)))
)
(define-datatype declarations declarations?
(let-decls
(ids (list-of symbol?))
(rands (list-of expression?)))
)
(define-datatype expression expression?
(proc-exp
(ids pdeclarations?)
(body expression?))
(app-exp
(rator expression?)
(rands (list-of expression?)))
(let-exp
(decls declarations?)
(body expression?))
(if-exp
(test-exp expression?)
(then-exp expression?)
(else-exp expression?))
(lit-exp
(datum number?))
(var-exp
(id symbol?))
(primapp-exp
(prim primitive?)
(rands (list-of expression?)))
)
(define-datatype primitive primitive?
(add-prim)
(sub-prim)
(mult-prim)
(inc-prim)
(dec-prim)
)
(load "environment.scm")
(define init-env
(lambda ()
(extend-env '(i v x) '(1 5 10) (empty-env))
)
)
(define eval-program
(lambda (pgm)
(cases program pgm
(a-program (body)
(eval-expression body (init-env)))
)
)
)
(define is-true?
(lambda (x)
(not (zero? x))
)
)
(define get-rands
(lambda (decls)
(cases declarations decls
(let-decls (ids rands)
rands)
)
)
)
(define get-ids
(lambda (decls)
(cond
((declarations? decls)
(cases declarations decls
(let-decls (ids rands)
ids)))
((pdeclarations? decls)
(cases pdeclarations decls
(param-decls (ids)
ids)))
)
)
)
(load "closure.scm")
(define eval-expression
(lambda (exp env)
(cases expression exp
(proc-exp (params body)
(closure (get-ids params) body env))
(app-exp (rator rands)
(let ((proc (eval-expression rator env))
(args (eval-rands rands env)))
(if (procval? proc)
(apply-procval proc args)
(eopl:error 'eval-expression
"Attempt to apply non-procedure ~s" proc))))
(let-exp (decls body)
(let ((args (eval-rands (get-rands decls) env)))
(eval-expression body (extend-env (get-ids decls) args env))))
(if-exp (test-exp true-exp false-exp)
(if (is-true? (eval-expression test-exp env))
(eval-expression true-exp env)
(eval-expression false-exp env)))
(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)))
)
)
)
(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)))
(add-prim () (fold-left args + 0))
; (sub-prim () (- (car args) (cadr args)))
(sub-prim () (fold-left (cdr args) - (car args)))
; (mult-prim () (* (car args) (cadr args)))
(mult-prim () (fold-left args * 1))
(inc-prim () (+ (car args) 1))
(dec-prim () (- (car args) 1))
)
)
)
(define interpreter
(lambda (string)
(eval-program (front-end string))
)
)
(define read-eval-loop
(sllgen:make-rep-loop
"$ "
eval-program
(sllgen:make-stream-parser scanner-spec grammar-spec)))
(load "readfile.scm")
(define run-from-file
(lambda (fname)
(interpreter (read-file fname))
)
)
(define parse-from-file
(lambda (fname)
(front-end (read-file fname))
)
)