-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstack-calculator-01.scm
71 lines (61 loc) · 2.03 KB
/
stack-calculator-01.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
(load "check.scm")
(check-set-mode! 'report-failed)
(define unary-operator?
(lambda (expression)
(eq? 'sqrt (car expression))))
(define operator?
(lambda (expression)
(let ((token (car expression)))
(or (eq? '+ token)
(eq? '- token)
(eq? '* token)
(eq? '^ token)
(unary-operator? expression)
(eq? '/ token)))))
(define operator
(lambda (expression)
(define oper (car expression))
(cond ((eq? '^ oper) 'expt)
(else oper))))
(define rpn
(lambda (expression)
(define evaluate
(lambda (expression . operands)
(eval (cons (operator expression) operands))))
(define calculate
(lambda (expr stack)
(cond ((null? expr) (car stack))
((unary-operator? expr)
(define first-operand (car stack))
(define result (evaluate expr first-operand))
(calculate (cdr expr) (cons result (cdr stack))))
((operator? expr)
(define first-operand (cadr stack))
(define second-operand (car stack))
(define result (evaluate expr first-operand second-operand))
(calculate (cdr expr) (cons result (cddr stack))))
(else (calculate (cdr expr) (cons (car expr) stack))))))
(if (null? expression)
"there is nothing to calculate!"
(calculate expression '()))))
(check (operator? '(+)) => #t)
(check (operator? '(-)) => #t)
(check (operator? '(*)) => #t)
(check (operator? '(/)) => #t)
(check (operator? '(^)) => #t)
(check (operator? '(sqrt)) => #t)
(check (unary-operator? '(sqrt)) => #t)
(check (unary-operator? '(+)) => #f)
(check (operator '(+)) => '+)
(check (operator '(-)) => '-)
(check (operator '(*)) => '*)
(check (operator '(/)) => '/)
(check (operator '(^)) => 'expt)
(check (operator '(sqrt)) => 'sqrt)
(check (rpn '(2 3 +)) => 5)
(check (rpn '(2 3 *)) => 6)
(check (rpn '(6 2 /)) => 3)
(check (rpn '(3 2 -)) => 1)
(check (rpn '(2 3 ^ )) => 8)
(check (rpn '(4 sqrt)) => 2.0)
(check-report)