tree-sitter-pyrope
June 14, 2026 · View on GitHub
A tree-sitter grammar and parser for Pyrope, plus the tooling built on top of it.
What's in here
| Path | What it is |
|---|---|
grammar.js, src/ | The tree-sitter grammar and the generated parser. This is the package. |
queries/ | Editor queries — highlights.scm, indents.scm, folds.scm. |
editors/ | Editor integration (currently a Neovim / nvim-treesitter plugin). |
prpfmt/ | A Pyrope code formatter (C) that walks the tree-sitter tree. See prpfmt/README.md. |
prpparse/ | Design for a future recursive-descent parser for LiveHD (faster than tree-sitter, not for editors). See prpparse/plan.md. |
scripts/ | extract.rb (build the test corpus from docs) and test.sh (parse it). |
full_pyrope/ | Auto-generated test corpus (git-ignored — rebuild with make corpus). |
Build & test
The repo uses a single Makefile as the entry point. It needs tree-sitter-cli,
installed locally via npm:
npm install # one-time: installs node_modules/tree-sitter-cli
| Command | Does |
|---|---|
make / make generate | Regenerate src/parser.c from grammar.js. |
make test / make test-grammar | Parse all full_pyrope/*.prp — the canonical regression (must stay green). |
make test-all | Also run prpfmt + prpparse (prpfmt is WIP, so this may be red). |
make corpus | Rebuild full_pyrope/ from the Pyrope docs in ../docs. |
make prpfmt / make test-prpfmt | Build the formatter / verify it over the corpus. |
make clean | Clean build artifacts. |
Parsing a single file (debugging the grammar)
# Print the parse tree (-t adds timing):
./node_modules/tree-sitter-cli/tree-sitter parse -t ./full_pyrope/file1.prp
# Just check it parses (no tree), the way scripts/test.sh does:
./node_modules/tree-sitter-cli/tree-sitter parse -q ./full_pyrope/file1.prp
Syntax highlighting (Neovim)
Pyrope syntax highlighting in Neovim is provided through the nvim-treesitter plugin.
These instructions target the
mainbranch of nvim-treesitter (the current rewrite, used by recent LazyVim). The oldermaster-branch API (get_parser_configs(), manual query copying,:TSEnable) no longer applies.
lazy.nvim / LazyVim
Copy editors/nvim/pyrope.lua into your plugins
directory (e.g. ~/.config/nvim/lua/plugins/pyrope.lua). It registers the
parser from this repo, maps *.prp files to the pyrope filetype, and adds
pyrope to ensure_installed:
local function register_pyrope()
require("nvim-treesitter.parsers").pyrope = {
install_info = {
url = "https://github.com/masc-ucsc/tree-sitter-pyrope",
branch = "main",
queries = "queries",
},
}
end
return {
{
"nvim-treesitter/nvim-treesitter",
init = function()
vim.filetype.add({ extension = { prp = "pyrope" } })
vim.api.nvim_create_autocmd("User", {
pattern = "TSUpdate", -- re-register before every install/update
callback = register_pyrope,
})
-- Pyrope uses C-style comments; needed for `gc`/`gcc` commenting.
vim.api.nvim_create_autocmd("FileType", {
pattern = "pyrope",
callback = function()
vim.bo.commentstring = "// %s"
end,
})
end,
opts = function(_, opts)
opts.ensure_installed = opts.ensure_installed or {}
vim.list_extend(opts.ensure_installed, { "pyrope" })
end,
},
}
Restart Neovim (or :Lazy reload nvim-treesitter), then run :TSInstall pyrope.
The parser is registered on the
User TSUpdateevent, not once at startup. nvim-treesitter reloads its parser table from disk before every install/update (wiping runtime registrations) and re-fires this event so out-of-tree parsers can re-register. Registering only at startup yieldsskipping unsupported language: pyrope.
Plain nvim-treesitter (no LazyVim)
Add the following to your init.lua, then run :TSInstall pyrope:
vim.api.nvim_create_autocmd("User", {
pattern = "TSUpdate", -- re-register before every install/update
callback = function()
require("nvim-treesitter.parsers").pyrope = {
install_info = {
url = "https://github.com/masc-ucsc/tree-sitter-pyrope",
branch = "main",
queries = "queries",
},
}
end,
})
vim.filetype.add({ extension = { prp = "pyrope" } })
vim.api.nvim_create_autocmd("FileType", {
pattern = "pyrope",
callback = function()
vim.treesitter.start()
vim.bo.commentstring = "// %s" -- Pyrope uses C-style comments
end,
})
The queries = "queries" field installs this repo's queries/*.scm
(highlights, folds, indents) automatically — no manual copying needed.
Verify
Open a .prp file and check:
:set ft?showsfiletype=pyrope:checkhealth nvim-treesitterlistspyropeas installed:Inspecton a token shows the matched@captureand highlight group
Local development
To highlight from a local checkout instead of the public repo (so grammar and
query edits show up locally), replace url/branch with a path:
install_info = {
path = vim.fn.expand("~/projs/tree-sitter-pyrope"),
queries = "queries",
},
Query edits are picked up live (symlinked). After changing grammar.js, run
make generate and then :TSInstall! pyrope to rebuild the parser.
prpfmt
prpfmt is a Pyrope code formatter (think clang-format): it parses with the
tree-sitter grammar and re-emits standardized, vertically-aligned Pyrope. Build
it with make prpfmt; details and options are in prpfmt/README.md.
prpparse
prpparse is a fast, recursive-descent Pyrope parser intended for LiveHD (not
editors), using this grammar as a differential oracle. The parser is implemented
(Phases 0–3: lexer, tree schema, parser; accept-parity on all 428 corpus files)
and the next step is a streaming statement interface so the LiveHD front-end can
replace tree-sitter — see prpparse/plan.md.