tree-sitter-ktav 0.6.1 → 0.8.0
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/README.md +63 -40
- package/README.ru.md +72 -48
- package/README.zh.md +65 -42
- package/bindings/node/binding_test.js +198 -0
- package/grammar.js +384 -82
- package/package.json +14 -5
- package/queries/highlights.scm +16 -11
- package/queries/locals.scm +5 -0
- package/scripts/rebuild-node.mjs +12 -0
- package/src/grammar.json +938 -177
- package/src/node-types.json +70 -17
- package/src/parser.c +9472 -4023
- package/src/scanner.c +611 -55
package/README.md
CHANGED
|
@@ -19,9 +19,10 @@
|
|
|
19
19
|
## What is Ktav?
|
|
20
20
|
|
|
21
21
|
Ktav (Hebrew **כְּתָב**, "writing") is a plain-text configuration
|
|
22
|
-
format
|
|
23
|
-
|
|
24
|
-
(`server.port: 8080`)
|
|
22
|
+
format with a JSON-shaped data model (scalars, arrays, objects, `null`,
|
|
23
|
+
booleans). Strings are unquoted, ordinary entries have no commas (inline
|
|
24
|
+
compounds use commas), and dotted keys (`server.port: 8080`) express
|
|
25
|
+
nesting. The full specification — the same
|
|
25
26
|
one all official Ktav implementations target — lives in the
|
|
26
27
|
[`ktav-lang/spec`](https://github.com/ktav-lang/spec) repository.
|
|
27
28
|
|
|
@@ -41,7 +42,7 @@ this crate / npm package is the one for Ktav.
|
|
|
41
42
|
```toml
|
|
42
43
|
[dependencies]
|
|
43
44
|
tree-sitter = "0.25"
|
|
44
|
-
tree-sitter-ktav = "0.
|
|
45
|
+
tree-sitter-ktav = "0.8.0"
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
```rust
|
|
@@ -58,6 +59,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
58
59
|
|
|
59
60
|
### Node.js (`tree-sitter` package)
|
|
60
61
|
|
|
62
|
+
The npm package ships native source, not prebuilt `.node` binaries.
|
|
63
|
+
Installation needs a C/C++ build toolchain and Python for `node-gyp`;
|
|
64
|
+
the generated parser is included, so the Tree-sitter CLI is not needed.
|
|
65
|
+
|
|
61
66
|
```bash
|
|
62
67
|
npm install tree-sitter tree-sitter-ktav
|
|
63
68
|
```
|
|
@@ -77,25 +82,33 @@ console.log(tree.rootNode.toString());
|
|
|
77
82
|
|
|
78
83
|
### Neovim (with [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
The current `nvim-treesitter` main branch no longer uses the legacy
|
|
86
|
+
`get_parser_configs()` registration API. Build the parser library from the
|
|
87
|
+
grammar repository, then load it with Neovim's Tree-sitter API. The CLI
|
|
88
|
+
includes `src/scanner.c` automatically when building this grammar:
|
|
81
89
|
|
|
82
90
|
```lua
|
|
83
|
-
require("nvim-treesitter
|
|
84
|
-
install_info = {
|
|
85
|
-
url = "https://github.com/ktav-lang/tree-sitter-ktav",
|
|
86
|
-
files = { "src/parser.c" },
|
|
87
|
-
branch = "main",
|
|
88
|
-
},
|
|
89
|
-
filetype = "ktav",
|
|
90
|
-
}
|
|
91
|
-
|
|
91
|
+
require("nvim-treesitter").setup({})
|
|
92
92
|
vim.filetype.add({ extension = { ktav = "ktav" } })
|
|
93
|
+
vim.treesitter.language.add("ktav", {
|
|
94
|
+
path = vim.fn.stdpath("data") .. "/site/parser/ktav.so",
|
|
95
|
+
})
|
|
96
|
+
vim.api.nvim_create_autocmd("FileType", {
|
|
97
|
+
pattern = "ktav",
|
|
98
|
+
callback = function() vim.treesitter.start() end,
|
|
99
|
+
})
|
|
93
100
|
```
|
|
94
101
|
|
|
95
|
-
|
|
96
|
-
`
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
Create the target `parser` directory first. On Unix, for example, run
|
|
103
|
+
`mkdir -p ~/.local/share/nvim/site/parser`, then build from the grammar
|
|
104
|
+
repository with `npx tree-sitter build --output
|
|
105
|
+
~/.local/share/nvim/site/parser/ktav.so`. The directory and `.so` filename
|
|
106
|
+
are Unix examples; use the path from `stdpath("data")` and your platform's
|
|
107
|
+
shared-library extension (for example, `.dll` on Windows) in both the build
|
|
108
|
+
command and Lua config. If building from an explicit source-file list,
|
|
109
|
+
include both `src/parser.c` and `src/scanner.c`. Copy
|
|
110
|
+
`queries/highlights.scm`, `queries/locals.scm`, and `queries/injections.scm`
|
|
111
|
+
to `~/.config/nvim/queries/ktav/`.
|
|
99
112
|
|
|
100
113
|
### Helix
|
|
101
114
|
|
|
@@ -107,7 +120,7 @@ name = "ktav"
|
|
|
107
120
|
scope = "source.ktav"
|
|
108
121
|
file-types = ["ktav"]
|
|
109
122
|
roots = []
|
|
110
|
-
comment-token = "
|
|
123
|
+
comment-token = "##"
|
|
111
124
|
indent = { tab-width = 4, unit = " " }
|
|
112
125
|
|
|
113
126
|
[[grammar]]
|
|
@@ -125,38 +138,47 @@ with tree-sitter support can consume it once the parser is built.
|
|
|
125
138
|
|
|
126
139
|
## Node types
|
|
127
140
|
|
|
128
|
-
|
|
141
|
+
Representative named nodes from the CST (`src/node-types.json`) include:
|
|
129
142
|
|
|
130
143
|
| Node | What it captures |
|
|
131
144
|
|----------------------------|-------------------------------------------------|
|
|
132
145
|
| `source_file` | the whole document |
|
|
133
|
-
| `comment` | a
|
|
146
|
+
| `comment` | a `##`-line comment |
|
|
134
147
|
| `blank_line` | an empty line |
|
|
135
148
|
| `object_pair` | `key SEP value` line |
|
|
136
|
-
| `key` / `dotted_key` | the key portion
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
149
|
+
| `key` / `dotted_key` | the key portion and dotted segments |
|
|
150
|
+
| `quoted_key_segment` | a `"…"`, `'…'` or `` `…` `` key segment (§ 5.3.3) |
|
|
151
|
+
| `escape_sequence` | an escape in a key or inline value (§ 3.7) |
|
|
152
|
+
| `sep_string` / `sep_raw` | the `:` and `::` pair separators |
|
|
153
|
+
| `keyword` / `kw_null` / `kw_true` / `kw_false` | keywords, whole-line and inline |
|
|
154
|
+
| `integer` / `float` | numbers, whole-line and inline (§ 5.2 typing) |
|
|
155
|
+
| `scalar` / `raw_scalar` | ordinary and raw single-line values |
|
|
156
|
+
| `top_scalar` | a string item of a root-level Array |
|
|
157
|
+
| `inline_scalar` / `inline_raw_scalar` | string values after `:` / `::` in inline compounds |
|
|
140
158
|
| `compound_object` | `{` … `}` block |
|
|
141
159
|
| `compound_array` | `[` … `]` block |
|
|
142
|
-
| `
|
|
160
|
+
| `inline_object` / `inline_array` | inline compounds with comma-separated entries |
|
|
161
|
+
| `inline_pair` / `inline_value` | entries and values in inline compounds |
|
|
162
|
+
| `array_item` / `top_array_item` | items in compound and top-level arrays |
|
|
143
163
|
| `multiline_stripped` | `(` … `)` block |
|
|
144
164
|
| `multiline_verbatim` | `((` … `))` block |
|
|
145
165
|
| `multiline_content_line` | a single line inside a multi-line string |
|
|
146
166
|
| `empty_object` / `empty_array` / `empty_paren` / `empty_double_paren` | inline empty forms |
|
|
147
|
-
| `empty_value` | separator
|
|
167
|
+
| `empty_value` | separator plus the maximal allowed whitespace run through EOL or true EOF |
|
|
148
168
|
|
|
149
|
-
`object_pair`
|
|
150
|
-
`
|
|
169
|
+
`object_pair` and `inline_pair` expose `key`, `separator`, and `value` fields
|
|
170
|
+
(`inline_pair.value` is optional); `array_item` and `top_array_item` expose a
|
|
171
|
+
required `value` and optional `marker`.
|
|
151
172
|
|
|
152
173
|
## Building from source
|
|
153
174
|
|
|
154
175
|
```bash
|
|
155
|
-
git clone https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
176
|
+
git clone --recurse-submodules https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
156
177
|
cd tree-sitter-ktav
|
|
157
|
-
npm
|
|
158
|
-
npx tree-sitter generate #
|
|
159
|
-
npx tree-sitter test # runs the corpus
|
|
178
|
+
npm ci # installs the locked tree-sitter-cli 0.26.8
|
|
179
|
+
npx tree-sitter generate # regenerates src/parser.c and related files
|
|
180
|
+
npx tree-sitter test # runs the tree-sitter corpus
|
|
181
|
+
cargo test # Rust tests, including spec conformance
|
|
160
182
|
```
|
|
161
183
|
|
|
162
184
|
The generated `src/parser.c`, `src/grammar.json`, `src/node-types.json`,
|
|
@@ -165,13 +187,14 @@ so consumers do not need the CLI to build.
|
|
|
165
187
|
|
|
166
188
|
## Status
|
|
167
189
|
|
|
168
|
-
`0.
|
|
169
|
-
The grammar
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
190
|
+
`0.8.0` — Tree-sitter grammar targeting the syntax in [Ktav 0.8.0](https://github.com/ktav-lang/spec/blob/main/versions/0.8/spec.md).
|
|
191
|
+
The grammar parses every pinned spec 0.8 valid fixture without error and
|
|
192
|
+
checks each Object/Array root against its JSON oracle. Every invalid
|
|
193
|
+
fixture yields a syntax error except those needing key validation
|
|
194
|
+
(`DuplicateKey`, `KeyPathConflict`) or pre-parse UTF-8 byte validation
|
|
195
|
+
(`InvalidUtf8`). Tree-sitter supplies
|
|
196
|
+
editor syntax trees; it does not perform the semantic validation of the
|
|
197
|
+
reference Rust parser.
|
|
175
198
|
|
|
176
199
|
## License
|
|
177
200
|
|
package/README.ru.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# tree-sitter-ktav
|
|
2
2
|
|
|
3
3
|
> Грамматика [tree-sitter](https://tree-sitter.github.io/) для
|
|
4
|
-
> [Ktav (כְּתָב)](https://github.com/ktav-lang/spec) —
|
|
5
|
-
>
|
|
4
|
+
> [Ktav (כְּתָב)](https://github.com/ktav-lang/spec) — формата
|
|
5
|
+
> письменной конфигурации.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Languages:** [English](README.md) · **Русский** · [简体中文](README.zh.md)
|
|
8
8
|
|
|
9
9
|
**Песочница:** конвертация JSON / YAML / TOML / INI ⇄ Ktav прямо в браузере — **[ktav-lang.github.io](https://ktav-lang.github.io/)**.
|
|
10
10
|
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
|
|
21
21
|
Ktav (иврит **כְּתָב**, «писание») — текстовый формат конфигурации
|
|
22
22
|
JSON-формы (скаляры, массивы, объекты, `null`, булево), но без кавычек
|
|
23
|
-
вокруг
|
|
24
|
-
|
|
23
|
+
вокруг строк; между обычными элементами запятых нет, однако в inline-
|
|
24
|
+
структурах они используются. Для вложенности служат точечные ключи
|
|
25
|
+
(`server.port: 8080`). Полная спецификация (та же, на которую ориентируются
|
|
25
26
|
все официальные реализации Ktav) лежит в
|
|
26
27
|
[`ktav-lang/spec`](https://github.com/ktav-lang/spec).
|
|
27
28
|
|
|
@@ -36,12 +37,12 @@ VS Code, Zed, …) используют его для подсветки син
|
|
|
36
37
|
|
|
37
38
|
## Установка
|
|
38
39
|
|
|
39
|
-
### Rust
|
|
40
|
+
### Rust (крейт `tree-sitter`)
|
|
40
41
|
|
|
41
42
|
```toml
|
|
42
43
|
[dependencies]
|
|
43
|
-
tree-sitter
|
|
44
|
-
tree-sitter-ktav
|
|
44
|
+
tree-sitter = "0.25"
|
|
45
|
+
tree-sitter-ktav = "0.8.0"
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
```rust
|
|
@@ -56,7 +57,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
56
57
|
}
|
|
57
58
|
```
|
|
58
59
|
|
|
59
|
-
### Node.js
|
|
60
|
+
### Node.js (пакет `tree-sitter`)
|
|
61
|
+
|
|
62
|
+
Пакет npm содержит исходники нативного модуля, а не готовые `.node`-бинарники.
|
|
63
|
+
Для установки нужны компилятор C/C++ и Python для `node-gyp`;
|
|
64
|
+
сгенерированный парсер уже включён, поэтому Tree-sitter CLI не нужен.
|
|
60
65
|
|
|
61
66
|
```bash
|
|
62
67
|
npm install tree-sitter tree-sitter-ktav
|
|
@@ -75,27 +80,35 @@ console.log(tree.rootNode.toString());
|
|
|
75
80
|
|
|
76
81
|
## Интеграция с редакторами
|
|
77
82
|
|
|
78
|
-
### Neovim (
|
|
83
|
+
### Neovim (с [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
В текущей основной ветке `nvim-treesitter` больше не используется устаревший
|
|
86
|
+
API регистрации `get_parser_configs()`. Соберите библиотеку парсера из
|
|
87
|
+
репозитория грамматики и загрузите её через Tree-sitter API Neovim. CLI
|
|
88
|
+
автоматически включает `src/scanner.c` при сборке этой грамматики:
|
|
81
89
|
|
|
82
90
|
```lua
|
|
83
|
-
require("nvim-treesitter
|
|
84
|
-
install_info = {
|
|
85
|
-
url = "https://github.com/ktav-lang/tree-sitter-ktav",
|
|
86
|
-
files = { "src/parser.c" },
|
|
87
|
-
branch = "main",
|
|
88
|
-
},
|
|
89
|
-
filetype = "ktav",
|
|
90
|
-
}
|
|
91
|
-
|
|
91
|
+
require("nvim-treesitter").setup({})
|
|
92
92
|
vim.filetype.add({ extension = { ktav = "ktav" } })
|
|
93
|
+
vim.treesitter.language.add("ktav", {
|
|
94
|
+
path = vim.fn.stdpath("data") .. "/site/parser/ktav.so",
|
|
95
|
+
})
|
|
96
|
+
vim.api.nvim_create_autocmd("FileType", {
|
|
97
|
+
pattern = "ktav",
|
|
98
|
+
callback = function() vim.treesitter.start() end,
|
|
99
|
+
})
|
|
93
100
|
```
|
|
94
101
|
|
|
95
|
-
|
|
96
|
-
`
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
Сначала создайте целевой каталог `parser`. Например, в Unix выполните
|
|
103
|
+
`mkdir -p ~/.local/share/nvim/site/parser`, затем из репозитория грамматики
|
|
104
|
+
соберите библиотеку командой `npx tree-sitter build --output
|
|
105
|
+
~/.local/share/nvim/site/parser/ktav.so`. Каталог и расширение `.so` здесь
|
|
106
|
+
приведены как пример для Unix; используйте путь из `stdpath("data")` и
|
|
107
|
+
расширение динамической библиотеки вашей платформы (например, `.dll` в
|
|
108
|
+
Windows) и в команде сборки, и в Lua-конфигурации. Если список исходников
|
|
109
|
+
задаётся явно, включите `src/parser.c` и `src/scanner.c`. Скопируйте
|
|
110
|
+
`queries/highlights.scm`, `queries/locals.scm` и `queries/injections.scm` в
|
|
111
|
+
`~/.config/nvim/queries/ktav/`.
|
|
99
112
|
|
|
100
113
|
### Helix
|
|
101
114
|
|
|
@@ -107,7 +120,7 @@ name = "ktav"
|
|
|
107
120
|
scope = "source.ktav"
|
|
108
121
|
file-types = ["ktav"]
|
|
109
122
|
roots = []
|
|
110
|
-
comment-token = "
|
|
123
|
+
comment-token = "##"
|
|
111
124
|
indent = { tab-width = 4, unit = " " }
|
|
112
125
|
|
|
113
126
|
[[grammar]]
|
|
@@ -123,40 +136,49 @@ source = { git = "https://github.com/ktav-lang/tree-sitter-ktav", rev = "main" }
|
|
|
123
136
|
(`src/node-types.json`) и запросы (`queries/*.scm`), так что любой
|
|
124
137
|
редактор с поддержкой tree-sitter сможет с ней работать.
|
|
125
138
|
|
|
126
|
-
##
|
|
139
|
+
## Типы узлов CST
|
|
127
140
|
|
|
128
|
-
|
|
141
|
+
Примеры именованных узлов CST (см. `src/node-types.json`):
|
|
129
142
|
|
|
130
143
|
| Узел | Что захватывает |
|
|
131
144
|
|----------------------------|--------------------------------------------------|
|
|
132
145
|
| `source_file` | весь документ |
|
|
133
|
-
| `comment` | строковый комментарий
|
|
146
|
+
| `comment` | строковый комментарий `##` |
|
|
134
147
|
| `blank_line` | пустую строку |
|
|
135
148
|
| `object_pair` | строку `ключ SEP значение` |
|
|
136
|
-
| `key` / `dotted_key` | ключ
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
149
|
+
| `key` / `dotted_key` | ключ и сегменты точечного пути |
|
|
150
|
+
| `quoted_key_segment` | сегмент ключа `"…"`, `'…'` или `` `…` `` (§ 5.3.3) |
|
|
151
|
+
| `escape_sequence` | экранирование в ключе или inline-значении (§ 3.7) |
|
|
152
|
+
| `sep_string` / `sep_raw` | разделители пар `:` и `::` |
|
|
153
|
+
| `keyword` / `kw_null` / `kw_true` / `kw_false` | ключевые слова, в строке и inline |
|
|
154
|
+
| `integer` / `float` | числа, в строке и inline (типизация § 5.2) |
|
|
155
|
+
| `scalar` / `raw_scalar` | обычные и raw-значения в одну строку |
|
|
156
|
+
| `top_scalar` | строковый элемент массива верхнего уровня |
|
|
157
|
+
| `inline_scalar` / `inline_raw_scalar` | строковые значения после `:` / `::` в inline-структурах |
|
|
140
158
|
| `compound_object` | блок `{` … `}` |
|
|
141
159
|
| `compound_array` | блок `[` … `]` |
|
|
142
|
-
| `
|
|
160
|
+
| `inline_object` / `inline_array` | inline-структуры с элементами через запятую |
|
|
161
|
+
| `inline_pair` / `inline_value` | пары и значения inline-структур |
|
|
162
|
+
| `array_item` / `top_array_item` | элементы массива и массива верхнего уровня |
|
|
143
163
|
| `multiline_stripped` | блок `(` … `)` |
|
|
144
164
|
| `multiline_verbatim` | блок `((` … `))` |
|
|
145
165
|
| `multiline_content_line` | строка внутри многострочного значения |
|
|
146
166
|
| `empty_object` / `empty_array` / `empty_paren` / `empty_double_paren` | пустые inline-формы |
|
|
147
|
-
| `empty_value` | разделитель
|
|
167
|
+
| `empty_value` | разделитель и максимальная последовательность допустимых пробелов до конца строки или файла |
|
|
148
168
|
|
|
149
|
-
`object_pair`
|
|
150
|
-
`
|
|
169
|
+
`object_pair` и `inline_pair` имеют поля `key`, `separator`, `value`
|
|
170
|
+
(`inline_pair.value` необязательно); `array_item` и `top_array_item` имеют
|
|
171
|
+
обязательное `value` и необязательное `marker`.
|
|
151
172
|
|
|
152
173
|
## Сборка из исходников
|
|
153
174
|
|
|
154
175
|
```bash
|
|
155
|
-
git clone https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
176
|
+
git clone --recurse-submodules https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
156
177
|
cd tree-sitter-ktav
|
|
157
|
-
npm
|
|
158
|
-
npx tree-sitter generate #
|
|
159
|
-
npx tree-sitter test # запускает корпус
|
|
178
|
+
npm ci # устанавливает tree-sitter-cli 0.26.8 из lock-файла
|
|
179
|
+
npx tree-sitter generate # обновляет src/parser.c и связанные файлы
|
|
180
|
+
npx tree-sitter test # запускает корпус tree-sitter
|
|
181
|
+
cargo test # тесты Rust, включая проверку соответствия спекам
|
|
160
182
|
```
|
|
161
183
|
|
|
162
184
|
Файлы `src/parser.c`, `src/grammar.json`, `src/node-types.json` и
|
|
@@ -165,17 +187,19 @@ npx tree-sitter test # запускает корпус
|
|
|
165
187
|
|
|
166
188
|
## Статус
|
|
167
189
|
|
|
168
|
-
`0.
|
|
169
|
-
Грамматика
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
190
|
+
`0.8.0` — Tree-sitter-грамматика синтаксиса [Ktav 0.8.0](https://github.com/ktav-lang/spec/blob/main/versions/0.8/spec.md).
|
|
191
|
+
Грамматика разбирает все закреплённые валидные фикстуры spec 0.8 без
|
|
192
|
+
ошибок и сверяет корневой Object/Array с JSON-оракулом. Каждая
|
|
193
|
+
невалидная фикстура даёт синтаксическую ошибку, кроме случаев, где
|
|
194
|
+
нужна проверка ключей (`DuplicateKey`, `KeyPathConflict`) или исходных
|
|
195
|
+
байтов UTF-8 до разбора (`InvalidUtf8`). Tree-sitter
|
|
196
|
+
строит синтаксическое дерево для редакторов и не заменяет
|
|
197
|
+
семантическую проверку эталонного Rust-парсера.
|
|
175
198
|
|
|
176
199
|
## Лицензия
|
|
177
200
|
|
|
178
|
-
MIT OR Apache-2.0
|
|
201
|
+
Двойная лицензия — **MIT OR Apache-2.0**; см.
|
|
202
|
+
[LICENSE-MIT](LICENSE-MIT) и [LICENSE-APACHE](LICENSE-APACHE).
|
|
179
203
|
|
|
180
204
|
## Другие репозитории Ktav
|
|
181
205
|
|
package/README.zh.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> 面向 [Ktav (כְּתָב)](https://github.com/ktav-lang/spec)(书面配置
|
|
4
4
|
> 格式)的 [tree-sitter](https://tree-sitter.github.io/) 语法。
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
**Languages:** [English](README.md) · [Русский](README.ru.md) · **简体中文**
|
|
7
7
|
|
|
8
8
|
**演练场:** 在浏览器中互转 JSON / YAML / TOML / INI ⇄ Ktav — **[ktav-lang.github.io](https://ktav-lang.github.io/)**。
|
|
9
9
|
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
## 什么是 Ktav?
|
|
19
19
|
|
|
20
20
|
Ktav(希伯来语 **כְּתָב**,"书写")是一种纯文本配置格式。形态与
|
|
21
|
-
JSON 相同(标量、数组、对象、`null
|
|
22
|
-
|
|
21
|
+
JSON 相同(标量、数组、对象、`null`、布尔值),但字符串不加引号;
|
|
22
|
+
普通条目之间不使用逗号(内联复合结构中会使用逗号),并使用点式键
|
|
23
|
+
(`server.port: 8080`)表示嵌套。完整规范——所有官
|
|
23
24
|
方 Ktav 实现共同遵循的——在
|
|
24
25
|
[`ktav-lang/spec`](https://github.com/ktav-lang/spec) 仓库中。
|
|
25
26
|
|
|
@@ -32,12 +33,12 @@ JSON 相同(标量、数组、对象、`null`、布尔值),但字符串无
|
|
|
32
33
|
|
|
33
34
|
## 安装
|
|
34
35
|
|
|
35
|
-
### Rust
|
|
36
|
+
### Rust(`tree-sitter` crate)
|
|
36
37
|
|
|
37
38
|
```toml
|
|
38
39
|
[dependencies]
|
|
39
|
-
tree-sitter
|
|
40
|
-
tree-sitter-ktav
|
|
40
|
+
tree-sitter = "0.25"
|
|
41
|
+
tree-sitter-ktav = "0.8.0"
|
|
41
42
|
```
|
|
42
43
|
|
|
43
44
|
```rust
|
|
@@ -52,7 +53,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
52
53
|
}
|
|
53
54
|
```
|
|
54
55
|
|
|
55
|
-
### Node.js
|
|
56
|
+
### Node.js(`tree-sitter` 包)
|
|
57
|
+
|
|
58
|
+
npm 包提供原生源码,而不是预编译的 `.node` 二进制文件。
|
|
59
|
+
安装需要 C/C++ 编译工具链及供 `node-gyp` 使用的 Python;
|
|
60
|
+
包已包含生成的解析器,因此无需 Tree-sitter CLI。
|
|
56
61
|
|
|
57
62
|
```bash
|
|
58
63
|
npm install tree-sitter tree-sitter-ktav
|
|
@@ -73,25 +78,32 @@ console.log(tree.rootNode.toString());
|
|
|
73
78
|
|
|
74
79
|
### Neovim(搭配 [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
|
|
75
80
|
|
|
76
|
-
|
|
81
|
+
当前 `nvim-treesitter` 主分支已不再使用旧的
|
|
82
|
+
`get_parser_configs()` 注册 API。请从语法仓库构建解析器库,再通过
|
|
83
|
+
Neovim 的 Tree-sitter API 加载。构建此语法时,CLI 会自动包含
|
|
84
|
+
`src/scanner.c`:
|
|
77
85
|
|
|
78
86
|
```lua
|
|
79
|
-
require("nvim-treesitter
|
|
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
|
-
|
|
87
|
+
require("nvim-treesitter").setup({})
|
|
88
88
|
vim.filetype.add({ extension = { ktav = "ktav" } })
|
|
89
|
+
vim.treesitter.language.add("ktav", {
|
|
90
|
+
path = vim.fn.stdpath("data") .. "/site/parser/ktav.so",
|
|
91
|
+
})
|
|
92
|
+
vim.api.nvim_create_autocmd("FileType", {
|
|
93
|
+
pattern = "ktav",
|
|
94
|
+
callback = function() vim.treesitter.start() end,
|
|
95
|
+
})
|
|
89
96
|
```
|
|
90
97
|
|
|
91
|
-
|
|
92
|
-
`
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
先创建目标 `parser` 目录。例如,在 Unix 上运行
|
|
99
|
+
`mkdir -p ~/.local/share/nvim/site/parser`,然后在语法仓库中执行
|
|
100
|
+
`npx tree-sitter build --output
|
|
101
|
+
~/.local/share/nvim/site/parser/ktav.so`。此目录和 `.so` 扩展名是 Unix
|
|
102
|
+
示例;请按平台使用 `stdpath("data")` 对应的路径及共享库扩展名(例如
|
|
103
|
+
Windows 上的 `.dll`),并同时更新构建命令和 Lua 配置。若显式列出源文件,
|
|
104
|
+
请同时包含 `src/parser.c` 和 `src/scanner.c`。将 `queries/highlights.scm`、
|
|
105
|
+
`queries/locals.scm` 和 `queries/injections.scm` 复制到
|
|
106
|
+
`~/.config/nvim/queries/ktav/`。
|
|
95
107
|
|
|
96
108
|
### Helix
|
|
97
109
|
|
|
@@ -103,7 +115,7 @@ name = "ktav"
|
|
|
103
115
|
scope = "source.ktav"
|
|
104
116
|
file-types = ["ktav"]
|
|
105
117
|
roots = []
|
|
106
|
-
comment-token = "
|
|
118
|
+
comment-token = "##"
|
|
107
119
|
indent = { tab-width = 4, unit = " " }
|
|
108
120
|
|
|
109
121
|
[[grammar]]
|
|
@@ -121,38 +133,47 @@ tree-sitter 的编辑器都可以在解析器构建后直接使用。
|
|
|
121
133
|
|
|
122
134
|
## 节点类型
|
|
123
135
|
|
|
124
|
-
|
|
136
|
+
以下是 CST(参见 `src/node-types.json`)中的代表性命名节点:
|
|
125
137
|
|
|
126
138
|
| 节点 | 捕获内容 |
|
|
127
139
|
|---------------------------|-----------------------------------------------|
|
|
128
140
|
| `source_file` | 整个文档 |
|
|
129
|
-
| `comment` |
|
|
141
|
+
| `comment` | `##` 行注释 |
|
|
130
142
|
| `blank_line` | 空行 |
|
|
131
143
|
| `object_pair` | `key SEP value` 行 |
|
|
132
|
-
| `key` / `dotted_key` |
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
144
|
+
| `key` / `dotted_key` | 键及其点分段 |
|
|
145
|
+
| `quoted_key_segment` | `"…"`、`'…'` 或 `` `…` `` 形式的键段(§ 5.3.3) |
|
|
146
|
+
| `escape_sequence` | 键或内联值中的转义(§ 3.7) |
|
|
147
|
+
| `sep_string` / `sep_raw` | 键值对分隔符 `:` 和 `::` |
|
|
148
|
+
| `keyword` / `kw_null` / `kw_true` / `kw_false` | 关键字(整行值与内联值) |
|
|
149
|
+
| `integer` / `float` | 数值(整行值与内联值,按 § 5.2 推断) |
|
|
150
|
+
| `scalar` / `raw_scalar` | 普通及 raw 单行值 |
|
|
151
|
+
| `top_scalar` | 顶层数组中的字符串条目 |
|
|
152
|
+
| `inline_scalar` / `inline_raw_scalar` | 内联结构中 `:` / `::` 之后的字符串值 |
|
|
136
153
|
| `compound_object` | `{` … `}` 块 |
|
|
137
154
|
| `compound_array` | `[` … `]` 块 |
|
|
138
|
-
| `
|
|
155
|
+
| `inline_object` / `inline_array` | 内联结构及其逗号分隔的条目 |
|
|
156
|
+
| `inline_pair` / `inline_value` | 内联结构中的键值对和值 |
|
|
157
|
+
| `array_item` / `top_array_item` | 复合数组和顶层数组中的条目 |
|
|
139
158
|
| `multiline_stripped` | `(` … `)` 块 |
|
|
140
159
|
| `multiline_verbatim` | `((` … `))` 块 |
|
|
141
160
|
| `multiline_content_line` | 多行字符串内的单行 |
|
|
142
161
|
| `empty_object` / `empty_array` / `empty_paren` / `empty_double_paren` | 内联空形式 |
|
|
143
|
-
| `empty_value` |
|
|
162
|
+
| `empty_value` | 分隔符后接最长的允许空白序列,直到行尾或真正的文件末尾 |
|
|
144
163
|
|
|
145
|
-
`object_pair` 暴露字段 `key`、`separator`、`value
|
|
146
|
-
|
|
164
|
+
`object_pair` 和 `inline_pair` 暴露字段 `key`、`separator`、`value`
|
|
165
|
+
(`inline_pair.value` 可选);`array_item` 与 `top_array_item` 暴露必需的
|
|
166
|
+
`value` 和可选的 `marker`。
|
|
147
167
|
|
|
148
168
|
## 从源码构建
|
|
149
169
|
|
|
150
170
|
```bash
|
|
151
|
-
git clone https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
171
|
+
git clone --recurse-submodules https://github.com/ktav-lang/tree-sitter-ktav.git
|
|
152
172
|
cd tree-sitter-ktav
|
|
153
|
-
npm
|
|
154
|
-
npx tree-sitter generate #
|
|
155
|
-
npx tree-sitter test #
|
|
173
|
+
npm ci # 安装 lock 文件固定的 tree-sitter-cli 0.26.8
|
|
174
|
+
npx tree-sitter generate # 重新生成 src/parser.c 等文件
|
|
175
|
+
npx tree-sitter test # 运行 tree-sitter 语料库
|
|
176
|
+
cargo test # 运行 Rust 测试,包括规范一致性测试
|
|
156
177
|
```
|
|
157
178
|
|
|
158
179
|
`src/parser.c`、`src/grammar.json`、`src/node-types.json` 与
|
|
@@ -161,15 +182,17 @@ CLI 即可构建。
|
|
|
161
182
|
|
|
162
183
|
## 状态
|
|
163
184
|
|
|
164
|
-
`0.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
185
|
+
`0.8.0` — 面向 [Ktav 0.8.0](https://github.com/ktav-lang/spec/blob/main/versions/0.8/spec.md) 语法的 Tree-sitter 语法包。
|
|
186
|
+
语法可无错误地解析所有固定的 spec 0.8 有效样例,并将每个根
|
|
187
|
+
Object/Array 与 JSON 预期结果核对。除需验证键的错误(`DuplicateKey`、
|
|
188
|
+
`KeyPathConflict`)或解析前检查原始 UTF-8 字节的错误(`InvalidUtf8`)外,
|
|
189
|
+
每个无效样例都会产生语法错误。
|
|
190
|
+
Tree-sitter 为编辑器构建语法树,不代替参考 Rust 解析器的语义校验。
|
|
169
191
|
|
|
170
192
|
## 许可证
|
|
171
193
|
|
|
172
|
-
MIT OR Apache-2.0
|
|
194
|
+
基于 **MIT OR Apache-2.0** 双重许可 —— 详见
|
|
195
|
+
[LICENSE-MIT](LICENSE-MIT) 与 [LICENSE-APACHE](LICENSE-APACHE)。
|
|
173
196
|
|
|
174
197
|
## 其他 Ktav 仓库
|
|
175
198
|
|