tree-sitter-ktav 0.6.0 → 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 CHANGED
@@ -6,8 +6,12 @@
6
6
 
7
7
  **Languages:** **English** · [Русский](README.ru.md) · [简体中文](README.zh.md)
8
8
 
9
- [![CI](https://github.com/ktav-lang/tree-sitter-ktav/actions/workflows/ci.yml/badge.svg)](https://github.com/ktav-lang/tree-sitter-ktav/actions/workflows/ci.yml)
10
- [![crates.io](https://img.shields.io/crates/v/tree-sitter-ktav.svg)](https://crates.io/crates/tree-sitter-ktav)
9
+ **Playground:** convert JSON / YAML / TOML / INI ⇄ Ktav in your browser at **[ktav-lang.github.io](https://ktav-lang.github.io/)**.
10
+
11
+ [![Crates.io](https://img.shields.io/crates/v/tree-sitter-ktav?style=flat-square&logo=rust&label=crates.io)](https://crates.io/crates/tree-sitter-ktav)
12
+ [![CI](https://img.shields.io/github/actions/workflow/status/ktav-lang/tree-sitter-ktav/ci.yml?style=flat-square&logo=github&label=CI)](https://github.com/ktav-lang/tree-sitter-ktav/actions)
13
+ ![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue?style=flat-square)
14
+ [![Playground](https://img.shields.io/badge/playground-try%20online-7c3aed?style=flat-square&logo=rocket&logoColor=white)](https://ktav-lang.github.io/)
11
15
  [![npm](https://img.shields.io/npm/v/tree-sitter-ktav.svg)](https://www.npmjs.com/package/tree-sitter-ktav)
12
16
 
13
17
  ---
@@ -15,9 +19,10 @@
15
19
  ## What is Ktav?
16
20
 
17
21
  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
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
21
26
  one all official Ktav implementations target — lives in the
22
27
  [`ktav-lang/spec`](https://github.com/ktav-lang/spec) repository.
23
28
 
@@ -37,7 +42,7 @@ this crate / npm package is the one for Ktav.
37
42
  ```toml
38
43
  [dependencies]
39
44
  tree-sitter = "0.25"
40
- tree-sitter-ktav = "0.1"
45
+ tree-sitter-ktav = "0.8.0"
41
46
  ```
42
47
 
43
48
  ```rust
@@ -45,7 +50,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
45
50
  let mut parser = tree_sitter::Parser::new();
46
51
  parser.set_language(&tree_sitter_ktav::LANGUAGE.into())?;
47
52
 
48
- let source = "name: Russia\nport:i 8080\n";
53
+ let source = "name: Russia\nport: 8080\n";
49
54
  let tree = parser.parse(source, None).unwrap();
50
55
  println!("{}", tree.root_node().to_sexp());
51
56
  Ok(())
@@ -54,6 +59,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
54
59
 
55
60
  ### Node.js (`tree-sitter` package)
56
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
+
57
66
  ```bash
58
67
  npm install tree-sitter tree-sitter-ktav
59
68
  ```
@@ -65,7 +74,7 @@ const Ktav = require("tree-sitter-ktav");
65
74
  const parser = new Parser();
66
75
  parser.setLanguage(Ktav);
67
76
 
68
- const tree = parser.parse("name: Russia\nport:i 8080\n");
77
+ const tree = parser.parse("name: Russia\nport: 8080\n");
69
78
  console.log(tree.rootNode.toString());
70
79
  ```
71
80
 
@@ -73,25 +82,33 @@ console.log(tree.rootNode.toString());
73
82
 
74
83
  ### Neovim (with [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
75
84
 
76
- Until the grammar is upstreamed, register it manually in your config:
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:
77
89
 
78
90
  ```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
-
91
+ require("nvim-treesitter").setup({})
88
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
+ })
89
100
  ```
90
101
 
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).
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/`.
95
112
 
96
113
  ### Helix
97
114
 
@@ -103,7 +120,7 @@ name = "ktav"
103
120
  scope = "source.ktav"
104
121
  file-types = ["ktav"]
105
122
  roots = []
106
- comment-token = "#"
123
+ comment-token = "##"
107
124
  indent = { tab-width = 4, unit = " " }
108
125
 
109
126
  [[grammar]]
@@ -121,38 +138,47 @@ with tree-sitter support can consume it once the parser is built.
121
138
 
122
139
  ## Node types
123
140
 
124
- The grammar produces the following named nodes:
141
+ Representative named nodes from the CST (`src/node-types.json`) include:
125
142
 
126
143
  | Node | What it captures |
127
144
  |----------------------------|-------------------------------------------------|
128
145
  | `source_file` | the whole document |
129
- | `comment` | a `#`-line comment |
146
+ | `comment` | a `##`-line comment |
130
147
  | `blank_line` | an empty line |
131
148
  | `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 |
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 |
136
158
  | `compound_object` | `{` … `}` block |
137
159
  | `compound_array` | `[` … `]` block |
138
- | `array_item` | a single item in an array |
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 |
139
163
  | `multiline_stripped` | `(` … `)` block |
140
164
  | `multiline_verbatim` | `((` … `))` block |
141
165
  | `multiline_content_line` | a single line inside a multi-line string |
142
166
  | `empty_object` / `empty_array` / `empty_paren` / `empty_double_paren` | inline empty forms |
143
- | `empty_value` | separator immediately followed by EOL |
167
+ | `empty_value` | separator plus the maximal allowed whitespace run through EOL or true EOF |
144
168
 
145
- `object_pair` exposes `key`, `separator`, and `value` as fields;
146
- `array_item` exposes `marker` (optional) and `value`.
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`.
147
172
 
148
173
  ## Building from source
149
174
 
150
175
  ```bash
151
- 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
152
177
  cd tree-sitter-ktav
153
- npm install
154
- npx tree-sitter generate # writes src/parser.c
155
- 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
156
182
  ```
157
183
 
158
184
  The generated `src/parser.c`, `src/grammar.json`, `src/node-types.json`,
@@ -161,13 +187,14 @@ so consumers do not need the CLI to build.
161
187
 
162
188
  ## Status
163
189
 
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).
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.
171
198
 
172
199
  ## License
173
200
 
package/README.ru.md CHANGED
@@ -1,13 +1,17 @@
1
1
  # tree-sitter-ktav
2
2
 
3
3
  > Грамматика [tree-sitter](https://tree-sitter.github.io/) для
4
- > [Ktav (כְּתָב)](https://github.com/ktav-lang/spec) — Written
5
- > Configuration Format.
4
+ > [Ktav (כְּתָב)](https://github.com/ktav-lang/spec) — формата
5
+ > письменной конфигурации.
6
6
 
7
- **Языки:** [English](README.md) · **Русский** · [简体中文](README.zh.md)
7
+ **Languages:** [English](README.md) · **Русский** · [简体中文](README.zh.md)
8
8
 
9
- [![CI](https://github.com/ktav-lang/tree-sitter-ktav/actions/workflows/ci.yml/badge.svg)](https://github.com/ktav-lang/tree-sitter-ktav/actions/workflows/ci.yml)
10
- [![crates.io](https://img.shields.io/crates/v/tree-sitter-ktav.svg)](https://crates.io/crates/tree-sitter-ktav)
9
+ **Песочница:** конвертация JSON / YAML / TOML / INI ⇄ Ktav прямо в браузере — **[ktav-lang.github.io](https://ktav-lang.github.io/)**.
10
+
11
+ [![Crates.io](https://img.shields.io/crates/v/tree-sitter-ktav?style=flat-square&logo=rust&label=crates.io)](https://crates.io/crates/tree-sitter-ktav)
12
+ [![CI](https://img.shields.io/github/actions/workflow/status/ktav-lang/tree-sitter-ktav/ci.yml?style=flat-square&logo=github&label=CI)](https://github.com/ktav-lang/tree-sitter-ktav/actions)
13
+ ![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue?style=flat-square)
14
+ [![Playground](https://img.shields.io/badge/playground-try%20online-7c3aed?style=flat-square&logo=rocket&logoColor=white)](https://ktav-lang.github.io/)
11
15
  [![npm](https://img.shields.io/npm/v/tree-sitter-ktav.svg)](https://www.npmjs.com/package/tree-sitter-ktav)
12
16
 
13
17
  ---
@@ -16,8 +20,9 @@
16
20
 
17
21
  Ktav (иврит **כְּתָב**, «писание») — текстовый формат конфигурации
18
22
  JSON-формы (скаляры, массивы, объекты, `null`, булево), но без кавычек
19
- вокруг строк, без запятых, с точечными ключами (`server.port: 8080`)
20
- для вложенности. Полная спецификация (та же, на которую ориентируются
23
+ вокруг строк; между обычными элементами запятых нет, однако в inline-
24
+ структурах они используются. Для вложенности служат точечные ключи
25
+ (`server.port: 8080`). Полная спецификация (та же, на которую ориентируются
21
26
  все официальные реализации Ktav) лежит в
22
27
  [`ktav-lang/spec`](https://github.com/ktav-lang/spec).
23
28
 
@@ -32,12 +37,12 @@ VS Code, Zed, …) используют его для подсветки син
32
37
 
33
38
  ## Установка
34
39
 
35
- ### Rust
40
+ ### Rust (крейт `tree-sitter`)
36
41
 
37
42
  ```toml
38
43
  [dependencies]
39
- tree-sitter = "0.25"
40
- tree-sitter-ktav = "0.1"
44
+ tree-sitter = "0.25"
45
+ tree-sitter-ktav = "0.8.0"
41
46
  ```
42
47
 
43
48
  ```rust
@@ -45,14 +50,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
45
50
  let mut parser = tree_sitter::Parser::new();
46
51
  parser.set_language(&tree_sitter_ktav::LANGUAGE.into())?;
47
52
 
48
- let source = "name: Russia\nport:i 8080\n";
53
+ let source = "name: Russia\nport: 8080\n";
49
54
  let tree = parser.parse(source, None).unwrap();
50
55
  println!("{}", tree.root_node().to_sexp());
51
56
  Ok(())
52
57
  }
53
58
  ```
54
59
 
55
- ### Node.js
60
+ ### Node.js (пакет `tree-sitter`)
61
+
62
+ Пакет npm содержит исходники нативного модуля, а не готовые `.node`-бинарники.
63
+ Для установки нужны компилятор C/C++ и Python для `node-gyp`;
64
+ сгенерированный парсер уже включён, поэтому Tree-sitter CLI не нужен.
56
65
 
57
66
  ```bash
58
67
  npm install tree-sitter tree-sitter-ktav
@@ -65,33 +74,41 @@ const Ktav = require("tree-sitter-ktav");
65
74
  const parser = new Parser();
66
75
  parser.setLanguage(Ktav);
67
76
 
68
- const tree = parser.parse("name: Russia\nport:i 8080\n");
77
+ const tree = parser.parse("name: Russia\nport: 8080\n");
69
78
  console.log(tree.rootNode.toString());
70
79
  ```
71
80
 
72
81
  ## Интеграция с редакторами
73
82
 
74
- ### Neovim (через [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
83
+ ### Neovim (с [`nvim-treesitter`](https://github.com/nvim-treesitter/nvim-treesitter))
75
84
 
76
- Пока грамматика не зарегистрирована в апстриме, добавьте вручную:
85
+ В текущей основной ветке `nvim-treesitter` больше не используется устаревший
86
+ API регистрации `get_parser_configs()`. Соберите библиотеку парсера из
87
+ репозитория грамматики и загрузите её через Tree-sitter API Neovim. CLI
88
+ автоматически включает `src/scanner.c` при сборке этой грамматики:
77
89
 
78
90
  ```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
-
91
+ require("nvim-treesitter").setup({})
88
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
+ })
89
100
  ```
90
101
 
91
- Затем `:TSInstall ktav`. Положите `queries/highlights.scm`,
92
- `queries/locals.scm` и `queries/injections.scm` в
93
- `~/.config/nvim/queries/ktav/` (либо позвольте `nvim-treesitter`
94
- подобрать их из репозитория грамматики).
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/`.
95
112
 
96
113
  ### Helix
97
114
 
@@ -103,7 +120,7 @@ name = "ktav"
103
120
  scope = "source.ktav"
104
121
  file-types = ["ktav"]
105
122
  roots = []
106
- comment-token = "#"
123
+ comment-token = "##"
107
124
  indent = { tab-width = 4, unit = " " }
108
125
 
109
126
  [[grammar]]
@@ -119,40 +136,49 @@ source = { git = "https://github.com/ktav-lang/tree-sitter-ktav", rev = "main" }
119
136
  (`src/node-types.json`) и запросы (`queries/*.scm`), так что любой
120
137
  редактор с поддержкой tree-sitter сможет с ней работать.
121
138
 
122
- ## Узлы AST
139
+ ## Типы узлов CST
123
140
 
124
- Грамматика генерирует следующие именованные узлы:
141
+ Примеры именованных узлов CST (см. `src/node-types.json`):
125
142
 
126
143
  | Узел | Что захватывает |
127
144
  |----------------------------|--------------------------------------------------|
128
145
  | `source_file` | весь документ |
129
- | `comment` | строковый комментарий `#` |
146
+ | `comment` | строковый комментарий `##` |
130
147
  | `blank_line` | пустую строку |
131
148
  | `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` | универсальное однострочное значение |
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-структурах |
136
158
  | `compound_object` | блок `{` … `}` |
137
159
  | `compound_array` | блок `[` … `]` |
138
- | `array_item` | элемент массива |
160
+ | `inline_object` / `inline_array` | inline-структуры с элементами через запятую |
161
+ | `inline_pair` / `inline_value` | пары и значения inline-структур |
162
+ | `array_item` / `top_array_item` | элементы массива и массива верхнего уровня |
139
163
  | `multiline_stripped` | блок `(` … `)` |
140
164
  | `multiline_verbatim` | блок `((` … `))` |
141
165
  | `multiline_content_line` | строка внутри многострочного значения |
142
166
  | `empty_object` / `empty_array` / `empty_paren` / `empty_double_paren` | пустые inline-формы |
143
- | `empty_value` | разделитель сразу за концом строки |
167
+ | `empty_value` | разделитель и максимальная последовательность допустимых пробелов до конца строки или файла |
144
168
 
145
- `object_pair` экспонирует поля `key`, `separator`, `value`;
146
- `array_item` — `marker` (опционально) и `value`.
169
+ `object_pair` и `inline_pair` имеют поля `key`, `separator`, `value`
170
+ (`inline_pair.value` необязательно); `array_item` и `top_array_item` имеют
171
+ обязательное `value` и необязательное `marker`.
147
172
 
148
173
  ## Сборка из исходников
149
174
 
150
175
  ```bash
151
- 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
152
177
  cd tree-sitter-ktav
153
- npm install
154
- npx tree-sitter generate # генерирует src/parser.c
155
- 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, включая проверку соответствия спекам
156
182
  ```
157
183
 
158
184
  Файлы `src/parser.c`, `src/grammar.json`, `src/node-types.json` и
@@ -161,17 +187,19 @@ npx tree-sitter test # запускает корпус
161
187
 
162
188
  ## Статус
163
189
 
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).
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-парсера.
171
198
 
172
199
  ## Лицензия
173
200
 
174
- MIT OR Apache-2.0. См. [LICENSE-MIT](LICENSE-MIT) и [LICENSE-APACHE](LICENSE-APACHE).
201
+ Двойная лицензия — **MIT OR Apache-2.0**; см.
202
+ [LICENSE-MIT](LICENSE-MIT) и [LICENSE-APACHE](LICENSE-APACHE).
175
203
 
176
204
  ## Другие репозитории Ktav
177
205