├── .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 |
179 | { 180 | let href = "https://github.com" 181 | {React.string("Hello")} 182 | } 183 |
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 | --------------------------------------------------------------------------------