tree-sitter-kdl 1.0.3 → 2.0.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/LICENSE +1 -1
- package/README.md +3 -2
- package/binding.gyp +22 -6
- package/bindings/node/binding.cc +12 -23
- package/bindings/node/index.d.ts +60 -0
- package/bindings/node/index.js +33 -15
- package/grammar.js +193 -170
- package/package.json +48 -31
- package/prebuilds/darwin-arm64/tree-sitter-kdl.node +0 -0
- package/prebuilds/darwin-x64/tree-sitter-kdl.node +0 -0
- package/prebuilds/linux-arm64/tree-sitter-kdl.node +0 -0
- package/prebuilds/linux-x64/tree-sitter-kdl.node +0 -0
- package/prebuilds/win32-arm64/tree-sitter-kdl.node +0 -0
- package/prebuilds/win32-x64/tree-sitter-kdl.node +0 -0
- package/queries/highlights.scm +37 -17
- package/queries/indents.scm +1 -1
- package/queries/injections.scm +10 -0
- package/queries/locals.scm +3 -3
- package/src/grammar.json +744 -761
- package/src/node-types.json +271 -238
- package/src/parser.c +12895 -11901
- package/src/scanner.c +161 -53
- package/src/tree_sitter/alloc.h +54 -0
- package/src/tree_sitter/array.h +336 -0
- package/src/tree_sitter/parser.h +79 -17
- package/tree-sitter-kdl.wasm +0 -0
- package/tree-sitter.json +44 -0
- package/.eslintrc.js +0 -20
- package/.gitattributes +0 -7
- package/.github/workflows/ci.yml +0 -34
- package/.github/workflows/fuzz.yml +0 -21
- package/.github/workflows/lint.yml +0 -19
- package/.github/workflows/publish.yml +0 -51
- package/Cargo.toml +0 -27
- package/Package.swift +0 -38
- package/bindings/rust/README.md +0 -36
- package/bindings/rust/build.rs +0 -19
- package/bindings/rust/lib.rs +0 -68
- package/bindings/swift/kdl.h +0 -16
package/grammar.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file KDL grammar for tree-sitter
|
|
3
|
-
* @author Amaan Qureshi <
|
|
3
|
+
* @author Amaan Qureshi <contact@amaanq.com>
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @see {@link https://kdl.dev|official website}
|
|
6
|
-
* @see {@link https://github.com/kdl-org/kdl/blob/
|
|
6
|
+
* @see {@link https://github.com/kdl-org/kdl/blob/1.0.0/SPEC.md|KDL 1 syntax spec}
|
|
7
|
+
* @see {@link https://github.com/kdl-org/kdl/blob/2.0.0/SPEC.md|KDL 2 syntax spec}
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
// deno-lint-ignore-file no-control-regex
|
|
@@ -13,56 +14,75 @@
|
|
|
13
14
|
/// <reference types="tree-sitter-cli/dsl" />
|
|
14
15
|
// @ts-check
|
|
15
16
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
'
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
17
|
+
const BOOLEAN_KEYWORDS = ['true', 'false', '#true', '#false'];
|
|
18
|
+
const NULL_KEYWORDS = ['null', '#null'];
|
|
19
|
+
const KEYWORD_NUMBERS = ['#inf', '#-inf', '#nan'];
|
|
20
|
+
const UNICODE_SPACES = '\\u0009\\u0020\\u00A0\\u1680\\u2000-\\u200A\\u202F\\u205F\\u3000';
|
|
21
|
+
const NEWLINES = '\\r\\n\\u0085\\u000B\\u000C\\u2028\\u2029';
|
|
22
|
+
const DISALLOWED_LITERAL =
|
|
23
|
+
'\\u0000-\\u0008\\u000E-\\u001F\\u007F\\u200E\\u200F\\u202A-\\u202E\\u2066-\\u2069\\uFEFF';
|
|
24
|
+
const IDENTIFIER_EXCLUSIONS = `${UNICODE_SPACES}${NEWLINES}${DISALLOWED_LITERAL}\\\\\\/(){};\\[\\]"=`;
|
|
25
|
+
const IDENTIFIER_CHAR = `[^${IDENTIFIER_EXCLUSIONS}]`;
|
|
26
|
+
const IDENTIFIER_START = `[^${IDENTIFIER_EXCLUSIONS}0-9+\\-]`;
|
|
27
|
+
const IDENTIFIER_START_AFTER_SIGN = `[^${IDENTIFIER_EXCLUSIONS}0-9]`;
|
|
28
|
+
const STRING_CHAR = `[^"\\\\${DISALLOWED_LITERAL}]`;
|
|
29
|
+
const SIGN = '[+-]';
|
|
30
|
+
// integer := digit (digit | '_')*
|
|
31
|
+
const DIGITS = '[0-9][0-9_]*';
|
|
32
|
+
// hex-unicode := hex-digit{1, 6} - surrogate - above-max-scalar
|
|
33
|
+
const HEX_CHARS = '0-9a-fA-F';
|
|
34
|
+
const HEX = `[${HEX_CHARS}]`;
|
|
35
|
+
const NON_SURROGATE_4 = `(?:[0-9a-cA-Ce-fE-F]${HEX}{3}|[dD][0-7]${HEX}{2})`;
|
|
36
|
+
const SCALAR_5 = `(?:[1-9a-fA-F]${HEX}{4}|0${NON_SURROGATE_4})`;
|
|
37
|
+
const SCALAR_6 = `(?:0${SCALAR_5}|10${HEX}{4})`;
|
|
38
|
+
const UNICODE_SCALAR_ESCAPE = new RegExp(
|
|
39
|
+
`u\\{(?:${HEX}{1,3}|${NON_SURROGATE_4}|${SCALAR_5}|${SCALAR_6})\\}`,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* nodes := line-space* (node line-space*)*
|
|
44
|
+
*
|
|
45
|
+
* @param {GrammarSymbols<string>} $
|
|
46
|
+
* @returns {SeqRule}
|
|
47
|
+
*/
|
|
48
|
+
function linespacedNodes($) {
|
|
49
|
+
return seq(
|
|
50
|
+
repeat($._linespace),
|
|
51
|
+
repeat(seq($.node, repeat($._linespace))),
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* (node-space* slashdash node-children)* (node-space* node-children)?
|
|
57
|
+
* (node-space* slashdash node-children)*
|
|
58
|
+
*
|
|
59
|
+
* Written with the trailing slashdashes nested inside the optional block, since
|
|
60
|
+
* the flat spelling cannot say which repeat owns them when the block is absent.
|
|
61
|
+
*
|
|
62
|
+
* @param {GrammarSymbols<string>} $
|
|
63
|
+
* @returns {SeqRule}
|
|
64
|
+
*/
|
|
65
|
+
function childBlocks($) {
|
|
66
|
+
const commented = seq(repeat($._node_space), field('children', $.node_children_comment));
|
|
67
|
+
const block = seq(repeat($._node_space), field('children', $.node_children));
|
|
68
|
+
return seq(repeat(commented), optional(seq(block, repeat(commented))));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default grammar({
|
|
57
72
|
name: 'kdl',
|
|
58
73
|
|
|
59
74
|
conflicts: $ => [
|
|
60
|
-
[$.
|
|
61
|
-
[$.
|
|
62
|
-
[$.node_children],
|
|
75
|
+
[$.version, $._ws],
|
|
76
|
+
[$.identifier, $.value],
|
|
63
77
|
],
|
|
64
78
|
|
|
65
|
-
externals: $ => [
|
|
79
|
+
externals: $ => [
|
|
80
|
+
$._eof,
|
|
81
|
+
$.multi_line_comment,
|
|
82
|
+
$._raw_string_start,
|
|
83
|
+
$._raw_string_content,
|
|
84
|
+
$._raw_string_end,
|
|
85
|
+
],
|
|
66
86
|
|
|
67
87
|
extras: $ => [$.multi_line_comment],
|
|
68
88
|
|
|
@@ -70,171 +90,174 @@ module.exports = grammar({
|
|
|
70
90
|
|
|
71
91
|
rules: {
|
|
72
92
|
// nodes := linespace* (node nodes?)? linespace*
|
|
73
|
-
document: $ =>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
),
|
|
93
|
+
document: $ => seq(optional($._bom), optional(field('version', $.version)), linespacedNodes($)),
|
|
94
|
+
|
|
95
|
+
version: $ => prec(2, seq(
|
|
96
|
+
'/-',
|
|
97
|
+
repeat($._unicode_space),
|
|
98
|
+
'kdl-version',
|
|
99
|
+
repeat1($._unicode_space),
|
|
100
|
+
field('version', choice('1', '2')),
|
|
101
|
+
repeat($._unicode_space),
|
|
102
|
+
$._newline,
|
|
103
|
+
)),
|
|
85
104
|
|
|
86
105
|
// node := ('/-' node-space*)? type? identifier (node-space+ node-prop-or-arg)* (node-space* node-children ws*)? node-space* node-terminator
|
|
87
|
-
node: $ =>
|
|
106
|
+
node: $ => seq($._base_node, $._node_terminator),
|
|
107
|
+
_final_node: $ => seq(alias($._base_node, $.node), '}'),
|
|
108
|
+
_base_node: $ =>
|
|
88
109
|
seq(
|
|
89
|
-
|
|
90
|
-
optional($.type),
|
|
91
|
-
$.identifier,
|
|
92
|
-
repeat(
|
|
93
|
-
|
|
110
|
+
optional($.node_comment),
|
|
111
|
+
optional(seq(field('type', $.type), repeat($._node_space))),
|
|
112
|
+
field('name', $.identifier),
|
|
113
|
+
repeat($.node_field),
|
|
114
|
+
childBlocks($),
|
|
94
115
|
repeat($._node_space),
|
|
95
|
-
$._node_terminator,
|
|
96
116
|
),
|
|
97
|
-
),
|
|
98
117
|
|
|
99
118
|
// node-prop-or-arg (field) := ('/-' node-space*)? (prop | value)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
_node_field: $ => choice($.prop, $.value),
|
|
119
|
+
node_field: $ => choice(
|
|
120
|
+
seq(repeat1($._node_space), $._node_field),
|
|
121
|
+
seq(repeat($._node_space), $.node_field_comment),
|
|
122
|
+
),
|
|
123
|
+
node_comment: $ => seq('/-', repeat($._linespace)),
|
|
124
|
+
node_field_comment: $ => seq('/-', repeat($._linespace), $._node_field),
|
|
125
|
+
_node_field: $ => choice(field('property', $.prop), field('argument', $.value)),
|
|
108
126
|
// node-children := ('/-' node-space*)? '{' nodes '}'
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
optional(seq($.node, repeat(seq(repeat($._linespace), $.node)))),
|
|
116
|
-
repeat($._linespace),
|
|
117
|
-
),
|
|
118
|
-
'}',
|
|
119
|
-
),
|
|
127
|
+
node_children_comment: $ => seq('/-', repeat($._linespace), $.node_children),
|
|
128
|
+
node_children: $ => seq(
|
|
129
|
+
'{',
|
|
130
|
+
repeat(choice($._linespace, $.node)),
|
|
131
|
+
choice('}', $._final_node),
|
|
132
|
+
),
|
|
120
133
|
// node-space := ws* escline ws* | ws+
|
|
121
|
-
_node_space: $ =>
|
|
122
|
-
choice(
|
|
123
|
-
seq(repeat($._ws), $._escline, repeat($._ws)),
|
|
124
|
-
repeat1($._ws),
|
|
125
|
-
),
|
|
134
|
+
_node_space: $ => choice($._ws, $._escline),
|
|
126
135
|
// node-terminator := single-line-comment | newline | ';' | eof
|
|
127
136
|
_node_terminator: $ =>
|
|
128
137
|
choice($.single_line_comment, $._newline, ';', $._eof),
|
|
129
138
|
|
|
130
139
|
// identifier := string | bare-identifier
|
|
131
140
|
identifier: $ => choice($.string, $._bare_identifier),
|
|
141
|
+
|
|
132
142
|
// bare-identifier := ((identifier-char - digit - sign) identifier-char* | sign ((identifier-char - digit) identifier-char*)?) - keyword
|
|
133
|
-
_bare_identifier: $ =>
|
|
134
|
-
choice(
|
|
135
|
-
$._normal_bare_identifier,
|
|
136
|
-
seq($._sign, optional(seq($.__identifier_char_no_digit, repeat($._identifier_char)))),
|
|
137
|
-
),
|
|
143
|
+
_bare_identifier: $ => choice($._normal_bare_identifier, $._signed_bare_identifier),
|
|
138
144
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
seq(
|
|
142
|
-
/[\u4E00-\u9FFF\p{L}\p{M}\p{N}\p{Emoji}_~!@#\$%\^&\*.:'\|\?&&[^\s\d\/(){}<>;\[\]=,"]]/,
|
|
143
|
-
/[\u4E00-\u9FFF\p{L}\p{M}\p{N}\p{Emoji}\-_~!@#\$%\^&\*.:'\|\?+&&[^\s\/(){}<>;\[\]=,"]]*/,
|
|
144
|
-
),
|
|
145
|
-
),
|
|
146
|
-
// identifier-char := unicode - linespace - [\/(){}<>;[]=,"]
|
|
147
|
-
_identifier_char: _ => token(
|
|
148
|
-
/[\u4E00-\u9FFF\p{L}\p{M}\p{N}\-_~!@#\$%\^&\*.:'\|\?+&&[^\s\/(){}<>;\[\]=,"]]/,
|
|
149
|
-
),
|
|
145
|
+
_normal_bare_identifier: _ =>
|
|
146
|
+
token(new RegExp(`${IDENTIFIER_START}${IDENTIFIER_CHAR}*`)),
|
|
150
147
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
/[\u4E00-\u9FFF\p{L}\p{M}\p{N}\-_~!@#\$%\^&\*.:'\|\?+&&[^\s\d\/(){}<>;\[\]=,"]]/,
|
|
154
|
-
),
|
|
148
|
+
_signed_bare_identifier: _ =>
|
|
149
|
+
token(new RegExp(`${SIGN}(?:${IDENTIFIER_START_AFTER_SIGN}${IDENTIFIER_CHAR}*)?`)),
|
|
155
150
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
151
|
+
keyword: $ => choice($.boolean, ...NULL_KEYWORDS.map(value => token(prec(2, value)))),
|
|
152
|
+
|
|
153
|
+
prop: $ => seq(
|
|
154
|
+
field('key', $.identifier),
|
|
155
|
+
repeat($._node_space),
|
|
156
|
+
'=',
|
|
157
|
+
repeat($._node_space),
|
|
158
|
+
field('value', $.value),
|
|
159
159
|
),
|
|
160
160
|
|
|
161
|
-
// keyword := boolean | 'null'
|
|
162
|
-
keyword: $ => choice($.boolean, 'null'),
|
|
163
|
-
// type annotations
|
|
164
|
-
annotation_type: _ => choice(...ANNOTATION_BUILTINS),
|
|
165
|
-
// prop := identifier '=' value
|
|
166
|
-
prop: $ => seq($.identifier, '=', $.value),
|
|
167
161
|
// value := type? (string | number | keyword)
|
|
168
|
-
value: $ => seq(
|
|
162
|
+
value: $ => seq(
|
|
163
|
+
optional(seq(field('type', $.type), repeat($._node_space))),
|
|
164
|
+
field('value', choice($.string, alias($._bare_identifier, $.string), $.number, $.keyword)),
|
|
165
|
+
),
|
|
166
|
+
|
|
169
167
|
// type := '(' identifier ')'
|
|
170
|
-
type: $ => seq(
|
|
168
|
+
type: $ => seq(
|
|
169
|
+
'(',
|
|
170
|
+
repeat($._node_space),
|
|
171
|
+
field('name', $.identifier),
|
|
172
|
+
repeat($._node_space),
|
|
173
|
+
')',
|
|
174
|
+
),
|
|
171
175
|
|
|
172
176
|
// String
|
|
173
|
-
|
|
174
|
-
string
|
|
177
|
+
string: $ => choice($._raw_string, $.multi_line_string, $._escaped_string),
|
|
178
|
+
// raw-string := '#' raw-string-quotes '#' | '#' raw-string '#'
|
|
179
|
+
_raw_string: $ => seq(
|
|
180
|
+
$._raw_string_start,
|
|
181
|
+
optional(alias($._raw_string_content, $.string_fragment)),
|
|
182
|
+
$._raw_string_end,
|
|
183
|
+
),
|
|
184
|
+
// quoted-string := '"""' newline (multi-line-string-body newline)?
|
|
185
|
+
// (unicode-space | ws-escape)* '"""'
|
|
186
|
+
multi_line_string: $ => seq(
|
|
187
|
+
$._multiline_open,
|
|
188
|
+
repeat(choice(
|
|
189
|
+
alias($._multiline_fragment, $.string_fragment),
|
|
190
|
+
$.escape,
|
|
191
|
+
$.escaped_whitespace,
|
|
192
|
+
)),
|
|
193
|
+
'"""',
|
|
194
|
+
),
|
|
195
|
+
_multiline_open: _ => token(seq('"""', choice('\r\n', new RegExp(`[${NEWLINES}]`)))),
|
|
196
|
+
// multi-line-string-body := ('"' ^'"' | '""' ^'"' | string-character)*?
|
|
197
|
+
_multiline_fragment: _ =>
|
|
198
|
+
token.immediate(new RegExp(`(?:${STRING_CHAR}|"${STRING_CHAR}|""${STRING_CHAR})+`)),
|
|
175
199
|
// escaped-string := '"' character* '"'
|
|
176
|
-
_escaped_string: $ => seq(
|
|
200
|
+
_escaped_string: $ => seq(
|
|
201
|
+
'"',
|
|
202
|
+
repeat(choice(
|
|
203
|
+
alias($._string_fragment, $.string_fragment),
|
|
204
|
+
$.escape,
|
|
205
|
+
$.escaped_whitespace,
|
|
206
|
+
)),
|
|
207
|
+
'"',
|
|
208
|
+
),
|
|
177
209
|
// character := '\' escape | [^\"]
|
|
178
|
-
|
|
179
|
-
// escape := ["\\/
|
|
180
|
-
escape: _ =>
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
choice(
|
|
194
|
-
// raw-string-hash := '#' raw-string-hash '#' | raw-string-quotes
|
|
195
|
-
// yes this isn't perfect but it works, ideally this should be handled in an external scanner
|
|
196
|
-
seq(token.immediate(seq('r', repeat1('#'))), /[^#]*/, repeat1('#')),
|
|
197
|
-
// raw-string-quotes := '"' . '"'
|
|
198
|
-
seq(token.immediate(seq('r', '"')), /[^"]*/, '"'),
|
|
199
|
-
),
|
|
210
|
+
_string_fragment: _ => token.immediate(new RegExp(`${STRING_CHAR}+`)),
|
|
211
|
+
// escape := ["\\/bfnrts] | 'u{' hex-digit{1, 6} '}'
|
|
212
|
+
escape: _ => token.immediate(seq(
|
|
213
|
+
'\\',
|
|
214
|
+
choice(
|
|
215
|
+
'\\',
|
|
216
|
+
'"',
|
|
217
|
+
'/',
|
|
218
|
+
'b',
|
|
219
|
+
'f',
|
|
220
|
+
'n',
|
|
221
|
+
'r',
|
|
222
|
+
't',
|
|
223
|
+
's',
|
|
224
|
+
UNICODE_SCALAR_ESCAPE,
|
|
200
225
|
),
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
226
|
+
)),
|
|
227
|
+
escaped_whitespace: _ => token.immediate(
|
|
228
|
+
/\\(?:\r\n|[\u0009\u0020\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000\r\n\u0085\u000B\u000C\u2028\u2029])+/,
|
|
229
|
+
),
|
|
230
|
+
number: $ => choice($.keyword_number, $._decimal, $._hex, $._octal, $._binary),
|
|
204
231
|
|
|
205
232
|
// decimal := sign? integer ('.' integer)? exponent?
|
|
206
233
|
_decimal: $ =>
|
|
207
234
|
seq(
|
|
208
|
-
optional($._sign),
|
|
209
235
|
$._integer,
|
|
210
|
-
optional(seq('.', alias($.
|
|
236
|
+
optional(seq('.', alias($._fraction, $.decimal))),
|
|
211
237
|
optional(alias($._exponent, $.exponent)),
|
|
212
238
|
),
|
|
213
239
|
|
|
214
|
-
// exponent := ('e' | 'E') sign? integer
|
|
215
|
-
_exponent: $ => seq(choice('e', 'E'), optional($._sign), $._integer),
|
|
216
240
|
// integer := digit (digit | '_')*
|
|
217
|
-
_integer:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
_sign: _ => choice('+', '-'),
|
|
222
|
-
|
|
241
|
+
_integer: _ => token(new RegExp(`${SIGN}?${DIGITS}`)),
|
|
242
|
+
_fraction: _ => token.immediate(new RegExp(DIGITS)),
|
|
243
|
+
// exponent := ('e' | 'E') sign? integer
|
|
244
|
+
_exponent: _ => token.immediate(new RegExp(`[eE]${SIGN}?${DIGITS}`)),
|
|
223
245
|
// hex := sign? '0x' hex-digit (hex-digit | '_')*
|
|
224
|
-
_hex:
|
|
246
|
+
_hex: _ => token(new RegExp(`${SIGN}?0x${HEX}[${HEX_CHARS}_]*`)),
|
|
225
247
|
// octal := sign? '0o' [0-7] [0-7_]*
|
|
226
|
-
_octal:
|
|
248
|
+
_octal: _ => token(new RegExp(`${SIGN}?0o[0-7][0-7_]*`)),
|
|
227
249
|
// binary := sign? '0b' ('0' | '1') ('0' | '1' | '_')*
|
|
228
|
-
_binary:
|
|
250
|
+
_binary: _ => token(new RegExp(`${SIGN}?0b[01][01_]*`)),
|
|
251
|
+
|
|
252
|
+
keyword_number: _ => choice(...KEYWORD_NUMBERS.map(value => token(prec(2, value)))),
|
|
229
253
|
|
|
230
|
-
|
|
231
|
-
boolean: _ => choice('true', 'false'),
|
|
254
|
+
boolean: _ => choice(...BOOLEAN_KEYWORDS.map(value => token(prec(2, value)))),
|
|
232
255
|
|
|
233
256
|
// escline := '\\' ws* (single-line-comment | newline)
|
|
234
|
-
_escline: $ => seq('\\', repeat($._ws), choice($.single_line_comment, $._newline)),
|
|
257
|
+
_escline: $ => seq('\\', repeat($._ws), choice($.single_line_comment, $._newline, $._eof)),
|
|
235
258
|
|
|
236
259
|
// linespace := newline | ws | single-line-comment
|
|
237
|
-
_linespace: $ => choice($.
|
|
260
|
+
_linespace: $ => choice($._ws, $._escline, $._newline, $.single_line_comment),
|
|
238
261
|
|
|
239
262
|
// newline := See Table (All line-break white_space)
|
|
240
263
|
// Newline
|
|
@@ -251,10 +274,10 @@ module.exports = grammar({
|
|
|
251
274
|
// │ PS Paragraph Separator U+2029 │
|
|
252
275
|
// ╰──────────────────────────────────────────────────────────╯
|
|
253
276
|
// Note that for the purpose of new lines, CRLF is considered a single newline.
|
|
254
|
-
_newline: _ => choice(/\r
|
|
277
|
+
_newline: _ => choice(/\r\n/, /\r/, /\n/, /\u0085/, /\u000B/, /\u000C/, /\u2028/, /\u2029/),
|
|
255
278
|
|
|
256
279
|
// ws := bom | unicode-space | multi-line-comment
|
|
257
|
-
_ws: $ => choice($.
|
|
280
|
+
_ws: $ => choice($._unicode_space, $.multi_line_comment),
|
|
258
281
|
|
|
259
282
|
// bom := '\u{FEFF}'
|
|
260
283
|
_bom: _ => /\u{FEFF}/,
|
|
@@ -291,7 +314,7 @@ module.exports = grammar({
|
|
|
291
314
|
single_line_comment: $ =>
|
|
292
315
|
seq(
|
|
293
316
|
'//',
|
|
294
|
-
repeat(/[^\r\n\u0085\u000C\u2028\u2029]/),
|
|
317
|
+
repeat(/[^\r\n\u0085\u000B\u000C\u2028\u2029]/),
|
|
295
318
|
choice($._newline, $._eof),
|
|
296
319
|
),
|
|
297
320
|
},
|
package/package.json
CHANGED
|
@@ -1,46 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tree-sitter-kdl",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "KDL grammar for tree-sitter",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/amaanq/tree-sitter-kdl.git"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"author": {
|
|
12
|
+
"name": "Amaan Qureshi",
|
|
13
|
+
"email": "contact@amaanq.com"
|
|
14
|
+
},
|
|
15
|
+
"contributors": [
|
|
16
|
+
"Andrew Hlynskyi <ahlincq@gmail.com>"
|
|
17
|
+
],
|
|
5
18
|
"main": "bindings/node",
|
|
19
|
+
"types": "bindings/node",
|
|
6
20
|
"keywords": [
|
|
7
|
-
"
|
|
8
|
-
"
|
|
21
|
+
"incremental",
|
|
22
|
+
"parsing",
|
|
23
|
+
"tree-sitter",
|
|
9
24
|
"kdl"
|
|
10
25
|
],
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
"
|
|
26
|
+
"files": [
|
|
27
|
+
"grammar.js",
|
|
28
|
+
"tree-sitter.json",
|
|
29
|
+
"binding.gyp",
|
|
30
|
+
"prebuilds/**",
|
|
31
|
+
"bindings/node/*",
|
|
32
|
+
"queries/*",
|
|
33
|
+
"src/**",
|
|
34
|
+
"*.wasm"
|
|
14
35
|
],
|
|
15
|
-
"license": "MIT",
|
|
16
|
-
"bugs": {
|
|
17
|
-
"url": "https://github.com/amaanq/tree-sitter-kdl/issues"
|
|
18
|
-
},
|
|
19
|
-
"homepage": "https://github.com/amaanq/tree-sitter-kdl#readme",
|
|
20
36
|
"dependencies": {
|
|
21
|
-
"
|
|
37
|
+
"node-addon-api": "^8.5.0",
|
|
38
|
+
"node-gyp-build": "^4.8.4"
|
|
22
39
|
},
|
|
23
40
|
"devDependencies": {
|
|
24
|
-
"eslint": "^
|
|
25
|
-
"eslint-config-
|
|
26
|
-
"
|
|
41
|
+
"eslint": "^9.39.5",
|
|
42
|
+
"eslint-config-treesitter": "^1.0.2",
|
|
43
|
+
"prebuildify": "^6.0.1",
|
|
44
|
+
"tree-sitter": "^0.25.1",
|
|
45
|
+
"tree-sitter-cli": "^0.27.0"
|
|
27
46
|
},
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
"build": "tree-sitter generate && node-gyp build",
|
|
31
|
-
"test": "tree-sitter test && script/parse-examples",
|
|
32
|
-
"parse": "tree-sitter parse",
|
|
33
|
-
"test-windows": "tree-sitter test"
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"tree-sitter": "^0.25.0"
|
|
34
49
|
},
|
|
35
|
-
"
|
|
36
|
-
{
|
|
37
|
-
"
|
|
38
|
-
"file-types": [
|
|
39
|
-
"kdl"
|
|
40
|
-
],
|
|
41
|
-
"highlights": [
|
|
42
|
-
"queries/highlights.scm"
|
|
43
|
-
]
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"tree-sitter": {
|
|
52
|
+
"optional": true
|
|
44
53
|
}
|
|
45
|
-
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"install": "node-gyp-build",
|
|
57
|
+
"lint": "eslint grammar.js",
|
|
58
|
+
"parse": "tree-sitter parse",
|
|
59
|
+
"prestart": "tree-sitter build --wasm",
|
|
60
|
+
"start": "tree-sitter playground",
|
|
61
|
+
"test": "tree-sitter test && script/parse-examples"
|
|
62
|
+
}
|
|
46
63
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/queries/highlights.scm
CHANGED
|
@@ -1,40 +1,59 @@
|
|
|
1
|
-
;
|
|
1
|
+
; Variables
|
|
2
2
|
|
|
3
|
-
(
|
|
3
|
+
(identifier) @variable
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
; Nodes
|
|
6
6
|
|
|
7
|
-
(
|
|
7
|
+
(node name: (identifier) @tag)
|
|
8
|
+
(node name: (identifier (string) @tag))
|
|
8
9
|
|
|
9
|
-
;
|
|
10
|
+
; Types
|
|
10
11
|
|
|
11
|
-
(
|
|
12
|
+
(type) @type
|
|
13
|
+
(type name: (identifier) @type)
|
|
14
|
+
|
|
15
|
+
; Reserved type annotations are advisory in the spec, not syntax.
|
|
16
|
+
((type name: (identifier) @type.builtin)
|
|
17
|
+
(#any-of? @type.builtin
|
|
18
|
+
"i8" "i16" "i32" "i64" "i128"
|
|
19
|
+
"u8" "u16" "u32" "u64" "u128"
|
|
20
|
+
"isize" "usize" "f32" "f64" "decimal64" "decimal128"
|
|
21
|
+
"date-time" "time" "date" "duration" "decimal" "currency"
|
|
22
|
+
"country-2" "country-3" "country-subdivision"
|
|
23
|
+
"email" "idn-email" "hostname" "idn-hostname"
|
|
24
|
+
"ipv4" "ipv6" "url" "url-reference" "irl" "irl-reference"
|
|
25
|
+
"url-template" "uuid" "regex" "base64" "base85"))
|
|
12
26
|
|
|
13
|
-
;
|
|
27
|
+
; Properties
|
|
14
28
|
|
|
15
|
-
(identifier) @
|
|
29
|
+
(prop key: (identifier) @property)
|
|
16
30
|
|
|
17
31
|
; Operators
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"+"
|
|
21
|
-
"-"
|
|
22
|
-
] @operator
|
|
32
|
+
|
|
33
|
+
"=" @operator
|
|
23
34
|
|
|
24
35
|
; Literals
|
|
25
36
|
|
|
26
37
|
(string) @string
|
|
27
38
|
|
|
39
|
+
(multi_line_string) @string
|
|
40
|
+
|
|
41
|
+
(string_fragment) @string
|
|
42
|
+
|
|
28
43
|
(escape) @string.escape
|
|
29
44
|
|
|
45
|
+
(escaped_whitespace) @string.escape
|
|
46
|
+
|
|
30
47
|
(number) @number
|
|
31
48
|
|
|
49
|
+
(keyword_number) @number
|
|
50
|
+
|
|
32
51
|
(number (decimal) @float)
|
|
33
52
|
(number (exponent) @float)
|
|
34
53
|
|
|
35
54
|
(boolean) @boolean
|
|
36
55
|
|
|
37
|
-
"null" @constant.builtin
|
|
56
|
+
[ "null" "#null" ] @constant.builtin
|
|
38
57
|
|
|
39
58
|
; Punctuation
|
|
40
59
|
|
|
@@ -51,8 +70,9 @@
|
|
|
51
70
|
[
|
|
52
71
|
(single_line_comment)
|
|
53
72
|
(multi_line_comment)
|
|
73
|
+
(version)
|
|
54
74
|
] @comment @spell
|
|
55
75
|
|
|
56
|
-
(
|
|
57
|
-
(
|
|
58
|
-
(
|
|
76
|
+
(node_comment) @comment
|
|
77
|
+
(node_field_comment) @comment
|
|
78
|
+
(node_children_comment) @comment
|
package/queries/indents.scm
CHANGED