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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
(in-package :monkey)
(eval-always
(defmacro def-tokens (prefix &body tok-def)
(let ((i 0)
(hash-sym (gensym))
(body (list)))
(loop :for def :in tok-def
:if (consp def)
:do (let ((sym (concat-symbols prefix (car def))))
(push `(defparameter ,sym ,i) body)
(push `(setf (gethash ,sym ,hash-sym) ,(cadr def)) body))
:else
:do (push `(defparameter ,(concat-symbols prefix def) ,i) body)
:do (incf i)
:finally (setf body (reverse body)))
`(progn (defparameter ,hash-sym (make-hash-table))
,@body
(defparameter ,(concat-symbols prefix 'count) ,i)
(defun as-token (token-type)
(make-token token-type (or (gethash token-type ,hash-sym) "")))))))
(def-tokens token
illegal
eof
ident
int
(= "=")
(+ "+")
(- "-")
(! "!")
(* "*")
(/ "/")
(== "==")
(!= "!=")
(< "<")
(> ">")
(comma ",")
(semicolon ";")
(lparen "(")
(rparen ")")
(lbrace "{")
(rbrace "}")
(function "fn")
(let "let")
(true "true")
(false "false")
(if "if")
(else "else")
(return "return"))
(defclass token ()
((_type :reader _type :initarg :type)
(literal :reader literal :initarg :literal)))
(defmethod token= ((t1 token) (t2 token))
(and (= (_type t1) (_type t2))
(string= (literal t1) (literal t2))))
(defun make-token (type literal)
(make-instance 'token :type type :literal (string literal)))
(defmethod print-object ((token token) stream)
(print-unreadable-object (token stream :type t :identity t)
(princ (literal token) stream)))
(defparameter *keywords*
(let ((kw (make-hash-table)))
(setf (gethash "fn" kw) token-function)
(setf (gethash "let" kw) token-let)
(setf (gethash "true" kw) token-true)
(setf (gethash "false" kw) token-false)
(setf (gethash "if" kw) token-if)
(setf (gethash "else" kw) token-else)
(setf (gethash "return" kw) token-return)
kw))
(defun lookup-identifier (str)
(multiple-value-bind (val ok) (gethash str *keywords*)
(if (not (null ok))
val
token-ident)))
|