tree-sitter-awsum
May 25, 2026 · View on GitHub
Tree-sitter grammar for the Awsum programming language (.aww files).
The grammar drives syntax highlighting and the outline view in tree-sitter-aware editors — Zed (via the awsum-zed extension), Helix, Neovim, Emacs ts-mode. Precise diagnostics never come from this grammar; they come from the official Awsum compiler's Language Server (awsum lsp), which runs the real Megaparsec parser + typechecker and pushes results through LSP.
The grammar is tested against every .aww program in the compiler's test corpus (awsum/test/sources/successful/ and awsum/test/sources/property/) — see How the grammar is verified against the compiler below. Anything those programs use, this grammar parses without error.
How layout works
An external scanner (src/scanner.c) maintains an indent stack with one entry per active block. Six external tokens drive it:
_layout_open/_let_open— pushed when the parser seesdo/of/let. Captures the column of the first token inside the block plus the current paren-depth._layout_end— sibling separator inside a block (column == top of stack); also serves as the top-level boundary on a column-0 newline / EOF._layout_close— block exit: column < top of stack, EOF inside a block, or an enclosing)that's about to close._paren_open/_paren_close— every(/)is routed through the scanner so paren-depth stays accurate. Layout tokens are suppressed while the current paren-depth exceeds the depth captured at block-open, which is what lets a multi-line(…)span layout boundaries cleanly.
The literal 'in' keyword stays in the grammar as a regular tree-sitter token, matched by keyword-extraction in FOLLOW(_layout_close).
Build
npm install # install the tree-sitter CLI
npx tree-sitter generate # produce src/parser.c from grammar.js
npx tree-sitter test # run the corpus tests under test/corpus/
How the grammar is verified against the compiler
Three test layers — all live in the compiler repo (awsum/), under a standalone tree-sitter-tests test-suite gated by a cabal flag so it doesn't run on CI:
-
Corpus. Every
.awwunderawsum/test/sources/successful/andawsum/test/sources/property/is parsed by this grammar and asserted to produce no(ERROR …)/(MISSING …)nodes. These are the canonical surface-syntax fixtures the compiler itself accepts; if tree-sitter can't parse them, the grammar drifted from the language. -
Queries. Every
.scmundertree-sitter-awsum/queries/is run against every.awwin the corpus viatree-sitter queryand asserted to produce noQuery error/Invalid node type/Query compilation failed. Catches grammar/queries drift — when a grammar change renames or hides a node type, the queries that reference it now have nowhere to bind, but the tree-sitter CLI prints those errors to stdout while exiting 0, so neithertree-sitter generatenor parse-only checks would notice. -
Property. For each QuickCheck-generated
Program, render it via the compiler'sAwsum.Render.renderProgram(the same pipelineawsum formatuses), feed the output totree-sitter parse, and assert the same no-error invariant. Drives the grammar past the corpus into rare combinations that arbitrary generation hits.
Run from inside awsum/:
just test-tree-sitter # corpus only — fast, deterministic
just test-tree-sitter-property # property only — slow, ~100 generated programs
Both recipes regenerate src/parser.c from grammar.js first and require:
- This repo (
tree-sitter-awsum/) checked out next toawsum/, orTREE_SITTER_AWSUM_DIRset to its path. node_modules/populated inside it (npm ci). The compiler-side recipes invokenpx tree-sitterand the Haskell spec callsnode_modules/.bin/tree-sitterdirectly — both deliberately ignore any globaltree-sitterbinary so the version pinned in this repo'spackage-lock.jsonis the only one that runs.
If either is missing, the test-suite falls back to a single pendingWith and the rest of the (compiler-side) test suite is unaffected.
Versioning
tree-sitter-awsum releases follow the awsum compiler version one-to-one: tree-sitter-awsum A.B.C is built and tested against awsum A.B.C. Same lockstep convention as awsum-vscode and awsum-zed.
AI use
This Tree-sitter grammar is developed with substantial usage of generative AI. Every generated change is reviewed, edited, and accepted by a human before it lands in the repository, and no output is shipped unedited.