Execute HQ9+/Common Lisp

From Rosetta Code
Revision as of 04:57, 11 August 2009 by rosettacode>Tayloj (creating a page, not a category :\)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Common Lisp

The interpreter accepts a string, treated as program text, or a pathname object, in which case the contents of the file are the program text.

<lang lisp>(defun slurp (filespec)

 "Return the contents of the file as a string."
 (with-output-to-string (out)
   (with-open-file (in filespec :direction :input)
     (loop for line = (read-line in nil nil)
           until (null line) do (write-line line out)))))

(defun hq9+ (input &optional (out *standard-output*))

 "Execute the hq9+ program designated by input.  If input is a

string, it is taken as the program text. If it is a pathname, then the program text is the content of the file. The final value of the accumulator is returned."

 (loop with src = (if (stringp input) input (slurp input))
       with accumulator = 0
       for c across src
       do (cond
           ((char-equal c #\h) (write-line "Hello, world!" out))
           ((char-equal c #\q) (write-line src out))
           ((char-equal c #\+) (incf accumulator))
           ((char-equal c #\9)
            (do ((n 99 (1- n))) ((zerop n))
              (format out "~&~%~w bottle~:p of beer on the wall~%~
                           ~w bottle~:p of beer~%~
                           Take one down, pass it around~%~
                           ~:[~w bottle~:p~;No more bottles~] ~
                                          of beer on the wall~%"
                      n n (zerop (1- n)) n))
            (format out "~&~%No more bottles of beer on the wall~%~
                         No more bottles of beer on the wall~%~
                         Go to the store and buy some more~%~
                         99 bottles of beer on the wall.~%")))
       finally (return accumulator)))</lang>