UNB/ CS/ David Bremner/ teaching/ cs4613/ lectures/ lecture02/ parse.rkt
#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}) "")