Files
tree-sitter-lscript/docs/cst.md
T
2026-09-23 00:36:22 -04:00

88 lines
3.6 KiB
Markdown

# 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.