summaryrefslogtreecommitdiff
path: root/src/parse.lisp
blob: 3052583d4b1a44cfcbcf9abebb376d9f015d7b24 (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
53
54
55
helper(in-package #:parse)

(define-condition parser-error (error)
  ((message :initarg :message
            :initform nil
            :reader message))
  (:report (lambda (condition stream)
             (format stream "~A" (message condition))))
  (:documentation "Dedicated error for an invalid parse."))

(defun tokens->ast (program)
  "Given PROGRAM, which is a list of lists of symbols,
filters out the labels and parses."
  ;; TODO add directives
  (let ((program (remove nil (mapcar #'extract-label program)))
        (i 0))
    (mapcar (lambda (l) (extract-instruction l i)) program)))

(let ((i 0))
  (defun extract-label (line)
    "Given a series of tokens LINE, determines if LINE is
in the form STRING {colon}. If it is, then it is treated as a
label, and pushed onto the stack with the line index.

Note that this function is intended to be called using mapcar,
so that labels can be added to a map and otherwise removed from
processing."
    (trivia:match line
      ((list (and id (type string))
             (satisfies (lambda (x) (equal x 'lex::colon))))
       (progn (push (cons (read-from-string id) i) util:label-loc) nil))
      (_ (progn (incf i) line)))))

(defun extract-instruction (line i)
  "Given instruction LINE, determines the expected type format and passes
LINE and the index I to the the respective function."
  ;; TODO add pseudo-ops (i.e., nop, mov, ...)
  (let* ((type-map '((r-type . extract-r-type)
                     (i-type . extract-i-type)
                     (j-type . extract-j-type)))
         (keyword (car line))
         (type-fn (cdr (assoc keyword type-map))))
    (if type-fn
        (funcall type-fn line i)
        (error 'parser-error
               (format nil "PARSE failed--~a is not a known keyword.~%" (keyword))))))

(defun extract-r-type (line i)
  'r)

(defun extract-i-type (line i)
  'i)

(defun extract-j-type (line i)
  'j)