Merge remote-tracking branch 'thecentury/f#'

pull/625/head
Wilfred Hughes 2024-05-14 09:46:55 +07:00
commit d92b65c5fd
44 changed files with 627592 additions and 0 deletions

@ -153,6 +153,11 @@ fn main() {
src_dir: "vendored_parsers/tree-sitter-erlang-src",
extra_files: vec![],
},
TreeSitterParser {
name: "tree-sitter-f-sharp",
src_dir: "vendored_parsers/tree-sitter-f-sharp-src",
extra_files: vec!["scanner.cc"],
},
TreeSitterParser {
name: "tree-sitter-gleam",
src_dir: "vendored_parsers/tree-sitter-gleam-src",

@ -24,6 +24,7 @@ with `difft --list-languages`.
| Elvish | [ckafi/tree-sitter-elvish](https://github.com/ckafi/tree-sitter-elvish) |
| Erlang | [WhatsApp/tree-sitter-erlang](https://github.com/WhatsApp/tree-sitter-erlang) |
| Emacs Lisp | [wilfred/tree-sitter-elisp](https://github.com/Wilfred/tree-sitter-elisp) |
| F# | [Nsidorenco/tree-sitter-fsharp](https://github.com/Nsidorenco/tree-sitter-fsharp) |
| Gleam | [gleam-lang/tree-sitter-gleam](https://github.com/gleam-lang/tree-sitter-gleam) |
| Go | [tree-sitter/tree-sitter-go](https://github.com/tree-sitter/tree-sitter-go) |
| Hack | [slackhq/tree-sitter-hack](https://github.com/slackhq/tree-sitter-hack) |

@ -67,6 +67,9 @@ f80b47646e7dd2bd3a49393d00657465 -
sample_files/erlang_1.erl sample_files/erlang_2.erl
dccdb8f65d2f099ab1a8cb66011376a2 -
sample_files/f_sharp_1.fs sample_files/f_sharp_2.fs
6ba65e62a804124f56bdfb19afc8cd40 -
sample_files/hack_1.php sample_files/hack_2.php
c2bb0aa7d7b07d6ced79f6a5363e878b -

@ -0,0 +1,13 @@
namespace X
open System
type A = A of int
type Record = { A : string }
module M =
let f x = x + 1
let list = []

@ -0,0 +1,22 @@
namespace X
open System
open System.IO
type A =
| A of int
| B of string
type Record = {
A : string
B : int
}
module M =
let f y = y + 1
let list = [
"a"
"b"
]

@ -35,6 +35,7 @@ pub(crate) enum Language {
Elvish,
EmacsLisp,
Erlang,
FSharp,
Gleam,
Go,
Hack,
@ -127,6 +128,7 @@ pub(crate) fn language_name(language: Language) -> &'static str {
Elvish => "Elvish",
EmacsLisp => "Emacs Lisp",
Erlang => "Erlang",
FSharp => "F#",
Gleam => "Gleam",
Go => "Go",
Hack => "Hack",
@ -262,6 +264,7 @@ pub(crate) fn language_globs(language: Language) -> Vec<glob::Pattern> {
"*.yrl",
"Emakefile",
],
FSharp => &["*.fs", "*.fsx", "*.fsi"],
Gleam => &["*.gleam"],
Go => &["*.go"],
Hack => &["*.hack", "*.hck", "*.hhi"],
@ -510,6 +513,7 @@ fn from_emacs_mode_header(src: &str) -> Option<Language> {
"elm" => Some(Elm),
"elvish" => Some(Elvish),
"emacs-lisp" => Some(EmacsLisp),
"fsharp" => Some(FSharp),
"gleam" => Some(Gleam),
"go" => Some(Go),
"haskell" => Some(Haskell),

@ -77,6 +77,7 @@ extern "C" {
fn tree_sitter_elm() -> ts::Language;
fn tree_sitter_elvish() -> ts::Language;
fn tree_sitter_erlang() -> ts::Language;
fn tree_sitter_fsharp() -> ts::Language;
fn tree_sitter_gleam() -> ts::Language;
fn tree_sitter_go() -> ts::Language;
fn tree_sitter_hare() -> ts::Language;
@ -411,6 +412,20 @@ pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig {
sub_languages: vec![],
}
}
FSharp => {
let language = unsafe { tree_sitter_fsharp() };
TreeSitterConfig {
language,
atom_nodes: ["string", "triple_quoted_string"].into(),
delimiter_tokens: vec![("(", ")"), ("[", "]"), ("{", "}")],
highlight_query: ts::Query::new(
language,
include_str!("../../vendored_parsers/highlights/f-sharp.scm"),
)
.unwrap(),
sub_languages: vec![],
}
}
Gleam => {
let language = unsafe { tree_sitter_gleam() };
TreeSitterConfig {

@ -0,0 +1 @@
../tree-sitter-f-sharp/queries/highlights.scm

@ -0,0 +1 @@
tree-sitter-f-sharp/src

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
- package-ecosystem: "cargo" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

@ -0,0 +1,21 @@
name: Build/test
on:
pull_request:
push:
branches:
- "develop"
- "main"
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- run: npm install
- run: npm test

@ -0,0 +1,53 @@
name: Build/release
on:
workflow_dispatch:
permissions:
contents: write
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v3
with:
ref: "develop"
- uses: actions/setup-node@v2
with:
node-version: 16
- run: npm install
- run: npm test
release:
runs-on: ubuntu-latest
steps:
- name: Checkout develop branch
uses: actions/checkout@v3
with:
ref: "develop"
- name: Fetch main branch
run: |
git fetch origin main
git branch -t main origin/main
- name: "remove src/parser.c from .gitignore"
run: sed -i '/src\/parser.c/d' .gitignore
- uses: actions/setup-node@v2
with:
node-version: 16
- name: "compile main branch"
run: |
npm install
npm run build
- name: Merge into main branch and publish
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
git add .
tree=$(git write-tree)
commit=$(git commit-tree -p main -p develop -m "release" $tree)
git update-ref refs/heads/main $commit
git push origin main

@ -0,0 +1,8 @@
Cargo.lock
package-lock.json
node_modules
build
*.log
examples/*
*.o
*.so

@ -0,0 +1,26 @@
[package]
name = "tree-sitter-fsharp"
description = "fsharp grammar for the tree-sitter parsing library"
version = "0.0.1"
keywords = ["incremental", "parsing", "fsharp"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/nsidorenco/tree-sitter-fsharp"
edition = "2018"
license = "MIT"
build = "bindings/rust/build.rs"
include = [
"bindings/rust/*",
"grammar.js",
"queries/*",
"src/*",
]
[lib]
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = "~0.20"
[build-dependencies]
cc = "1.0"

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Nikolaj Sidorenco
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,79 @@
# 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
The parser consists of two parts:
- `src/scanner.cc` is responsible for parsing newlines and comments and keeps track of indentation to open and close scopes.
- `grammar.js` the main tree-sitter grammar. The indent tokens from the external scanner is access though the `$.virtual_open_section` and `virtual_end_section` tokens.
The grammar starts with the `file` node at the begging of the rules.
### Adding to neovim
#### From the local copy:
```lua
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
parser_config.fsharp = {
install_info = {
url = "path/to/tree-sitter-fsharp",
files = {"src/scanner.cc", "src/parser.c" }
},
filetype = "fsharp",
}
```
#### From GitHub repository:
```lua
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
parser_config.fsharp = {
install_info = {
url = "https://github.com/Nsidorenco/tree-sitter-fsharp",
branch = "develop",
files = {"src/scanner.cc", "src/parser.c" },
generate_requires_npm = true,
requires_generate_from_grammar = true
},
filetype = "fsharp",
}
```
Then run `:TSInstallFromGrammar fsharp` inside Nvim.
## Status
The grammar currently has support for most language features, but might have rough edges.
Some parts, like the type annotations are still very bare-bones.
The grammar supports indentation-based scoping but does not fully support offside indentation and opening new indentation levels on record/list construction.
The precedence rules for the different grammar nodes (and particularly expressions) are not set properly yet, which means that the parser size is much larger than needed.
### Missing
- [ ] Computational expressions
- [ ] Type annotations
- [x] Annotations
- [ ] Offside tokens inside indentation scope
- [ ] Testing
- [ ] Set properly precedence rules
## Testing
### Testing corpus
To run all tests stores in `corpus/` run
```sh
$ npm test
```
### Test parsing a specific file
```
$ npm run debug $file
```
## How to contribute
Clone the repo and start playing around with it.
If you find a code example which fails to parse, please reduce it to a minimal example, such that it can be added to the corpus as a test case.
PRs fleshing out the grammar or fixing bugs are very welcome!

@ -0,0 +1,28 @@
{
"targets": [
{
"target_name": "tree_sitter_fsharp_binding",
"include_dirs": [
"<!(node -e \"require('nan')\")",
"src"
],
"sources": [
"bindings/node/binding.cc",
"src/parser.c",
"src/scanner.cc",
],
"cflags_c": [
"-std=c99",
],
'actions': [
{
'action_name': 'generate parser',
'inputs': ['grammar.js'],
'outputs': ['src'],
'action': ['tree-sitter', 'generate'],
'message': 'generated parser'
}
],
}
]
}

@ -0,0 +1,28 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"
using namespace v8;
extern "C" TSLanguage * tree_sitter_fsharp();
namespace {
NAN_METHOD(New) {}
void Init(Local<Object> exports, Local<Object> module) {
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_fsharp());
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("fsharp").ToLocalChecked());
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_fsharp_binding, Init)
} // namespace

@ -0,0 +1,19 @@
try {
module.exports = require("../../build/Release/tree_sitter_fsharp_binding");
} catch (error1) {
if (error1.code !== 'MODULE_NOT_FOUND') {
throw error1;
}
try {
module.exports = require("../../build/Debug/tree_sitter_fsharp_binding");
} catch (error2) {
if (error2.code !== 'MODULE_NOT_FOUND') {
throw error2;
}
throw error1
}
}
try {
module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}

@ -0,0 +1,40 @@
fn main() {
let src_dir = std::path::Path::new("src");
let mut c_config = cc::Build::new();
c_config.include(&src_dir);
c_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable")
.flag_if_supported("-Wno-trigraphs");
let parser_path = src_dir.join("parser.c");
c_config.file(&parser_path);
// If your language uses an external scanner written in C,
// then include this block of code:
/*
let scanner_path = src_dir.join("scanner.c");
c_config.file(&scanner_path);
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
*/
c_config.compile("parser");
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
// If your language uses an external scanner written in C++,
// then include this block of code:
/*
let mut cpp_config = cc::Build::new();
cpp_config.cpp(true);
cpp_config.include(&src_dir);
cpp_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable");
let scanner_path = src_dir.join("scanner.cc");
cpp_config.file(&scanner_path);
cpp_config.compile("scanner");
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
*/
}

@ -0,0 +1,52 @@
//! This crate provides fsharp language support for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [language][language func] function to add this language to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! let code = "";
//! let mut parser = tree_sitter::Parser::new();
//! parser.set_language(tree_sitter_fsharp::language()).expect("Error loading fsharp grammar");
//! let tree = parser.parse(code, None).unwrap();
//! ```
//!
//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
//! [language func]: fn.language.html
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/
use tree_sitter::Language;
extern "C" {
fn tree_sitter_fsharp() -> Language;
}
/// Get the tree-sitter [Language][] for this grammar.
///
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
pub fn language() -> Language {
unsafe { tree_sitter_fsharp() }
}
/// The content of the [`node-types.json`][] file for this grammar.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
// Uncomment these to include any queries that this grammar contains
// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
#[cfg(test)]
mod tests {
#[test]
fn test_can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(super::language())
.expect("Error loading fsharp language");
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,27 @@
{
"name": "tree-sitter-fsharp",
"version": "1.0.0",
"description": "",
"repository": "https://github.com/tree-sitter/tree-sitter-fsharp",
"main": "bindings/node",
"scripts": {
"build": "tree-sitter generate",
"test": "tree-sitter generate && tree-sitter test",
"parse": "tree-sitter generate && tree-sitter parse",
"debug": "tree-sitter generate && tree-sitter parse -d"
},
"author": "Nikolaj Sidorenco",
"license": "MIT",
"dependencies": {
"nan": "^2.16.0"
},
"devDependencies": {
"tree-sitter-cli": "^0.20.6"
},
"tree-sitter": [
{
"scope": "source.fsharp",
"file-types": [ "fs", "fsx"]
}
]
}

@ -0,0 +1,196 @@
;; ----------------------------------------------------------------------------
;; Literals and comments
[
(line_comment)
(block_comment)
(block_comment_content)
] @comment
;; ----------------------------------------------------------------------------
;; Punctuation
[
"("
")"
"{"
"}"
"["
"]"
"[|"
"|]"
"[<"
">]"
] @punctuation.bracket
[
","
";"
] @punctuation.delimiter
[
"|"
"="
">"
"<"
"-"
"~"
(infix_op)
(prefix_op)
(symbolic_op)
] @operator
(attribute) @attribute
[
"if"
"then"
"else"
"elif"
"when"
"match"
"match!"
"and"
"or"
"&&"
"||"
"then"
] @keyword.control.conditional
[
"return"
"return!"
] @keyword.control.return
[
"for"
"while"
] @keyword.control.return
[
"open"
"#r"
"#load"
] @keyword.control.import
[
"abstract"
"delegate"
"static"
"inline"
"internal"
"mutable"
"override"
"private"
"public"
"rec"
] @keyword.storage.modifier
[
"enum"
"let"
"let!"
"member"
"module"
"namespace"
"type"
] @keyword.storage
[
"as"
"assert"
"begin"
"default"
"do"
"do!"
"done"
"downcast"
"downto"
"end"
"event"
"field"
"finally"
"fun"
"function"
"get"
"global"
"inherit"
"interface"
"lazy"
"new"
"not"
"null"
"of"
"param"
"property"
"set"
"struct"
"try"
"upcast"
"use"
"use!"
"val"
"with"
"yield"
"yield!"
] @keyword
[
"true"
"false"
"unit"
] @constant.builtin
[
(type)
(const)
] @constant
[
(union_type_case)
(rules (rule (identifier_pattern)))
] @type.enum
(fsi_directive_decl (string) @namespace)
[
(import_decl (long_identifier))
(named_module (long_identifier))
(namespace (long_identifier))
(named_module
name: (long_identifier) )
(namespace
name: (long_identifier) )
] @namespace
(dot_expression
base: (long_identifier_or_op) @variable.other.member
field: (long_identifier_or_op) @function)
[
;;(value_declaration_left (identifier_pattern) )
(function_declaration_left (identifier) )
(call_expression (long_identifier_or_op (long_identifier)))
;;(application_expression (long_identifier_or_op (long_identifier)))
] @function
[
(string)
(triple_quoted_string)
] @string
[
(int)
(int16)
(int32)
(int64)
(float)
(decimal)
] @constant.numeric

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,372 @@
#include <tree_sitter/parser.h>
#include <vector>
#include <utility>
#include <cwctype>
#include <cstring>
#include <cassert>
#include <stdio.h>
#include <string>
#include <algorithm>
namespace {
using std::vector;
using std::string;
enum TokenType {
VIRTUAL_OPEN_SECTION,
VIRTUAL_END_SECTION,
VIRTUAL_END_ALIGNED,
BLOCK_COMMENT_CONTENT,
};
bool in_error_recovery(const bool *valid_symbols) {
return
(valid_symbols[VIRTUAL_OPEN_SECTION] &&
valid_symbols[VIRTUAL_END_SECTION] &&
valid_symbols[VIRTUAL_END_ALIGNED]);
}
struct Scanner {
Scanner() { }
unsigned serialize(char *buffer) {
size_t i = 0;
size_t runback_count = runback.size();
if (runback_count > UINT8_MAX)
runback_count = UINT8_MAX;
buffer[i++] = runback_count;
if (runback_count > 0)
{
memcpy(&buffer[i], runback.data(), runback_count);
}
i += runback_count;
size_t indent_length_length = sizeof(indent_length);
buffer[i++] = indent_length_length;
if (indent_length_length > 0)
{
memcpy(&buffer[i], &indent_length, indent_length_length);
}
i += indent_length_length;
vector<uint32_t>::iterator
iter = indent_length_stack.begin() + 1,
end = indent_length_stack.end();
for (; iter != end && i < TREE_SITTER_SERIALIZATION_BUFFER_SIZE; ++iter)
{
buffer[i++] = *iter;
}
return i;
}
void deserialize(const char *buffer, unsigned length) {
runback.clear();
indent_length_stack.clear();
indent_length_stack.push_back(0);
if (length > 0)
{
size_t i = 0;
size_t runback_count = (uint8_t)buffer[i++];
runback.resize(runback_count);
if (runback_count > 0)
{
memcpy(runback.data(), &buffer[i], runback_count);
}
i += runback_count;
size_t indent_length_length = buffer[i++];
if (indent_length_length > 0)
{
memcpy(&indent_length, &buffer[i], indent_length_length);
}
i += indent_length_length;
for (; i < length; i++)
{
indent_length_stack.push_back(buffer[i]);
}
}
}
void advance(TSLexer *lexer) {
lexer->advance(lexer, false);
}
void skip(TSLexer *lexer) {
lexer->advance(lexer, true);
}
bool isWS(TSLexer *lexer) {
return lexer->lookahead == ' ' || lexer->lookahead == '\r' || lexer->lookahead == '\n';
}
bool scan_block_comment(TSLexer *lexer) {
lexer->mark_end(lexer);
if (lexer->lookahead != '(')
return false;
advance(lexer);
if (lexer->lookahead != '*')
return false;
advance(lexer);
while (true) {
switch (lexer->lookahead) {
case '(':
scan_block_comment(lexer);
break;
case '*':
advance(lexer);
if (lexer->lookahead == ')') {
advance(lexer);
return true;
}
break;
case '\0':
return true;
default:
advance(lexer);
}
}
}
void advance_to_line_end(TSLexer *lexer) {
while (true) {
if (lexer->lookahead == '\n') {
break;
} else if (lexer->eof(lexer)) {
break;
} else {
advance(lexer);
}
}
}
bool scan(TSLexer *lexer, const bool *valid_symbols) {
if (in_error_recovery(valid_symbols))
return false;
// First handle eventual runback tokens, we saved on a previous scan op
if (!runback.empty() && runback.back() == 0 && valid_symbols[VIRTUAL_END_ALIGNED])
{
runback.pop_back();
lexer->result_symbol = VIRTUAL_END_ALIGNED;
return true;
}
if (!runback.empty() && runback.back() == 1 && valid_symbols[VIRTUAL_END_SECTION])
{
runback.pop_back();
lexer->result_symbol = VIRTUAL_END_SECTION;
return true;
}
runback.clear();
// Check if we have newlines and how much indentation
bool has_newline = false;
bool can_call_mark_end = true;
lexer->mark_end(lexer);
while (true) {
if (lexer->lookahead == ' ') {
skip(lexer);
}
else if (lexer->lookahead == '\n') {
skip(lexer);
has_newline = true;
while (true)
{
if (lexer->lookahead == ' ')
{
skip(lexer);
}
else
{
indent_length = lexer->get_column(lexer);
break;
}
}
}
else if (lexer->lookahead == '\r') {
skip(lexer);
}
else if (valid_symbols[VIRTUAL_END_ALIGNED] && lexer->lookahead == ';') {
advance(lexer);
lexer->mark_end(lexer);
lexer->result_symbol = VIRTUAL_END_ALIGNED;
return true;
}
else if (valid_symbols[VIRTUAL_END_SECTION] && lexer->lookahead == ')') {
lexer->result_symbol = VIRTUAL_END_SECTION;
indent_length_stack.pop_back();
return true;
}
else if (valid_symbols[VIRTUAL_END_SECTION] && lexer->lookahead == ']') {
lexer->result_symbol = VIRTUAL_END_SECTION;
indent_length_stack.pop_back();
return true;
}
else if (valid_symbols[VIRTUAL_END_SECTION] && lexer->lookahead == '}') {
lexer->result_symbol = VIRTUAL_END_SECTION;
indent_length_stack.pop_back();
return true;
}
else if (valid_symbols[VIRTUAL_END_SECTION] && lexer->lookahead == '|') {
skip(lexer);
if (lexer->lookahead == '}' || lexer->lookahead == ']') {
lexer->result_symbol = VIRTUAL_END_SECTION;
indent_length_stack.pop_back();
return true;
}
}
else if (lexer->eof(lexer)) {
if (valid_symbols[VIRTUAL_END_SECTION])
{
lexer->result_symbol = VIRTUAL_END_SECTION;
return true;
}
if (valid_symbols[VIRTUAL_END_ALIGNED])
{
lexer->result_symbol = VIRTUAL_END_ALIGNED;
return true;
}
break;
}
else { break; }
}
bool closing = lexer->lookahead == ']' || lexer->lookahead == ')' || lexer->lookahead == '}';
// Open section if the grammar lets us but only push to indent stack if we go further down in the stack
if (valid_symbols[VIRTUAL_OPEN_SECTION] && !lexer->eof(lexer)) {
indent_length_stack.push_back(lexer->get_column(lexer));
if (closing) {
return false;
}
if (lexer->lookahead == '|') {
skip(lexer);
if (lexer->lookahead == '}' || lexer->lookahead == ']') {
return false;
}
}
lexer->result_symbol = VIRTUAL_OPEN_SECTION;
return true;
}
else if (valid_symbols[BLOCK_COMMENT_CONTENT]) {
if (!can_call_mark_end) { return false; }
lexer->mark_end(lexer);
while (true) {
if (lexer->lookahead == '\0') { break; }
if (lexer->lookahead != '(' && lexer->lookahead != '*') {
advance(lexer);
}
else if (lexer->lookahead == '*') {
lexer->mark_end(lexer);
advance(lexer);
if (lexer->lookahead == ')')
{
break;
}
}
else if (scan_block_comment(lexer))
{
lexer->mark_end(lexer);
advance(lexer);
if (lexer->lookahead == '*')
{
break;
}
}
}
lexer->result_symbol = BLOCK_COMMENT_CONTENT;
return true;
}
else if (has_newline) {
// We had a newline now it's time to check if we need to add multiple tokens to get back up to the right level
runback.clear();
while (indent_length <= indent_length_stack.back()) {
if (indent_length == indent_length_stack.back()) {
// Don't insert VIRTUAL_END_DECL when there is a line comment incoming
if (lexer->lookahead == '/') {
skip(lexer);
if (lexer->lookahead == '/') { break; }
}
// Don't insert VIRTUAL_END_DECL when there is a block comment incoming
if (lexer->lookahead == '(') {
skip(lexer);
if (lexer->lookahead == '*') { break; }
}
runback.push_back(0);
break;
}
else if (indent_length < indent_length_stack.back()) {
indent_length_stack.pop_back();
runback.push_back(1);
}
}
// Our list is the wrong way around, reverse it
std::reverse(runback.begin(), runback.end());
// Handle the first runback token if we have them, if there are more they will be handled on the next scan operation
if (!runback.empty() && runback.back() == 0 && valid_symbols[VIRTUAL_END_ALIGNED]) {
runback.pop_back();
lexer->result_symbol = VIRTUAL_END_ALIGNED;
return true;
}
if (!runback.empty() && runback.back() == 1 && valid_symbols[VIRTUAL_END_SECTION]) {
runback.pop_back();
lexer->result_symbol = VIRTUAL_END_SECTION;
return true;
}
else if (lexer->eof(lexer) && valid_symbols[VIRTUAL_END_SECTION]) {
lexer->result_symbol = VIRTUAL_END_SECTION;
return true;
}
}
return false;
}
uint32_t indent_length;
vector<uint32_t> indent_length_stack;
vector<uint8_t> runback;
};
} // namespace end
extern "C" {
void *tree_sitter_fsharp_external_scanner_create() {
return new Scanner();
}
bool tree_sitter_fsharp_external_scanner_scan(void *payload, TSLexer *lexer,
const bool *valid_symbols) {
Scanner *scanner = static_cast<Scanner *>(payload);
return scanner->scan(lexer, valid_symbols);
}
unsigned tree_sitter_fsharp_external_scanner_serialize(void *payload, char *buffer) {
Scanner *scanner = static_cast<Scanner *>(payload);
return scanner->serialize(buffer);
}
void tree_sitter_fsharp_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
Scanner *scanner = static_cast<Scanner *>(payload);
scanner->deserialize(buffer, length);
}
void tree_sitter_fsharp_external_scanner_destroy(void *payload) {
Scanner *scanner = static_cast<Scanner *>(payload);
delete scanner;
}
}

@ -0,0 +1,224 @@
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
typedef uint16_t TSStateId;
#ifndef TREE_SITTER_API_H_
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
#endif
typedef struct {
TSFieldId field_id;
uint8_t child_index;
bool inherited;
} TSFieldMapEntry;
typedef struct {
uint16_t index;
uint16_t length;
} TSFieldMapSlice;
typedef struct {
bool visible;
bool named;
bool supertype;
} TSSymbolMetadata;
typedef struct TSLexer TSLexer;
struct TSLexer {
int32_t lookahead;
TSSymbol result_symbol;
void (*advance)(TSLexer *, bool);
void (*mark_end)(TSLexer *);
uint32_t (*get_column)(TSLexer *);
bool (*is_at_included_range_start)(const TSLexer *);
bool (*eof)(const TSLexer *);
};
typedef enum {
TSParseActionTypeShift,
TSParseActionTypeReduce,
TSParseActionTypeAccept,
TSParseActionTypeRecover,
} TSParseActionType;
typedef union {
struct {
uint8_t type;
TSStateId state;
bool extra;
bool repetition;
} shift;
struct {
uint8_t type;
uint8_t child_count;
TSSymbol symbol;
int16_t dynamic_precedence;
uint16_t production_id;
} reduce;
uint8_t type;
} TSParseAction;
typedef struct {
uint16_t lex_state;
uint16_t external_lex_state;
} TSLexMode;
typedef union {
TSParseAction action;
struct {
uint8_t count;
bool reusable;
} entry;
} TSParseActionEntry;
struct TSLanguage {
uint32_t version;
uint32_t symbol_count;
uint32_t alias_count;
uint32_t token_count;
uint32_t external_token_count;
uint32_t state_count;
uint32_t large_state_count;
uint32_t production_id_count;
uint32_t field_count;
uint16_t max_alias_sequence_length;
const uint16_t *parse_table;
const uint16_t *small_parse_table;
const uint32_t *small_parse_table_map;
const TSParseActionEntry *parse_actions;
const char * const *symbol_names;
const char * const *field_names;
const TSFieldMapSlice *field_map_slices;
const TSFieldMapEntry *field_map_entries;
const TSSymbolMetadata *symbol_metadata;
const TSSymbol *public_symbol_map;
const uint16_t *alias_map;
const TSSymbol *alias_sequences;
const TSLexMode *lex_modes;
bool (*lex_fn)(TSLexer *, TSStateId);
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
TSSymbol keyword_capture_token;
struct {
const bool *states;
const TSSymbol *symbol_map;
void *(*create)(void);
void (*destroy)(void *);
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
unsigned (*serialize)(void *, char *);
void (*deserialize)(void *, const char *, unsigned);
} external_scanner;
const TSStateId *primary_state_ids;
};
/*
* Lexer Macros
*/
#define START_LEXER() \
bool result = false; \
bool skip = false; \
bool eof = false; \
int32_t lookahead; \
goto start; \
next_state: \
lexer->advance(lexer, skip); \
start: \
skip = false; \
lookahead = lexer->lookahead;
#define ADVANCE(state_value) \
{ \
state = state_value; \
goto next_state; \
}
#define SKIP(state_value) \
{ \
skip = true; \
state = state_value; \
goto next_state; \
}
#define ACCEPT_TOKEN(symbol_value) \
result = true; \
lexer->result_symbol = symbol_value; \
lexer->mark_end(lexer);
#define END_STATE() return result;
/*
* Parse Table Macros
*/
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
#define STATE(id) id
#define ACTIONS(id) id
#define SHIFT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value \
} \
}}
#define SHIFT_REPEAT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value, \
.repetition = true \
} \
}}
#define SHIFT_EXTRA() \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.extra = true \
} \
}}
#define REDUCE(symbol_val, child_count_val, ...) \
{{ \
.reduce = { \
.type = TSParseActionTypeReduce, \
.symbol = symbol_val, \
.child_count = child_count_val, \
__VA_ARGS__ \
}, \
}}
#define RECOVER() \
{{ \
.type = TSParseActionTypeRecover \
}}
#define ACCEPT_INPUT() \
{{ \
.type = TSParseActionTypeAccept \
}}
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_PARSER_H_

@ -0,0 +1,131 @@
================================================================================
top-level module attribute
================================================================================
[<AutoOpen>]
module test =
let x = 4
--------------------------------------------------------------------------------
(file
(module_defn
(attributes
(attribute_set
(attribute
(object_construction
(type
(long_identifier
(identifier)))))))
(identifier)
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const (int))))))
================================================================================
top-level module attributes repeated
================================================================================
[<A;B;C>]
module test =
let x = 4
--------------------------------------------------------------------------------
(file
(module_defn
(attributes
(attribute_set
(attribute
(object_construction
(type
(long_identifier
(identifier)))))
(attribute
(object_construction
(type
(long_identifier
(identifier)))))
(attribute
(object_construction
(type
(long_identifier
(identifier)))))))
(identifier)
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
top-level module attributes separate
================================================================================
[<A>]
[<B;C>]
module test =
let x = 4
--------------------------------------------------------------------------------
(file
(module_defn
(attributes
(attribute_set
(attribute
(object_construction
(type
(long_identifier
(identifier))))))
(attribute_set
(attribute
(object_construction
(type
(long_identifier
(identifier)))))
(attribute
(object_construction
(type
(long_identifier
(identifier)))))))
(identifier)
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
top-level class attribute
================================================================================
[<Route("test")>]
type A() =
do ()
--------------------------------------------------------------------------------
(file
(type_definition
(attributes
(attribute_set
(attribute
(object_construction
(type (long_identifier (identifier)))
(paren_expression
(const (string)))))))
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(const (unit)))))

@ -0,0 +1,135 @@
================================================================================
line comment
================================================================================
// comment
let x = 1
--------------------------------------------------------------------------------
(file
(line_comment)
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const (int)))))
================================================================================
block comment
================================================================================
(* comment *)
let x = 1
--------------------------------------------------------------------------------
(file
(block_comment
(block_comment_content))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const (int)))))
================================================================================
multi-line block comment
================================================================================
(*
* comment
*)
let x = 1
--------------------------------------------------------------------------------
(file
(block_comment
(block_comment_content))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const (int)))))
================================================================================
docstring
================================================================================
/// <c>code</c>
let x = 1
--------------------------------------------------------------------------------
(file
(line_comment)
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const (int)))))
================================================================================
coment in simple string
================================================================================
let x = "//comment in string"
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(string)))))
================================================================================
coment in triple-quoted string
================================================================================
let x = """
//comment in string
"""
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(triple_quoted_string)))))
================================================================================
coment in verbatim string
================================================================================
let x = @"//comment in string"
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(verbatim_string)))))

