ruby_tree_sitter 1.6.0-x86_64-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +213 -0
- data/ext/tree_sitter/encoding.c +29 -0
- data/ext/tree_sitter/extconf.rb +149 -0
- data/ext/tree_sitter/input.c +127 -0
- data/ext/tree_sitter/input_edit.c +42 -0
- data/ext/tree_sitter/language.c +219 -0
- data/ext/tree_sitter/logger.c +228 -0
- data/ext/tree_sitter/macros.h +163 -0
- data/ext/tree_sitter/node.c +623 -0
- data/ext/tree_sitter/parser.c +398 -0
- data/ext/tree_sitter/point.c +26 -0
- data/ext/tree_sitter/quantifier.c +43 -0
- data/ext/tree_sitter/query.c +289 -0
- data/ext/tree_sitter/query_capture.c +28 -0
- data/ext/tree_sitter/query_cursor.c +231 -0
- data/ext/tree_sitter/query_error.c +41 -0
- data/ext/tree_sitter/query_match.c +44 -0
- data/ext/tree_sitter/query_predicate_step.c +83 -0
- data/ext/tree_sitter/range.c +35 -0
- data/ext/tree_sitter/repo.rb +128 -0
- data/ext/tree_sitter/symbol_type.c +46 -0
- data/ext/tree_sitter/tree.c +234 -0
- data/ext/tree_sitter/tree_cursor.c +269 -0
- data/ext/tree_sitter/tree_sitter.c +44 -0
- data/ext/tree_sitter/tree_sitter.h +107 -0
- data/lib/tree_sitter/3.0/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.1/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.2/tree_sitter.so +0 -0
- data/lib/tree_sitter/3.3/tree_sitter.so +0 -0
- data/lib/tree_sitter/helpers.rb +23 -0
- data/lib/tree_sitter/mixins/language.rb +167 -0
- data/lib/tree_sitter/node.rb +167 -0
- data/lib/tree_sitter/query.rb +191 -0
- data/lib/tree_sitter/query_captures.rb +30 -0
- data/lib/tree_sitter/query_cursor.rb +27 -0
- data/lib/tree_sitter/query_match.rb +100 -0
- data/lib/tree_sitter/query_matches.rb +39 -0
- data/lib/tree_sitter/query_predicate.rb +14 -0
- data/lib/tree_sitter/text_predicate_capture.rb +37 -0
- data/lib/tree_sitter/version.rb +8 -0
- data/lib/tree_sitter.rb +34 -0
- data/lib/tree_stand/ast_modifier.rb +30 -0
- data/lib/tree_stand/breadth_first_visitor.rb +54 -0
- data/lib/tree_stand/config.rb +19 -0
- data/lib/tree_stand/node.rb +351 -0
- data/lib/tree_stand/parser.rb +87 -0
- data/lib/tree_stand/range.rb +55 -0
- data/lib/tree_stand/tree.rb +123 -0
- data/lib/tree_stand/utils/printer.rb +73 -0
- data/lib/tree_stand/version.rb +7 -0
- data/lib/tree_stand/visitor.rb +127 -0
- data/lib/tree_stand/visitors/tree_walker.rb +37 -0
- data/lib/tree_stand.rb +48 -0
- data/tree_sitter.gemspec +34 -0
- metadata +135 -0
@@ -0,0 +1,269 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cTreeCursor;
|
6
|
+
|
7
|
+
DATA_TYPE(TSTreeCursor, tree_cursor)
|
8
|
+
static void tree_cursor_free(void *ptr) {
|
9
|
+
tree_cursor_t *type = (tree_cursor_t *)ptr;
|
10
|
+
ts_tree_cursor_delete(&type->data);
|
11
|
+
xfree(ptr);
|
12
|
+
}
|
13
|
+
DATA_MEMSIZE(tree_cursor)
|
14
|
+
DATA_DECLARE_DATA_TYPE(tree_cursor)
|
15
|
+
DATA_ALLOCATE(tree_cursor)
|
16
|
+
DATA_UNWRAP(tree_cursor)
|
17
|
+
DATA_NEW(cTreeCursor, TSTreeCursor, tree_cursor)
|
18
|
+
DATA_FROM_VALUE(TSTreeCursor, tree_cursor)
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Safely copy a tree cursor.
|
22
|
+
*
|
23
|
+
* @return [TreeCursor]
|
24
|
+
*/
|
25
|
+
static VALUE tree_cursor_copy(VALUE self) {
|
26
|
+
VALUE res = tree_cursor_allocate(cTreeCursor);
|
27
|
+
tree_cursor_t *ptr = unwrap(res);
|
28
|
+
ptr->data = ts_tree_cursor_copy(&SELF);
|
29
|
+
return res;
|
30
|
+
}
|
31
|
+
|
32
|
+
/**
|
33
|
+
* Get the depth of the cursor's current node relative to the original
|
34
|
+
* node that the cursor was constructed with.
|
35
|
+
*
|
36
|
+
* @return [Integer]
|
37
|
+
*/
|
38
|
+
static VALUE tree_cursor_current_depth(VALUE self) {
|
39
|
+
return UINT2NUM(ts_tree_cursor_current_depth(&SELF));
|
40
|
+
}
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Get the index of the cursor's current node out of all of the
|
44
|
+
* descendants of the original node that the cursor was constructed with.
|
45
|
+
*
|
46
|
+
* @return [Integer]
|
47
|
+
*/
|
48
|
+
static VALUE tree_cursor_current_descendant_index(VALUE self) {
|
49
|
+
return UINT2NUM(ts_tree_cursor_current_descendant_index(&SELF));
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Get the field id of the tree cursor's current node.
|
54
|
+
*
|
55
|
+
* This returns zero if the current node doesn't have a field.
|
56
|
+
*
|
57
|
+
* @see Node#child_by_field_id
|
58
|
+
* @see Node#field_id_for_name
|
59
|
+
*
|
60
|
+
* @return [Integer]
|
61
|
+
*/
|
62
|
+
static VALUE tree_cursor_current_field_id(VALUE self) {
|
63
|
+
return UINT2NUM(ts_tree_cursor_current_field_id(&SELF));
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* Get the field name of the tree cursor's current node.
|
68
|
+
*
|
69
|
+
* This returns +nil+ if the current node doesn't have a field.
|
70
|
+
*
|
71
|
+
* @see Node#child_by_field_name
|
72
|
+
*
|
73
|
+
* @return [String]
|
74
|
+
*/
|
75
|
+
static VALUE tree_cursor_current_field_name(VALUE self) {
|
76
|
+
return safe_str(ts_tree_cursor_current_field_name(&SELF));
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Get the tree cursor's current node.
|
81
|
+
*
|
82
|
+
* @return [Node]
|
83
|
+
*/
|
84
|
+
static VALUE tree_cursor_current_node(VALUE self) {
|
85
|
+
TSNode node = ts_tree_cursor_current_node(&SELF);
|
86
|
+
return new_node(&node);
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Move the cursor to the node that is the nth descendant of
|
91
|
+
* the original node that the cursor was constructed with, where
|
92
|
+
* zero represents the original node itself.
|
93
|
+
*
|
94
|
+
* @return [nil]
|
95
|
+
*/
|
96
|
+
static VALUE tree_cursor_goto_descendant(VALUE self, VALUE descendant_idx) {
|
97
|
+
uint32_t idx = NUM2UINT(descendant_idx);
|
98
|
+
ts_tree_cursor_goto_descendant(&SELF, idx);
|
99
|
+
return Qnil;
|
100
|
+
}
|
101
|
+
|
102
|
+
/**
|
103
|
+
* Move the cursor to the first child of its current node.
|
104
|
+
*
|
105
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+
|
106
|
+
* if there were no children.
|
107
|
+
*
|
108
|
+
* @return [Boolean]
|
109
|
+
*/
|
110
|
+
static VALUE tree_cursor_goto_first_child(VALUE self) {
|
111
|
+
return ts_tree_cursor_goto_first_child(&SELF) ? Qtrue : Qfalse;
|
112
|
+
}
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Move the cursor to the first child of its current node that extends beyond
|
116
|
+
* the given byte offset.
|
117
|
+
*
|
118
|
+
* This returns the index of the child node if one was found, and returns -1
|
119
|
+
* if no such child was found.
|
120
|
+
*
|
121
|
+
* @return [Integer]
|
122
|
+
*/
|
123
|
+
static VALUE tree_cursor_goto_first_child_for_byte(VALUE self, VALUE byte) {
|
124
|
+
return LL2NUM(
|
125
|
+
ts_tree_cursor_goto_first_child_for_byte(&SELF, NUM2UINT(byte)));
|
126
|
+
}
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Move the cursor to the first child of its current node that extends beyond
|
130
|
+
* the given or point.
|
131
|
+
*
|
132
|
+
* This returns the index of the child node if one was found, and returns -1
|
133
|
+
* if no such child was found.
|
134
|
+
*
|
135
|
+
* @return [Integer]
|
136
|
+
*/
|
137
|
+
static VALUE tree_cursor_goto_first_child_for_point(VALUE self, VALUE point) {
|
138
|
+
return LL2NUM(
|
139
|
+
ts_tree_cursor_goto_first_child_for_point(&SELF, value_to_point(point)));
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Move the cursor to the last child of its current node.
|
144
|
+
*
|
145
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+ if
|
146
|
+
* there were no children.
|
147
|
+
*
|
148
|
+
* Note that this function may be slower than {#goto_first_child}
|
149
|
+
* because it needs to iterate through all the children to compute the child's
|
150
|
+
* position.
|
151
|
+
*/
|
152
|
+
static VALUE tree_cursor_goto_last_child(VALUE self) {
|
153
|
+
return ts_tree_cursor_goto_last_child(&SELF) ? Qtrue : Qfalse;
|
154
|
+
}
|
155
|
+
|
156
|
+
/**
|
157
|
+
* Move the cursor to the next sibling of its current node.
|
158
|
+
*
|
159
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+
|
160
|
+
* if there was no next sibling node.
|
161
|
+
*
|
162
|
+
* @return Boolean
|
163
|
+
*/
|
164
|
+
static VALUE tree_cursor_goto_next_sibling(VALUE self) {
|
165
|
+
return ts_tree_cursor_goto_next_sibling(&SELF) ? Qtrue : Qfalse;
|
166
|
+
}
|
167
|
+
|
168
|
+
/**
|
169
|
+
* Move the cursor to the parent of its current node.
|
170
|
+
*
|
171
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+
|
172
|
+
* if there was no parent node (the cursor was already on the root node).
|
173
|
+
*
|
174
|
+
* @return [Boolean]
|
175
|
+
*/
|
176
|
+
static VALUE tree_cursor_goto_parent(VALUE self) {
|
177
|
+
return ts_tree_cursor_goto_parent(&SELF) ? Qtrue : Qfalse;
|
178
|
+
}
|
179
|
+
|
180
|
+
/**
|
181
|
+
* Move the cursor to the previous sibling of its current node.
|
182
|
+
*
|
183
|
+
* This returns +true+ if the cursor successfully moved, and returns +false+ if
|
184
|
+
* there was no previous sibling node.
|
185
|
+
*
|
186
|
+
* Note, that this function may be slower than
|
187
|
+
* {#goto_next_sibling} due to how node positions are stored. In
|
188
|
+
* the worst case, this will need to iterate through all the children upto the
|
189
|
+
* previous sibling node to recalculate its position.
|
190
|
+
*
|
191
|
+
* @return [Boolean]
|
192
|
+
*/
|
193
|
+
static VALUE tree_cursor_goto_previous_sibling(VALUE self) {
|
194
|
+
return ts_tree_cursor_goto_previous_sibling(&SELF) ? Qtrue : Qfalse;
|
195
|
+
}
|
196
|
+
|
197
|
+
/**
|
198
|
+
* Create a new tree cursor starting from the given node.
|
199
|
+
*
|
200
|
+
* A tree cursor allows you to walk a syntax tree more efficiently than is
|
201
|
+
* possible using the {Node} functions. It is a mutable object that is always
|
202
|
+
* on a certain syntax node, and can be moved imperatively to different nodes.
|
203
|
+
*
|
204
|
+
* @return [TreeCursor]
|
205
|
+
*/
|
206
|
+
static VALUE tree_cursor_initialize(VALUE self, VALUE node) {
|
207
|
+
TSNode n = value_to_node(node);
|
208
|
+
tree_cursor_t *ptr = unwrap(self);
|
209
|
+
ptr->data = ts_tree_cursor_new(n);
|
210
|
+
return self;
|
211
|
+
}
|
212
|
+
|
213
|
+
/**
|
214
|
+
* Re-initialize a tree cursor to start at a different node.
|
215
|
+
*
|
216
|
+
* @return [nil]
|
217
|
+
*/
|
218
|
+
static VALUE tree_cursor_reset(VALUE self, VALUE node) {
|
219
|
+
ts_tree_cursor_reset(&SELF, value_to_node(node));
|
220
|
+
return Qnil;
|
221
|
+
}
|
222
|
+
|
223
|
+
/**
|
224
|
+
* Re-initialize a tree cursor to the same position as another cursor.
|
225
|
+
*
|
226
|
+
* Unlike {#reset}, this will not lose parent information and allows reusing
|
227
|
+
* already created cursors.
|
228
|
+
*
|
229
|
+
* @return [nil]
|
230
|
+
*/
|
231
|
+
VALUE tree_cursor_reset_to(VALUE self, VALUE src) {
|
232
|
+
ts_tree_cursor_reset_to(&SELF, &unwrap(src)->data);
|
233
|
+
return Qnil;
|
234
|
+
}
|
235
|
+
|
236
|
+
void init_tree_cursor(void) {
|
237
|
+
cTreeCursor = rb_define_class_under(mTreeSitter, "TreeCursor", rb_cObject);
|
238
|
+
|
239
|
+
rb_define_alloc_func(cTreeCursor, tree_cursor_allocate);
|
240
|
+
|
241
|
+
/* Class methods */
|
242
|
+
rb_define_method(cTreeCursor, "copy", tree_cursor_copy, 0);
|
243
|
+
rb_define_method(cTreeCursor, "current_depth", tree_cursor_current_depth, 0);
|
244
|
+
rb_define_method(cTreeCursor, "current_descendant_index",
|
245
|
+
tree_cursor_current_descendant_index, 0);
|
246
|
+
rb_define_method(cTreeCursor, "current_field_id",
|
247
|
+
tree_cursor_current_field_id, 0);
|
248
|
+
rb_define_method(cTreeCursor, "current_field_name",
|
249
|
+
tree_cursor_current_field_name, 0);
|
250
|
+
rb_define_method(cTreeCursor, "current_node", tree_cursor_current_node, 0);
|
251
|
+
rb_define_method(cTreeCursor, "goto_descendant", tree_cursor_goto_descendant,
|
252
|
+
1);
|
253
|
+
rb_define_method(cTreeCursor, "goto_first_child",
|
254
|
+
tree_cursor_goto_first_child, 0);
|
255
|
+
rb_define_method(cTreeCursor, "goto_first_child_for_byte",
|
256
|
+
tree_cursor_goto_first_child_for_byte, 1);
|
257
|
+
rb_define_method(cTreeCursor, "goto_first_child_for_point",
|
258
|
+
tree_cursor_goto_first_child_for_point, 1);
|
259
|
+
rb_define_method(cTreeCursor, "goto_last_child", tree_cursor_goto_last_child,
|
260
|
+
0);
|
261
|
+
rb_define_method(cTreeCursor, "goto_next_sibling",
|
262
|
+
tree_cursor_goto_next_sibling, 0);
|
263
|
+
rb_define_method(cTreeCursor, "goto_parent", tree_cursor_goto_parent, 0);
|
264
|
+
rb_define_method(cTreeCursor, "goto_previous_sibling",
|
265
|
+
tree_cursor_goto_previous_sibling, 0);
|
266
|
+
rb_define_method(cTreeCursor, "initialize", tree_cursor_initialize, 1);
|
267
|
+
rb_define_method(cTreeCursor, "reset", tree_cursor_reset, 1);
|
268
|
+
rb_define_method(cTreeCursor, "reset_to", tree_cursor_reset_to, 1);
|
269
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
VALUE mTreeSitter;
|
4
|
+
|
5
|
+
void Init_tree_sitter() {
|
6
|
+
mTreeSitter = rb_define_module("TreeSitter");
|
7
|
+
|
8
|
+
/**
|
9
|
+
* The latest ABI version that is supported by the current version of the
|
10
|
+
* library. When Languages are generated by the Tree-sitter CLI, they are
|
11
|
+
* assigned an ABI version number that corresponds to the current CLI version.
|
12
|
+
* The Tree-sitter library is generally backwards-compatible with languages
|
13
|
+
* generated using older CLI versions, but is not forwards-compatible.
|
14
|
+
*/
|
15
|
+
rb_define_const(mTreeSitter, "LANGUAGE_VERSION",
|
16
|
+
INT2NUM(TREE_SITTER_LANGUAGE_VERSION));
|
17
|
+
|
18
|
+
/**
|
19
|
+
* The earliest ABI version that is supported by the current version of the
|
20
|
+
* library.
|
21
|
+
*/
|
22
|
+
rb_define_const(mTreeSitter, "MIN_COMPATIBLE_LANGUAGE_VERSION",
|
23
|
+
TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION);
|
24
|
+
|
25
|
+
init_encoding();
|
26
|
+
init_input();
|
27
|
+
init_input_edit();
|
28
|
+
init_language();
|
29
|
+
init_logger();
|
30
|
+
init_node();
|
31
|
+
init_parser();
|
32
|
+
init_point();
|
33
|
+
init_quantifier();
|
34
|
+
init_query();
|
35
|
+
init_query_capture();
|
36
|
+
init_query_cursor();
|
37
|
+
init_query_error();
|
38
|
+
init_query_match();
|
39
|
+
init_query_predicate_step();
|
40
|
+
init_range();
|
41
|
+
init_symbol_type();
|
42
|
+
init_tree();
|
43
|
+
init_tree_cursor();
|
44
|
+
}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
#ifndef _RB_TREE_SITTER_H
|
2
|
+
#define _RB_TREE_SITTER_H
|
3
|
+
|
4
|
+
#include "macros.h"
|
5
|
+
#include <dlfcn.h>
|
6
|
+
#include <fcntl.h>
|
7
|
+
#include <ruby.h>
|
8
|
+
#include <stdio.h>
|
9
|
+
#include <string.h>
|
10
|
+
#include <tree_sitter/api.h>
|
11
|
+
|
12
|
+
static inline VALUE safe_str(const char *str) {
|
13
|
+
if (str == NULL) {
|
14
|
+
return Qnil;
|
15
|
+
} else {
|
16
|
+
return rb_utf8_str_new_cstr(str);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
static inline VALUE safe_str2(const char *str, uint32_t len) {
|
21
|
+
if (str == NULL) {
|
22
|
+
return Qnil;
|
23
|
+
} else if (len == 0) {
|
24
|
+
return rb_utf8_str_new_cstr("");
|
25
|
+
} else {
|
26
|
+
return rb_utf8_str_new(str, len);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
static inline VALUE safe_symbol(const char *str) {
|
31
|
+
if (str == NULL) {
|
32
|
+
return Qnil;
|
33
|
+
} else {
|
34
|
+
return ID2SYM(rb_intern(str));
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
// VALUE to TS* converters
|
39
|
+
|
40
|
+
TSInput value_to_input(VALUE);
|
41
|
+
TSInputEdit value_to_input_edit(VALUE);
|
42
|
+
TSInputEncoding value_to_encoding(VALUE);
|
43
|
+
TSLanguage *value_to_language(VALUE);
|
44
|
+
TSLogger value_to_logger(VALUE);
|
45
|
+
TSNode value_to_node(VALUE);
|
46
|
+
TSPoint value_to_point(VALUE);
|
47
|
+
TSQuantifier value_to_quantifier(VALUE);
|
48
|
+
TSQuery *value_to_query(VALUE);
|
49
|
+
TSQueryCursor *value_to_query_cursor(VALUE);
|
50
|
+
TSQueryError value_to_query_error(VALUE);
|
51
|
+
TSQueryMatch value_to_query_match(VALUE);
|
52
|
+
TSQueryPredicateStep value_to_query_predicate_step(VALUE);
|
53
|
+
TSQueryPredicateStepType value_to_query_predicate_step_type(VALUE);
|
54
|
+
TSRange value_to_range(VALUE);
|
55
|
+
TSSymbolType value_to_symbol_type(VALUE);
|
56
|
+
TSTree *value_to_tree(VALUE);
|
57
|
+
TSTreeCursor value_to_tree_cursor(VALUE);
|
58
|
+
|
59
|
+
// TS* to VALUE converters
|
60
|
+
VALUE new_input(const TSInput *);
|
61
|
+
VALUE new_language(const TSLanguage *);
|
62
|
+
VALUE new_logger(const TSLogger *);
|
63
|
+
VALUE new_logger_by_val(TSLogger);
|
64
|
+
VALUE new_node(const TSNode *);
|
65
|
+
VALUE new_node_by_val(TSNode);
|
66
|
+
VALUE new_point(const TSPoint *);
|
67
|
+
VALUE new_point_by_val(TSPoint);
|
68
|
+
VALUE new_query_capture(const TSQueryCapture *);
|
69
|
+
VALUE new_query_match(const TSQueryMatch *);
|
70
|
+
VALUE new_query_predicate_step(const TSQueryPredicateStep *);
|
71
|
+
VALUE new_range(const TSRange *);
|
72
|
+
VALUE new_symbol_type(TSSymbolType);
|
73
|
+
VALUE new_tree(TSTree *);
|
74
|
+
|
75
|
+
// All init_* functions are called from Init_tree_sitter
|
76
|
+
void init_encoding(void);
|
77
|
+
void init_input(void);
|
78
|
+
void init_input_edit(void);
|
79
|
+
void init_language(void);
|
80
|
+
void init_logger(void);
|
81
|
+
void init_node(void);
|
82
|
+
void init_parser(void);
|
83
|
+
void init_point(void);
|
84
|
+
void init_quantifier(void);
|
85
|
+
void init_query(void);
|
86
|
+
void init_query_capture(void);
|
87
|
+
void init_query_cursor(void);
|
88
|
+
void init_query_error(void);
|
89
|
+
void init_query_match(void);
|
90
|
+
void init_query_predicate_step(void);
|
91
|
+
void init_range(void);
|
92
|
+
void init_symbol_type(void);
|
93
|
+
void init_tree(void);
|
94
|
+
void init_tree_cursor(void);
|
95
|
+
|
96
|
+
// Other helpers
|
97
|
+
const char *quantifier_str(TSQuantifier);
|
98
|
+
const char *query_error_str(TSQueryError);
|
99
|
+
|
100
|
+
// TSTree reference counting
|
101
|
+
int tree_rc_free(const TSTree *);
|
102
|
+
void tree_rc_new(const TSTree *);
|
103
|
+
|
104
|
+
// This is a special entry-point for the extension
|
105
|
+
void Init_tree_sitter(void);
|
106
|
+
|
107
|
+
#endif
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# splits an array like [rust](https://doc.rust-lang.org/std/primitive.slice.html#method.split)
|
4
|
+
def array_split_like_rust(array, &block)
|
5
|
+
return enum_for(__method__, array) if !block_given?
|
6
|
+
|
7
|
+
return [] if array.empty?
|
8
|
+
|
9
|
+
result = []
|
10
|
+
current_slice = []
|
11
|
+
|
12
|
+
array.each do |element|
|
13
|
+
if yield(element)
|
14
|
+
result << current_slice
|
15
|
+
current_slice = []
|
16
|
+
else
|
17
|
+
current_slice << element
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
result << current_slice
|
22
|
+
result
|
23
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TreeSitter
|
4
|
+
# A colon-separated list of paths pointing to directories that can contain parsers.
|
5
|
+
# Order matters.
|
6
|
+
# Takes precedence over default lookup paths.
|
7
|
+
ENV_PARSERS =
|
8
|
+
ENV['TREE_SITTER_PARSERS']
|
9
|
+
&.split(':')
|
10
|
+
&.map { |v| Pathname(v) }
|
11
|
+
.freeze
|
12
|
+
|
13
|
+
# The default paths we use to lookup parsers.
|
14
|
+
# Order matters.
|
15
|
+
LIBDIRS = [
|
16
|
+
'.vendor/parsers',
|
17
|
+
'.vendor/tree-sitter-parsers',
|
18
|
+
'vendor/parsers',
|
19
|
+
'vendor/tree-sitter-parsers',
|
20
|
+
'parsers',
|
21
|
+
'tree-sitter-parsers',
|
22
|
+
'.',
|
23
|
+
'/opt/local/lib',
|
24
|
+
'/opt/lib',
|
25
|
+
'/usr/local/lib',
|
26
|
+
'/usr/lib',
|
27
|
+
].map { |p| Pathname(p) }.freeze
|
28
|
+
|
29
|
+
# Mixins.
|
30
|
+
module Mixins
|
31
|
+
# Language Mixin.
|
32
|
+
module Language
|
33
|
+
# Load a language from configuration or default lookup paths.
|
34
|
+
#
|
35
|
+
# @example Load java from default paths
|
36
|
+
# # This will look for:
|
37
|
+
# #
|
38
|
+
# # .vendor/tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
|
39
|
+
# # .vendor/parsers/(java/)?(libtree-sitter-)?java.{ext}
|
40
|
+
# # vendor/tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
|
41
|
+
# # vendor/parsers/(java/)?(libtree-sitter-)?java.{ext}
|
42
|
+
# # parsers/(java/)?(libtree-sitter-)?java.{ext}
|
43
|
+
# # tree-sitter-parsers/(java/)?(libtree-sitter-)?java.{ext}
|
44
|
+
# # /opt/local/lib/(java/)?(libtree-sitter-)?java.{ext}
|
45
|
+
# # /opt/lib/(java/)?(libtree-sitter-)?java.{ext}
|
46
|
+
# # /usr/local/lib/(java/)?(libtree-sitter-)?java.{ext}
|
47
|
+
# # /usr/lib/(java/)?(libtree-sitter-)?java.{ext}
|
48
|
+
# #
|
49
|
+
# java = TreeSitter.language('java')
|
50
|
+
#
|
51
|
+
# @example (TreeStand) Load java from a configured path
|
52
|
+
# # This will look for:
|
53
|
+
# #
|
54
|
+
# # /my/path/(java/)?(libtree-sitter-)?java.{ext}
|
55
|
+
# #
|
56
|
+
# TreeStand.config.parser_path = '/my/path'
|
57
|
+
# java = TreeStand::Parser.language('java')
|
58
|
+
#
|
59
|
+
# @example (TreeStand) Load java from environment variables
|
60
|
+
# # This will look for:
|
61
|
+
# #
|
62
|
+
# # /my/forced/env/path/(java/)?(libtree-sitter-)?java.{ext}
|
63
|
+
# # /my/path/(java/)?(libtree-sitter-)?java.{ext}
|
64
|
+
# #
|
65
|
+
# # … and the same works for the default paths if `TreeStand.config.parser_path`
|
66
|
+
# # was `nil`
|
67
|
+
# ENV['TREE_SITTER_PARSERS'] = '/my/forced/env/path'
|
68
|
+
# TreeStand.config.parser_path = '/my/path'
|
69
|
+
# java = TreeStand::Parser.language('java')
|
70
|
+
#
|
71
|
+
# @note the name is case sensitive, but library lookup is not: if your parser is defined as `COBOL`,
|
72
|
+
# then you have to call `language('COBOL')`, but the parser can be `cobol.so/COBOL.so/…`.
|
73
|
+
#
|
74
|
+
# @param name [String] the name of the parser.
|
75
|
+
# This name is used to load the symbol from the compiled parser, replacing `-` with `_`.
|
76
|
+
#
|
77
|
+
# @return [TreeSitter:language] a language object to use in your parsers.
|
78
|
+
#
|
79
|
+
# @raise [RuntimeError] if the parser was not found.
|
80
|
+
#
|
81
|
+
# @see search_for_lib
|
82
|
+
def language(name)
|
83
|
+
lib = search_for_lib(name)
|
84
|
+
|
85
|
+
if lib.nil?
|
86
|
+
raise <<~MSG.chomp
|
87
|
+
Failed to load a parser for #{name}.
|
88
|
+
|
89
|
+
#{search_lib_message}
|
90
|
+
MSG
|
91
|
+
end
|
92
|
+
|
93
|
+
# We know that the bindings will accept `lib`, but I don't know how to tell sorbet
|
94
|
+
# the types in ext/tree_sitter where `load` is defined.
|
95
|
+
TreeSitter::Language.load(name.tr('-', '_'), lib)
|
96
|
+
end
|
97
|
+
|
98
|
+
# The platform-specific extension of the parser.
|
99
|
+
# @return [String] `dylib` or `so` for mac or linux.
|
100
|
+
def ext
|
101
|
+
case Gem::Platform.local.os
|
102
|
+
in /darwin/ then 'dylib'
|
103
|
+
else 'so'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# The library directories we need to look into.
|
110
|
+
#
|
111
|
+
# @return [Array<Pathname>] the list of candidate places to use when searching for parsers.
|
112
|
+
#
|
113
|
+
# @see ENV_PARSERS
|
114
|
+
# @see LIBDIRS
|
115
|
+
def lib_dirs = [*TreeSitter::ENV_PARSERS, *TreeSitter::LIBDIRS]
|
116
|
+
|
117
|
+
# Lookup a parser by name.
|
118
|
+
#
|
119
|
+
# Precedence:
|
120
|
+
# 1. `Env['TREE_SITTER_PARSERS]`.
|
121
|
+
# 2. {TreeStand::Config#parser_path} if using {TreeStand}.
|
122
|
+
# 3. {LIBDIRS}.
|
123
|
+
#
|
124
|
+
# If a {TreeStand::Config#parser_path} is `nil`, {LIBDIRS} is used.
|
125
|
+
# If a {TreeStand::Config#parser_path} is a {::Pathname}, {LIBDIRS} is ignored.
|
126
|
+
def search_for_lib(name)
|
127
|
+
files =
|
128
|
+
[name, name.upcase, name.downcase]
|
129
|
+
.uniq
|
130
|
+
.flat_map do |n|
|
131
|
+
base = "#{n}.#{ext}"
|
132
|
+
[base, "tree-sitter-#{base}", "libtree-sitter-#{base}"]
|
133
|
+
end
|
134
|
+
|
135
|
+
lib_dirs
|
136
|
+
.product(files)
|
137
|
+
.find do |dir, so|
|
138
|
+
path = dir / so
|
139
|
+
path = dir / name / so if !path.exist?
|
140
|
+
break path.expand_path if path.exist?
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Generates a string message on where parser lookup happens.
|
145
|
+
#
|
146
|
+
# @return [String] A pretty message.
|
147
|
+
def search_lib_message
|
148
|
+
indent = 2
|
149
|
+
pretty = ->(arr) {
|
150
|
+
if arr
|
151
|
+
arr
|
152
|
+
.compact
|
153
|
+
.map { |v| "#{' ' * indent}#{v.expand_path}" }
|
154
|
+
.join("\n")
|
155
|
+
end
|
156
|
+
}
|
157
|
+
<<~MSG.chomp
|
158
|
+
From ENV['TREE_SITTER_PARSERS']:
|
159
|
+
#{pretty.call(ENV_PARSERS)}
|
160
|
+
|
161
|
+
From Defaults:
|
162
|
+
#{pretty.call(lib_dirs)}
|
163
|
+
MSG
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|