1+ (in-package :lisp-inference )
2+
3+ (defparameter *binding-precedence*
4+ ' (
5+ (" ^" . 80 )
6+ (" v" . 70 )
7+ (" [+]" . 60 )
8+ (" =>" . 50 )
9+ (" <=>" . 40 )))
10+
11+ (defvar *tokens* nil )
12+ (defvar *pos* 0 )
13+
14+
15+ (defun read-token (stream )
16+ (cond
17+ ((peek-char nil stream nil nil )
18+ (let ((c (peek-char nil stream )))
19+ (cond
20+ ((find c " ()" ) (list (string (read-char stream ))))
21+ ((char= c #\~ ) (list (string (read-char stream ))))
22+ ((member c ' (#\Space #\Tab #\Newline )) (read-char stream ) (read-token stream ))
23+ ((alpha-char-p c)
24+ (let ((sym (read stream )))
25+ (list (string-downcase (string sym)))))
26+ (t
27+ (let ((token (with-output-to-string (out)
28+ (loop for ch = (peek-char nil stream nil nil )
29+ while (and ch (find ch " <=>[+]" ))
30+ do (write-char (read-char stream ) out)))))
31+ (if (string= token " " ) (list (string (read-char stream ))) (list token)))))))))
32+
33+ (defun tokenize (input)
34+ (with-input-from-string (in input)
35+ (loop for token = (read-token in)
36+ while token
37+ append token)))
38+
39+ (defun next-token ()
40+ (nth *pos* *tokens* ))
41+
42+ (defun advance ()
43+ (prog1 (next-token) (incf *pos* )))
44+
45+ (defun match (tok)
46+ (when (equal (next-token) tok) (advance) t ))
47+
48+ (defun get-binding (tok)
49+ (or (cdr (assoc tok *binding-precedence* :test #' string= )) 0 ))
50+
51+ (defun nud (token)
52+ (cond
53+ ((string= token " ~" ) ` (~ , (parse-expression 90 )))
54+ ((string= token " (" )
55+ (prog1 (parse-expression) (match " )" )))
56+ (t (intern (string-upcase token)))))
57+
58+ (defun led (token left)
59+ (let ((right (parse-expression
60+ (if (member token ' (" =>" " <=>" ) :test #' string= )
61+ (1- (get-binding token)) ; ; Right-associative
62+ (get-binding token)))))
63+ (list (intern (string-upcase token)) left right)))
64+
65+ (defun parse-expression (&optional (rbp 0 ))
66+ (let* ((token (advance))
67+ (left (nud token)))
68+ (loop while (and (next-token) (< rbp (get-binding (next-token))))
69+ do (setf left (led (advance) left)))
70+ left))
71+
72+ ; ; entrypoint
73+ (defun parse-logic (input)
74+ (setf *tokens* (tokenize input)
75+ *pos* 0 )
76+ (parse-expression))
0 commit comments