Regenerate the parser from grammar.js

June 24, 2026 · View on GitHub

// SPDX-License-Identifier: CC-BY-SA-4.0 // Copyright (c) Jonathan D.A. Jewell j.d.a.jewell@open.ac.uk // SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell j.d.a.jewell@open.ac.uk = tree-sitter-k9 image:https://img.shields.io/badge/OpenSSF-Best_Practices-green?logo=openssourcesecurity[OpenSSF Best Practices,link="https://www.bestpractices.dev/en/projects/new?repo_url=https://github.com/hyperpolymath/tree-sitter-k9"]

:toc: preamble :icons: font :author: Jonathan D.A. Jewell :email: j.d.a.jewell@open.ac.uk

Tree-sitter grammar for the K9 configuration format — dual-syntax: Kennel and Yard/Hunt.

image:https://img.shields.io/badge/License-MPL_2.0-blue.svg[License: MPL-2.0,link="https://opensource.org/licenses/MPL-2.0"] image:https://img.shields.io/badge/tree--sitter-grammar-blue.svg[Tree-sitter] image:https://img.shields.io/badge/format-K9-green.svg[K9]

== What this is

tree-sitter-k9 provides a generated C parser for both K9 syntax variants:

  • Kennel level (.k9) — a YAML-like format with key: value pairs and pedigree blocks
  • Yard/Hunt level (.k9.ncl) — a Nickel-derived format with let bindings, type annotations, contracts, and recipe blocks

Both variants share:

  • A mandatory K9! magic number on line 1
  • Trust levels: 'Kennel, 'Yard, 'Hunt
  • A pedigree block (name, version, description, security level)

== Quick start

[source,bash]

Regenerate the parser from grammar.js

just generate

Run corpus tests

just test

Benchmark parse speed

just bench

Build language bindings

just build-bindings

== Grammar structure

The grammar.js document rule is:

[source,javascript]

seq( magic_number, optional(header_block), choice(record_literal, kennel_body) )

record_literal handles .k9.ncl (Nickel-derived); kennel_body handles .k9 (YAML-like). A PREC table resolves expression ambiguities in the Nickel branch (function application: 7, multiplication: 5, …, pipe: 0).

== Editor integration

[cols="2,3", options="header"] |=== | File | Purpose

| queries/highlights.scm | K9-specific captures: magic_number@keyword.directive, trust_level@constant.builtin, enum_tag@constant, pedigree_block@keyword.type

| queries/locals.scm | Scope captures for let-bindings in .k9.ncl (jump-to-definition) |===

== Deno integration

[source,javascript]

import { parser } from "jsr:@hyperpolymath/tree-sitter-k9";

const tree = parser.parse(k9Source); // Access pedigree fields directly by name via named nodes

== File map

[cols="2,3", options="header"] |=== | Path | What it contains

| grammar.js | Authoritative grammar: dual-syntax rules, PREC table, trust-level nodes

| src/parser.c | Generated C parser (do not edit — regenerate with just generate)

| src/grammar.json | Serialised grammar

| src/node-types.json | Node type manifest

| queries/highlights.scm | Highlight captures for both K9 variants

| queries/locals.scm | Scope captures for .k9.ncl let-bindings

| bindings/ | Auto-generated: Node.js, Python, Rust

| test/ | Tree-sitter corpus tests for .k9 and .k9.ncl

| tests/ | Extended integration tests against real K9 files |===

== K9 ecosystem

See link:EXPLAINME.adoc[EXPLAINME.adoc] for implementation evidence and caveats.

== License

This project is licensed under the Mozilla Public License, v. 2.0. See the LICENSE file for details.

SPDX-License-Identifier: CC-BY-SA-4.0

== Author

Jonathan D.A. Jewell + j.d.a.jewell@open.ac.uk