@ -0,0 +1,11 @@
================================================================================
basic compiler directive
================================================================================
#nowarn "42"
--------------------------------------------------------------------------------
(file
(compiler_directive_decl
(string)))

@ -0,0 +1,412 @@
================================================================================
simple string
================================================================================
let x = "test"
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(string)))))
================================================================================
verbatim string
================================================================================
let x = @"\"
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(verbatim_string)))))
================================================================================
int
================================================================================
let x = 1
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int)))))
================================================================================
int64
================================================================================
let x = 1L
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int64
(int))))))
================================================================================
int32
================================================================================
let x = 1l
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int32
(int))))))
================================================================================
int16
================================================================================
let x = 1s
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int16
(int))))))
================================================================================
sbyte
================================================================================
let x = 1y
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(sbyte
(int))))))
================================================================================
byte
================================================================================
let x = 1uy
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(byte
(int))))))
================================================================================
uint16
================================================================================
let x = 1us
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(uint16
(int))))))
================================================================================
uint32
================================================================================
let x = 1u
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(uint32
(int))))))
================================================================================
uint32 alternative
================================================================================
let x = 1ul
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(uint32
(int))))))
================================================================================
uint64
================================================================================
let x = 1UL
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(uint64
(int))))))
================================================================================
uint64 alternative
================================================================================
let x = 1uL
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(uint64
(int))))))
================================================================================
nativeint
================================================================================
do
1n
0b1n
--------------------------------------------------------------------------------
(file
(value_declaration
(do
(const
(nativeint
(int)))
(const
(nativeint
(xint))))))
================================================================================
unativeint
================================================================================
do
1un
0b1un
--------------------------------------------------------------------------------
(file
(value_declaration
(do
(const
(unativeint
(int)))
(const
(unativeint
(xint))))))
================================================================================
ieee32
================================================================================
let x = 1.f
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(ieee32
(float))))))
================================================================================
ieee32 alternative
================================================================================
let x = 0b1lf
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(ieee32
(xint))))))
================================================================================
ieee64
================================================================================
let x = 0b0LF
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(ieee64
(xint))))))
================================================================================
bignum
================================================================================
do
1Q
1R
1Z
1I
1N
1G
--------------------------------------------------------------------------------
(file
(value_declaration
(do
(const
(bignum
(int)))
(const
(bignum
(int)))
(const
(bignum
(int)))
(const
(bignum
(int)))
(const
(bignum
(int)))
(const
(bignum
(int))))))
================================================================================
decimal
================================================================================
do
1.0M
1.M
1M
1.0m
1.m
1m
--------------------------------------------------------------------------------
(file
(value_declaration
(do
(const
(decimal
(float)))
(const
(decimal
(float)))
(const
(decimal
(int)))
(const
(decimal
(float)))
(const
(decimal
(float)))
(const
(decimal
(int))))))

