ruby_tree_sitter 0.20.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +152 -0
- data/ext/tree_sitter/encoding.c +29 -0
- data/ext/tree_sitter/extconf.rb +172 -0
- data/ext/tree_sitter/input.c +126 -0
- data/ext/tree_sitter/input_edit.c +42 -0
- data/ext/tree_sitter/language.c +134 -0
- data/ext/tree_sitter/logger.c +212 -0
- data/ext/tree_sitter/macros.h +163 -0
- data/ext/tree_sitter/node.c +310 -0
- data/ext/tree_sitter/parser.c +203 -0
- data/ext/tree_sitter/point.c +26 -0
- data/ext/tree_sitter/quantifier.c +43 -0
- data/ext/tree_sitter/query.c +157 -0
- data/ext/tree_sitter/query_capture.c +28 -0
- data/ext/tree_sitter/query_cursor.c +103 -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/symbol_type.c +46 -0
- data/ext/tree_sitter/tree.c +145 -0
- data/ext/tree_sitter/tree_cursor.c +97 -0
- data/ext/tree_sitter/tree_sitter.c +32 -0
- data/ext/tree_sitter/tree_sitter.h +107 -0
- data/lib/tree_sitter/node.rb +164 -0
- data/lib/tree_sitter/version.rb +5 -0
- data/lib/tree_sitter.rb +13 -0
- data/test/README.md +15 -0
- data/test/test_helper.rb +9 -0
- data/test/tree_sitter/language_test.rb +68 -0
- data/test/tree_sitter/logger_test.rb +69 -0
- data/test/tree_sitter/node_test.rb +355 -0
- data/test/tree_sitter/parser_test.rb +140 -0
- data/test/tree_sitter/query_test.rb +153 -0
- data/test/tree_sitter/tree_cursor_test.rb +83 -0
- data/test/tree_sitter/tree_test.rb +51 -0
- data/tree_sitter.gemspec +32 -0
- metadata +189 -0
@@ -0,0 +1,212 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cLogger;
|
6
|
+
|
7
|
+
// This type is layed out in the DATA_* style.
|
8
|
+
// data: the TSLogger object
|
9
|
+
// payload: what will be used in TSLogger.log()
|
10
|
+
// therefore: data.payload = payload
|
11
|
+
// format: optional formatting string. Passed to "printf" if it exists
|
12
|
+
typedef struct {
|
13
|
+
TSLogger data;
|
14
|
+
VALUE payload;
|
15
|
+
VALUE format;
|
16
|
+
} logger_t;
|
17
|
+
|
18
|
+
static const char *logger_log_type_str(TSLogType log_type) {
|
19
|
+
switch (log_type) {
|
20
|
+
case TSLogTypeParse:
|
21
|
+
return "Parse:";
|
22
|
+
case TSLogTypeLex:
|
23
|
+
return "Lex :";
|
24
|
+
default:
|
25
|
+
return "?????:";
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
static void logger_log_printf(void *ptr, TSLogType log_type,
|
30
|
+
const char *message) {
|
31
|
+
logger_t *logger = (logger_t *)ptr;
|
32
|
+
VALUE type = safe_str(logger_log_type_str(log_type));
|
33
|
+
VALUE msg = safe_str(message);
|
34
|
+
rb_funcall(logger->payload, rb_intern("printf"), 3, logger->format, type,
|
35
|
+
msg);
|
36
|
+
}
|
37
|
+
|
38
|
+
static void logger_log_puts(void *ptr, TSLogType log_type,
|
39
|
+
const char *message) {
|
40
|
+
logger_t *logger = (logger_t *)ptr;
|
41
|
+
const char *format =
|
42
|
+
NIL_P(logger->format) ? "%s %s" : StringValueCStr(logger->format);
|
43
|
+
VALUE str = rb_sprintf(format, logger_log_type_str(log_type), message);
|
44
|
+
rb_funcall(logger->payload, rb_intern("puts"), 1, str);
|
45
|
+
}
|
46
|
+
|
47
|
+
static void logger_log_write(void *ptr, TSLogType log_type,
|
48
|
+
const char *message) {
|
49
|
+
logger_t *logger = (logger_t *)ptr;
|
50
|
+
const char *format =
|
51
|
+
NIL_P(logger->format) ? "%s %s\n" : StringValueCStr(logger->format);
|
52
|
+
VALUE str = rb_sprintf(format, logger_log_type_str(log_type), message);
|
53
|
+
rb_funcall(logger->payload, rb_intern("write"), 1, str);
|
54
|
+
}
|
55
|
+
|
56
|
+
static void logger_payload_set(logger_t *logger, VALUE value) {
|
57
|
+
logger->payload = value;
|
58
|
+
logger->data.payload = (void *)logger;
|
59
|
+
|
60
|
+
if (!NIL_P(logger->format) && !NIL_P(logger->payload)) {
|
61
|
+
if (rb_respond_to(logger->payload, rb_intern("printf"))) {
|
62
|
+
logger->data.log = logger_log_printf;
|
63
|
+
} else if (rb_respond_to(logger->payload, rb_intern("puts"))) {
|
64
|
+
logger->data.log = &logger_log_puts;
|
65
|
+
} else {
|
66
|
+
logger->data.log = &logger_log_write;
|
67
|
+
}
|
68
|
+
} else if (!NIL_P(logger->payload)) {
|
69
|
+
logger->data.log = &logger_log_write;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
static void logger_free(void *ptr) { xfree(ptr); }
|
74
|
+
|
75
|
+
static size_t logger_memsize(const void *ptr) {
|
76
|
+
logger_t *type = (logger_t *)ptr;
|
77
|
+
return sizeof(type);
|
78
|
+
}
|
79
|
+
|
80
|
+
static void logger_mark(void *ptr) {
|
81
|
+
logger_t *logger = (logger_t *)ptr;
|
82
|
+
rb_gc_mark_movable(logger->payload);
|
83
|
+
// we don't want format to move because its reference will be
|
84
|
+
// consumed by the parser.
|
85
|
+
//
|
86
|
+
// No funny things please.
|
87
|
+
rb_gc_mark(logger->format);
|
88
|
+
}
|
89
|
+
|
90
|
+
static void logger_compact(void *ptr) {
|
91
|
+
logger_t *logger = (logger_t *)ptr;
|
92
|
+
logger->payload = rb_gc_location(logger->payload);
|
93
|
+
}
|
94
|
+
|
95
|
+
const rb_data_type_t logger_data_type = {
|
96
|
+
.wrap_struct_name = "logger",
|
97
|
+
.function =
|
98
|
+
{
|
99
|
+
.dmark = logger_mark,
|
100
|
+
.dfree = logger_free,
|
101
|
+
.dsize = logger_memsize,
|
102
|
+
.dcompact = logger_compact,
|
103
|
+
},
|
104
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
105
|
+
};
|
106
|
+
|
107
|
+
DATA_UNWRAP(logger)
|
108
|
+
|
109
|
+
static VALUE logger_allocate(VALUE klass) {
|
110
|
+
logger_t *logger;
|
111
|
+
return TypedData_Make_Struct(klass, logger_t, &logger_data_type, logger);
|
112
|
+
}
|
113
|
+
|
114
|
+
VALUE new_logger(const TSLogger *ptr) {
|
115
|
+
if (ptr != NULL) {
|
116
|
+
VALUE res = logger_allocate(cLogger);
|
117
|
+
logger_t *logger = unwrap(res);
|
118
|
+
|
119
|
+
logger->data.payload = logger;
|
120
|
+
|
121
|
+
VALUE payload = Qnil;
|
122
|
+
VALUE format = Qnil;
|
123
|
+
if (ptr->payload != NULL) {
|
124
|
+
logger_t *old_logger = (logger_t *)ptr->payload;
|
125
|
+
payload = old_logger->payload;
|
126
|
+
format = old_logger->format;
|
127
|
+
}
|
128
|
+
logger_payload_set(logger, payload);
|
129
|
+
logger->format = format;
|
130
|
+
|
131
|
+
return res;
|
132
|
+
} else {
|
133
|
+
return Qnil;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
VALUE new_logger_by_val(TSLogger val) { return new_logger(&val); }
|
138
|
+
|
139
|
+
TSLogger value_to_logger(VALUE self) { return SELF; }
|
140
|
+
|
141
|
+
static void logger_initialize_stderr(logger_t *logger) {
|
142
|
+
VALUE stderr = rb_gv_get("$stderr");
|
143
|
+
if (!NIL_P(stderr)) {
|
144
|
+
logger_payload_set(logger, stderr);
|
145
|
+
} else {
|
146
|
+
logger_payload_set(logger, Qnil);
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
// For now, we only take:
|
151
|
+
// argv[0] = stream
|
152
|
+
// argv[1] = format : String
|
153
|
+
//
|
154
|
+
// We need to add support for argv[1] : lambda/block
|
155
|
+
//
|
156
|
+
// case argv[1]
|
157
|
+
// in lambda => lambda
|
158
|
+
// in String => puts || printf || write
|
159
|
+
// else => write
|
160
|
+
// end
|
161
|
+
//
|
162
|
+
static VALUE logger_initialize(int argc, VALUE *argv, VALUE self) {
|
163
|
+
logger_t *logger = unwrap(self);
|
164
|
+
|
165
|
+
VALUE payload;
|
166
|
+
VALUE format;
|
167
|
+
rb_scan_args(argc, argv, "02", &payload, &format);
|
168
|
+
|
169
|
+
logger->format = format;
|
170
|
+
|
171
|
+
if (argc == 0) {
|
172
|
+
logger_initialize_stderr(logger);
|
173
|
+
} else {
|
174
|
+
logger_payload_set(logger, payload);
|
175
|
+
}
|
176
|
+
|
177
|
+
return self;
|
178
|
+
}
|
179
|
+
|
180
|
+
static VALUE logger_inspect(VALUE self) {
|
181
|
+
logger_t *logger = unwrap(self);
|
182
|
+
return rb_sprintf("{payload=%+" PRIsVALUE ", format=%+" PRIsVALUE "}",
|
183
|
+
logger->payload, logger->format);
|
184
|
+
}
|
185
|
+
|
186
|
+
DATA_FAST_FORWARD_FNV(logger, write, payload)
|
187
|
+
DATA_FAST_FORWARD_FNV(logger, puts, payload)
|
188
|
+
DATA_FAST_FORWARD_FNV(logger, printf, payload)
|
189
|
+
|
190
|
+
DEFINE_ACCESSOR(logger, format)
|
191
|
+
DEFINE_GETTER(logger, payload)
|
192
|
+
|
193
|
+
static VALUE logger_set_payload(VALUE self, VALUE payload) {
|
194
|
+
logger_payload_set(unwrap(self), payload);
|
195
|
+
return Qnil;
|
196
|
+
}
|
197
|
+
|
198
|
+
void init_logger(void) {
|
199
|
+
cLogger = rb_define_class_under(mTreeSitter, "Logger", rb_cObject);
|
200
|
+
|
201
|
+
rb_define_alloc_func(cLogger, logger_allocate);
|
202
|
+
|
203
|
+
/* Class methods */
|
204
|
+
rb_define_method(cLogger, "initialize", logger_initialize, -1);
|
205
|
+
DECLARE_ACCESSOR(cLogger, logger, format)
|
206
|
+
DECLARE_ACCESSOR(cLogger, logger, payload)
|
207
|
+
rb_define_method(cLogger, "write", logger_write, -1);
|
208
|
+
rb_define_method(cLogger, "puts", logger_puts, -1);
|
209
|
+
rb_define_method(cLogger, "printf", logger_printf, -1);
|
210
|
+
rb_define_method(cLogger, "inspect", logger_inspect, 0);
|
211
|
+
rb_define_method(cLogger, "to_s", logger_inspect, 0);
|
212
|
+
}
|
@@ -0,0 +1,163 @@
|
|
1
|
+
#ifndef _RB_TREE_SITTER_MACROS_H
|
2
|
+
#define _RB_TREE_SITTER_MACROS_H
|
3
|
+
|
4
|
+
#define DECLARE_GETTER(klass, type, field) \
|
5
|
+
rb_define_method(klass, #field, type##_get_##field, 0);
|
6
|
+
|
7
|
+
#define DECLARE_SETTER(klass, type, field) \
|
8
|
+
rb_define_method(klass, #field "=", type##_set_##field, 1);
|
9
|
+
|
10
|
+
#define DECLARE_ACCESSOR(klass, type, field) \
|
11
|
+
DECLARE_GETTER(klass, type, field) \
|
12
|
+
DECLARE_SETTER(klass, type, field)
|
13
|
+
|
14
|
+
// Plain DEFINE_GETTER/DEFINE_SETTER/etc are for TypedData structs, reaching
|
15
|
+
// their top-level fields, and are of type VALUE
|
16
|
+
//
|
17
|
+
// DATA_* are for TypeData structs, raching their data field
|
18
|
+
// which can be of an arbitraty tuype.
|
19
|
+
|
20
|
+
#define DEFINE_GETTER(type, field) \
|
21
|
+
static VALUE type##_get_##field(VALUE self) { return (unwrap(self))->field; }
|
22
|
+
|
23
|
+
#define DEFINE_SETTER(type, field) \
|
24
|
+
static VALUE type##_set_##field(VALUE self, VALUE val) { \
|
25
|
+
unwrap(self)->field = val; \
|
26
|
+
return Qnil; \
|
27
|
+
}
|
28
|
+
|
29
|
+
#define DEFINE_ACCESSOR(type, field) \
|
30
|
+
DEFINE_GETTER(type, field) \
|
31
|
+
DEFINE_SETTER(type, field)
|
32
|
+
|
33
|
+
#define DATA_WRAP(base, type) \
|
34
|
+
DATA_TYPE(TS##base, type) \
|
35
|
+
DATA_FREE(type) \
|
36
|
+
DATA_MEMSIZE(type) \
|
37
|
+
DATA_DECLARE_DATA_TYPE(type) \
|
38
|
+
DATA_ALLOCATE(type) \
|
39
|
+
DATA_UNWRAP(type) \
|
40
|
+
DATA_NEW(c##base, TS##base, type) \
|
41
|
+
DATA_FROM_VALUE(TS##base, type)
|
42
|
+
|
43
|
+
#define DATA_PTR_WRAP(base, type) \
|
44
|
+
DATA_TYPE(TS##base *, type) \
|
45
|
+
DATA_FREE_PTR(type) \
|
46
|
+
DATA_MEMSIZE(type) \
|
47
|
+
DATA_DECLARE_DATA_TYPE(type) \
|
48
|
+
DATA_ALLOCATE(type) \
|
49
|
+
DATA_UNWRAP(type) \
|
50
|
+
DATA_PTR_NEW(c##base, TS##base, type) \
|
51
|
+
DATA_FROM_VALUE(TS##base *, type)
|
52
|
+
|
53
|
+
#define DATA_TYPE(klass, type) \
|
54
|
+
typedef struct { \
|
55
|
+
klass data; \
|
56
|
+
} type##_t;
|
57
|
+
|
58
|
+
#define DATA_FREE(type) \
|
59
|
+
static void type##_free(void *ptr) { xfree(ptr); }
|
60
|
+
|
61
|
+
#define DATA_FREE_PTR(type) \
|
62
|
+
static void type##_free(void *ptr) { \
|
63
|
+
type##_t *type = (type##_t *)ptr; \
|
64
|
+
if (type->data != NULL) { \
|
65
|
+
ts_##type##_delete(type->data); \
|
66
|
+
} \
|
67
|
+
xfree(ptr); \
|
68
|
+
}
|
69
|
+
|
70
|
+
#define DATA_MEMSIZE(type) \
|
71
|
+
static size_t type##_memsize(const void *ptr) { \
|
72
|
+
type##_t *type = (type##_t *)ptr; \
|
73
|
+
return sizeof(type); \
|
74
|
+
}
|
75
|
+
|
76
|
+
#define DATA_DECLARE_DATA_TYPE(type) \
|
77
|
+
const rb_data_type_t type##_data_type = { \
|
78
|
+
.wrap_struct_name = #type "", \
|
79
|
+
.function = \
|
80
|
+
{ \
|
81
|
+
.dmark = NULL, \
|
82
|
+
.dfree = type##_free, \
|
83
|
+
.dsize = type##_memsize, \
|
84
|
+
.dcompact = NULL, \
|
85
|
+
}, \
|
86
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY, \
|
87
|
+
};
|
88
|
+
|
89
|
+
#define DATA_ALLOCATE(type) \
|
90
|
+
static VALUE type##_allocate(VALUE klass) { \
|
91
|
+
type##_t *type; \
|
92
|
+
return TypedData_Make_Struct(klass, type##_t, &type##_data_type, type); \
|
93
|
+
}
|
94
|
+
|
95
|
+
#define DATA_UNWRAP(type) \
|
96
|
+
static type##_t *unwrap(VALUE self) { \
|
97
|
+
type##_t *type; \
|
98
|
+
TypedData_Get_Struct(self, type##_t, &type##_data_type, type); \
|
99
|
+
return type; \
|
100
|
+
}
|
101
|
+
|
102
|
+
#define SELF unwrap(self)->data
|
103
|
+
|
104
|
+
#define DATA_NEW(klass, struct, type) \
|
105
|
+
VALUE new_##type(const struct *ptr) { \
|
106
|
+
if (ptr == NULL) { \
|
107
|
+
return Qnil; \
|
108
|
+
} \
|
109
|
+
VALUE res = type##_allocate(klass); \
|
110
|
+
type##_t *type = unwrap(res); \
|
111
|
+
type->data = *ptr; \
|
112
|
+
return res; \
|
113
|
+
} \
|
114
|
+
VALUE new_##type##_by_val(struct ptr) { \
|
115
|
+
VALUE res = type##_allocate(klass); \
|
116
|
+
type##_t *type = unwrap(res); \
|
117
|
+
type->data = ptr; \
|
118
|
+
return res; \
|
119
|
+
}
|
120
|
+
|
121
|
+
#define DATA_FROM_VALUE(struct, type) \
|
122
|
+
struct value_to_##type(VALUE self) { \
|
123
|
+
return (unwrap(self))->data; \
|
124
|
+
}
|
125
|
+
|
126
|
+
#define DATA_PTR_NEW(klass, struct, type) \
|
127
|
+
VALUE new_##type(struct *ptr) { \
|
128
|
+
if (ptr == NULL) { \
|
129
|
+
return Qnil; \
|
130
|
+
} \
|
131
|
+
VALUE res = type##_allocate(klass); \
|
132
|
+
type##_t *type = unwrap(res); \
|
133
|
+
type->data = ptr; \
|
134
|
+
return res; \
|
135
|
+
}
|
136
|
+
|
137
|
+
#define DATA_DEFINE_GETTER(type, field, cast) \
|
138
|
+
static VALUE type##_get_##field(VALUE self) { \
|
139
|
+
return cast((unwrap(self))->data.field); \
|
140
|
+
}
|
141
|
+
|
142
|
+
#define DATA_DEFINE_SETTER(type, field, cast) \
|
143
|
+
static VALUE type##_set_##field(VALUE self, VALUE val) { \
|
144
|
+
type##_t *type = unwrap(self); \
|
145
|
+
type->data.field = cast(val); \
|
146
|
+
return Qnil; \
|
147
|
+
}
|
148
|
+
|
149
|
+
#define DATA_DEFINE_ACCESSOR(type, field, cast_get, cast_set) \
|
150
|
+
DATA_DEFINE_GETTER(type, field, cast_get) \
|
151
|
+
DATA_DEFINE_SETTER(type, field, cast_set)
|
152
|
+
|
153
|
+
#define DATA_FAST_FORWARD_FNV(type, fn, field) \
|
154
|
+
static VALUE type##_##fn(int argc, VALUE *argv, VALUE self) { \
|
155
|
+
type##_t *type = unwrap(self); \
|
156
|
+
if (!NIL_P(type->field)) { \
|
157
|
+
return rb_funcallv(type->field, rb_intern(#fn ""), argc, argv); \
|
158
|
+
} else { \
|
159
|
+
return Qnil; \
|
160
|
+
} \
|
161
|
+
}
|
162
|
+
|
163
|
+
#endif
|
@@ -0,0 +1,310 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
#include "tree_sitter/api.h"
|
3
|
+
|
4
|
+
extern VALUE mTreeSitter;
|
5
|
+
|
6
|
+
VALUE cNode;
|
7
|
+
|
8
|
+
DATA_TYPE(TSNode, node)
|
9
|
+
|
10
|
+
static void node_free(void *ptr) {
|
11
|
+
node_t *type = (node_t *)ptr;
|
12
|
+
tree_rc_free(type->data.tree);
|
13
|
+
xfree(ptr);
|
14
|
+
}
|
15
|
+
|
16
|
+
DATA_MEMSIZE(node)
|
17
|
+
DATA_DECLARE_DATA_TYPE(node)
|
18
|
+
DATA_ALLOCATE(node)
|
19
|
+
DATA_UNWRAP(node)
|
20
|
+
|
21
|
+
VALUE new_node(const TSNode *ptr) {
|
22
|
+
if (ptr == NULL) {
|
23
|
+
return Qnil;
|
24
|
+
}
|
25
|
+
VALUE res = node_allocate(cNode);
|
26
|
+
node_t *type = unwrap(res);
|
27
|
+
type->data = *ptr;
|
28
|
+
tree_rc_new(type->data.tree);
|
29
|
+
return res;
|
30
|
+
}
|
31
|
+
VALUE new_node_by_val(TSNode ptr) {
|
32
|
+
VALUE res = node_allocate(cNode);
|
33
|
+
node_t *type = unwrap(res);
|
34
|
+
type->data = ptr;
|
35
|
+
tree_rc_new(type->data.tree);
|
36
|
+
return res;
|
37
|
+
}
|
38
|
+
|
39
|
+
DATA_FROM_VALUE(TSNode, node)
|
40
|
+
|
41
|
+
static VALUE node_type(VALUE self) { return safe_symbol(ts_node_type(SELF)); }
|
42
|
+
|
43
|
+
static VALUE node_symbol(VALUE self) { return UINT2NUM(ts_node_symbol(SELF)); }
|
44
|
+
|
45
|
+
static VALUE node_start_byte(VALUE self) {
|
46
|
+
return UINT2NUM(ts_node_start_byte(SELF));
|
47
|
+
}
|
48
|
+
|
49
|
+
static VALUE node_start_point(VALUE self) {
|
50
|
+
return new_point_by_val(ts_node_start_point(SELF));
|
51
|
+
}
|
52
|
+
|
53
|
+
static VALUE node_end_byte(VALUE self) {
|
54
|
+
return UINT2NUM(ts_node_end_byte(SELF));
|
55
|
+
}
|
56
|
+
|
57
|
+
static VALUE node_end_point(VALUE self) {
|
58
|
+
return new_point_by_val(ts_node_end_point(SELF));
|
59
|
+
}
|
60
|
+
|
61
|
+
static VALUE node_string(VALUE self) {
|
62
|
+
char *str = ts_node_string(SELF);
|
63
|
+
VALUE res = safe_str(str);
|
64
|
+
if (str) {
|
65
|
+
free(str);
|
66
|
+
}
|
67
|
+
return res;
|
68
|
+
}
|
69
|
+
|
70
|
+
static VALUE node_is_null(VALUE self) {
|
71
|
+
return ts_node_is_null(SELF) ? Qtrue : Qfalse;
|
72
|
+
}
|
73
|
+
|
74
|
+
static VALUE node_is_named(VALUE self) {
|
75
|
+
return ts_node_is_named(SELF) ? Qtrue : Qfalse;
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE node_is_missing(VALUE self) {
|
79
|
+
return ts_node_is_missing(SELF) ? Qtrue : Qfalse;
|
80
|
+
}
|
81
|
+
|
82
|
+
static VALUE node_is_extra(VALUE self) {
|
83
|
+
return ts_node_is_extra(SELF) ? Qtrue : Qfalse;
|
84
|
+
}
|
85
|
+
|
86
|
+
static VALUE node_has_changes(VALUE self) {
|
87
|
+
return ts_node_has_changes(SELF) ? Qtrue : Qfalse;
|
88
|
+
}
|
89
|
+
|
90
|
+
static VALUE node_has_error(VALUE self) {
|
91
|
+
return ts_node_has_error(SELF) ? Qtrue : Qfalse;
|
92
|
+
}
|
93
|
+
|
94
|
+
static VALUE node_parent(VALUE self) {
|
95
|
+
return new_node_by_val(ts_node_parent(SELF));
|
96
|
+
}
|
97
|
+
|
98
|
+
static VALUE node_child(VALUE self, VALUE idx) {
|
99
|
+
TSNode node = SELF;
|
100
|
+
uint32_t index = NUM2UINT(idx);
|
101
|
+
uint32_t range = ts_node_child_count(node);
|
102
|
+
|
103
|
+
if (index < range) {
|
104
|
+
return new_node_by_val(ts_node_child(node, index));
|
105
|
+
} else {
|
106
|
+
rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
|
107
|
+
range);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
static VALUE node_field_name_for_child(VALUE self, VALUE idx) {
|
112
|
+
TSNode node = SELF;
|
113
|
+
uint32_t index = NUM2UINT(idx);
|
114
|
+
uint32_t range = ts_node_child_count(node);
|
115
|
+
|
116
|
+
if (index < range) {
|
117
|
+
return safe_str(ts_node_field_name_for_child(node, index));
|
118
|
+
} else {
|
119
|
+
rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
|
120
|
+
range);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
static VALUE node_child_count(VALUE self) {
|
125
|
+
TSNode node = SELF;
|
126
|
+
const char *type = ts_node_type(node);
|
127
|
+
if (strcmp(type, "end") == 0) {
|
128
|
+
return UINT2NUM(0);
|
129
|
+
} else {
|
130
|
+
return UINT2NUM(ts_node_child_count(SELF));
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
static VALUE node_named_child(VALUE self, VALUE idx) {
|
135
|
+
TSNode node = SELF;
|
136
|
+
uint32_t index = NUM2UINT(idx);
|
137
|
+
uint32_t range = ts_node_named_child_count(node);
|
138
|
+
|
139
|
+
if (index < range) {
|
140
|
+
return new_node_by_val(ts_node_named_child(node, index));
|
141
|
+
} else {
|
142
|
+
rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
|
143
|
+
range);
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
static VALUE node_named_child_count(VALUE self) {
|
148
|
+
return UINT2NUM(ts_node_named_child_count(SELF));
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE node_child_by_field_name(VALUE self, VALUE field_name) {
|
152
|
+
const char *name = StringValuePtr(field_name);
|
153
|
+
uint32_t length = (uint32_t)RSTRING_LEN(field_name);
|
154
|
+
return new_node_by_val(ts_node_child_by_field_name(SELF, name, length));
|
155
|
+
}
|
156
|
+
|
157
|
+
static VALUE node_child_by_field_id(VALUE self, VALUE field_id) {
|
158
|
+
return new_node_by_val(ts_node_child_by_field_id(SELF, NUM2UINT(field_id)));
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE node_next_sibling(VALUE self) {
|
162
|
+
return new_node_by_val(ts_node_next_sibling(SELF));
|
163
|
+
}
|
164
|
+
|
165
|
+
static VALUE node_prev_sibling(VALUE self) {
|
166
|
+
return new_node_by_val(ts_node_prev_sibling(SELF));
|
167
|
+
}
|
168
|
+
|
169
|
+
static VALUE node_next_named_sibling(VALUE self) {
|
170
|
+
return new_node_by_val(ts_node_next_named_sibling(SELF));
|
171
|
+
}
|
172
|
+
|
173
|
+
static VALUE node_prev_named_sibling(VALUE self) {
|
174
|
+
return new_node_by_val(ts_node_prev_named_sibling(SELF));
|
175
|
+
}
|
176
|
+
|
177
|
+
static VALUE node_first_child_for_byte(VALUE self, VALUE byte) {
|
178
|
+
return new_node_by_val(ts_node_first_child_for_byte(SELF, NUM2UINT(byte)));
|
179
|
+
}
|
180
|
+
|
181
|
+
static VALUE node_first_named_child_for_byte(VALUE self, VALUE byte) {
|
182
|
+
return new_node_by_val(
|
183
|
+
ts_node_first_named_child_for_byte(SELF, NUM2UINT(byte)));
|
184
|
+
}
|
185
|
+
|
186
|
+
static VALUE node_descendant_for_byte_range(VALUE self, VALUE from, VALUE to) {
|
187
|
+
uint32_t from_b = NUM2UINT(from);
|
188
|
+
uint32_t to_b = NUM2UINT(to);
|
189
|
+
|
190
|
+
if (from_b > to_b) {
|
191
|
+
rb_raise(rb_eIndexError, "From > To: %d > %d", from_b, to_b);
|
192
|
+
} else {
|
193
|
+
return new_node_by_val(
|
194
|
+
ts_node_descendant_for_byte_range(SELF, from_b, to_b));
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
static VALUE node_descendant_for_point_range(VALUE self, VALUE from, VALUE to) {
|
199
|
+
TSNode node = SELF;
|
200
|
+
TSPoint start = ts_node_start_point(node);
|
201
|
+
TSPoint end = ts_node_end_point(node);
|
202
|
+
TSPoint f = value_to_point(from);
|
203
|
+
TSPoint t = value_to_point(to);
|
204
|
+
|
205
|
+
if ((f.row < start.row) || (t.row > end.row) ||
|
206
|
+
(f.row == start.row && (f.column < start.column)) ||
|
207
|
+
(t.row == end.row && (t.column > end.column))) {
|
208
|
+
rb_raise(rb_eIndexError,
|
209
|
+
"Invalid point range: [%+" PRIsVALUE ", %+" PRIsVALUE
|
210
|
+
"] is not in [%+" PRIsVALUE ", %+" PRIsVALUE "].",
|
211
|
+
from, to, new_point(&start), new_point(&end));
|
212
|
+
} else {
|
213
|
+
return new_node_by_val(ts_node_descendant_for_point_range(node, f, t));
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
static VALUE node_named_descendant_for_byte_range(VALUE self, VALUE from,
|
218
|
+
VALUE to) {
|
219
|
+
uint32_t from_b = NUM2UINT(from);
|
220
|
+
uint32_t to_b = NUM2UINT(to);
|
221
|
+
|
222
|
+
if (from_b > to_b) {
|
223
|
+
rb_raise(rb_eIndexError, "From > To: %d > %d", from_b, to_b);
|
224
|
+
} else {
|
225
|
+
return new_node_by_val(
|
226
|
+
ts_node_named_descendant_for_byte_range(SELF, from_b, to_b));
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
static VALUE node_named_descendant_for_point_range(VALUE self, VALUE from,
|
231
|
+
VALUE to) {
|
232
|
+
TSNode node = SELF;
|
233
|
+
TSPoint start = ts_node_start_point(node);
|
234
|
+
TSPoint end = ts_node_end_point(node);
|
235
|
+
TSPoint f = value_to_point(from);
|
236
|
+
TSPoint t = value_to_point(to);
|
237
|
+
|
238
|
+
if ((f.row < start.row) || (t.row > end.row) ||
|
239
|
+
(f.row == start.row && (f.column < start.column)) ||
|
240
|
+
(t.row == end.row && (t.column > end.column))) {
|
241
|
+
rb_raise(rb_eIndexError,
|
242
|
+
"Invalid point range: [%+" PRIsVALUE ", %+" PRIsVALUE
|
243
|
+
"] is not in [%+" PRIsVALUE ", %+" PRIsVALUE "].",
|
244
|
+
from, to, new_point(&start), new_point(&end));
|
245
|
+
} else {
|
246
|
+
return new_node_by_val(
|
247
|
+
ts_node_named_descendant_for_point_range(node, f, t));
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
251
|
+
static VALUE node_edit(VALUE self, VALUE input_edit) {
|
252
|
+
TSNode node = SELF;
|
253
|
+
TSInputEdit edit = value_to_input_edit(input_edit);
|
254
|
+
ts_node_edit(&node, &edit);
|
255
|
+
|
256
|
+
return Qnil;
|
257
|
+
}
|
258
|
+
|
259
|
+
static VALUE node_eq(VALUE self, VALUE other) {
|
260
|
+
return ts_node_eq(SELF, unwrap(other)->data) ? Qtrue : Qfalse;
|
261
|
+
}
|
262
|
+
|
263
|
+
void init_node(void) {
|
264
|
+
cNode = rb_define_class_under(mTreeSitter, "Node", rb_cObject);
|
265
|
+
|
266
|
+
rb_undef_alloc_func(cNode);
|
267
|
+
|
268
|
+
/* Class methods */
|
269
|
+
rb_define_method(cNode, "type", node_type, 0);
|
270
|
+
rb_define_method(cNode, "symbol", node_symbol, 0);
|
271
|
+
rb_define_method(cNode, "start_byte", node_start_byte, 0);
|
272
|
+
rb_define_method(cNode, "start_point", node_start_point, 0);
|
273
|
+
rb_define_method(cNode, "end_byte", node_end_byte, 0);
|
274
|
+
rb_define_method(cNode, "end_point", node_end_point, 0);
|
275
|
+
rb_define_method(cNode, "null?", node_is_null, 0);
|
276
|
+
rb_define_method(cNode, "named?", node_is_named, 0);
|
277
|
+
rb_define_method(cNode, "missing?", node_is_missing, 0);
|
278
|
+
rb_define_method(cNode, "extra?", node_is_extra, 0);
|
279
|
+
rb_define_method(cNode, "changed?", node_has_changes, 0);
|
280
|
+
rb_define_method(cNode, "error?", node_has_error, 0);
|
281
|
+
rb_define_method(cNode, "parent", node_parent, 0);
|
282
|
+
rb_define_method(cNode, "child", node_child, 1);
|
283
|
+
rb_define_method(cNode, "field_name_for_child", node_field_name_for_child, 1);
|
284
|
+
rb_define_method(cNode, "child_count", node_child_count, 0);
|
285
|
+
rb_define_method(cNode, "named_child", node_named_child, 1);
|
286
|
+
rb_define_method(cNode, "named_child_count", node_named_child_count, 0);
|
287
|
+
rb_define_method(cNode, "child_by_field_name", node_child_by_field_name, 1);
|
288
|
+
rb_define_method(cNode, "child_by_field_id", node_child_by_field_id, 1);
|
289
|
+
rb_define_method(cNode, "next_sibling", node_next_sibling, 0);
|
290
|
+
rb_define_method(cNode, "prev_sibling", node_prev_sibling, 0);
|
291
|
+
rb_define_method(cNode, "next_named_sibling", node_next_named_sibling, 0);
|
292
|
+
rb_define_method(cNode, "prev_named_sibling", node_prev_named_sibling, 0);
|
293
|
+
rb_define_method(cNode, "first_child_for_byte", node_first_child_for_byte, 1);
|
294
|
+
rb_define_method(cNode, "first_named_child_for_byte",
|
295
|
+
node_first_named_child_for_byte, 1);
|
296
|
+
rb_define_method(cNode, "descendant_for_byte_range",
|
297
|
+
node_descendant_for_byte_range, 2);
|
298
|
+
rb_define_method(cNode, "descendant_for_point_range",
|
299
|
+
node_descendant_for_point_range, 2);
|
300
|
+
rb_define_method(cNode, "named_descendant_for_byte_range",
|
301
|
+
node_named_descendant_for_byte_range, 2);
|
302
|
+
rb_define_method(cNode, "named_descendant_for_point_range",
|
303
|
+
node_named_descendant_for_point_range, 2);
|
304
|
+
rb_define_method(cNode, "eq?", node_eq, 1);
|
305
|
+
rb_define_method(cNode, "edit", node_edit, 1);
|
306
|
+
rb_define_method(cNode, "to_s", node_string, 0);
|
307
|
+
rb_define_method(cNode, "to_str", node_string, 0);
|
308
|
+
rb_define_method(cNode, "inspect", node_string, 0);
|
309
|
+
rb_define_method(cNode, "==", node_eq, 1);
|
310
|
+
}
|