git.fiddlerwoaroof.com
Browse code

feat(tree-sitter): initial pass

Edward authored on 13/02/2021 18:35:35
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,74 @@
1
+;; Uses death's bindings to tree-sitter: https://github.com/death/cl-tree-sitter
2
+(defpackage :fwoar.lisp-sandbox.tree-sitter-parser
3
+  (:use :cl )
4
+  (:export ))
5
+(in-package :fwoar.lisp-sandbox.tree-sitter-parser)
6
+
7
+(named-readtables:in-readtable :fare-quasiquote)
8
+
9
+(defun tag-p (it)
10
+  (typecase it
11
+    (keyword t)
12
+    (list (= 2 (length it)))))
13
+
14
+(defun d-string (pos src)
15
+  (let ((lines (fwoar.string-utils:get-part-modifier #\newline src)))
16
+    lines
17
+    (trivia:ematch pos
18
+      (`((,s-c ,s-l) (,e-c ,e-l))
19
+        (multiple-value-bind (_ s-l-c) (array-displacement (elt lines s-l))
20
+          (declare (ignore _))
21
+          (let ((start-pos (+ s-l-c s-c)))
22
+            (multiple-value-bind (_ e-l-c) (array-displacement (elt lines e-l))
23
+              (declare (ignore _))
24
+              (let ((end-pos (+ e-l-c e-c)))
25
+                (make-array (- end-pos start-pos)
26
+                            :element-type (array-element-type src)
27
+                            :displaced-to src
28
+                            :displaced-index-offset start-pos)))))))))
29
+
30
+(defun parse-thing (it)
31
+  (trivia:ematch it
32
+    (`((,tag ,op) ,pos ,childs)
33
+      `(,tag ,op ,pos ,childs))
34
+    (`(,op ,pos ,childs)
35
+      `(nil ,op ,pos ,childs))))
36
+
37
+(defun displace-tree (tree src)
38
+  (serapeum:map-tree
39
+   (lambda (node)
40
+     (typecase node
41
+       (cons (if (and (tag-p (car node)) (= 3 (length node)))
42
+                 (locally (declare (optimize (debug 3)))
43
+                   (destructuring-bind (tag op pos childs) (parse-thing node)
44
+                     (list (if tag
45
+                               (list tag op)
46
+                               op)
47
+                           (d-string pos src)
48
+                           childs)))
49
+                 node))
50
+       (t node)))
51
+   tree
52
+   :traversal :postorder))
53
+
54
+(defvar *current-language*)
55
+(defun parse (src &optional (language *current-language*))
56
+  (typecase src
57
+    (pathname (parse language (alexandria:read-file-into-string src)))
58
+    (string (displace-tree (cl-tree-sitter:parse-string language src)
59
+                           src))))
60
+
61
+(defun collect-nodes-of-type (tree type)
62
+  (serapeum:with-collector (save)
63
+    (serapeum:map-tree
64
+     (lambda (node)
65
+       (typecase node
66
+         (cons (if (and (tag-p (car node)) (= 3 (length node)))
67
+                   (destructuring-bind (_ op . __) (parse-thing node)
68
+                     (declare (ignore _ __))
69
+                     (when (eql op type)
70
+                       (save node)))
71
+                   node))
72
+         (t node)))
73
+     tree
74
+     :traversal :postorder)))