#lang plait (define-type Exp [num (n : Number)] [plus (left : Exp) (right : Exp)] [times (left : Exp) (right : Exp)]) (define (parse s) (local [(define (sx n) (list-ref (s-exp->list s) n)) (define (px n) (parse (sx n))) (define (? pat) (s-exp-match? pat s))] (cond [(? `NUMBER) (num (s-exp->number s))] [(? `(+ ANY ANY)) (plus (px 1) (px 2))] [(? `(* ANY ANY)) (times (px 1) (px 2))] [else (error 'parse (to-string s))]))) (test (parse `1) (num 1)) (test (parse `2.3) (num 2.3)) (test (parse `{+ 1 2}) (plus (num 1) (num 2))) (test (parse `{+ 1 {+ {+ 2 3} 4}}) (plus (num 1) (plus (plus (num 2) (num 3)) (num 4)))) (test (parse `{+ 1 {* 2 3}}) (plus (num 1) (times (num 2) (num 3)))) (test (parse `{+ {* 1 2} 3}) (plus (times (num 1) (num 2)) (num 3))) (test (parse `{* {+ 1 2} {+ 3 4}}) (times (plus (num 1) (num 2)) (plus (num 3) (num 4)))) (test/exn (parse `{1 + 2}) "")