File diff suppressed because it is too large Load Diff

@ -0,0 +1,37 @@
===
refer dll
===
#r "path/to/MyAssembly.dll"
---
(file
(fsi_directive_decl
(string)))
===
refer nuget package
===
#r "path/to/MyAssembly.dll"
---
(file
(fsi_directive_decl
(string)))
===
load script
===
#load "Script1.fsx"
---
(file
(fsi_directive_decl
(string)))

@ -0,0 +1,169 @@
================================================================================
basic constant function
================================================================================
let functionName x = 4
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(function_declaration_left
(identifier)
(argument_patterns
(long_identifier
(identifier))))
body: (const
(int)))))
================================================================================
basic constant function inline
================================================================================
let inline functionName x = 4
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(function_declaration_left
(identifier)
(argument_patterns
(long_identifier
(identifier))))
body: (const
(int)))))
================================================================================
basic private constant function
================================================================================
let private functionName x = 4
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(function_declaration_left
(identifier)
(argument_patterns
(long_identifier
(identifier))))
body: (const
(int)))))
================================================================================
basic private constant function inline
================================================================================
let inline private functionName x = 4
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(function_declaration_left
(identifier)
(argument_patterns
(long_identifier
(identifier))))
body: (const
(int)))))
================================================================================
basic function with srt constraint (old-style, with ^)
================================================================================
let inline double<^a when ^a:(member Double: unit -> ^a)> (x: ^a) = x.Double()
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(function_declaration_left
(identifier)
(type_arguments
(type_argument_defn
(type_argument
(identifier)))
(type_argument_constraints
(constraint
(static_type_argument
(identifier))
(trait_member_constraint
(identifier)
(type
(type
(long_identifier
(identifier)))
(type
(type_argument
(identifier))))))))
(argument_patterns
(typed_pattern
(identifier_pattern
(long_identifier
(identifier)))
(type
(type_argument
(identifier))))))
(call_expression
(dot_expression
(long_identifier_or_op
(long_identifier
(identifier)))
(long_identifier_or_op
(long_identifier
(identifier))))))))
================================================================================
basic function with srt constraint (new-style, with ')
================================================================================
let inline double<'a when 'a:(member Double: unit -> 'a)> (x: 'a) = x.Double()
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(function_declaration_left
(identifier)
(type_arguments
(type_argument_defn
(type_argument
(identifier)))
(type_argument_constraints
(constraint
(static_type_argument
(identifier))
(trait_member_constraint
(identifier)
(type
(type
(long_identifier
(identifier)))
(type
(type_argument
(identifier))))))))
(argument_patterns
(typed_pattern
(identifier_pattern
(long_identifier
(identifier)))
(type
(type_argument
(identifier))))))
(call_expression
(dot_expression
(long_identifier_or_op
(long_identifier
(identifier)))
(long_identifier_or_op
(long_identifier
(identifier))))))))

