Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

AST query DSL

A tree-sitter-flavoured pattern DSL selects nodes / tokens from the concrete syntax tree. Editor surfaces (LSP textDocument/documentHighlight, “find all ruby annotations”, refactoring filters, syntax-aware search) compose against the DSL instead of re-implementing tree walks.

The DSL ships behind the query Cargo feature on the aozora crate; that feature also enables cst since queries run against SyntaxNode.

Quickstart

use aozora::Document;
use aozora::query::compile;

let doc = Document::new("|青梅《おうめ》と|青空《あおぞら》");
let cst = aozora::cst::from_tree(&doc.parse());
let query = compile("(Construct @ruby)").expect("compile");
for capture in query.captures(&cst) {
    println!("{} -> {:?}", capture.name, capture.node);
}

Grammar

query   := pattern ('\n' pattern)* '\n'?
pattern := '(' kind capture? ')'
         | '(' '_'  capture? ')'
kind    := SyntaxKind ident      // e.g. `Construct`, `Container`
capture := '@' ident
ident   := [A-Za-z_][A-Za-z0-9_-]*
  • (Construct) — match every Construct node.
  • (Construct @ruby) — capture each Construct under the name ruby.
  • (_) — match any kind (node or token).
  • (_ @any) — combined; tour every kind in preorder.
  • Multiple patterns separated by newlines run as an OR — every matching node yields one Capture per pattern that hits.

Execution model

The DSL compiles once into a Vec<Pattern>; the engine then tests every pattern at every preorder step (O(nodes × patterns)). The small capture-only surface keeps the implementation tight while the predicate / field-access / alternation extensions wait for a concrete consumer ask.

Not yet supported

  • Predicates (#eq?, #match?) — the tree-sitter query language exposes per-capture filters. The DSL ships without them; consumers filter the resulting [Capture] vec in Rust.
  • Field accessors ((Container body: (Construct))) — the CST has no named fields yet.
  • Quantifiers ((...)?, (...)*, (...)+).
  • Alternation [...] between patterns.

These extensions are forward-compatible with the existing API shape (compilecaptures); a future release can land them without breaking existing queries.

Cross-references