Files
2026-09-23 00:36:22 -04:00

3.6 KiB

Concrete syntax tree contract

This document describes the named nodes and fields intended for consumers such as editor integrations, formatters, and structural search. Rules prefixed with _ and rules listed as Tree-sitter supertypes are implementation details and do not appear as named wrapper nodes in ordinary trees.

Source and declarations

source_file contains declarations, imports, publication declarations, and standalone expressions directly. The choice-only module_item, expression, and value_expression rules are hidden supertypes.

declaration uses these fields:

  • name for a named declaration;
  • pattern for a destructuring declaration;
  • type for an explicit type;
  • value for an initializer.

The punctuation distinguishes immutable, mutable, typed, and deferred forms. Consumers should inspect that punctuation rather than infer the form from the set of fields alone.

Expressions

Only expressions that actually contain an operator produce an operator node:

Node Fields
assignment_expression left, operator, right
range_expression left, operator, right
binary_expression left, operator, right
unary_expression operator, operand
postfix_expression value, repeated operator; member and index operators additionally expose member or index
pipeline_expression input, followed by stage nodes

Precedence-only rules are hidden. For example, a + b * -c has one outer and one inner binary_expression, then a unary_expression; it does not contain a wrapper for every precedence level.

Literal leaves are named. Boolean and nil values use boolean_literal and nil_literal; numeric, string, character, and unit literals retain their specific nodes. default_expression is also named.

function_literal takes one input and owns the body field. Direct binding appears as parameter: (typed_parameter); tuple destructuring appears as parameter: (typed_tuple_pattern). A typed_tuple_pattern contains zero or at least two typed_tuple_component nodes. These bind components of one tuple input, not separate function arguments. () matches unit; singleton tuple patterns are invalid. Typed bindings expose pattern and type; a header may also expose effect (-> or =>) and result.

Types

Meaningful type constructors are named directly:

Node Fields
function_type input, effect, result
result_type value, error
optional_type value
array_type element
map_type key, value
grouped_type value
type_application constructor followed by its type arguments

Primitive, unit, tuple, product, sum, and bits types retain their corresponding named nodes. Internal primary/container/result categories are hidden.

Trivia and physical lines

Comments are named extra nodes. Spaces, tabs, and structural newlines remain in the source gaps between nodes, so a formatter must retain the original source alongside the tree. Leading-operator and pipeline continuations use composite tokens containing their newline; this prevents a scope separator from stealing a valid continuation and preserves the language's physical-line rules.

Compatibility

Adding nodes or fields is compatible. Removing or renaming a named node or field, changing its meaning, or changing which source construct owns it is a breaking CST change. Until the package reaches 1.0, such changes require corpus snapshot updates and a version change, and must be called out in release notes.

The Tree-sitter tree is designed for source tooling and error recovery; it does not perform semantic validation.