tree-sitter-fsharp
July 29, 2026 · View on GitHub
tree-sitter grammar for F# (still WIP) Based on the 4.1 F# language specification (Mostly, Appendix A) and the F# compiler parser
Using the grammar
If you just want to use the F# parsers rather than work on the grammar, install the package for your ecosystem — each has its own usage guide:
| Ecosystem | Package | Guide |
|---|---|---|
| Node.js | npm: tree-sitter-fsharp | bindings/node/README.md |
| Python | PyPI: tree-sitter-fsharp | bindings/python/README.md |
| Rust | crates.io: tree-sitter-fsharp | bindings/rust/README.md |
| Go | github.com/ionide/tree-sitter-fsharp/bindings/go | bindings/go/README.md |
| Swift | SwiftPM: TreeSitterFsharp | bindings/swift/README.md |
| C | built from source (make / CMake) | bindings/c/README.md |
| Neovim | via nvim-treesitter | below |
The rest of this README covers building and developing the grammar itself.
Getting started
First, run npm install to install the tree-sitter CLI as a local devDependency (it lands at node_modules/.bin/tree-sitter, not on your global $PATH).
Run the CLI with npx tree-sitter <command> — this resolves the local binary automatically. To regenerate both parsers use npm run generate.
To parse a file: npx tree-sitter parse <file> (see the Development section for more).
Project structure
This project defines two parsers:
- ./fsharp/grammar.js — grammar for
.fs/.fsx(source files). - ./fsharp_signature/grammar.js — grammar for
.fsi(signature files). This is not a standalone grammar: it starts withgrammar(require("../fsharp/grammar"), { ... })and overrides/adds a few rules on top of the base. Any change tofsharp/grammar.jsalso changes the derived signature grammar, so both parsers must be regenerated together (npm run generate).
Both parsers share the external scanner at ./common/scanner.h. The per-parser src/scanner.c files are thin shims that #include the header — real scanner logic (newlines, comments, indent/dedent bookkeeping) lives in the header. Each grammar starts with the file node.
The generated src/grammar.json and src/parser.c files are checked into git and validated by CI. Do not hand-edit them; merge conflicts are resolved by re-running npm run generate. See AGENTS.md for the full development workflow.
Adding to neovim
tree-sitter-fsharp is supported through the usual installation methods of nvim-treesitter.
Installing the lastest grammar from this repo involves the following three steps:
- Update your Neovim config for nvim-treesitter to refer to tree-sitter-fsharp.
- Run
:TSInstall fsharpinside Neovim. - Copy the files from ./queries/ to the neovim config directory at
$XDG_CONFIG_HOME/nvim/queries/fsharp/- see the Adding queries section of the nvim-treesitter README.
The config you need is this (you can use a local path for url if you prefer):
local parser_config = require('nvim-treesitter.parsers').get_parser_configs()
parser_config.fsharp = {
install_info = {
url = 'https://github.com/ionide/tree-sitter-fsharp',
branch = 'main',
files = { 'src/scanner.c', 'src/parser.c' },
location = "fsharp"
},
requires_generate_from_grammar = false,
filetype = 'fsharp',
}
Development
The package.json defines some helpful targets for developing the grammar:
- Run commands from the repository root so tree-sitter picks up both grammars from
tree-sitter.json. npm run generaterebuilds both parsers.npx tree-sitter testruns all tests for both parsers.npx tree-sitter parse $fileruns thefsharpparser on$fileand outputs the parse tree.npx tree-sitter parse -d $fileruns thefsharpparser on$fileand prints debug information.- For
.fsifiles, usenpx tree-sitter parse -p fsharp_signature $filebecausetree-sitter parsedoes not reliably select the signature parser automatically.
How to contribute
Clone the project and start playing around with it.
If you find a code example which fails to parse, please reduce it to a minimal example and added to the corpus (fsharp/test/corpus/*.txt) as a test case.
For an introduction to developing tree-sitter parsers the official documentation is a good reference point.
PRs fleshing out the grammar or fixing bugs are welcome!