#lang scheme
(require (planet "main.rkt" ("samsergey" "rewrite.plt" 1 0))
rackunit)
(define/. infix->prefix
`(,x __1 + ,y __1) --> (list '+ (infix->prefix x) (infix->prefix y))
`(,x __1 - ,y __1) --> (list '- (infix->prefix x) (infix->prefix y))
`(,x __1 * ,y __1) --> (list '* (infix->prefix x) (infix->prefix y))
`(,x __1 / ,y __1) --> (list '/ (infix->prefix x) (infix->prefix y))
`(,f ,x __1) --> (list f (infix->prefix x))
`(,x) --> (infix->prefix x))
(check-equal? (infix->prefix '(1)) 1)
(check-equal? (infix->prefix '(1 + 2 * x)) '(+ 1 (* 2 x)))
(check-equal? (infix->prefix '((a + b) * c)) '(* (+ a b) c))
(check-equal? (infix->prefix '(2 * sin(2 * x))) '(* 2 (sin (* 2 x))))
(define ((nest f g) x y) (f (g x) y))
(define/. prefix->RPN
(cons f x) --> (foldl (nest append prefix->RPN) (list f) x)
x --> (list x))
(define infix->RPN (compose prefix->RPN infix->prefix))
(check-equal? (infix->RPN '(1)) '(1))
(check-equal? (infix->RPN '(1 + 2 * x)) '(x 2 * 1 +))
(check-equal? (infix->RPN '((a + b) * c)) '(c b a + *))
(check-equal? (infix->RPN '(2 * sin(2 * x))) '(x 2 * sin 2 *))
(define (calculate-RPN expr)
(define/. read-stack
(? number? n) s --> (cons n s)
'+ (list x y s ___) --> (cons (+ x y) s)
'- (list x y s ___) --> (cons (- x y) s)
'* (list x y s ___) --> (cons (* x y) s)
'/ (list x y s ___) --> (cons (/ x y) s)
x s --> (error "Expression contains unknown operation:" x))
((/. `(,s) --> s)
(reverse (foldl read-stack '() expr))))
(check-eq? (calculate-RPN (infix->RPN '(1))) 1)
(check-eq? (calculate-RPN (infix->RPN '(1 + 2 * 3))) 7)
(check-eq? (calculate-RPN (infix->RPN '((1 + 2) * 3))) 9)
(check-eq? (calculate-RPN (infix->RPN '((1 + 2) * (3 - 4)))) -3)
(check-eq? (calculate-RPN (infix->RPN '((1 + 2) / (3 - 4)))) -3)