@ -0,0 +1,87 @@
================================================================================
basic ident
================================================================================
do sample
--------------------------------------------------------------------------------
(file
(value_declaration
(do
(long_identifier_or_op
(long_identifier
(identifier))))))
================================================================================
ident with numbers
================================================================================
do wh0ar3y0u
--------------------------------------------------------------------------------
(file
(value_declaration
(do
(long_identifier_or_op
(long_identifier
(identifier))))))
================================================================================
tick ident
================================================================================
do ``I can have anything in here ASDFAS?DFS``
--------------------------------------------------------------------------------
(file
(value_declaration
(do
(long_identifier_or_op
(long_identifier
(identifier))))))
================================================================================
ident with leading _
================================================================================
do _yo
--------------------------------------------------------------------------------
(file
(value_declaration
(do
(long_identifier_or_op
(long_identifier
(identifier))))))
================================================================================
long ident
================================================================================
module test = foo.bar.baz
--------------------------------------------------------------------------------
(file
(module_abbrev
(identifier)
(long_identifier
(identifier)
(identifier)
(identifier))))
================================================================================
long ident with tick
================================================================================
module _ = foo.bar.``baz``
--------------------------------------------------------------------------------
(file
(module_abbrev
(identifier)
(long_identifier
(identifier)
(identifier)
(identifier))))

