tree-sitter-dataweave 0.1.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/grammar.js ADDED
@@ -0,0 +1,596 @@
1
+ /**
2
+ * @file DataWeave grammar for tree-sitter
3
+ * @author M. Reifschneider
4
+ * @license MIT
5
+ */
6
+
7
+ /// <reference types="tree-sitter-cli/dsl" />
8
+ // @ts-check
9
+
10
+ const PREC = {
11
+ LAMBDA: 1,
12
+ IF: 2,
13
+ MATCH: 3,
14
+ DEFAULT: 4,
15
+ LOGICAL_OR: 5,
16
+ LOGICAL_AND: 6,
17
+ RELATIONAL: 7,
18
+ EQUALITY: 8,
19
+ INFIX: 9,
20
+ ADD: 10,
21
+ MULTIPLY: 11,
22
+ UNARY: 12,
23
+ AS_IS: 13,
24
+ CALL: 14,
25
+ SELECTOR: 15,
26
+ PRIMARY: 16,
27
+ };
28
+
29
+ export default grammar({
30
+ name: 'dataweave',
31
+
32
+ extras: $ => [
33
+ /\s+/,
34
+ $.line_comment,
35
+ $.block_comment,
36
+ ],
37
+
38
+ conflicts: $ => [
39
+ [$._expression, $.parameter],
40
+ // A conditional key and a typed lambda share the prefix `(name:`.
41
+ [$._object_key, $.lambda_expression],
42
+ ],
43
+
44
+ word: $ => $.identifier,
45
+
46
+ rules: {
47
+ document: $ => choice(
48
+ seq(optional($.header), '---', optional($._expression)),
49
+ $.header,
50
+ $._expression
51
+ ),
52
+
53
+ // --- Comments ---
54
+ line_comment: $ => token(seq('//', /.*/)),
55
+ block_comment: $ => token(seq('/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/')),
56
+
57
+ // --- Header and Directives ---
58
+ header: $ => repeat1($._directive),
59
+
60
+ _directive: $ => choice(
61
+ $.version_directive,
62
+ $.output_directive,
63
+ $.input_directive,
64
+ $.var_directive,
65
+ $.fun_directive,
66
+ $.type_directive,
67
+ $.namespace_directive,
68
+ $.import_directive
69
+ ),
70
+
71
+ version_directive: $ => seq(
72
+ choice('%dw', 'dw'),
73
+ field('version', $.version_number)
74
+ ),
75
+
76
+ version_number: $ => /[0-9]+(\.[0-9]+)*/,
77
+
78
+ output_directive: $ => seq(
79
+ choice('%output', 'output'),
80
+ field('mime_type', $.mime_type),
81
+ repeat($.directive_parameter)
82
+ ),
83
+
84
+ input_directive: $ => seq(
85
+ choice('%input', 'input'),
86
+ field('name', $.identifier),
87
+ field('mime_type', $.mime_type),
88
+ repeat($.directive_parameter)
89
+ ),
90
+
91
+ mime_type: $ => /[a-zA-Z0-9_\.\-]+(\/[a-zA-Z0-9_\.\-\+]+)?/,
92
+
93
+ directive_parameter: $ => seq(
94
+ field('name', $.identifier),
95
+ '=',
96
+ field('value', choice($.string, $.number, $.boolean, $.identifier))
97
+ ),
98
+
99
+ var_directive: $ => seq(
100
+ choice('%var', 'var'),
101
+ field('name', $.identifier),
102
+ '=',
103
+ field('value', $._expression)
104
+ ),
105
+
106
+ fun_directive: $ => seq(
107
+ choice('%fun', '%function', 'fun'),
108
+ field('name', $.identifier),
109
+ '(',
110
+ optional($.parameter_list),
111
+ ')',
112
+ optional(seq(':', field('return_type', $._type))),
113
+ '=',
114
+ field('body', $._expression)
115
+ ),
116
+
117
+ type_directive: $ => seq(
118
+ choice('%type', 'type'),
119
+ field('name', $.identifier),
120
+ '=',
121
+ field('type', $._type)
122
+ ),
123
+
124
+ namespace_directive: $ => seq(
125
+ choice('%ns', '%namespace', 'ns', 'namespace'),
126
+ field('prefix', $.identifier),
127
+ field('uri', choice($.namespace_uri, $.string, $.identifier))
128
+ ),
129
+
130
+ namespace_uri: $ => /[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]+/,
131
+
132
+ qualified_name: $ => seq(
133
+ field('namespace', $.identifier),
134
+ '#',
135
+ field('name', choice($.identifier, $.string))
136
+ ),
137
+
138
+ import_directive: $ => seq(
139
+ choice('%import', 'import'),
140
+ choice(
141
+ seq(
142
+ choice('*', commaSep1($.identifier)),
143
+ 'from',
144
+ field('module', choice($.module_path, $.identifier))
145
+ ),
146
+ field('module', choice($.module_path, $.identifier))
147
+ ),
148
+ optional(seq('as', field('alias', $.identifier)))
149
+ ),
150
+
151
+ module_path: $ => prec.left(seq(
152
+ $.identifier,
153
+ repeat1(seq('::', $.identifier))
154
+ )),
155
+
156
+ parameter_list: $ => seq(
157
+ commaSep1($.parameter),
158
+ optional(',')
159
+ ),
160
+
161
+ parameter: $ => seq(
162
+ field('name', $.identifier),
163
+ optional(seq(':', field('type', $._type))),
164
+ optional(seq('=', field('default', $._expression)))
165
+ ),
166
+
167
+ // --- Types ---
168
+ _type: $ => choice(
169
+ $.type_name,
170
+ $.type_with_parameters,
171
+ $.array_type,
172
+ $.object_type,
173
+ $.union_type,
174
+ $.intersection_type,
175
+ $.parenthesized_type
176
+ ),
177
+
178
+ type_name: $ => choice(
179
+ 'Any',
180
+ 'String',
181
+ 'Number',
182
+ 'Boolean',
183
+ 'Array',
184
+ 'Object',
185
+ 'Date',
186
+ 'DateTime',
187
+ 'Time',
188
+ 'LocalDateTime',
189
+ 'LocalTime',
190
+ 'TimeZone',
191
+ 'Period',
192
+ 'Null',
193
+ 'Nothing',
194
+ 'Binary',
195
+ 'Regex',
196
+ 'Type',
197
+ 'Comparable',
198
+ 'Key',
199
+ 'Namespace',
200
+ 'Range',
201
+ 'Iterator',
202
+ $.identifier
203
+ ),
204
+
205
+ type_with_parameters: $ => prec(PREC.CALL, seq(
206
+ field('type', choice($.type_name, $.identifier)),
207
+ field('parameters', $.object)
208
+ )),
209
+
210
+ array_type: $ => prec(1, choice(
211
+ seq('Array', '<', $._type, '>'),
212
+ seq($._type, '[', ']')
213
+ )),
214
+
215
+ object_type: $ => seq(
216
+ '{',
217
+ repeat(seq($.type_field, optional(','))),
218
+ '}'
219
+ ),
220
+
221
+ type_field: $ => seq(
222
+ field('name', choice($.identifier, $.string)),
223
+ choice('?:', seq(optional('?'), ':')),
224
+ field('type', $._type)
225
+ ),
226
+
227
+ union_type: $ => prec.left(1, seq($._type, '|', $._type)),
228
+ intersection_type: $ => prec.left(2, seq($._type, '&', $._type)),
229
+ parenthesized_type: $ => seq('(', $._type, ')'),
230
+
231
+ // --- Expressions ---
232
+ _expression: $ => choice(
233
+ $._literal,
234
+ $.identifier,
235
+ $.module_path,
236
+ $.anonymous_parameter,
237
+ $.parenthesized_expression,
238
+ $.unary_expression,
239
+ $.binary_expression,
240
+ $.infix_call,
241
+ $.as_expression,
242
+ $.is_expression,
243
+ $.default_expression,
244
+ $.if_expression,
245
+ $.match_expression,
246
+ $.do_expression,
247
+ $.lambda_expression,
248
+ $.call_expression,
249
+ $.member_expression,
250
+ $.descendant_expression,
251
+ $.multi_value_expression,
252
+ $.attribute_expression,
253
+ $.key_expression,
254
+ $.null_safe_selector,
255
+ $.index_expression,
256
+ $.filter_selector_expression
257
+ ),
258
+
259
+ _literal: $ => choice(
260
+ $.object,
261
+ $.array,
262
+ $.string,
263
+ $.number,
264
+ $.boolean,
265
+ $.null,
266
+ $.regex,
267
+ $.date_time
268
+ ),
269
+
270
+ // --- Object literal ---
271
+ object: $ => seq(
272
+ '{',
273
+ repeat(seq($.object_entry, optional(','))),
274
+ '}'
275
+ ),
276
+
277
+ object_entry: $ => choice(
278
+ $.pair,
279
+ $.conditional_pair,
280
+ $.dynamic_pair,
281
+ $.enclosed_pair,
282
+ $.spread_expression
283
+ ),
284
+
285
+ pair: $ => seq(
286
+ field('key', $._object_key),
287
+ ':',
288
+ field('value', $._expression),
289
+ optional($.conditional_clause)
290
+ ),
291
+
292
+ conditional_pair: $ => seq(
293
+ '(',
294
+ $.pair,
295
+ ')',
296
+ optional($.conditional_clause)
297
+ ),
298
+
299
+ dynamic_pair: $ => seq(
300
+ '(',
301
+ field('key', $._expression),
302
+ ')',
303
+ ':',
304
+ field('value', $._expression),
305
+ optional($.conditional_clause)
306
+ ),
307
+
308
+ enclosed_pair: $ => seq(
309
+ '(',
310
+ '(',
311
+ $.pair,
312
+ ')',
313
+ ')',
314
+ optional($.conditional_clause)
315
+ ),
316
+
317
+ spread_expression: $ => seq(
318
+ choice(
319
+ seq('{(', $._expression, ')}'),
320
+ seq('(', $._expression, ')')
321
+ )
322
+ ),
323
+
324
+ conditional_clause: $ => seq(
325
+ 'if',
326
+ '(',
327
+ field('condition', $._expression),
328
+ ')'
329
+ ),
330
+
331
+ _object_key: $ => prec(PREC.LAMBDA, choice(
332
+ $.qualified_name,
333
+ $.identifier,
334
+ $.string,
335
+ $.number
336
+ )),
337
+
338
+ // --- Array literal ---
339
+ array: $ => seq(
340
+ '[',
341
+ repeat(seq($._expression, optional(','))),
342
+ ']'
343
+ ),
344
+
345
+ // --- Literals ---
346
+ boolean: $ => choice('true', 'false'),
347
+ null: $ => 'null',
348
+
349
+ number: $ => token(choice(
350
+ /0x[0-9a-fA-F]+/,
351
+ /-?[0-9]+(\.[0-9]+)?([eE][+-]?[0-9]+)?/
352
+ )),
353
+
354
+ regex: $ => token(seq('/', /([^/\\]|\\.)*/, '/', optional(/[gimsuy]+/))),
355
+
356
+ date_time: $ => token(seq('|', /[^|\r\n]+/, '|')),
357
+
358
+ // --- Strings & Interpolation ---
359
+ string: $ => choice(
360
+ $.double_quoted_string,
361
+ $.single_quoted_string,
362
+ $.triple_quoted_string
363
+ ),
364
+
365
+ double_quoted_string: $ => seq(
366
+ '"',
367
+ repeat(choice(
368
+ $.string_content,
369
+ $.escape_sequence,
370
+ $.interpolation,
371
+ '$'
372
+ )),
373
+ '"'
374
+ ),
375
+
376
+ single_quoted_string: $ => seq(
377
+ "'",
378
+ repeat(choice(
379
+ $.single_quote_content,
380
+ $.escape_sequence
381
+ )),
382
+ "'"
383
+ ),
384
+
385
+ triple_quoted_string: $ => seq(
386
+ '"""',
387
+ repeat(choice(
388
+ $.triple_quote_content,
389
+ $.escape_sequence,
390
+ $.interpolation,
391
+ '$'
392
+ )),
393
+ '"""'
394
+ ),
395
+
396
+ string_content: $ => token.immediate(prec(1, /[^"\\$]+/)),
397
+ single_quote_content: $ => token.immediate(prec(1, /[^'\\]+/)),
398
+ triple_quote_content: $ => token.immediate(choice(/[^"\\$]+/, '"', '""')),
399
+ escape_sequence: $ => token.immediate(seq('\\', /./)),
400
+ interpolation: $ => seq('$(', field('expression', $._expression), ')'),
401
+
402
+ // --- Identifiers ---
403
+ identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/,
404
+ anonymous_parameter: $ => token(/\${1,3}/),
405
+
406
+ parenthesized_expression: $ => seq('(', $._expression, ')'),
407
+
408
+ // --- Operators ---
409
+ unary_expression: $ => prec(PREC.UNARY, choice(
410
+ seq('-', $._expression),
411
+ seq('!', $._expression),
412
+ seq('not', $._expression)
413
+ )),
414
+
415
+ binary_expression: $ => choice(
416
+ prec.left(PREC.MULTIPLY, seq($._expression, choice('*', '/'), $._expression)),
417
+ prec.left(PREC.ADD, seq($._expression, choice('+', '-', '++', '--', '<<', '>>'), $._expression)),
418
+ prec.left(PREC.RELATIONAL, seq($._expression, choice('<', '<=', '>', '>='), $._expression)),
419
+ prec.left(PREC.EQUALITY, seq($._expression, choice('==', '!=', '~='), $._expression)),
420
+ prec.left(PREC.LOGICAL_AND, seq($._expression, 'and', $._expression)),
421
+ prec.left(PREC.LOGICAL_OR, seq($._expression, 'or', $._expression))
422
+ ),
423
+
424
+ infix_call: $ => prec.left(PREC.INFIX, seq(
425
+ field('left', $._expression),
426
+ field('function', $.identifier),
427
+ field('right', $._expression)
428
+ )),
429
+
430
+ as_expression: $ => prec.left(PREC.AS_IS, seq(
431
+ field('expression', $._expression),
432
+ 'as',
433
+ field('type', $._type)
434
+ )),
435
+
436
+ is_expression: $ => prec.left(PREC.AS_IS, seq(
437
+ field('expression', $._expression),
438
+ 'is',
439
+ field('type', $._type)
440
+ )),
441
+
442
+ default_expression: $ => prec.right(PREC.DEFAULT, seq(
443
+ field('expression', $._expression),
444
+ choice('default', '?:'),
445
+ field('default', $._expression)
446
+ )),
447
+
448
+ // --- Control Flow ---
449
+ if_expression: $ => prec.right(PREC.IF, seq(
450
+ 'if',
451
+ '(',
452
+ field('condition', $._expression),
453
+ ')',
454
+ field('consequence', $._expression),
455
+ 'else',
456
+ field('alternative', $._expression)
457
+ )),
458
+
459
+ match_expression: $ => prec(PREC.MATCH, seq(
460
+ field('value', $._expression),
461
+ 'match',
462
+ '{',
463
+ repeat($.match_case),
464
+ optional($.match_else),
465
+ '}'
466
+ )),
467
+
468
+ match_case: $ => seq(
469
+ 'case',
470
+ choice(
471
+ seq(
472
+ optional(seq(field('variable', $.identifier), ':')),
473
+ field('pattern', choice($.string, $.number, $.boolean, $.null))
474
+ ),
475
+ seq(
476
+ optional(field('variable', $.identifier)),
477
+ choice(
478
+ seq('matches', field('pattern', $.regex)),
479
+ seq(
480
+ optional(seq('is', field('type', $._type))),
481
+ optional(seq('if', field('guard', $._expression)))
482
+ )
483
+ )
484
+ )
485
+ ),
486
+ '->',
487
+ field('consequence', $._expression)
488
+ ),
489
+
490
+ match_else: $ => seq(
491
+ 'else',
492
+ optional(field('variable', $.identifier)),
493
+ '->',
494
+ field('consequence', $._expression)
495
+ ),
496
+
497
+ do_expression: $ => seq(
498
+ 'do',
499
+ '{',
500
+ optional(seq(field('header', $.header), '---')),
501
+ field('body', $._expression),
502
+ '}'
503
+ ),
504
+
505
+ // --- Lambdas & Function Calls ---
506
+ lambda_expression: $ => prec.right(PREC.LAMBDA, seq(
507
+ field('parameters', choice(
508
+ seq('(', optional($.parameter_list), ')'),
509
+ $.identifier
510
+ )),
511
+ optional(seq(':', field('return_type', $._type))),
512
+ '->',
513
+ field('body', $._expression)
514
+ )),
515
+
516
+ call_expression: $ => prec(PREC.CALL, seq(
517
+ field('function', $._expression),
518
+ '(',
519
+ optional(commaSep($._expression)),
520
+ ')'
521
+ )),
522
+
523
+ // --- Selectors ---
524
+ member_expression: $ => prec.left(PREC.SELECTOR, seq(
525
+ field('object', $._expression),
526
+ '.',
527
+ field('property', choice($.identifier, $.string, $.qualified_name))
528
+ )),
529
+
530
+ descendant_expression: $ => prec.left(PREC.SELECTOR, seq(
531
+ field('object', $._expression),
532
+ '..',
533
+ field('property', choice($.identifier, $.string, $.qualified_name))
534
+ )),
535
+
536
+ multi_value_expression: $ => prec.left(PREC.SELECTOR, seq(
537
+ field('object', $._expression),
538
+ '.*',
539
+ field('property', choice($.identifier, $.string, $.qualified_name))
540
+ )),
541
+
542
+ attribute_expression: $ => prec.left(PREC.SELECTOR, seq(
543
+ field('object', $._expression),
544
+ choice('.@', '@'),
545
+ field('attribute', choice($.identifier, $.string, $.qualified_name))
546
+ )),
547
+
548
+ key_expression: $ => prec.left(PREC.SELECTOR, seq(
549
+ field('object', $._expression),
550
+ '.&',
551
+ field('key', choice($.identifier, $.string, $.qualified_name))
552
+ )),
553
+
554
+ null_safe_selector: $ => prec.left(PREC.SELECTOR, choice(
555
+ seq(field('object', $._expression), choice('?.', '.?'), field('property', choice($.identifier, $.string))),
556
+ seq(field('object', $._expression), '?')
557
+ )),
558
+
559
+ index_expression: $ => prec(PREC.SELECTOR, seq(
560
+ field('collection', $._expression),
561
+ '[',
562
+ choice(
563
+ field('index', $._expression),
564
+ seq(field('from', $._expression), 'to', field('to', $._expression))
565
+ ),
566
+ ']'
567
+ )),
568
+
569
+ filter_selector_expression: $ => prec(PREC.SELECTOR, seq(
570
+ field('collection', $._expression),
571
+ '[?',
572
+ field('condition', $._expression),
573
+ ']'
574
+ )),
575
+ },
576
+ });
577
+
578
+ /**
579
+ * Creates a rule to match one or more occurrences of `rule` separated by comma.
580
+ *
581
+ * @param {RuleOrLiteral} rule
582
+ * @returns {SeqRule}
583
+ */
584
+ function commaSep1(rule) {
585
+ return seq(rule, repeat(seq(choice(',', /\r?\n/), rule)));
586
+ }
587
+
588
+ /**
589
+ * Creates a rule to match zero or more occurrences of `rule` separated by comma.
590
+ *
591
+ * @param {RuleOrLiteral} rule
592
+ * @returns {ChoiceRule}
593
+ */
594
+ function commaSep(rule) {
595
+ return optional(commaSep1(rule));
596
+ }
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "tree-sitter-dataweave",
3
+ "version": "0.1.0",
4
+ "description": "DataWeave grammar for tree-sitter",
5
+ "main": "bindings/node",
6
+ "types": "bindings/node",
7
+ "scripts": {
8
+ "install": "node-gyp-build",
9
+ "prestart": "npx --yes --package=tree-sitter-cli@v0.27.0 -- tree-sitter build --wasm",
10
+ "start": "npx --yes --package=tree-sitter-cli@v0.27.0 -- tree-sitter playground",
11
+ "test": "node --test bindings/node/*_test.js"
12
+ },
13
+ "author": "M. Reifschneider",
14
+ "license": "MIT",
15
+ "dependencies": {
16
+ "node-addon-api": "^8.9.2",
17
+ "node-gyp-build": "^4.8.0"
18
+ },
19
+ "devDependencies": {
20
+ "node-gyp": "^13.0.2",
21
+ "tree-sitter": "^0.25.0"
22
+ },
23
+ "peerDependencies": {
24
+ "tree-sitter": "^0.25.0"
25
+ },
26
+ "peerDependenciesMeta": {
27
+ "tree-sitter": {
28
+ "optional": true
29
+ }
30
+ },
31
+ "gypfile": true,
32
+ "directories": {
33
+ "test": "test"
34
+ },
35
+ "type": "module",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/meloncholic/tree-sitter-mulesoft.git",
39
+ "directory": "dataweave"
40
+ },
41
+ "bugs": {
42
+ "url": "https://github.com/meloncholic/tree-sitter-mulesoft/issues"
43
+ },
44
+ "homepage": "https://github.com/meloncholic/tree-sitter-mulesoft#readme",
45
+ "keywords": [
46
+ "parser",
47
+ "dataweave",
48
+ "dwl",
49
+ "mulesoft",
50
+ "tree-sitter"
51
+ ],
52
+ "files": [
53
+ "grammar.js",
54
+ "binding.gyp",
55
+ "bindings/node/*",
56
+ "queries/*",
57
+ "src/**",
58
+ "NOTICE"
59
+ ],
60
+ "allowScripts": {
61
+ "tree-sitter-cli@0.27.0": true,
62
+ "tree-sitter@0.25.1": true
63
+ }
64
+ }