Browse code
feat(tree-sitter): initial pass
Edward authored on 13/02/2021 18:35:35
Showing 1 changed files
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))) |