forked from ynadji/lisp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rpn.lisp
36 lines (31 loc) · 1.08 KB
/
rpn.lisp
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
;;;; Basic RPN-calculator. Leverages Lisp's ability to evaluate
;;;; commands from a string.
;;;;
;;;; Author: Yacin Nadji
(defpackage :rpn
(:use :cl)
(:import-from :nifty-funs #:split)
(:export #:repl))
(provide :rpn)
(in-package :rpn)
(defparameter *opt* '("+" "-" "*" "/" "expt"))
(defun repl (&optional (stack nil))
(let ((input (split (prompt-read ">") #\Space #'string)))
(loop for x in input
do (cond ((string= x "quit") (return-from repl))
((string= x "stack") (format t "(~{~a~^ ~})~%" stack))
((string= x "clear") (setq stack nil))
((find x *opt* :test #'string=)
(setq stack (calc stack x))
(format t "--> ~:d~%" (car stack)))
(t (setq stack (cons (read-from-string x) stack)))))
(repl stack)))
(defun prompt-read (prompt)
(format *query-io* "~a " prompt)
(force-output *query-io*)
(read-line *query-io*))
(defun calc (stack opt)
(if (< (length stack) 2)
(progn (format t "Insufficient values for ~a in (~{~a~^ ~})~%" opt stack)
stack)
(cons (funcall (read-from-string opt) (cadr stack) (car stack)) (cddr stack))))