3.4 Rudimentary Interpreter
You must complete this assignment using a specific language. Choose Determine language from source in the DrRacket menu, then writeas the first line of your program, overwritting the default #lang at the top of the file.
3.4.1 WAE
3.4.1.1 Datatypes
(define-type Binding [binding (name symbol?) (named-expr WAE?)]) (define-type WAE [num (n number?)] [add (lhs WAE?) (rhs WAE?)] [sub (lhs WAE?) (rhs WAE?)] [with (b Binding?) (body WAE?)] [id (name symbol?)])
This part requires no test cases.
3.4.1.2 Parser
Write the following function:
procedure
(parse s-exp) → WAE?
s-exp : s-expression?
WAE | = | number | ||
| | (+ WAE WAE) | |||
| | (- WAE WAE) | |||
| | (with ([id WAE]) WAE) | |||
| | id |
where number is a Racket number and id is not '+, '-, or 'with.
The textbook provides a basic version for you.
(test (parse '5) (num 5)) (test/exn (parse true) "Illegal syntax") (test (parse '(+ 1 2)) (add (num 1) (num 2))) (test/exn (parse '(+ 1 2 3)) "More than two arguments") (test/exn (parse '(with [x 1] x)) "Not a list of bindings")
3.4.1.3 Interpreter
Write the following function:
The textbook provides a basic version for you.
3.4.2 W*AE
3.4.2.1 Datatypes
(define-type Binding [binding (name symbol?) (named-expr WAE?)]) (define-type WAE [num (n number?)] [binop (op procedure?) (lhs WAE?) (rhs WAE?)] [with (lob (listof Binding?)) (body WAE?)] [id (name symbol?)])
This part requires no test cases.
3.4.2.2 Operator Table
Define a data-structure to contain a mapping from operator symbols to their definitions.
value
op-table : (listof (list/c symbol? (number? number? . -> . number?)))
Populate it with mappings for '+, '-, '*, and '/.
Define a function that extracts the definition of an operator or false:
procedure
(lookup-op op) → (or/c procedure? false/c)
op : symbol?
You will find the Racket function assoc useful.
3.4.2.3 Parser
Write the following function:
procedure
(parse s-exp) → WAE?
s-exp : s-expression?
WAE | = | number | ||
| | (+ WAE WAE) | |||
| | (- WAE WAE) | |||
| | (* WAE WAE) | |||
| | (/ WAE WAE) | |||
| | (with ([id WAE] ...) WAE) | |||
| | id |
where number is a Racket number and id is not '+, '-, '*, '/, or 'with.
WAE | = | number | ||
| | (list '+ WAE WAE) | |||
| | (list '- WAE WAE) | |||
| | (list '* WAE WAE) | |||
| | (list '/ WAE WAE) | |||
| | (list 'with (list (list id WAE) ...) WAE) | |||
| | id |
Your parser must call lookup-op.
You will find the Racket functions length, andmap, symbol?, list?, symbol=?, and map useful.
(test (parse '(with ([x 1] [x 2]) (+ x x))) (with (list (binding 'x (num 1)) (binding 'x (num 2))) (binop + (id 'x) (id 'x))))
(test (parse '5) (num 5)) (test/exn (parse true) "Illegal syntax") (test (parse '(+ 1 2)) (binop + (num 1) (num 2))) (test/exn (parse '(+ 1 2 3)) "Illegal syntax") (test/exn (parse '(with [x 1] x)) "Illegal syntax")
3.4.2.4 Multiple Substitution
Write the following function:
You may assume that lob (the argument to subst*) only contains bindings to num objects. (This assumption must be obeyed by the other code you write.)
You will find using your previous subst function useful.
You will find the Racket function foldr useful.
(test (subst* (list (binding 'x (num 1))) (id 'x)) (num 1)) (test (subst* (list (binding 'x (num 1)) (binding 'y (num 2))) (binop + (id 'x) (id 'y))) (binop + (num 1) (num 2)))
3.4.2.5 Interpreter
Write the following function:
You will find the Racket functions map useful.
You will find the functions ormap and symbol=? to detect errors like this.