ruby_tree_sitter 1.6.0-arm-linux-musl
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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1925f8308ea5699baa8b6b6d3d08f0050f258ee06a30117d330fa6409a2fd118
|
4
|
+
data.tar.gz: a07bd4d589807750947d5d55ac82f050da5d1989ea9c3e06d954676b26948283
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b8e70368acb17bee7195590f84cb8d9f9e72a25d6ad0bf12ece45ee2b004a658ddaa5f81a1e9a3831dd2c4b5d8bf99876e79b1a9bef700a42a7f56c9d356f4be
|
7
|
+
data.tar.gz: 6a29bad05ad4ebc04ba40266f9a3d2a175c66e460531ab36cce6830d89085d0c0e4c017cd3508335bd23e50ee1de1ebf94078e5133b7f7c8a7056a1243e8d7d5
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2022-present, Faveod SAS.
|
4
|
+
Copyright (c) 2022-present, Shopify Inc.
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
8
|
+
in the Software without restriction, including without limitation the rights
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
14
|
+
copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
# Ruby tree-sitter bindings
|
2
|
+
|
3
|
+
[](https://faveod.github.io/ruby-tree-sitter)
|
4
|
+
[](https://rubygems.org/gems/ruby_tree_sitter)
|
5
|
+
[](https://github.com/Faveod/ruby-tree-sitter/actions/workflows/ci.yml)
|
6
|
+
<!--
|
7
|
+
[](https://github.com/Faveod/ruby-tree-sitter/actions/workflows/valgrind.yml)
|
8
|
+
[](https://github.com/Faveod/ruby-tree-sitter/actions/workflows/asan.yml)
|
9
|
+
-->
|
10
|
+
|
11
|
+
Ruby bindings for [tree-sitter](https://github.com/tree-sitter/tree-sitter).
|
12
|
+
|
13
|
+
The [official bindings](https://github.com/tree-sitter/ruby-tree-sitter) are
|
14
|
+
very old, unmaintained, and don't work with modern `tree-sitter` APIs.
|
15
|
+
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
### TreeSitter API
|
20
|
+
|
21
|
+
The TreeSitter API is a low-level Ruby binding for tree-sitter.
|
22
|
+
|
23
|
+
``` ruby
|
24
|
+
require 'tree_sitter'
|
25
|
+
|
26
|
+
parser = TreeSitter::Parser.new
|
27
|
+
language = TreeSitter::Language.load('javascript', 'path/to/libtree-sitter-javascript.{so,dylib}')
|
28
|
+
# Or simply
|
29
|
+
language = TreeSitter.lang('javascript')
|
30
|
+
# Which will try to look in your local directory and the system for installed parsers.
|
31
|
+
# See TreeSitter::Mixin::Language#lib_dirs
|
32
|
+
|
33
|
+
src = "[1, null]"
|
34
|
+
|
35
|
+
parser.language = language
|
36
|
+
|
37
|
+
tree = parser.parse_string(nil, src)
|
38
|
+
root = tree.root_node
|
39
|
+
|
40
|
+
root.each do |child|
|
41
|
+
# ...
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
The main philosophy behind the TreeSitter bindings is to do a 1:1 mapping between
|
46
|
+
tree-sitter's `C` API and `Ruby`, which makes it easier to experiment and port
|
47
|
+
ideas from different languages/bindings.
|
48
|
+
|
49
|
+
But it feels like writing some managed `C` with `Ruby`, and that's why we provide
|
50
|
+
a high-level API ([TreeStand](#treestand-api)) as well.
|
51
|
+
|
52
|
+
### TreeStand API
|
53
|
+
|
54
|
+
The TreeStand API is a high-level Ruby wrapper for the [TreeSitter](#treesitter-api) bindings. It
|
55
|
+
makes it easier to configure the parsers, and work with the underlying syntax tree.
|
56
|
+
```ruby
|
57
|
+
require 'tree_stand'
|
58
|
+
|
59
|
+
TreeStand.configure do
|
60
|
+
config.parser_path = "path/to/parser/folder/"
|
61
|
+
end
|
62
|
+
|
63
|
+
sql_parser = TreeStand::Parser.new("sql")
|
64
|
+
ruby_parser = TreeStand::Parser.new("ruby")
|
65
|
+
```
|
66
|
+
|
67
|
+
TreeStand provides an idiomatic Ruby interface to work with tree-sitter parsers.
|
68
|
+
|
69
|
+
## Dependencies
|
70
|
+
|
71
|
+
This gem is a binding for `tree-sitter`, and comes with a pre-built version
|
72
|
+
of `tree-sitter` bundled with it, so you can start using it without any
|
73
|
+
special configuration.
|
74
|
+
|
75
|
+
We support the following platforms:
|
76
|
+
|
77
|
+
- `aarch64-linux-gnu`
|
78
|
+
- `aarch64-linux-musl`
|
79
|
+
- `arm-linux-gnu`
|
80
|
+
- `arm-linux-musl`
|
81
|
+
- `x86_64-linux-gnu`
|
82
|
+
- `x86_64-linux-musl`
|
83
|
+
- `x86-linux-musl`
|
84
|
+
- `arm64-darwin`
|
85
|
+
- `x86_64-darwin`
|
86
|
+
|
87
|
+
(see [Build from source](docs/Contributing.md#build-from-source)).
|
88
|
+
|
89
|
+
You can either install `tree-sitter` from source or through your go-to package manager.
|
90
|
+
|
91
|
+
### Linux
|
92
|
+
|
93
|
+
`ubuntu >= 22.04`
|
94
|
+
|
95
|
+
```console
|
96
|
+
sudo apt install libtree-sitter-dev
|
97
|
+
```
|
98
|
+
|
99
|
+
`arch`
|
100
|
+
|
101
|
+
```console
|
102
|
+
sudo pacman -S tree-sitter
|
103
|
+
```
|
104
|
+
|
105
|
+
### MacOS
|
106
|
+
|
107
|
+
```console
|
108
|
+
sudo port install tree-sitter
|
109
|
+
```
|
110
|
+
|
111
|
+
or
|
112
|
+
|
113
|
+
```console
|
114
|
+
brew install tree-sitter
|
115
|
+
```
|
116
|
+
|
117
|
+
## Install
|
118
|
+
|
119
|
+
From [rubygems](https://rubygems.org/gems/ruby_tree_sitter), in your `Gemfile`:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
gem 'ruby_tree_sitter', '~> 1.6'
|
123
|
+
```
|
124
|
+
|
125
|
+
Or manually:
|
126
|
+
|
127
|
+
```sh
|
128
|
+
gem install ruby_tree_sitter
|
129
|
+
```
|
130
|
+
|
131
|
+
Or from `git` sources, which will compile on installation:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
gem 'ruby_tree_sitter', git: 'https://github.com/Faveod/ruby-tree-sitter'
|
135
|
+
```
|
136
|
+
|
137
|
+
### Enable system libraries
|
138
|
+
|
139
|
+
To install with `--enable-sys-libs`, you can either:
|
140
|
+
|
141
|
+
```sh
|
142
|
+
gem install ruby_tree_sitter --platform=ruby -- --enable-sys-libs
|
143
|
+
```
|
144
|
+
|
145
|
+
Or via bundle:
|
146
|
+
|
147
|
+
```sh
|
148
|
+
bundle config force_ruby_platform true
|
149
|
+
bundle config set build.ruby_tree_sitter --enable-sys-libs
|
150
|
+
```
|
151
|
+
|
152
|
+
### No compilation
|
153
|
+
|
154
|
+
If you don't want to install from `rubygems`, `git`, or if you don't want to
|
155
|
+
compile on install, then download a native gem from this repository's
|
156
|
+
[releases](https://github.com/Faveod/ruby-tree-sitter/releases), or you can
|
157
|
+
compile it yourself (see [Build from source](docs/Contributing.md#build-from-source) .)
|
158
|
+
|
159
|
+
In that case, you'd have to point your `Gemfile` to the `gem` as such:
|
160
|
+
|
161
|
+
``` ruby
|
162
|
+
gem 'tree_sitter', path: 'path/to/native/tree_sitter.gem'
|
163
|
+
```
|
164
|
+
|
165
|
+
⚠️ We're currently missing a lot of platforms and architectures. Cross-build
|
166
|
+
will come back in the near future.
|
167
|
+
|
168
|
+
### Parsers
|
169
|
+
|
170
|
+
You will have to install parsers yourself, either by:
|
171
|
+
|
172
|
+
1. Downloading and building from source.
|
173
|
+
1. Downloading from your package manager, if available.
|
174
|
+
1. Downloading a pre-built binary from
|
175
|
+
[Faveod/tree-sitter-parsers](https://github.com/Faveod/tree-sitter-parsers)
|
176
|
+
which supports numerous architectures.
|
177
|
+
|
178
|
+
## Examples
|
179
|
+
|
180
|
+
See `examples` directory.
|
181
|
+
|
182
|
+
## Development
|
183
|
+
|
184
|
+
See [`docs/Contributing.md`](docs/Contributing.md).
|
185
|
+
|
186
|
+
## 🚧 👷♀️ Notes 👷 🚧
|
187
|
+
|
188
|
+
Since we're doing a 1:1 mapping between the `tree-sitter` API and the bindings,
|
189
|
+
you need to be extra-careful when playing with the provided objects. Some of
|
190
|
+
them have their underlying `C` data-structure automatically freed, so you might
|
191
|
+
get yourself in undesirable situations if you don't pay attention to what you're
|
192
|
+
doing.
|
193
|
+
|
194
|
+
We're only talking about `Tree`, `TreeCursor`, `Query`, and `QueryCursor`. Just
|
195
|
+
don't copy them left and right, and then expect them to work without
|
196
|
+
`SEGFAULT`ing and creating a black-hole in your living-room. Assume that you
|
197
|
+
have to work locally with them. If you get a `SEGFAULT`, you can debug the
|
198
|
+
native `C` code using `gdb`. You can read more on `SEGFAULT`s
|
199
|
+
[here](docs/SIGSEGV.md), and debugging [here](docs/Contributing#Debugging.md).
|
200
|
+
|
201
|
+
That said, we do aim at providing an idiomatic `Ruby` interface. It should also
|
202
|
+
provide a _safer_ interface, where you don't have to worry about when and how
|
203
|
+
resources are freed.
|
204
|
+
|
205
|
+
To See a full list of the ruby-specific APIs, see [here](lib/README.md).
|
206
|
+
|
207
|
+
## Sponsors
|
208
|
+
|
209
|
+
- <a href="https://faveod.com">https://faveod.com</a>
|
210
|
+
|
211
|
+
<a href="https://faveod.com">
|
212
|
+
<img src="img/faveod.jpg" width="66%" />
|
213
|
+
</a>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE mEncoding;
|
6
|
+
|
7
|
+
const char *utf8 = "utf8";
|
8
|
+
const char *utf16 = "utf16";
|
9
|
+
|
10
|
+
TSInputEncoding value_to_encoding(VALUE encoding) {
|
11
|
+
VALUE enc = SYM2ID(encoding);
|
12
|
+
/* VALUE u8 = rb_const_get_at(mEncoding, rb_intern(utf8)); */
|
13
|
+
VALUE u16 = SYM2ID(rb_const_get_at(mEncoding, rb_intern("UTF16")));
|
14
|
+
|
15
|
+
// NOTE: should we emit a warning instead of defaulting to UTF8?
|
16
|
+
if (enc == u16) {
|
17
|
+
return TSInputEncodingUTF16;
|
18
|
+
} else {
|
19
|
+
return TSInputEncodingUTF8;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
void init_encoding(void) {
|
24
|
+
mEncoding = rb_define_module_under(mTreeSitter, "Encoding");
|
25
|
+
|
26
|
+
/* Constants */
|
27
|
+
rb_define_const(mEncoding, "UTF8", ID2SYM(rb_intern(utf8)));
|
28
|
+
rb_define_const(mEncoding, "UTF16", ID2SYM(rb_intern(utf16)));
|
29
|
+
}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
require_relative 'repo'
|
7
|
+
|
8
|
+
# ################################## #
|
9
|
+
# Some helpers #
|
10
|
+
# ################################## #
|
11
|
+
|
12
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
13
|
+
|
14
|
+
cflags = []
|
15
|
+
ldflags = []
|
16
|
+
|
17
|
+
def system_tree_sitter?
|
18
|
+
enable_config('sys-libs', false)
|
19
|
+
end
|
20
|
+
|
21
|
+
def env_var_on?(var)
|
22
|
+
%w[1 on true t yes y].include?(ENV.fetch(var, '').downcase)
|
23
|
+
end
|
24
|
+
|
25
|
+
# ################################## #
|
26
|
+
# System lib vs Downloaded lib #
|
27
|
+
# ################################## #
|
28
|
+
|
29
|
+
repo = TreeSitter::Repo.new
|
30
|
+
|
31
|
+
dir_include, dir_lib =
|
32
|
+
if system_tree_sitter?
|
33
|
+
[
|
34
|
+
%w[/opt/include /opt/local/include /usr/include /usr/local/include],
|
35
|
+
%w[/opt/lib /opt/local/lib /usr/lib /usr/local/lib],
|
36
|
+
]
|
37
|
+
else
|
38
|
+
if !repo.download
|
39
|
+
msg = <<~MSG
|
40
|
+
|
41
|
+
Could not fetch tree-sitter sources:
|
42
|
+
|
43
|
+
#{repo.exe.map { |k, v| "#{k}: #{v}" }.join("\n")}
|
44
|
+
|
45
|
+
MSG
|
46
|
+
abort(msg)
|
47
|
+
end
|
48
|
+
|
49
|
+
# We need to make sure we're selecting the proper toolchain.
|
50
|
+
# Especially needed for corss-compilation.
|
51
|
+
ENV.store('CC', RbConfig::CONFIG['CC'])
|
52
|
+
repo.patch
|
53
|
+
repo.compile
|
54
|
+
repo.include_and_lib_dirs
|
55
|
+
end
|
56
|
+
|
57
|
+
dir_config('tree-sitter', dir_include&.first, dir_lib&.first)
|
58
|
+
|
59
|
+
# ################################## #
|
60
|
+
# Generate Makefile #
|
61
|
+
# ################################## #
|
62
|
+
|
63
|
+
header = find_header('tree_sitter/api.h')
|
64
|
+
library = find_library('tree-sitter', 'ts_parser_new')
|
65
|
+
|
66
|
+
if !header || !library
|
67
|
+
abort <<~MSG
|
68
|
+
|
69
|
+
* Missing header : #{header ? 'no' : 'yes'}
|
70
|
+
* Missing lib : #{library ? 'no' : 'yes'}
|
71
|
+
* Use system tree-sitter : #{system_tree_sitter?}
|
72
|
+
|
73
|
+
Try to install tree-sitter from source, or through your package manager,
|
74
|
+
or even try one of the following options to extconf.rb/rake compile:
|
75
|
+
|
76
|
+
--with-tree-sitter-dir=/path/to/tree-sitter
|
77
|
+
--with-tree-sitter-lib=/path/to/tree-sitter/lib
|
78
|
+
--with-tree-sitter-include=/path/to/tree-sitter/include
|
79
|
+
|
80
|
+
MSG
|
81
|
+
end
|
82
|
+
|
83
|
+
cflags << '-Werror' if env_var_on?('TREE_SITTER_PEDANTIC')
|
84
|
+
|
85
|
+
if env_var_on?('DEBUG')
|
86
|
+
cflags << '-fbounds-check'
|
87
|
+
CONFIG['optflags'].gsub!(/-O\d/, '-O0')
|
88
|
+
else
|
89
|
+
cflags << '-DNDEBUG'
|
90
|
+
CONFIG['optflags'].gsub!(/-O\d/, '-O3')
|
91
|
+
end
|
92
|
+
|
93
|
+
sanitizers = ENV.fetch('SANITIZE', nil)
|
94
|
+
|
95
|
+
if sanitizers =~ /memory/
|
96
|
+
puts <<~MSG
|
97
|
+
|
98
|
+
We do not support memory sanitizers as of yet.
|
99
|
+
It requires building ruby with the same sanitizer, and maybe its dependencies.
|
100
|
+
|
101
|
+
exiting…
|
102
|
+
|
103
|
+
MSG
|
104
|
+
exit 1
|
105
|
+
end
|
106
|
+
|
107
|
+
if sanitizers
|
108
|
+
# NOTE: when sanitizing, the default generated warning flags emit a lot of …
|
109
|
+
# warnings.
|
110
|
+
#
|
111
|
+
# I couldn't make mkmf understand it's running with clang and not gcc, so
|
112
|
+
# I'm omitting the warning generating warnings.
|
113
|
+
#
|
114
|
+
# It should be harmless, since sanitization is meant for CI and dev builds.
|
115
|
+
%w[
|
116
|
+
-Wduplicated-cond
|
117
|
+
-Wimplicit-fallthrough=\d+
|
118
|
+
-Wno-cast-function-type
|
119
|
+
-Wno-packed-bitfield-compat
|
120
|
+
-Wsuggest-attribute=\w+
|
121
|
+
].each do |r|
|
122
|
+
$warnflags.gsub!(/#{r}/, '')
|
123
|
+
end
|
124
|
+
|
125
|
+
cflags.concat %W[
|
126
|
+
-fms-extensions
|
127
|
+
-fdeclspec
|
128
|
+
-fsanitize=#{sanitizers}
|
129
|
+
-fsanitize-blacklist=../../../../.asanignore
|
130
|
+
-fsanitize-recover=#{sanitizers}
|
131
|
+
-fno-sanitize-recover=all
|
132
|
+
-fno-sanitize=null
|
133
|
+
-fno-sanitize=alignment
|
134
|
+
-fno-omit-frame-pointer
|
135
|
+
]
|
136
|
+
|
137
|
+
ldflags.concat %W[
|
138
|
+
-fsanitize=#{sanitizers}
|
139
|
+
-dynamic-libasan
|
140
|
+
]
|
141
|
+
end
|
142
|
+
|
143
|
+
cflags.concat %w[-std=c99 -fPIC -Wall]
|
144
|
+
|
145
|
+
append_cflags(cflags)
|
146
|
+
append_ldflags(ldflags)
|
147
|
+
|
148
|
+
create_header
|
149
|
+
create_makefile('tree_sitter/tree_sitter')
|
@@ -0,0 +1,127 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cInput;
|
6
|
+
|
7
|
+
typedef struct {
|
8
|
+
TSInput data;
|
9
|
+
VALUE payload;
|
10
|
+
VALUE last_result;
|
11
|
+
} input_t;
|
12
|
+
|
13
|
+
const char *input_read(void *payload, uint32_t byte_index, TSPoint position,
|
14
|
+
uint32_t *bytes_read) {
|
15
|
+
input_t *input = (input_t *)payload;
|
16
|
+
VALUE read = rb_funcall(input->payload, rb_intern("read"), 2,
|
17
|
+
UINT2NUM(byte_index), new_point(&position));
|
18
|
+
if (NIL_P(read)) {
|
19
|
+
*bytes_read = 0;
|
20
|
+
input->last_result = Qnil;
|
21
|
+
return NULL;
|
22
|
+
}
|
23
|
+
|
24
|
+
VALUE size = rb_funcall(read, rb_intern("bytesize"), 0);
|
25
|
+
*bytes_read = NUM2UINT(size);
|
26
|
+
input->last_result = rb_funcall(read, rb_intern("to_str"), 0);
|
27
|
+
|
28
|
+
return StringValueCStr(input->last_result);
|
29
|
+
}
|
30
|
+
|
31
|
+
static void input_payload_set(input_t *input, VALUE value) {
|
32
|
+
input->payload = value;
|
33
|
+
input->last_result = Qnil;
|
34
|
+
input->data.payload = (void *)input;
|
35
|
+
input->data.read = input_read;
|
36
|
+
}
|
37
|
+
|
38
|
+
static void input_free(void *ptr) { xfree(ptr); }
|
39
|
+
|
40
|
+
static size_t input_memsize(const void *ptr) {
|
41
|
+
input_t *type = (input_t *)ptr;
|
42
|
+
return sizeof(type);
|
43
|
+
}
|
44
|
+
|
45
|
+
static void input_mark(void *ptr) {
|
46
|
+
input_t *input = (input_t *)ptr;
|
47
|
+
rb_gc_mark_movable(input->payload);
|
48
|
+
// we don't want last_result to move because its const char* content will be
|
49
|
+
// consumed by the parser.
|
50
|
+
//
|
51
|
+
// No funny things please.
|
52
|
+
rb_gc_mark(input->last_result);
|
53
|
+
}
|
54
|
+
|
55
|
+
static void input_compact(void *ptr) {
|
56
|
+
input_t *input = (input_t *)ptr;
|
57
|
+
input->payload = rb_gc_location(input->payload);
|
58
|
+
}
|
59
|
+
|
60
|
+
const rb_data_type_t input_data_type = {
|
61
|
+
.wrap_struct_name = "input",
|
62
|
+
.function =
|
63
|
+
{
|
64
|
+
.dmark = input_mark,
|
65
|
+
.dfree = input_free,
|
66
|
+
.dsize = input_memsize,
|
67
|
+
.dcompact = input_compact,
|
68
|
+
},
|
69
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
70
|
+
};
|
71
|
+
|
72
|
+
DATA_UNWRAP(input)
|
73
|
+
|
74
|
+
static VALUE input_allocate(VALUE klass) {
|
75
|
+
input_t *input;
|
76
|
+
return TypedData_Make_Struct(klass, input_t, &input_data_type, input);
|
77
|
+
}
|
78
|
+
|
79
|
+
TSInput value_to_input(VALUE self) { return SELF; }
|
80
|
+
|
81
|
+
VALUE new_input(const TSInput *ptr) {
|
82
|
+
if (ptr != NULL) {
|
83
|
+
VALUE res = input_allocate(cInput);
|
84
|
+
input_t *input = unwrap(res);
|
85
|
+
VALUE payload = Qnil;
|
86
|
+
if (ptr->payload != NULL) {
|
87
|
+
input_t *old_input = (input_t *)ptr->payload;
|
88
|
+
payload = old_input->payload;
|
89
|
+
}
|
90
|
+
input_payload_set(input, payload);
|
91
|
+
return res;
|
92
|
+
} else {
|
93
|
+
return Qnil;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
static VALUE input_initialize(int argc, VALUE *argv, VALUE self) {
|
98
|
+
input_t *input = unwrap(self);
|
99
|
+
VALUE payload;
|
100
|
+
rb_scan_args(argc, argv, "01", &payload);
|
101
|
+
input_payload_set(input, payload);
|
102
|
+
return self;
|
103
|
+
}
|
104
|
+
|
105
|
+
static VALUE input_inspect(VALUE self) {
|
106
|
+
return rb_sprintf("{payload=%+" PRIsVALUE "}", unwrap(self)->payload);
|
107
|
+
}
|
108
|
+
|
109
|
+
DEFINE_GETTER(input, payload)
|
110
|
+
|
111
|
+
static VALUE input_set_payload(VALUE self, VALUE payload) {
|
112
|
+
input_payload_set(unwrap(self), payload);
|
113
|
+
return Qnil;
|
114
|
+
}
|
115
|
+
|
116
|
+
// FIXME: Missing encoding and read!
|
117
|
+
void init_input(void) {
|
118
|
+
cInput = rb_define_class_under(mTreeSitter, "Input", rb_cObject);
|
119
|
+
|
120
|
+
rb_define_alloc_func(cInput, input_allocate);
|
121
|
+
|
122
|
+
/* Class methods */
|
123
|
+
DECLARE_ACCESSOR(cInput, input, payload)
|
124
|
+
rb_define_method(cInput, "initialize", input_initialize, -1);
|
125
|
+
rb_define_method(cInput, "inspect", input_inspect, 0);
|
126
|
+
rb_define_method(cInput, "to_s", input_inspect, 0);
|
127
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
|
3
|
+
extern VALUE mTreeSitter;
|
4
|
+
|
5
|
+
VALUE cInputEdit;
|
6
|
+
|
7
|
+
DATA_WRAP(InputEdit, input_edit)
|
8
|
+
DATA_DEFINE_ACCESSOR(input_edit, start_byte, UINT2NUM, NUM2UINT)
|
9
|
+
DATA_DEFINE_ACCESSOR(input_edit, old_end_byte, UINT2NUM, NUM2UINT)
|
10
|
+
DATA_DEFINE_ACCESSOR(input_edit, new_end_byte, UINT2NUM, NUM2UINT)
|
11
|
+
DATA_DEFINE_ACCESSOR(input_edit, start_point, new_point_by_val, value_to_point)
|
12
|
+
DATA_DEFINE_ACCESSOR(input_edit, old_end_point, new_point_by_val, value_to_point)
|
13
|
+
DATA_DEFINE_ACCESSOR(input_edit, new_end_point, new_point_by_val, value_to_point)
|
14
|
+
|
15
|
+
static VALUE input_edit_inspect(VALUE self) {
|
16
|
+
input_edit_t *input_edit = unwrap(self);
|
17
|
+
return rb_sprintf("{start_byte=%i, old_end_byte=%i , new_end_byte=%i, "
|
18
|
+
"start_point=%+" PRIsVALUE ", old_end_point=%+" PRIsVALUE
|
19
|
+
", new_end_point=%+" PRIsVALUE "}",
|
20
|
+
input_edit->data.start_byte, input_edit->data.old_end_byte,
|
21
|
+
input_edit->data.new_end_byte,
|
22
|
+
new_point_by_val(input_edit->data.start_point),
|
23
|
+
new_point_by_val(input_edit->data.old_end_point),
|
24
|
+
new_point_by_val(input_edit->data.new_end_point));
|
25
|
+
}
|
26
|
+
|
27
|
+
void init_input_edit(void) {
|
28
|
+
cInputEdit = rb_define_class_under(mTreeSitter, "InputEdit", rb_cObject);
|
29
|
+
|
30
|
+
rb_define_alloc_func(cInputEdit, input_edit_allocate);
|
31
|
+
|
32
|
+
/* Class methods */
|
33
|
+
DECLARE_ACCESSOR(cInputEdit, input_edit, start_byte)
|
34
|
+
DECLARE_ACCESSOR(cInputEdit, input_edit, old_end_byte)
|
35
|
+
DECLARE_ACCESSOR(cInputEdit, input_edit, new_end_byte)
|
36
|
+
DECLARE_ACCESSOR(cInputEdit, input_edit, start_point)
|
37
|
+
DECLARE_ACCESSOR(cInputEdit, input_edit, old_end_point)
|
38
|
+
DECLARE_ACCESSOR(cInputEdit, input_edit, new_end_point)
|
39
|
+
|
40
|
+
rb_define_method(cInputEdit, "inspect", input_edit_inspect, 0);
|
41
|
+
rb_define_method(cInputEdit, "to_s", input_edit_inspect, 0);
|
42
|
+
}
|