├── .nvmrc
├── bindings
├── python
│ ├── tree_sitter_rescript
│ │ ├── py.typed
│ │ ├── __init__.pyi
│ │ ├── binding.c
│ │ └── __init__.py
│ └── tests
│ │ └── test_binding.py
├── node
│ ├── binding_test.js
│ ├── index.js
│ ├── index.d.ts
│ └── binding.cc
├── c
│ ├── tree-sitter-rescript.h
│ └── tree-sitter-rescript.pc.in
├── swift
│ ├── TreeSitterReScript
│ │ └── rescript.h
│ └── TreeSitterReScriptTests
│ │ └── TreeSitterReScriptTests.swift
├── go
│ ├── binding.go
│ └── binding_test.go
└── rust
│ ├── build.rs
│ └── lib.rs
├── test
├── highlight
│ ├── decorators.res
│ ├── type_declarations.res
│ ├── functions.res
│ ├── jsx.res
│ ├── literals.res
│ ├── modules.res
│ └── expressions.res
├── corpus
│ ├── error_scopes.txt
│ ├── comments.txt
│ ├── decorators.txt
│ ├── functions.txt
│ ├── literals.txt
│ ├── jsx.txt
│ ├── let_bindings.txt
│ ├── type_declarations.txt
│ └── modules.txt
└── manual
│ └── embedded.res
├── go.mod
├── queries
├── locals.scm
├── injections.scm
├── textobjects.scm
└── highlights.scm
├── README.md
├── .gitignore
├── Cargo.toml
├── .editorconfig
├── package.json
├── pyproject.toml
├── binding.gyp
├── .github
└── workflows
│ └── ci.yml
├── tree-sitter.json
├── .gitattributes
├── LICENSE
├── src
├── tree_sitter
│ ├── alloc.h
│ ├── parser.h
│ └── array.h
└── scanner.c
├── Package.swift
├── setup.py
├── CMakeLists.txt
├── Makefile
├── Cargo.lock
└── grammar.js
/.nvmrc:
--------------------------------------------------------------------------------
1 | v23.7.0
2 |
--------------------------------------------------------------------------------
/bindings/python/tree_sitter_rescript/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/highlight/decorators.res:
--------------------------------------------------------------------------------
1 | @name
2 | //<- attribute
3 |
4 | @@name
5 | //<- attribute
6 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/tree-sitter/tree-sitter-rescript
2 |
3 | go 1.22
4 |
5 | require github.com/tree-sitter/go-tree-sitter v0.24.0
6 |
--------------------------------------------------------------------------------
/queries/locals.scm:
--------------------------------------------------------------------------------
1 | (switch_expression) @scope
2 |
3 | ; Definitions
4 | ;------------
5 | (type_declaration) @definition.type
6 | (let_binding) @definition.var
7 | (module_declaration) @definition.namespace
8 |
--------------------------------------------------------------------------------
/bindings/node/binding_test.js:
--------------------------------------------------------------------------------
1 | const assert = require("node:assert");
2 | const { test } = require("node:test");
3 |
4 | const Parser = require("tree-sitter");
5 |
6 | test("can load grammar", () => {
7 | const parser = new Parser();
8 | assert.doesNotThrow(() => parser.setLanguage(require(".")));
9 | });
10 |
--------------------------------------------------------------------------------
/bindings/python/tree_sitter_rescript/__init__.pyi:
--------------------------------------------------------------------------------
1 | from typing import Final
2 |
3 | # NOTE: uncomment these to include any queries that this grammar contains:
4 |
5 | # HIGHLIGHTS_QUERY: Final[str]
6 | # INJECTIONS_QUERY: Final[str]
7 | # LOCALS_QUERY: Final[str]
8 | # TAGS_QUERY: Final[str]
9 |
10 | def language() -> object: ...
11 |
--------------------------------------------------------------------------------
/bindings/c/tree-sitter-rescript.h:
--------------------------------------------------------------------------------
1 | #ifndef TREE_SITTER_RESCRIPT_H_
2 | #define TREE_SITTER_RESCRIPT_H_
3 |
4 | typedef struct TSLanguage TSLanguage;
5 |
6 | #ifdef __cplusplus
7 | extern "C" {
8 | #endif
9 |
10 | const TSLanguage *tree_sitter_rescript(void);
11 |
12 | #ifdef __cplusplus
13 | }
14 | #endif
15 |
16 | #endif // TREE_SITTER_RESCRIPT_H_
17 |
--------------------------------------------------------------------------------
/test/highlight/type_declarations.res:
--------------------------------------------------------------------------------
1 |
2 | type rec t =
3 | //<- keyword.type
4 | // ^ keyword.modifier
5 | // ^ type
6 | | Node(t, t)
7 | // ^ constructor
8 | // ^ type
9 | | Terminal
10 | // ^ constructor
11 | | Component(module(Foo.t))
12 | // ^ keyword
13 |
14 | type obj = {
15 | "x": int,
16 | // ^ @property
17 | }
18 |
--------------------------------------------------------------------------------
/bindings/swift/TreeSitterReScript/rescript.h:
--------------------------------------------------------------------------------
1 | #ifndef TREE_SITTER_RESCRIPT_H_
2 | #define TREE_SITTER_RESCRIPT_H_
3 |
4 | typedef struct TSLanguage TSLanguage;
5 |
6 | #ifdef __cplusplus
7 | extern "C" {
8 | #endif
9 |
10 | const TSLanguage *tree_sitter_rescript(void);
11 |
12 | #ifdef __cplusplus
13 | }
14 | #endif
15 |
16 | #endif // TREE_SITTER_RESCRIPT_H_
17 |
--------------------------------------------------------------------------------
/bindings/c/tree-sitter-rescript.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@CMAKE_INSTALL_PREFIX@
2 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
4 |
5 | Name: tree-sitter-rescript
6 | Description: @PROJECT_DESCRIPTION@
7 | URL: @PROJECT_HOMEPAGE_URL@
8 | Version: @PROJECT_VERSION@
9 | Libs: -L${libdir} -ltree-sitter-rescript
10 | Cflags: -I${includedir}
11 |
--------------------------------------------------------------------------------
/bindings/python/tests/test_binding.py:
--------------------------------------------------------------------------------
1 | from unittest import TestCase
2 |
3 | import tree_sitter
4 | import tree_sitter_rescript
5 |
6 |
7 | class TestLanguage(TestCase):
8 | def test_can_load_grammar(self):
9 | try:
10 | tree_sitter.Language(tree_sitter_rescript.language())
11 | except Exception:
12 | self.fail("Error loading ReScript grammar")
13 |
--------------------------------------------------------------------------------
/bindings/go/binding.go:
--------------------------------------------------------------------------------
1 | package tree_sitter_rescript
2 |
3 | // #cgo CFLAGS: -std=c11 -fPIC
4 | // #include "../../src/parser.c"
5 | // #if __has_include("../../src/scanner.c")
6 | // #include "../../src/scanner.c"
7 | // #endif
8 | import "C"
9 |
10 | import "unsafe"
11 |
12 | // Get the tree-sitter Language for this grammar.
13 | func Language() unsafe.Pointer {
14 | return unsafe.Pointer(C.tree_sitter_rescript())
15 | }
16 |
--------------------------------------------------------------------------------
/bindings/go/binding_test.go:
--------------------------------------------------------------------------------
1 | package tree_sitter_rescript_test
2 |
3 | import (
4 | "testing"
5 |
6 | tree_sitter "github.com/tree-sitter/go-tree-sitter"
7 | tree_sitter_rescript "github.com/tree-sitter/tree-sitter-rescript/bindings/go"
8 | )
9 |
10 | func TestCanLoadGrammar(t *testing.T) {
11 | language := tree_sitter.NewLanguage(tree_sitter_rescript.Language())
12 | if language == nil {
13 | t.Errorf("Error loading ReScript grammar")
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/test/highlight/functions.res:
--------------------------------------------------------------------------------
1 | let inc = n => n + 1
2 | // ^ variable.parameter
3 | // ^ punctuation.special
4 | // ^ function
5 |
6 | let fn = (a, (b, c), {d, e}, [f, g]) => a + b + c + d + e + f + g
7 | // ^ variable.parameter
8 | // ^ variable.parameter
9 | // ^ variable.parameter
10 | // ^ variable.parameter
11 |
12 | let get = async (id) => id
13 | // ^ keyword.coroutine
14 |
--------------------------------------------------------------------------------
/bindings/swift/TreeSitterReScriptTests/TreeSitterReScriptTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | import SwiftTreeSitter
3 | import TreeSitterReScript
4 |
5 | final class TreeSitterReScriptTests: XCTestCase {
6 | func testCanLoadGrammar() throws {
7 | let parser = Parser()
8 | let language = Language(language: tree_sitter_rescript())
9 | XCTAssertNoThrow(try parser.setLanguage(language),
10 | "Error loading ReScript grammar")
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/test/highlight/jsx.res:
--------------------------------------------------------------------------------
1 |
2 | //<- tag.delimiter
3 | // ^ tag
4 | // ^ tag.delimiter
5 |
6 | // ^ tag.attribute
7 | a b c
8 | // ^ tag
9 | // ^ tag
10 |
11 | // ^ tag
12 | // ^ tag
13 | // ^ tag
14 | // ^ tag
15 | React.null
16 | // ^ tag.delimiter
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tree-sitter-rescript
2 |
3 | ReScript grammar for [Tree-sitter](https://tree-sitter.github.io/tree-sitter/)
4 |
5 | ## Contributing
6 |
7 | Contributions are welcome. Here’s how you can help:
8 |
9 | 🙂 Provide a minimal ReScript snippet which produces an `(ERROR)` node or otherwise incorrect syntax tree. Open a new issue providing this snippet and the resulting syntax tree. You can use the following command to see the syntax tree:
10 |
11 | ```bash
12 | npm run parse path/to/file.res
13 | ```
14 |
--------------------------------------------------------------------------------
/bindings/node/index.js:
--------------------------------------------------------------------------------
1 | const root = require("path").join(__dirname, "..", "..");
2 |
3 | module.exports =
4 | typeof process.versions.bun === "string"
5 | // Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time
6 | ? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-rescript.node`)
7 | : require("node-gyp-build")(root);
8 |
9 | try {
10 | module.exports.nodeTypeInfo = require("../../src/node-types.json");
11 | } catch (_) {}
12 |
--------------------------------------------------------------------------------
/test/corpus/error_scopes.txt:
--------------------------------------------------------------------------------
1 | ===========================================
2 | Limit switch damage
3 | ===========================================
4 |
5 | switch foo {
6 | | 7 => 42
7 | | zhopa-priehali?
8 | }
9 |
10 | let x = 5
11 |
12 | (TODO: make this working)
13 |
14 | (source_file
15 | (expression_statement
16 | (switch_expression
17 | (value_identifier)
18 | (switch_match (number) (expression_statement (number)))
19 | (ERROR (value_identifier) (UNEXPECTED 'p'))))
20 | (let_binding (value_identifier) (number)))
21 |
--------------------------------------------------------------------------------
/bindings/node/index.d.ts:
--------------------------------------------------------------------------------
1 | type BaseNode = {
2 | type: string;
3 | named: boolean;
4 | };
5 |
6 | type ChildNode = {
7 | multiple: boolean;
8 | required: boolean;
9 | types: BaseNode[];
10 | };
11 |
12 | type NodeInfo =
13 | | (BaseNode & {
14 | subtypes: BaseNode[];
15 | })
16 | | (BaseNode & {
17 | fields: { [name: string]: ChildNode };
18 | children: ChildNode[];
19 | });
20 |
21 | type Language = {
22 | language: unknown;
23 | nodeTypeInfo: NodeInfo[];
24 | };
25 |
26 | declare const language: Language;
27 | export = language;
28 |
--------------------------------------------------------------------------------
/test/highlight/literals.res:
--------------------------------------------------------------------------------
1 |
2 | /**/ #polyvar
3 | // ^ constructor
4 | // ^ constructor
5 |
6 | /**/ #"polyvar"
7 | // ^ constructor
8 | // ^ constructor
9 | // ^ constructor
10 |
11 | /**/ #\"polyvar"
12 | // ^ constructor
13 | // ^ constructor
14 | // ^ constructor
15 | // ^ constructor
16 |
17 | /**/ #77
18 | // ^ constructor
19 | // ^ constructor
20 |
21 | /**/ 'R'
22 | // ^ character
23 | // ^ character
24 |
25 | /**/ '\\'
26 | // ^ string.escape
27 |
28 | /**/ `${hello}`
29 | // ^ punctuation.special
30 | // ^ punctuation.special
31 | // ^ punctuation.special
32 |
--------------------------------------------------------------------------------
/bindings/node/binding.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | typedef struct TSLanguage TSLanguage;
4 |
5 | extern "C" TSLanguage *tree_sitter_rescript();
6 |
7 | // "tree-sitter", "language" hashed with BLAKE2
8 | const napi_type_tag LANGUAGE_TYPE_TAG = {
9 | 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
10 | };
11 |
12 | Napi::Object Init(Napi::Env env, Napi::Object exports) {
13 | auto language = Napi::External::New(env, tree_sitter_rescript());
14 | language.TypeTag(&LANGUAGE_TYPE_TAG);
15 | exports["language"] = language;
16 | return exports;
17 | }
18 |
19 | NODE_API_MODULE(tree_sitter_rescript_binding, Init)
20 |
--------------------------------------------------------------------------------
/test/manual/embedded.res:
--------------------------------------------------------------------------------
1 | // NOT AN AUTOMATED TEST.
2 | //
3 | // Looks like Tree-sitter test framework does not allow to test
4 | // for correct language embedding. So, this file is just a showcase
5 | // to observe results with eyes.
6 | //
7 | // You should see comprehensive highlighting for constructs inside
8 | // strings. That is, they should not look like plain strings if
9 | // you have corresponding grammar installed.
10 |
11 | // :TSInstall javascript
12 | let inc = %raw(`function(x) {return x + 1;}`)
13 |
14 | // :TSInstall graphql
15 | let gql = %graphql(`{ hero { name } }`)
16 |
17 | // :TSInstall regex
18 | let re = %re(`^[A-Z][a-z0-9]*$`)
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Rust artifacts
2 | target/
3 |
4 | # Node artifacts
5 | build/
6 | prebuilds/
7 | node_modules/
8 |
9 | # Swift artifacts
10 | .build/
11 |
12 | # Go artifacts
13 | _obj/
14 |
15 | # Python artifacts
16 | .venv/
17 | dist/
18 | *.egg-info
19 | *.whl
20 |
21 | # C artifacts
22 | *.a
23 | *.so
24 | *.so.*
25 | *.dylib
26 | *.dll
27 | *.pc
28 | *.exp
29 | *.lib
30 |
31 | # Zig artifacts
32 | .zig-cache/
33 | zig-cache/
34 | zig-out/
35 |
36 | # Example dirs
37 | /examples/*/
38 |
39 | # Grammar volatiles
40 | *.wasm
41 | *.obj
42 | *.o
43 |
44 | # Archives
45 | *.tar.gz
46 | *.tgz
47 | *.zip
48 |
49 | # Others
50 | log.html
51 | test_wild/
52 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tree-sitter-rescript"
3 | description = "rescript grammar for the tree-sitter parsing library"
4 | version = "0.0.1"
5 | keywords = ["incremental", "parsing", "rescript"]
6 | categories = ["parsing", "text-editors"]
7 | repository = "https://github.com/tree-sitter/tree-sitter-rescript"
8 | edition = "2018"
9 | license = "MIT"
10 |
11 | build = "bindings/rust/build.rs"
12 | include = ["bindings/rust/*", "grammar.js", "queries/*", "src/*"]
13 |
14 | [lib]
15 | path = "bindings/rust/lib.rs"
16 |
17 | [dependencies]
18 | tree-sitter-language = "0.1"
19 |
20 | [build-dependencies]
21 | cc = "1.2"
22 |
23 | [dev-dependencies]
24 | tree-sitter = "0.25.2"
25 |
--------------------------------------------------------------------------------
/bindings/rust/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | let src_dir = std::path::Path::new("src");
3 |
4 | let mut c_config = cc::Build::new();
5 | c_config.std("c11").include(src_dir);
6 |
7 | #[cfg(target_env = "msvc")]
8 | c_config.flag("-utf-8");
9 |
10 | let parser_path = src_dir.join("parser.c");
11 | c_config.file(&parser_path);
12 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
13 |
14 | let scanner_path = src_dir.join("scanner.c");
15 | if scanner_path.exists() {
16 | c_config.file(&scanner_path);
17 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
18 | }
19 |
20 | c_config.compile("tree-sitter-rescript");
21 | }
22 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 |
6 | [*.{json,toml,yml,gyp}]
7 | indent_style = space
8 | indent_size = 2
9 |
10 | [*.js]
11 | indent_style = space
12 | indent_size = 2
13 |
14 | [*.scm]
15 | indent_style = space
16 | indent_size = 2
17 |
18 | [*.{c,cc,h}]
19 | indent_style = space
20 | indent_size = 4
21 |
22 | [*.rs]
23 | indent_style = space
24 | indent_size = 4
25 |
26 | [*.{py,pyi}]
27 | indent_style = space
28 | indent_size = 4
29 |
30 | [*.swift]
31 | indent_style = space
32 | indent_size = 4
33 |
34 | [*.go]
35 | indent_style = tab
36 | indent_size = 8
37 |
38 | [Makefile]
39 | indent_style = tab
40 | indent_size = 8
41 |
42 | [parser.c]
43 | indent_size = 2
44 |
45 | [{alloc,array,parser}.h]
46 | indent_size = 2
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tree-sitter-rescript",
3 | "version": "1.2.0",
4 | "main": "bindings/node",
5 | "author": "Victor Nakoryakov",
6 | "license": "MIT",
7 | "dependencies": {
8 | "nan": "^2.15.0",
9 | "node-addon-api": "^8.2.2",
10 | "node-gyp-build": "^4.8.2"
11 | },
12 | "devDependencies": {
13 | "tree-sitter-cli": "^0.25.2"
14 | },
15 | "peerDependencies": {
16 | "tree-sitter": "^0.21.1"
17 | },
18 | "peerDependenciesMeta": {
19 | "tree-sitter": {
20 | "optional": true
21 | }
22 | },
23 | "scripts": {
24 | "install": "node-gyp-build",
25 | "prestart": "tree-sitter build --wasm",
26 | "start": "tree-sitter playground",
27 | "test": "node --test bindings/node/*_test.js",
28 | "parse": "tree-sitter parse"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools>=42", "wheel"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [project]
6 | name = "tree-sitter-rescript"
7 | description = "ReScript parser for Tree-Sitter"
8 | version = "5.0.0"
9 | keywords = ["incremental", "parsing", "tree-sitter", "rescript"]
10 | classifiers = [
11 | "Intended Audience :: Developers",
12 | "Topic :: Software Development :: Compilers",
13 | "Topic :: Text Processing :: Linguistic",
14 | "Typing :: Typed",
15 | ]
16 | authors = [{ name = "Victor Nakoryakov" }]
17 | requires-python = ">=3.10"
18 | license.text = "MIT"
19 | readme = "README.md"
20 |
21 | [project.urls]
22 | Homepage = "https://github.com/tree-sitter/tree-sitter-rescript"
23 |
24 | [project.optional-dependencies]
25 | core = ["tree-sitter~=0.24"]
26 |
27 | [tool.cibuildwheel]
28 | build = "cp310-*"
29 | build-frontend = "build"
30 |
--------------------------------------------------------------------------------
/binding.gyp:
--------------------------------------------------------------------------------
1 | {
2 | "targets": [
3 | {
4 | "target_name": "tree_sitter_rescript_binding",
5 | "dependencies": [
6 | "
2 |
3 | typedef struct TSLanguage TSLanguage;
4 |
5 | TSLanguage *tree_sitter_rescript(void);
6 |
7 | static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
8 | return PyCapsule_New(tree_sitter_rescript(), "tree_sitter.Language", NULL);
9 | }
10 |
11 | static struct PyModuleDef_Slot slots[] = {
12 | #ifdef Py_GIL_DISABLED
13 | {Py_mod_gil, Py_MOD_GIL_NOT_USED},
14 | #endif
15 | {0, NULL}
16 | };
17 |
18 | static PyMethodDef methods[] = {
19 | {"language", _binding_language, METH_NOARGS,
20 | "Get the tree-sitter language for this grammar."},
21 | {NULL, NULL, 0, NULL}
22 | };
23 |
24 | static struct PyModuleDef module = {
25 | .m_base = PyModuleDef_HEAD_INIT,
26 | .m_name = "_binding",
27 | .m_doc = NULL,
28 | .m_size = 0,
29 | .m_methods = methods,
30 | .m_slots = slots,
31 | };
32 |
33 | PyMODINIT_FUNC PyInit__binding(void) {
34 | return PyModuleDef_Init(&module);
35 | }
36 |
--------------------------------------------------------------------------------
/tree-sitter.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/config.schema.json",
3 | "grammars": [
4 | {
5 | "name": "rescript",
6 | "camelcase": "ReScript",
7 | "scope": "source.rescript",
8 | "file-types": ["res", "resi"],
9 | "injection-regex": "^(res|rescript)$",
10 | "class-name": "TreeSitterReScript",
11 | "highlights": "queries/highlights.scm",
12 | "injections": "queries/injections.scm",
13 | "locals": "queries/locals.scm"
14 | }
15 | ],
16 | "metadata": {
17 | "version": "5.0.0",
18 | "license": "MIT",
19 | "description": "ReScript parser for Tree-Sitter",
20 | "authors": [
21 | {
22 | "name": "Victor Nakoryakov"
23 | }
24 | ],
25 | "links": {
26 | "repository": "https://github.com/tree-sitter/tree-sitter-rescript"
27 | }
28 | },
29 | "bindings": {
30 | "c": true,
31 | "go": true,
32 | "node": true,
33 | "python": true,
34 | "rust": true,
35 | "swift": true,
36 | "zig": false
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
3 | # Generated source files
4 | src/*.json linguist-generated
5 | src/parser.c linguist-generated
6 | src/tree_sitter/* linguist-generated
7 |
8 | # C bindings
9 | bindings/c/** linguist-generated
10 | CMakeLists.txt linguist-generated
11 | Makefile linguist-generated
12 |
13 | # Rust bindings
14 | bindings/rust/* linguist-generated
15 | Cargo.toml linguist-generated
16 | Cargo.lock linguist-generated
17 |
18 | # Node.js bindings
19 | bindings/node/* linguist-generated
20 | binding.gyp linguist-generated
21 | package.json linguist-generated
22 | package-lock.json linguist-generated
23 |
24 | # Python bindings
25 | bindings/python/** linguist-generated
26 | setup.py linguist-generated
27 | pyproject.toml linguist-generated
28 |
29 | # Go bindings
30 | bindings/go/* linguist-generated
31 | go.mod linguist-generated
32 | go.sum linguist-generated
33 |
34 | # Swift bindings
35 | bindings/swift/** linguist-generated
36 | Package.swift linguist-generated
37 | Package.resolved linguist-generated
38 |
39 | # Zig bindings
40 | build.zig linguist-generated
41 | build.zig.zon linguist-generated
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2021 Victor Nakoryakov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/test/highlight/modules.res:
--------------------------------------------------------------------------------
1 |
2 | @@warning("-27")
3 | //<- attribute
4 | //^attribute
5 | // ^ string
6 |
7 | include NumericCurve({
8 | // ^ keyword.import
9 | // ^ module
10 | let foo = foo
11 | })
12 |
13 | let {baz, _} = module(User.Inner)
14 | // ^ keyword
15 | // ^ module
16 | // ^ module
17 |
18 | module Belt = {
19 | include (Belt: module type of Belt with module Map := Belt.Map and module Result := Belt.Result)
20 | // ^ keyword.import
21 | // ^ keyword
22 | // ^ keyword
23 | // ^ operator
24 | }
25 |
26 | let a = module(
27 | // ^ keyword
28 | {
29 | type t
30 | let hello = "Hello"
31 | }: X
32 | // ^ module
33 | )
34 |
35 | module B = unpack(a)
36 | // ^ keyword
37 |
38 | module type A = {
39 | type t = int
40 | let value: t
41 | }
42 |
43 | module A: A = {
44 | type t = int
45 | let value: t = 42
46 | }
47 |
48 | let packedA = module(A: A)
49 | // ^ module
50 | // ^ module
51 |
--------------------------------------------------------------------------------
/src/tree_sitter/alloc.h:
--------------------------------------------------------------------------------
1 | #ifndef TREE_SITTER_ALLOC_H_
2 | #define TREE_SITTER_ALLOC_H_
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | // Allow clients to override allocation functions
13 | #ifdef TREE_SITTER_REUSE_ALLOCATOR
14 |
15 | extern void *(*ts_current_malloc)(size_t size);
16 | extern void *(*ts_current_calloc)(size_t count, size_t size);
17 | extern void *(*ts_current_realloc)(void *ptr, size_t size);
18 | extern void (*ts_current_free)(void *ptr);
19 |
20 | #ifndef ts_malloc
21 | #define ts_malloc ts_current_malloc
22 | #endif
23 | #ifndef ts_calloc
24 | #define ts_calloc ts_current_calloc
25 | #endif
26 | #ifndef ts_realloc
27 | #define ts_realloc ts_current_realloc
28 | #endif
29 | #ifndef ts_free
30 | #define ts_free ts_current_free
31 | #endif
32 |
33 | #else
34 |
35 | #ifndef ts_malloc
36 | #define ts_malloc malloc
37 | #endif
38 | #ifndef ts_calloc
39 | #define ts_calloc calloc
40 | #endif
41 | #ifndef ts_realloc
42 | #define ts_realloc realloc
43 | #endif
44 | #ifndef ts_free
45 | #define ts_free free
46 | #endif
47 |
48 | #endif
49 |
50 | #ifdef __cplusplus
51 | }
52 | #endif
53 |
54 | #endif // TREE_SITTER_ALLOC_H_
55 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 |
3 | import Foundation
4 | import PackageDescription
5 |
6 | var sources = ["src/parser.c"]
7 | if FileManager.default.fileExists(atPath: "src/scanner.c") {
8 | sources.append("src/scanner.c")
9 | }
10 |
11 | let package = Package(
12 | name: "TreeSitterReScript",
13 | products: [
14 | .library(name: "TreeSitterReScript", targets: ["TreeSitterReScript"]),
15 | ],
16 | dependencies: [
17 | .package(url: "https://github.com/ChimeHQ/SwiftTreeSitter", from: "0.8.0"),
18 | ],
19 | targets: [
20 | .target(
21 | name: "TreeSitterReScript",
22 | dependencies: [],
23 | path: ".",
24 | sources: sources,
25 | resources: [
26 | .copy("queries")
27 | ],
28 | publicHeadersPath: "bindings/swift",
29 | cSettings: [.headerSearchPath("src")]
30 | ),
31 | .testTarget(
32 | name: "TreeSitterReScriptTests",
33 | dependencies: [
34 | "SwiftTreeSitter",
35 | "TreeSitterReScript",
36 | ],
37 | path: "bindings/swift/TreeSitterReScriptTests"
38 | )
39 | ],
40 | cLanguageStandard: .c11
41 | )
42 |
--------------------------------------------------------------------------------
/bindings/python/tree_sitter_rescript/__init__.py:
--------------------------------------------------------------------------------
1 | """ReScript parser for Tree-Sitter"""
2 |
3 | from importlib.resources import files as _files
4 |
5 | from ._binding import language
6 |
7 |
8 | def _get_query(name, file):
9 | query = _files(f"{__package__}.queries") / file
10 | globals()[name] = query.read_text()
11 | return globals()[name]
12 |
13 |
14 | def __getattr__(name):
15 | # NOTE: uncomment these to include any queries that this grammar contains:
16 |
17 | # if name == "HIGHLIGHTS_QUERY":
18 | # return _get_query("HIGHLIGHTS_QUERY", "highlights.scm")
19 | # if name == "INJECTIONS_QUERY":
20 | # return _get_query("INJECTIONS_QUERY", "injections.scm")
21 | # if name == "LOCALS_QUERY":
22 | # return _get_query("LOCALS_QUERY", "locals.scm")
23 | # if name == "TAGS_QUERY":
24 | # return _get_query("TAGS_QUERY", "tags.scm")
25 |
26 | raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
27 |
28 |
29 | __all__ = [
30 | "language",
31 | # "HIGHLIGHTS_QUERY",
32 | # "INJECTIONS_QUERY",
33 | # "LOCALS_QUERY",
34 | # "TAGS_QUERY",
35 | ]
36 |
37 |
38 | def __dir__():
39 | return sorted(__all__ + [
40 | "__all__", "__builtins__", "__cached__", "__doc__", "__file__",
41 | "__loader__", "__name__", "__package__", "__path__", "__spec__",
42 | ])
43 |
--------------------------------------------------------------------------------
/test/corpus/comments.txt:
--------------------------------------------------------------------------------
1 | ================================================================================
2 | Comments
3 | ================================================================================
4 |
5 | // Single line
6 | 1
7 |
8 | /*
9 | * Multiline
10 | */
11 | 2
12 |
13 | /* /* Nested
14 | /* multiple */ times
15 | // */ */
16 | 3
17 |
18 | 4 // post single-line
19 |
20 | 5 /* post multi-line */
21 |
22 | /* / */
23 | 6
24 |
25 | /* */ 7
26 |
27 | /** **/ 8
28 |
29 | /* comment //*/ */*/ 9
30 |
31 | foo
32 | // in-pipe
33 | ->bar
34 |
35 | switch foo {
36 | | 1 => 1
37 | // in-switch
38 | }
39 |
40 | --------------------------------------------------------------------------------
41 |
42 | (source_file
43 | (comment)
44 | (expression_statement
45 | (number))
46 | (comment)
47 | (expression_statement
48 | (number))
49 | (comment)
50 | (expression_statement
51 | (number))
52 | (expression_statement
53 | (number))
54 | (comment)
55 | (expression_statement
56 | (number))
57 | (comment)
58 | (comment)
59 | (expression_statement
60 | (number))
61 | (comment)
62 | (expression_statement
63 | (number))
64 | (comment)
65 | (expression_statement
66 | (number))
67 | (comment)
68 | (expression_statement
69 | (number))
70 | (expression_statement
71 | (pipe_expression
72 | (value_identifier)
73 | (comment)
74 | (value_identifier)))
75 | (expression_statement
76 | (switch_expression
77 | (value_identifier)
78 | (switch_match
79 | (number)
80 | (sequence_expression
81 | (expression_statement
82 | (number))))
83 | (comment))))
84 |
--------------------------------------------------------------------------------
/test/highlight/expressions.res:
--------------------------------------------------------------------------------
1 | foo->bar == +x +. 1.0
2 | // ^ operator
3 | // ^ operator
4 | // ^ operator
5 | // ^ operator
6 |
7 |
8 | { . "x": 1 }
9 | // ^ property
10 |
11 | switch foo {
12 | // <- keyword.conditional
13 | | list{1, x, ...rest} =>
14 | //^ type
15 | // ^ number
16 | // ^ variable.parameter
17 | // ^ punctuation.special
18 | // ^ variable.parameter
19 | // ^ operator
20 | 42
21 | | list{1, 2, ...list{b, ..._} as rest} => rest
22 | // ^ variable.parameter
23 | // ^ variable
24 | | exception Js.Exn.Error(_) => 99
25 | //^ keyword.exception
26 | }
27 |
28 | switch bar {
29 | | #...Mod.t => 33
30 | //^ constructor
31 | }
32 |
33 | { foo, bar: baz, qux: 1 }
34 | //^ property
35 | // ^ property
36 |
37 | exception InputClosed(string)
38 | //<- keyword.exception
39 |
40 | raise(InputClosed("The stream has closed!"))
41 | //<- keyword.exception
42 |
43 | try {
44 | //<- keyword.exception
45 | someOtherJSFunctionThatThrows()
46 | } catch {
47 | // ^ keyword.exception
48 | | Not_found => 1 // catch a ReScript exception
49 | | Invalid_argument(_) => 2 // catch a second ReScript exception
50 | | Js.Exn.Error(obj) => 3 // catch the JS exception
51 | }
52 |
53 |
54 | let c = list{a, ...list{b}}
55 | // ^ type
56 | // ^ variable
57 | // ^ variable
58 |
59 | let x = fn()
60 | // ^ function.call
61 |
62 | let y = x->M.f->f
63 | // ^function.call
64 | // ^function.call
65 |
66 | let v = M.v
67 | // ^variable
68 |
69 | let {x} = y
70 | // ^variable
71 |
72 | let {X.x} = y
73 | // ^variable.member
74 |
75 | let x = y.x
76 | // ^variable.member
77 |
78 | f(~a=b, ())
79 | // ^variable.parameter
80 | // ^constant.builtin
81 |
--------------------------------------------------------------------------------
/bindings/rust/lib.rs:
--------------------------------------------------------------------------------
1 | //! This crate provides ReScript language support for the [tree-sitter][] parsing library.
2 | //!
3 | //! Typically, you will use the [LANGUAGE][] constant to add this language to a
4 | //! tree-sitter [Parser][], and then use the parser to parse some code:
5 | //!
6 | //! ```
7 | //! let code = r#"
8 | //! "#;
9 | //! let mut parser = tree_sitter::Parser::new();
10 | //! let language = tree_sitter_rescript::LANGUAGE;
11 | //! parser
12 | //! .set_language(&language.into())
13 | //! .expect("Error loading ReScript parser");
14 | //! let tree = parser.parse(code, None).unwrap();
15 | //! assert!(!tree.root_node().has_error());
16 | //! ```
17 | //!
18 | //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
19 | //! [tree-sitter]: https://tree-sitter.github.io/
20 |
21 | use tree_sitter_language::LanguageFn;
22 |
23 | extern "C" {
24 | fn tree_sitter_rescript() -> *const ();
25 | }
26 |
27 | /// The tree-sitter [`LanguageFn`][LanguageFn] for this grammar.
28 | ///
29 | /// [LanguageFn]: https://docs.rs/tree-sitter-language/*/tree_sitter_language/struct.LanguageFn.html
30 | pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_rescript) };
31 |
32 | /// The content of the [`node-types.json`][] file for this grammar.
33 | ///
34 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types
35 | pub const NODE_TYPES: &str = include_str!("../../src/node-types.json");
36 |
37 | // NOTE: uncomment these to include any queries that this grammar contains:
38 |
39 | // pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm");
40 | // pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm");
41 | // pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm");
42 | // pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm");
43 |
44 | #[cfg(test)]
45 | mod tests {
46 | #[test]
47 | fn test_can_load_grammar() {
48 | let mut parser = tree_sitter::Parser::new();
49 | parser
50 | .set_language(&super::LANGUAGE.into())
51 | .expect("Error loading ReScript parser");
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from os import path
2 | from platform import system
3 | from sysconfig import get_config_var
4 |
5 | from setuptools import Extension, find_packages, setup
6 | from setuptools.command.build import build
7 | from setuptools.command.egg_info import egg_info
8 | from wheel.bdist_wheel import bdist_wheel
9 |
10 | sources = [
11 | "bindings/python/tree_sitter_rescript/binding.c",
12 | "src/parser.c",
13 | ]
14 | if path.exists("src/scanner.c"):
15 | sources.append("src/scanner.c")
16 |
17 | macros: list[tuple[str, str | None]] = [
18 | ("PY_SSIZE_T_CLEAN", None),
19 | ("TREE_SITTER_HIDE_SYMBOLS", None),
20 | ]
21 | if limited_api := not get_config_var("Py_GIL_DISABLED"):
22 | macros.append(("Py_LIMITED_API", "0x030A0000"))
23 |
24 | if system() != "Windows":
25 | cflags = ["-std=c11", "-fvisibility=hidden"]
26 | else:
27 | cflags = ["/std:c11", "/utf-8"]
28 |
29 |
30 | class Build(build):
31 | def run(self):
32 | if path.isdir("queries"):
33 | dest = path.join(self.build_lib, "tree_sitter_rescript", "queries")
34 | self.copy_tree("queries", dest)
35 | super().run()
36 |
37 |
38 | class BdistWheel(bdist_wheel):
39 | def get_tag(self):
40 | python, abi, platform = super().get_tag()
41 | if python.startswith("cp"):
42 | python, abi = "cp310", "abi3"
43 | return python, abi, platform
44 |
45 |
46 | class EggInfo(egg_info):
47 | def find_sources(self):
48 | super().find_sources()
49 | self.filelist.recursive_include("queries", "*.scm")
50 | self.filelist.include("src/tree_sitter/*.h")
51 |
52 |
53 | setup(
54 | packages=find_packages("bindings/python"),
55 | package_dir={"": "bindings/python"},
56 | package_data={
57 | "tree_sitter_rescript": ["*.pyi", "py.typed"],
58 | "tree_sitter_rescript.queries": ["*.scm"],
59 | },
60 | ext_package="tree_sitter_rescript",
61 | ext_modules=[
62 | Extension(
63 | name="_binding",
64 | sources=sources,
65 | extra_compile_args=cflags,
66 | define_macros=macros,
67 | include_dirs=["src"],
68 | py_limited_api=limited_api,
69 | )
70 | ],
71 | cmdclass={
72 | "build": Build,
73 | "bdist_wheel": BdistWheel,
74 | "egg_info": EggInfo,
75 | },
76 | zip_safe=False
77 | )
78 |
--------------------------------------------------------------------------------
/test/corpus/decorators.txt:
--------------------------------------------------------------------------------
1 | ================================================================================
2 | Decorator inline
3 | ================================================================================
4 |
5 | @@deprecated
6 | @@Uppercase
7 | @@Upper._2323
8 | @@_.decorator
9 | @@_.1decorator
10 | @@_123
11 | @@\"escape"
12 | @@\"de.2precated"
13 |
14 | --------------------------------------------------------------------------------
15 |
16 | (source_file
17 | (decorator
18 | (decorator_identifier))
19 | (decorator
20 | (decorator_identifier))
21 | (decorator
22 | (decorator_identifier))
23 | (decorator
24 | (decorator_identifier))
25 | (decorator
26 | (decorator_identifier))
27 | (decorator
28 | (decorator_identifier))
29 | (decorator
30 | (decorator_identifier))
31 | (decorator
32 | (decorator_identifier)))
33 |
34 | ================================================================================
35 | Decorator with arguments
36 | ================================================================================
37 |
38 | @@deprecated()
39 | @@Uppercase()
40 | @@Upper._2323()
41 | @@_.decorator()
42 | @@_.1decorator()
43 | @@_123()
44 | @@\"escape"()
45 | @@\"de.2precated"()
46 |
47 | --------------------------------------------------------------------------------
48 |
49 | (source_file
50 | (decorator
51 | (decorator_identifier)
52 | (decorator_arguments))
53 | (decorator
54 | (decorator_identifier)
55 | (decorator_arguments))
56 | (decorator
57 | (decorator_identifier)
58 | (decorator_arguments))
59 | (decorator
60 | (decorator_identifier)
61 | (decorator_arguments))
62 | (decorator
63 | (decorator_identifier)
64 | (decorator_arguments))
65 | (decorator
66 | (decorator_identifier)
67 | (decorator_arguments))
68 | (decorator
69 | (decorator_identifier)
70 | (decorator_arguments))
71 | (decorator
72 | (decorator_identifier)
73 | (decorator_arguments)))
74 |
75 | ================================================================================
76 | Decorator with type
77 | ================================================================================
78 |
79 | @react.component(:sharedProps)
80 |
81 | --------------------------------------------------------------------------------
82 |
83 | (source_file
84 | (decorator
85 | (decorator_identifier)
86 | (decorator_arguments
87 | (type_annotation
88 | (type_identifier)))))
89 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.13)
2 |
3 | project(tree-sitter-rescript
4 | VERSION "5.0.0"
5 | DESCRIPTION "ReScript parser for Tree-Sitter"
6 | HOMEPAGE_URL "https://github.com/tree-sitter/tree-sitter-rescript"
7 | LANGUAGES C)
8 |
9 | option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
10 | option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF)
11 |
12 | set(TREE_SITTER_ABI_VERSION 15 CACHE STRING "Tree-sitter ABI version")
13 | if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$")
14 | unset(TREE_SITTER_ABI_VERSION CACHE)
15 | message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer")
16 | endif()
17 |
18 | find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI")
19 |
20 | add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c"
21 | DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
22 | COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json
23 | --abi=${TREE_SITTER_ABI_VERSION}
24 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
25 | COMMENT "Generating parser.c")
26 |
27 | add_library(tree-sitter-rescript src/parser.c)
28 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c)
29 | target_sources(tree-sitter-rescript PRIVATE src/scanner.c)
30 | endif()
31 | target_include_directories(tree-sitter-rescript
32 | PRIVATE src
33 | INTERFACE $
34 | $)
35 |
36 | target_compile_definitions(tree-sitter-rescript PRIVATE
37 | $<$:TREE_SITTER_REUSE_ALLOCATOR>
38 | $<$:TREE_SITTER_DEBUG>)
39 |
40 | set_target_properties(tree-sitter-rescript
41 | PROPERTIES
42 | C_STANDARD 11
43 | POSITION_INDEPENDENT_CODE ON
44 | SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}"
45 | DEFINE_SYMBOL "")
46 |
47 | configure_file(bindings/c/tree-sitter-rescript.pc.in
48 | "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-rescript.pc" @ONLY)
49 |
50 | include(GNUInstallDirs)
51 |
52 | install(FILES bindings/c/tree-sitter-rescript.h
53 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter")
54 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-rescript.pc"
55 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig")
56 | install(TARGETS tree-sitter-rescript
57 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
58 |
59 | file(GLOB QUERIES queries/*.scm)
60 | install(FILES ${QUERIES}
61 | DESTINATION "${CMAKE_INSTALL_DATADIR}/tree-sitter/queries/rescript")
62 |
63 | add_custom_target(ts-test "${TREE_SITTER_CLI}" test
64 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
65 | COMMENT "tree-sitter test")
66 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | ifeq ($(OS),Windows_NT)
2 | $(error Windows is not supported)
3 | endif
4 |
5 | LANGUAGE_NAME := tree-sitter-rescript
6 | HOMEPAGE_URL := https://github.com/tree-sitter/tree-sitter-rescript
7 | VERSION := 0.1.0
8 |
9 | # repository
10 | SRC_DIR := src
11 |
12 | TS ?= tree-sitter
13 |
14 | # install directory layout
15 | PREFIX ?= /usr/local
16 | DATADIR ?= $(PREFIX)/share
17 | INCLUDEDIR ?= $(PREFIX)/include
18 | LIBDIR ?= $(PREFIX)/lib
19 | PCLIBDIR ?= $(LIBDIR)/pkgconfig
20 |
21 | # source/object files
22 | PARSER := $(SRC_DIR)/parser.c
23 | EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c))
24 | OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS))
25 |
26 | # flags
27 | ARFLAGS ?= rcs
28 | override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC
29 |
30 | # ABI versioning
31 | SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER))
32 | SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION)))
33 |
34 | # OS-specific bits
35 | ifeq ($(shell uname),Darwin)
36 | SOEXT = dylib
37 | SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT)
38 | SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT)
39 | LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks
40 | else
41 | SOEXT = so
42 | SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR)
43 | SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR)
44 | LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER)
45 | endif
46 | ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),)
47 | PCLIBDIR := $(PREFIX)/libdata/pkgconfig
48 | endif
49 |
50 | all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc
51 |
52 | lib$(LANGUAGE_NAME).a: $(OBJS)
53 | $(AR) $(ARFLAGS) $@ $^
54 |
55 | lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS)
56 | $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
57 | ifneq ($(STRIP),)
58 | $(STRIP) $@
59 | endif
60 |
61 | $(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in
62 | sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \
63 | -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \
64 | -e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \
65 | -e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \
66 | -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \
67 | -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@
68 |
69 | $(PARSER): $(SRC_DIR)/grammar.json
70 | $(TS) generate $^
71 |
72 | install: all
73 | install -d '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/rescript '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'
74 | install -m644 bindings/c/tree_sitter/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h
75 | install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
76 | install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a
77 | install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER)
78 | ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR)
79 | ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT)
80 | install -m644 queries/*.scm '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/rescript
81 |
82 | uninstall:
83 | $(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \
84 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \
85 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \
86 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \
87 | '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \
88 | '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
89 | $(RM) -r '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/rescript
90 |
91 | clean:
92 | $(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT)
93 |
94 | test:
95 | $(TS) test
96 |
97 | .PHONY: all install uninstall clean test
98 |
--------------------------------------------------------------------------------
/queries/textobjects.scm:
--------------------------------------------------------------------------------
1 | ; Queries for nvim-treesitter/nvim-treesitter-textobjects
2 | ;--------------------------------------------------------
3 |
4 | ; Classes (modules)
5 | ;------------------
6 |
7 | (module_binding definition: ((_) @class.inner)) @class.outer
8 |
9 | ; Blocks
10 | ;-------
11 |
12 | (block (_) @block.inner) @block.outer
13 |
14 | ; Functions
15 | ;----------
16 |
17 | (function body: (_) @function.inner) @function.outer
18 |
19 | ; Calls
20 | ;------
21 |
22 | (call_expression arguments: ((_) @call.inner)) @call.outer
23 |
24 | ; Comments
25 | ;---------
26 |
27 | (comment) @comment.outer
28 |
29 | ; Parameters
30 | ;-----------
31 |
32 | (function parameter: (_) @parameter.inner @parameter.outer)
33 |
34 | (formal_parameters
35 | "," @_formal_parameters_start
36 | . (_) @parameter.inner
37 | (#make-range! "parameter.outer" @_formal_parameters_start @parameter.inner))
38 | (formal_parameters
39 | . (_) @parameter.inner
40 | . ","? @_formal_parameters_end
41 | (#make-range! "parameter.outer" @parameter.inner @_formal_parameters_end))
42 |
43 | (arguments
44 | "," @_arguments_start
45 | . (_) @parameter.inner
46 | (#make-range! "parameter.outer" @_arguments_start @parameter.inner))
47 | (arguments
48 | . (_) @parameter.inner
49 | . ","? @_arguments_end
50 | (#make-range! "parameter.outer" @parameter.inner @_arguments_end))
51 |
52 | (function_type_parameters
53 | "," @_function_type_parameters_start
54 | . (_) @parameter.inner
55 | (#make-range! "parameter.outer" @_function_type_parameters_start @parameter.inner))
56 | (function_type_parameters
57 | . (_) @parameter.inner
58 | . ","? @_function_type_parameters_end
59 | (#make-range! "parameter.outer" @parameter.inner @_function_type_parameters_end))
60 |
61 | (functor_parameters
62 | "," @_functor_parameters_start
63 | . (_) @parameter.inner
64 | (#make-range! "parameter.outer" @_functor_parameters_start @parameter.inner))
65 | (functor_parameters
66 | . (_) @parameter.inner
67 | . ","? @_functor_parameters_end
68 | (#make-range! "parameter.outer" @parameter.inner @_functor_parameters_end))
69 |
70 | (type_parameters
71 | "," @_type_parameters_start
72 | . (_) @parameter.inner
73 | (#make-range! "parameter.outer" @_type_parameters_start @parameter.inner))
74 | (type_parameters
75 | . (_) @parameter.inner
76 | . ","? @_type_parameters_end
77 | (#make-range! "parameter.outer" @parameter.inner @_type_parameters_end))
78 |
79 | (type_arguments
80 | "," @_type_arguments_start
81 | . (_) @parameter.inner
82 | (#make-range! "parameter.outer" @_type_arguments_start @parameter.inner))
83 | (type_arguments
84 | . (_) @parameter.inner
85 | . ","? @_type_arguments_end
86 | (#make-range! "parameter.outer" @parameter.inner @_type_arguments_end))
87 |
88 | (decorator_arguments
89 | "," @_decorator_arguments_start
90 | . (_) @parameter.inner
91 | (#make-range! "parameter.outer" @_decorator_arguments_start @parameter.inner))
92 | (decorator_arguments
93 | . (_) @parameter.inner
94 | . ","? @_arguments_end
95 | (#make-range! "parameter.outer" @parameter.inner @_arguments_end))
96 |
97 | (variant_parameters
98 | "," @_variant_parameters_start
99 | . (_) @parameter.inner
100 | (#make-range! "parameter.outer" @_variant_parameters_start @parameter.inner))
101 | (variant_parameters
102 | . (_) @parameter.inner
103 | . ","? @_variant_parameters_end
104 | (#make-range! "parameter.outer" @parameter.inner @_variant_parameters_end))
105 |
106 | (polyvar_parameters
107 | "," @_polyvar_parameters_start
108 | . (_) @parameter.inner
109 | (#make-range! "parameter.outer" @_polyvar_parameters_start @parameter.inner))
110 | (polyvar_parameters
111 | . (_) @parameter.inner
112 | . ","? @_polyvar_parameters_end
113 | (#make-range! "parameter.outer" @parameter.inner @_polyvar_parameters_end))
114 |
115 |
--------------------------------------------------------------------------------
/queries/highlights.scm:
--------------------------------------------------------------------------------
1 | (comment) @comment
2 |
3 | ; Identifiers
4 | ;------------
5 |
6 | ; Escaped identifiers like \"+."
7 | ((value_identifier) @constant.macro
8 | (#match? @constant.macro "^\\.*$"))
9 |
10 |
11 | ((value_identifier) @variable)
12 |
13 | [
14 | (type_identifier)
15 | (unit_type)
16 | (list)
17 | (list_pattern)
18 | ] @type
19 |
20 | ((type_identifier) @type.builtin
21 | (#any-of? @type.builtin
22 | "int" "char" "string" "float" "bool" "unit"))
23 |
24 | [
25 | (variant_identifier)
26 | (polyvar_identifier)
27 | ] @constructor
28 |
29 | (record_type_field (property_identifier) @property)
30 | (record_field (property_identifier) @property)
31 | (object (field (property_identifier) @property))
32 | (object_type (field (property_identifier) @property))
33 | (module_identifier) @module
34 |
35 | (member_expression (property_identifier) @variable.member)
36 |
37 | (value_identifier_path
38 | (module_identifier)
39 | (value_identifier) @variable)
40 |
41 |
42 | (record_pattern
43 | (value_identifier_path
44 | (value_identifier) @variable.member))
45 |
46 | (record_pattern
47 | (value_identifier) @variable)
48 |
49 | (labeled_argument
50 | label: (value_identifier) @variable.parameter)
51 |
52 |
53 | ; Parameters
54 | ;----------------
55 |
56 | (list_pattern (value_identifier) @variable.parameter)
57 | (spread_pattern (value_identifier) @variable.parameter)
58 |
59 | ; String literals
60 | ;----------------
61 |
62 | [
63 | (string)
64 | (template_string)
65 | ] @string
66 |
67 |
68 | (character) @character
69 | (escape_sequence) @string.escape
70 |
71 | ; Other literals
72 | ;---------------
73 |
74 | [
75 | (true)
76 | (false)
77 | ] @boolean
78 |
79 | (number) @number
80 | (polyvar) @constructor
81 | (polyvar_string) @constructor
82 |
83 | ; Functions
84 | ;----------
85 |
86 | ; parameter(s) in parens
87 |
88 | (parameter (value_identifier) @variable.parameter)
89 | (labeled_parameter (value_identifier) @variable.parameter)
90 |
91 | ; single parameter with no parens
92 | (function parameter: (value_identifier) @variable.parameter)
93 |
94 | ; first-level descructuring (required for nvim-tree-sitter as it only matches direct
95 | ; children and the above patterns do not match destructuring patterns in NeoVim)
96 | (parameter (tuple_pattern (tuple_item_pattern (value_identifier) @variable.parameter)))
97 | (parameter (array_pattern (value_identifier) @variable.parameter))
98 | (parameter (record_pattern (value_identifier) @variable.parameter))
99 |
100 | ; function identifier in let binding
101 | (let_binding
102 | pattern: (value_identifier) @function
103 | body: (function))
104 |
105 | ; function calls
106 |
107 | (call_expression
108 | function: (value_identifier_path
109 | _
110 | (value_identifier) @function.call))
111 |
112 | (call_expression
113 | function: (value_identifier) @function.call)
114 |
115 | ; highlight the right-hand side of a pipe operator as a function call
116 | (pipe_expression
117 | _
118 | [(value_identifier_path
119 | _
120 | (value_identifier) @function.call)
121 | (value_identifier) @function.call])
122 |
123 |
124 | ; Meta
125 | ;-----
126 |
127 | (decorator_identifier) @attribute
128 |
129 | (extension_identifier) @keyword
130 | ("%") @keyword
131 |
132 | ; Misc
133 | ;-----
134 |
135 | (polyvar_type_pattern "#" @constructor)
136 |
137 | [
138 | "include"
139 | "open"
140 | ] @keyword.import
141 |
142 |
143 | [
144 | "private"
145 | "mutable"
146 | "rec"
147 | ] @keyword.modifier
148 |
149 | [
150 | "type"
151 | ] @keyword.type
152 |
153 | [
154 | "and"
155 | "with"
156 | "as"
157 | ] @keyword.operator
158 |
159 | [
160 | "export"
161 | "external"
162 | "let"
163 | "module"
164 | "assert"
165 | "await"
166 | "lazy"
167 | "constraint"
168 | ] @keyword
169 |
170 | (("await") @keyword.coroutine)
171 |
172 | ((function "async" @keyword.coroutine))
173 |
174 | (module_unpack "unpack" @keyword)
175 |
176 | [
177 | "if"
178 | "else"
179 | "switch"
180 | "when"
181 | ] @keyword.conditional
182 |
183 | [
184 | "exception"
185 | "try"
186 | "catch"
187 | ] @keyword.exception
188 |
189 | (call_expression
190 | function: (value_identifier) @keyword.exception
191 | (#eq? @keyword.exception "raise"))
192 |
193 | [
194 | "for"
195 | "in"
196 | "to"
197 | "downto"
198 | "while"
199 | ] @keyword.repeat
200 |
201 | [
202 | "."
203 | ","
204 | "|"
205 | ":"
206 | ] @punctuation.delimiter
207 |
208 | [
209 | "++"
210 | "+"
211 | "+."
212 | "-"
213 | "-."
214 | "*"
215 | "**"
216 | "*."
217 | "/."
218 | "<="
219 | "=="
220 | "==="
221 | "!"
222 | "!="
223 | "!=="
224 | ">="
225 | "&&"
226 | "||"
227 | "="
228 | ":="
229 | "->"
230 | "|>"
231 | ":>"
232 | "+="
233 | "=>"
234 | (uncurry)
235 | ] @operator
236 |
237 | ; Explicitly enclose these operators with binary_expression
238 | ; to avoid confusion with JSX tag delimiters
239 | (binary_expression ["<" ">" "/"] @operator)
240 |
241 | [
242 | "("
243 | ")"
244 | "{"
245 | "}"
246 | "["
247 | "]"
248 | "<"
249 | ">"
250 | ] @punctuation.bracket
251 |
252 | (unit ["(" ")"] @constant.builtin)
253 |
254 | (template_substitution
255 | "${" @punctuation.special
256 | "}" @punctuation.special) @none
257 |
258 | (polyvar_type
259 | [
260 | "["
261 | "[>"
262 | "[<"
263 | "]"
264 | ] @punctuation.bracket)
265 |
266 | [
267 | "~"
268 | "?"
269 | ".."
270 | "..."
271 | ] @punctuation.special
272 |
273 | (ternary_expression ["?" ":"] @keyword.conditional.ternary)
274 |
275 | ; JSX
276 | ;----------
277 | (jsx_identifier) @tag
278 | (jsx_element
279 | open_tag: (jsx_opening_element ["<" ">"] @tag.delimiter))
280 | (jsx_element
281 | close_tag: (jsx_closing_element ["<" "/" ">"] @tag.delimiter))
282 | (jsx_self_closing_element ["/" ">" "<"] @tag.delimiter)
283 | (jsx_fragment [">" "<" "/"] @tag.delimiter)
284 | (jsx_attribute (property_identifier) @tag.attribute)
285 |
286 | ; Error
287 | ;----------
288 |
289 | (ERROR) @error
290 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "aho-corasick"
7 | version = "1.1.3"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
10 | dependencies = [
11 | "memchr",
12 | ]
13 |
14 | [[package]]
15 | name = "cc"
16 | version = "1.2.16"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
19 | dependencies = [
20 | "shlex",
21 | ]
22 |
23 | [[package]]
24 | name = "equivalent"
25 | version = "1.0.2"
26 | source = "registry+https://github.com/rust-lang/crates.io-index"
27 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
28 |
29 | [[package]]
30 | name = "hashbrown"
31 | version = "0.15.2"
32 | source = "registry+https://github.com/rust-lang/crates.io-index"
33 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
34 |
35 | [[package]]
36 | name = "indexmap"
37 | version = "2.7.1"
38 | source = "registry+https://github.com/rust-lang/crates.io-index"
39 | checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
40 | dependencies = [
41 | "equivalent",
42 | "hashbrown",
43 | ]
44 |
45 | [[package]]
46 | name = "itoa"
47 | version = "1.0.14"
48 | source = "registry+https://github.com/rust-lang/crates.io-index"
49 | checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
50 |
51 | [[package]]
52 | name = "memchr"
53 | version = "2.7.4"
54 | source = "registry+https://github.com/rust-lang/crates.io-index"
55 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
56 |
57 | [[package]]
58 | name = "proc-macro2"
59 | version = "1.0.94"
60 | source = "registry+https://github.com/rust-lang/crates.io-index"
61 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
62 | dependencies = [
63 | "unicode-ident",
64 | ]
65 |
66 | [[package]]
67 | name = "quote"
68 | version = "1.0.39"
69 | source = "registry+https://github.com/rust-lang/crates.io-index"
70 | checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
71 | dependencies = [
72 | "proc-macro2",
73 | ]
74 |
75 | [[package]]
76 | name = "regex"
77 | version = "1.11.1"
78 | source = "registry+https://github.com/rust-lang/crates.io-index"
79 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
80 | dependencies = [
81 | "aho-corasick",
82 | "memchr",
83 | "regex-automata",
84 | "regex-syntax",
85 | ]
86 |
87 | [[package]]
88 | name = "regex-automata"
89 | version = "0.4.9"
90 | source = "registry+https://github.com/rust-lang/crates.io-index"
91 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
92 | dependencies = [
93 | "aho-corasick",
94 | "memchr",
95 | "regex-syntax",
96 | ]
97 |
98 | [[package]]
99 | name = "regex-syntax"
100 | version = "0.8.5"
101 | source = "registry+https://github.com/rust-lang/crates.io-index"
102 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
103 |
104 | [[package]]
105 | name = "ryu"
106 | version = "1.0.19"
107 | source = "registry+https://github.com/rust-lang/crates.io-index"
108 | checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
109 |
110 | [[package]]
111 | name = "serde"
112 | version = "1.0.218"
113 | source = "registry+https://github.com/rust-lang/crates.io-index"
114 | checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
115 | dependencies = [
116 | "serde_derive",
117 | ]
118 |
119 | [[package]]
120 | name = "serde_derive"
121 | version = "1.0.218"
122 | source = "registry+https://github.com/rust-lang/crates.io-index"
123 | checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
124 | dependencies = [
125 | "proc-macro2",
126 | "quote",
127 | "syn",
128 | ]
129 |
130 | [[package]]
131 | name = "serde_json"
132 | version = "1.0.140"
133 | source = "registry+https://github.com/rust-lang/crates.io-index"
134 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
135 | dependencies = [
136 | "indexmap",
137 | "itoa",
138 | "memchr",
139 | "ryu",
140 | "serde",
141 | ]
142 |
143 | [[package]]
144 | name = "shlex"
145 | version = "1.3.0"
146 | source = "registry+https://github.com/rust-lang/crates.io-index"
147 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
148 |
149 | [[package]]
150 | name = "streaming-iterator"
151 | version = "0.1.9"
152 | source = "registry+https://github.com/rust-lang/crates.io-index"
153 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
154 |
155 | [[package]]
156 | name = "syn"
157 | version = "2.0.99"
158 | source = "registry+https://github.com/rust-lang/crates.io-index"
159 | checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
160 | dependencies = [
161 | "proc-macro2",
162 | "quote",
163 | "unicode-ident",
164 | ]
165 |
166 | [[package]]
167 | name = "tree-sitter"
168 | version = "0.25.2"
169 | source = "registry+https://github.com/rust-lang/crates.io-index"
170 | checksum = "5168a515fe492af54c5cc8800ff8c840be09fa5168de45838afaecd3e008bce4"
171 | dependencies = [
172 | "cc",
173 | "regex",
174 | "regex-syntax",
175 | "serde_json",
176 | "streaming-iterator",
177 | "tree-sitter-language",
178 | ]
179 |
180 | [[package]]
181 | name = "tree-sitter-language"
182 | version = "0.1.5"
183 | source = "registry+https://github.com/rust-lang/crates.io-index"
184 | checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8"
185 |
186 | [[package]]
187 | name = "tree-sitter-rescript"
188 | version = "0.0.1"
189 | dependencies = [
190 | "cc",
191 | "tree-sitter",
192 | "tree-sitter-language",
193 | ]
194 |
195 | [[package]]
196 | name = "unicode-ident"
197 | version = "1.0.17"
198 | source = "registry+https://github.com/rust-lang/crates.io-index"
199 | checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
200 |
--------------------------------------------------------------------------------
/test/corpus/functions.txt:
--------------------------------------------------------------------------------
1 | ===================================================
2 | Simple parameters
3 | ===================================================
4 |
5 | a => 1
6 | () => 2
7 | (d, e) => 3
8 | (f, g) => {
9 | h
10 | }
11 | (trailing,) => 4
12 | (h, trailing,) => 5
13 | (set, kv) => 2
14 | (a, .b, c, .d) => 7
15 | (async) => 1
16 |
17 | ---
18 |
19 | (source_file
20 | (expression_statement (function
21 | (value_identifier)
22 | (number)))
23 | (expression_statement (function
24 | (formal_parameters)
25 | (number)))
26 | (expression_statement (function
27 | (formal_parameters
28 | (parameter (value_identifier)) (parameter (value_identifier)))
29 | (number)))
30 | (expression_statement (function
31 | (formal_parameters
32 | (parameter (value_identifier))
33 | (parameter (value_identifier)))
34 | (block
35 | (expression_statement (value_identifier)))))
36 | (expression_statement (function
37 | (formal_parameters
38 | (parameter (value_identifier)))
39 | (number)))
40 | (expression_statement (function
41 | (formal_parameters
42 | (parameter (value_identifier)) (parameter (value_identifier)))
43 | (number)))
44 | (expression_statement (function
45 | (formal_parameters (parameter (value_identifier)) (parameter (value_identifier)))
46 | (number)))
47 | (expression_statement (function
48 | (formal_parameters
49 | (parameter (value_identifier))
50 | (parameter
51 | (uncurry)
52 | (value_identifier))
53 | (parameter (value_identifier))
54 | (parameter
55 | (uncurry)
56 | (value_identifier)))
57 | (number)))
58 | (expression_statement
59 | (function
60 | (formal_parameters
61 | (parameter (value_identifier)))
62 | (number))))
63 |
64 | ===================================================
65 | Type annotations
66 | ===================================================
67 |
68 | (x: int, ~y: float): int => 5
69 | ({contents: (x: int)}, {contents: y}) => x == y
70 |
71 | ---
72 |
73 | (source_file
74 | (expression_statement
75 | (function
76 | parameters: (formal_parameters
77 | (parameter (value_identifier) (type_annotation (type_identifier)))
78 | (parameter (labeled_parameter (value_identifier) (type_annotation (type_identifier)))))
79 | return_type: (type_annotation (type_identifier))
80 | body: (number)))
81 |
82 | (expression_statement
83 | (function parameters:
84 | (formal_parameters
85 | (parameter
86 | (record_pattern
87 | (value_identifier)
88 | (parenthesized_pattern (value_identifier) (type_annotation (type_identifier)))))
89 | (parameter
90 | (record_pattern
91 | (value_identifier)
92 | (value_identifier))))
93 | body: (binary_expression
94 | left: (value_identifier)
95 | right: (value_identifier)))))
96 |
97 | ===================================================
98 | Abstract type
99 | ===================================================
100 |
101 | let foo = (type a, x: 'a): a => x
102 |
103 | ---
104 |
105 | (source_file
106 | (let_declaration
107 | (let_binding
108 | (value_identifier)
109 | (function
110 | (formal_parameters
111 | (parameter (abstract_type (type_identifier)))
112 | (parameter
113 | (value_identifier)
114 | (type_annotation (type_identifier))))
115 | (type_annotation (type_identifier))
116 | (value_identifier)))))
117 |
118 | ===================================================
119 | Parameter defaults
120 | ===================================================
121 |
122 | (~x: int=3, ~y=4.0, ~z: int=?, ~w=?, ()) => 5
123 |
124 | ---
125 |
126 | (source_file
127 | (expression_statement
128 | (function
129 | parameters: (formal_parameters
130 | (parameter
131 | (labeled_parameter
132 | (value_identifier)
133 | (type_annotation (type_identifier))
134 | default_value: (number)))
135 | (parameter
136 | (labeled_parameter
137 | (value_identifier)
138 | default_value: (number)))
139 | (parameter
140 | (labeled_parameter
141 | (value_identifier)
142 | (type_annotation (type_identifier))))
143 | (parameter
144 | (labeled_parameter
145 | (value_identifier)))
146 | (parameter (unit)))
147 | body: (number))))
148 |
149 | ===================================================
150 | Parameter aliasing
151 | ===================================================
152 |
153 | (~xTheGreat as x: int=3) => 5
154 | (~p as (x, _)) => x
155 |
156 | ---
157 |
158 | (source_file
159 | (expression_statement
160 | (function
161 | (formal_parameters
162 | (parameter
163 | (labeled_parameter
164 | (value_identifier)
165 | (as_aliasing (value_identifier))
166 | (type_annotation (type_identifier))
167 | (number))))
168 | (number)))
169 |
170 | (expression_statement
171 | (function
172 | (formal_parameters
173 | (parameter
174 | (labeled_parameter
175 | (value_identifier)
176 | (as_aliasing
177 | (tuple_pattern
178 | (tuple_item_pattern (value_identifier))
179 | (tuple_item_pattern (value_identifier)))))))
180 | (value_identifier))))
181 |
182 | ===================================================
183 | Record pattern
184 | ===================================================
185 |
186 | ({fooField, barField: {baz, qux}, mooField: baa}) => 5
187 |
188 | ---
189 |
190 | (source_file
191 | (expression_statement (function
192 | (formal_parameters
193 | (parameter
194 | (record_pattern
195 | (value_identifier)
196 | (value_identifier)
197 | (record_pattern
198 | (value_identifier)
199 | (value_identifier))
200 | (value_identifier)
201 | (value_identifier))))
202 | (number))))
203 |
204 | ===================================================
205 | Ref assignment as body
206 | ===================================================
207 |
208 | reactRef => myRef := Some(reactRef)
209 |
210 | ---
211 |
212 | (source_file
213 | (expression_statement
214 | (function
215 | (value_identifier)
216 | (mutation_expression
217 | (value_identifier)
218 | (variant
219 | (variant_identifier)
220 | (arguments (value_identifier)))))))
221 |
222 | ===================================================
223 | Operator precendence
224 | ===================================================
225 |
226 | (a) => a->Foo.bar == 5
227 |
228 | ---
229 |
230 | (source_file
231 | (expression_statement (function
232 | (formal_parameters (parameter (value_identifier)))
233 | (binary_expression
234 | (pipe_expression
235 | (value_identifier)
236 | (value_identifier_path (module_identifier) (value_identifier)))
237 | (number)))))
238 |
239 | ===================================================
240 | Async
241 | ===================================================
242 |
243 | async () => body
244 |
245 | ---
246 |
247 | (source_file
248 | (expression_statement
249 | (function (formal_parameters) (value_identifier))))
250 |
--------------------------------------------------------------------------------
/src/tree_sitter/parser.h:
--------------------------------------------------------------------------------
1 | #ifndef TREE_SITTER_PARSER_H_
2 | #define TREE_SITTER_PARSER_H_
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #define ts_builtin_sym_error ((TSSymbol)-1)
13 | #define ts_builtin_sym_end 0
14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
15 |
16 | #ifndef TREE_SITTER_API_H_
17 | typedef uint16_t TSStateId;
18 | typedef uint16_t TSSymbol;
19 | typedef uint16_t TSFieldId;
20 | typedef struct TSLanguage TSLanguage;
21 | typedef struct TSLanguageMetadata TSLanguageMetadata;
22 | typedef struct TSLanguageMetadata {
23 | uint8_t major_version;
24 | uint8_t minor_version;
25 | uint8_t patch_version;
26 | } TSLanguageMetadata;
27 | #endif
28 |
29 | typedef struct {
30 | TSFieldId field_id;
31 | uint8_t child_index;
32 | bool inherited;
33 | } TSFieldMapEntry;
34 |
35 | // Used to index the field and supertype maps.
36 | typedef struct {
37 | uint16_t index;
38 | uint16_t length;
39 | } TSMapSlice;
40 |
41 | typedef struct {
42 | bool visible;
43 | bool named;
44 | bool supertype;
45 | } TSSymbolMetadata;
46 |
47 | typedef struct TSLexer TSLexer;
48 |
49 | struct TSLexer {
50 | int32_t lookahead;
51 | TSSymbol result_symbol;
52 | void (*advance)(TSLexer *, bool);
53 | void (*mark_end)(TSLexer *);
54 | uint32_t (*get_column)(TSLexer *);
55 | bool (*is_at_included_range_start)(const TSLexer *);
56 | bool (*eof)(const TSLexer *);
57 | void (*log)(const TSLexer *, const char *, ...);
58 | };
59 |
60 | typedef enum {
61 | TSParseActionTypeShift,
62 | TSParseActionTypeReduce,
63 | TSParseActionTypeAccept,
64 | TSParseActionTypeRecover,
65 | } TSParseActionType;
66 |
67 | typedef union {
68 | struct {
69 | uint8_t type;
70 | TSStateId state;
71 | bool extra;
72 | bool repetition;
73 | } shift;
74 | struct {
75 | uint8_t type;
76 | uint8_t child_count;
77 | TSSymbol symbol;
78 | int16_t dynamic_precedence;
79 | uint16_t production_id;
80 | } reduce;
81 | uint8_t type;
82 | } TSParseAction;
83 |
84 | typedef struct {
85 | uint16_t lex_state;
86 | uint16_t external_lex_state;
87 | } TSLexMode;
88 |
89 | typedef struct {
90 | uint16_t lex_state;
91 | uint16_t external_lex_state;
92 | uint16_t reserved_word_set_id;
93 | } TSLexerMode;
94 |
95 | typedef union {
96 | TSParseAction action;
97 | struct {
98 | uint8_t count;
99 | bool reusable;
100 | } entry;
101 | } TSParseActionEntry;
102 |
103 | typedef struct {
104 | int32_t start;
105 | int32_t end;
106 | } TSCharacterRange;
107 |
108 | struct TSLanguage {
109 | uint32_t abi_version;
110 | uint32_t symbol_count;
111 | uint32_t alias_count;
112 | uint32_t token_count;
113 | uint32_t external_token_count;
114 | uint32_t state_count;
115 | uint32_t large_state_count;
116 | uint32_t production_id_count;
117 | uint32_t field_count;
118 | uint16_t max_alias_sequence_length;
119 | const uint16_t *parse_table;
120 | const uint16_t *small_parse_table;
121 | const uint32_t *small_parse_table_map;
122 | const TSParseActionEntry *parse_actions;
123 | const char * const *symbol_names;
124 | const char * const *field_names;
125 | const TSMapSlice *field_map_slices;
126 | const TSFieldMapEntry *field_map_entries;
127 | const TSSymbolMetadata *symbol_metadata;
128 | const TSSymbol *public_symbol_map;
129 | const uint16_t *alias_map;
130 | const TSSymbol *alias_sequences;
131 | const TSLexerMode *lex_modes;
132 | bool (*lex_fn)(TSLexer *, TSStateId);
133 | bool (*keyword_lex_fn)(TSLexer *, TSStateId);
134 | TSSymbol keyword_capture_token;
135 | struct {
136 | const bool *states;
137 | const TSSymbol *symbol_map;
138 | void *(*create)(void);
139 | void (*destroy)(void *);
140 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
141 | unsigned (*serialize)(void *, char *);
142 | void (*deserialize)(void *, const char *, unsigned);
143 | } external_scanner;
144 | const TSStateId *primary_state_ids;
145 | const char *name;
146 | const TSSymbol *reserved_words;
147 | uint16_t max_reserved_word_set_size;
148 | uint32_t supertype_count;
149 | const TSSymbol *supertype_symbols;
150 | const TSMapSlice *supertype_map_slices;
151 | const TSSymbol *supertype_map_entries;
152 | TSLanguageMetadata metadata;
153 | };
154 |
155 | static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
156 | uint32_t index = 0;
157 | uint32_t size = len - index;
158 | while (size > 1) {
159 | uint32_t half_size = size / 2;
160 | uint32_t mid_index = index + half_size;
161 | const TSCharacterRange *range = &ranges[mid_index];
162 | if (lookahead >= range->start && lookahead <= range->end) {
163 | return true;
164 | } else if (lookahead > range->end) {
165 | index = mid_index;
166 | }
167 | size -= half_size;
168 | }
169 | const TSCharacterRange *range = &ranges[index];
170 | return (lookahead >= range->start && lookahead <= range->end);
171 | }
172 |
173 | /*
174 | * Lexer Macros
175 | */
176 |
177 | #ifdef _MSC_VER
178 | #define UNUSED __pragma(warning(suppress : 4101))
179 | #else
180 | #define UNUSED __attribute__((unused))
181 | #endif
182 |
183 | #define START_LEXER() \
184 | bool result = false; \
185 | bool skip = false; \
186 | UNUSED \
187 | bool eof = false; \
188 | int32_t lookahead; \
189 | goto start; \
190 | next_state: \
191 | lexer->advance(lexer, skip); \
192 | start: \
193 | skip = false; \
194 | lookahead = lexer->lookahead;
195 |
196 | #define ADVANCE(state_value) \
197 | { \
198 | state = state_value; \
199 | goto next_state; \
200 | }
201 |
202 | #define ADVANCE_MAP(...) \
203 | { \
204 | static const uint16_t map[] = { __VA_ARGS__ }; \
205 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \
206 | if (map[i] == lookahead) { \
207 | state = map[i + 1]; \
208 | goto next_state; \
209 | } \
210 | } \
211 | }
212 |
213 | #define SKIP(state_value) \
214 | { \
215 | skip = true; \
216 | state = state_value; \
217 | goto next_state; \
218 | }
219 |
220 | #define ACCEPT_TOKEN(symbol_value) \
221 | result = true; \
222 | lexer->result_symbol = symbol_value; \
223 | lexer->mark_end(lexer);
224 |
225 | #define END_STATE() return result;
226 |
227 | /*
228 | * Parse Table Macros
229 | */
230 |
231 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT)
232 |
233 | #define STATE(id) id
234 |
235 | #define ACTIONS(id) id
236 |
237 | #define SHIFT(state_value) \
238 | {{ \
239 | .shift = { \
240 | .type = TSParseActionTypeShift, \
241 | .state = (state_value) \
242 | } \
243 | }}
244 |
245 | #define SHIFT_REPEAT(state_value) \
246 | {{ \
247 | .shift = { \
248 | .type = TSParseActionTypeShift, \
249 | .state = (state_value), \
250 | .repetition = true \
251 | } \
252 | }}
253 |
254 | #define SHIFT_EXTRA() \
255 | {{ \
256 | .shift = { \
257 | .type = TSParseActionTypeShift, \
258 | .extra = true \
259 | } \
260 | }}
261 |
262 | #define REDUCE(symbol_name, children, precedence, prod_id) \
263 | {{ \
264 | .reduce = { \
265 | .type = TSParseActionTypeReduce, \
266 | .symbol = symbol_name, \
267 | .child_count = children, \
268 | .dynamic_precedence = precedence, \
269 | .production_id = prod_id \
270 | }, \
271 | }}
272 |
273 | #define RECOVER() \
274 | {{ \
275 | .type = TSParseActionTypeRecover \
276 | }}
277 |
278 | #define ACCEPT_INPUT() \
279 | {{ \
280 | .type = TSParseActionTypeAccept \
281 | }}
282 |
283 | #ifdef __cplusplus
284 | }
285 | #endif
286 |
287 | #endif // TREE_SITTER_PARSER_H_
288 |
--------------------------------------------------------------------------------
/test/corpus/literals.txt:
--------------------------------------------------------------------------------
1 | ================================================================================
2 | Boolean
3 | ================================================================================
4 |
5 | true
6 | false
7 |
8 | --------------------------------------------------------------------------------
9 |
10 | (source_file
11 | (expression_statement
12 | (true))
13 | (expression_statement
14 | (false)))
15 |
16 | ================================================================================
17 | Numbers
18 | ================================================================================
19 |
20 | 04000
21 | 400
22 | 100n
23 | 0xffffffffn
24 | 0b00111n
25 | 0o1234n
26 | 0xa_b_c
27 | 0o1_1
28 | 0b1_000_000
29 | 1_2_3
30 | 12_3.4_5e6_7
31 | 0b1_000_000n
32 | 01
33 | 00000123
34 | -3
35 | -3.0
36 | +3
37 | +3.0
38 | 1L
39 | 1_2_3L
40 | -1L
41 | -1_2_3L
42 | 0b1_000_000L
43 | 0xffffffffL
44 | 0o1234L
45 | 10l
46 | 0xffffffffl
47 | -0x3.p+1
48 | 0x1p2047
49 | -0x1p2047
50 | 0x1.2p2047
51 | 0x1p-1022
52 | 0x0.0000_0000_0000_1p-1022
53 | 0x1p-52
54 | 0x1.0000_0000_0000_1
55 | 0x1p-1023
56 | 0xffffp0
57 | 00007.0
58 | 02e3
59 | 0000.2
60 | 00.
61 | 000.
62 | 01.
63 | 001.
64 | 002e3
65 |
66 | --------------------------------------------------------------------------------
67 |
68 | (source_file
69 | (expression_statement
70 | (number))
71 | (expression_statement
72 | (number))
73 | (expression_statement
74 | (number))
75 | (expression_statement
76 | (number))
77 | (expression_statement
78 | (number))
79 | (expression_statement
80 | (number))
81 | (expression_statement
82 | (number))
83 | (expression_statement
84 | (number))
85 | (expression_statement
86 | (number))
87 | (expression_statement
88 | (number))
89 | (expression_statement
90 | (number))
91 | (expression_statement
92 | (number))
93 | (expression_statement
94 | (number))
95 | (expression_statement
96 | (number))
97 | (expression_statement
98 | (number))
99 | (expression_statement
100 | (number))
101 | (expression_statement
102 | (number))
103 | (expression_statement
104 | (number))
105 | (expression_statement
106 | (number))
107 | (expression_statement
108 | (number))
109 | (expression_statement
110 | (number))
111 | (expression_statement
112 | (number))
113 | (expression_statement
114 | (number))
115 | (expression_statement
116 | (number))
117 | (expression_statement
118 | (number))
119 | (expression_statement
120 | (number))
121 | (expression_statement
122 | (number))
123 | (expression_statement
124 | (number))
125 | (expression_statement
126 | (number))
127 | (expression_statement
128 | (number))
129 | (expression_statement
130 | (number))
131 | (expression_statement
132 | (number))
133 | (expression_statement
134 | (number))
135 | (expression_statement
136 | (number))
137 | (expression_statement
138 | (number))
139 | (expression_statement
140 | (number))
141 | (expression_statement
142 | (number))
143 | (expression_statement
144 | (number))
145 | (expression_statement
146 | (number))
147 | (expression_statement
148 | (number))
149 | (expression_statement
150 | (number))
151 | (expression_statement
152 | (number))
153 | (expression_statement
154 | (number))
155 | (expression_statement
156 | (number))
157 | (expression_statement
158 | (number)))
159 |
160 | ================================================================================
161 | Strings containing comment-like content
162 | ================================================================================
163 |
164 | "//ok\n//what"
165 | "/*ok\n/*what"
166 |
167 | --------------------------------------------------------------------------------
168 |
169 | (source_file
170 | (expression_statement
171 | (string
172 | (string_fragment)
173 | (escape_sequence)
174 | (string_fragment)))
175 | (expression_statement
176 | (string
177 | (string_fragment)
178 | (escape_sequence)
179 | (string_fragment))))
180 |
181 | ================================================================================
182 | Quote escaping
183 | ================================================================================
184 |
185 | ""
186 | "\""
187 | "a\"b"
188 | "it's a tiny tiny world"
189 |
190 | --------------------------------------------------------------------------------
191 |
192 | (source_file
193 | (expression_statement
194 | (string))
195 | (expression_statement
196 | (string
197 | (escape_sequence)))
198 | (expression_statement
199 | (string
200 | (string_fragment)
201 | (escape_sequence)
202 | (string_fragment)))
203 | (expression_statement
204 | (string
205 | (string_fragment))))
206 |
207 | ================================================================================
208 | Template strings
209 | ================================================================================
210 |
211 | ``
212 | ` `
213 | ` \b`
214 | `one line`
215 | `multi
216 | line`
217 |
218 | j`Hello`
219 |
220 | `multi
221 | ${2 + 2}
222 | hello
223 | ${1 + 1}
224 | line`
225 |
226 | `The command \`git ${format(" ")}\` exited with an unexpected code: ${exitCode}.
227 | The caller should either handle this error, or expect that exit code.`
228 |
229 | `//`
230 |
231 | `\\`
232 |
233 | anything`Hello`
234 |
235 |
236 | --------------------------------------------------------------------------------
237 |
238 | (source_file
239 | (expression_statement
240 | (template_string))
241 | (expression_statement
242 | (template_string
243 | (template_string_content)))
244 | (expression_statement
245 | (template_string
246 | (template_string_content
247 | (escape_sequence))))
248 | (expression_statement
249 | (template_string
250 | (template_string_content)))
251 | (expression_statement
252 | (template_string
253 | (template_string_content)))
254 | (expression_statement
255 | (template_string
256 | (template_string_content)))
257 | (expression_statement
258 | (template_string
259 | (template_string_content
260 | (template_substitution
261 | (binary_expression
262 | (number)
263 | (number)))
264 | (template_substitution
265 | (binary_expression
266 | (number)
267 | (number))))))
268 | (expression_statement
269 | (template_string
270 | (template_string_content
271 | (escape_sequence)
272 | (template_substitution
273 | (call_expression
274 | (value_identifier)
275 | (arguments
276 | (string
277 | (string_fragment)))))
278 | (escape_sequence)
279 | (template_substitution
280 | (value_identifier)))))
281 | (expression_statement
282 | (template_string
283 | (template_string_content)))
284 | (expression_statement
285 | (template_string
286 | (template_string_content
287 | (escape_sequence))))
288 | (expression_statement
289 | (template_string
290 | (template_string_content))))
291 |
292 | ================================================================================
293 | Tricky template strings
294 | ================================================================================
295 |
296 | `$`
297 | `$$`
298 | `$$$`
299 | `$-notAsubstitution`
300 | `$NotAsubstitution`
301 |
302 | --------------------------------------------------------------------------------
303 |
304 | (source_file
305 | (expression_statement
306 | (template_string
307 | (template_string_content)))
308 | (expression_statement
309 | (template_string
310 | (template_string_content)))
311 | (expression_statement
312 | (template_string
313 | (template_string_content)))
314 | (expression_statement
315 | (template_string
316 | (template_string_content)))
317 | (expression_statement
318 | (template_string
319 | (template_string_content))))
320 |
321 | ================================================================================
322 | Characters
323 | ================================================================================
324 | 'a'
325 | '\''
326 | '\\'
327 | 'Ж'
328 | '😬'
329 | '\o021'
330 | '\179'
331 | '\u{1F600}'
332 | '@'
333 |
334 | --------------------------------------------------------------------------------
335 |
336 | (source_file
337 | (expression_statement
338 | (character))
339 | (expression_statement
340 | (character
341 | (escape_sequence)))
342 | (expression_statement
343 | (character
344 | (escape_sequence)))
345 | (expression_statement
346 | (character))
347 | (expression_statement
348 | (character))
349 | (expression_statement
350 | (character
351 | (escape_sequence)))
352 | (expression_statement
353 | (character
354 | (escape_sequence)))
355 | (expression_statement
356 | (character
357 | (escape_sequence)))
358 | (expression_statement
359 | (character)))
360 |
361 | ================================================================================
362 | Polyvars
363 | ================================================================================
364 |
365 | #foo
366 | #Bar(7)
367 | #"baz"
368 | #\"qux"
369 | #77
370 |
371 | --------------------------------------------------------------------------------
372 |
373 | (source_file
374 | (expression_statement
375 | (polyvar
376 | (polyvar_identifier)))
377 | (expression_statement
378 | (polyvar
379 | (polyvar_identifier)
380 | (arguments
381 | (number))))
382 | (expression_statement
383 | (polyvar
384 | (polyvar_identifier
385 | (polyvar_string
386 | (string_fragment)))))
387 | (expression_statement
388 | (polyvar
389 | (polyvar_identifier
390 | (polyvar_string
391 | (string_fragment)))))
392 | (expression_statement
393 | (polyvar
394 | (polyvar_identifier))))
395 |
--------------------------------------------------------------------------------
/test/corpus/jsx.txt:
--------------------------------------------------------------------------------
1 | ================================================================================
2 | Simple JSX elements
3 | ================================================================================
4 |
5 |
6 | a b c
7 |
8 | React.null
9 | item.content
10 |
11 | --------------------------------------------------------------------------------
12 |
13 | (source_file
14 | (expression_statement
15 | (jsx_self_closing_element
16 | (jsx_identifier)
17 | (jsx_attribute
18 | (property_identifier)
19 | (string
20 | (string_fragment)))
21 | (jsx_attribute
22 | (property_identifier)
23 | (jsx_expression
24 | (expression_statement
25 | (number))))))
26 | (expression_statement
27 | (jsx_element
28 | (jsx_opening_element
29 | (nested_jsx_identifier
30 | (jsx_identifier)
31 | (jsx_identifier)))
32 | (value_identifier)
33 | (jsx_element
34 | (jsx_opening_element
35 | (jsx_identifier))
36 | (value_identifier)
37 | (jsx_closing_element
38 | (jsx_identifier)))
39 | (value_identifier)
40 | (jsx_closing_element
41 | (nested_jsx_identifier
42 | (jsx_identifier)
43 | (jsx_identifier)))))
44 | (expression_statement
45 | (jsx_element
46 | (jsx_opening_element
47 | (nested_jsx_identifier
48 | (nested_jsx_identifier
49 | (nested_jsx_identifier
50 | (jsx_identifier)
51 | (jsx_identifier))
52 | (jsx_identifier))
53 | (jsx_identifier)))
54 | (jsx_closing_element
55 | (nested_jsx_identifier
56 | (nested_jsx_identifier
57 | (nested_jsx_identifier
58 | (jsx_identifier)
59 | (jsx_identifier))
60 | (jsx_identifier))
61 | (jsx_identifier)))))
62 | (expression_statement
63 | (jsx_element
64 | (jsx_opening_element
65 | (jsx_identifier))
66 | (value_identifier_path
67 | (module_identifier)
68 | (value_identifier))
69 | (jsx_closing_element
70 | (jsx_identifier))))
71 | (expression_statement
72 | (jsx_element
73 | (jsx_opening_element
74 | (jsx_identifier))
75 | (member_expression
76 | (value_identifier)
77 | (property_identifier))
78 | (jsx_closing_element
79 | (jsx_identifier)))))
80 |
81 | ================================================================================
82 | Custom type children
83 | ================================================================================
84 |
85 | "Hello"
86 | 48
87 |
88 | --------------------------------------------------------------------------------
89 |
90 | (source_file
91 | (expression_statement
92 | (jsx_element
93 | (jsx_opening_element
94 | (jsx_identifier))
95 | (string
96 | (string_fragment))
97 | (jsx_closing_element
98 | (jsx_identifier))))
99 | (expression_statement
100 | (jsx_element
101 | (jsx_opening_element
102 | (jsx_identifier))
103 | (number)
104 | (jsx_closing_element
105 | (jsx_identifier)))))
106 |
107 | ================================================================================
108 | Attribute values
109 | ================================================================================
110 | ;
111 | zoo
113 | y=true
114 | />
115 |
116 | --------------------------------------------------------------------------------
117 |
118 | (source_file
119 | (expression_statement
120 | (jsx_self_closing_element
121 | (jsx_identifier)
122 | (jsx_attribute
123 | (property_identifier)
124 | (number))
125 | (jsx_attribute
126 | (property_identifier)
127 | (polyvar
128 | (polyvar_identifier)))
129 | (jsx_attribute
130 | (property_identifier)
131 | (variant
132 | (variant_identifier)))
133 | (jsx_attribute
134 | (property_identifier))
135 | (jsx_attribute
136 | (property_identifier))
137 | (jsx_attribute
138 | (property_identifier)
139 | (jsx_expression
140 | (expression_statement
141 | (value_identifier))))))
142 | (expression_statement
143 | (jsx_self_closing_element
144 | (jsx_identifier)
145 | (jsx_attribute
146 | (property_identifier)
147 | (pipe_expression
148 | (value_identifier)
149 | (value_identifier)))
150 | (jsx_attribute
151 | (property_identifier)
152 | (true)))))
153 |
154 | ================================================================================
155 | Anonymous JSX element
156 | ================================================================================
157 |
158 | <>>
159 | <>>
160 |
161 | --------------------------------------------------------------------------------
162 |
163 | (source_file
164 | (expression_statement
165 | (jsx_fragment))
166 | (expression_statement
167 | (jsx_element
168 | (jsx_opening_element
169 | (jsx_identifier))
170 | (jsx_fragment)
171 | (jsx_closing_element
172 | (jsx_identifier)))))
173 |
174 | ================================================================================
175 | Block children
176 | ================================================================================
177 |
178 |
184 |
185 | --------------------------------------------------------------------------------
186 |
187 | (source_file
188 | (expression_statement
189 | (jsx_element
190 | (jsx_opening_element
191 | (jsx_identifier))
192 | (block
193 | (let_declaration
194 | (let_binding
195 | (value_identifier)
196 | (string
197 | (string_fragment))))
198 | (expression_statement
199 | (jsx_element
200 | (jsx_opening_element
201 | (jsx_identifier)
202 | (jsx_attribute
203 | (property_identifier)))
204 | (block
205 | (expression_statement
206 | (call_expression
207 | (value_identifier_path
208 | (module_identifier)
209 | (value_identifier))
210 | (arguments
211 | (string
212 | (string_fragment))))))
213 | (jsx_closing_element
214 | (jsx_identifier)))))
215 | (jsx_closing_element
216 | (jsx_identifier)))))
217 |
218 | ================================================================================
219 | Children spread
220 | ================================================================================
221 |
222 | ...myChild
223 |
224 | --------------------------------------------------------------------------------
225 |
226 | (source_file
227 | (expression_statement
228 | (jsx_element
229 | (jsx_opening_element
230 | (jsx_identifier))
231 | (spread_element
232 | (value_identifier))
233 | (jsx_closing_element
234 | (jsx_identifier)))))
235 |
236 | ================================================================================
237 | Attribute Block
238 | ================================================================================
239 |
240 |
249 |
250 |
251 |
252 | --------------------------------------------------------------------------------
253 |
254 | (source_file
255 | (expression_statement
256 | (jsx_element
257 | (jsx_opening_element
258 | (jsx_identifier)
259 | (jsx_attribute
260 | (property_identifier)
261 | (jsx_expression
262 | (expression_statement
263 | (call_expression
264 | (value_identifier_path
265 | (module_identifier)
266 | (value_identifier))
267 | (arguments
268 | (string
269 | (string_fragment)))))))
270 | (jsx_attribute
271 | (property_identifier)
272 | (jsx_expression
273 | (open_statement
274 | (module_identifier))
275 | (expression_statement
276 | (record
277 | (record_field
278 | (property_identifier)
279 | (value_identifier))
280 | (record_field
281 | (property_identifier)
282 | (false)))))))
283 | (jsx_self_closing_element
284 | (jsx_identifier))
285 | (jsx_closing_element
286 | (jsx_identifier)))))
287 |
288 | ================================================================================
289 | Spread props
290 | ================================================================================
291 |
292 |
293 |
294 |
295 | --------------------------------------------------------------------------------
296 |
297 | (source_file
298 | (expression_statement
299 | (jsx_self_closing_element
300 | (jsx_identifier)
301 | (jsx_expression
302 | (spread_element
303 | (value_identifier)))))
304 | (expression_statement
305 | (jsx_element
306 | (jsx_opening_element
307 | (jsx_identifier)
308 | (jsx_expression
309 | (spread_element
310 | (value_identifier))))
311 | (jsx_closing_element
312 | (jsx_identifier)))))
313 |
314 | ================================================================================
315 | Elements in pipes
316 | ================================================================================
317 |
318 | ->Some
319 |
320 | --------------------------------------------------------------------------------
321 |
322 | (source_file
323 | (expression_statement
324 | (pipe_expression
325 | (jsx_self_closing_element
326 | (jsx_identifier))
327 | (variant
328 | (variant_identifier)))))
329 |
330 |
--------------------------------------------------------------------------------
/src/tree_sitter/array.h:
--------------------------------------------------------------------------------
1 | #ifndef TREE_SITTER_ARRAY_H_
2 | #define TREE_SITTER_ARRAY_H_
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | #include "./alloc.h"
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #ifdef _MSC_VER
17 | #pragma warning(push)
18 | #pragma warning(disable : 4101)
19 | #elif defined(__GNUC__) || defined(__clang__)
20 | #pragma GCC diagnostic push
21 | #pragma GCC diagnostic ignored "-Wunused-variable"
22 | #endif
23 |
24 | #define Array(T) \
25 | struct { \
26 | T *contents; \
27 | uint32_t size; \
28 | uint32_t capacity; \
29 | }
30 |
31 | /// Initialize an array.
32 | #define array_init(self) \
33 | ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)
34 |
35 | /// Create an empty array.
36 | #define array_new() \
37 | { NULL, 0, 0 }
38 |
39 | /// Get a pointer to the element at a given `index` in the array.
40 | #define array_get(self, _index) \
41 | (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index])
42 |
43 | /// Get a pointer to the first element in the array.
44 | #define array_front(self) array_get(self, 0)
45 |
46 | /// Get a pointer to the last element in the array.
47 | #define array_back(self) array_get(self, (self)->size - 1)
48 |
49 | /// Clear the array, setting its size to zero. Note that this does not free any
50 | /// memory allocated for the array's contents.
51 | #define array_clear(self) ((self)->size = 0)
52 |
53 | /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
54 | /// less than the array's current capacity, this function has no effect.
55 | #define array_reserve(self, new_capacity) \
56 | _array__reserve((Array *)(self), array_elem_size(self), new_capacity)
57 |
58 | /// Free any memory allocated for this array. Note that this does not free any
59 | /// memory allocated for the array's contents.
60 | #define array_delete(self) _array__delete((Array *)(self))
61 |
62 | /// Push a new `element` onto the end of the array.
63 | #define array_push(self, element) \
64 | (_array__grow((Array *)(self), 1, array_elem_size(self)), \
65 | (self)->contents[(self)->size++] = (element))
66 |
67 | /// Increase the array's size by `count` elements.
68 | /// New elements are zero-initialized.
69 | #define array_grow_by(self, count) \
70 | do { \
71 | if ((count) == 0) break; \
72 | _array__grow((Array *)(self), count, array_elem_size(self)); \
73 | memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
74 | (self)->size += (count); \
75 | } while (0)
76 |
77 | /// Append all elements from one array to the end of another.
78 | #define array_push_all(self, other) \
79 | array_extend((self), (other)->size, (other)->contents)
80 |
81 | /// Append `count` elements to the end of the array, reading their values from the
82 | /// `contents` pointer.
83 | #define array_extend(self, count, contents) \
84 | _array__splice( \
85 | (Array *)(self), array_elem_size(self), (self)->size, \
86 | 0, count, contents \
87 | )
88 |
89 | /// Remove `old_count` elements from the array starting at the given `index`. At
90 | /// the same index, insert `new_count` new elements, reading their values from the
91 | /// `new_contents` pointer.
92 | #define array_splice(self, _index, old_count, new_count, new_contents) \
93 | _array__splice( \
94 | (Array *)(self), array_elem_size(self), _index, \
95 | old_count, new_count, new_contents \
96 | )
97 |
98 | /// Insert one `element` into the array at the given `index`.
99 | #define array_insert(self, _index, element) \
100 | _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))
101 |
102 | /// Remove one element from the array at the given `index`.
103 | #define array_erase(self, _index) \
104 | _array__erase((Array *)(self), array_elem_size(self), _index)
105 |
106 | /// Pop the last element off the array, returning the element by value.
107 | #define array_pop(self) ((self)->contents[--(self)->size])
108 |
109 | /// Assign the contents of one array to another, reallocating if necessary.
110 | #define array_assign(self, other) \
111 | _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self))
112 |
113 | /// Swap one array with another
114 | #define array_swap(self, other) \
115 | _array__swap((Array *)(self), (Array *)(other))
116 |
117 | /// Get the size of the array contents
118 | #define array_elem_size(self) (sizeof *(self)->contents)
119 |
120 | /// Search a sorted array for a given `needle` value, using the given `compare`
121 | /// callback to determine the order.
122 | ///
123 | /// If an existing element is found to be equal to `needle`, then the `index`
124 | /// out-parameter is set to the existing value's index, and the `exists`
125 | /// out-parameter is set to true. Otherwise, `index` is set to an index where
126 | /// `needle` should be inserted in order to preserve the sorting, and `exists`
127 | /// is set to false.
128 | #define array_search_sorted_with(self, compare, needle, _index, _exists) \
129 | _array__search_sorted(self, 0, compare, , needle, _index, _exists)
130 |
131 | /// Search a sorted array for a given `needle` value, using integer comparisons
132 | /// of a given struct field (specified with a leading dot) to determine the order.
133 | ///
134 | /// See also `array_search_sorted_with`.
135 | #define array_search_sorted_by(self, field, needle, _index, _exists) \
136 | _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists)
137 |
138 | /// Insert a given `value` into a sorted array, using the given `compare`
139 | /// callback to determine the order.
140 | #define array_insert_sorted_with(self, compare, value) \
141 | do { \
142 | unsigned _index, _exists; \
143 | array_search_sorted_with(self, compare, &(value), &_index, &_exists); \
144 | if (!_exists) array_insert(self, _index, value); \
145 | } while (0)
146 |
147 | /// Insert a given `value` into a sorted array, using integer comparisons of
148 | /// a given struct field (specified with a leading dot) to determine the order.
149 | ///
150 | /// See also `array_search_sorted_by`.
151 | #define array_insert_sorted_by(self, field, value) \
152 | do { \
153 | unsigned _index, _exists; \
154 | array_search_sorted_by(self, field, (value) field, &_index, &_exists); \
155 | if (!_exists) array_insert(self, _index, value); \
156 | } while (0)
157 |
158 | // Private
159 |
160 | typedef Array(void) Array;
161 |
162 | /// This is not what you're looking for, see `array_delete`.
163 | static inline void _array__delete(Array *self) {
164 | if (self->contents) {
165 | ts_free(self->contents);
166 | self->contents = NULL;
167 | self->size = 0;
168 | self->capacity = 0;
169 | }
170 | }
171 |
172 | /// This is not what you're looking for, see `array_erase`.
173 | static inline void _array__erase(Array *self, size_t element_size,
174 | uint32_t index) {
175 | assert(index < self->size);
176 | char *contents = (char *)self->contents;
177 | memmove(contents + index * element_size, contents + (index + 1) * element_size,
178 | (self->size - index - 1) * element_size);
179 | self->size--;
180 | }
181 |
182 | /// This is not what you're looking for, see `array_reserve`.
183 | static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) {
184 | if (new_capacity > self->capacity) {
185 | if (self->contents) {
186 | self->contents = ts_realloc(self->contents, new_capacity * element_size);
187 | } else {
188 | self->contents = ts_malloc(new_capacity * element_size);
189 | }
190 | self->capacity = new_capacity;
191 | }
192 | }
193 |
194 | /// This is not what you're looking for, see `array_assign`.
195 | static inline void _array__assign(Array *self, const Array *other, size_t element_size) {
196 | _array__reserve(self, element_size, other->size);
197 | self->size = other->size;
198 | memcpy(self->contents, other->contents, self->size * element_size);
199 | }
200 |
201 | /// This is not what you're looking for, see `array_swap`.
202 | static inline void _array__swap(Array *self, Array *other) {
203 | Array swap = *other;
204 | *other = *self;
205 | *self = swap;
206 | }
207 |
208 | /// This is not what you're looking for, see `array_push` or `array_grow_by`.
209 | static inline void _array__grow(Array *self, uint32_t count, size_t element_size) {
210 | uint32_t new_size = self->size + count;
211 | if (new_size > self->capacity) {
212 | uint32_t new_capacity = self->capacity * 2;
213 | if (new_capacity < 8) new_capacity = 8;
214 | if (new_capacity < new_size) new_capacity = new_size;
215 | _array__reserve(self, element_size, new_capacity);
216 | }
217 | }
218 |
219 | /// This is not what you're looking for, see `array_splice`.
220 | static inline void _array__splice(Array *self, size_t element_size,
221 | uint32_t index, uint32_t old_count,
222 | uint32_t new_count, const void *elements) {
223 | uint32_t new_size = self->size + new_count - old_count;
224 | uint32_t old_end = index + old_count;
225 | uint32_t new_end = index + new_count;
226 | assert(old_end <= self->size);
227 |
228 | _array__reserve(self, element_size, new_size);
229 |
230 | char *contents = (char *)self->contents;
231 | if (self->size > old_end) {
232 | memmove(
233 | contents + new_end * element_size,
234 | contents + old_end * element_size,
235 | (self->size - old_end) * element_size
236 | );
237 | }
238 | if (new_count > 0) {
239 | if (elements) {
240 | memcpy(
241 | (contents + index * element_size),
242 | elements,
243 | new_count * element_size
244 | );
245 | } else {
246 | memset(
247 | (contents + index * element_size),
248 | 0,
249 | new_count * element_size
250 | );
251 | }
252 | }
253 | self->size += new_count - old_count;
254 | }
255 |
256 | /// A binary search routine, based on Rust's `std::slice::binary_search_by`.
257 | /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`.
258 | #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \
259 | do { \
260 | *(_index) = start; \
261 | *(_exists) = false; \
262 | uint32_t size = (self)->size - *(_index); \
263 | if (size == 0) break; \
264 | int comparison; \
265 | while (size > 1) { \
266 | uint32_t half_size = size / 2; \
267 | uint32_t mid_index = *(_index) + half_size; \
268 | comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \
269 | if (comparison <= 0) *(_index) = mid_index; \
270 | size -= half_size; \
271 | } \
272 | comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \
273 | if (comparison == 0) *(_exists) = true; \
274 | else if (comparison < 0) *(_index) += 1; \
275 | } while (0)
276 |
277 | /// Helper macro for the `_sorted_by` routines below. This takes the left (existing)
278 | /// parameter by reference in order to work with the generic sorting function above.
279 | #define _compare_int(a, b) ((int)*(a) - (int)(b))
280 |
281 | #ifdef _MSC_VER
282 | #pragma warning(pop)
283 | #elif defined(__GNUC__) || defined(__clang__)
284 | #pragma GCC diagnostic pop
285 | #endif
286 |
287 | #ifdef __cplusplus
288 | }
289 | #endif
290 |
291 | #endif // TREE_SITTER_ARRAY_H_
292 |
--------------------------------------------------------------------------------
/src/scanner.c:
--------------------------------------------------------------------------------
1 | #include "tree_sitter/parser.h"
2 | #include
3 | #include
4 |
5 | enum TokenType {
6 | NEWLINE,
7 | COMMENT,
8 | NEWLINE_AND_COMMENT,
9 | QUOTE,
10 | BACKTICK,
11 | TEMPLATE_CHARS,
12 | L_PAREN,
13 | R_PAREN,
14 | LIST_CONSTRUCTOR,
15 | DECORATOR,
16 | DECORATOR_INLINE,
17 | };
18 |
19 | typedef struct ScannerState {
20 | int parens_nesting;
21 | bool in_quotes;
22 | bool in_backticks;
23 | bool eof_reported;
24 | } ScannerState;
25 |
26 | void *tree_sitter_rescript_external_scanner_create() {
27 | void* state = malloc(sizeof(ScannerState));
28 | memset(state, 0, sizeof(ScannerState));
29 | return state;
30 | }
31 |
32 | void tree_sitter_rescript_external_scanner_destroy(void* state) {
33 | free(state);
34 | }
35 |
36 | void tree_sitter_rescript_external_scanner_reset(void* state) {
37 | memset(state, 0, sizeof(ScannerState));
38 | }
39 |
40 | unsigned tree_sitter_rescript_external_scanner_serialize(void* state, char *buffer) {
41 | memcpy(buffer, state, sizeof(ScannerState));
42 | return sizeof(ScannerState);
43 | }
44 |
45 | void tree_sitter_rescript_external_scanner_deserialize(void* state, const char *buffer, unsigned n_bytes) {
46 | memcpy(state, buffer, n_bytes);
47 | }
48 |
49 | static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
50 | static void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
51 |
52 | static bool is_inline_whitespace(int32_t c) {
53 | return c == ' ' || c == '\t';
54 | }
55 |
56 | static bool is_identifier_start(char c) {
57 | return c == '_' || (c >= 'a' && c <= 'z');
58 | }
59 |
60 | static bool is_decorator_start(char c) {
61 | return c == '_' || c == '\\' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
62 | }
63 |
64 | static bool is_decorator_identifier(char c) {
65 | return c == '_' || c == '.' || c == '\'' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
66 | }
67 |
68 | static bool is_whitespace(char c) {
69 | return c == ' ' || c == '\t' || c == '\n' || c == '\r';
70 | }
71 |
72 | static void scan_whitespace(TSLexer *lexer, bool skip) {
73 | while (iswspace(lexer->lookahead) && !lexer->eof(lexer)) {
74 | lexer->advance(lexer, skip);
75 | }
76 | }
77 |
78 | static void scan_multiline_comment(TSLexer *lexer) {
79 | int level = 1;
80 | advance(lexer);
81 | while (level > 0 && !lexer->eof(lexer)) {
82 | switch (lexer->lookahead) {
83 | case '/':
84 | advance(lexer);
85 | if (lexer->lookahead == '*')
86 | ++level;
87 | else
88 | continue;
89 |
90 | break;
91 |
92 | case '*':
93 | advance(lexer);
94 | if (lexer->lookahead == '/')
95 | --level;
96 | else
97 | continue;
98 |
99 | break;
100 | }
101 |
102 | advance(lexer);
103 | }
104 | }
105 |
106 | static bool scan_comment(TSLexer *lexer) {
107 | if (lexer->lookahead != '/')
108 | return false;
109 |
110 | advance(lexer);
111 | switch (lexer->lookahead) {
112 | case '/':
113 | // Single-line comment
114 | do {
115 | advance(lexer);
116 | } while (lexer->lookahead != '\n' && !lexer->eof(lexer));
117 | return true;
118 |
119 | case '*':
120 | // Multi-line comment
121 | scan_multiline_comment(lexer);
122 | return true;
123 |
124 | default:
125 | // Division, etc
126 | return false;
127 | }
128 | }
129 |
130 | static bool scan_whitespace_and_comments(TSLexer *lexer) {
131 | bool has_comments = false;
132 | while (!lexer->eof(lexer)) {
133 | // Once a comment is found, the subsequent whitespace should not be marked
134 | // as skipped to keep the correct range of the comment node if it will be
135 | // marked so.
136 | bool skip_whitespace = !has_comments;
137 | scan_whitespace(lexer, skip_whitespace);
138 | if (scan_comment(lexer)) {
139 | has_comments = true;
140 | } else {
141 | break;
142 | }
143 | }
144 |
145 | return has_comments;
146 | }
147 |
148 | bool tree_sitter_rescript_external_scanner_scan(
149 | void* payload,
150 | TSLexer* lexer,
151 | const bool* valid_symbols
152 | ) {
153 | ScannerState* state = (ScannerState*)payload;
154 | bool in_string = state->in_quotes || state->in_backticks;
155 |
156 | while (is_inline_whitespace(lexer->lookahead) && !in_string) {
157 | skip(lexer);
158 | }
159 |
160 | if (valid_symbols[TEMPLATE_CHARS]) {
161 | lexer->result_symbol = TEMPLATE_CHARS;
162 | for (bool has_content = false;; has_content = true) {
163 | lexer->mark_end(lexer);
164 | switch (lexer->lookahead) {
165 | case '`':
166 | state->in_backticks = false;
167 | return has_content;
168 | case '\0':
169 | return false;
170 | case '$':
171 | advance(lexer);
172 | if (lexer->lookahead == '{' || is_identifier_start(lexer->lookahead)) {
173 | return has_content;
174 | }
175 | break;
176 | case '\\':
177 | return has_content;
178 | default:
179 | advance(lexer);
180 | }
181 | }
182 |
183 | return true;
184 | }
185 |
186 | // If a source file missing EOL at EOF, give the last statement a chance:
187 | // report the statement delimiting EOL at the very end of file. Make sure
188 | // it’s done only once, otherwise the scanner will enter dead-lock because
189 | // we report NEWLINE again and again, no matter the lexer is exhausted
190 | // already.
191 | if (valid_symbols[NEWLINE] && lexer->eof(lexer) && !state->eof_reported) {
192 | lexer->result_symbol = NEWLINE;
193 | state->eof_reported = true;
194 | return true;
195 | }
196 |
197 | // Magic ahead!
198 | // We have two types of newline in ReScript. The one which ends the current statement,
199 | // and the one used just for pretty-formatting (e.g. separates variant type values).
200 | // We report only the first one. The second one should be ignored and skipped as
201 | // whitespace.
202 | // What makes things worse is that we can have comments interleaved in statements.
203 | // Tree-sitter gives just one chance to say what type of a token we’re on. We can’t
204 | // say: “I see a significant newline, then I see a comment”. To deal with it, an
205 | // artificial token NEWLINE_AND_COMMENT was introduced. It has the same semantics for
206 | // the AST as simple newline and the same highlighting as a usual comment.
207 | if (valid_symbols[NEWLINE] && lexer->lookahead == '\n') {
208 | bool is_unnested = state->parens_nesting == 0;
209 | lexer->result_symbol = NEWLINE;
210 | lexer->advance(lexer, true);
211 | lexer->mark_end(lexer);
212 |
213 | bool has_comment = scan_whitespace_and_comments(lexer);
214 | if (has_comment && valid_symbols[NEWLINE_AND_COMMENT]) {
215 | lexer->result_symbol = NEWLINE_AND_COMMENT;
216 | lexer->mark_end(lexer);
217 | }
218 |
219 | bool in_multiline_statement = false;
220 | if (lexer->lookahead == '-') {
221 | advance(lexer);
222 | if (lexer->lookahead == '>') {
223 | // Ignore new lines before pipe operator (->)
224 | in_multiline_statement = true;
225 | }
226 | } else if (lexer->lookahead == '|') {
227 | // Ignore new lines before variant declarations and switch matches
228 | in_multiline_statement = true;
229 | } else if (lexer->lookahead == '?' || lexer->lookahead == ':') {
230 | // Ignore new lines before potential ternaries
231 | in_multiline_statement = true;
232 | } else if (lexer->lookahead == '}') {
233 | // Do not report new lines right before block/switch closings to avoid
234 | // parser confustion between a terminated and unterminated statements
235 | // for rules like seq(repeat($._statement), $.statement)
236 | in_multiline_statement = true;
237 | } else if (lexer->lookahead == 'a') {
238 | advance(lexer);
239 | if (lexer->lookahead == 'n') {
240 | advance(lexer);
241 | if (lexer->lookahead == 'd') {
242 | // Ignore new lines before `and` keyword (recursive definition)
243 | in_multiline_statement = true;
244 | }
245 | }
246 | }
247 |
248 | if (in_multiline_statement) {
249 | if (has_comment && valid_symbols[COMMENT]) {
250 | lexer->result_symbol = COMMENT;
251 | return true;
252 | }
253 | } else {
254 | return true;
255 | }
256 | }
257 |
258 | if (!in_string) {
259 | scan_whitespace(lexer, true);
260 | }
261 |
262 | if (valid_symbols[COMMENT] && lexer->lookahead == '/' && !in_string) {
263 | lexer->result_symbol = COMMENT;
264 | if (scan_comment(lexer)) {
265 | lexer->mark_end(lexer);
266 | return true;
267 | } else {
268 | return false;
269 | }
270 | }
271 |
272 | if (valid_symbols[QUOTE] && lexer->lookahead == '"') {
273 | state->in_quotes = !state->in_quotes;
274 | lexer->result_symbol = QUOTE;
275 | lexer->advance(lexer, false);
276 | lexer->mark_end(lexer);
277 | return true;
278 | }
279 |
280 | if (valid_symbols[BACKTICK] && lexer->lookahead == '`') {
281 | state->in_backticks = !state->in_backticks;
282 | lexer->result_symbol = BACKTICK;
283 | lexer->advance(lexer, false);
284 | lexer->mark_end(lexer);
285 | return true;
286 | }
287 |
288 | if (valid_symbols[L_PAREN] && lexer->lookahead == '(') {
289 | ++state->parens_nesting;
290 | lexer->result_symbol = L_PAREN;
291 | lexer->advance(lexer, false);
292 | lexer->mark_end(lexer);
293 | return true;
294 | }
295 |
296 | if (valid_symbols[R_PAREN] && lexer->lookahead == ')') {
297 | --state->parens_nesting;
298 | lexer->result_symbol = R_PAREN;
299 | lexer->advance(lexer, false);
300 | lexer->mark_end(lexer);
301 | return true;
302 | }
303 |
304 | if (valid_symbols[LIST_CONSTRUCTOR]) {
305 | lexer->result_symbol = LIST_CONSTRUCTOR;
306 | if (lexer->lookahead == 'l') {
307 | advance(lexer);
308 | if (lexer->lookahead == 'i') {
309 | advance(lexer);
310 | if (lexer->lookahead == 's') {
311 | advance(lexer);
312 | if (lexer->lookahead == 't') {
313 | advance(lexer);
314 | if (lexer->lookahead == '{') {
315 | lexer->mark_end(lexer);
316 | return true;
317 | }
318 | }
319 | }
320 | }
321 | }
322 | }
323 |
324 | if (valid_symbols[DECORATOR] && valid_symbols[DECORATOR_INLINE] && lexer->lookahead == '@') {
325 | advance(lexer);
326 | if (lexer->lookahead == '@') {
327 | advance(lexer);
328 | }
329 |
330 | if (is_decorator_start(lexer->lookahead)) {
331 | advance(lexer);
332 |
333 | if (lexer->lookahead == '"') {
334 | advance(lexer);
335 | while (lexer->lookahead != '"') {
336 | advance(lexer);
337 | if (lexer->eof(lexer)) {
338 | return false;
339 | }
340 | }
341 | advance(lexer);
342 | if (is_whitespace(lexer->lookahead)) {
343 | lexer->result_symbol = DECORATOR_INLINE;
344 | lexer->mark_end(lexer);
345 | return true;
346 | }
347 | if (lexer -> lookahead == '(') {
348 | lexer->result_symbol = DECORATOR;
349 | lexer->mark_end(lexer);
350 | return true;
351 | }
352 | return false;
353 | }
354 |
355 | while (is_decorator_identifier(lexer->lookahead)) {
356 | advance(lexer);
357 | if (lexer->eof(lexer)) {
358 | return false;
359 | }
360 | }
361 |
362 | if (is_whitespace(lexer->lookahead)) {
363 | lexer->result_symbol = DECORATOR_INLINE;
364 | lexer->mark_end(lexer);
365 | return true;
366 | }
367 |
368 | if (lexer->lookahead == '(') {
369 | lexer->result_symbol = DECORATOR;
370 | lexer->mark_end(lexer);
371 | return true;
372 | }
373 | }
374 | return false;
375 | }
376 |
377 | lexer->advance(lexer, iswspace(lexer->lookahead));
378 | return false;
379 | }
380 |
381 | // vim:sw=2
382 |
--------------------------------------------------------------------------------
/test/corpus/let_bindings.txt:
--------------------------------------------------------------------------------
1 | ================================================================================
2 | Plain
3 | ================================================================================
4 |
5 | let a = 5
6 | let b = a
7 | let c = #foo
8 | let list = 1
9 | let a = list
10 | let async = 1
11 | let unpack = 2
12 | export d = 5
13 |
14 | --------------------------------------------------------------------------------
15 |
16 | (source_file
17 | (let_declaration
18 | (let_binding
19 | (value_identifier)
20 | (number)))
21 | (let_declaration
22 | (let_binding
23 | (value_identifier)
24 | (value_identifier)))
25 | (let_declaration
26 | (let_binding
27 | (value_identifier)
28 | (polyvar
29 | (polyvar_identifier))))
30 | (let_declaration
31 | (let_binding
32 | (value_identifier)
33 | (number)))
34 | (let_declaration
35 | (let_binding
36 | (value_identifier)
37 | (value_identifier)))
38 | (let_declaration
39 | (let_binding
40 | (value_identifier)
41 | (number)))
42 | (let_declaration
43 | (let_binding
44 | (value_identifier)
45 | (number)))
46 | (let_declaration
47 | (let_binding
48 | (value_identifier)
49 | (number))))
50 |
51 | ================================================================================
52 | Tuple destructuring
53 | ================================================================================
54 |
55 | let (a, b, (c, d)) = foo
56 | let (state: int, setState) = foo
57 | let (a, b, ()) = foo
58 |
59 | --------------------------------------------------------------------------------
60 |
61 | (source_file
62 | (let_declaration
63 | (let_binding
64 | (tuple_pattern
65 | (tuple_item_pattern
66 | (value_identifier))
67 | (tuple_item_pattern
68 | (value_identifier))
69 | (tuple_item_pattern
70 | (tuple_pattern
71 | (tuple_item_pattern
72 | (value_identifier))
73 | (tuple_item_pattern
74 | (value_identifier)))))
75 | (value_identifier)))
76 | (let_declaration
77 | (let_binding
78 | (tuple_pattern
79 | (tuple_item_pattern
80 | (value_identifier)
81 | (type_annotation
82 | (type_identifier)))
83 | (tuple_item_pattern
84 | (value_identifier)))
85 | (value_identifier)))
86 | (let_declaration
87 | (let_binding
88 | (tuple_pattern
89 | (tuple_item_pattern
90 | (value_identifier))
91 | (tuple_item_pattern
92 | (value_identifier))
93 | (tuple_item_pattern
94 | (unit)))
95 | (value_identifier))))
96 |
97 | ================================================================================
98 | Record destructuring
99 | ================================================================================
100 |
101 | let {bar, baz} = foo
102 | let {bar, baz: qux} = foo
103 | let {Bar.Bar.bar: bar} = foo
104 | let {?Bar.bar} = foo
105 | let {?bar} = foo
106 |
107 | --------------------------------------------------------------------------------
108 |
109 | (source_file
110 | (let_declaration
111 | (let_binding
112 | (record_pattern
113 | (value_identifier)
114 | (value_identifier))
115 | (value_identifier)))
116 | (let_declaration
117 | (let_binding
118 | (record_pattern
119 | (value_identifier)
120 | (value_identifier)
121 | (value_identifier))
122 | (value_identifier)))
123 | (let_declaration
124 | (let_binding
125 | (record_pattern
126 | (value_identifier_path
127 | (module_identifier_path
128 | (module_identifier)
129 | (module_identifier))
130 | (value_identifier))
131 | (value_identifier))
132 | (value_identifier)))
133 | (let_declaration
134 | (let_binding
135 | (record_pattern
136 | (value_identifier_path
137 | (module_identifier)
138 | (value_identifier)))
139 | (value_identifier)))
140 | (let_declaration
141 | (let_binding
142 | (record_pattern
143 | (value_identifier))
144 | (value_identifier))))
145 |
146 | ================================================================================
147 | Array destructuring
148 | ================================================================================
149 |
150 | let [bar, baz] = foo
151 | let [bar, baz, _] = foo
152 |
153 | --------------------------------------------------------------------------------
154 |
155 | (source_file
156 | (let_declaration
157 | (let_binding
158 | (array_pattern
159 | (value_identifier)
160 | (value_identifier))
161 | (value_identifier)))
162 | (let_declaration
163 | (let_binding
164 | (array_pattern
165 | (value_identifier)
166 | (value_identifier)
167 | (value_identifier))
168 | (value_identifier))))
169 |
170 | ================================================================================
171 | List destructuring
172 | ================================================================================
173 |
174 | let list{head, ...tail} = foo
175 |
176 | --------------------------------------------------------------------------------
177 |
178 | (source_file
179 | (let_declaration
180 | (let_binding
181 | (list_pattern
182 | (value_identifier)
183 | (spread_pattern
184 | (value_identifier)))
185 | (value_identifier))))
186 |
187 | ================================================================================
188 | Block
189 | ================================================================================
190 |
191 | let x = {
192 | 3
193 | 4
194 | }
195 |
196 | --------------------------------------------------------------------------------
197 |
198 | (source_file
199 | (let_declaration
200 | (let_binding
201 | (value_identifier)
202 | (block
203 | (expression_statement
204 | (number))
205 | (expression_statement
206 | (number))))))
207 |
208 | ================================================================================
209 | Annotated
210 | ================================================================================
211 |
212 | let a: int = 5
213 | let b: 'a => unit = ignore
214 |
215 | --------------------------------------------------------------------------------
216 |
217 | (source_file
218 | (let_declaration
219 | (let_binding
220 | (value_identifier)
221 | (type_annotation
222 | (type_identifier))
223 | (number)))
224 | (let_declaration
225 | (let_binding
226 | (value_identifier)
227 | (type_annotation
228 | (function_type
229 | (function_type_parameters
230 | (type_identifier))
231 | (unit_type)))
232 | (value_identifier))))
233 |
234 | ================================================================================
235 | Recursive
236 | ================================================================================
237 |
238 | let rec foo = n => foo(n-1)
239 |
240 | --------------------------------------------------------------------------------
241 |
242 | (source_file
243 | (let_declaration
244 | (let_binding
245 | (value_identifier)
246 | (function
247 | (value_identifier)
248 | (call_expression
249 | (value_identifier)
250 | (arguments
251 | (binary_expression
252 | (value_identifier)
253 | (number))))))))
254 |
255 | ================================================================================
256 | Unit
257 | ================================================================================
258 |
259 | let () = noop
260 |
261 | --------------------------------------------------------------------------------
262 |
263 | (source_file
264 | (let_declaration
265 | (let_binding
266 | (unit)
267 | (value_identifier))))
268 |
269 | ================================================================================
270 | And (Primitives)
271 | ================================================================================
272 |
273 | let a = 5 and b = 4
274 |
275 | --------------------------------------------------------------------------------
276 |
277 | (source_file
278 | (let_declaration
279 | (let_binding
280 | (value_identifier)
281 | (number))
282 | (let_binding
283 | (value_identifier)
284 | (number))))
285 |
286 | ================================================================================
287 | And (Functions)
288 | ================================================================================
289 |
290 | let rec a = x => x + b(x) and b = y => y - 1
291 |
292 | --------------------------------------------------------------------------------
293 |
294 | (source_file
295 | (let_declaration
296 | (let_binding
297 | (value_identifier)
298 | (function
299 | (value_identifier)
300 | (binary_expression
301 | (value_identifier)
302 | (call_expression
303 | (value_identifier)
304 | (arguments
305 | (value_identifier))))))
306 | (let_binding
307 | (value_identifier)
308 | (function
309 | (value_identifier)
310 | (binary_expression
311 | (value_identifier)
312 | (number))))))
313 |
314 | ================================================================================
315 | Labled function with uncurried
316 | ================================================================================
317 |
318 | let test = (. ~attr) => ()
319 |
320 | --------------------------------------------------------------------------------
321 |
322 | (source_file
323 | (let_declaration
324 | (let_binding
325 | (value_identifier)
326 | (function
327 | (formal_parameters
328 | (parameter
329 | (uncurry)
330 | (labeled_parameter
331 | (value_identifier))))
332 | (unit)))))
333 |
334 | ================================================================================
335 | Destructuring module
336 | ================================================================================
337 |
338 |
339 | let {foo, bar} = module(User)
340 | let {baz, _} = module(User.Inner)
341 |
342 | --------------------------------------------------------------------------------
343 |
344 | (source_file
345 | (let_declaration
346 | (let_binding
347 | (record_pattern
348 | (value_identifier)
349 | (value_identifier))
350 | (module_pack
351 | (module_identifier))))
352 | (let_declaration
353 | (let_binding
354 | (record_pattern
355 | (value_identifier)
356 | (value_identifier))
357 | (module_pack
358 | (module_identifier_path
359 | (module_identifier)
360 | (module_identifier))))))
361 |
362 | ================================================================================
363 | Packing module
364 | ================================================================================
365 |
366 | let foo = module(Bar)
367 |
368 | --------------------------------------------------------------------------------
369 |
370 | (source_file
371 | (let_declaration
372 | (let_binding
373 | (value_identifier)
374 | (module_pack
375 | (module_identifier)))))
376 |
377 | ================================================================================
378 | Unpacking module
379 | ================================================================================
380 |
381 | let module(Bar) = foo
382 |
383 | --------------------------------------------------------------------------------
384 |
385 | (source_file
386 | (let_declaration
387 | (let_binding
388 | (module_pack
389 | (module_identifier))
390 | (value_identifier))))
391 |
392 | ================================================================================
393 | Lazy Values
394 | ================================================================================
395 |
396 | let lazy x = lazy(1)
397 |
398 | --------------------------------------------------------------------------------
399 |
400 | (source_file
401 | (let_declaration
402 | (let_binding
403 | (lazy_pattern
404 | (value_identifier))
405 | (lazy_expression
406 | (parenthesized_expression
407 | (number))))))
408 |
--------------------------------------------------------------------------------
/test/corpus/type_declarations.txt:
--------------------------------------------------------------------------------
1 | ================================================================================
2 | Opaque
3 | ================================================================================
4 |
5 | type t
6 | type t'
7 | type \"type"
8 | type t and b
9 |
10 | --------------------------------------------------------------------------------
11 |
12 | (source_file
13 | (type_declaration
14 | (type_binding
15 | (type_identifier)))
16 | (type_declaration
17 | (type_binding
18 | (type_identifier)))
19 | (type_declaration
20 | (type_binding
21 | (type_identifier)))
22 | (type_declaration
23 | (type_binding
24 | (type_identifier))
25 | (type_binding
26 | (type_identifier))))
27 |
28 | ================================================================================
29 | Export
30 | ================================================================================
31 |
32 | export type t
33 |
34 | --------------------------------------------------------------------------------
35 |
36 | (source_file
37 | (type_declaration
38 | (type_binding
39 | (type_identifier))))
40 |
41 | ================================================================================
42 | Alias
43 | ================================================================================
44 |
45 | type t = Foo.Bar.qux
46 |
47 | --------------------------------------------------------------------------------
48 |
49 | (source_file
50 | (type_declaration
51 | (type_binding
52 | (type_identifier)
53 | (type_identifier_path
54 | (module_identifier_path
55 | (module_identifier)
56 | (module_identifier))
57 | (type_identifier)))))
58 |
59 | ================================================================================
60 | Private
61 | ================================================================================
62 |
63 | type t = private string
64 |
65 | --------------------------------------------------------------------------------
66 |
67 | (source_file
68 | (type_declaration
69 | (type_binding
70 | (type_identifier)
71 | (type_identifier))))
72 |
73 | ================================================================================
74 | Tuple type
75 | ================================================================================
76 |
77 | type t = (int, string, float)
78 |
79 | --------------------------------------------------------------------------------
80 |
81 | (source_file
82 | (type_declaration
83 | (type_binding
84 | (type_identifier)
85 | (tuple_type
86 | (type_identifier)
87 | (type_identifier)
88 | (type_identifier)))))
89 |
90 | ================================================================================
91 | Record type
92 | ================================================================================
93 |
94 | type t = {
95 | a: int,
96 | b: myType,
97 |
98 | type_: string,
99 |
100 | mutable x: int,
101 |
102 | opt?: string,
103 |
104 | env: {..} as 'env
105 | }
106 |
107 | type t = Mod.t = {a: int}
108 |
109 | type t = {}
110 |
111 | type t = {
112 | ...a,
113 | ...b,
114 | ...Mod.t,
115 | ...Mod.t,
116 | other: int,
117 | }
118 |
119 | --------------------------------------------------------------------------------
120 |
121 | (source_file
122 | (type_declaration
123 | (type_binding
124 | (type_identifier)
125 | (record_type
126 | (record_type_field
127 | (property_identifier)
128 | (type_annotation
129 | (type_identifier)))
130 | (record_type_field
131 | (property_identifier)
132 | (type_annotation
133 | (type_identifier)))
134 | (record_type_field
135 | (property_identifier)
136 | (type_annotation
137 | (type_identifier)))
138 | (record_type_field
139 | (property_identifier)
140 | (type_annotation
141 | (type_identifier)))
142 | (record_type_field
143 | (property_identifier)
144 | (type_annotation
145 | (type_identifier)))
146 | (record_type_field
147 | (property_identifier)
148 | (type_annotation
149 | (as_aliasing_type
150 | (object_type)
151 | (type_identifier)))))))
152 | (type_declaration
153 | (type_binding
154 | (type_identifier)
155 | (type_identifier_path
156 | (module_identifier)
157 | (type_identifier))
158 | (record_type
159 | (record_type_field
160 | (property_identifier)
161 | (type_annotation
162 | (type_identifier))))))
163 | (type_declaration
164 | (type_binding
165 | (type_identifier)
166 | (record_type)))
167 | (type_declaration
168 | (type_binding
169 | (type_identifier)
170 | (record_type
171 | (type_spread
172 | (type_identifier))
173 | (type_spread
174 | (generic_type
175 | (type_identifier)
176 | (type_arguments
177 | (type_identifier))))
178 | (type_spread
179 | (generic_type
180 | (type_identifier_path
181 | (module_identifier)
182 | (type_identifier))
183 | (type_arguments
184 | (type_identifier))))
185 | (type_spread
186 | (type_identifier_path
187 | (module_identifier)
188 | (type_identifier)))
189 | (record_type_field
190 | (property_identifier)
191 | (type_annotation
192 | (type_identifier)))))))
193 |
194 | ================================================================================
195 | Extensible Variant
196 | ================================================================================
197 |
198 | type t = ..
199 |
200 | type t += Other
201 |
202 | type M.t +=
203 | | Point
204 | | Line
205 |
206 | --------------------------------------------------------------------------------
207 |
208 | (source_file
209 | (type_declaration
210 | (type_binding
211 | (type_identifier)))
212 | (type_declaration
213 | (type_binding
214 | (type_identifier)
215 | (variant_type
216 | (variant_declaration
217 | (variant_identifier)))))
218 | (type_declaration
219 | (type_binding
220 | (type_identifier_path
221 | (module_identifier)
222 | (type_identifier))
223 | (variant_type
224 | (variant_declaration
225 | (variant_identifier))
226 | (variant_declaration
227 | (variant_identifier))))))
228 |
229 | ================================================================================
230 | Variant
231 | ================================================================================
232 |
233 | type t =
234 | | A
235 | | A'
236 | | D
237 | | B(anotherType)
238 | | C({foo: int, bar: string})
239 | | D(module(Foo))
240 | | D(module(Bar.t))
241 |
242 | --------------------------------------------------------------------------------
243 |
244 | (source_file
245 | (type_declaration
246 | (type_binding
247 | (type_identifier)
248 | (variant_type
249 | (variant_declaration
250 | (variant_identifier))
251 | (variant_declaration
252 | (variant_identifier))
253 | (variant_declaration
254 | (variant_identifier))
255 | (variant_declaration
256 | (variant_identifier)
257 | (variant_parameters
258 | (type_identifier)))
259 | (variant_declaration
260 | (variant_identifier)
261 | (variant_parameters
262 | (record_type
263 | (record_type_field
264 | (property_identifier)
265 | (type_annotation
266 | (type_identifier)))
267 | (record_type_field
268 | (property_identifier)
269 | (type_annotation
270 | (type_identifier))))))
271 | (variant_declaration
272 | (variant_identifier)
273 | (variant_parameters
274 | (module_pack
275 | (module_identifier))))
276 | (variant_declaration
277 | (variant_identifier)
278 | (variant_parameters
279 | (module_pack
280 | (type_identifier_path
281 | (module_identifier)
282 | (type_identifier)))))))))
283 |
284 | ================================================================================
285 | Annotated variant
286 | ================================================================================
287 |
288 | type rec t = Any('a): t
289 |
290 | --------------------------------------------------------------------------------
291 |
292 | (source_file
293 | (type_declaration
294 | (type_binding
295 | (type_identifier)
296 | (variant_type
297 | (variant_declaration
298 | (variant_identifier)
299 | (variant_parameters
300 | (type_identifier))
301 | (type_annotation
302 | (type_identifier)))))))
303 |
304 | ================================================================================
305 | Polyvar
306 | ================================================================================
307 |
308 | type t = [>
309 | | #AAA
310 | | #AAA'
311 | | #bbb(anotherType)
312 | | #"cc-cc"
313 | | #\"cc-cc"
314 | | #42
315 | | #FortyTwo
316 | | anotherType
317 | ]
318 |
319 |
320 | type foo<'a> = [> #Blue | #DeepBlue | #LightBlue ] as 'a
321 | type t<'w> = [M.t<'w>]
322 |
323 | --------------------------------------------------------------------------------
324 |
325 | (source_file
326 | (type_declaration
327 | (type_binding
328 | (type_identifier)
329 | (polyvar_type
330 | (polyvar_declaration
331 | (polyvar_identifier))
332 | (polyvar_declaration
333 | (polyvar_identifier))
334 | (polyvar_declaration
335 | (polyvar_identifier)
336 | (polyvar_parameters
337 | (type_identifier)))
338 | (polyvar_declaration
339 | (polyvar_identifier
340 | (polyvar_string
341 | (string_fragment))))
342 | (polyvar_declaration
343 | (polyvar_identifier
344 | (polyvar_string
345 | (string_fragment))))
346 | (polyvar_declaration
347 | (polyvar_identifier))
348 | (polyvar_declaration
349 | (polyvar_identifier))
350 | (polyvar_declaration
351 | (type_identifier)))))
352 | (type_declaration
353 | (type_binding
354 | (type_identifier)
355 | (type_parameters
356 | (type_identifier))
357 | (as_aliasing_type
358 | (polyvar_type
359 | (polyvar_declaration
360 | (polyvar_identifier))
361 | (polyvar_declaration
362 | (polyvar_identifier))
363 | (polyvar_declaration
364 | (polyvar_identifier)))
365 | (type_identifier))))
366 | (type_declaration
367 | (type_binding
368 | (type_identifier)
369 | (type_parameters
370 | (type_identifier))
371 | (polyvar_type
372 | (polyvar_declaration
373 | (generic_type
374 | (type_identifier_path
375 | (module_identifier)
376 | (type_identifier))
377 | (type_arguments
378 | (type_identifier))))))))
379 |
380 | ================================================================================
381 | Function
382 | ================================================================================
383 |
384 | type fooA = t => float
385 | type fooB = (t) => float
386 | type fooC = (t1, t2) => float
387 | type fooD = (~arg1: t1, ~arg2: t2=?, unit) => float
388 |
389 | --------------------------------------------------------------------------------
390 |
391 | (source_file
392 | (type_declaration
393 | (type_binding
394 | (type_identifier)
395 | (function_type
396 | (function_type_parameters
397 | (type_identifier))
398 | (type_identifier))))
399 | (type_declaration
400 | (type_binding
401 | (type_identifier)
402 | (function_type
403 | (function_type_parameters
404 | (parameter
405 | (type_identifier)))
406 | (type_identifier))))
407 | (type_declaration
408 | (type_binding
409 | (type_identifier)
410 | (function_type
411 | (function_type_parameters
412 | (parameter
413 | (type_identifier))
414 | (parameter
415 | (type_identifier)))
416 | (type_identifier))))
417 | (type_declaration
418 | (type_binding
419 | (type_identifier)
420 | (function_type
421 | (function_type_parameters
422 | (parameter
423 | (labeled_parameter
424 | (value_identifier)
425 | (type_annotation
426 | (type_identifier))))
427 | (parameter
428 | (labeled_parameter
429 | (value_identifier)
430 | (type_annotation
431 | (type_identifier))))
432 | (parameter
433 | (unit_type)))
434 | (type_identifier)))))
435 |
436 | ================================================================================
437 | Object
438 | ================================================================================
439 |
440 | type t = {..}
441 | type t = {.}
442 | type t = {.. "my-field": int }
443 | type t = {
444 | "my-field": int,
445 | "my-field-two": string,
446 | ...rest
447 | }
448 | type t<'a> = {.."name": string} as 'a
449 |
450 | --------------------------------------------------------------------------------
451 |
452 | (source_file
453 | (type_declaration
454 | (type_binding
455 | (type_identifier)
456 | (object_type)))
457 | (type_declaration
458 | (type_binding
459 | (type_identifier)
460 | (object_type)))
461 | (type_declaration
462 | (type_binding
463 | (type_identifier)
464 | (object_type
465 | (field
466 | (property_identifier
467 | (string_fragment))
468 | (type_identifier)))))
469 | (type_declaration
470 | (type_binding
471 | (type_identifier)
472 | (object_type
473 | (field
474 | (property_identifier
475 | (string_fragment))
476 | (type_identifier))
477 | (field
478 | (property_identifier
479 | (string_fragment))
480 | (type_identifier))
481 | (type_spread
482 | (type_identifier)))))
483 | (type_declaration
484 | (type_binding
485 | (type_identifier)
486 | (type_parameters
487 | (type_identifier))
488 | (as_aliasing_type
489 | (object_type
490 | (field
491 | (property_identifier
492 | (string_fragment))
493 | (type_identifier)))
494 | (type_identifier)))))
495 |
496 | ================================================================================
497 | Generic
498 | ================================================================================
499 |
500 | type t<'a, 'b> = (array<'a>, array<'b>)
501 | type t = result<(), string>
502 | type t<'a> = generic<'a> as 's
503 |
504 | --------------------------------------------------------------------------------
505 |
506 | (source_file
507 | (type_declaration
508 | (type_binding
509 | (type_identifier)
510 | (type_parameters
511 | (type_identifier)
512 | (type_identifier))
513 | (tuple_type
514 | (generic_type
515 | (type_identifier)
516 | (type_arguments
517 | (type_identifier)))
518 | (generic_type
519 | (type_identifier)
520 | (type_arguments
521 | (type_identifier))))))
522 | (type_declaration
523 | (type_binding
524 | (type_identifier)
525 | (generic_type
526 | (type_identifier)
527 | (type_arguments
528 | (unit)
529 | (type_identifier)))))
530 | (type_declaration
531 | (type_binding
532 | (type_identifier)
533 | (type_parameters
534 | (type_identifier))
535 | (as_aliasing_type
536 | (generic_type
537 | (type_identifier)
538 | (type_arguments
539 | (type_identifier)))
540 | (type_identifier)))))
541 |
542 | ================================================================================
543 | Recursive
544 | ================================================================================
545 |
546 | type rec t = t
547 |
548 | --------------------------------------------------------------------------------
549 |
550 | (source_file
551 | (type_declaration
552 | (type_binding
553 | (type_identifier)
554 | (type_identifier))))
555 |
556 | ================================================================================
557 | Mutually Recursive
558 | ================================================================================
559 |
560 | type rec student = {
561 | teacher: teacher
562 | }
563 | and teacher = {
564 | students: array
565 | }
566 |
567 | --------------------------------------------------------------------------------
568 |
569 | (source_file
570 | (type_declaration
571 | (type_binding
572 | (type_identifier)
573 | (record_type
574 | (record_type_field
575 | (property_identifier)
576 | (type_annotation
577 | (type_identifier)))))
578 | (type_binding
579 | (type_identifier)
580 | (record_type
581 | (record_type_field
582 | (property_identifier)
583 | (type_annotation
584 | (generic_type
585 | (type_identifier)
586 | (type_arguments
587 | (type_identifier)))))))))
588 |
589 | ================================================================================
590 | Labled function with uncurried
591 | ================================================================================
592 |
593 | type test = (. ~attr: string) => unit
594 |
595 | --------------------------------------------------------------------------------
596 |
597 | (source_file
598 | (type_declaration
599 | (type_binding
600 | (type_identifier)
601 | (function_type
602 | (function_type_parameters
603 | (parameter
604 | (uncurry)
605 | (labeled_parameter
606 | (value_identifier)
607 | (type_annotation
608 | (type_identifier)))))
609 | (unit_type)))))
610 |
611 | ================================================================================
612 | Polymorphic type
613 | ================================================================================
614 |
615 | let id: 'a. 'a => 'a = x => x
616 |
617 | let add: type a. (number, number) => a
618 |
619 | --------------------------------------------------------------------------------
620 |
621 | (source_file
622 | (let_declaration
623 | (let_binding
624 | (value_identifier)
625 | (type_annotation
626 | (polymorphic_type
627 | (type_identifier)
628 | (function_type
629 | (function_type_parameters
630 | (type_identifier))
631 | (type_identifier))))
632 | (function
633 | (value_identifier)
634 | (value_identifier))))
635 | (let_declaration
636 | (let_binding
637 | (value_identifier)
638 | (type_annotation
639 | (polymorphic_type
640 | (abstract_type
641 | (type_identifier))
642 | (function_type
643 | (function_type_parameters
644 | (parameter
645 | (generic_type
646 | (type_identifier)
647 | (type_arguments
648 | (type_identifier))))
649 | (parameter
650 | (generic_type
651 | (type_identifier)
652 | (type_arguments
653 | (type_identifier)))))
654 | (type_identifier)))))))
655 |
656 | ================================================================================
657 | Variance annotations
658 | ================================================================================
659 |
660 | type t<+'a>
661 | type t<-'a>
662 |
663 | --------------------------------------------------------------------------------
664 |
665 | (source_file
666 | (type_declaration
667 | (type_binding
668 | (type_identifier)
669 | (type_parameters
670 | (type_identifier))))
671 | (type_declaration
672 | (type_binding
673 | (type_identifier)
674 | (type_parameters
675 | (type_identifier)))))
676 |
677 | ================================================================================
678 | Type constraint
679 | ================================================================================
680 |
681 | type t<'a> = 'a constraint 'a = int
682 | type decorator<'a, 'b> = 'a => 'b constraint 'a = int constraint 'b = _ => _
683 | type t<'a> constraint 'a = t
684 |
685 | --------------------------------------------------------------------------------
686 |
687 | (source_file
688 | (type_declaration
689 | (type_binding
690 | (type_identifier)
691 | (type_parameters
692 | (type_identifier))
693 | (type_identifier)
694 | (type_constraint
695 | (type_identifier)
696 | (type_identifier))))
697 | (type_declaration
698 | (type_binding
699 | (type_identifier)
700 | (type_parameters
701 | (type_identifier)
702 | (type_identifier))
703 | (function_type
704 | (function_type_parameters
705 | (type_identifier))
706 | (type_identifier))
707 | (type_constraint
708 | (type_identifier)
709 | (type_identifier))
710 | (type_constraint
711 | (type_identifier)
712 | (function_type
713 | (function_type_parameters
714 | (type_identifier))
715 | (type_identifier)))))
716 | (type_declaration
717 | (type_binding
718 | (type_identifier)
719 | (type_parameters
720 | (type_identifier))
721 | (type_constraint
722 | (type_identifier)
723 | (type_identifier)))))
724 |
--------------------------------------------------------------------------------
/test/corpus/modules.txt:
--------------------------------------------------------------------------------
1 | ================================================================================
2 | Open
3 | ================================================================================
4 |
5 | open Foo
6 | open! Foo.Bar
7 |
8 | --------------------------------------------------------------------------------
9 |
10 | (source_file
11 | (open_statement
12 | (module_identifier))
13 | (open_statement
14 | (module_identifier_path
15 | (module_identifier)
16 | (module_identifier))))
17 |
18 | ================================================================================
19 | Include
20 | ================================================================================
21 |
22 | include Foo
23 | include Foo.Bar
24 | include Foo.Bar(X)
25 | include Foo.Bar({
26 | type t
27 | let x: int
28 | })
29 |
30 | include module type of Belt.Array
31 | include (module type of Belt.Array)
32 | include (Belt: module type of Belt with module Map.Inner := Belt.Map and module Result := Belt.Result)
33 | include module type of {
34 | include T
35 | }
36 | include (
37 | {
38 | let a = Js.log("Hello")
39 | }
40 | )
41 |
42 | --------------------------------------------------------------------------------
43 |
44 | (source_file
45 | (include_statement
46 | (module_identifier))
47 | (include_statement
48 | (module_identifier_path
49 | (module_identifier)
50 | (module_identifier)))
51 | (include_statement
52 | (functor_use
53 | (module_identifier_path
54 | (module_identifier)
55 | (module_identifier))
56 | (arguments
57 | (module_identifier))))
58 | (include_statement
59 | (functor_use
60 | (module_identifier_path
61 | (module_identifier)
62 | (module_identifier))
63 | (arguments
64 | (block
65 | (type_declaration
66 | (type_binding
67 | (type_identifier)))
68 | (let_declaration
69 | (let_binding
70 | (value_identifier)
71 | (type_annotation
72 | (type_identifier))))))))
73 | (include_statement
74 | (module_type_of
75 | (module_identifier_path
76 | (module_identifier)
77 | (module_identifier))))
78 | (include_statement
79 | (parenthesized_module_expression
80 | (module_type_of
81 | (module_identifier_path
82 | (module_identifier)
83 | (module_identifier)))))
84 | (include_statement
85 | (parenthesized_module_expression
86 | (module_identifier)
87 | (module_type_annotation
88 | (module_type_constraint
89 | (module_type_of
90 | (module_identifier))
91 | (constrain_module
92 | (module_identifier_path
93 | (module_identifier)
94 | (module_identifier))
95 | (module_identifier_path
96 | (module_identifier)
97 | (module_identifier)))
98 | (constrain_module
99 | (module_identifier)
100 | (module_identifier_path
101 | (module_identifier)
102 | (module_identifier)))))))
103 | (include_statement
104 | (module_type_of
105 | (block
106 | (include_statement
107 | (module_identifier)))))
108 | (include_statement
109 | (block
110 | (let_declaration
111 | (let_binding
112 | (value_identifier)
113 | (call_expression
114 | (value_identifier_path
115 | (module_identifier)
116 | (value_identifier))
117 | (arguments
118 | (string
119 | (string_fragment)))))))))
120 |
121 | ================================================================================
122 | Simple definition
123 | ================================================================================
124 |
125 | module MyModule = {
126 | type t
127 | }
128 |
129 | --------------------------------------------------------------------------------
130 |
131 | (source_file
132 | (module_declaration
133 | (module_binding
134 | (module_identifier)
135 | (block
136 | (type_declaration
137 | (type_binding
138 | (type_identifier)))))))
139 |
140 | ================================================================================
141 | Signature and definition
142 | ================================================================================
143 |
144 | module MyModule: {
145 | let a: int
146 | let b: float
147 | let c: string
148 | }
149 |
150 | module MyModule: Foo.Bar = {
151 | type t
152 | }
153 |
154 | module MyModule: {
155 | type t
156 | } = {
157 | type t = int
158 | }
159 |
160 | --------------------------------------------------------------------------------
161 |
162 | (source_file
163 | (module_declaration
164 | (module_binding
165 | name: (module_identifier)
166 | signature: (block
167 | (let_declaration
168 | (let_binding
169 | pattern: (value_identifier)
170 | (type_annotation
171 | (type_identifier))))
172 | (let_declaration
173 | (let_binding
174 | pattern: (value_identifier)
175 | (type_annotation
176 | (type_identifier))))
177 | (let_declaration
178 | (let_binding
179 | pattern: (value_identifier)
180 | (type_annotation
181 | (type_identifier)))))))
182 | (module_declaration
183 | (module_binding
184 | name: (module_identifier)
185 | signature: (module_identifier_path
186 | (module_identifier)
187 | (module_identifier))
188 | definition: (block
189 | (type_declaration
190 | (type_binding
191 | name: (type_identifier))))))
192 | (module_declaration
193 | (module_binding
194 | name: (module_identifier)
195 | signature: (block
196 | (type_declaration
197 | (type_binding
198 | name: (type_identifier))))
199 | definition: (block
200 | (type_declaration
201 | (type_binding
202 | name: (type_identifier)
203 | (type_identifier)))))))
204 |
205 | ================================================================================
206 | Module types
207 | ================================================================================
208 |
209 | module type S1 = { type t }
210 | module type S2 = module type of MyModule.Submod
211 | module type t
212 |
213 | --------------------------------------------------------------------------------
214 |
215 | (source_file
216 | (module_declaration
217 | (module_binding
218 | (module_identifier)
219 | (block
220 | (type_declaration
221 | (type_binding
222 | (type_identifier))))))
223 | (module_declaration
224 | (module_binding
225 | (module_identifier)
226 | (module_type_of
227 | (module_identifier_path
228 | (module_identifier)
229 | (module_identifier)))))
230 | (module_declaration
231 | (module_binding
232 | (type_identifier))))
233 |
234 | ================================================================================
235 | First Class module
236 | ================================================================================
237 |
238 | module(LightTheme)
239 | module(A: A)
240 | module(
241 | {
242 | type t
243 | let foo = "Hello"
244 | }: X
245 | )
246 | module(SomeFunctor(unpack(x)))
247 |
248 | module T = unpack(foo: T)
249 |
250 | module S = unpack(foo: T with type t = a)
251 |
252 | module S = unpack(Mod.read(v))
253 |
254 | module S = unpack(%extension(payload))
255 |
256 | --------------------------------------------------------------------------------
257 |
258 | (source_file
259 | (expression_statement
260 | (module_pack
261 | (module_identifier)))
262 | (expression_statement
263 | (module_pack
264 | (module_identifier)
265 | (module_type_annotation
266 | (module_identifier))))
267 | (expression_statement
268 | (module_pack
269 | (block
270 | (type_declaration
271 | (type_binding
272 | (type_identifier)))
273 | (let_declaration
274 | (let_binding
275 | (value_identifier)
276 | (string
277 | (string_fragment)))))
278 | (module_type_annotation
279 | (module_identifier))))
280 | (expression_statement
281 | (module_pack
282 | (functor_use
283 | (module_identifier)
284 | (arguments
285 | (module_unpack
286 | (value_identifier))))))
287 | (module_declaration
288 | (module_binding
289 | (module_identifier)
290 | (module_unpack
291 | (value_identifier)
292 | (module_type_annotation
293 | (module_identifier)))))
294 | (module_declaration
295 | (module_binding
296 | (module_identifier)
297 | (module_unpack
298 | (value_identifier)
299 | (module_type_annotation
300 | (module_type_constraint
301 | (module_identifier)
302 | (constrain_type
303 | (type_identifier)
304 | (type_identifier)))))))
305 | (module_declaration
306 | (module_binding
307 | (module_identifier)
308 | (module_unpack
309 | (call_expression
310 | (value_identifier_path
311 | (module_identifier)
312 | (value_identifier))
313 | (arguments
314 | (value_identifier))))))
315 | (module_declaration
316 | (module_binding
317 | (module_identifier)
318 | (module_unpack
319 | (extension_expression
320 | (extension_identifier)
321 | (expression_statement
322 | (value_identifier)))))))
323 |
324 | ================================================================================
325 | Functor definition
326 | ================================================================================
327 |
328 | module MyFunctor = (X: {type t}, Y: {type t}): {type tx; type ty} => {
329 | type tx = X.t
330 | type ty = Y.t
331 | }
332 |
333 | module F2: (S1, S1) => T = (X: S, Y: S) => {
334 | let cow = x => Y.foo(X.foo(x))
335 | }
336 |
337 | --------------------------------------------------------------------------------
338 |
339 | (source_file
340 | (module_declaration
341 | (module_binding
342 | name: (module_identifier)
343 | definition: (functor
344 | parameters: (functor_parameters
345 | (functor_parameter
346 | (module_identifier)
347 | (module_type_annotation
348 | (block
349 | (type_declaration
350 | (type_binding
351 | name: (type_identifier))))))
352 | (functor_parameter
353 | (module_identifier)
354 | (module_type_annotation
355 | (block
356 | (type_declaration
357 | (type_binding
358 | name: (type_identifier)))))))
359 | return_module_type: (module_type_annotation
360 | (block
361 | (type_declaration
362 | (type_binding
363 | name: (type_identifier)))
364 | (type_declaration
365 | (type_binding
366 | name: (type_identifier)))))
367 | body: (block
368 | (type_declaration
369 | (type_binding
370 | name: (type_identifier)
371 | (type_identifier_path
372 | (module_identifier)
373 | (type_identifier))))
374 | (type_declaration
375 | (type_binding
376 | name: (type_identifier)
377 | (type_identifier_path
378 | (module_identifier)
379 | (type_identifier))))))))
380 | (module_declaration
381 | (module_binding
382 | name: (module_identifier)
383 | signature: (functor
384 | parameters: (functor_parameters
385 | (functor_parameter
386 | (module_identifier))
387 | (functor_parameter
388 | (module_identifier)))
389 | body: (module_identifier))
390 | definition: (functor
391 | parameters: (functor_parameters
392 | (functor_parameter
393 | (module_identifier)
394 | (module_type_annotation
395 | (module_identifier)))
396 | (functor_parameter
397 | (module_identifier)
398 | (module_type_annotation
399 | (module_identifier))))
400 | body: (block
401 | (let_declaration
402 | (let_binding
403 | pattern: (value_identifier)
404 | body: (function
405 | parameter: (value_identifier)
406 | body: (call_expression
407 | function: (value_identifier_path
408 | (module_identifier)
409 | (value_identifier))
410 | arguments: (arguments
411 | (call_expression
412 | function: (value_identifier_path
413 | (module_identifier)
414 | (value_identifier))
415 | arguments: (arguments
416 | (value_identifier)))))))))))))
417 |
418 | ================================================================================
419 | Functor signature
420 | ================================================================================
421 |
422 | module Make: (Content: StaticContent) => {
423 | let make: string => string
424 | }
425 |
426 | --------------------------------------------------------------------------------
427 |
428 | (source_file
429 | (module_declaration
430 | (module_binding
431 | (module_identifier)
432 | (functor
433 | (functor_parameters
434 | (functor_parameter
435 | (module_identifier)
436 | (module_type_annotation
437 | (module_identifier))))
438 | (block
439 | (let_declaration
440 | (let_binding
441 | (value_identifier)
442 | (type_annotation
443 | (function_type
444 | (function_type_parameters
445 | (type_identifier))
446 | (type_identifier))))))))))
447 |
448 | ================================================================================
449 | Functor use
450 | ================================================================================
451 |
452 | module M = MyFunctor(Foo, Bar.Baz)
453 |
454 | --------------------------------------------------------------------------------
455 |
456 | (source_file
457 | (module_declaration
458 | (module_binding
459 | (module_identifier)
460 | (functor_use
461 | (module_identifier)
462 | (arguments
463 | (module_identifier)
464 | (module_identifier_path
465 | (module_identifier)
466 | (module_identifier)))))))
467 |
468 | ================================================================================
469 | Alias
470 | ================================================================================
471 |
472 | module Q = Foo.Bar.Qux
473 | module Foo' = Foo
474 |
475 | --------------------------------------------------------------------------------
476 |
477 | (source_file
478 | (module_declaration
479 | (module_binding
480 | (module_identifier)
481 | (module_identifier_path
482 | (module_identifier_path
483 | (module_identifier)
484 | (module_identifier))
485 | (module_identifier))))
486 | (module_declaration
487 | (module_binding
488 | (module_identifier)
489 | (module_identifier))))
490 |
491 | ================================================================================
492 | Recursive
493 | ================================================================================
494 |
495 | module rec BYOBReader: {
496 | include Reader
497 | } = BYOBReader
498 |
499 | module rec A: T = {
500 | let x = B.x
501 | }
502 | and B: T = {
503 | let x = 1
504 | }
505 |
506 | --------------------------------------------------------------------------------
507 |
508 | (source_file
509 | (module_declaration
510 | (module_binding
511 | (module_identifier)
512 | (block
513 | (include_statement
514 | (module_identifier)))
515 | (module_identifier)))
516 | (module_declaration
517 | (module_binding
518 | (module_identifier)
519 | (module_identifier)
520 | (block
521 | (let_declaration
522 | (let_binding
523 | (value_identifier)
524 | (value_identifier_path
525 | (module_identifier)
526 | (value_identifier))))))
527 | (module_binding
528 | (module_identifier)
529 | (module_identifier)
530 | (block
531 | (let_declaration
532 | (let_binding
533 | (value_identifier)
534 | (number)))))))
535 |
536 | ================================================================================
537 | Definition through extension
538 | ================================================================================
539 |
540 | module Styles = %makeStyles(())
541 |
542 | --------------------------------------------------------------------------------
543 |
544 | (source_file
545 | (module_declaration
546 | (module_binding
547 | (module_identifier)
548 | (extension_expression
549 | (extension_identifier)
550 | (expression_statement
551 | (unit))))))
552 |
553 | ================================================================================
554 | Externals
555 | ================================================================================
556 |
557 | external aX: t => float = "aX"
558 | external foo: int = "foo"
559 | external foo: int = "foo"
560 | external foo: t = "Foo"
561 | external _makeStyles: ({..}, . unit) => {..} = "makeStyles"
562 |
563 | external pushState: (Dom.history, ~href: string) => unit =
564 | "pushState"
565 |
566 | external add: (
567 | t,
568 | ~option: [#Option(Dom.htmlOptionElement) | #OptGroup(Dom.htmlOptGroupElement)],
569 | ) => unit = "add"
570 |
571 | --------------------------------------------------------------------------------
572 |
573 | (source_file
574 | (external_declaration
575 | (value_identifier)
576 | (type_annotation
577 | (function_type
578 | (function_type_parameters
579 | (type_identifier))
580 | (type_identifier)))
581 | (string
582 | (string_fragment)))
583 | (external_declaration
584 | (value_identifier)
585 | (type_annotation
586 | (type_identifier))
587 | (string
588 | (string_fragment)))
589 | (external_declaration
590 | (value_identifier)
591 | (type_annotation
592 | (type_identifier))
593 | (string
594 | (string_fragment)))
595 | (external_declaration
596 | (value_identifier)
597 | (type_annotation
598 | (type_identifier))
599 | (string
600 | (string_fragment)))
601 | (external_declaration
602 | (value_identifier)
603 | (type_annotation
604 | (function_type
605 | (function_type_parameters
606 | (parameter
607 | (object_type))
608 | (parameter
609 | (uncurry)
610 | (unit_type)))
611 | (object_type)))
612 | (string
613 | (string_fragment)))
614 | (external_declaration
615 | (value_identifier)
616 | (type_annotation
617 | (function_type
618 | (function_type_parameters
619 | (parameter
620 | (type_identifier_path
621 | (module_identifier)
622 | (type_identifier)))
623 | (parameter
624 | (labeled_parameter
625 | (value_identifier)
626 | (type_annotation
627 | (type_identifier)))))
628 | (unit_type)))
629 | (string
630 | (string_fragment)))
631 | (external_declaration
632 | (value_identifier)
633 | (type_annotation
634 | (function_type
635 | (function_type_parameters
636 | (parameter
637 | (type_identifier))
638 | (parameter
639 | (labeled_parameter
640 | (value_identifier)
641 | (type_annotation
642 | (polyvar_type
643 | (polyvar_declaration
644 | (polyvar_identifier)
645 | (polyvar_parameters
646 | (type_identifier_path
647 | (module_identifier)
648 | (type_identifier))))
649 | (polyvar_declaration
650 | (polyvar_identifier)
651 | (polyvar_parameters
652 | (type_identifier_path
653 | (module_identifier)
654 | (type_identifier)))))))))
655 | (unit_type)))
656 | (string
657 | (string_fragment))))
658 |
659 | ================================================================================
660 | Exception declaration
661 | ================================================================================
662 |
663 | exception InputClosed(string)
664 | exception Error = Failed
665 | exception Invalid = Errors.Invalid
666 |
667 | --------------------------------------------------------------------------------
668 |
669 | (source_file
670 | (exception_declaration
671 | (variant_identifier)
672 | (variant_parameters
673 | (type_identifier)))
674 | (exception_declaration
675 | (variant_identifier)
676 | (variant_identifier))
677 | (exception_declaration
678 | (variant_identifier)
679 | (nested_variant_identifier
680 | (module_identifier)
681 | (variant_identifier))))
682 |
683 | ================================================================================
684 | Module Constraints
685 | ================================================================================
686 |
687 | module(M: T with type t = a and type t = b)
688 |
689 | module M = (): (T with type t = int) => {}
690 |
691 | module M = (Na: N, Nb: N): (
692 | (S with type t = x) with type a = b
693 | ) => {}
694 |
695 | --------------------------------------------------------------------------------
696 |
697 | (source_file
698 | (expression_statement
699 | (module_pack
700 | (module_identifier)
701 | (module_type_annotation
702 | (module_type_constraint
703 | (module_identifier)
704 | (constrain_type
705 | (type_identifier)
706 | (type_identifier))
707 | (constrain_type
708 | (type_identifier)
709 | (type_identifier))))))
710 | (module_declaration
711 | (module_binding
712 | name: (module_identifier)
713 | definition: (functor
714 | parameters: (functor_parameters)
715 | return_module_type: (module_type_annotation
716 | (parenthesized_module_expression
717 | (module_type_constraint
718 | (module_identifier)
719 | (constrain_type
720 | (type_identifier)
721 | (type_identifier)))))
722 | body: (block))))
723 | (module_declaration
724 | (module_binding
725 | name: (module_identifier)
726 | definition: (functor
727 | parameters: (functor_parameters
728 | (functor_parameter
729 | (module_identifier)
730 | (module_type_annotation
731 | (module_identifier)))
732 | (functor_parameter
733 | (module_identifier)
734 | (module_type_annotation
735 | (module_identifier))))
736 | return_module_type: (module_type_annotation
737 | (parenthesized_module_expression
738 | (module_type_constraint
739 | (parenthesized_module_expression
740 | (module_type_constraint
741 | (module_identifier)
742 | (constrain_type
743 | (type_identifier)
744 | (type_identifier))))
745 | (constrain_type
746 | (type_identifier)
747 | (type_identifier)))))
748 | body: (block)))))
749 |
750 | ================================================================================
751 | Dynamic imports
752 | ================================================================================
753 |
754 | module LazyUtils: UtilsType = await Utils
755 |
756 | --------------------------------------------------------------------------------
757 |
758 | (source_file
759 | (module_declaration
760 | (module_binding
761 | (module_identifier)
762 | (module_identifier)
763 | (module_identifier))))
764 |
765 | ================================================================================
766 | Record with module path
767 | ================================================================================
768 |
769 | t.A.B.c
770 |
771 | --------------------------------------------------------------------------------
772 |
773 | (source_file
774 | (expression_statement
775 | (member_expression
776 | (value_identifier)
777 | (module_identifier)
778 | (module_identifier)
779 | (property_identifier))))
780 |
--------------------------------------------------------------------------------
/grammar.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | module.exports = grammar({
4 | name: 'rescript',
5 |
6 | externals: $ => [
7 | $._newline,
8 | $.comment,
9 | $._newline_and_comment,
10 | '"',
11 | "`",
12 | $._template_chars,
13 | $._lparen,
14 | $._rparen,
15 | $._list_constructor,
16 | $._decorator,
17 | $._decorator_inline,
18 | ],
19 |
20 | extras: $ => [
21 | $.comment,
22 | $.decorator,
23 | /[\s\uFEFF\u2060\u200B\u00A0]/
24 | ],
25 |
26 | supertypes: $ => [
27 | $.statement,
28 | $.declaration,
29 | $.expression,
30 | $.primary_expression,
31 | $._type,
32 | $.module_expression,
33 | $.module_primary_expression,
34 | ],
35 |
36 | inline: $ => [
37 | $._module_definition,
38 | ],
39 |
40 | precedences: $ => [
41 | // + - Operators -> precendence
42 | [
43 | 'unary_not',
44 | 'member',
45 | 'call',
46 | $.spread_element,
47 | $.await_expression,
48 | $.pipe_expression,
49 | $.lazy_expression,
50 | 'binary_times',
51 | 'binary_pow',
52 | 'binary_plus',
53 | 'binary_compare',
54 | 'binary_relation',
55 | 'binary_and',
56 | 'binary_or',
57 | 'coercion_relation',
58 | $.expression,
59 | $.primary_expression,
60 | $.ternary_expression,
61 | $.mutation_expression,
62 | $.function,
63 | $.let_declaration,
64 | ],
65 | // Nested.Module.Path precendence
66 | [
67 | $.module_primary_expression,
68 | $.value_identifier_path,
69 | $.nested_variant_identifier,
70 | $.module_identifier_path,
71 | ],
72 | [$._jsx_attribute_value, $.pipe_expression],
73 | [$.function_type_parameters, $.function_type],
74 | [$._reserved_identifier, $.module_unpack],
75 | [$.lazy_pattern, $.or_pattern]
76 | ],
77 |
78 | conflicts: $ => [
79 | [$.unit, $.formal_parameters],
80 | [$.primary_expression, $._pattern],
81 | [$.primary_expression, $.record_pattern],
82 | [$.primary_expression, $.spread_pattern],
83 | [$.primary_expression, $._literal_pattern],
84 | [$.primary_expression, $._jsx_child],
85 | [$.tuple_type, $.function_type_parameter],
86 | [$.list, $.list_pattern],
87 | [$.array, $.array_pattern],
88 | [$.type_declaration],
89 | [$.let_declaration],
90 | [$.variant_identifier, $.module_identifier],
91 | [$.variant, $.variant_pattern],
92 | [$.variant_arguments, $._variant_pattern_parameters],
93 | [$.polyvar, $.polyvar_pattern],
94 | [$._pattern],
95 | [$._record_element, $._record_single_field],
96 | [$._record_pun_field, $._record_single_pun_field],
97 | [$._record_field_name, $.record_pattern],
98 | [$._statement, $._one_or_more_statements],
99 | [$._inline_type, $.function_type_parameters],
100 | [$.primary_expression, $.parameter, $._pattern],
101 | [$.parameter, $._pattern],
102 | [$.parameter, $.parenthesized_pattern],
103 | [$.parameter, $.tuple_item_pattern],
104 | [$.unit, $._function_type_parameter_list],
105 | [$.functor_parameter, $.module_primary_expression, $.module_identifier_path],
106 | [$._reserved_identifier, $.function],
107 | [$.exception_pattern, $.or_pattern],
108 | [$.type_binding, $._inline_type],
109 | [$._module_structure, $.parenthesized_module_expression],
110 | [$._record_type_member, $._object_type_member],
111 | ],
112 |
113 | rules: {
114 | source_file: $ => seq(
115 | repeat($._statement_delimeter),
116 | repeat($._statement)
117 | ),
118 |
119 | _statement: $ => seq(
120 | $.statement,
121 | repeat1($._statement_delimeter)
122 | ),
123 |
124 | _statement_delimeter: $ => choice(
125 | ';',
126 | $._newline,
127 | alias($._newline_and_comment, $.comment),
128 | ),
129 |
130 | _one_or_more_statements: $ => seq(
131 | repeat($._statement),
132 | $.statement,
133 | optional($._statement_delimeter),
134 | ),
135 |
136 | statement: $ => choice(
137 | $.expression_statement,
138 | $.declaration,
139 | $.open_statement,
140 | $.include_statement,
141 | ),
142 |
143 | block: $ => prec.right(seq(
144 | '{',
145 | optional($._one_or_more_statements),
146 | '}',
147 | )),
148 |
149 | open_statement: $ => seq(
150 | 'open',
151 | optional('!'),
152 | $.module_expression,
153 | ),
154 |
155 | include_statement: $ => seq(
156 | 'include',
157 | choice(
158 | $._module_definition,
159 | parenthesize($._module_structure)
160 | )
161 | ),
162 |
163 | declaration: $ => choice(
164 | $.type_declaration,
165 | $.let_declaration,
166 | $.module_declaration,
167 | $.external_declaration,
168 | $.exception_declaration,
169 | ),
170 |
171 | module_binding: $ => prec.left(seq(
172 | field('name', choice($.module_identifier, $.type_identifier)),
173 | optional(seq(
174 | ':',
175 | field('signature', choice($.block, $.module_expression, $.functor)),
176 | )),
177 | optional(seq(
178 | '=',
179 | optional('await'),
180 | field('definition', $._module_definition),
181 | )),
182 | )),
183 |
184 | module_declaration: $ => seq(
185 | 'module',
186 | optional('rec'),
187 | optional('type'),
188 | sep1('and', $.module_binding)
189 | ),
190 |
191 | _module_structure: $ => seq(
192 | $._module_definition,
193 | optional($.module_type_annotation),
194 | ),
195 |
196 | _module_definition: $ => choice(
197 | $.block,
198 | $.module_expression,
199 | $.functor,
200 | $.extension_expression,
201 | ),
202 |
203 | module_unpack: $ => seq(
204 | 'unpack',
205 | '(',
206 | choice(
207 | seq(
208 | choice($.value_identifier, $.value_identifier_path, $.member_expression),
209 | optional($.module_type_annotation)
210 | ),
211 | $.call_expression,
212 | $.extension_expression
213 | ),
214 | ')'
215 | ),
216 |
217 | functor: $ => seq(
218 | field('parameters', $.functor_parameters),
219 | optional(field('return_module_type', $.module_type_annotation)),
220 | '=>',
221 | field('body', $._module_definition),
222 | ),
223 |
224 | functor_parameters: $ => seq(
225 | '(',
226 | optional(commaSep1t($.functor_parameter)),
227 | ')',
228 | ),
229 |
230 | functor_parameter: $ => seq(
231 | $.module_identifier,
232 | optional($.module_type_annotation),
233 | ),
234 |
235 | module_type_annotation: $ => seq(
236 | ':',
237 | choice(
238 | $.module_expression,
239 | $.block,
240 | )
241 | ),
242 |
243 | external_declaration: $ => seq(
244 | 'external',
245 | $.value_identifier,
246 | $.type_annotation,
247 | '=',
248 | $.string,
249 | ),
250 |
251 | exception_declaration: $ => seq(
252 | 'exception',
253 | $.variant_identifier,
254 | optional($.variant_parameters),
255 | optional(seq('=', choice($.variant_identifier, $.nested_variant_identifier)))
256 | ),
257 |
258 | type_declaration: $ => seq(
259 | optional('export'),
260 | 'type',
261 | optional('rec'),
262 | sep1(
263 | seq(repeat($._newline), 'and'),
264 | $.type_binding
265 | )
266 | ),
267 |
268 | type_binding: $ => seq(
269 | field('name', choice($.type_identifier, $.type_identifier_path)),
270 | optional($.type_parameters),
271 | optional(seq(
272 | optional(seq('=', $._non_function_inline_type)),
273 | optional(seq(
274 | choice('=', '+='),
275 | optional('private'),
276 | field('body', $._type),
277 | )),
278 | repeat($.type_constraint),
279 | )),
280 | ),
281 |
282 | type_parameters: $ => seq(
283 | '<',
284 | commaSep1t(
285 | seq(
286 | optional(choice('+', '-')),
287 | $.type_identifier
288 | )
289 | ),
290 | '>',
291 | ),
292 |
293 | type_annotation: $ => seq(
294 | ':',
295 | $._inline_type,
296 | ),
297 |
298 | _type: $ => choice(
299 | $._inline_type,
300 | $.variant_type,
301 | $.record_type,
302 | $.as_aliasing_type,
303 | ),
304 |
305 | _inline_type: $ => choice(
306 | $._non_function_inline_type,
307 | $.function_type,
308 | ),
309 |
310 | _non_function_inline_type: $ => choice(
311 | $._type_identifier,
312 | $.tuple_type,
313 | $.polyvar_type,
314 | $.object_type,
315 | $.generic_type,
316 | $.unit_type,
317 | $.module_pack,
318 | $.unit,
319 | $.polymorphic_type,
320 | alias($._as_aliasing_non_function_inline_type, $.as_aliasing_type)
321 | ),
322 |
323 | polymorphic_type: $ => seq(
324 | choice(repeat1($.type_identifier), $.abstract_type),
325 | '.',
326 | $._inline_type
327 | ),
328 |
329 | type_constraint: $ => seq(
330 | 'constraint',
331 | $._type,
332 | '=',
333 | $._type
334 | ),
335 |
336 | tuple_type: $ => prec.dynamic(-1, seq(
337 | '(',
338 | commaSep1t($._type),
339 | ')',
340 | )),
341 |
342 | variant_type: $ => prec.left(seq(
343 | optional('|'),
344 | barSep1($.variant_declaration),
345 | )),
346 |
347 | variant_declaration: $ => prec.right(seq(
348 | $.variant_identifier,
349 | optional($.variant_parameters),
350 | optional($.type_annotation),
351 | )),
352 |
353 | variant_parameters: $ => seq(
354 | '(',
355 | commaSep1t($._type),
356 | ')',
357 | ),
358 |
359 | polyvar_type: $ => prec.left(seq(
360 | choice('[', '[>', '[<',),
361 | optional('|'),
362 | barSep1($.polyvar_declaration),
363 | ']',
364 | )),
365 |
366 | polyvar_declaration: $ => prec.right(
367 | choice(
368 | seq(
369 | $.polyvar_identifier,
370 | optional($.polyvar_parameters),
371 | ),
372 | $._inline_type
373 | )
374 | ),
375 |
376 | polyvar_parameters: $ => seq(
377 | '(',
378 | commaSep1t($._type),
379 | ')',
380 | ),
381 |
382 | record_type: $ => seq(
383 | '{',
384 | commaSept($._record_type_member),
385 | '}',
386 | ),
387 |
388 | record_type_field: $ =>
389 | seq(
390 | optional('mutable'),
391 | alias($.value_identifier, $.property_identifier),
392 | optional('?'),
393 | $.type_annotation,
394 | ),
395 |
396 | type_spread: $ =>
397 | seq('...', choice($.type_identifier, $.generic_type, $.type_identifier_path)),
398 |
399 | _record_type_member: $ => choice(
400 | $.record_type_field,
401 | $.type_spread
402 | ),
403 |
404 | object_type: $ => prec.left(seq(
405 | '{',
406 | choice(
407 | commaSep1t($._object_type_member),
408 | seq('.', commaSept($._object_type_member)),
409 | seq('..', commaSept($._object_type_member)),
410 | ),
411 | '}',
412 | )),
413 |
414 | _object_type_member: $ =>
415 | choice(
416 | alias($.object_type_field, $.field),
417 | $.type_spread
418 | ),
419 |
420 | object_type_field: $ => choice(
421 | seq(
422 | alias($.string, $.property_identifier),
423 | ':',
424 | $._type,
425 | ),
426 | ),
427 |
428 | generic_type: $ => prec.left(seq(
429 | $._type_identifier,
430 | $.type_arguments,
431 | )),
432 |
433 | type_arguments: $ => seq(
434 | '<',
435 | commaSep1t($._type),
436 | '>'
437 | ),
438 |
439 | function_type: $ => prec.left(seq(
440 | $.function_type_parameters,
441 | '=>',
442 | $._type,
443 | )),
444 |
445 | function_type_parameters: $ => choice(
446 | $._non_function_inline_type,
447 | $._function_type_parameter_list,
448 | ),
449 |
450 | _function_type_parameter_list: $ => seq(
451 | '(',
452 | commaSept(alias($.function_type_parameter, $.parameter)),
453 | ')',
454 | ),
455 |
456 | function_type_parameter: $ => seq(
457 | optional($.uncurry),
458 | choice(
459 | $._type,
460 | seq($.uncurry, $._type),
461 | $.labeled_parameter,
462 | ),
463 | ),
464 |
465 | let_declaration: $ => seq(
466 | choice('export', 'let'),
467 | optional('rec'),
468 | sep1(
469 | seq(repeat($._newline), 'and'),
470 | $.let_binding
471 | )
472 | ),
473 |
474 | let_binding: $ => seq(
475 | field('pattern', $._pattern),
476 | choice(
477 | seq(
478 | $.type_annotation,
479 | optional(
480 | seq('=',
481 | field('body', $.expression)
482 | )
483 | )
484 | ),
485 | seq(
486 | '=',
487 | field('body', $.expression),
488 | )
489 | )
490 | ),
491 |
492 | expression_statement: $ => $.expression,
493 |
494 | expression: $ => choice(
495 | $.primary_expression,
496 | $._jsx_element,
497 | $.jsx_fragment,
498 | $.unary_expression,
499 | $.binary_expression,
500 | $.coercion_expression,
501 | $.ternary_expression,
502 | $.for_expression,
503 | $.while_expression,
504 | $.mutation_expression,
505 | $.await_expression,
506 | $.block,
507 | $.assert_expression,
508 | ),
509 |
510 | primary_expression: $ => choice(
511 | $.parenthesized_expression,
512 | $.value_identifier_path,
513 | $.value_identifier,
514 | $.number,
515 | $.string,
516 | $.template_string,
517 | $.character,
518 | $.true,
519 | $.false,
520 | $.function,
521 | $.unit,
522 | $.record,
523 | $.object,
524 | $.tuple,
525 | $.array,
526 | $.list,
527 | $.variant,
528 | $.polyvar,
529 | $.if_expression,
530 | $.switch_expression,
531 | $.try_expression,
532 | $.call_expression,
533 | $.pipe_expression,
534 | $.subscript_expression,
535 | $.member_expression,
536 | $.module_pack,
537 | $.extension_expression,
538 | $.lazy_expression,
539 | $._jsx_element
540 | ),
541 |
542 | parenthesized_expression: $ => seq(
543 | '(',
544 | $.expression,
545 | optional($.type_annotation),
546 | ')'
547 | ),
548 |
549 | value_identifier_path: $ => seq(
550 | $.module_primary_expression,
551 | '.',
552 | $.value_identifier,
553 | ),
554 |
555 | function: $ => prec.left(seq(
556 | optional('async'),
557 | choice(
558 | field('parameter', $.value_identifier),
559 | $._definition_signature
560 | ),
561 | '=>',
562 | field('body', $.expression),
563 | )),
564 |
565 | record: $ => seq(
566 | '{',
567 | choice(
568 | $._record_single_field,
569 | $._record_single_pun_field,
570 | commaSep2t($._record_element),
571 | ),
572 | '}',
573 | ),
574 |
575 | _record_element: $ => choice(
576 | $.spread_element,
577 | $.record_field,
578 | alias($._record_pun_field, $.record_field),
579 | ),
580 |
581 | record_field: $ => seq(
582 | $._record_field_name,
583 | ':',
584 | optional('?'),
585 | $.expression,
586 | ),
587 |
588 | _record_pun_field: $ => seq(
589 | optional('?'),
590 | $._record_field_name,
591 | ),
592 |
593 | _record_single_field: $ => seq(
594 | $.record_field,
595 | optional(','),
596 | ),
597 |
598 | _record_single_pun_field: $ => seq(
599 | '?',
600 | $._record_field_name,
601 | optional(','),
602 | ),
603 |
604 | _record_field_name: $ => choice(
605 | alias($.value_identifier, $.property_identifier),
606 | alias($.value_identifier_path, $.property_identifier),
607 | ),
608 |
609 | object: $ => seq(
610 | '{',
611 | choice(
612 | commaSep1t($._object_field),
613 | seq('.', commaSept($._object_field)),
614 | seq('..', commaSept($._object_field)),
615 | ),
616 | '}',
617 | ),
618 |
619 | _object_field: $ => alias($.object_field, $.field),
620 |
621 | object_field: $ => seq(
622 | alias($.string, $.property_identifier),
623 | ':',
624 | $.expression,
625 | ),
626 |
627 | tuple: $ => seq(
628 | '(',
629 | commaSep2t(
630 | $.expression
631 | ),
632 | ')',
633 | ),
634 |
635 | array: $ => seq(
636 | '[',
637 | commaSept($.expression),
638 | ']'
639 | ),
640 |
641 | list: $ => seq(
642 | $._list_constructor,
643 | '{',
644 | optional(commaSep1t($._list_element)),
645 | '}'
646 | ),
647 |
648 | _list_element: $ => choice(
649 | $.expression,
650 | $.spread_element,
651 | ),
652 |
653 | if_expression: $ => seq(
654 | 'if',
655 | $.expression,
656 | $.block,
657 | repeat($.else_if_clause),
658 | optional($.else_clause),
659 | ),
660 |
661 | else_if_clause: $ => seq(
662 | 'else',
663 | 'if',
664 | $.expression,
665 | $.block,
666 | ),
667 |
668 | else_clause: $ => seq(
669 | 'else',
670 | $.block,
671 | ),
672 |
673 | switch_expression: $ => seq(
674 | 'switch',
675 | $.expression,
676 | '{',
677 | repeat($.switch_match),
678 | '}',
679 | ),
680 |
681 | switch_match: $ => prec.dynamic(-1, seq(
682 | '|',
683 | field('pattern', $._pattern),
684 | optional($.guard),
685 | '=>',
686 | field('body', alias($._one_or_more_statements, $.sequence_expression)),
687 | )),
688 |
689 | guard: $ => seq(
690 | choice('if', 'when'),
691 | $.expression,
692 | ),
693 |
694 | polyvar_type_pattern: $ => seq(
695 | '#',
696 | '...',
697 | $._type_identifier,
698 | ),
699 |
700 | try_expression: $ => seq(
701 | 'try',
702 | $.expression,
703 | 'catch',
704 | '{',
705 | repeat($.switch_match),
706 | '}',
707 | ),
708 |
709 | as_aliasing: $ => prec.left(seq(
710 | 'as',
711 | $._pattern,
712 | optional($.type_annotation)
713 | )),
714 |
715 | as_aliasing_type: $ => seq($._type, 'as', $.type_identifier),
716 |
717 | _as_aliasing_non_function_inline_type: $ =>
718 | prec(2, seq($._non_function_inline_type, 'as', $.type_identifier)),
719 |
720 | assert_expression: $ => prec.left(seq('assert', $.expression)),
721 |
722 | call_expression: $ => prec('call', seq(
723 | field('function', $.primary_expression),
724 | field('arguments', alias($.call_arguments, $.arguments)),
725 | )),
726 |
727 | pipe_expression: $ => prec.left(seq(
728 | choice(
729 | $.primary_expression,
730 | $.block,
731 | ),
732 | choice('->', '|>'),
733 | choice(
734 | $.primary_expression,
735 | $.block,
736 | ),
737 | )),
738 |
739 | module_pack: $ => seq(
740 | 'module',
741 | parenthesize(choice($._module_structure, $.type_identifier_path))
742 | ),
743 |
744 | call_arguments: $ => seq(
745 | '(',
746 | optional($.uncurry),
747 | optional(commaSep1t($._call_argument)),
748 | optional($.partial_application_spread),
749 | ')'
750 | ),
751 |
752 | _call_argument: $ => choice(
753 | seq(
754 | $.expression,
755 | optional($.type_annotation),
756 | ),
757 | $.labeled_argument,
758 | ),
759 |
760 | partial_application_spread: $ => "...",
761 |
762 | labeled_argument: $ => seq(
763 | '~',
764 | field('label', $.value_identifier),
765 | optional(choice(
766 | '?',
767 | seq(
768 | '=',
769 | optional('?'),
770 | field('value', $.expression),
771 | optional(field('type', $.type_annotation)),
772 | ),
773 | )),
774 | ),
775 |
776 | _definition_signature: $ => seq(
777 | field('parameters', $.formal_parameters),
778 | optional(field('return_type', alias($._return_type_annotation, $.type_annotation))),
779 | ),
780 |
781 | _return_type_annotation: $ => seq(
782 | ':',
783 | $._non_function_inline_type,
784 | ),
785 |
786 | formal_parameters: $ => seq(
787 | '(',
788 | optional(commaSep1t($.parameter)),
789 | ')'
790 | ),
791 |
792 | parameter: $ => seq(
793 | optional($.uncurry),
794 | choice(
795 | seq($._pattern, optional($.type_annotation)),
796 | $.labeled_parameter,
797 | $.unit,
798 | $.abstract_type
799 | ),
800 | ),
801 |
802 | labeled_parameter: $ => seq(
803 | '~',
804 | $.value_identifier,
805 | optional($.as_aliasing),
806 | optional($.type_annotation),
807 | optional(field('default_value', $._labeled_parameter_default_value)),
808 | ),
809 |
810 | abstract_type: $ => seq(
811 | 'type',
812 | repeat1($.type_identifier),
813 | ),
814 |
815 | _labeled_parameter_default_value: $ => seq(
816 | '=',
817 | choice(
818 | '?',
819 | $.expression,
820 | ),
821 | ),
822 |
823 | // This negative dynamic precedence ensures that during error recovery,
824 | // unfinished constructs are generally treated as literal expressions,
825 | // not patterns.
826 | _pattern: $ => prec.dynamic(-1, seq(
827 | choice(
828 | $.value_identifier,
829 | $._literal_pattern,
830 | $._destructuring_pattern,
831 | $.polyvar_type_pattern,
832 | $.unit,
833 | $.module_pack,
834 | $.lazy_pattern,
835 | $.parenthesized_pattern,
836 | $.or_pattern,
837 | $.range_pattern,
838 | $.exception_pattern
839 | ),
840 | optional($.as_aliasing),
841 | )),
842 |
843 | parenthesized_pattern: $ => seq('(', $._pattern, optional($.type_annotation), ')'),
844 |
845 | range_pattern: $ => seq(
846 | $._literal_pattern,
847 | '..',
848 | $._literal_pattern,
849 | ),
850 |
851 | or_pattern: $ => prec.left(seq($._pattern, '|', $._pattern)),
852 |
853 | exception_pattern: $ => seq('exception', $._pattern),
854 |
855 | _destructuring_pattern: $ => choice(
856 | $.variant_pattern,
857 | $.polyvar_pattern,
858 | $.record_pattern,
859 | $.tuple_pattern,
860 | $.array_pattern,
861 | $.list_pattern,
862 | ),
863 |
864 | _literal_pattern: $ => choice(
865 | $.string,
866 | $.template_string,
867 | $.character,
868 | $.number,
869 | $.true,
870 | $.false,
871 | ),
872 |
873 | variant_pattern: $ => seq(
874 | optional('?'),
875 | choice(
876 | $.variant_identifier,
877 | $.nested_variant_identifier,
878 | ),
879 | optional(alias($._variant_pattern_parameters, $.formal_parameters))
880 | ),
881 |
882 | _variant_pattern_parameters: $ => seq(
883 | '(',
884 | commaSept($._variant_pattern_parameter),
885 | ')',
886 | ),
887 |
888 | _variant_pattern_parameter: $ => seq(
889 | $._pattern,
890 | optional($.type_annotation),
891 | ),
892 |
893 | polyvar_pattern: $ => seq(
894 | $.polyvar_identifier,
895 | optional(alias($._variant_pattern_parameters, $.formal_parameters))
896 | ),
897 |
898 | record_pattern: $ => seq(
899 | '{',
900 | commaSep1t(seq(
901 | optional("?"),
902 | choice(
903 | $.value_identifier,
904 | $.value_identifier_path,
905 | ),
906 | optional(seq(
907 | ':',
908 | $._pattern,
909 | )),
910 | )),
911 | '}'
912 | ),
913 |
914 | tuple_item_pattern: $ => seq(
915 | $._pattern,
916 | optional($.type_annotation),
917 | ),
918 |
919 | tuple_pattern: $ => seq(
920 | '(',
921 | commaSep2t($.tuple_item_pattern),
922 | ')',
923 | ),
924 |
925 | array_pattern: $ => seq(
926 | '[',
927 | optional(commaSep1t(
928 | $._collection_element_pattern
929 | )),
930 | ']',
931 | ),
932 |
933 | list_pattern: $ => seq(
934 | $._list_constructor,
935 | '{',
936 | optional(commaSep1t($._collection_element_pattern)),
937 | '}',
938 | ),
939 |
940 | _collection_element_pattern: $ => seq(
941 | choice($._pattern, $.spread_pattern),
942 | optional($.as_aliasing)
943 | ),
944 |
945 | spread_pattern: $ => seq(
946 | '...',
947 | choice($.value_identifier, $.list_pattern, $.array_pattern),
948 | ),
949 |
950 | lazy_pattern: $ => seq(
951 | 'lazy',
952 | $._pattern
953 | ),
954 |
955 | _jsx_element: $ => choice($.jsx_element, $.jsx_self_closing_element),
956 |
957 | jsx_element: $ => seq(
958 | field('open_tag', $.jsx_opening_element),
959 | repeat($._jsx_child),
960 | field('close_tag', $.jsx_closing_element)
961 | ),
962 |
963 | jsx_fragment: $ => seq('<', '>', repeat($._jsx_child), '<', '/', '>'),
964 |
965 | jsx_expression: $ => seq(
966 | '{',
967 | optional(choice(
968 | $._one_or_more_statements,
969 | $.spread_element
970 | )),
971 | '}'
972 | ),
973 |
974 | _jsx_child: $ => choice(
975 | $.value_identifier,
976 | $.value_identifier_path,
977 | $.number,
978 | $.string,
979 | $.template_string,
980 | $.character,
981 | $._jsx_element,
982 | $.jsx_fragment,
983 | $.block,
984 | $.spread_element,
985 | $.member_expression
986 | ),
987 |
988 | jsx_opening_element: $ => prec.dynamic(-1, seq(
989 | '<',
990 | field('name', $._jsx_element_name),
991 | repeat(field('attribute', $._jsx_attribute)),
992 | '>'
993 | )),
994 |
995 | _jsx_identifier: $ => alias(
996 | choice($.value_identifier, $.module_identifier),
997 | $.jsx_identifier
998 | ),
999 |
1000 | nested_jsx_identifier: $ => prec('member', seq(
1001 | choice($._jsx_identifier, $.nested_jsx_identifier),
1002 | '.',
1003 | $._jsx_identifier
1004 | )),
1005 |
1006 | _jsx_element_name: $ => choice(
1007 | $._jsx_identifier,
1008 | $.nested_jsx_identifier,
1009 | ),
1010 |
1011 | jsx_closing_element: $ => seq(
1012 | '<',
1013 | '/',
1014 | field('name', $._jsx_element_name),
1015 | '>'
1016 | ),
1017 |
1018 | jsx_self_closing_element: $ => seq(
1019 | '<',
1020 | field('name', $._jsx_element_name),
1021 | repeat(field('attribute', $._jsx_attribute)),
1022 | '/',
1023 | '>'
1024 | ),
1025 |
1026 | _jsx_attribute_name: $ => alias($.value_identifier, $.property_identifier),
1027 |
1028 | _jsx_attribute: $ => choice($.jsx_attribute, $.jsx_expression),
1029 |
1030 | jsx_attribute: $ => seq(
1031 | optional('?'),
1032 | $._jsx_attribute_name,
1033 | optional(seq(
1034 | '=',
1035 | optional('?'),
1036 | $._jsx_attribute_value
1037 | )),
1038 | ),
1039 |
1040 | _jsx_attribute_value: $ => choice(
1041 | $.primary_expression,
1042 | $.jsx_expression,
1043 | ),
1044 |
1045 | mutation_expression: $ => seq(
1046 | $._mutation_lvalue,
1047 | choice('=', ':='),
1048 | $.expression,
1049 | ),
1050 |
1051 | _mutation_lvalue: $ => choice(
1052 | $.value_identifier,
1053 | $.member_expression,
1054 | $.subscript_expression,
1055 | ),
1056 |
1057 | await_expression: $ => seq(
1058 | 'await',
1059 | $.expression,
1060 | ),
1061 |
1062 | decorator: $ => choice(
1063 | alias($._decorator_inline, $.decorator_identifier),
1064 | seq(alias($._decorator, $.decorator_identifier), $.decorator_arguments)
1065 | ),
1066 |
1067 | decorator_arguments: $ => seq(
1068 | '(',
1069 | choice(
1070 | commaSept($.expression),
1071 | $.type_annotation
1072 | ),
1073 | ')',
1074 | ),
1075 |
1076 | subscript_expression: $ => prec.right('member', seq(
1077 | field('object', $.primary_expression),
1078 | '[', field('index', $.expression), ']'
1079 | )),
1080 |
1081 | member_expression: $ => prec('member', seq(
1082 | field('record', $.primary_expression),
1083 | '.',
1084 | optional(seq(
1085 | field('module', seq(repeat(seq($.module_identifier, '.')), $.module_identifier)),
1086 | '.'
1087 | )),
1088 | field('property', alias($.value_identifier, $.property_identifier)),
1089 | )),
1090 |
1091 | spread_element: $ => seq('...', $.expression),
1092 |
1093 | ternary_expression: $ => prec.left(seq(
1094 | field('condition', $.expression),
1095 | '?',
1096 | field('consequence', $.expression),
1097 | ':',
1098 | field('alternative', $.expression)
1099 | )),
1100 |
1101 | for_expression: $ => seq(
1102 | 'for',
1103 | $.value_identifier,
1104 | 'in',
1105 | $.expression,
1106 | choice('to', 'downto'),
1107 | $.expression,
1108 | $.block,
1109 | ),
1110 |
1111 | while_expression: $ => seq(
1112 | 'while',
1113 | $.expression,
1114 | $.block,
1115 | ),
1116 |
1117 | lazy_expression: $ => seq(
1118 | 'lazy',
1119 | $.expression,
1120 | ),
1121 |
1122 | binary_expression: $ => choice(
1123 | ...[
1124 | ['&&', 'binary_and'],
1125 | ['||', 'binary_or'],
1126 | ['++', 'binary_plus'],
1127 | ['+', 'binary_plus'],
1128 | ['+.', 'binary_plus'],
1129 | ['-', 'binary_plus'],
1130 | ['-.', 'binary_plus'],
1131 | ['*', 'binary_times'],
1132 | ['*.', 'binary_times'],
1133 | ['**', 'binary_pow'],
1134 | ['/', 'binary_times'],
1135 | ['/.', 'binary_times'],
1136 | ['<', 'binary_relation'],
1137 | ['<=', 'binary_relation'],
1138 | ['==', 'binary_relation'],
1139 | ['===', 'binary_relation'],
1140 | ['!=', 'binary_relation'],
1141 | ['!==', 'binary_relation'],
1142 | ['>=', 'binary_relation'],
1143 | ['>', 'binary_relation'],
1144 | ].map(([operator, precedence]) =>
1145 | prec.left(precedence, seq(
1146 | field('left', $.expression),
1147 | field('operator', operator),
1148 | field('right', $.expression)
1149 | ))
1150 | )
1151 | ),
1152 |
1153 | coercion_expression: $ => prec.left(
1154 | 'coercion_relation',
1155 | seq(
1156 | field('left', $.expression),
1157 | field('operator', ':>'),
1158 | field('right', $._type_identifier),
1159 | )
1160 | ),
1161 |
1162 | unary_expression: $ => choice(...[
1163 | ['!', 'unary_not'],
1164 | ['-', 'unary_not'],
1165 | ['-.', 'unary_not'],
1166 | ['+', 'unary_not'],
1167 | ['+.', 'unary_not'],
1168 | ].map(([operator, precedence]) =>
1169 | prec.left(precedence, seq(
1170 | field('operator', operator),
1171 | field('argument', $.expression)
1172 | ))
1173 | )),
1174 |
1175 | extension_expression: $ => prec.right(seq(
1176 | repeat1('%'),
1177 | $.extension_identifier,
1178 | optional(
1179 | $._extension_expression_payload,
1180 | )
1181 | )),
1182 |
1183 | _extension_expression_payload: $ => seq(
1184 | '(',
1185 | $._one_or_more_statements,
1186 | // explicit newline here because it won’t be reported otherwise by the scanner
1187 | // because we’re in parens
1188 | optional($._newline),
1189 | ')',
1190 | ),
1191 |
1192 | variant: $ => prec.right(seq(
1193 | choice($.variant_identifier, $.nested_variant_identifier),
1194 | optional(alias($.variant_arguments, $.arguments)),
1195 | )),
1196 |
1197 | nested_variant_identifier: $ => seq(
1198 | $.module_primary_expression,
1199 | '.',
1200 | $.variant_identifier
1201 | ),
1202 |
1203 | variant_arguments: $ => seq(
1204 | '(',
1205 | commaSept(seq(
1206 | $.expression,
1207 | optional($.type_annotation),
1208 | )),
1209 | ')',
1210 | ),
1211 |
1212 | polyvar: $ => prec.right(seq(
1213 | $.polyvar_identifier,
1214 | optional(alias($.variant_arguments, $.arguments)),
1215 | )),
1216 |
1217 | _type_identifier: $ => choice(
1218 | $.type_identifier,
1219 | $.type_identifier_path,
1220 | ".."
1221 | ),
1222 |
1223 | type_identifier_path: $ => seq(
1224 | $.module_primary_expression,
1225 | '.',
1226 | $.type_identifier
1227 | ),
1228 |
1229 | module_expression: $ => choice(
1230 | $.module_primary_expression,
1231 | $.module_type_of,
1232 | $.module_type_constraint,
1233 | ),
1234 |
1235 | module_primary_expression: $ => choice(
1236 | $.parenthesized_module_expression,
1237 | $.module_identifier,
1238 | $.module_identifier_path,
1239 | $.functor_use,
1240 | $.module_unpack,
1241 | ),
1242 |
1243 | parenthesized_module_expression: $ => seq(
1244 | '(',
1245 | $.module_expression,
1246 | optional($.module_type_annotation),
1247 | ')',
1248 | ),
1249 |
1250 | module_identifier_path: $ => path(
1251 | $.module_primary_expression,
1252 | $.module_identifier,
1253 | ),
1254 |
1255 | module_type_of: $ => prec.left(seq(
1256 | 'module',
1257 | 'type',
1258 | 'of',
1259 | choice($.module_expression, $.block)
1260 | )),
1261 |
1262 | _module_type_constraint_with: $ => prec.right(seq(
1263 | 'with',
1264 | sep1(choice('and', 'with'),
1265 | choice($.constrain_module, $.constrain_type)
1266 | ),
1267 | )),
1268 |
1269 | module_type_constraint: $ => prec.left(choice(
1270 | seq($.module_expression, $._module_type_constraint_with),
1271 | seq(
1272 | '(',
1273 | $.module_expression, $._module_type_constraint_with,
1274 | ')',
1275 | $._module_type_constraint_with
1276 | )
1277 | )),
1278 |
1279 | constrain_module: $ => seq(
1280 | 'module',
1281 | $.module_primary_expression,
1282 | choice('=', ':='),
1283 | $.module_primary_expression,
1284 | ),
1285 |
1286 | constrain_type: $ => seq(
1287 | 'type',
1288 | $._type,
1289 | choice('=', ':='),
1290 | $._type,
1291 | ),
1292 |
1293 | functor_use: $ => seq(
1294 | $.module_primary_expression,
1295 | alias($.functor_arguments, $.arguments),
1296 | ),
1297 |
1298 | functor_arguments: $ => seq(
1299 | '(',
1300 | optional(commaSep1t($._functor_argument)),
1301 | ')',
1302 | ),
1303 |
1304 | _functor_argument: $ => choice(
1305 | $.module_expression,
1306 | $.block,
1307 | ),
1308 |
1309 | variant_identifier: $ => /[A-Z][a-zA-Z0-9_']*/,
1310 |
1311 | polyvar_identifier: $ => seq(
1312 | '#',
1313 | choice(
1314 | /[a-zA-Z0-9_']+/,
1315 | seq(
1316 | optional('\\'),
1317 | alias($.string, $.polyvar_string),
1318 | ),
1319 | ),
1320 | ),
1321 |
1322 | type_identifier: $ => choice(
1323 | /[a-z_'][a-zA-Z0-9_']*/,
1324 | $._escape_identifier,
1325 | ),
1326 |
1327 | value_identifier: $ => choice(
1328 | /[a-z_][a-zA-Z0-9_']*/,
1329 | $._reserved_identifier,
1330 | $._escape_identifier,
1331 | ),
1332 |
1333 | _escape_identifier: $ => token(seq('\\"', /[^"]+/, '"')),
1334 |
1335 | module_identifier: $ => /[A-Z][a-zA-Z0-9_']*/,
1336 |
1337 | extension_identifier: $ => /[a-zA-Z0-9_\.]+/,
1338 |
1339 | number: $ => {
1340 | // OCaml: https://github.com/tree-sitter/tree-sitter-ocaml/blob/f1106bf834703f1f2f795da1a3b5f8f40174ffcc/ocaml/grammar.js#L26
1341 | const hex_literal = seq(
1342 | optional(choice('-', '+')),
1343 | /0[xX][0-9A-Fa-f][0-9A-Fa-f_]*(\.[0-9A-Fa-f_]*)?([pP][+\-]?[0-9][0-9_]*)?[g-zG-Z]?/
1344 | )
1345 |
1346 | const decimal_digits = /\d(_?\d)*/
1347 | const signed_integer = seq(optional(choice('-', '+')), decimal_digits)
1348 | const exponent_part = seq(choice('e', 'E'), signed_integer)
1349 |
1350 | const binary_literal = seq(choice('0b', '0B'), /[0-1](_?[0-1])*/)
1351 |
1352 | const octal_literal = seq(choice('0o', '0O'), /[0-7](_?[0-7])*/)
1353 |
1354 | const bigint_literal = seq(choice(hex_literal, binary_literal, octal_literal, decimal_digits), 'n')
1355 |
1356 | const decimal_integer_literal = choice(
1357 | repeat1('0'),
1358 | seq(repeat('0'), /[1-9]/, optional(seq(optional('_'), decimal_digits)))
1359 | )
1360 |
1361 | const decimal_literal = seq(
1362 | optional(choice('-', '+')),
1363 | choice(
1364 | seq(decimal_integer_literal, '.', optional(decimal_digits), optional(exponent_part)),
1365 | seq('.', decimal_digits, optional(exponent_part)),
1366 | seq(decimal_integer_literal, exponent_part),
1367 | decimal_digits,
1368 | )
1369 | )
1370 |
1371 | const int_32_64 = seq(
1372 | optional(choice('-', '+')),
1373 | choice(decimal_integer_literal, binary_literal, octal_literal, hex_literal),
1374 | choice('L', 'l')
1375 | )
1376 |
1377 | return token(choice(
1378 | hex_literal,
1379 | decimal_literal,
1380 | binary_literal,
1381 | octal_literal,
1382 | bigint_literal,
1383 | int_32_64
1384 | ))
1385 | },
1386 |
1387 | unit: $ => seq('(', ')'),
1388 | unit_type: $ => 'unit',
1389 |
1390 | true: $ => 'true',
1391 | false: $ => 'false',
1392 |
1393 | string: $ => seq(
1394 | '"',
1395 | repeat(choice(
1396 | alias($.unescaped_double_string_fragment, $.string_fragment),
1397 | $.escape_sequence
1398 | )),
1399 | '"'
1400 | ),
1401 |
1402 | // Workaround to https://github.com/tree-sitter/tree-sitter/issues/1156
1403 | // We give names to the token() constructs containing a regexp
1404 | // so as to obtain a node in the CST.
1405 | //
1406 | unescaped_double_string_fragment: $ =>
1407 | token.immediate(prec(1, /[^"\\]+/)),
1408 |
1409 | escape_sequence: $ => token.immediate(seq(
1410 | '\\',
1411 | choice(
1412 | /[^xu0-7]/,
1413 | /[0-7]{1,3}/,
1414 | /x[0-9a-fA-F]{2}/,
1415 | /u[0-9a-fA-F]{4}/,
1416 | /u\{[0-9a-fA-F]+\}/
1417 | )
1418 | )),
1419 |
1420 | template_string: $ => seq(
1421 | token(seq(
1422 | optional(
1423 | choice(
1424 | /[a-z_][a-zA-Z0-9_']*/,
1425 | // escape_sequence
1426 | seq('\\"', /[^"]+/, '"'),
1427 | )
1428 | ),
1429 | '`',
1430 | )),
1431 | optional($.template_string_content),
1432 | '`'
1433 | ),
1434 |
1435 | template_string_content: $ =>
1436 | repeat1(
1437 | choice(
1438 | $._template_chars,
1439 | $.template_substitution,
1440 | /\s/,
1441 | choice(
1442 | alias('\\`', $.escape_sequence),
1443 | $.escape_sequence,
1444 | )
1445 | ),
1446 | ),
1447 |
1448 | template_substitution: $ => choice(
1449 | seq('$', $.value_identifier),
1450 | seq('${', $.expression, '}'),
1451 | ),
1452 |
1453 | character: $ => seq(
1454 | "'",
1455 | repeat(choice(/[^\\']/, $.escape_sequence)),
1456 | "'"
1457 | ),
1458 |
1459 | _unescaped_template_string_fragment: $ =>
1460 | token.immediate(prec(1, /[^`\\\$]+/)),
1461 |
1462 | lparen: $ => alias($._lparen, '('),
1463 | rparen: $ => alias($._rparen, ')'),
1464 | uncurry: $ => '.',
1465 |
1466 | _reserved_identifier: $ => choice(
1467 | 'async',
1468 | 'unpack'
1469 | )
1470 | },
1471 | });
1472 |
1473 | function barSep1(rule) {
1474 | return seq(rule, repeat(seq('|', rule)));
1475 | }
1476 |
1477 | function commaSep1(rule) {
1478 | return seq(rule, repeat(seq(',', rule)));
1479 | }
1480 |
1481 | function commaSep2(rule) {
1482 | return seq(rule, ',', commaSep1(rule));
1483 | }
1484 |
1485 | function commaSep1t(rule) {
1486 | return seq(commaSep1(rule), optional(','));
1487 | }
1488 |
1489 | function commaSep2t(rule) {
1490 | return seq(commaSep2(rule), optional(','));
1491 | }
1492 |
1493 | function commaSep(rule) {
1494 | return optional(commaSep1(rule));
1495 | }
1496 |
1497 | function commaSept(rule) {
1498 | return optional(commaSep1t(rule));
1499 | }
1500 |
1501 | function sep1(delimiter, rule) {
1502 | return seq(rule, repeat(seq(delimiter, rule)))
1503 | }
1504 |
1505 | function path(prefix, final) {
1506 | return choice(final, seq(prefix, '.', final))
1507 | }
1508 |
1509 | function parenthesize(rule) {
1510 | return seq('(', rule, ')')
1511 | }
1512 |
--------------------------------------------------------------------------------