Skip to content

Commit 8fd9150

Browse files
committed
feat: add pratt parser
1 parent 41b0a2b commit 8fd9150

File tree

5 files changed

+85
-13
lines changed

5 files changed

+85
-13
lines changed

lisp-inference.asd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414
:components ((:file "package")
1515
(:file "operators")
1616
(:file "parser")
17+
(:file "pratt")
1718
(:file "equivalences"
1819
:depends-on ("parser" "operators"))
1920
(:file "inferences"
2021
:depends-on ("parser" "operators"))
2122
(:file "truth-table"
22-
:depends-on ("parser" "operators" "equivalences"))))
23+
:depends-on ("pratt" "parser" "operators" "equivalences"))))
2324

2425
(asdf:defsystem #:lisp-inference/web
2526
:description "An web interface for Lisp Inference Truth Table"

src/package.lisp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#:simplification-first
1616
#:simplification-second
1717
#:syllogism-hypothetical
18+
#:parse-logic ;; pratt
1819
#:absorption ;; parser
1920
#:propositionp
2021
#:operationp

src/pratt.lisp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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))

src/truth-table.lisp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ a tautology."
203203
"A easy way to generate a truth table"
204204
`(print-truth-table (quote ,exp)))
205205

206+
;; TODO: implement a pratt parser
206207
(defmacro truth-infix (exp)
207208
"A easy and infix way of EXP generate a truth table.
208209
Ex.: (truth-infix (p ^ q)) "
@@ -212,9 +213,9 @@ a tautology."
212213
(defun main ()
213214
(format t "Example of usage: (p ^ q)~%Operators: ~a ~%" *valid-operators*)
214215
(let ((*output-stream* *standard-output*))
215-
(handler-case (loop do (princ-n "TRUTH-TABLE> ")
216+
(handler-case (loop do (princ-n "TRUTH-TABLE> ")
216217
do (force-output *output-stream*)
217-
do (print-truth-table (infix-to-prefix (read))))
218+
do (print-truth-table (parse-logic (read-line))))
218219
(end-of-file () )
219220
#+sbcl (sb-sys:interactive-interrupt () nil))
220221

web/webapp.lisp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,10 @@
4040
:initform nil
4141
:accessor truth)))
4242

43-
(defun parse-string (string)
44-
"Translate string to a list expression"
45-
(if (and (str:starts-with-p "(" string)
46-
(str:ends-with-p ")" string))
47-
(read-from-string string)
48-
(read-from-string (str:concat "(" string ")"))))
49-
5043
(defun truth-table (exp)
5144
(with-output-to-string (s)
5245
(let ((inference:*output-stream* s))
53-
(inference:print-truth-table (inference:infix-to-prefix exp)))))
46+
(inference:print-truth-table exp))))
5447

5548
(defun create-table (exp)
5649
(make-instance 'table
@@ -61,13 +54,13 @@
6154

6255
(defmethod update-table (table (exp list))
6356
(setf (prop table) (format nil "~a" exp))
64-
(setf (truth table) (truth-table exp))
57+
(setf (truth table) (truth-table exp)
6558
(update table))
6659

6760
(defmethod update-table (table (exp string))
6861
(update-table
6962
table
70-
(parse-string exp)))
63+
(inference:parse-logic exp)))
7164

7265
(defmethod render ((table table))
7366
(with-html

0 commit comments

Comments
 (0)