; http://www.radford.edu/itec380/2008fall/Homeworks/Hw06/hw06.html ; Ian Barland, 2008.Nov.27 ; Run this program in language-level 'Module', ; *not* 'Advanced Student'. ; These two lines make a module which exports everything ; (in Java terms: a package where everything is public). ; #lang scheme (provide (all-defined-out)) ;;;;;;;;;;; language L0 ;;;;;;;;;;;;;; ; An Expr is one of: ; - a number ; - (make-sum Expr Expr) ; - (make-prod Expr Expr) ; - (make-ifZero Expr Expr Expr) (define-struct sum (e1 e2) #:transparent) (define-struct prod (e1 e2) #:transparent) (define-struct ifZero (cond then else) #:transparent) ; ; The keyword 'transparent' makes structs with 'public' fields; ; in particular check-expect can inspect these structs. ; parse: (-> s-expr expr) ; Convert the given S-expression representing exactly *one* single Expr ; into our internal format (structs). ; (define (parse tokens) (cond [(number? tokens) tokens] ; Note that the following cases presume 'tokens' is a list ; (since we just checked it's not a number). Our code would break, ; if we moved the following tests above 'number'; a more robust ; solution would add '(and (cons? tokens) ...)' to each condition. [(symbol=? (first tokens) 'plus) (make-sum (parse (second tokens)) (parse (third tokens)))] [(symbol=? (first tokens) 'times) (make-prod (parse (second tokens)) (parse (third tokens)))] [(symbol=? (first tokens) 'ifZero) (make-ifZero (parse (second tokens)) (parse (third tokens)) (parse (fourth tokens)))] [else (error 'parse (format "Unrecognized expr: ~v." tokens))])) ; parse-string: (-> string expr) ; Convert the given string representing exactly *one* single Expr ; into our internal format (structs). ; ;; Since S-Expressions are (in Scheme) more natural for representing ;; the input, this function is merely a wrapper for 'parse', which ;; takes in an S-expression. ;; You don't need to modify this function; ;; only update 'parse' so that it handles all the types of Exprs. ;; (define (parse-string str) (parse (read (open-input-string str)))) ; expr->string : (-> expr string) (a.k.a. toString) ; Return a human-readable version of our internal representaiton of Exprs. ; ;; You don't need to modify this function; ;; only update 'expr->tokens' so that it handles all the types of Exprs. ;; (define (expr->string e) (pretty-format (expr->tokens e))) ; expr->tokens : (-> expr s-expr) ; Return an S-Expression representing our Expr (internal format). ; (define (expr->tokens e) (cond [(number? e) e] [(sum? e) (list 'plus (expr->tokens (sum-e1 e)) (expr->tokens (sum-e2 e)))] [(prod? e) (list 'times (expr->tokens (prod-e1 e)) (expr->tokens (prod-e2 e)))] [(ifZero? e) (list 'ifZero (expr->tokens (ifZero-cond e)) (expr->tokens (ifZero-then e)) (expr->tokens (ifZero-else e)))] [else (error 'expr->tokens (format "Unhandled internal format: ~v." e))])) ; eval : (-> expr val) ; Evaluate the given expr. ; (define (eval e) (cond [(number? e) e] [(sum? e) (+ (eval (sum-e1 e)) (eval (sum-e2 e)))] [(prod? e) (* (eval (prod-e1 e)) (eval (prod-e2 e)))] [(ifZero? e) (if (= (eval (ifZero-cond e)) 0) (eval (ifZero-then e)) (eval (ifZero-else e)))] [else (error 'eval (format "fell off cond with expr: ~v." e))])) ;;;;;;;;;;;;;;;;;;; TEST CASES: L0 ;;;;;;;;;;;;;;;; ;;; The following is used by 'hw06-test-helpers.ss': (define tests ; Each entry in the list is either ; [str val] (where val is the result of interpreting the string str), or ; [str val expr] (as above, but expr is the internal (struct) representation). `{["7" 7 7] ["{plus 3 4}" 7 ,(make-sum 3 4)] ["{times 3 4}" 12 ,(make-prod 3 4)] ["{plus {plus 3 4} {times 3 4}}" 19] ["{ifZero 0 1 2}" 1 ,(make-ifZero 0 1 2)] ["{ifZero 1 1 2}" 2 ,(make-ifZero 1 1 2)] ["{ifZero {plus 3 -3} 1 2}" 1 ,(make-ifZero (make-sum 3 -3) 1 2)] ["{ifZero {plus {ifZero {ifZero 0 1 2} 3 4} -3} 1 2}" 2 ,(make-ifZero (make-sum (make-ifZero (make-ifZero 0 1 2) 3 4) -3) 1 2)] })