# tree-sitter-fsharp
tree-sitter grammar for F# (still WIP)
Based on [the 4.1 F# language specification](https://fsharp.org/specs/language-spec/4.1/FSharpSpec-4.1-latest.pdf) (Mostly, Appendix A)
and the [F# compiler parser](https://github.com/dotnet/fsharp/blob/main/src/Compiler/pars.fsy)
## Getting started
First, run `npm install` to install the `tree-sitter cli`.
Next, the grammar can be build using `npm run build`, or used to parse a file with `npm run parse $file`
### Project structure
This project defined two parser:
- [./fsharp/grammar.js](./fsharp/grammar.js)`fsharp` grammar.
- [./fsharp_signature/grammar.js](./fsharp_signature/grammar.js) defines the grammar for signature files
In addition to the `grammar.js` files each parser depends on a common external scanner found at [./common/scanner.h](./common/scanner.h).
The external scanner is responsible for parsing newlines and comments and keeps track of indentation to open and close scopes.
each grammar starts with the `file` node at the beginning of the rules.
### Adding to neovim
tree-sitter-fsharp isn't supported out-of-the box by [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter).
However, nvim-treesitter has [instructions for how to manually add unsupported parsers](https://github.com/nvim-treesitter/nvim-treesitter?tab=readme-ov-file#adding-parsers).
For tree-sitter-fsharp, this involves three steps:
1. Update your Neovim config for nvim-treesitter to refer to tree-sitter-fsharp.
2. Run `:TSInstall fsharp` inside Neovim.
3. Copy the files from [./queries/](./queries) to the neovim config directory at`$XDG_CONFIG_HOME/nvim/queries/fsharp/` - see [the Adding queries section of the nvim-treesitter README](https://github.com/nvim-treesitter/nvim-treesitter?tab=readme-ov-file#adding-queries).
The config you need is this (you can use a local path for `url` if you prefer):
```lua
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:
- `npm run build` rebuilds all parser.
- `npm test` runs all tests for both parsers.
- `npm run parse $file` run the `fsharp` parser on `$file` and outputs the parse tree.
- `npm run debug $file` run the `fsharp` parser on `$file` and prints debug information.
## 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](https://tree-sitter.github.io/tree-sitter/creating-parsers) is a good reference point.
PRs fleshing out the grammar or fixing bugs are welcome!