Skip to content

fix: prefer generic call interpretation for f<T>(x) via prec.dynamic#236

Merged
VladimirMakaev merged 1 commit intofwcd:mainfrom
VladimirMakaev:fix/generic-call-prec-dynamic
Feb 20, 2026
Merged

fix: prefer generic call interpretation for f<T>(x) via prec.dynamic#236
VladimirMakaev merged 1 commit intofwcd:mainfrom
VladimirMakaev:fix/generic-call-prec-dynamic

Conversation

@VladimirMakaev
Copy link
Copy Markdown
Collaborator

Summary

  • Adds a _generic_call_expression rule with required type_arguments and prec.dynamic(1) to resolve the <> generic-vs-comparison ambiguity
  • When the GLR parser forks on < (could be type_arguments or comparison operator), the generic call path now has higher dynamic precedence
  • The rule is aliased to call_expression so the output tree is unchanged
  • A separate rule is needed because prec.dynamic on the full call_expression (with optional type_arguments) would also boost trailing lambda calls, breaking object literal class_body parsing and getter/setter accessor recognition (12 test failures)

Before

f<T>(x)  // parsed as: (f < T) > (x)  — comparison chain

After

f<T>(x)  // parsed as: call_expression(f, type_arguments(<T>), value_arguments(x))

Follows the pattern used by tree-sitter-java (prec.dynamic on generic_type) and tree-sitter-go (prec.dynamic on type_arguments).

Parser size

Branch parser.c size Change from main
main 25,505,362 B (24.3 MB)
After accessor fix 28,666,529 B (27.3 MB) +12.4%
This PR (cumulative) 28,775,213 B (27.4 MB) +12.8%
This PR (incremental) +0.4% over accessor fix

The prec.dynamic variant adds minimal parser states (+0.4%) since the GLR conflict infrastructure already exists.

Test plan

  • All 241 existing corpus tests pass (zero regressions)
  • Object literals, anonymous functions, getter/setter accessors unaffected
  • f<T>(x) correctly parses as generic call
  • if (x < y) still parses as comparison
  • npm run cross-validate shows no regressions

@github-actions github-actions bot added the grammar Related to the grammar label Feb 20, 2026
@VladimirMakaev VladimirMakaev force-pushed the fix/generic-call-prec-dynamic branch from 9e43ddb to 2556fe3 Compare February 20, 2026 03:12
Add _generic_call_expression rule with required type_arguments and
prec.dynamic(1) to resolve the <> generic vs comparison ambiguity.
When the GLR parser forks on `<` (type_arguments vs comparison
operator), the generic call path now has higher dynamic precedence.

The rule is aliased to call_expression so the output tree is
unchanged. A separate rule is needed because prec.dynamic on the
full call_expression (with optional type_arguments) would also
boost trailing lambda calls, breaking object literal class_body
parsing and getter/setter accessor recognition.

Follows the pattern used by tree-sitter-java (prec.dynamic on
generic_type) and tree-sitter-go (prec.dynamic on type_arguments).
@VladimirMakaev VladimirMakaev force-pushed the fix/generic-call-prec-dynamic branch from 2556fe3 to 3aec6ae Compare February 20, 2026 21:46
@VladimirMakaev VladimirMakaev marked this pull request as ready for review February 20, 2026 22:56
@VladimirMakaev VladimirMakaev merged commit b1594c5 into fwcd:main Feb 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

grammar Related to the grammar

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant