(define-datatype expression expression? (lit-exp (value anything?)) (var-exp (id symbol?)) (let-exp (syms (list-of symbol?)) (vals (list-of expression?)) (bodies (list-of expression?))) (set-exp (id symbol?) (value expression?)) (app-exp (exps (list-of expression?))) (or-exp (exps (list-of expression?))) (if-exp (test-exp expression?) (true-exp expression?) (false-exp expression?))) (define anything? (lambda (v) #t)) (define parse-expression (lambda (datum) (cond [(symbol? datum) (var-exp datum)] [(number? datum) (lit-exp datum)] [(boolean? datum) (lit-exp datum)] [(pair? datum) (cond [(eqv? (car datum) 'if) (if-exp (parse-expression (cadr datum)) (parse-expression (caddr datum)) (parse-expression (cadddr datum)))] [(eqv? (car datum) 'let) (let-exp (map car (cadr datum)) (map parse-expression (map cadr (cadr datum))) (map parse-expression (cddr datum)))] [(eqv? (car datum) 'set!) (set-exp (cadr datum) (parse-expression (caddr datum)))] [(eqv? (car datum) 'quote) (lit-exp (cadr datum))] [(eqv? (car datum) 'or) (or-exp (map parse-expression (cdr datum)))] [else (app-exp (map parse-expression datum))])] [else (eopl:error 'parse-expression "Invalid concrete syntax ~s" datum)])))