diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..becd6ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Ignore raket temp files +*.rkt~ diff --git a/A1/infix-ae.rkt b/A1/infix-ae.rkt index e69de29..a87b172 100644 --- a/A1/infix-ae.rkt +++ b/A1/infix-ae.rkt @@ -0,0 +1,56 @@ +#lang plait + +#| BNF for the AE language: + ae: NUMBER + | { ae + ae } + | { ae - ae } + | { ae * ae } + | { ae / ae } +|# + +;; AE abstract syntax trees +(define-type AE + [Num (val : Number)] + [Add (l : AE) (r : AE)] + [Sub (l : AE) (r : AE)] + [Mul (l : AE) (r : AE)] + [Div (l : AE) (r : AE)]) + +;; to convert s-expressions into AEs +(define (parse-sx sx) + (let ([rec (lambda (fn sx) + (parse-sx (fn (s-exp->list sx))))]) + (cond + [(s-exp-match? `NUMBER sx) + (Num (s-exp->number sx))] + [(s-exp-match? `(ANY + ANY) sx) + (Add (rec first sx) (rec third sx))] + [(s-exp-match? `(ANY - ANY) sx) + (Sub (rec first sx) (rec third sx))] + [(s-exp-match? `(ANY * ANY) sx) + (Mul (rec first sx) (rec third sx))] + [(s-exp-match? `(ANY / ANY) sx) + (Div (rec first sx) (rec third sx))] + [else (error 'parse-sx (to-string sx))]))) + +;; consumes an AE and computes the corresponding number +(define (eval expr) + (type-case AE expr + [(Num n) n] + [(Add l r) (+ (eval l) (eval r))] + [(Sub l r) (- (eval l) (eval r))] + [(Mul l r) (* (eval l) (eval r))] + [(Div l r) (/ (eval l) (eval r))])) + +;; evaluate an AE program contained in an s-expr +(define (run sx) + (eval (parse-sx sx))) + +(test (run `3) 3) +(test (run `{3 + 4}) 7) +(test (run `{{3 - 4} + 7}) 6) +(test (run `{8 * 9}) 72) +(test (run `{8 / 2}) 4) +(test (run `{-8 / 0}) -inf.0) +(test (run `{8 / {5 - 5}}) +inf.0) +(test (run `{1 / {1 / 0}}) 0.0) \ No newline at end of file