Skip to content

feat(microsyntax): introduce structured microsyntax grammar for structural directives#97

Open
albaniosi wants to merge 8 commits into
dlvandenberg:mainfrom
albaniosi:feat/microsyntax
Open

feat(microsyntax): introduce structured microsyntax grammar for structural directives#97
albaniosi wants to merge 8 commits into
dlvandenberg:mainfrom
albaniosi:feat/microsyntax

Conversation

@albaniosi

Copy link
Copy Markdown

Summary

Replaces the ad-hoc structural_expression / structural_declaration / structural_assignment grammar nodes with a new, purpose-built microsyntax grammar that more precisely models the Angular structural directive microsyntax language.

This also fixes a small bug where naked & characters in text nodes would break the parser. (which in theory is correct by the HTML specification, but is ignored in reality by all parsers and renderers)

Motivation

The previous grammar did not model the possible syntax of Angulars microsyntax for directives very well. For example:

  • optionality of the delimiters (,/; - e.g. *ngIf="someCondition else elseBlock")
  • *myDirective="let t = x; prefix: 'test.something.asdfasdfasdfdfdf'" (this completly broke the whole following pasing)
  • *ngIf="someCondition; then thenBlock else elseBlock"
  • *ngFor="let item; of: items trackBy (a, v) => test(a, v)"
  • and more

I use Zed whose angular plugin uses this. The parsing was resulting in completely broken files, so i fixed it locally for me. But I thought this might be useful for the project in general.

I hope this helps and I am happy to alter my code to comply with your wishes and standards if possible.

Changes

Grammar (grammar.js)

  • Removed structural_expression, structural_declaration, structural_assignment, _else_template_expression, and _context_expression.
  • Added a microsyntax subtree:
    • microsyntax — top-level container for the full directive value
    • microsyntax_anonymous_binding — the primary/leading expression (e.g. items, condition ? a : b)
    • microsyntax_binding — any subsequent named binding (dispatches to one of the three below)
    • microsyntax_keyword_binding — reserved keywords (else, then, of) with an optional expression and alias
    • microsyntax_variable_declarationlet name = value / let name declarations
    • microsyntax_property_binding — arbitrary identifier bindings with an expression
  • Fixed the text rule to accept a bare & as a fallback, preventing parse failures on ampersands in template text.
  • Added conflict resolutions for [$._any_expression, $.arguments], [$.expression, $.arguments], and [$.microsyntax_property_binding, $._primitive].

Highlights (queries/highlights.scm)

  • Removed the now-obsolete structural_assignment operator highlight rule.

Tests (test/corpus/structural-directives.txt)

  • Migrated all existing corpus cases from structural_expression / structural_declaration nodes to the new microsyntax_* node hierarchy.
  • Added comprehensive new corpus cases covering:
    • Primary bindings (identifier and full expression forms)
    • let variable declarations with and without initializers
    • Keyword bindings (else, then, of) with aliases
    • Property bindings
    • Delimiter-less forms
    • Mixed / edge-case combinations

Breaking Change

Any downstream consumers (syntax highlighting, queries, linters) that reference structural_expression, structural_declaration, or structural_assignment nodes will need to be updated to use the new microsyntax_* node names.

Simon Albani and others added 8 commits June 3, 2026 14:26
introduce a new microsyntax grammar that is used to parse the microsyntax of structural directives. This allows us to better understand the structure of structural directives and to provide better support for them in our parser.

fix: an issue breaking on ampersand in text
add comprehensive corpus cases for structural directives, including
primary bindings, variable declarations, keyword bindings, property
bindings, delimiter-less forms, and mixed edge-case combinations

update expected parse trees to reflect refined microsyntax node mapping,
especially for keyword vs property bindings and variable declarations

revert grammar file types in tree-sitter metadata to component.html only
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant