summaryrefslogtreecommitdiff
path: root/src/lex.lisp
blob: ad386ba38c336a366464fe0830b1efe7497e2d82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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))))