@dekobon/tree-sitter-groovy 0.2.2 → 0.4.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 +148 -35
- package/package.json +9 -3
- package/prebuilds/darwin-arm64/@dekobon+tree-sitter-groovy.node +0 -0
- package/prebuilds/linux-x64/@dekobon+tree-sitter-groovy.node +0 -0
- package/prebuilds/win32-x64/@dekobon+tree-sitter-groovy.node +0 -0
- package/src/grammar.json +442 -138
- package/src/node-types.json +53 -3
- package/src/parser.c +121565 -113987
- package/src/tree_sitter/array.h +23 -17
- package/tree-sitter.json +1 -1
package/grammar.js
CHANGED
|
@@ -109,7 +109,7 @@ module.exports = grammar({
|
|
|
109
109
|
// (list_literal vs map_literal — tree-sitter resolves without
|
|
110
110
|
// an explicit conflict because `:` after the first element
|
|
111
111
|
// always disambiguates within one token of lookahead.)
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
// §5.15 — inside `( … )` an identifier could be either an
|
|
114
114
|
// _expression (parenthesized_expression) or a _type
|
|
115
115
|
// (parenthesized_type_cast). Tree-sitter explores both via
|
|
@@ -145,6 +145,25 @@ module.exports = grammar({
|
|
|
145
145
|
// decides; the conflict keeps both alternatives alive until
|
|
146
146
|
// then.
|
|
147
147
|
[$.variable_declarator, $._property_name],
|
|
148
|
+
|
|
149
|
+
// §4 — `static NAME` inside a class body: after one or more
|
|
150
|
+
// modifiers and one identifier, that identifier could be the
|
|
151
|
+
// modifier-only field_declaration's variable_declarator name
|
|
152
|
+
// (`static MEDIUM_TTL = 900`) or the start of a typed
|
|
153
|
+
// field_declaration/method_declaration's `_type` (`static Foo
|
|
154
|
+
// bar`). The next token (`=`/`,`/`;` vs a second identifier)
|
|
155
|
+
// disambiguates.
|
|
156
|
+
[$.variable_declarator, $._type],
|
|
157
|
+
|
|
158
|
+
// §4 — `enum E { E(v, w) { } }`: after `E(` an identifier could be
|
|
159
|
+
// a constant's argument (`_expression`) or a constructor's untyped
|
|
160
|
+
// parameter (`formal_parameter`); the `{` after `)` decides. The
|
|
161
|
+
// conflict is global by necessity — it is between the two
|
|
162
|
+
// reductions, not their containers — and was checked inert
|
|
163
|
+
// outside an enum body: declaring it on the v0.3.0 grammar makes
|
|
164
|
+
// tree-sitter report it unnecessary. Regenerate without it to
|
|
165
|
+
// confirm that still holds.
|
|
166
|
+
[$.formal_parameter, $._expression],
|
|
148
167
|
],
|
|
149
168
|
|
|
150
169
|
rules: {
|
|
@@ -390,9 +409,10 @@ module.exports = grammar({
|
|
|
390
409
|
|
|
391
410
|
// §4 — `catch_formal_parameter` accepts either a single _type
|
|
392
411
|
// or a multi_type for Java 7+ / Groovy multi-catch. Closes
|
|
393
|
-
// murtaza64 #39.
|
|
412
|
+
// murtaza64 #39. The type itself is optional — Groovy allows a
|
|
413
|
+
// bare `catch (e) { … }`, implicitly typed as Exception.
|
|
394
414
|
catch_formal_parameter: $ => seq(
|
|
395
|
-
field('type', choice($._type, $.multi_type)),
|
|
415
|
+
optional(field('type', choice($._type, $.multi_type))),
|
|
396
416
|
field('name', $.identifier),
|
|
397
417
|
),
|
|
398
418
|
|
|
@@ -537,11 +557,17 @@ module.exports = grammar({
|
|
|
537
557
|
'}',
|
|
538
558
|
),
|
|
539
559
|
|
|
560
|
+
// A nested enum (`static enum EventType { … }` inside a domain
|
|
561
|
+
// class) is common enough in real Groovy that leaving it out
|
|
562
|
+
// silently misparses `enum` as a field_declaration's type name.
|
|
563
|
+
// Nested class/interface/trait land separately (bigger surface,
|
|
564
|
+
// own conflict set) — out of scope here.
|
|
540
565
|
_class_member: $ => choice(
|
|
541
566
|
$.method_declaration,
|
|
542
567
|
$.field_declaration,
|
|
543
568
|
$.constructor_declaration,
|
|
544
569
|
$.static_initializer,
|
|
570
|
+
$.enum_declaration,
|
|
545
571
|
),
|
|
546
572
|
|
|
547
573
|
// §4 — constructors share the method_declaration shape but have
|
|
@@ -573,12 +599,28 @@ module.exports = grammar({
|
|
|
573
599
|
// more declarators (each with optional initializer). Method
|
|
574
600
|
// declarations share the same prefix; `prec(2, …)` on
|
|
575
601
|
// `method_declaration` and the trailing `(` discriminate.
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
602
|
+
//
|
|
603
|
+
// A modifier alone (no `def`, no type) also introduces a field —
|
|
604
|
+
// `static MEDIUM_TTL = 900` infers Object, a common constant-field
|
|
605
|
+
// idiom. Gated behind `repeat1($._modifier)` (not `repeat`) so this
|
|
606
|
+
// alternative can't match a bare, modifier-less identifier, which
|
|
607
|
+
// would collide with a plain expression_statement.
|
|
608
|
+
field_declaration: $ => choice(
|
|
609
|
+
// Prefer the typed field when both parses succeed, rather than
|
|
610
|
+
// splitting `private final int v\n C() {}` after `int`.
|
|
611
|
+
prec.dynamic(1, seq(
|
|
612
|
+
repeat($.annotation),
|
|
613
|
+
repeat($._modifier),
|
|
614
|
+
choice('def', field('type', $._type)),
|
|
615
|
+
$.variable_declarator,
|
|
616
|
+
repeat(seq(',', $.variable_declarator)),
|
|
617
|
+
)),
|
|
618
|
+
seq(
|
|
619
|
+
repeat($.annotation),
|
|
620
|
+
repeat1($._modifier),
|
|
621
|
+
$.variable_declarator,
|
|
622
|
+
repeat(seq(',', $.variable_declarator)),
|
|
623
|
+
),
|
|
582
624
|
),
|
|
583
625
|
|
|
584
626
|
// §4 — `def name(params) body`. Typed return type (`String foo()
|
|
@@ -626,10 +668,13 @@ module.exports = grammar({
|
|
|
626
668
|
')',
|
|
627
669
|
),
|
|
628
670
|
|
|
629
|
-
// §5.13 — formal parameter with optional
|
|
630
|
-
//
|
|
671
|
+
// §5.13 — formal parameter with optional annotations (Spring's
|
|
672
|
+
// `@PathVariable`, `@RequestBody`, JPA's `@Param`, … — ubiquitous
|
|
673
|
+
// on framework-facing methods), optional type, optional varargs
|
|
674
|
+
// marker (`Type... name`), and optional default value
|
|
631
675
|
// (`name = expr`).
|
|
632
676
|
formal_parameter: $ => seq(
|
|
677
|
+
repeat($.annotation),
|
|
633
678
|
optional(field('type', choice($._type, $.varargs_type))),
|
|
634
679
|
field('name', $.identifier),
|
|
635
680
|
optional(seq('=', field('default', $._expression))),
|
|
@@ -637,13 +682,24 @@ module.exports = grammar({
|
|
|
637
682
|
|
|
638
683
|
varargs_type: $ => seq($._type, '...'),
|
|
639
684
|
|
|
640
|
-
// §4 — enum. Closes murtaza64 #36 first half. Constants
|
|
641
|
-
//
|
|
642
|
-
//
|
|
643
|
-
//
|
|
644
|
-
//
|
|
685
|
+
// §4 — enum. Closes murtaza64 #36 first half. Constants may
|
|
686
|
+
// carry constructor arguments (`RED(0xff0000)`) via the optional
|
|
687
|
+
// argument_list.
|
|
688
|
+
//
|
|
689
|
+
// The body follows GroovyParser.g4 `classBody` for `t == 2`:
|
|
690
|
+
// after the constants either a trailing `,` closes the list, or
|
|
691
|
+
// members follow after `;`, `,;`, or nothing at all — Groovy's
|
|
692
|
+
// own parser treats the newline as the separator (GROOVY-7773,
|
|
693
|
+
// GROOVY-9306), and newlines are extras here, so the member
|
|
694
|
+
// simply follows the last constant. `A,` directly before a
|
|
695
|
+
// member is rejected, as in Groovy. With no constants the body
|
|
696
|
+
// is an ordinary member list. The member list is spelled three
|
|
697
|
+
// times rather than shared with `class_body` through a hidden
|
|
698
|
+
// rule: a new rule renumbers the aux symbols and ~100 symbol ids,
|
|
699
|
+
// which a patch release must not do.
|
|
645
700
|
enum_declaration: $ => seq(
|
|
646
701
|
repeat($.annotation),
|
|
702
|
+
repeat($._modifier),
|
|
647
703
|
'enum',
|
|
648
704
|
field('name', $.identifier),
|
|
649
705
|
field('body', $.enum_body),
|
|
@@ -651,19 +707,37 @@ module.exports = grammar({
|
|
|
651
707
|
|
|
652
708
|
enum_body: $ => seq(
|
|
653
709
|
'{',
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
710
|
+
choice(
|
|
711
|
+
seq(
|
|
712
|
+
$.enum_constant,
|
|
713
|
+
repeat(seq(',', $.enum_constant)),
|
|
714
|
+
optional(choice(
|
|
715
|
+
',',
|
|
716
|
+
seq(optional(','), ';', repeat(choice($._class_member, ';'))),
|
|
717
|
+
seq($._class_member, repeat(choice($._class_member, ';'))),
|
|
718
|
+
)),
|
|
719
|
+
),
|
|
720
|
+
repeat(choice($._class_member, ';')),
|
|
721
|
+
),
|
|
660
722
|
'}',
|
|
661
723
|
),
|
|
662
724
|
|
|
663
|
-
|
|
725
|
+
// §4 — `prec(1)` makes a bare identifier at the start of the body
|
|
726
|
+
// a constant rather than the type of the first member: `A\n E() { }`
|
|
727
|
+
// is a constant followed by a constructor, not a method `E`
|
|
728
|
+
// returning `A`. The mirror case with no constants, `int f() { }`
|
|
729
|
+
// as the first thing in the body, therefore reads as constant `int`
|
|
730
|
+
// plus constructor `f` — a newline is whitespace here and nothing
|
|
731
|
+
// else tells the two apart; a modifier, `def`, or a leading `;`
|
|
732
|
+
// makes it a member. Static precedence rather than `prec.dynamic`
|
|
733
|
+
// with an `[enum_constant, _type]` conflict: both yield the same
|
|
734
|
+
// tree on every valid shape, but the GLR form silently accepts
|
|
735
|
+
// `A\n B` (constants missing their comma, which Groovy rejects) as
|
|
736
|
+
// a field `A B`, where this form reports the ERROR.
|
|
737
|
+
enum_constant: $ => prec(1, seq(
|
|
664
738
|
field('name', $.identifier),
|
|
665
739
|
optional(field('arguments', $.argument_list)),
|
|
666
|
-
),
|
|
740
|
+
)),
|
|
667
741
|
|
|
668
742
|
// §4 — record (Groovy 4+). `record Name(Type a, Type b) [{ body }]`.
|
|
669
743
|
// `record` is a contextual keyword — tree-sitter's word: directive
|
|
@@ -779,16 +853,18 @@ module.exports = grammar({
|
|
|
779
853
|
optional(field('arguments', $.argument_list)),
|
|
780
854
|
),
|
|
781
855
|
|
|
782
|
-
// §4 — `for (x in xs)
|
|
783
|
-
//
|
|
784
|
-
//
|
|
785
|
-
//
|
|
786
|
-
//
|
|
856
|
+
// §4 — `for (x in xs)`, plus the Java-compatible enhanced-for
|
|
857
|
+
// form Groovy accepts side by side: `for (Type x : xs)` / `for
|
|
858
|
+
// (def x : xs)`. The `in` / `:` keyword here is a structural
|
|
859
|
+
// delimiter, not the membership_expression operator or a
|
|
860
|
+
// labelled_statement colon — context disambiguates because the
|
|
861
|
+
// for-header is not an expression position.
|
|
787
862
|
for_in_statement: $ => seq(
|
|
788
863
|
'for',
|
|
789
864
|
'(',
|
|
865
|
+
optional(choice('def', field('type', $._type))),
|
|
790
866
|
field('variable', $.identifier),
|
|
791
|
-
'in',
|
|
867
|
+
choice('in', ':'),
|
|
792
868
|
field('value', $._expression),
|
|
793
869
|
')',
|
|
794
870
|
field('body', choice($.block, $._statement)),
|
|
@@ -972,10 +1048,22 @@ module.exports = grammar({
|
|
|
972
1048
|
// (`new Foo().bar`).
|
|
973
1049
|
object_creation_expression: $ => prec.right(PREC.PRIMARY, seq(
|
|
974
1050
|
'new',
|
|
975
|
-
field('type', $._type),
|
|
1051
|
+
field('type', choice($._type, alias($._diamond_type, $.generic_type))),
|
|
976
1052
|
field('arguments', $.argument_list),
|
|
977
1053
|
)),
|
|
978
1054
|
|
|
1055
|
+
// §3.2 — Apache's createdName permits diamond, but ordinary types
|
|
1056
|
+
// (including nested type arguments) do not. Keep the public shape.
|
|
1057
|
+
_diamond_type: $ => prec.right(PREC.ARRAY_TYPE, seq(
|
|
1058
|
+
field('base', choice(
|
|
1059
|
+
alias($.identifier, $.type_identifier),
|
|
1060
|
+
$.qualified_type,
|
|
1061
|
+
)),
|
|
1062
|
+
field('arguments', alias($._diamond_type_arguments, $.type_arguments)),
|
|
1063
|
+
)),
|
|
1064
|
+
|
|
1065
|
+
_diamond_type_arguments: _ => seq(token.immediate('<'), '>'),
|
|
1066
|
+
|
|
979
1067
|
// §5.15 — C-style cast `(Foo) x`. Distinct from
|
|
980
1068
|
// `parenthesized_expression` followed by something (resolved
|
|
981
1069
|
// by tree-sitter's GLR; declared as a conflict if needed).
|
|
@@ -1135,10 +1223,35 @@ module.exports = grammar({
|
|
|
1135
1223
|
// expression so subscript / future field_access / future
|
|
1136
1224
|
// safe_navigation chains compose naturally. PREC.POSTFIX
|
|
1137
1225
|
// matches subscript so chains like `obj[i](x)[j]` work.
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1226
|
+
//
|
|
1227
|
+
// Trailing closure (§5.5's command_chain covers the bare-
|
|
1228
|
+
// identifier statement form; this covers the general expression
|
|
1229
|
+
// form used constantly on property-access chains: `list.find {
|
|
1230
|
+
// it > 5 }`, `list.inject(0) { acc, x -> acc + x }`). Groovy
|
|
1231
|
+
// treats a closure literal as the call's last argument whether
|
|
1232
|
+
// or not parens are present, so `argument_list` becomes optional
|
|
1233
|
+
// once a trailing closure is there to anchor the call.
|
|
1234
|
+
//
|
|
1235
|
+
// The args-and-closure alternative sits one precedence level
|
|
1236
|
+
// above plain POSTFIX so `f(x) { … }` reduces to a single
|
|
1237
|
+
// method_invocation node (arguments AND closure fields on the
|
|
1238
|
+
// same node) instead of GLR instead reaching the same span by
|
|
1239
|
+
// nesting a closure-only method_invocation around a plain call.
|
|
1240
|
+
method_invocation: $ => choice(
|
|
1241
|
+
prec.left(PREC.POSTFIX + 1, seq(
|
|
1242
|
+
field('function', $._expression),
|
|
1243
|
+
field('arguments', $.argument_list),
|
|
1244
|
+
field('closure', $.closure),
|
|
1245
|
+
)),
|
|
1246
|
+
prec.left(PREC.POSTFIX, seq(
|
|
1247
|
+
field('function', $._expression),
|
|
1248
|
+
field('arguments', $.argument_list),
|
|
1249
|
+
)),
|
|
1250
|
+
prec.left(PREC.POSTFIX, seq(
|
|
1251
|
+
field('function', $._expression),
|
|
1252
|
+
field('closure', $.closure),
|
|
1253
|
+
)),
|
|
1254
|
+
),
|
|
1142
1255
|
|
|
1143
1256
|
// §3.2 / §5.11 — argument list. Positional args are `_expression`;
|
|
1144
1257
|
// named args (Groovy's `k: v` in call position) are `map_entry`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dekobon/tree-sitter-groovy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Apache Groovy grammar for tree-sitter (dekobon fork)",
|
|
5
5
|
"main": "bindings/node",
|
|
6
6
|
"types": "bindings/node",
|
|
@@ -67,10 +67,16 @@
|
|
|
67
67
|
}
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"eslint": "^
|
|
70
|
+
"eslint": "^10.14.0",
|
|
71
71
|
"eslint-config-treesitter": "^1.0.2",
|
|
72
|
+
"globals": "^17.14.0",
|
|
72
73
|
"prebuildify": "^6.0.1",
|
|
73
|
-
"tree-sitter-cli": "^0.
|
|
74
|
+
"tree-sitter-cli": "^0.27.2"
|
|
75
|
+
},
|
|
76
|
+
"overrides": {
|
|
77
|
+
"eslint-config-treesitter": {
|
|
78
|
+
"eslint-plugin-jsdoc": "^62.9.0"
|
|
79
|
+
}
|
|
74
80
|
},
|
|
75
81
|
"tree-sitter": [
|
|
76
82
|
{
|
|
Binary file
|
|
Binary file
|
|
Binary file
|