tree-sitter-ktav 0.2.1
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.
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/README.ru.md +185 -0
- package/README.zh.md +179 -0
- package/binding.gyp +28 -0
- package/bindings/node/binding.cc +20 -0
- package/bindings/node/index.d.ts +28 -0
- package/bindings/node/index.js +7 -0
- package/grammar.js +255 -0
- package/package.json +66 -0
- package/queries/highlights.scm +85 -0
- package/queries/injections.scm +10 -0
- package/queries/locals.scm +12 -0
- package/src/grammar.json +818 -0
- package/src/node-types.json +479 -0
- package/src/parser.c +2874 -0
- package/src/scanner.c +209 -0
- package/src/tree_sitter/alloc.h +54 -0
- package/src/tree_sitter/array.h +330 -0
- package/src/tree_sitter/parser.h +286 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Marat K and the Ktav contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# tree-sitter-ktav
|
|
2
|
+
|
|
3
|
+
> A [tree-sitter](https://tree-sitter.github.io/) grammar for
|
|
4
|
+
> [Ktav (כְּתָב)](https://github.com/ktav-lang/spec) — the Written
|
|
5
|
+
> Configuration Format.
|
|
6
|
+
|
|
7
|
+
**Languages:** **English** · [Русский](README.ru.md) · [简体中文](README.zh.md)
|
|
8
|
+
|
|
9
|
+
[](https://github.com/ktav-lang/tree-sitter-ktav/actions/workflows/ci.yml)
|
|
10
|
+
[](https://crates.io/crates/tree-sitter-ktav)
|
|
11
|
+
[](https://www.npmjs.com/package/tree-sitter-ktav)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What is Ktav?
|
|
16
|
+
|
|
17
|
+
Ktav (Hebrew **כְּתָב**, "writing") is a plain-text configuration
|
|
18
|
+
format. JSON-shape (scalars, arrays, objects, `null`, booleans), but
|
|
19
|
+
without quotes around strings, without commas, and with dotted keys
|
|
20
|
+
(`server.port: 8080`) for nesting. The full specification — the same
|
|
21
|
+
one all official Ktav implementations target — lives in the
|
|
22
|
+
[`ktav-lang/spec`](https://github.com/ktav-lang/spec) repository.
|
|
23
|
+
|
|
24
|
+
## What is tree-sitter?
|
|
25
|
+
|
|
26
|
+
[Tree-sitter](https://tree-sitter.github.io/tree-sitter/) is an
|
|
27
|
+
incremental parser generator. Editors (Neovim, Helix, Emacs, VS Code,
|
|
28
|
+
Zed, …) use it for syntax highlighting, code folding, structural
|
|
29
|
+
selection, and other features that need a real parse tree rather than
|
|
30
|
+
a regex-based tokenizer. Each language ships its own grammar package;
|
|
31
|
+
this crate / npm package is the one for Ktav.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
### Rust (`tree-sitter` crate)
|
|
36
|
+
|
|
37
|
+
```toml
|
|
38
|
+
[dependencies]
|
|
39
|
+
tree-sitter = "0.25"
|
|
40
|
+
tree-sitter-ktav = "0.1"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```rust
|
|
44
|
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
45
|
+
let mut parser = tree_sitter::Parser::new();
|
|
46
|
+
parser.set_language(&tree_sitter_ktav::LANGUAGE.into())?;
|
|
47
|
+
|
|
48
|
+
let source = "name: Russia\nport:i 8080\n";
|
|
49
|
+
let tree = parser.parse(source, None).unwrap();
|
|
50
|
+
println!("{}", tree.root_node().to_sexp());
|
|
51
|
+
Ok(())
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Node.js (`tree-sitter` package)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install tree-sitter tree-sitter-ktav
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const Parser = require("tree-sitter");
|
|
63
|
+
const Ktav = require("tree-sitter-ktav");
|
|
64
|
+
|
|
65
|
+
const parser = new Parser();
|
|
66
|
+
parser.setLanguage(Ktav);
|
|
67
|
+
|
|
68
|
+
const tree = parser.parse("name: Russia\nport:i 8080\n");
|
|
69
|
+
console.log(tree.rootNode.toString());
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Editor integration
|
|
73
|
+
|
|
74
|
+
### Neovim (with [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
|
|
75
|
+
|
|
76
|
+
Until the grammar is upstreamed, register it manually in your config:
|
|
77
|
+
|
|
78
|
+
```lua
|
|
79
|
+
require("nvim-treesitter.parsers").get_parser_configs().ktav = {
|
|
80
|
+
install_info = {
|
|
81
|
+
url = "https://github.com/ktav-lang/tree-sitter-ktav",
|
|
82
|
+
files = { "src/parser.c" },
|
|
83
|
+
branch = "main",
|
|
84
|
+
},
|
|
85
|
+
filetype = "ktav",
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
vim.filetype.add({ extension = { ktav = "ktav" } })
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Then `:TSInstall ktav`. Drop `queries/highlights.scm`,
|
|
92
|
+
`queries/locals.scm`, and `queries/injections.scm` into your
|
|
93
|
+
`~/.config/nvim/queries/ktav/` directory (or let nvim-treesitter pick
|
|
94
|
+
them up from the parser repo).
|
|
95
|
+
|
|
96
|
+
### Helix
|
|
97
|
+
|
|
98
|
+
Add to `~/.config/helix/languages.toml`:
|
|
99
|
+
|
|
100
|
+
```toml
|
|
101
|
+
[[language]]
|
|
102
|
+
name = "ktav"
|
|
103
|
+
scope = "source.ktav"
|
|
104
|
+
file-types = ["ktav"]
|
|
105
|
+
roots = []
|
|
106
|
+
comment-token = "#"
|
|
107
|
+
indent = { tab-width = 4, unit = " " }
|
|
108
|
+
|
|
109
|
+
[[grammar]]
|
|
110
|
+
name = "ktav"
|
|
111
|
+
source = { git = "https://github.com/ktav-lang/tree-sitter-ktav", rev = "main" }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Then `hx --grammar fetch && hx --grammar build`.
|
|
115
|
+
|
|
116
|
+
### Other editors
|
|
117
|
+
|
|
118
|
+
The grammar exports the standard tree-sitter node-type metadata
|
|
119
|
+
(`src/node-types.json`) and queries (`queries/*.scm`), so any editor
|
|
120
|
+
with tree-sitter support can consume it once the parser is built.
|
|
121
|
+
|
|
122
|
+
## Node types
|
|
123
|
+
|
|
124
|
+
The grammar produces the following named nodes:
|
|
125
|
+
|
|
126
|
+
| Node | What it captures |
|
|
127
|
+
|----------------------------|-------------------------------------------------|
|
|
128
|
+
| `source_file` | the whole document |
|
|
129
|
+
| `comment` | a `#`-line comment |
|
|
130
|
+
| `blank_line` | an empty line |
|
|
131
|
+
| `object_pair` | `key SEP value` line |
|
|
132
|
+
| `key` / `dotted_key` | the key portion (with optional `.` separators) |
|
|
133
|
+
| `sep_string` / `sep_raw` / `sep_int` / `sep_float` | the four separators |
|
|
134
|
+
| `keyword` / `kw_null` / `kw_true` / `kw_false` | keywords |
|
|
135
|
+
| `scalar` | the catch-all single-line value body |
|
|
136
|
+
| `compound_object` | `{` … `}` block |
|
|
137
|
+
| `compound_array` | `[` … `]` block |
|
|
138
|
+
| `array_item` | a single item in an array |
|
|
139
|
+
| `multiline_stripped` | `(` … `)` block |
|
|
140
|
+
| `multiline_verbatim` | `((` … `))` block |
|
|
141
|
+
| `multiline_content_line` | a single line inside a multi-line string |
|
|
142
|
+
| `empty_object` / `empty_array` / `empty_paren` / `empty_double_paren` | inline empty forms |
|
|
143
|
+
| `empty_value` | separator immediately followed by EOL |
|
|
144
|
+
|
|
145
|
+
`object_pair` exposes `key`, `separator`, and `value` as fields;
|
|
146
|
+
`array_item` exposes `marker` (optional) and `value`.
|
|
147
|
+
|
|
148
|
+
## Building from source
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
git clone https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
152
|
+
cd tree-sitter-ktav
|
|
153
|
+
npm install
|
|
154
|
+
npx tree-sitter generate # writes src/parser.c
|
|
155
|
+
npx tree-sitter test # runs the corpus
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The generated `src/parser.c`, `src/grammar.json`, `src/node-types.json`,
|
|
159
|
+
and `src/tree_sitter/*` are checked into git per tree-sitter convention,
|
|
160
|
+
so consumers do not need the CLI to build.
|
|
161
|
+
|
|
162
|
+
## Status
|
|
163
|
+
|
|
164
|
+
`0.1.0` — implements [Ktav 0.1.0](https://github.com/ktav-lang/spec/blob/main/versions/0.1/spec.md).
|
|
165
|
+
The grammar accepts every valid Ktav 0.1.0 document (verified against
|
|
166
|
+
all `tests/valid/*.ktav` fixtures from the spec repo). It is a
|
|
167
|
+
syntactic accepter, not a strict spec validator — see
|
|
168
|
+
[`CHANGELOG.md`](CHANGELOG.md) "Known limitations" for the small
|
|
169
|
+
number of pathological cases the grammar accepts that the spec
|
|
170
|
+
rejects (mostly missing-whitespace-after-marker — § 6.10).
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT — see [LICENSE](LICENSE).
|
|
175
|
+
|
|
176
|
+
## Other Ktav repositories
|
|
177
|
+
|
|
178
|
+
- [`spec`](https://github.com/ktav-lang/spec) — specification + conformance suite
|
|
179
|
+
- [`rust`](https://github.com/ktav-lang/rust) — Rust (`cargo add ktav`)
|
|
180
|
+
- [`csharp`](https://github.com/ktav-lang/csharp) — C# / .NET (`dotnet add package Ktav`)
|
|
181
|
+
- [`golang`](https://github.com/ktav-lang/golang) — Go
|
|
182
|
+
- [`java`](https://github.com/ktav-lang/java) — Java / JVM (Maven Central)
|
|
183
|
+
- [`js`](https://github.com/ktav-lang/js) — JS / TS (`npm install @ktav-lang/ktav`)
|
|
184
|
+
- [`php`](https://github.com/ktav-lang/php) — PHP (`composer require ktav-lang/ktav`)
|
|
185
|
+
- [`python`](https://github.com/ktav-lang/python) — Python (`pip install ktav`)
|
package/README.ru.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# tree-sitter-ktav
|
|
2
|
+
|
|
3
|
+
> Грамматика [tree-sitter](https://tree-sitter.github.io/) для
|
|
4
|
+
> [Ktav (כְּתָב)](https://github.com/ktav-lang/spec) — Written
|
|
5
|
+
> Configuration Format.
|
|
6
|
+
|
|
7
|
+
**Языки:** [English](README.md) · **Русский** · [简体中文](README.zh.md)
|
|
8
|
+
|
|
9
|
+
[](https://github.com/ktav-lang/tree-sitter-ktav/actions/workflows/ci.yml)
|
|
10
|
+
[](https://crates.io/crates/tree-sitter-ktav)
|
|
11
|
+
[](https://www.npmjs.com/package/tree-sitter-ktav)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Что такое Ktav?
|
|
16
|
+
|
|
17
|
+
Ktav (иврит **כְּתָב**, «писание») — текстовый формат конфигурации
|
|
18
|
+
JSON-формы (скаляры, массивы, объекты, `null`, булево), но без кавычек
|
|
19
|
+
вокруг строк, без запятых, с точечными ключами (`server.port: 8080`)
|
|
20
|
+
для вложенности. Полная спецификация (та же, на которую ориентируются
|
|
21
|
+
все официальные реализации Ktav) лежит в
|
|
22
|
+
[`ktav-lang/spec`](https://github.com/ktav-lang/spec).
|
|
23
|
+
|
|
24
|
+
## Что такое tree-sitter?
|
|
25
|
+
|
|
26
|
+
[Tree-sitter](https://tree-sitter.github.io/tree-sitter/) — это
|
|
27
|
+
инкрементальный генератор парсеров. Редакторы (Neovim, Helix, Emacs,
|
|
28
|
+
VS Code, Zed, …) используют его для подсветки синтаксиса, фолдинга,
|
|
29
|
+
структурного выделения и других возможностей, требующих настоящего
|
|
30
|
+
дерева разбора, а не regex-токенизатора. Под каждый язык — своя
|
|
31
|
+
грамматика; этот пакет — грамматика для Ktav.
|
|
32
|
+
|
|
33
|
+
## Установка
|
|
34
|
+
|
|
35
|
+
### Rust
|
|
36
|
+
|
|
37
|
+
```toml
|
|
38
|
+
[dependencies]
|
|
39
|
+
tree-sitter = "0.25"
|
|
40
|
+
tree-sitter-ktav = "0.1"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```rust
|
|
44
|
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
45
|
+
let mut parser = tree_sitter::Parser::new();
|
|
46
|
+
parser.set_language(&tree_sitter_ktav::LANGUAGE.into())?;
|
|
47
|
+
|
|
48
|
+
let source = "name: Russia\nport:i 8080\n";
|
|
49
|
+
let tree = parser.parse(source, None).unwrap();
|
|
50
|
+
println!("{}", tree.root_node().to_sexp());
|
|
51
|
+
Ok(())
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Node.js
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install tree-sitter tree-sitter-ktav
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const Parser = require("tree-sitter");
|
|
63
|
+
const Ktav = require("tree-sitter-ktav");
|
|
64
|
+
|
|
65
|
+
const parser = new Parser();
|
|
66
|
+
parser.setLanguage(Ktav);
|
|
67
|
+
|
|
68
|
+
const tree = parser.parse("name: Russia\nport:i 8080\n");
|
|
69
|
+
console.log(tree.rootNode.toString());
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Интеграция с редакторами
|
|
73
|
+
|
|
74
|
+
### Neovim (через [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
|
|
75
|
+
|
|
76
|
+
Пока грамматика не зарегистрирована в апстриме, добавьте вручную:
|
|
77
|
+
|
|
78
|
+
```lua
|
|
79
|
+
require("nvim-treesitter.parsers").get_parser_configs().ktav = {
|
|
80
|
+
install_info = {
|
|
81
|
+
url = "https://github.com/ktav-lang/tree-sitter-ktav",
|
|
82
|
+
files = { "src/parser.c" },
|
|
83
|
+
branch = "main",
|
|
84
|
+
},
|
|
85
|
+
filetype = "ktav",
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
vim.filetype.add({ extension = { ktav = "ktav" } })
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Затем `:TSInstall ktav`. Положите `queries/highlights.scm`,
|
|
92
|
+
`queries/locals.scm` и `queries/injections.scm` в
|
|
93
|
+
`~/.config/nvim/queries/ktav/` (либо позвольте `nvim-treesitter`
|
|
94
|
+
подобрать их из репозитория грамматики).
|
|
95
|
+
|
|
96
|
+
### Helix
|
|
97
|
+
|
|
98
|
+
В `~/.config/helix/languages.toml`:
|
|
99
|
+
|
|
100
|
+
```toml
|
|
101
|
+
[[language]]
|
|
102
|
+
name = "ktav"
|
|
103
|
+
scope = "source.ktav"
|
|
104
|
+
file-types = ["ktav"]
|
|
105
|
+
roots = []
|
|
106
|
+
comment-token = "#"
|
|
107
|
+
indent = { tab-width = 4, unit = " " }
|
|
108
|
+
|
|
109
|
+
[[grammar]]
|
|
110
|
+
name = "ktav"
|
|
111
|
+
source = { git = "https://github.com/ktav-lang/tree-sitter-ktav", rev = "main" }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Затем `hx --grammar fetch && hx --grammar build`.
|
|
115
|
+
|
|
116
|
+
### Другие редакторы
|
|
117
|
+
|
|
118
|
+
Грамматика экспортирует стандартные tree-sitter-метаданные
|
|
119
|
+
(`src/node-types.json`) и запросы (`queries/*.scm`), так что любой
|
|
120
|
+
редактор с поддержкой tree-sitter сможет с ней работать.
|
|
121
|
+
|
|
122
|
+
## Узлы AST
|
|
123
|
+
|
|
124
|
+
Грамматика генерирует следующие именованные узлы:
|
|
125
|
+
|
|
126
|
+
| Узел | Что захватывает |
|
|
127
|
+
|----------------------------|--------------------------------------------------|
|
|
128
|
+
| `source_file` | весь документ |
|
|
129
|
+
| `comment` | строковый комментарий `#` |
|
|
130
|
+
| `blank_line` | пустую строку |
|
|
131
|
+
| `object_pair` | строку `ключ SEP значение` |
|
|
132
|
+
| `key` / `dotted_key` | ключ (с возможным `.`-разбиением) |
|
|
133
|
+
| `sep_string` / `sep_raw` / `sep_int` / `sep_float` | четыре разделителя |
|
|
134
|
+
| `keyword` / `kw_null` / `kw_true` / `kw_false` | ключевые слова |
|
|
135
|
+
| `scalar` | универсальное однострочное значение |
|
|
136
|
+
| `compound_object` | блок `{` … `}` |
|
|
137
|
+
| `compound_array` | блок `[` … `]` |
|
|
138
|
+
| `array_item` | элемент массива |
|
|
139
|
+
| `multiline_stripped` | блок `(` … `)` |
|
|
140
|
+
| `multiline_verbatim` | блок `((` … `))` |
|
|
141
|
+
| `multiline_content_line` | строка внутри многострочного значения |
|
|
142
|
+
| `empty_object` / `empty_array` / `empty_paren` / `empty_double_paren` | пустые inline-формы |
|
|
143
|
+
| `empty_value` | разделитель сразу за концом строки |
|
|
144
|
+
|
|
145
|
+
`object_pair` экспонирует поля `key`, `separator`, `value`;
|
|
146
|
+
`array_item` — `marker` (опционально) и `value`.
|
|
147
|
+
|
|
148
|
+
## Сборка из исходников
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
git clone https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
152
|
+
cd tree-sitter-ktav
|
|
153
|
+
npm install
|
|
154
|
+
npx tree-sitter generate # генерирует src/parser.c
|
|
155
|
+
npx tree-sitter test # запускает корпус
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Файлы `src/parser.c`, `src/grammar.json`, `src/node-types.json` и
|
|
159
|
+
`src/tree_sitter/*` коммитятся в git по соглашению tree-sitter, так
|
|
160
|
+
что потребителям грамматики не нужен CLI для сборки.
|
|
161
|
+
|
|
162
|
+
## Статус
|
|
163
|
+
|
|
164
|
+
`0.1.0` — реализует [Ktav 0.1.0](https://github.com/ktav-lang/spec/blob/main/versions/0.1/spec.md).
|
|
165
|
+
Грамматика принимает любой валидный документ Ktav 0.1.0 (проверено на
|
|
166
|
+
всех фикстурах `tests/valid/*.ktav` из spec-репозитория). Это
|
|
167
|
+
синтаксический акцептор, а не строгий валидатор — небольшое число
|
|
168
|
+
патологических случаев, которые грамматика принимает, а спецификация
|
|
169
|
+
запрещает (в основном § 6.10, отсутствие пробела после маркера),
|
|
170
|
+
перечислены в [`CHANGELOG.md`](CHANGELOG.md).
|
|
171
|
+
|
|
172
|
+
## Лицензия
|
|
173
|
+
|
|
174
|
+
MIT — см. [LICENSE](LICENSE).
|
|
175
|
+
|
|
176
|
+
## Другие репозитории Ktav
|
|
177
|
+
|
|
178
|
+
- [`spec`](https://github.com/ktav-lang/spec) — спецификация и conformance-сюита
|
|
179
|
+
- [`rust`](https://github.com/ktav-lang/rust) — Rust (`cargo add ktav`)
|
|
180
|
+
- [`csharp`](https://github.com/ktav-lang/csharp) — C# / .NET (`dotnet add package Ktav`)
|
|
181
|
+
- [`golang`](https://github.com/ktav-lang/golang) — Go
|
|
182
|
+
- [`java`](https://github.com/ktav-lang/java) — Java / JVM (Maven Central)
|
|
183
|
+
- [`js`](https://github.com/ktav-lang/js) — JS / TS (`npm install @ktav-lang/ktav`)
|
|
184
|
+
- [`php`](https://github.com/ktav-lang/php) — PHP (`composer require ktav-lang/ktav`)
|
|
185
|
+
- [`python`](https://github.com/ktav-lang/python) — Python (`pip install ktav`)
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# tree-sitter-ktav
|
|
2
|
+
|
|
3
|
+
> 面向 [Ktav (כְּתָב)](https://github.com/ktav-lang/spec)(书面配置
|
|
4
|
+
> 格式)的 [tree-sitter](https://tree-sitter.github.io/) 语法。
|
|
5
|
+
|
|
6
|
+
**语言:** [English](README.md) · [Русский](README.ru.md) · **简体中文**
|
|
7
|
+
|
|
8
|
+
[](https://github.com/ktav-lang/tree-sitter-ktav/actions/workflows/ci.yml)
|
|
9
|
+
[](https://crates.io/crates/tree-sitter-ktav)
|
|
10
|
+
[](https://www.npmjs.com/package/tree-sitter-ktav)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 什么是 Ktav?
|
|
15
|
+
|
|
16
|
+
Ktav(希伯来语 **כְּתָב**,"书写")是一种纯文本配置格式。形态与
|
|
17
|
+
JSON 相同(标量、数组、对象、`null`、布尔值),但字符串无引号、无逗
|
|
18
|
+
号,并使用点式键(`server.port: 8080`)表示嵌套。完整规范——所有官
|
|
19
|
+
方 Ktav 实现共同遵循的——在
|
|
20
|
+
[`ktav-lang/spec`](https://github.com/ktav-lang/spec) 仓库中。
|
|
21
|
+
|
|
22
|
+
## 什么是 tree-sitter?
|
|
23
|
+
|
|
24
|
+
[Tree-sitter](https://tree-sitter.github.io/tree-sitter/) 是一种增
|
|
25
|
+
量解析器生成器。编辑器(Neovim、Helix、Emacs、VS Code、Zed 等)使用
|
|
26
|
+
它实现语法高亮、代码折叠、结构化选择以及其他需要真正解析树而非正则
|
|
27
|
+
词法器的功能。每种语言都有自己的语法包;本包就是 Ktav 的语法。
|
|
28
|
+
|
|
29
|
+
## 安装
|
|
30
|
+
|
|
31
|
+
### Rust
|
|
32
|
+
|
|
33
|
+
```toml
|
|
34
|
+
[dependencies]
|
|
35
|
+
tree-sitter = "0.25"
|
|
36
|
+
tree-sitter-ktav = "0.1"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```rust
|
|
40
|
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
41
|
+
let mut parser = tree_sitter::Parser::new();
|
|
42
|
+
parser.set_language(&tree_sitter_ktav::LANGUAGE.into())?;
|
|
43
|
+
|
|
44
|
+
let source = "name: Russia\nport:i 8080\n";
|
|
45
|
+
let tree = parser.parse(source, None).unwrap();
|
|
46
|
+
println!("{}", tree.root_node().to_sexp());
|
|
47
|
+
Ok(())
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Node.js
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm install tree-sitter tree-sitter-ktav
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
const Parser = require("tree-sitter");
|
|
59
|
+
const Ktav = require("tree-sitter-ktav");
|
|
60
|
+
|
|
61
|
+
const parser = new Parser();
|
|
62
|
+
parser.setLanguage(Ktav);
|
|
63
|
+
|
|
64
|
+
const tree = parser.parse("name: Russia\nport:i 8080\n");
|
|
65
|
+
console.log(tree.rootNode.toString());
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 编辑器集成
|
|
69
|
+
|
|
70
|
+
### Neovim(搭配 [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
|
|
71
|
+
|
|
72
|
+
在语法尚未上游之前,请在配置中手动注册:
|
|
73
|
+
|
|
74
|
+
```lua
|
|
75
|
+
require("nvim-treesitter.parsers").get_parser_configs().ktav = {
|
|
76
|
+
install_info = {
|
|
77
|
+
url = "https://github.com/ktav-lang/tree-sitter-ktav",
|
|
78
|
+
files = { "src/parser.c" },
|
|
79
|
+
branch = "main",
|
|
80
|
+
},
|
|
81
|
+
filetype = "ktav",
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
vim.filetype.add({ extension = { ktav = "ktav" } })
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
随后执行 `:TSInstall ktav`。把 `queries/highlights.scm`、
|
|
88
|
+
`queries/locals.scm` 与 `queries/injections.scm` 放入
|
|
89
|
+
`~/.config/nvim/queries/ktav/`(或让 `nvim-treesitter` 自动从仓库
|
|
90
|
+
拉取)。
|
|
91
|
+
|
|
92
|
+
### Helix
|
|
93
|
+
|
|
94
|
+
在 `~/.config/helix/languages.toml` 中:
|
|
95
|
+
|
|
96
|
+
```toml
|
|
97
|
+
[[language]]
|
|
98
|
+
name = "ktav"
|
|
99
|
+
scope = "source.ktav"
|
|
100
|
+
file-types = ["ktav"]
|
|
101
|
+
roots = []
|
|
102
|
+
comment-token = "#"
|
|
103
|
+
indent = { tab-width = 4, unit = " " }
|
|
104
|
+
|
|
105
|
+
[[grammar]]
|
|
106
|
+
name = "ktav"
|
|
107
|
+
source = { git = "https://github.com/ktav-lang/tree-sitter-ktav", rev = "main" }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
随后执行 `hx --grammar fetch && hx --grammar build`。
|
|
111
|
+
|
|
112
|
+
### 其他编辑器
|
|
113
|
+
|
|
114
|
+
语法导出标准的 tree-sitter 节点类型元数据
|
|
115
|
+
(`src/node-types.json`)和查询文件(`queries/*.scm`),任何支持
|
|
116
|
+
tree-sitter 的编辑器都可以在解析器构建后直接使用。
|
|
117
|
+
|
|
118
|
+
## 节点类型
|
|
119
|
+
|
|
120
|
+
语法生成以下命名节点:
|
|
121
|
+
|
|
122
|
+
| 节点 | 捕获内容 |
|
|
123
|
+
|---------------------------|-----------------------------------------------|
|
|
124
|
+
| `source_file` | 整个文档 |
|
|
125
|
+
| `comment` | `#` 行注释 |
|
|
126
|
+
| `blank_line` | 空行 |
|
|
127
|
+
| `object_pair` | `key SEP value` 行 |
|
|
128
|
+
| `key` / `dotted_key` | 键部分(可包含 `.` 分隔符) |
|
|
129
|
+
| `sep_string` / `sep_raw` / `sep_int` / `sep_float` | 四种分隔符 |
|
|
130
|
+
| `keyword` / `kw_null` / `kw_true` / `kw_false` | 关键字 |
|
|
131
|
+
| `scalar` | 通用单行值正文 |
|
|
132
|
+
| `compound_object` | `{` … `}` 块 |
|
|
133
|
+
| `compound_array` | `[` … `]` 块 |
|
|
134
|
+
| `array_item` | 数组中的单个元素 |
|
|
135
|
+
| `multiline_stripped` | `(` … `)` 块 |
|
|
136
|
+
| `multiline_verbatim` | `((` … `))` 块 |
|
|
137
|
+
| `multiline_content_line` | 多行字符串内的单行 |
|
|
138
|
+
| `empty_object` / `empty_array` / `empty_paren` / `empty_double_paren` | 内联空形式 |
|
|
139
|
+
| `empty_value` | 分隔符紧跟行尾 |
|
|
140
|
+
|
|
141
|
+
`object_pair` 暴露字段 `key`、`separator`、`value`;`array_item`
|
|
142
|
+
暴露 `marker`(可选)和 `value`。
|
|
143
|
+
|
|
144
|
+
## 从源码构建
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
git clone https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
148
|
+
cd tree-sitter-ktav
|
|
149
|
+
npm install
|
|
150
|
+
npx tree-sitter generate # 生成 src/parser.c
|
|
151
|
+
npx tree-sitter test # 运行语料库
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`src/parser.c`、`src/grammar.json`、`src/node-types.json` 与
|
|
155
|
+
`src/tree_sitter/*` 按 tree-sitter 惯例已纳入 git,下游消费者无需
|
|
156
|
+
CLI 即可构建。
|
|
157
|
+
|
|
158
|
+
## 状态
|
|
159
|
+
|
|
160
|
+
`0.1.0` — 实现 [Ktav 0.1.0](https://github.com/ktav-lang/spec/blob/main/versions/0.1/spec.md)。
|
|
161
|
+
语法接受所有合法的 Ktav 0.1.0 文档(对 spec 仓库下
|
|
162
|
+
`tests/valid/*.ktav` 全部用例验证通过)。它是一个语法接受器,而非
|
|
163
|
+
严格的规范校验器——少数语法接受但规范拒绝的边界情况(主要是 § 6.10
|
|
164
|
+
"标记后必须有空格")见 [`CHANGELOG.md`](CHANGELOG.md)。
|
|
165
|
+
|
|
166
|
+
## 许可证
|
|
167
|
+
|
|
168
|
+
MIT — 见 [LICENSE](LICENSE)。
|
|
169
|
+
|
|
170
|
+
## 其他 Ktav 仓库
|
|
171
|
+
|
|
172
|
+
- [`spec`](https://github.com/ktav-lang/spec) — 规范与一致性测试套件
|
|
173
|
+
- [`rust`](https://github.com/ktav-lang/rust) — Rust(`cargo add ktav`)
|
|
174
|
+
- [`csharp`](https://github.com/ktav-lang/csharp) — C# / .NET(`dotnet add package Ktav`)
|
|
175
|
+
- [`golang`](https://github.com/ktav-lang/golang) — Go
|
|
176
|
+
- [`java`](https://github.com/ktav-lang/java) — Java / JVM(Maven Central)
|
|
177
|
+
- [`js`](https://github.com/ktav-lang/js) — JS / TS(`npm install @ktav-lang/ktav`)
|
|
178
|
+
- [`php`](https://github.com/ktav-lang/php) — PHP(`composer require ktav-lang/ktav`)
|
|
179
|
+
- [`python`](https://github.com/ktav-lang/python) — Python(`pip install ktav`)
|
package/binding.gyp
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "tree_sitter_ktav_binding",
|
|
5
|
+
"dependencies": [
|
|
6
|
+
"<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except"
|
|
7
|
+
],
|
|
8
|
+
"include_dirs": [
|
|
9
|
+
"src"
|
|
10
|
+
],
|
|
11
|
+
"sources": [
|
|
12
|
+
"bindings/node/binding.cc",
|
|
13
|
+
"src/parser.c",
|
|
14
|
+
"src/scanner.c"
|
|
15
|
+
],
|
|
16
|
+
"cflags_c": [
|
|
17
|
+
"-std=c11"
|
|
18
|
+
],
|
|
19
|
+
"conditions": [
|
|
20
|
+
["OS!='win'", {
|
|
21
|
+
"cflags_c": [
|
|
22
|
+
"-Wno-unused-but-set-variable"
|
|
23
|
+
]
|
|
24
|
+
}]
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#include <napi.h>
|
|
2
|
+
|
|
3
|
+
typedef struct TSLanguage TSLanguage;
|
|
4
|
+
|
|
5
|
+
extern "C" TSLanguage *tree_sitter_ktav();
|
|
6
|
+
|
|
7
|
+
// "tree-sitter", "language" hashed with BLAKE2
|
|
8
|
+
const napi_type_tag LANGUAGE_TYPE_TAG = {
|
|
9
|
+
0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
13
|
+
exports["name"] = Napi::String::New(env, "ktav");
|
|
14
|
+
auto language = Napi::External<TSLanguage>::New(env, tree_sitter_ktav());
|
|
15
|
+
language.TypeTag(&LANGUAGE_TYPE_TAG);
|
|
16
|
+
exports["language"] = language;
|
|
17
|
+
return exports;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
NODE_API_MODULE(tree_sitter_ktav_binding, Init)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
type BaseNode = {
|
|
2
|
+
type: string;
|
|
3
|
+
named: boolean;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type ChildNode = {
|
|
7
|
+
multiple: boolean;
|
|
8
|
+
required: boolean;
|
|
9
|
+
types: BaseNode[];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type NodeInfo =
|
|
13
|
+
| (BaseNode & {
|
|
14
|
+
subtypes: BaseNode[];
|
|
15
|
+
})
|
|
16
|
+
| (BaseNode & {
|
|
17
|
+
fields: { [name: string]: ChildNode };
|
|
18
|
+
children: ChildNode[];
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
type Language = {
|
|
22
|
+
name: string;
|
|
23
|
+
language: unknown;
|
|
24
|
+
nodeTypeInfo: NodeInfo[];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
declare const language: Language;
|
|
28
|
+
export = language;
|