@ -0,0 +1,23 @@
===
basic import
===
open test
---
(file
(import_decl
(long_identifier (identifier))))
===
basic import long identifier
===
open Mod.Test
---
(file
(import_decl
(long_identifier (identifier) (identifier))))

@ -0,0 +1,126 @@
================================================================================
basic module with indent
================================================================================
module test =
let x = 4
--------------------------------------------------------------------------------
(file
(module_defn
(identifier)
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
basic module with large indent
================================================================================
module test =
let x = 4
--------------------------------------------------------------------------------
(file
(module_defn
(identifier)
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
basic module with multiple elements
================================================================================
module test =
let x = 4
let y = 5
--------------------------------------------------------------------------------
(file
(module_defn
(identifier)
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
top-level module with multiple elements
================================================================================
module Test
let x = 4
let y = 5
--------------------------------------------------------------------------------
(file
(named_module
name: (long_identifier
(identifier))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
body: (const
(int))))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
body: (const
(int))))))
================================================================================
namespace open
================================================================================
namespace Test.A
open B
open X.Y
--------------------------------------------------------------------------------
(file
(namespace
(long_identifier
(identifier)
(identifier))
(import_decl
(long_identifier (identifier)))
(import_decl
(long_identifier
(identifier)
(identifier)))))

@ -0,0 +1,13 @@
===
basic module abbreviation
===
module local = Mod.local
---
(file
(module_abbrev
(identifier)
(long_identifier (identifier) (identifier))))

@ -0,0 +1,79 @@
================================================================================
constant pattern
================================================================================
let x = 1
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern (long_identifier (identifier))))
(const (int)))))
================================================================================
tuple pattern
================================================================================
let (x,y) = (1,2)
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(paren_pattern
(repeat_pattern
(identifier_pattern (long_identifier (identifier)))
(identifier_pattern (long_identifier (identifier))))))
(paren_expression
(tuple_expression
(const (int))
(const (int)))))))
================================================================================
typed pattern
================================================================================
let name (x : int) = 1
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(function_declaration_left
(identifier)
(argument_patterns
(typed_pattern
(identifier_pattern (long_identifier (identifier)))
(type (long_identifier (identifier))))))
(const (int)))))
================================================================================
typed tuple pattern
================================================================================
let name (x: int, y: string) = 1, "test"
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(function_declaration_left
(identifier)
(argument_patterns
(repeat_pattern
(typed_pattern
(identifier_pattern (long_identifier (identifier)))
(type (long_identifier (identifier))))
(typed_pattern
(identifier_pattern (long_identifier (identifier)))
(type (long_identifier (identifier)))))))
(tuple_expression
(const (int))
(const (string))))))

