As an exercise, I've implemented a simple reader macro in Common Lisp (using SBCL). It converts Octal (unsigned integers only) into numbers.
Usage:
* #z1234
668
The code:
(defun oct-string-to-number
(string)
"Converts an octal string to a number. Only digits from 0 - 7 are accepted; sign or decimal point symbols will cause oct-to-number to fail"
(setq place 1)
(setq result 0)
(setq digits '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7))
(loop for char across (reverse string)
do
(setq pos (position char digits))
(setq result (+ result (* pos place)))
(setq place (* 8 place)))
result)
(defun slurp-octal-digits
(stream)
(setq string (make-array 0 :element-type 'character :fill-pointer 0 :adjustable t))
"Slurps all digits from 0 - 7 from a stream into a string, stopping at EOF, no data, or a non-digit character."
(setq digits '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7))
(with-output-to-string (out)
(loop do
(setq char (read-char stream))
(setq isnum nil)
(if char
(progn
(setq isnum (find char digits))
(if isnum
(vector-push-extend char string)
(unread-char char stream))))
while (not (eq nil isnum))))
string)
(defun octal-string-transformer
(stream subchar args)
"Slurps an octal number from stream, and converts it to a number. Number must be an unsigned integer."
(setq oct-string (slurp-octal-digits stream))
(oct-string-to-number oct-string))
;; Sets #z to call octal-string-transformer, so e.g. #z1234 will evaluate to 668. Use #z as SBCL has #o already :-)
(set-dispatch-macro-character
#\# #\z
#'octal-string-transformer)
I'm quite new to Common Lisp, so I'd greatly appreciate feedback on everything: formatting, style, idiom, correctness :-)
Edited to add: Actually, the formatting in the pasted code snippet is rendered oddly; indentation that is present when I edit vanishes when I submit. So maybe be a bit gentle with feedback about the formatting ;-)