summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lex.lisp22
-rw-r--r--t/lex.lisp19
2 files changed, 39 insertions, 2 deletions
diff --git a/src/lex.lisp b/src/lex.lisp
index c6e9cf7..e86d1e9 100644
--- a/src/lex.lisp
+++ b/src/lex.lisp
@@ -9,7 +9,7 @@
:reader instance))
(:report (lambda (condition stream)
(format stream
- "Lex failed--encountered ~a while reading ~a."
+ "LEX failed--encountered ~a while reading ~a."
(chr condition) (instance condition))))
(:documentation "Dedicated error for immediates/keywords which contain
invalid characters."))
@@ -63,6 +63,9 @@ Comments start with a semi-colon ';' and all tokens after are ignored."
(t (error (format nil "~a is not a valid lexical symbol.~%" chr))))))
(defun read-immediate (chr)
+ "Reads a sequence of digits, in base 2, 8, 10, or 16.. Throws
+`invalid-immediate-or-keyword' error if an alphabetic character is encountered."
+ ;; may be combined with read-keyword-helper
(defun read-immediate-helper (chrs-so-far)
(let ((chr (peek-char nil *standard-input* nil)))
(cond ((and (not (null chr)) (digit-char-p chr))
@@ -70,9 +73,24 @@ Comments start with a semi-colon ';' and all tokens after are ignored."
((and (not (null chr)) (alpha-char-p chr))
(error 'invalid-immediate-or-keyword :chr chr :instance "immediate"))
(t (reverse chrs-so-far)))))
- (parse-integer (coerce (read-immediate-helper (list chr)) 'string)))
+
+ (let* ((next (peek-char nil *standard-input* nil))
+ (radix (cond ((null next) 10)
+ ((char= next #\b) 2)
+ ((char= next #\o) 8)
+ ((char= next #\x) 16)
+ ((digit-char-p next) 10)
+ (t nil)))
+ (arg (list chr)))
+ (when (and (char= chr #\0) radix (not (= radix 10)))
+ (read-char *standard-input* nil)
+ (setq arg '()))
+ (parse-integer (coerce (read-immediate-helper arg) 'string) :radix radix)))
(defun read-keyword (chr)
+ "Reads a sequence of alphabetic characters. Throws `invalid-immediate-or-keyword'
+error if a digit is encountered."
+ ;; may be combined with read-immediate-helper
(defun read-keyword-helper (chrs-so-far)
(let ((chr (peek-char nil *standard-input* nil)))
(cond ((and (not (null chr)) (alpha-char-p chr))
diff --git a/t/lex.lisp b/t/lex.lisp
index 40698f9..ab0ed99 100644
--- a/t/lex.lisp
+++ b/t/lex.lisp
@@ -52,12 +52,31 @@
(read-this "123456789"
(is (= (lex:read-token) 123456789))))
+(test read-token-immediate-binary
+ (read-this "0b00101010"
+ (is (= (lex:read-token) 42))))
+
+(test read-token-immediate-octal
+ (read-this "0o052"
+ (is (= (lex:read-token) 42))))
+
+(test read-token-immediate-hexadecimal
+ (read-this "0x200"
+ (is (= (lex:read-token) 512))))
+
(test read-token-immediate-invalid-immediate
(handler-case
(progn (read-this "0v0" (lex:read-token))
(fail))
(lex:invalid-immediate-or-keyword ())))
+;; do we want a custom error for this too?
+(test read-token-immediate-radix
+ (handler-case
+ (progn (read-this "0x" (lex:read-token))
+ (fail))
+ (sb-int:simple-parse-error ())))
+
(test read-token-keyword-single
(read-this "a"
(is (string= (lex:read-token) "a"))))