@@ -91,20 +91,21 @@ module.exports = grammar({
9191 [ $ . _postfix_unary_expression , $ . _expression ] ,
9292
9393 // ambiguity between generics and comparison operations (foo < b > c)
94- [ $ . call_expression , $ . navigation_expression , $ . range_expression , $ . comparison_expression ] ,
95- [ $ . call_expression , $ . navigation_expression , $ . elvis_expression , $ . comparison_expression ] ,
96- [ $ . call_expression , $ . navigation_expression , $ . check_expression , $ . comparison_expression ] ,
97- [ $ . call_expression , $ . navigation_expression , $ . additive_expression , $ . comparison_expression ] ,
98- [ $ . call_expression , $ . navigation_expression , $ . infix_expression , $ . comparison_expression ] ,
99- [ $ . call_expression , $ . navigation_expression , $ . multiplicative_expression , $ . comparison_expression ] ,
94+ // _generic_call_expression is the prec.dynamic(1) variant with required type_arguments
95+ [ $ . call_expression , $ . _generic_call_expression , $ . navigation_expression , $ . range_expression , $ . comparison_expression ] ,
96+ [ $ . call_expression , $ . _generic_call_expression , $ . navigation_expression , $ . elvis_expression , $ . comparison_expression ] ,
97+ [ $ . call_expression , $ . _generic_call_expression , $ . navigation_expression , $ . check_expression , $ . comparison_expression ] ,
98+ [ $ . call_expression , $ . _generic_call_expression , $ . navigation_expression , $ . additive_expression , $ . comparison_expression ] ,
99+ [ $ . call_expression , $ . _generic_call_expression , $ . navigation_expression , $ . infix_expression , $ . comparison_expression ] ,
100+ [ $ . call_expression , $ . _generic_call_expression , $ . navigation_expression , $ . multiplicative_expression , $ . comparison_expression ] ,
100101 [ $ . type_arguments , $ . _comparison_operator ] ,
101102
102103 // ambiguity between prefix expressions and annotations before functions
103104 [ $ . _statement , $ . prefix_expression ] ,
104105 [ $ . prefix_expression , $ . when_subject ] ,
105106 [ $ . prefix_expression , $ . value_argument ] ,
106107 // ambiguity between prefix unary operators and other expression types
107- [ $ . call_expression , $ . navigation_expression , $ . prefix_expression , $ . comparison_expression ] ,
108+ [ $ . call_expression , $ . _generic_call_expression , $ . navigation_expression , $ . prefix_expression , $ . comparison_expression ] ,
108109
109110 // ambiguity between multiple user types and class property/function declarations
110111 [ $ . user_type ] ,
@@ -156,6 +157,10 @@ module.exports = grammar({
156157 // Three-way conflict: callable_reference (Foo::bar) starts with simple_identifier
157158 // which both primary_expression variants can match.
158159 [ $ . _primary_expression , $ . _primary_expression_no_trailing_lambda , $ . callable_reference ] ,
160+
161+ // ambiguity between call_suffix and _generic_call_suffix (both can match type_arguments + args)
162+ [ $ . call_suffix , $ . _generic_call_suffix ] ,
163+ [ $ . _call_suffix_no_trailing_lambda , $ . _generic_call_suffix_no_trailing_lambda ] ,
159164 ] ,
160165
161166 externals : $ => [
@@ -355,6 +360,7 @@ module.exports = grammar({
355360 $ . string_literal ,
356361 $ . callable_reference ,
357362 alias ( $ . call_expression_no_trailing_lambda , $ . call_expression ) ,
363+ alias ( $ . _generic_call_expression_no_trailing_lambda , $ . call_expression ) ,
358364 $ . _function_literal ,
359365 $ . object_literal ,
360366 $ . collection_literal ,
@@ -372,11 +378,22 @@ module.exports = grammar({
372378 alias ( $ . _call_suffix_no_trailing_lambda , $ . call_suffix )
373379 ) ) ,
374380
381+ // Generic call (required type_arguments) without trailing lambda
382+ _generic_call_expression_no_trailing_lambda : $ => prec . left ( PREC . POSTFIX , prec . dynamic ( 1 , seq (
383+ $ . _expression_no_trailing_lambda ,
384+ alias ( $ . _generic_call_suffix_no_trailing_lambda , $ . call_suffix )
385+ ) ) ) ,
386+
375387 _call_suffix_no_trailing_lambda : $ => seq (
376388 optional ( $ . type_arguments ) ,
377389 $ . value_arguments
378390 ) ,
379391
392+ _generic_call_suffix_no_trailing_lambda : $ => seq (
393+ $ . type_arguments ,
394+ $ . value_arguments
395+ ) ,
396+
380397 type_parameters : $ => seq ( "<" , sep1 ( $ . type_parameter , "," ) , optional ( "," ) , ">" ) ,
381398
382399 type_parameter : $ => seq (
@@ -727,6 +744,16 @@ module.exports = grammar({
727744
728745 call_expression : $ => prec . left ( PREC . POSTFIX , seq ( $ . _expression , $ . call_suffix ) ) ,
729746
747+ // Generic call expression: call with REQUIRED type_arguments.
748+ // prec.dynamic(1) tells GLR to prefer the generic-call interpretation
749+ // (f<T>(x)) over the comparison interpretation (f < T > (x)).
750+ // Separated from call_expression so the dynamic boost only applies
751+ // when type_arguments are actually parsed, not for all calls.
752+ _generic_call_expression : $ => prec . left ( PREC . POSTFIX , prec . dynamic ( 1 , seq (
753+ $ . _expression ,
754+ alias ( $ . _generic_call_suffix , $ . call_suffix )
755+ ) ) ) ,
756+
730757 indexing_expression : $ => prec . left ( PREC . POSTFIX , seq ( $ . _expression , $ . indexing_suffix ) ) ,
731758
732759 navigation_expression : $ => prec . left ( PREC . POSTFIX , seq ( $ . _expression , $ . navigation_suffix ) ) ,
@@ -801,6 +828,15 @@ module.exports = grammar({
801828 )
802829 ) ) ,
803830
831+ // Call suffix with REQUIRED type_arguments (used by _generic_call_expression)
832+ _generic_call_suffix : $ => prec . left ( seq (
833+ $ . type_arguments ,
834+ choice (
835+ prec ( PREC . ARGUMENTS , seq ( optional ( $ . value_arguments ) , $ . annotated_lambda ) ) ,
836+ $ . value_arguments
837+ )
838+ ) ) ,
839+
804840 annotated_lambda : $ => seq (
805841 repeat ( $ . annotation ) ,
806842 optional ( $ . label ) ,
@@ -834,6 +870,7 @@ module.exports = grammar({
834870 $ . string_literal ,
835871 $ . callable_reference ,
836872 $ . call_expression ,
873+ alias ( $ . _generic_call_expression , $ . call_expression ) ,
837874 $ . _function_literal ,
838875 $ . object_literal ,
839876 $ . collection_literal ,
0 commit comments