summaryrefslogtreecommitdiff
path: root/src/lex.lisp
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-03-20 13:51:28 -0400
committerbd <bdunahu@operationnull.com>2025-03-20 13:51:28 -0400
commit6e338215192c26dfb16236398ca8e3762a8d4d0e (patch)
tree823d7102f43ea5a4b377d5c2cb04a5ec02fb20b7 /src/lex.lisp
parent19d13c8339ee990fba358417a54aa6f1c94c7bca (diff)
Add logic to open file, lex single character symbols, tests
Diffstat (limited to 'src/lex.lisp')
-rw-r--r--src/lex.lisp52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/lex.lisp b/src/lex.lisp
new file mode 100644
index 0000000..ad386ba
--- /dev/null
+++ b/src/lex.lisp
@@ -0,0 +1,52 @@
+(in-package #:lex)
+
+(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."
+ (let ((token (read-token)))
+ (if token
+ (read-tokens (cons token tokens-so-far))
+ (reverse tokens-so-far))))
+
+ (and (probe-file file)
+ (with-open-file (*standard-input* file :direction :input)
+ (read-tokens '()))))
+
+(defun read-token ()
+ "Reads *STANDARD-INPUT* and returns a token, or nil if the end
+of file has been reached.
+Whitespace, commas, colons, and parentheses are token delimiters.
+Comments start with a semi-colon ';' and all tokens after are ignored."
+ (let ((chr (read-char *standard-input* nil)))
+ (cond
+ ((null chr) chr)
+ ((whitespace-char-p chr)
+ (read-token))
+
+ ((char= chr #\;)
+ (progn (read-line *standard-input* nil)
+ (read-token)))
+
+ ((char= chr #\() 'left-paren)
+ ((char= chr #\)) 'right-paren)
+
+ ((digit-char-p chr)
+ (read-immediate chr))
+
+ ((alpha-char-p chr)
+ (read-identifier chr))
+
+ (t (error (format nil "~a is not a valid lexical symbol.~%" chr))))))
+
+(defun read-immediate (chr)
+ 'immediate)
+
+(defun read-identifier (chr)
+ 'id)
+
+(defun whitespace-char-p (x)
+ (or (char= #\space x)
+ (not (graphic-char-p x))))