summaryrefslogtreecommitdiff
path: root/src/lex.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lex.lisp')
-rw-r--r--src/lex.lisp57
1 files changed, 46 insertions, 11 deletions
diff --git a/src/lex.lisp b/src/lex.lisp
index ad386ba..c6e9cf7 100644
--- a/src/lex.lisp
+++ b/src/lex.lisp
@@ -1,19 +1,34 @@
(in-package #:lex)
+(define-condition invalid-immediate-or-keyword (error)
+ ((chr :initarg :chr
+ :initform nil
+ :reader chr)
+ (instance :initarg :instance
+ :initform nil
+ :reader instance))
+ (:report (lambda (condition stream)
+ (format stream
+ "Lex failed--encountered ~a while reading ~a."
+ (chr condition) (instance condition))))
+ (:documentation "Dedicated error for immediates/keywords which contain
+invalid characters."))
+
(defun file->tokens (file)
"Opens FILE and parses returns a list of tokens, or
NIL if the file could not be opened."
- (defun read-tokens (tokens-so-far)
- "Collects tokens in FILE into TOKENS-SO-FAR."
+ (defun read-instr (lst tokens-so-far)
+ "Collects tokens in FILE into TOKENS-SO-FAR, splitting on a newline."
(let ((token (read-token)))
- (if token
- (read-tokens (cons token tokens-so-far))
- (reverse tokens-so-far))))
+ (cond ((null token) (reverse tokens-so-far))
+ ((eq token 'nl)
+ (cons (reverse tokens-so-far) (read-instr nil nil)))
+ (t (read-instr lst (cons token tokens-so-far))))))
(and (probe-file file)
(with-open-file (*standard-input* file :direction :input)
- (read-tokens '()))))
+ (remove nil (read-instr '() '())))))
(defun read-token ()
"Reads *STANDARD-INPUT* and returns a token, or nil if the end
@@ -23,29 +38,49 @@ Comments start with a semi-colon ';' and all tokens after are ignored."
(let ((chr (read-char *standard-input* nil)))
(cond
((null chr) chr)
+
+ ((char= chr #\linefeed) 'nl)
+
((whitespace-char-p chr)
(read-token))
((char= chr #\;)
(progn (read-line *standard-input* nil)
- (read-token)))
+ 'nl))
((char= chr #\() 'left-paren)
((char= chr #\)) 'right-paren)
+ ((char= chr #\:) 'colon)
+ ((char= chr #\$) 'dollar)
+
((digit-char-p chr)
(read-immediate chr))
((alpha-char-p chr)
- (read-identifier chr))
+ (read-keyword chr))
(t (error (format nil "~a is not a valid lexical symbol.~%" chr))))))
(defun read-immediate (chr)
- 'immediate)
+ (defun read-immediate-helper (chrs-so-far)
+ (let ((chr (peek-char nil *standard-input* nil)))
+ (cond ((and (not (null chr)) (digit-char-p chr))
+ (read-immediate-helper (cons (read-char *standard-input* nil) chrs-so-far)))
+ ((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)))
-(defun read-identifier (chr)
- 'id)
+(defun read-keyword (chr)
+ (defun read-keyword-helper (chrs-so-far)
+ (let ((chr (peek-char nil *standard-input* nil)))
+ (cond ((and (not (null chr)) (alpha-char-p chr))
+ (read-keyword-helper (cons (read-char *standard-input* nil) chrs-so-far)))
+ ((and (not (null chr)) (digit-char-p chr))
+ (error 'invalid-immediate-or-keyword :chr chr :instance "keyword"))
+ (t (reverse chrs-so-far)))))
+ (coerce (read-keyword-helper (list chr)) 'string))
(defun whitespace-char-p (x)
(or (char= #\space x)