# laburnum-syntax-macro

Proc-macros for defining CST and AST node types in language frontends built with
the [laburnum](https://crates.io/crates/laburnum) LSP framework.

The macro takes a plain `struct` (or `enum`) describing the fields of a syntax
node and generates the accessors, traversal glue, and laburnum integration
needed to use it as a node in a concrete or abstract syntax tree.

## Usage

```rust,ignore
use laburnum_syntax_macro::laburnum_syntax;

#[laburnum_syntax(CST)]
pub struct BinaryExpr {
    span: Span,
    lhs: NodeId<crate::Expression>,
    op: NodeId<crate::Token>,
    rhs: NodeId<crate::Expression>,
}

#[laburnum_syntax(AST)]
pub struct Function {
    visibility: Field<Enum<crate::modifier::Visibility>>,
    ident: NodeId<crate::symbol::Ident>,
    parameters: Vec<crate::ty::Parameters>,
    return_ty: Option<NodeId<crate::ty::Path>>,
    body: NodeId<crate::expression::Block>,
}
```

The macro generates a typed accessor for each field (`get_visibility`,
`get_ident`, …) alongside the impls laburnum needs to query the node from the
incremental tree.

## Attribute flags

| Flag             | Purpose                                                      |
| ---------------- | ------------------------------------------------------------ |
| `CST`            | Generate a concrete syntax tree node (trivia-preserving).    |
| `AST`            | Generate an abstract syntax tree node.                       |
| `error`          | Mark the node as an error/recovery node.                     |
| `allow_semantic` | Allow the node to participate in LSP semantic tokens.        |

Exactly one of `CST` or `AST` must be specified. `error` and `allow_semantic`
are optional modifiers that may be combined with either, e.g.
`#[laburnum_syntax(CST, error)]` or `#[laburnum_syntax(AST, allow_semantic)]`.

## Supported field shapes

The macro understands the field types commonly used by laburnum syntax trees:

- `Span` — the source span of the node
- `NodeId<T>` — a single child of type `T`
- `NodeId<T1, T2, ...>` — a child that can be one of several node types
- `Option<NodeId<T>>` — an optional child
- `Vec<T>` / `Vec<NodeId<T>>` — a list of children
- `Field<Enum<T>>` — a field carrying an enum value

Field names that would collide with Rust reserved keywords (e.g. `self_`,
`type_`) are rejected at macro expansion with a descriptive error.

## License

Licensed under the [Blue Oak Model License 1.0.0](https://blueoakcouncil.org/license/1.0.0).