@ -0,0 +1,156 @@
================================================================================
basic anonymous module
================================================================================
let x = 4
--------------------------------------------------------------------------------
(file
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int)))))
================================================================================
basic named module
================================================================================
module Test
let x = 4
--------------------------------------------------------------------------------
(file
(named_module
(long_identifier
(identifier))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
named module with whitespace
================================================================================
module Test
let x = 4
--------------------------------------------------------------------------------
(file
(named_module
(long_identifier
(identifier))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
named module lowercase
================================================================================
module test
let x = 4
--------------------------------------------------------------------------------
(file
(named_module
(long_identifier
(identifier))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
basic namespace
================================================================================
namespace test
let x = 4
--------------------------------------------------------------------------------
(file
(namespace
(long_identifier
(identifier))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
basic global namespace
================================================================================
namespace global test
let x = 4
--------------------------------------------------------------------------------
(file
(namespace
(ERROR
(UNEXPECTED 'e')
(UNEXPECTED '\n'))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))
================================================================================
basic long namespace
================================================================================
namespace test.val
let x = 4
--------------------------------------------------------------------------------
(file
(namespace
(long_identifier
(identifier)
(identifier))
(value_declaration
(function_or_value_defn
(value_declaration_left
(identifier_pattern
(long_identifier
(identifier))))
(const
(int))))))

@ -0,0 +1,577 @@
================================================================================
Enum type definition
================================================================================
type Test = Red = 1
--------------------------------------------------------------------------------
(file
(type_definition
(enum_type_defn
(type_name
(identifier))
(enum_type_cases
(enum_type_case
(identifier)
(const
(int)))))))
================================================================================
Enum type definition - multi line
================================================================================
type Test =
| Red = "red"
| Blue = "blue"
--------------------------------------------------------------------------------
(file
(type_definition
(enum_type_defn
(type_name
(identifier))
(enum_type_cases
(enum_type_case
(identifier)
(const
(string)))
(enum_type_case
(identifier)
(const
(string)))))))
================================================================================
Union type definition
================================================================================
type Test = Red
--------------------------------------------------------------------------------
(file
(type_definition
(union_type_defn
(type_name
(identifier))
(union_type_cases
(union_type_case
(identifier))))))
================================================================================
Union type definition - multi line
================================================================================
type Test =
| Red
| Blue
--------------------------------------------------------------------------------
(file
(type_definition
(union_type_defn
(type_name
(identifier))
(union_type_cases
(union_type_case
(identifier))
(union_type_case
(identifier))))))
================================================================================
basic class definition
================================================================================
type A() =
do ()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(const (unit)))))
================================================================================
class inherit definition
================================================================================
type A() =
inherit ControllerBase()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(class_inherits_decl
(type (long_identifier (identifier)))
(const (unit))))))
================================================================================
basic class member definition
================================================================================
type A() =
member this.Post(msg: string) = msg
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(paren_pattern
(typed_pattern
(identifier_pattern (long_identifier (identifier)))
(type (long_identifier (identifier)))))
(long_identifier_or_op (long_identifier (identifier))))))))
================================================================================
basic class member definition with two members
================================================================================
type A() =
member this.Post() = ()
member this.Get() = ()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit))))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit)))))))
================================================================================
basic class interface implementation definition
================================================================================
type A() =
interface A with
member _.B() = ()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(interface_implementation
(type (long_identifier (identifier)))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit))))))))
================================================================================
basic class interface implementation definition with two members
================================================================================
type A() =
interface A with
member _.B() = ()
member _.C() = ()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(interface_implementation
(type (long_identifier (identifier)))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit))))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit))))))))
================================================================================
class interface implementation definition with member and property
================================================================================
type A() =
interface A with
member _.B = 1
member _.C() = ()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(interface_implementation
(type (long_identifier (identifier)))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const (int))))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit))))))))
================================================================================
class inherit and do definition
================================================================================
type A() =
inherit ControllerBase()
do ()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(class_inherits_decl
(type (long_identifier (identifier)))
(const (unit)))
(const (unit)))))
================================================================================
class inherit and member method definition
================================================================================
type A() =
inherit ControllerBase()
member ctx.Index() = ()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(class_inherits_decl
(type (long_identifier (identifier)))
(const (unit)))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit)))))))
================================================================================
class member then interface impl. test
================================================================================
type A() =
member B.C() = ()
interface Z with
member _.Y() = ()
--------------------------------------------------------------------------------
(file
(type_definition
(anon_type_defn
(type_name (identifier))
(primary_constr_args)
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit))))
(interface_implementation
(type (long_identifier (identifier)))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern (unit))
(const (unit))))))))
================================================================================
Mutual type definition
================================================================================
type A = | B
and B = C
--------------------------------------------------------------------------------
(file
(type_definition
(union_type_defn
(type_name (identifier))
(union_type_cases (union_type_case (identifier))))
(union_type_defn
(type_name (identifier))
(union_type_cases (union_type_case (identifier))))))
================================================================================
Recursive type definition
================================================================================
type Maybe<'T> = | Just B<'T> | Nothing
and 'T maybe = Maybe<'T>
--------------------------------------------------------------------------------
(file
(type_definition
(union_type_defn
(type_name
(identifier)
(type_arguments
(type_argument_defn
(type_argument
(identifier)))))
(union_type_cases
(union_type_case
(identifier))
(ERROR
(UNEXPECTED 'B')
(UNEXPECTED 'T'))
(union_type_case
(identifier))))
(type_abbrev_defn
(type_name
(type_argument
(identifier))
(identifier))
(type
(long_identifier
(identifier))
(type_attributes
(type_attribute
(type
(type_argument
(identifier)))))))))
================================================================================
record definition
================================================================================
type T =
{ A: int
B: int }
--------------------------------------------------------------------------------
(file
(type_definition
(record_type_defn
(type_name
(identifier))
(record_fields
(record_field
(identifier)
(type
(long_identifier
(identifier))))
(record_field
(identifier)
(type
(long_identifier
(identifier))))))))
================================================================================
Type extension
================================================================================
type T =
{ A: int
B: int }
static member Default = { A = 1; B = 2 }
--------------------------------------------------------------------------------
(file
(type_definition
(record_type_defn
(type_name (identifier))
(record_fields
(record_field
(identifier)
(type (long_identifier (identifier))))
(record_field
(identifier)
(type (long_identifier (identifier)))))
(type_extension_elements
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier))
(brace_expression
(field_expression
(field_initializers
(field_initializer
(long_identifier (identifier))
(const (int))
(infix_expression
(long_identifier_or_op
(long_identifier (identifier)))
(infix_op)
(const (int)))))))))))))
================================================================================
Type extension. "with" keyword
================================================================================
type T =
{ A: int
B: int }
with static member Default = { A = 1; B = 2 }
--------------------------------------------------------------------------------
(file
(type_definition
(record_type_defn
(type_name (identifier))
(record_fields
(record_field
(identifier)
(type (long_identifier (identifier))))
(record_field
(identifier)
(type (long_identifier (identifier)))))
(type_extension_elements
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier))
(brace_expression
(field_expression
(field_initializers
(field_initializer
(long_identifier (identifier))
(const (int))
(infix_expression
(long_identifier_or_op
(long_identifier (identifier)))
(infix_op)
(const (int)))))))))))))
================================================================================
Type extension. "with" keyword newline
================================================================================
type T =
{ A: int
B: int }
with
static member Default1 = { A = 1; B = 2 }
member x.Test() = { A = 1; B = 2 }
--------------------------------------------------------------------------------
(file
(type_definition
(record_type_defn
(type_name
(identifier))
(record_fields
(record_field
(identifier)
(type
(long_identifier
(identifier))))
(record_field
(identifier)
(type
(long_identifier
(identifier)))))
(type_extension_elements
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier))
(brace_expression
(field_expression
(field_initializers
(field_initializer
(long_identifier
(identifier))
(const
(int))
(infix_expression
(long_identifier_or_op
(long_identifier
(identifier)))
(infix_op)
(const
(int)))))))))
(member_defn
(method_or_prop_defn
(property_or_ident
(identifier)
(identifier))
(const_pattern
(unit))
(brace_expression
(field_expression
(field_initializers
(field_initializer
(long_identifier
(identifier))
(const
(int))
(infix_expression
(long_identifier_or_op
(long_identifier
(identifier)))
(infix_op)
(const
(int)))))))))))))

@ -0,0 +1,10 @@
#r "nuget: FSharp.Compiler.Service, 43.7.300"
//<- keyword.control.import
// ^ namespace
#r "/home/bin/MyApp.dll"
//<- keyword.control.import
// ^ namespace
#load "Strings.fsx"
//<- keyword.control.import
// ^ namespace