├── bindings ├── python │ ├── tree_sitter_cuda │ │ ├── py.typed │ │ ├── __init__.pyi │ │ ├── __init__.py │ │ └── binding.c │ └── tests │ │ └── test_binding.py ├── node │ ├── binding_test.js │ ├── index.js │ ├── index.d.ts │ └── binding.cc ├── swift │ ├── TreeSitterCUDA │ │ └── cuda.h │ └── TreeSitterCUDATests │ │ └── TreeSitterCUDATests.swift ├── c │ ├── tree_sitter │ │ └── tree-sitter-cuda.h │ └── tree-sitter-cuda.pc.in ├── go │ ├── binding.go │ └── binding_test.go └── rust │ ├── build.rs │ └── lib.rs ├── go.mod ├── queries └── highlights.scm ├── test └── corpus │ ├── c │ ├── crlf.txt │ ├── types.txt │ ├── microsoft.txt │ ├── ambiguities.txt │ ├── preprocessor.txt │ └── statements.txt │ ├── microsoft.txt │ ├── ambiguities.txt │ ├── types.txt │ ├── cuda.txt │ ├── definitions.txt │ ├── statements.txt │ └── concepts.txt ├── .github ├── workflows │ ├── update.yml │ ├── publish.yml │ └── ci.yml └── dependabot.yml ├── .gitignore ├── Package.resolved ├── .editorconfig ├── Cargo.toml ├── pyproject.toml ├── tree-sitter.json ├── binding.gyp ├── .gitattributes ├── LICENSE ├── README.md ├── src ├── tree_sitter │ ├── alloc.h │ ├── parser.h │ └── array.h └── scanner.c ├── Package.swift ├── package.json ├── grammar.js ├── setup.py ├── CMakeLists.txt ├── Makefile ├── go.sum ├── examples ├── marker-index.cuh └── rule.cu └── Cargo.lock /bindings/python/tree_sitter_cuda/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_cuda/__init__.pyi: -------------------------------------------------------------------------------- 1 | def language() -> object: ... 2 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_cuda/__init__.py: -------------------------------------------------------------------------------- 1 | """CUDA grammar for tree-sitter""" 2 | 3 | from ._binding import language 4 | 5 | __all__ = ["language"] 6 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tree-sitter-grammars/tree-sitter-cuda 2 | 3 | go 1.22 4 | 5 | require github.com/tree-sitter/go-tree-sitter v0.24.0 6 | 7 | require github.com/mattn/go-pointer v0.0.1 // indirect 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 | -------------------------------------------------------------------------------- /queries/highlights.scm: -------------------------------------------------------------------------------- 1 | ; inherits: cpp 2 | 3 | [ 4 | "<<<" 5 | ">>>" 6 | ] @punctuation.bracket 7 | 8 | [ 9 | "__host__" 10 | "__device__" 11 | "__global__" 12 | "__managed__" 13 | "__forceinline__" 14 | "__noinline__" 15 | ] @keyword.modifier 16 | 17 | "__launch_bounds__" @keyword.modifier 18 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterCUDA/cuda.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_CUDA_H_ 2 | #define TREE_SITTER_CUDA_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | const TSLanguage *tree_sitter_cuda(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_CUDA_H_ 17 | -------------------------------------------------------------------------------- /bindings/c/tree_sitter/tree-sitter-cuda.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_CUDA_H_ 2 | #define TREE_SITTER_CUDA_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | const TSLanguage *tree_sitter_cuda(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_CUDA_H_ 17 | -------------------------------------------------------------------------------- /bindings/c/tree-sitter-cuda.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ 3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 4 | 5 | Name: tree-sitter-cuda 6 | Description: @PROJECT_DESCRIPTION@ 7 | URL: @PROJECT_HOMEPAGE_URL@ 8 | Version: @PROJECT_VERSION@ 9 | Libs: -L${libdir} -ltree-sitter-cuda 10 | Cflags: -I${includedir} 11 | -------------------------------------------------------------------------------- /test/corpus/c/crlf.txt: -------------------------------------------------------------------------------- 1 | ============================================ 2 | Line comments with escaped CRLF line endings 3 | ============================================ 4 | 5 | // hello \ 6 | this is still a comment 7 | this_is_not a_comment; 8 | 9 | --- 10 | 11 | (translation_unit 12 | (comment) 13 | (declaration (type_identifier) (identifier))) 14 | -------------------------------------------------------------------------------- /bindings/go/binding.go: -------------------------------------------------------------------------------- 1 | package tree_sitter_cuda 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_cuda()) 15 | } 16 | -------------------------------------------------------------------------------- /bindings/go/binding_test.go: -------------------------------------------------------------------------------- 1 | package tree_sitter_cuda_test 2 | 3 | import ( 4 | "testing" 5 | 6 | tree_sitter "github.com/tree-sitter/go-tree-sitter" 7 | tree_sitter_cuda "github.com/tree-sitter-grammars/tree-sitter-cuda/bindings/go" 8 | ) 9 | 10 | func TestCanLoadGrammar(t *testing.T) { 11 | language := tree_sitter.NewLanguage(tree_sitter_cuda.Language()) 12 | if language == nil { 13 | t.Errorf("Error loading CUDA grammar") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | name: Update parser 2 | 3 | on: 4 | pull_request: 5 | 6 | permissions: 7 | contents: write 8 | pull-requests: write 9 | 10 | concurrency: 11 | group: ${{github.workflow}}-${{github.ref}} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | regenerate: 16 | uses: tree-sitter/workflows/.github/workflows/regenerate.yml@main 17 | if: github.actor == 'dependabot[bot]' 18 | with: 19 | abi-version: 14 20 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterCUDATests/TreeSitterCUDATests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import SwiftTreeSitter 3 | import TreeSitterCUDA 4 | 5 | final class TreeSitterCUDATests: XCTestCase { 6 | func testCanLoadGrammar() throws { 7 | let parser = Parser() 8 | let language = Language(language: tree_sitter_cuda()) 9 | XCTAssertNoThrow(try parser.setLanguage(language), 10 | "Error loading CUDA grammar") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /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-cuda.node`) 7 | : require("node-gyp-build")(root); 8 | 9 | try { 10 | module.exports.nodeTypeInfo = require("../../src/node-types.json"); 11 | } catch (_) {} 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /bindings/node/binding.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | extern "C" TSLanguage *tree_sitter_cuda(); 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_cuda()); 14 | language.TypeTag(&LANGUAGE_TYPE_TAG); 15 | exports["language"] = language; 16 | return exports; 17 | } 18 | 19 | NODE_API_MODULE(tree_sitter_cuda_binding, Init) 20 | -------------------------------------------------------------------------------- /bindings/python/tests/test_binding.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import tree_sitter 4 | import tree_sitter_cuda 5 | 6 | 7 | class TestLanguage(TestCase): 8 | def test_can_load_grammar(self): 9 | try: 10 | tree_sitter.Language(tree_sitter_cuda.language()) 11 | except Exception: 12 | self.fail("Error loading CUDA grammar") 13 | 14 | def test_parse(self): 15 | lang = tree_sitter.Language(tree_sitter_cuda.language()) 16 | parser = tree_sitter.Parser(lang) 17 | tree = parser.parse(b"int main() { return 0; }") 18 | self.assertIsNotNone(tree) 19 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | day: sunday 8 | commit-message: 9 | prefix: ci 10 | labels: 11 | - dependencies 12 | groups: 13 | actions: 14 | patterns: ["*"] 15 | 16 | - package-ecosystem: npm 17 | versioning-strategy: increase 18 | directory: / 19 | schedule: 20 | interval: weekly 21 | day: sunday 22 | commit-message: 23 | prefix: build(deps) 24 | labels: 25 | - dependencies 26 | groups: 27 | npm: 28 | patterns: ["*"] 29 | -------------------------------------------------------------------------------- /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-cuda"); 21 | } 22 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "SwiftTreeSitter", 6 | "repositoryURL": "https://github.com/tree-sitter/swift-tree-sitter", 7 | "state": { 8 | "branch": null, 9 | "revision": "36aa61d1b531f744f35229f010efba9c6d6cbbdd", 10 | "version": "0.9.0" 11 | } 12 | }, 13 | { 14 | "package": "TreeSitter", 15 | "repositoryURL": "https://github.com/tree-sitter/tree-sitter", 16 | "state": { 17 | "branch": null, 18 | "revision": "d97db6d63507eb62c536bcb2c4ac7d70c8ec665e", 19 | "version": "0.23.2" 20 | } 21 | } 22 | ] 23 | }, 24 | "version": 1 25 | } 26 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /test/corpus/microsoft.txt: -------------------------------------------------------------------------------- 1 | ================================ 2 | declaration specs 3 | ================================ 4 | 5 | struct __declspec(dllexport) s2 6 | { 7 | }; 8 | 9 | union __declspec(noinline) u2 { 10 | }; 11 | 12 | class __declspec(uuid) u2 { 13 | }; 14 | 15 | --- 16 | 17 | (translation_unit 18 | (struct_specifier 19 | (ms_declspec_modifier 20 | (identifier)) 21 | name: (type_identifier) 22 | body: (field_declaration_list)) 23 | (union_specifier 24 | (ms_declspec_modifier 25 | (identifier)) 26 | name: (type_identifier) 27 | body: (field_declaration_list)) 28 | (class_specifier 29 | (ms_declspec_modifier 30 | (identifier)) 31 | name: (type_identifier) 32 | body: (field_declaration_list))) 33 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish package 2 | 3 | on: 4 | push: 5 | tags: ["*"] 6 | 7 | jobs: 8 | release: 9 | uses: tree-sitter/workflows/.github/workflows/release.yml@main 10 | with: 11 | attestations: true 12 | permissions: 13 | contents: write 14 | id-token: write 15 | attestations: write 16 | npm: 17 | uses: tree-sitter/workflows/.github/workflows/package-npm.yml@main 18 | secrets: 19 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 20 | crates: 21 | uses: tree-sitter/workflows/.github/workflows/package-crates.yml@main 22 | secrets: 23 | CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_TOKEN}} 24 | pypi: 25 | uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@main 26 | secrets: 27 | PYPI_API_TOKEN: ${{secrets.PYPI_TOKEN}} 28 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tree-sitter-cuda" 3 | description = "CUDA grammar for tree-sitter" 4 | version = "0.21.1" 5 | authors = ["Stephan Seitz"] 6 | license = "MIT" 7 | readme = "README.md" 8 | keywords = ["incremental", "parsing", "tree-sitter", "cuda"] 9 | categories = ["parser-implementations", "parsing", "text-editors"] 10 | repository = "https://github.com/tree-sitter-grammars/tree-sitter-cuda" 11 | edition = "2021" 12 | autoexamples = false 13 | 14 | build = "bindings/rust/build.rs" 15 | include = [ 16 | "bindings/rust/*", 17 | "grammar.js", 18 | "queries/*", 19 | "src/*", 20 | "tree-sitter.json", 21 | "LICENSE", 22 | ] 23 | 24 | [lib] 25 | path = "bindings/rust/lib.rs" 26 | 27 | [dependencies] 28 | tree-sitter-language = "0.1" 29 | 30 | [build-dependencies] 31 | cc = "1.2" 32 | 33 | [dev-dependencies] 34 | tree-sitter = "0.25.4" 35 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "tree-sitter-cuda" 7 | description = "CUDA grammar for tree-sitter" 8 | version = "0.21.1" 9 | keywords = ["incremental", "parsing", "tree-sitter", "cuda"] 10 | classifiers = [ 11 | "Intended Audience :: Developers", 12 | "Topic :: Software Development :: Compilers", 13 | "Topic :: Text Processing :: Linguistic", 14 | "Typing :: Typed", 15 | ] 16 | authors = [{ name = "Stephan Seitz" }] 17 | requires-python = ">=3.10" 18 | license.text = "MIT" 19 | readme = "README.md" 20 | 21 | [project.urls] 22 | Homepage = "https://github.com/tree-sitter-grammars/tree-sitter-cuda" 23 | 24 | [project.optional-dependencies] 25 | core = ["tree-sitter~=0.24"] 26 | 27 | [tool.cibuildwheel] 28 | build = "cp310-*" 29 | build-frontend = "build" 30 | -------------------------------------------------------------------------------- /tree-sitter.json: -------------------------------------------------------------------------------- 1 | { 2 | "grammars": [ 3 | { 4 | "name": "cuda", 5 | "camelcase": "CUDA", 6 | "title": "CUDA", 7 | "scope": "source.cpp", 8 | "path": ".", 9 | "file-types": [ 10 | "cu", 11 | "cuh" 12 | ], 13 | "highlights": [ 14 | "node_modules/tree-sitter-c/queries/highlights.scm", 15 | "node_modules/tree-sitter-cpp/queries/highlights.scm", 16 | "queries/highlights.scm" 17 | ], 18 | "class-name": "TreeSitterCUDA" 19 | } 20 | ], 21 | "metadata": { 22 | "version": "0.21.1", 23 | "license": "MIT", 24 | "description": "CUDA grammar for tree-sitter", 25 | "authors": [ 26 | { 27 | "name": "Stephan Seitz" 28 | } 29 | ], 30 | "links": { 31 | "repository": "https://github.com/tree-sitter-grammars/tree-sitter-cuda" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_cuda_binding", 5 | "dependencies": [ 6 | " 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | TSLanguage *tree_sitter_cuda(void); 6 | 7 | static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { 8 | return PyCapsule_New(tree_sitter_cuda(), "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 | -------------------------------------------------------------------------------- /.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) 2014 Max Brunsfield 4 | Copyright (c) 2021 Stephan Seitz 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tree-sitter-cuda 2 | ================== 3 | 4 | [![CI][ci]](https://github.com/tree-sitter-grammars/tree-sitter-cuda/actions/workflows/ci.yml) 5 | [![discord][discord]](https://discord.gg/w7nTvsVJhm) 6 | [![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org) 7 | [![npm][npm]](https://www.npmjs.com/package/tree-sitter-cuda) 8 | [![crates][crates]](https://crates.io/crates/tree-sitter-cuda) 9 | [![pypi][pypi]](https://pypi.org/project/tree-sitter-cuda) 10 | 11 | This is a extension of [tree-sitter-cpp](https://github.com/tree-sitter/tree-sitter-cpp) to support 12 | CUDA storage and function specifiers (`__shared__`, `__device__`) and its kernel call syntax. 13 | 14 | [ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter-grammars/tree-sitter-cuda/ci.yml?logo=github&label=CI 15 | [discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord 16 | [matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix 17 | [npm]: https://img.shields.io/npm/v/tree-sitter-cuda?logo=npm 18 | [crates]: https://img.shields.io/crates/v/tree-sitter-cuda?logo=rust 19 | [pypi]: https://img.shields.io/pypi/v/tree-sitter-cuda?logo=pypi&logoColor=ffd242 20 | -------------------------------------------------------------------------------- /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: "TreeSitterCUDA", 13 | products: [ 14 | .library(name: "TreeSitterCUDA", targets: ["TreeSitterCUDA"]), 15 | ], 16 | dependencies: [ 17 | .package(name: "SwiftTreeSitter", url: "https://github.com/tree-sitter/swift-tree-sitter", from: "0.9.0"), 18 | ], 19 | targets: [ 20 | .target( 21 | name: "TreeSitterCUDA", 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: "TreeSitterCUDATests", 33 | dependencies: [ 34 | "SwiftTreeSitter", 35 | "TreeSitterCUDA", 36 | ], 37 | path: "bindings/swift/TreeSitterCUDATests" 38 | ) 39 | ], 40 | cLanguageStandard: .c11 41 | ) 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-cuda", 3 | "version": "0.21.1", 4 | "description": "CUDA grammar for tree-sitter", 5 | "repository": "https://github.com/tree-sitter-grammars/tree-sitter-cuda", 6 | "license": "MIT", 7 | "author": { 8 | "name": "Stephan Seitz" 9 | }, 10 | "main": "bindings/node", 11 | "types": "bindings/node", 12 | "keywords": [ 13 | "incremental", 14 | "parsing", 15 | "tree-sitter", 16 | "cuda" 17 | ], 18 | "files": [ 19 | "grammar.js", 20 | "tree-sitter.json", 21 | "binding.gyp", 22 | "prebuilds/**", 23 | "bindings/node/*", 24 | "queries/*", 25 | "src/**", 26 | "*.wasm" 27 | ], 28 | "dependencies": { 29 | "node-addon-api": "^8.5.0", 30 | "node-gyp-build": "^4.8.4", 31 | "tree-sitter-c": "0.24.1", 32 | "tree-sitter-cpp": "0.23.4" 33 | }, 34 | "devDependencies": { 35 | "prebuildify": "^6.0.1", 36 | "tree-sitter-cli": "^0.25.9" 37 | }, 38 | "peerDependencies": { 39 | "tree-sitter": "^0.22.4" 40 | }, 41 | "peerDependenciesMeta": { 42 | "tree-sitter": { 43 | "optional": true 44 | } 45 | }, 46 | "overrides": { 47 | "tree-sitter": "^0.22.4" 48 | }, 49 | "scripts": { 50 | "install": "node-gyp-build", 51 | "prestart": "tree-sitter build --wasm", 52 | "start": "tree-sitter playground", 53 | "test": "node --test bindings/node/*_test.js" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | const CPP = require("tree-sitter-cpp/grammar") 2 | 3 | module.exports = grammar(CPP, { 4 | name: 'cuda', 5 | 6 | rules: { 7 | _top_level_item: (_, original) => original, 8 | 9 | _declaration_modifiers: ($, original) => 10 | choice( 11 | $.launch_bounds, 12 | '__device__', 13 | '__host__', 14 | prec(10, '__global__'), 15 | '__forceinline__', 16 | '__noinline__', 17 | original 18 | ), 19 | 20 | delete_expression: (_, original) => prec.left(original), 21 | 22 | expression: ($, original) => choice( 23 | original, 24 | alias(prec(10, $.kernel_call_expression), $.call_expression), 25 | ), 26 | 27 | kernel_call_expression: ($) => prec(1,seq( 28 | field('function', $.expression), 29 | $.kernel_call_syntax, 30 | field('arguments', $.argument_list), 31 | )), 32 | 33 | kernel_call_syntax: $ => seq(alias(rep3('<'), '<<<'), $.expression, repeat(seq(",", $.expression)), alias(rep3('>'), '>>>')), 34 | 35 | type_qualifier: (_, original) => choice( 36 | original, 37 | '__shared__', 38 | '__global__', 39 | '__local__', 40 | '__constant__', 41 | '__managed__', 42 | '__grid_constant__', 43 | ), 44 | 45 | launch_bounds: $ => seq("__launch_bounds__", "(", $.expression, optional(seq(",", $.expression),), ")"), 46 | } 47 | }); 48 | 49 | function rep3(obj) { 50 | return token(seq(obj, /\s*/, obj, /\s*/, obj)); 51 | } 52 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides CUDA 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 | //! __global__ void cuda_hello(){ 9 | //! printf("Hello World from GPU!\n"); 10 | //! } 11 | //! 12 | //! int main() { 13 | //! cuda_hello<<<1,1>>>(); 14 | //! return 0; 15 | //! } 16 | //! "#; 17 | //! let mut parser = tree_sitter::Parser::new(); 18 | //! let language = tree_sitter_cuda::LANGUAGE; 19 | //! parser 20 | //! .set_language(&language.into()) 21 | //! .expect("Error loading CUDA parser"); 22 | //! let tree = parser.parse(code, None).unwrap(); 23 | //! assert!(!tree.root_node().has_error()); 24 | //! ``` 25 | //! 26 | //! [`Parser`]: https://docs.rs/tree-sitter/0.25.4/tree_sitter/struct.Parser.html 27 | //! [tree-sitter]: https://tree-sitter.github.io/ 28 | 29 | use tree_sitter_language::LanguageFn; 30 | 31 | extern "C" { 32 | fn tree_sitter_cuda() -> *const (); 33 | } 34 | 35 | /// The tree-sitter [`LanguageFn`] for this grammar. 36 | pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_cuda) }; 37 | 38 | /// The content of the [`node-types.json`] file for this grammar. 39 | /// 40 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types 41 | pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); 42 | 43 | /// The highlights queries for this grammar. 44 | pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | #[test] 49 | fn test_can_load_grammar() { 50 | let mut parser = tree_sitter::Parser::new(); 51 | parser 52 | .set_language(&super::LANGUAGE.into()) 53 | .expect("Error loading CUDA parser"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from os import name, path 2 | from sysconfig import get_config_var 3 | 4 | from setuptools import Extension, find_packages, setup 5 | from setuptools.command.build import build 6 | from setuptools.command.egg_info import egg_info 7 | from wheel.bdist_wheel import bdist_wheel 8 | 9 | sources = [ 10 | "bindings/python/tree_sitter_cuda/binding.c", 11 | "src/parser.c", 12 | ] 13 | if path.exists("src/scanner.c"): 14 | sources.append("src/scanner.c") 15 | 16 | macros: list[tuple[str, str | None]] = [ 17 | ("PY_SSIZE_T_CLEAN", None), 18 | ("TREE_SITTER_HIDE_SYMBOLS", None), 19 | ] 20 | if limited_api := not get_config_var("Py_GIL_DISABLED"): 21 | macros.append(("Py_LIMITED_API", "0x030A0000")) 22 | 23 | if name != "nt": 24 | cflags = ["-std=c11", "-fvisibility=hidden"] 25 | else: 26 | cflags = ["/std:c11", "/utf-8"] 27 | 28 | 29 | class Build(build): 30 | def run(self): 31 | if path.isdir("queries"): 32 | dest = path.join(self.build_lib, "tree_sitter_cuda", "queries") 33 | self.copy_tree("queries", dest) 34 | super().run() 35 | 36 | 37 | class BdistWheel(bdist_wheel): 38 | def get_tag(self): 39 | python, abi, platform = super().get_tag() 40 | if python.startswith("cp"): 41 | python, abi = "cp310", "abi3" 42 | return python, abi, platform 43 | 44 | 45 | class EggInfo(egg_info): 46 | def find_sources(self): 47 | super().find_sources() 48 | self.filelist.recursive_include("queries", "*.scm") 49 | self.filelist.include("src/tree_sitter/*.h") 50 | 51 | 52 | setup( 53 | packages=find_packages("bindings/python"), 54 | package_dir={"": "bindings/python"}, 55 | package_data={ 56 | "tree_sitter_cuda": ["*.pyi", "py.typed"], 57 | "tree_sitter_cuda.queries": ["*.scm"], 58 | }, 59 | ext_package="tree_sitter_cuda", 60 | ext_modules=[ 61 | Extension( 62 | name="_binding", 63 | sources=sources, 64 | extra_compile_args=cflags, 65 | define_macros=macros, 66 | include_dirs=["src"], 67 | py_limited_api=limited_api, 68 | ) 69 | ], 70 | cmdclass={ 71 | "build": Build, 72 | "bdist_wheel": BdistWheel, 73 | "egg_info": EggInfo, 74 | }, 75 | zip_safe=False 76 | ) 77 | -------------------------------------------------------------------------------- /test/corpus/c/types.txt: -------------------------------------------------------------------------------- 1 | ======================================== 2 | Primitive types 3 | ======================================== 4 | 5 | int a; 6 | uint8_t a; 7 | uint16_t a; 8 | uint32_t a; 9 | uint64_t a; 10 | uintptr_t a; 11 | 12 | int8_t a; 13 | int16_t a; 14 | int32_t a; 15 | int64_t a; 16 | intptr_t a; 17 | 18 | char16_t a; 19 | char32_t a; 20 | 21 | size_t a; 22 | ssize_t a; 23 | 24 | --- 25 | 26 | (translation_unit 27 | (declaration (primitive_type) (identifier)) 28 | (declaration (primitive_type) (identifier)) 29 | (declaration (primitive_type) (identifier)) 30 | (declaration (primitive_type) (identifier)) 31 | (declaration (primitive_type) (identifier)) 32 | (declaration (primitive_type) (identifier)) 33 | (declaration (primitive_type) (identifier)) 34 | (declaration (primitive_type) (identifier)) 35 | (declaration (primitive_type) (identifier)) 36 | (declaration (primitive_type) (identifier)) 37 | (declaration (primitive_type) (identifier)) 38 | (declaration (primitive_type) (identifier)) 39 | (declaration (primitive_type) (identifier)) 40 | (declaration (primitive_type) (identifier)) 41 | (declaration (primitive_type) (identifier))) 42 | 43 | ======================================== 44 | Type modifiers 45 | ======================================== 46 | 47 | void f(unsigned); 48 | void f(unsigned int); 49 | void f(signed long int); 50 | void f(unsigned v1); 51 | void f(unsigned long v2); 52 | 53 | --- 54 | 55 | (translation_unit 56 | (declaration 57 | (primitive_type) 58 | (function_declarator 59 | (identifier) 60 | (parameter_list (parameter_declaration (sized_type_specifier))))) 61 | (declaration 62 | (primitive_type) 63 | (function_declarator 64 | (identifier) 65 | (parameter_list (parameter_declaration (sized_type_specifier (primitive_type)))))) 66 | (declaration 67 | (primitive_type) 68 | (function_declarator 69 | (identifier) 70 | (parameter_list (parameter_declaration (sized_type_specifier (primitive_type)))))) 71 | (declaration 72 | (primitive_type) 73 | (function_declarator 74 | (identifier) 75 | (parameter_list (parameter_declaration (sized_type_specifier) (identifier))))) 76 | (declaration 77 | (primitive_type) 78 | (function_declarator 79 | (identifier) 80 | (parameter_list (parameter_declaration (sized_type_specifier) (identifier)))))) 81 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | project(tree-sitter-cuda 4 | VERSION "0.21.1" 5 | DESCRIPTION "CUDA grammar for tree-sitter" 6 | HOMEPAGE_URL "https://github.com/tree-sitter-grammars/tree-sitter-cuda" 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-cuda src/parser.c) 28 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c) 29 | target_sources(tree-sitter-cuda PRIVATE src/scanner.c) 30 | endif() 31 | target_include_directories(tree-sitter-cuda 32 | PRIVATE src 33 | INTERFACE $ 34 | $) 35 | 36 | target_compile_definitions(tree-sitter-cuda PRIVATE 37 | $<$:TREE_SITTER_REUSE_ALLOCATOR> 38 | $<$:TREE_SITTER_DEBUG>) 39 | 40 | set_target_properties(tree-sitter-cuda 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-cuda.pc.in 48 | "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-cuda.pc" @ONLY) 49 | 50 | include(GNUInstallDirs) 51 | 52 | install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bindings/c/tree_sitter" 53 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 54 | FILES_MATCHING PATTERN "*.h") 55 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-cuda.pc" 56 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig") 57 | install(TARGETS tree-sitter-cuda 58 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") 59 | 60 | file(GLOB QUERIES queries/*.scm) 61 | install(FILES ${QUERIES} 62 | DESTINATION "${CMAKE_INSTALL_DATADIR}/tree-sitter/queries/cuda") 63 | 64 | add_custom_target(ts-test "${TREE_SITTER_CLI}" test 65 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 66 | COMMENT "tree-sitter test") 67 | -------------------------------------------------------------------------------- /test/corpus/ambiguities.txt: -------------------------------------------------------------------------------- 1 | ================================================ 2 | template functions vs relational expressions 3 | ================================================ 4 | 5 | T1 a = b < c > d; 6 | T2 e = f(g); 7 | int a = std::get<0>(t); 8 | 9 | --- 10 | 11 | (translation_unit 12 | (declaration 13 | (type_identifier) 14 | (init_declarator 15 | (identifier) 16 | (binary_expression 17 | (binary_expression (identifier) (identifier)) 18 | (identifier)))) 19 | (declaration 20 | (type_identifier) 21 | (init_declarator 22 | (identifier) 23 | (call_expression 24 | (template_function (identifier) (template_argument_list 25 | (type_descriptor (type_identifier)))) 26 | (argument_list (identifier))))) 27 | (declaration 28 | (primitive_type) 29 | (init_declarator 30 | (identifier) 31 | (call_expression 32 | (qualified_identifier 33 | (namespace_identifier) 34 | (template_function 35 | (identifier) 36 | (template_argument_list (number_literal)))) 37 | (argument_list (identifier)))))) 38 | 39 | ================================================= 40 | function declarations vs variable initializations 41 | ================================================= 42 | 43 | // Function declarations 44 | T1 a(T2 *b); 45 | T3 c(T4 &d, T5 &&e); 46 | 47 | // Variable declarations with initializers 48 | T7 f(g.h); 49 | T6 i{j}; 50 | 51 | --- 52 | 53 | (translation_unit 54 | (comment) 55 | (declaration 56 | (type_identifier) 57 | (function_declarator 58 | (identifier) 59 | (parameter_list (parameter_declaration (type_identifier) (pointer_declarator (identifier)))))) 60 | (declaration 61 | (type_identifier) 62 | (function_declarator 63 | (identifier) 64 | (parameter_list 65 | (parameter_declaration (type_identifier) (reference_declarator (identifier))) 66 | (parameter_declaration (type_identifier) (reference_declarator (identifier)))))) 67 | 68 | (comment) 69 | (declaration 70 | (type_identifier) 71 | (init_declarator 72 | (identifier) 73 | (argument_list (field_expression (identifier) (field_identifier))))) 74 | (declaration 75 | (type_identifier) 76 | (init_declarator 77 | (identifier) 78 | (initializer_list (identifier))))) 79 | 80 | ================================================ 81 | template classes vs relational expressions 82 | ================================================ 83 | 84 | int main() { 85 | T1 v1; 86 | T1 v2 = v3; 87 | } 88 | 89 | --- 90 | 91 | (translation_unit (function_definition 92 | (primitive_type) 93 | (function_declarator (identifier) (parameter_list)) 94 | (compound_statement 95 | (declaration 96 | (template_type (type_identifier) 97 | (template_argument_list (type_descriptor (type_identifier)))) 98 | (identifier)) 99 | (declaration 100 | (template_type (type_identifier) 101 | (template_argument_list (type_descriptor (type_identifier)))) 102 | (init_declarator (identifier) (identifier)))))) 103 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | $(error Windows is not supported) 3 | endif 4 | 5 | LANGUAGE_NAME := tree-sitter-cuda 6 | HOMEPAGE_URL := https://github.com/tree-sitter-grammars/tree-sitter-cuda 7 | VERSION := 0.21.1 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/cuda '$(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 | ifneq ($(wildcard queries/*.scm),) 81 | install -m644 queries/*.scm '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/cuda 82 | endif 83 | 84 | uninstall: 85 | $(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \ 86 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \ 87 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \ 88 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \ 89 | '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \ 90 | '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc 91 | $(RM) -r '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/cuda 92 | 93 | clean: 94 | $(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) 95 | 96 | test: 97 | $(TS) test 98 | 99 | .PHONY: all install uninstall clean test 100 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= 4 | github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 8 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 9 | github.com/tree-sitter/go-tree-sitter v0.24.0 h1:kRZb6aBNfcI/u0Qh8XEt3zjNVnmxTisDBN+kXK0xRYQ= 10 | github.com/tree-sitter/go-tree-sitter v0.24.0/go.mod h1:x681iFVoLMEwOSIHA1chaLkXlroXEN7WY+VHGFaoDbk= 11 | github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb h1:A8425heRM8mylnv4H58FPUiH+aYivyitre0PzxrfmWs= 12 | github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb/go.mod h1:dOF6gtQiF9UwNh995T5OphYmtIypkjsp3ap7r9AN/iA= 13 | github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148 h1:AfFPZwtwGN01BW1jDdqBVqscTwetvMpydqYZz57RSlc= 14 | github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148/go.mod h1:Bh6U3viD57rFXRYIQ+kmiYtr+1Bx0AceypDLJJSyi9s= 15 | github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33 h1:TwqSV3qLp3tKSqirGLRHnjFk9Tc2oy57LIl+FQ4GjI4= 16 | github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33/go.mod h1:CvCKCt3v04Ufos1zZnNCelBDeCGRpPucaN8QczoUsN4= 17 | github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012 h1:Xvxck3tE5FW7F7bTS97iNM2ADMyCMJztVqn5HYKdJGo= 18 | github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012/go.mod h1:T40D0O1cPvUU/+AmiXVXy1cncYQT6wem4Z0g4SfAYvY= 19 | github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo= 20 | github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU= 21 | github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA= 22 | github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc= 23 | github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg= 24 | github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU= 25 | github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4= 26 | github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk= 27 | github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g= 28 | github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs= 29 | github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw= 30 | github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g= 31 | github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d h1:fcYCvoXdcP1uRQYXqJHRy6Hec+uKScQdKVtMwK9JeCI= 32 | github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d/go.mod h1:T1nShQ4v5AJtozZ8YyAS4uzUtDAJj/iv4YfwXSbUHzg= 33 | github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc= 34 | github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc= 35 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 36 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 37 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - grammar.js 8 | - src/** 9 | - test/** 10 | - bindings/** 11 | - binding.gyp 12 | - examples/* 13 | pull_request: 14 | paths: 15 | - grammar.js 16 | - src/** 17 | - test/** 18 | - bindings/** 19 | - binding.gyp 20 | - examples/* 21 | 22 | concurrency: 23 | group: ${{github.workflow}}-${{github.ref}} 24 | cancel-in-progress: true 25 | 26 | jobs: 27 | test: 28 | name: Test parser 29 | runs-on: ${{matrix.os}} 30 | strategy: 31 | fail-fast: false 32 | matrix: 33 | os: [ubuntu-latest, windows-latest, macos-latest] 34 | steps: 35 | - name: Checkout repository 36 | uses: actions/checkout@v5 37 | - name: Set up tree-sitter 38 | uses: tree-sitter/setup-action/cli@v2 39 | - name: Run parser and binding tests 40 | uses: tree-sitter/parser-test-action@v3 41 | with: 42 | generate: false 43 | test-rust: true 44 | - name: Clone CUDA samples 45 | uses: actions/checkout@v5 46 | with: 47 | path: examples/cuda-samples 48 | repository: NVIDIA/cuda-samples 49 | ref: 8a9e2c830c8a336b4f48c79e5ed5837031eb8551 50 | sparse-checkout: Samples/ 51 | - name: Parse sample files 52 | uses: tree-sitter/parse-action@v4 53 | id: parse-files 54 | with: 55 | files: |- 56 | examples/**/*.cu 57 | examples/**/*.cuh 58 | # ignore files with macro errors 59 | invalid-files: |- 60 | examples/cuda-samples/Samples/0_Introduction/simpleCallback/simpleCallback.cu 61 | examples/cuda-samples/Samples/0_Introduction/simpleStreams/simpleStreams.cu 62 | examples/cuda-samples/Samples/0_Introduction/simpleZeroCopy/simpleZeroCopy.cu 63 | examples/cuda-samples/Samples/2_Concepts_and_Techniques/FunctionPointers/FunctionPointers_kernels.cu 64 | examples/cuda-samples/Samples/2_Concepts_and_Techniques/MC_EstimatePiInlineP/src/piestimator.cu 65 | examples/cuda-samples/Samples/2_Concepts_and_Techniques/MC_EstimatePiInlineQ/src/piestimator.cu 66 | examples/cuda-samples/Samples/2_Concepts_and_Techniques/MC_EstimatePiP/src/piestimator.cu 67 | examples/cuda-samples/Samples/2_Concepts_and_Techniques/MC_EstimatePiQ/src/piestimator.cu 68 | examples/cuda-samples/Samples/2_Concepts_and_Techniques/MC_SingleAsianOptionP/src/pricingengine.cu 69 | examples/cuda-samples/Samples/2_Concepts_and_Techniques/dct8x8/dct8x8_kernel_short.cuh 70 | examples/cuda-samples/Samples/3_CUDA_Features/newdelete/newdelete.cu 71 | examples/cuda-samples/Samples/3_CUDA_Features/simpleCudaGraphs/simpleCudaGraphs.cu 72 | examples/cuda-samples/Samples/4_CUDA_Libraries/conjugateGradientMultiDeviceCG/conjugateGradientMultiDeviceCG.cu 73 | examples/cuda-samples/Samples/5_Domain_Specific/HSOpticalFlow/flowCUDA.cu 74 | examples/cuda-samples/Samples/5_Domain_Specific/SobelFilter/SobelFilter_kernels.cu 75 | examples/cuda-samples/Samples/5_Domain_Specific/convolutionFFT2D/convolutionFFT2D.cu 76 | examples/cuda-samples/Samples/5_Domain_Specific/convolutionFFT2D/convolutionFFT2D.cuh 77 | examples/cuda-samples/Samples/5_Domain_Specific/postProcessGL/postProcessGL.cu 78 | examples/cuda-samples/Samples/5_Domain_Specific/vulkanImageCUDA/vulkanImageCUDA.cu 79 | examples/cuda-samples/Samples/6_Performance/alignedTypes/alignedTypes.cu 80 | examples/cuda-samples/Samples/8_Platform_Specific/Tegra/EGLSync_CUDAEvent_Interop/EGLSync_CUDAEvent_Interop.cu 81 | - name: Upload failures artifact 82 | uses: actions/upload-artifact@v4 83 | if: "!cancelled() && steps.parse-files.outcome == 'failure'" 84 | with: 85 | name: failures-${{runner.os}} 86 | path: ${{steps.parse-files.outputs.failures}} 87 | fuzz: 88 | name: Fuzz scanner 89 | runs-on: ubuntu-latest 90 | steps: 91 | - name: Checkout repository 92 | uses: actions/checkout@v5 93 | with: 94 | fetch-depth: 2 95 | - name: Check for scanner changes 96 | id: scanner-check 97 | run: |- 98 | if git diff --quiet HEAD^ -- src/scanner.c; then 99 | printf 'changed=false\n' >> "$GITHUB_OUTPUT" 100 | else 101 | printf 'changed=true\n' >> "$GITHUB_OUTPUT" 102 | fi 103 | - name: Run the fuzzer 104 | uses: tree-sitter/fuzz-action@v4 105 | if: steps.scanner-check.outputs.changed == 'true' 106 | -------------------------------------------------------------------------------- /examples/marker-index.cuh: -------------------------------------------------------------------------------- 1 | #ifndef MARKER_INDEX_H_ 2 | #define MARKER_INDEX_H_ 3 | 4 | #include 5 | #include 6 | #include "flat_set.h" 7 | #include "point.h" 8 | #include "range.h" 9 | 10 | class MarkerIndex { 11 | public: 12 | using MarkerId = unsigned; 13 | using MarkerIdSet = flat_set; 14 | 15 | struct SpliceResult { 16 | flat_set touch; 17 | flat_set inside; 18 | flat_set overlap; 19 | flat_set surround; 20 | }; 21 | 22 | struct Boundary { 23 | Point position; 24 | flat_set starting; 25 | flat_set ending; 26 | }; 27 | 28 | struct BoundaryQueryResult { 29 | std::vector containing_start; 30 | std::vector boundaries; 31 | }; 32 | 33 | MarkerIndex(unsigned seed = 0u); 34 | ~MarkerIndex(); 35 | int generate_random_number(); 36 | void insert(MarkerId id, Point start, Point end); 37 | void set_exclusive(MarkerId id, bool exclusive); 38 | void remove(MarkerId id); 39 | bool has(MarkerId id); 40 | SpliceResult splice(Point start, Point old_extent, Point new_extent); 41 | Point get_start(MarkerId id) const; 42 | Point get_end(MarkerId id) const; 43 | Range get_range(MarkerId id) const; 44 | 45 | int compare(MarkerId id1, MarkerId id2) const; 46 | flat_set find_intersecting(Point start, Point end); 47 | flat_set find_containing(Point start, Point end); 48 | flat_set find_contained_in(Point start, Point end); 49 | flat_set find_starting_in(Point start, Point end); 50 | flat_set find_starting_at(Point position); 51 | flat_set find_ending_in(Point start, Point end); 52 | flat_set find_ending_at(Point position); 53 | BoundaryQueryResult find_boundaries_after(Point start, size_t max_count); 54 | 55 | std::unordered_map dump(); 56 | 57 | private: 58 | friend class Iterator; 59 | 60 | struct Node { 61 | Node *parent; 62 | Node *left; 63 | Node *right; 64 | Point left_extent; 65 | flat_set left_marker_ids; 66 | flat_set right_marker_ids; 67 | flat_set start_marker_ids; 68 | flat_set end_marker_ids; 69 | int priority; 70 | 71 | Node(Node *parent, Point left_extent); 72 | bool is_marker_endpoint(); 73 | }; 74 | 75 | class Iterator { 76 | public: 77 | Iterator(MarkerIndex *marker_index); 78 | void reset(); 79 | Node* insert_marker_start(const MarkerId &id, const Point &start_position, const Point &end_position); 80 | Node* insert_marker_end(const MarkerId &id, const Point &start_position, const Point &end_position); 81 | Node* insert_splice_boundary(const Point &position, bool is_insertion_end); 82 | void find_intersecting(const Point &start, const Point &end, flat_set *result); 83 | void find_contained_in(const Point &start, const Point &end, flat_set *result); 84 | void find_starting_in(const Point &start, const Point &end, flat_set *result); 85 | void find_ending_in(const Point &start, const Point &end, flat_set *result); 86 | void find_boundaries_after(Point start, size_t max_count, BoundaryQueryResult *result); 87 | std::unordered_map dump(); 88 | 89 | private: 90 | void ascend(); 91 | void descend_left(); 92 | void descend_right(); 93 | void move_to_successor(); 94 | void seek_to_first_node_greater_than_or_equal_to(const Point &position); 95 | void mark_right(const MarkerId &id, const Point &start_position, const Point &end_position); 96 | void mark_left(const MarkerId &id, const Point &start_position, const Point &end_position); 97 | Node* insert_left_child(const Point &position); 98 | Node* insert_right_child(const Point &position); 99 | void check_intersection(const Point &start, const Point &end, flat_set *results); 100 | void cache_node_position() const; 101 | 102 | MarkerIndex *marker_index; 103 | Node *current_node; 104 | Point current_node_position; 105 | Point left_ancestor_position; 106 | Point right_ancestor_position; 107 | std::vector left_ancestor_position_stack; 108 | std::vector right_ancestor_position_stack; 109 | }; 110 | 111 | Point get_node_position(const Node *node) const; 112 | void delete_node(Node *node); 113 | void delete_subtree(Node *node); 114 | void bubble_node_up(Node *node); 115 | void bubble_node_down(Node *node); 116 | void rotate_node_left(Node *pivot); 117 | void rotate_node_right(Node *pivot); 118 | void get_starting_and_ending_markers_within_subtree(const Node *node, flat_set *starting, flat_set *ending); 119 | void populate_splice_invalidation_sets(SpliceResult *invalidated, const Node *start_node, const Node *end_node, const flat_set &starting_inside_splice, const flat_set &ending_inside_splice); 120 | 121 | std::default_random_engine random_engine; 122 | std::uniform_int_distribution random_distribution; 123 | Node *root; 124 | std::unordered_map start_nodes_by_id; 125 | std::unordered_map end_nodes_by_id; 126 | Iterator iterator; 127 | flat_set exclusive_marker_ids; 128 | mutable std::unordered_map node_position_cache; 129 | }; 130 | 131 | #endif // MARKER_INDEX_H_ 132 | -------------------------------------------------------------------------------- /src/scanner.c: -------------------------------------------------------------------------------- 1 | #include "tree_sitter/alloc.h" 2 | #include "tree_sitter/parser.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum TokenType { RAW_STRING_DELIMITER, RAW_STRING_CONTENT }; 9 | 10 | /// The spec limits delimiters to 16 chars 11 | #define MAX_DELIMITER_LENGTH 16 12 | 13 | typedef struct { 14 | uint8_t delimiter_length; 15 | wchar_t delimiter[MAX_DELIMITER_LENGTH]; 16 | } Scanner; 17 | 18 | static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); } 19 | 20 | static inline void reset(Scanner *scanner) { 21 | scanner->delimiter_length = 0; 22 | memset(scanner->delimiter, 0, sizeof scanner->delimiter); 23 | } 24 | 25 | /// Scan the raw string delimiter in R"delimiter(content)delimiter" 26 | static bool scan_raw_string_delimiter(Scanner *scanner, TSLexer *lexer) { 27 | if (scanner->delimiter_length > 0) { 28 | // Closing delimiter: must exactly match the opening delimiter. 29 | // We already checked this when scanning content, but this is how we 30 | // know when to stop. We can't stop at ", because R"""hello""" is valid. 31 | for (int i = 0; i < scanner->delimiter_length; ++i) { 32 | if (lexer->lookahead != scanner->delimiter[i]) { 33 | return false; 34 | } 35 | advance(lexer); 36 | } 37 | reset(scanner); 38 | return true; 39 | } 40 | 41 | // Opening delimiter: record the d-char-sequence up to (. 42 | // d-char is any basic character except parens, backslashes, and spaces. 43 | for (;;) { 44 | if (scanner->delimiter_length >= MAX_DELIMITER_LENGTH || lexer->eof(lexer) || lexer->lookahead == '\\' || 45 | iswspace(lexer->lookahead)) { 46 | return false; 47 | } 48 | if (lexer->lookahead == '(') { 49 | // Rather than create a token for an empty delimiter, we fail and 50 | // let the grammar fall back to a delimiter-less rule. 51 | return scanner->delimiter_length > 0; 52 | } 53 | scanner->delimiter[scanner->delimiter_length++] = lexer->lookahead; 54 | advance(lexer); 55 | } 56 | } 57 | 58 | /// Scan the raw string content in R"delimiter(content)delimiter" 59 | static bool scan_raw_string_content(Scanner *scanner, TSLexer *lexer) { 60 | // The progress made through the delimiter since the last ')'. 61 | // The delimiter may not contain ')' so a single counter suffices. 62 | for (int delimiter_index = -1;;) { 63 | // If we hit EOF, consider the content to terminate there. 64 | // This forms an incomplete raw_string_literal, and models the code 65 | // well. 66 | if (lexer->eof(lexer)) { 67 | lexer->mark_end(lexer); 68 | return true; 69 | } 70 | 71 | if (delimiter_index >= 0) { 72 | if (delimiter_index == scanner->delimiter_length) { 73 | if (lexer->lookahead == '"') { 74 | return true; 75 | } 76 | delimiter_index = -1; 77 | } else { 78 | if (lexer->lookahead == scanner->delimiter[delimiter_index]) { 79 | delimiter_index += 1; 80 | } else { 81 | delimiter_index = -1; 82 | } 83 | } 84 | } 85 | 86 | if (delimiter_index == -1 && lexer->lookahead == ')') { 87 | // The content doesn't include the )delimiter" part. 88 | // We must still scan through it, but exclude it from the token. 89 | lexer->mark_end(lexer); 90 | delimiter_index = 0; 91 | } 92 | 93 | advance(lexer); 94 | } 95 | } 96 | 97 | void *tree_sitter_cuda_external_scanner_create() { 98 | Scanner *scanner = (Scanner *)ts_calloc(1, sizeof(Scanner)); 99 | memset(scanner, 0, sizeof(Scanner)); 100 | return scanner; 101 | } 102 | 103 | bool tree_sitter_cuda_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { 104 | Scanner *scanner = (Scanner *)payload; 105 | 106 | if (valid_symbols[RAW_STRING_DELIMITER] && valid_symbols[RAW_STRING_CONTENT]) { 107 | // we're in error recovery 108 | return false; 109 | } 110 | 111 | // No skipping leading whitespace: raw-string grammar is space-sensitive. 112 | if (valid_symbols[RAW_STRING_DELIMITER]) { 113 | lexer->result_symbol = RAW_STRING_DELIMITER; 114 | return scan_raw_string_delimiter(scanner, lexer); 115 | } 116 | 117 | if (valid_symbols[RAW_STRING_CONTENT]) { 118 | lexer->result_symbol = RAW_STRING_CONTENT; 119 | return scan_raw_string_content(scanner, lexer); 120 | } 121 | 122 | return false; 123 | } 124 | 125 | unsigned tree_sitter_cuda_external_scanner_serialize(void *payload, char *buffer) { 126 | static_assert(MAX_DELIMITER_LENGTH * sizeof(wchar_t) < TREE_SITTER_SERIALIZATION_BUFFER_SIZE, 127 | "Serialized delimiter is too long!"); 128 | 129 | Scanner *scanner = (Scanner *)payload; 130 | size_t size = scanner->delimiter_length * sizeof(wchar_t); 131 | memcpy(buffer, scanner->delimiter, size); 132 | return (unsigned)size; 133 | } 134 | 135 | void tree_sitter_cuda_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) { 136 | assert(length % sizeof(wchar_t) == 0 && "Can't decode serialized delimiter!"); 137 | 138 | Scanner *scanner = (Scanner *)payload; 139 | scanner->delimiter_length = length / sizeof(wchar_t); 140 | if (length > 0) { 141 | memcpy(&scanner->delimiter[0], buffer, length); 142 | } 143 | } 144 | 145 | void tree_sitter_cuda_external_scanner_destroy(void *payload) { 146 | Scanner *scanner = (Scanner *)payload; 147 | ts_free(scanner); 148 | } 149 | -------------------------------------------------------------------------------- /test/corpus/types.txt: -------------------------------------------------------------------------------- 1 | ========================================== 2 | The auto type 3 | ========================================== 4 | 5 | void foo() { 6 | auto x = 1; 7 | } 8 | 9 | --- 10 | 11 | (translation_unit 12 | (function_definition 13 | (primitive_type) 14 | (function_declarator (identifier) (parameter_list)) 15 | (compound_statement 16 | (declaration (placeholder_type_specifier (auto)) (init_declarator (identifier) (number_literal)))))) 17 | 18 | ========================================== 19 | Namespaced types 20 | ========================================== 21 | 22 | std::string my_string; 23 | std::vector::size_typ my_string; 24 | 25 | --- 26 | 27 | (translation_unit 28 | (declaration 29 | (qualified_identifier (namespace_identifier) (type_identifier)) 30 | (identifier)) 31 | (declaration 32 | (qualified_identifier 33 | (namespace_identifier) 34 | (qualified_identifier 35 | (template_type 36 | (type_identifier) 37 | (template_argument_list (type_descriptor (primitive_type)))) 38 | (type_identifier))) 39 | (identifier))) 40 | 41 | ========================================== 42 | Dependent type names 43 | ========================================== 44 | 45 | template 46 | struct X : B 47 | { 48 | typename T::A* pa; 49 | }; 50 | 51 | --- 52 | 53 | (translation_unit 54 | (template_declaration 55 | (template_parameter_list (type_parameter_declaration (type_identifier))) 56 | (struct_specifier 57 | (type_identifier) 58 | (base_class_clause 59 | (template_type (type_identifier) (template_argument_list (type_descriptor (type_identifier))))) 60 | (field_declaration_list 61 | (field_declaration 62 | (dependent_type (qualified_identifier (namespace_identifier) (type_identifier))) 63 | (pointer_declarator (field_identifier))))))) 64 | 65 | ========================================== 66 | Template types with empty argument lists 67 | ========================================== 68 | 69 | use_future_t<> use_future; 70 | 71 | --- 72 | 73 | (translation_unit 74 | (declaration (template_type (type_identifier) (template_argument_list)) (identifier))) 75 | 76 | ================================ 77 | Function types as template arguments 78 | ================================ 79 | 80 | typedef std::function MyFunc; 81 | typedef std::function b; 82 | 83 | --- 84 | 85 | (translation_unit 86 | (type_definition 87 | (qualified_identifier 88 | (namespace_identifier) 89 | (template_type 90 | (type_identifier) 91 | (template_argument_list 92 | (type_descriptor 93 | (type_identifier) 94 | (abstract_function_declarator (parameter_list 95 | (parameter_declaration (primitive_type)))))))) 96 | (type_identifier)) 97 | (type_definition 98 | (qualified_identifier 99 | (namespace_identifier) 100 | (template_type 101 | (type_identifier) 102 | (template_argument_list 103 | (type_descriptor 104 | (primitive_type) 105 | (abstract_function_declarator (parameter_list 106 | (parameter_declaration (primitive_type)))))))) 107 | (type_identifier))) 108 | 109 | ==================================================== 110 | Decltype 111 | ==================================================== 112 | 113 | decltype(A) x; 114 | decltype(B) foo(void x, decltype(C) y); 115 | template auto add(T t, U u) -> decltype(t + u); 116 | array arr; 117 | 118 | --- 119 | 120 | (translation_unit 121 | (declaration 122 | (decltype (identifier)) 123 | (identifier)) 124 | (declaration 125 | (decltype (identifier)) 126 | (function_declarator (identifier) 127 | (parameter_list 128 | (parameter_declaration (primitive_type) (identifier)) 129 | (parameter_declaration (decltype (identifier)) (identifier))))) 130 | (template_declaration 131 | (template_parameter_list 132 | (type_parameter_declaration (type_identifier)) (type_parameter_declaration (type_identifier))) 133 | (declaration 134 | (placeholder_type_specifier (auto)) 135 | (function_declarator 136 | (identifier) 137 | (parameter_list 138 | (parameter_declaration (type_identifier) (identifier)) 139 | (parameter_declaration (type_identifier) (identifier))) 140 | (trailing_return_type 141 | (type_descriptor 142 | (decltype (binary_expression (identifier) (identifier)))))))) 143 | (declaration 144 | (template_type 145 | (type_identifier) 146 | (template_argument_list 147 | (type_descriptor 148 | (qualified_identifier 149 | (decltype (identifier)) 150 | (type_identifier))) 151 | (number_literal))) 152 | (identifier))) 153 | 154 | ==================================================== 155 | Trailing return type 156 | ==================================================== 157 | 158 | auto a::foo() const -> const A& {} 159 | auto b::foo() const -> A const& {} 160 | 161 | --- 162 | 163 | (translation_unit 164 | (function_definition 165 | (placeholder_type_specifier (auto)) 166 | (function_declarator 167 | (qualified_identifier (namespace_identifier) (identifier)) 168 | (parameter_list) 169 | (type_qualifier) 170 | (trailing_return_type 171 | (type_descriptor 172 | (type_qualifier) 173 | (template_type (type_identifier) (template_argument_list (type_descriptor (type_identifier)))) 174 | (abstract_reference_declarator)))) 175 | (compound_statement)) 176 | (function_definition 177 | (placeholder_type_specifier (auto)) 178 | (function_declarator 179 | (qualified_identifier (namespace_identifier) (identifier)) 180 | (parameter_list) 181 | (type_qualifier) 182 | (trailing_return_type 183 | (type_descriptor 184 | (template_type (type_identifier) (template_argument_list (type_descriptor (type_identifier)))) 185 | (type_qualifier) 186 | (abstract_reference_declarator)))) 187 | (compound_statement)) 188 | ) 189 | -------------------------------------------------------------------------------- /test/corpus/c/microsoft.txt: -------------------------------------------------------------------------------- 1 | ================================ 2 | declaration specs 3 | ================================ 4 | 5 | struct __declspec(dllexport) s2 6 | { 7 | }; 8 | 9 | union __declspec(noinline) u2 { 10 | }; 11 | 12 | --- 13 | 14 | (translation_unit 15 | (struct_specifier 16 | (ms_declspec_modifier 17 | (identifier)) 18 | name: (type_identifier) 19 | body: (field_declaration_list)) 20 | (union_specifier 21 | (ms_declspec_modifier 22 | (identifier)) 23 | name: (type_identifier) 24 | body: (field_declaration_list))) 25 | 26 | ================================ 27 | pointers 28 | ================================ 29 | 30 | struct s2 31 | { 32 | int * __restrict x; 33 | int * __sptr psp; 34 | int * __uptr pup; 35 | int * __unaligned pup; 36 | }; 37 | 38 | void sum2(int n, int * __restrict a, int * __restrict b, 39 | int * c, int * d) { 40 | int i; 41 | for (i = 0; i < n; i++) { 42 | a[i] = b[i] + c[i]; 43 | c[i] = b[i] + d[i]; 44 | } 45 | } 46 | 47 | void MyFunction(char * __uptr myValue); 48 | 49 | --- 50 | 51 | (translation_unit 52 | (struct_specifier 53 | name: (type_identifier) 54 | body: (field_declaration_list 55 | (field_declaration 56 | type: (primitive_type) 57 | declarator: (pointer_declarator 58 | (ms_pointer_modifier 59 | (ms_restrict_modifier)) 60 | declarator: (field_identifier))) 61 | (field_declaration 62 | type: (primitive_type) 63 | declarator: (pointer_declarator 64 | (ms_pointer_modifier 65 | (ms_signed_ptr_modifier)) 66 | declarator: (field_identifier))) 67 | (field_declaration 68 | type: (primitive_type) 69 | declarator: (pointer_declarator 70 | (ms_pointer_modifier 71 | (ms_unsigned_ptr_modifier)) 72 | declarator: (field_identifier))) 73 | (field_declaration 74 | type: (primitive_type) 75 | declarator: (pointer_declarator 76 | (ms_pointer_modifier 77 | (ms_unaligned_ptr_modifier)) 78 | declarator: (field_identifier))))) 79 | (function_definition 80 | type: (primitive_type) 81 | declarator: (function_declarator 82 | declarator: (identifier) 83 | parameters: (parameter_list 84 | (parameter_declaration 85 | type: (primitive_type) 86 | declarator: (identifier)) 87 | (parameter_declaration 88 | type: (primitive_type) 89 | declarator: (pointer_declarator 90 | (ms_pointer_modifier 91 | (ms_restrict_modifier)) 92 | declarator: (identifier))) 93 | (parameter_declaration 94 | type: (primitive_type) 95 | declarator: (pointer_declarator 96 | (ms_pointer_modifier 97 | (ms_restrict_modifier)) 98 | declarator: (identifier))) 99 | (parameter_declaration 100 | type: (primitive_type) 101 | declarator: (pointer_declarator 102 | declarator: (identifier))) 103 | (parameter_declaration 104 | type: (primitive_type) 105 | declarator: (pointer_declarator 106 | declarator: (identifier))))) 107 | body: (compound_statement 108 | (declaration 109 | type: (primitive_type) 110 | declarator: (identifier)) 111 | (for_statement 112 | initializer: (assignment_expression 113 | left: (identifier) 114 | right: (number_literal)) 115 | condition: (binary_expression 116 | left: (identifier) 117 | right: (identifier)) 118 | update: (update_expression 119 | argument: (identifier)) 120 | body: (compound_statement 121 | (expression_statement 122 | (assignment_expression 123 | left: (subscript_expression 124 | argument: (identifier) 125 | indices: (subscript_argument_list 126 | (identifier))) 127 | right: (binary_expression 128 | left: (subscript_expression 129 | argument: (identifier) 130 | indices: (subscript_argument_list 131 | (identifier))) 132 | right: (subscript_expression 133 | argument: (identifier) 134 | indices: (subscript_argument_list 135 | (identifier)))))) 136 | (expression_statement 137 | (assignment_expression 138 | left: (subscript_expression 139 | argument: (identifier) 140 | indices: (subscript_argument_list 141 | (identifier))) 142 | right: (binary_expression 143 | left: (subscript_expression 144 | argument: (identifier) 145 | indices: (subscript_argument_list 146 | (identifier))) 147 | right: (subscript_expression 148 | argument: (identifier) 149 | indices: (subscript_argument_list 150 | (identifier)))))))))) 151 | (declaration 152 | type: (primitive_type) 153 | declarator: (function_declarator 154 | declarator: (identifier) 155 | parameters: (parameter_list 156 | (parameter_declaration 157 | type: (primitive_type) 158 | declarator: (pointer_declarator 159 | (ms_pointer_modifier 160 | (ms_unsigned_ptr_modifier)) 161 | declarator: (identifier))))))) 162 | 163 | ================================ 164 | call modifiers 165 | ================================ 166 | 167 | __cdecl void mymethod(){ 168 | return; 169 | } 170 | 171 | __fastcall void mymethod(){ 172 | return; 173 | } 174 | 175 | --- 176 | 177 | (translation_unit 178 | (function_definition 179 | (ms_call_modifier) 180 | type: (primitive_type) 181 | declarator: (function_declarator 182 | declarator: (identifier) 183 | parameters: (parameter_list)) 184 | body: (compound_statement 185 | (return_statement))) 186 | (function_definition 187 | (ms_call_modifier) 188 | type: (primitive_type) 189 | declarator: (function_declarator 190 | declarator: (identifier) 191 | parameters: (parameter_list)) 192 | body: (compound_statement 193 | (return_statement)))) 194 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 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.37" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44" 19 | dependencies = [ 20 | "find-msvc-tools", 21 | "shlex", 22 | ] 23 | 24 | [[package]] 25 | name = "equivalent" 26 | version = "1.0.2" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 29 | 30 | [[package]] 31 | name = "find-msvc-tools" 32 | version = "0.1.1" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" 35 | 36 | [[package]] 37 | name = "hashbrown" 38 | version = "0.16.0" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" 41 | 42 | [[package]] 43 | name = "indexmap" 44 | version = "2.11.4" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" 47 | dependencies = [ 48 | "equivalent", 49 | "hashbrown", 50 | ] 51 | 52 | [[package]] 53 | name = "itoa" 54 | version = "1.0.15" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 57 | 58 | [[package]] 59 | name = "memchr" 60 | version = "2.7.5" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 63 | 64 | [[package]] 65 | name = "proc-macro2" 66 | version = "1.0.101" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 69 | dependencies = [ 70 | "unicode-ident", 71 | ] 72 | 73 | [[package]] 74 | name = "quote" 75 | version = "1.0.40" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 78 | dependencies = [ 79 | "proc-macro2", 80 | ] 81 | 82 | [[package]] 83 | name = "regex" 84 | version = "1.11.2" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" 87 | dependencies = [ 88 | "aho-corasick", 89 | "memchr", 90 | "regex-automata", 91 | "regex-syntax", 92 | ] 93 | 94 | [[package]] 95 | name = "regex-automata" 96 | version = "0.4.10" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" 99 | dependencies = [ 100 | "aho-corasick", 101 | "memchr", 102 | "regex-syntax", 103 | ] 104 | 105 | [[package]] 106 | name = "regex-syntax" 107 | version = "0.8.6" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" 110 | 111 | [[package]] 112 | name = "ryu" 113 | version = "1.0.20" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 116 | 117 | [[package]] 118 | name = "serde" 119 | version = "1.0.225" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" 122 | dependencies = [ 123 | "serde_core", 124 | ] 125 | 126 | [[package]] 127 | name = "serde_core" 128 | version = "1.0.225" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" 131 | dependencies = [ 132 | "serde_derive", 133 | ] 134 | 135 | [[package]] 136 | name = "serde_derive" 137 | version = "1.0.225" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" 140 | dependencies = [ 141 | "proc-macro2", 142 | "quote", 143 | "syn", 144 | ] 145 | 146 | [[package]] 147 | name = "serde_json" 148 | version = "1.0.145" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 151 | dependencies = [ 152 | "indexmap", 153 | "itoa", 154 | "memchr", 155 | "ryu", 156 | "serde", 157 | "serde_core", 158 | ] 159 | 160 | [[package]] 161 | name = "shlex" 162 | version = "1.3.0" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 165 | 166 | [[package]] 167 | name = "streaming-iterator" 168 | version = "0.1.9" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" 171 | 172 | [[package]] 173 | name = "syn" 174 | version = "2.0.106" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" 177 | dependencies = [ 178 | "proc-macro2", 179 | "quote", 180 | "unicode-ident", 181 | ] 182 | 183 | [[package]] 184 | name = "tree-sitter" 185 | version = "0.25.9" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "ccd2a058a86cfece0bf96f7cce1021efef9c8ed0e892ab74639173e5ed7a34fa" 188 | dependencies = [ 189 | "cc", 190 | "regex", 191 | "regex-syntax", 192 | "serde_json", 193 | "streaming-iterator", 194 | "tree-sitter-language", 195 | ] 196 | 197 | [[package]] 198 | name = "tree-sitter-cuda" 199 | version = "0.21.1" 200 | dependencies = [ 201 | "cc", 202 | "tree-sitter", 203 | "tree-sitter-language", 204 | ] 205 | 206 | [[package]] 207 | name = "tree-sitter-language" 208 | version = "0.1.5" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8" 211 | 212 | [[package]] 213 | name = "unicode-ident" 214 | version = "1.0.19" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" 217 | -------------------------------------------------------------------------------- /test/corpus/c/ambiguities.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | pointer declarations vs expressions 3 | ================================================================================ 4 | 5 | TSLanguage *(*lang_parser)(void); 6 | 7 | char (*ptr_to_array)[]; 8 | 9 | int main() { 10 | // declare a function pointer 11 | T1 * b(T2 a); 12 | 13 | // evaluate expressions 14 | c * d(5); 15 | e(f * g); 16 | } 17 | 18 | -------------------------------------------------------------------------------- 19 | 20 | (translation_unit 21 | (declaration 22 | (type_identifier) 23 | (pointer_declarator 24 | (function_declarator 25 | (parenthesized_declarator 26 | (pointer_declarator 27 | (identifier))) 28 | (parameter_list 29 | (parameter_declaration 30 | (primitive_type)))))) 31 | (expression_statement 32 | (subscript_expression 33 | (call_expression 34 | (primitive_type) 35 | (argument_list 36 | (pointer_expression 37 | (identifier)))) 38 | (subscript_argument_list))) 39 | (function_definition 40 | (primitive_type) 41 | (function_declarator 42 | (identifier) 43 | (parameter_list)) 44 | (compound_statement 45 | (comment) 46 | (declaration 47 | (type_identifier) 48 | (pointer_declarator 49 | (function_declarator 50 | (identifier) 51 | (parameter_list 52 | (parameter_declaration 53 | (type_identifier) 54 | (identifier)))))) 55 | (comment) 56 | (expression_statement 57 | (binary_expression 58 | (identifier) 59 | (call_expression 60 | (identifier) 61 | (argument_list 62 | (number_literal))))) 63 | (expression_statement 64 | (call_expression 65 | (identifier) 66 | (argument_list 67 | (binary_expression 68 | (identifier) 69 | (identifier)))))))) 70 | 71 | ================================================================================ 72 | casts vs multiplications 73 | ================================================================================ 74 | 75 | /* 76 | * ambiguities 77 | */ 78 | 79 | int main() { 80 | // cast 81 | a((B *)c); 82 | 83 | // parenthesized product 84 | d((e * f)); 85 | } 86 | 87 | -------------------------------------------------------------------------------- 88 | 89 | (translation_unit 90 | (comment) 91 | (function_definition 92 | (primitive_type) 93 | (function_declarator 94 | (identifier) 95 | (parameter_list)) 96 | (compound_statement 97 | (comment) 98 | (expression_statement 99 | (call_expression 100 | (identifier) 101 | (argument_list 102 | (cast_expression 103 | (type_descriptor 104 | (type_identifier) 105 | (abstract_pointer_declarator)) 106 | (identifier))))) 107 | (comment) 108 | (expression_statement 109 | (call_expression 110 | (identifier) 111 | (argument_list 112 | (parenthesized_expression 113 | (binary_expression 114 | (identifier) 115 | (identifier))))))))) 116 | 117 | ================================================================================ 118 | function calls vs parenthesized declarators vs macro types 119 | ================================================================================ 120 | 121 | int main() { 122 | /* 123 | * Could be either: 124 | * - function call 125 | * - declaration w/ parenthesized declarator 126 | * - declaration w/ macro type, no declarator 127 | */ 128 | ABC(d); 129 | 130 | /* 131 | * Normal declaration 132 | */ 133 | efg hij; 134 | } 135 | 136 | -------------------------------------------------------------------------------- 137 | 138 | (translation_unit 139 | (function_definition 140 | (primitive_type) 141 | (function_declarator 142 | (identifier) 143 | (parameter_list)) 144 | (compound_statement 145 | (comment) 146 | (expression_statement 147 | (call_expression 148 | (identifier) 149 | (argument_list 150 | (identifier)))) 151 | (comment) 152 | (declaration 153 | (type_identifier) 154 | (identifier))))) 155 | 156 | ================================================================================ 157 | Call expressions vs empty declarations w/ macros as types 158 | ================================================================================ 159 | 160 | int main() { 161 | int a = 1; 162 | b(a); 163 | } 164 | 165 | -------------------------------------------------------------------------------- 166 | 167 | (translation_unit 168 | (function_definition 169 | (primitive_type) 170 | (function_declarator 171 | (identifier) 172 | (parameter_list)) 173 | (compound_statement 174 | (declaration 175 | (primitive_type) 176 | (init_declarator 177 | (identifier) 178 | (number_literal))) 179 | (expression_statement 180 | (call_expression 181 | (identifier) 182 | (argument_list 183 | (identifier))))))) 184 | 185 | ================================================================================ 186 | Comments after for loops with ambiguities 187 | ================================================================================ 188 | 189 | int main() { 190 | for (a *b = c; d; e) { 191 | aff; 192 | } 193 | 194 | // a-comment 195 | 196 | g; 197 | } 198 | 199 | -------------------------------------------------------------------------------- 200 | 201 | (translation_unit 202 | (function_definition 203 | (primitive_type) 204 | (function_declarator 205 | (identifier) 206 | (parameter_list)) 207 | (compound_statement 208 | (for_statement 209 | (declaration 210 | (type_identifier) 211 | (init_declarator 212 | (pointer_declarator 213 | (identifier)) 214 | (identifier))) 215 | (identifier) 216 | (identifier) 217 | (compound_statement 218 | (expression_statement 219 | (identifier)))) 220 | (comment) 221 | (expression_statement 222 | (identifier))))) 223 | 224 | ================================================================================ 225 | Top-level macro invocations 226 | ================================================================================ 227 | 228 | DEFINE_SOMETHING(THING_A, "this is a thing a"); 229 | DEFINE_SOMETHING(THING_B, "this is a thing b", "thanks"); 230 | 231 | -------------------------------------------------------------------------------- 232 | 233 | (translation_unit 234 | (expression_statement 235 | (call_expression 236 | (identifier) 237 | (argument_list 238 | (identifier) 239 | (string_literal 240 | (string_content))))) 241 | (expression_statement 242 | (call_expression 243 | (identifier) 244 | (argument_list 245 | (identifier) 246 | (string_literal 247 | (string_content)) 248 | (string_literal 249 | (string_content)))))) 250 | -------------------------------------------------------------------------------- /test/corpus/cuda.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | CUDA functions 3 | ================================================================================ 4 | 5 | __device__ __host__ int foo() { 6 | 7 | } 8 | 9 | -------------------------------------------------------------------------------- 10 | 11 | (translation_unit 12 | (function_definition 13 | type: (primitive_type) 14 | declarator: (function_declarator 15 | declarator: (identifier) 16 | parameters: (parameter_list)) 17 | body: (compound_statement))) 18 | 19 | ================================================================================ 20 | __restrict__ 21 | ================================================================================ 22 | 23 | __device__ __host__ int foo(int* __restrict__ x, int* __restrict__ y) { 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- 28 | 29 | (translation_unit 30 | (function_definition 31 | type: (primitive_type) 32 | declarator: (function_declarator 33 | declarator: (identifier) 34 | parameters: (parameter_list 35 | (parameter_declaration 36 | type: (primitive_type) 37 | declarator: (pointer_declarator 38 | (type_qualifier) 39 | declarator: (identifier))) 40 | (parameter_declaration 41 | type: (primitive_type) 42 | declarator: (pointer_declarator 43 | (type_qualifier) 44 | declarator: (identifier))))) 45 | body: (compound_statement))) 46 | 47 | ================================================================================ 48 | CUDA kernel calls 49 | ================================================================================ 50 | 51 | int foo() { 52 | foo<<>>(); 53 | foo<<>>(); 54 | foo< <>>(); 55 | } 56 | 57 | -------------------------------------------------------------------------------- 58 | 59 | (translation_unit 60 | (function_definition 61 | type: (primitive_type) 62 | declarator: (function_declarator 63 | declarator: (identifier) 64 | parameters: (parameter_list)) 65 | body: (compound_statement 66 | (expression_statement 67 | (call_expression 68 | function: (identifier) 69 | (kernel_call_syntax 70 | (identifier)) 71 | arguments: (argument_list))) 72 | (expression_statement 73 | (call_expression 74 | function: (identifier) 75 | (kernel_call_syntax 76 | (identifier) 77 | (identifier)) 78 | arguments: (argument_list))) 79 | (expression_statement 80 | (call_expression 81 | function: (identifier) 82 | (kernel_call_syntax 83 | (identifier) 84 | (identifier)) 85 | arguments: (argument_list)))))) 86 | 87 | ================================================================================ 88 | __launch_bounds__ 89 | ================================================================================ 90 | __launch_bounds__(MAX(2, 3), MIN(23,XXX)) 91 | __global__ int foo() { 92 | 93 | } 94 | 95 | -------------------------------------------------------------------------------- 96 | 97 | (translation_unit 98 | (function_definition 99 | (launch_bounds 100 | (call_expression 101 | (identifier) 102 | (argument_list 103 | (number_literal) 104 | (number_literal))) 105 | (call_expression 106 | (identifier) 107 | (argument_list 108 | (number_literal) 109 | (identifier)))) 110 | (primitive_type) 111 | (function_declarator 112 | (identifier) 113 | (parameter_list)) 114 | (compound_statement))) 115 | 116 | ================================================================================ 117 | __launch_bounds__ function declaration 118 | ================================================================================ 119 | void Test2Args(void); 120 | __launch_bounds__(128, 7) void Test2Args(void); 121 | __launch_bounds__(128) void Test1Arg(void); 122 | 123 | -------------------------------------------------------------------------------- 124 | 125 | (translation_unit 126 | (declaration 127 | (primitive_type) 128 | (function_declarator 129 | (identifier) 130 | (parameter_list 131 | (parameter_declaration 132 | (primitive_type))))) 133 | (declaration 134 | (launch_bounds 135 | (number_literal) 136 | (number_literal)) 137 | (primitive_type) 138 | (function_declarator 139 | (identifier) 140 | (parameter_list 141 | (parameter_declaration 142 | (primitive_type))))) 143 | (declaration 144 | (launch_bounds 145 | (number_literal)) 146 | (primitive_type) 147 | (function_declarator 148 | (identifier) 149 | (parameter_list 150 | (parameter_declaration 151 | (primitive_type)))))) 152 | 153 | ================================================================================ 154 | __launch_bounds__ template 155 | ================================================================================ 156 | 157 | template 158 | __launch_bounds__(MAX(2, 3), MIN(23,XXX)) 159 | __global__ int foo() { 160 | 161 | } 162 | -------------------------------------------------------------------------------- 163 | 164 | (translation_unit 165 | (template_declaration 166 | (template_parameter_list 167 | (variadic_parameter_declaration 168 | (primitive_type) 169 | (variadic_declarator 170 | (identifier)))) 171 | (function_definition 172 | (launch_bounds 173 | (call_expression 174 | (identifier) 175 | (argument_list 176 | (number_literal) 177 | (number_literal))) 178 | (call_expression 179 | (identifier) 180 | (argument_list 181 | (number_literal) 182 | (identifier)))) 183 | (primitive_type) 184 | (function_declarator 185 | (identifier) 186 | (parameter_list)) 187 | (compound_statement)))) 188 | 189 | ================================================================================ 190 | template inline 191 | ================================================================================ 192 | inline __device__ void vec_set(int &a, V b) { a = b; } 193 | template inline __device__ void vec_set(int &a, V b) { a = b; } 194 | -------------------------------------------------------------------------------- 195 | 196 | (translation_unit 197 | (function_definition 198 | (storage_class_specifier) 199 | (primitive_type) 200 | (function_declarator 201 | (identifier) 202 | (parameter_list 203 | (parameter_declaration 204 | (primitive_type) 205 | (reference_declarator 206 | (identifier))) 207 | (parameter_declaration 208 | (type_identifier) 209 | (identifier)))) 210 | (compound_statement 211 | (expression_statement 212 | (assignment_expression 213 | (identifier) 214 | (identifier))))) 215 | (template_declaration 216 | (template_parameter_list 217 | (type_parameter_declaration 218 | (type_identifier))) 219 | (function_definition 220 | (storage_class_specifier) 221 | (primitive_type) 222 | (function_declarator 223 | (identifier) 224 | (parameter_list 225 | (parameter_declaration 226 | (primitive_type) 227 | (reference_declarator 228 | (identifier))) 229 | (parameter_declaration 230 | (type_identifier) 231 | (identifier)))) 232 | (compound_statement 233 | (expression_statement 234 | (assignment_expression 235 | (identifier) 236 | (identifier))))))) 237 | -------------------------------------------------------------------------------- /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 { 22 | uint8_t major_version; 23 | uint8_t minor_version; 24 | uint8_t patch_version; 25 | } TSLanguageMetadata; 26 | #endif 27 | 28 | typedef struct { 29 | TSFieldId field_id; 30 | uint8_t child_index; 31 | bool inherited; 32 | } TSFieldMapEntry; 33 | 34 | // Used to index the field and supertype maps. 35 | typedef struct { 36 | uint16_t index; 37 | uint16_t length; 38 | } TSMapSlice; 39 | 40 | typedef struct { 41 | bool visible; 42 | bool named; 43 | bool supertype; 44 | } TSSymbolMetadata; 45 | 46 | typedef struct TSLexer TSLexer; 47 | 48 | struct TSLexer { 49 | int32_t lookahead; 50 | TSSymbol result_symbol; 51 | void (*advance)(TSLexer *, bool); 52 | void (*mark_end)(TSLexer *); 53 | uint32_t (*get_column)(TSLexer *); 54 | bool (*is_at_included_range_start)(const TSLexer *); 55 | bool (*eof)(const TSLexer *); 56 | void (*log)(const TSLexer *, const char *, ...); 57 | }; 58 | 59 | typedef enum { 60 | TSParseActionTypeShift, 61 | TSParseActionTypeReduce, 62 | TSParseActionTypeAccept, 63 | TSParseActionTypeRecover, 64 | } TSParseActionType; 65 | 66 | typedef union { 67 | struct { 68 | uint8_t type; 69 | TSStateId state; 70 | bool extra; 71 | bool repetition; 72 | } shift; 73 | struct { 74 | uint8_t type; 75 | uint8_t child_count; 76 | TSSymbol symbol; 77 | int16_t dynamic_precedence; 78 | uint16_t production_id; 79 | } reduce; 80 | uint8_t type; 81 | } TSParseAction; 82 | 83 | typedef struct { 84 | uint16_t lex_state; 85 | uint16_t external_lex_state; 86 | } TSLexMode; 87 | 88 | typedef struct { 89 | uint16_t lex_state; 90 | uint16_t external_lex_state; 91 | uint16_t reserved_word_set_id; 92 | } TSLexerMode; 93 | 94 | typedef union { 95 | TSParseAction action; 96 | struct { 97 | uint8_t count; 98 | bool reusable; 99 | } entry; 100 | } TSParseActionEntry; 101 | 102 | typedef struct { 103 | int32_t start; 104 | int32_t end; 105 | } TSCharacterRange; 106 | 107 | struct TSLanguage { 108 | uint32_t abi_version; 109 | uint32_t symbol_count; 110 | uint32_t alias_count; 111 | uint32_t token_count; 112 | uint32_t external_token_count; 113 | uint32_t state_count; 114 | uint32_t large_state_count; 115 | uint32_t production_id_count; 116 | uint32_t field_count; 117 | uint16_t max_alias_sequence_length; 118 | const uint16_t *parse_table; 119 | const uint16_t *small_parse_table; 120 | const uint32_t *small_parse_table_map; 121 | const TSParseActionEntry *parse_actions; 122 | const char * const *symbol_names; 123 | const char * const *field_names; 124 | const TSMapSlice *field_map_slices; 125 | const TSFieldMapEntry *field_map_entries; 126 | const TSSymbolMetadata *symbol_metadata; 127 | const TSSymbol *public_symbol_map; 128 | const uint16_t *alias_map; 129 | const TSSymbol *alias_sequences; 130 | const TSLexerMode *lex_modes; 131 | bool (*lex_fn)(TSLexer *, TSStateId); 132 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 133 | TSSymbol keyword_capture_token; 134 | struct { 135 | const bool *states; 136 | const TSSymbol *symbol_map; 137 | void *(*create)(void); 138 | void (*destroy)(void *); 139 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 140 | unsigned (*serialize)(void *, char *); 141 | void (*deserialize)(void *, const char *, unsigned); 142 | } external_scanner; 143 | const TSStateId *primary_state_ids; 144 | const char *name; 145 | const TSSymbol *reserved_words; 146 | uint16_t max_reserved_word_set_size; 147 | uint32_t supertype_count; 148 | const TSSymbol *supertype_symbols; 149 | const TSMapSlice *supertype_map_slices; 150 | const TSSymbol *supertype_map_entries; 151 | TSLanguageMetadata metadata; 152 | }; 153 | 154 | static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 155 | uint32_t index = 0; 156 | uint32_t size = len - index; 157 | while (size > 1) { 158 | uint32_t half_size = size / 2; 159 | uint32_t mid_index = index + half_size; 160 | const TSCharacterRange *range = &ranges[mid_index]; 161 | if (lookahead >= range->start && lookahead <= range->end) { 162 | return true; 163 | } else if (lookahead > range->end) { 164 | index = mid_index; 165 | } 166 | size -= half_size; 167 | } 168 | const TSCharacterRange *range = &ranges[index]; 169 | return (lookahead >= range->start && lookahead <= range->end); 170 | } 171 | 172 | /* 173 | * Lexer Macros 174 | */ 175 | 176 | #ifdef _MSC_VER 177 | #define UNUSED __pragma(warning(suppress : 4101)) 178 | #else 179 | #define UNUSED __attribute__((unused)) 180 | #endif 181 | 182 | #define START_LEXER() \ 183 | bool result = false; \ 184 | bool skip = false; \ 185 | UNUSED \ 186 | bool eof = false; \ 187 | int32_t lookahead; \ 188 | goto start; \ 189 | next_state: \ 190 | lexer->advance(lexer, skip); \ 191 | start: \ 192 | skip = false; \ 193 | lookahead = lexer->lookahead; 194 | 195 | #define ADVANCE(state_value) \ 196 | { \ 197 | state = state_value; \ 198 | goto next_state; \ 199 | } 200 | 201 | #define ADVANCE_MAP(...) \ 202 | { \ 203 | static const uint16_t map[] = { __VA_ARGS__ }; \ 204 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 205 | if (map[i] == lookahead) { \ 206 | state = map[i + 1]; \ 207 | goto next_state; \ 208 | } \ 209 | } \ 210 | } 211 | 212 | #define SKIP(state_value) \ 213 | { \ 214 | skip = true; \ 215 | state = state_value; \ 216 | goto next_state; \ 217 | } 218 | 219 | #define ACCEPT_TOKEN(symbol_value) \ 220 | result = true; \ 221 | lexer->result_symbol = symbol_value; \ 222 | lexer->mark_end(lexer); 223 | 224 | #define END_STATE() return result; 225 | 226 | /* 227 | * Parse Table Macros 228 | */ 229 | 230 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 231 | 232 | #define STATE(id) id 233 | 234 | #define ACTIONS(id) id 235 | 236 | #define SHIFT(state_value) \ 237 | {{ \ 238 | .shift = { \ 239 | .type = TSParseActionTypeShift, \ 240 | .state = (state_value) \ 241 | } \ 242 | }} 243 | 244 | #define SHIFT_REPEAT(state_value) \ 245 | {{ \ 246 | .shift = { \ 247 | .type = TSParseActionTypeShift, \ 248 | .state = (state_value), \ 249 | .repetition = true \ 250 | } \ 251 | }} 252 | 253 | #define SHIFT_EXTRA() \ 254 | {{ \ 255 | .shift = { \ 256 | .type = TSParseActionTypeShift, \ 257 | .extra = true \ 258 | } \ 259 | }} 260 | 261 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 262 | {{ \ 263 | .reduce = { \ 264 | .type = TSParseActionTypeReduce, \ 265 | .symbol = symbol_name, \ 266 | .child_count = children, \ 267 | .dynamic_precedence = precedence, \ 268 | .production_id = prod_id \ 269 | }, \ 270 | }} 271 | 272 | #define RECOVER() \ 273 | {{ \ 274 | .type = TSParseActionTypeRecover \ 275 | }} 276 | 277 | #define ACCEPT_INPUT() \ 278 | {{ \ 279 | .type = TSParseActionTypeAccept \ 280 | }} 281 | 282 | #ifdef __cplusplus 283 | } 284 | #endif 285 | 286 | #endif // TREE_SITTER_PARSER_H_ 287 | -------------------------------------------------------------------------------- /examples/rule.cu: -------------------------------------------------------------------------------- 1 | #include "compiler/rule.h" 2 | #include "compiler/util/hash_combine.h" 3 | 4 | namespace tree_sitter { 5 | namespace rules { 6 | 7 | using std::move; 8 | using std::vector; 9 | using util::hash_combine; 10 | 11 | Rule::Rule(const Rule &other) : blank_(Blank{}), type(BlankType) { 12 | *this = other; 13 | } 14 | 15 | Rule::Rule(Rule &&other) noexcept : blank_(Blank{}), type(BlankType) { 16 | *this = move(other); 17 | } 18 | 19 | static void destroy_value(Rule *rule) { 20 | switch (rule->type) { 21 | case Rule::BlankType: return rule->blank_.~Blank(); 22 | case Rule::CharacterSetType: return rule->character_set_.~CharacterSet(); 23 | case Rule::StringType: return rule->string_ .~String(); 24 | case Rule::PatternType: return rule->pattern_ .~Pattern(); 25 | case Rule::NamedSymbolType: return rule->named_symbol_.~NamedSymbol(); 26 | case Rule::SymbolType: return rule->symbol_ .~Symbol(); 27 | case Rule::ChoiceType: return rule->choice_ .~Choice(); 28 | case Rule::MetadataType: return rule->metadata_ .~Metadata(); 29 | case Rule::RepeatType: return rule->repeat_ .~Repeat(); 30 | case Rule::SeqType: return rule->seq_ .~Seq(); 31 | } 32 | } 33 | 34 | Rule &Rule::operator=(const Rule &other) { 35 | destroy_value(this); 36 | type = other.type; 37 | switch (type) { 38 | case BlankType: 39 | new (&blank_) Blank(other.blank_); 40 | break; 41 | case CharacterSetType: 42 | new (&character_set_) CharacterSet(other.character_set_); 43 | break; 44 | case StringType: 45 | new (&string_) String(other.string_); 46 | break; 47 | case PatternType: 48 | new (&pattern_) Pattern(other.pattern_); 49 | break; 50 | case NamedSymbolType: 51 | new (&named_symbol_) NamedSymbol(other.named_symbol_); 52 | break; 53 | case SymbolType: 54 | new (&symbol_) Symbol(other.symbol_); 55 | break; 56 | case ChoiceType: 57 | new (&choice_) Choice(other.choice_); 58 | break; 59 | case MetadataType: 60 | new (&metadata_) Metadata(other.metadata_); 61 | break; 62 | case RepeatType: 63 | new (&repeat_) Repeat(other.repeat_); 64 | break; 65 | case SeqType: 66 | new (&seq_) Seq(other.seq_); 67 | break; 68 | } 69 | return *this; 70 | } 71 | 72 | Rule &Rule::operator=(Rule &&other) noexcept { 73 | destroy_value(this); 74 | type = other.type; 75 | switch (type) { 76 | case BlankType: 77 | new (&blank_) Blank(move(other.blank_)); 78 | break; 79 | case CharacterSetType: 80 | new (&character_set_) CharacterSet(move(other.character_set_)); 81 | break; 82 | case StringType: 83 | new (&string_) String(move(other.string_)); 84 | break; 85 | case PatternType: 86 | new (&pattern_) Pattern(move(other.pattern_)); 87 | break; 88 | case NamedSymbolType: 89 | new (&named_symbol_) NamedSymbol(move(other.named_symbol_)); 90 | break; 91 | case SymbolType: 92 | new (&symbol_) Symbol(move(other.symbol_)); 93 | break; 94 | case ChoiceType: 95 | new (&choice_) Choice(move(other.choice_)); 96 | break; 97 | case MetadataType: 98 | new (&metadata_) Metadata(move(other.metadata_)); 99 | break; 100 | case RepeatType: 101 | new (&repeat_) Repeat(move(other.repeat_)); 102 | break; 103 | case SeqType: 104 | new (&seq_) Seq(move(other.seq_)); 105 | break; 106 | } 107 | other.type = BlankType; 108 | other.blank_ = Blank{}; 109 | return *this; 110 | } 111 | 112 | Rule::~Rule() noexcept { 113 | destroy_value(this); 114 | } 115 | 116 | bool Rule::operator==(const Rule &other) const { 117 | if (type != other.type) return false; 118 | switch (type) { 119 | case Rule::CharacterSetType: return character_set_ == other.character_set_; 120 | case Rule::StringType: return string_ == other.string_; 121 | case Rule::PatternType: return pattern_ == other.pattern_; 122 | case Rule::NamedSymbolType: return named_symbol_ == other.named_symbol_; 123 | case Rule::SymbolType: return symbol_ == other.symbol_; 124 | case Rule::ChoiceType: return choice_ == other.choice_; 125 | case Rule::MetadataType: return metadata_ == other.metadata_; 126 | case Rule::RepeatType: return repeat_ == other.repeat_; 127 | case Rule::SeqType: return seq_ == other.seq_; 128 | default: return blank_ == other.blank_; 129 | } 130 | } 131 | 132 | template <> 133 | bool Rule::is() const { return type == BlankType; } 134 | 135 | template <> 136 | bool Rule::is() const { return type == SymbolType; } 137 | 138 | template <> 139 | bool Rule::is() const { return type == RepeatType; } 140 | 141 | template <> 142 | const Symbol & Rule::get_unchecked() const { return symbol_; } 143 | 144 | static inline void add_choice_element(std::vector *elements, const Rule &new_rule) { 145 | new_rule.match( 146 | [elements](Choice choice) { 147 | for (auto &element : choice.elements) { 148 | add_choice_element(elements, element); 149 | } 150 | }, 151 | 152 | [elements](auto rule) { 153 | for (auto &element : *elements) { 154 | if (element == rule) return; 155 | } 156 | elements->push_back(rule); 157 | } 158 | ); 159 | } 160 | 161 | Rule Rule::choice(const vector &rules) { 162 | vector elements; 163 | for (auto &element : rules) { 164 | add_choice_element(&elements, element); 165 | } 166 | return (elements.size() == 1) ? elements.front() : Choice{elements}; 167 | } 168 | 169 | Rule Rule::repeat(const Rule &rule) { 170 | return rule.is() ? rule : Repeat{rule}; 171 | } 172 | 173 | Rule Rule::seq(const vector &rules) { 174 | Rule result; 175 | for (const auto &rule : rules) { 176 | rule.match( 177 | [](Blank) {}, 178 | [&](Metadata metadata) { 179 | if (!metadata.rule->is()) { 180 | result = Seq{result, rule}; 181 | } 182 | }, 183 | [&](auto) { 184 | if (result.is()) { 185 | result = rule; 186 | } else { 187 | result = Seq{result, rule}; 188 | } 189 | } 190 | ); 191 | } 192 | return result; 193 | } 194 | 195 | } // namespace rules 196 | } // namespace tree_sitter 197 | 198 | namespace std { 199 | 200 | size_t hash::operator()(const Symbol &symbol) const { 201 | auto result = hash()(symbol.index); 202 | hash_combine(&result, hash()(symbol.type)); 203 | return result; 204 | } 205 | 206 | size_t hash::operator()(const NamedSymbol &symbol) const { 207 | return hash()(symbol.value); 208 | } 209 | 210 | size_t hash::operator()(const Pattern &symbol) const { 211 | return hash()(symbol.value); 212 | } 213 | 214 | size_t hash::operator()(const String &symbol) const { 215 | return hash()(symbol.value); 216 | } 217 | 218 | size_t hash::operator()(const CharacterSet &character_set) const { 219 | size_t result = 0; 220 | hash_combine(&result, character_set.includes_all); 221 | hash_combine(&result, character_set.included_chars.size()); 222 | for (uint32_t c : character_set.included_chars) { 223 | hash_combine(&result, c); 224 | } 225 | hash_combine(&result, character_set.excluded_chars.size()); 226 | for (uint32_t c : character_set.excluded_chars) { 227 | hash_combine(&result, c); 228 | } 229 | return result; 230 | } 231 | 232 | size_t hash::operator()(const Blank &blank) const { 233 | return 0; 234 | } 235 | 236 | size_t hash::operator()(const Choice &choice) const { 237 | size_t result = 0; 238 | for (const auto &element : choice.elements) { 239 | symmetric_hash_combine(&result, element); 240 | } 241 | return result; 242 | } 243 | 244 | size_t hash::operator()(const Repeat &repeat) const { 245 | size_t result = 0; 246 | hash_combine(&result, *repeat.rule); 247 | return result; 248 | } 249 | 250 | size_t hash::operator()(const Seq &seq) const { 251 | size_t result = 0; 252 | hash_combine(&result, *seq.left); 253 | hash_combine(&result, *seq.right); 254 | return result; 255 | } 256 | 257 | size_t hash::operator()(const Metadata &metadata) const { 258 | size_t result = 0; 259 | hash_combine(&result, *metadata.rule); 260 | hash_combine(&result, metadata.params.precedence); 261 | hash_combine(&result, metadata.params.associativity); 262 | hash_combine(&result, metadata.params.has_precedence); 263 | hash_combine(&result, metadata.params.has_associativity); 264 | hash_combine(&result, metadata.params.is_token); 265 | hash_combine(&result, metadata.params.is_string); 266 | hash_combine(&result, metadata.params.is_active); 267 | hash_combine(&result, metadata.params.is_main_token); 268 | return result; 269 | } 270 | 271 | size_t hash::operator()(const Rule &rule) const { 272 | size_t result = hash()(rule.type); 273 | switch (rule.type) { 274 | case Rule::CharacterSetType: return result ^ hash()(rule.character_set_); 275 | case Rule::StringType: return result ^ hash()(rule.string_); 276 | case Rule::PatternType: return result ^ hash()(rule.pattern_); 277 | case Rule::NamedSymbolType: return result ^ hash()(rule.named_symbol_); 278 | case Rule::SymbolType: return result ^ hash()(rule.symbol_); 279 | case Rule::ChoiceType: return result ^ hash()(rule.choice_); 280 | case Rule::MetadataType: return result ^ hash()(rule.metadata_); 281 | case Rule::RepeatType: return result ^ hash()(rule.repeat_); 282 | case Rule::SeqType: return result ^ hash()(rule.seq_); 283 | default: return result ^ hash()(rule.blank_); 284 | } 285 | } 286 | 287 | } // namespace std -------------------------------------------------------------------------------- /test/corpus/definitions.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Scoped function definitions 3 | ================================================================================ 4 | 5 | int T::foo() { return 1; } 6 | int T::foo() const { return 0; } 7 | 8 | -------------------------------------------------------------------------------- 9 | 10 | (translation_unit 11 | (function_definition 12 | (primitive_type) 13 | (function_declarator 14 | (qualified_identifier 15 | (namespace_identifier) 16 | (identifier)) 17 | (parameter_list)) 18 | (compound_statement 19 | (return_statement 20 | (number_literal)))) 21 | (function_definition 22 | (primitive_type) 23 | (function_declarator 24 | (qualified_identifier 25 | (namespace_identifier) 26 | (identifier)) 27 | (parameter_list) 28 | (type_qualifier)) 29 | (compound_statement 30 | (return_statement 31 | (number_literal))))) 32 | 33 | ================================================================================ 34 | Constructor definitions 35 | ================================================================================ 36 | 37 | T::T() {} 38 | 39 | T::T() : f1(0), f2(1, 2) { 40 | puts("HI"); 41 | } 42 | 43 | T::T() : Base() {} 44 | 45 | T::T() try : f1(0) {} catch(...) {} 46 | 47 | -------------------------------------------------------------------------------- 48 | 49 | (translation_unit 50 | (function_definition 51 | (function_declarator 52 | (qualified_identifier 53 | (namespace_identifier) 54 | (identifier)) 55 | (parameter_list)) 56 | (compound_statement)) 57 | (function_definition 58 | (function_declarator 59 | (qualified_identifier 60 | (namespace_identifier) 61 | (identifier)) 62 | (parameter_list)) 63 | (field_initializer_list 64 | (field_initializer 65 | (field_identifier) 66 | (argument_list 67 | (number_literal))) 68 | (field_initializer 69 | (field_identifier) 70 | (argument_list 71 | (number_literal) 72 | (number_literal)))) 73 | (compound_statement 74 | (expression_statement 75 | (call_expression 76 | (identifier) 77 | (argument_list 78 | (string_literal 79 | (string_content))))))) 80 | (function_definition 81 | (function_declarator 82 | (qualified_identifier 83 | (namespace_identifier) 84 | (identifier)) 85 | (parameter_list)) 86 | (field_initializer_list 87 | (field_initializer 88 | (template_method 89 | (field_identifier) 90 | (template_argument_list 91 | (type_descriptor 92 | (type_identifier)))) 93 | (argument_list))) 94 | (compound_statement)) 95 | (function_definition 96 | (function_declarator 97 | (qualified_identifier 98 | (namespace_identifier) 99 | (identifier)) 100 | (parameter_list)) 101 | (try_statement 102 | (field_initializer_list 103 | (field_initializer 104 | (field_identifier) 105 | (argument_list 106 | (number_literal)))) 107 | (compound_statement) 108 | (catch_clause 109 | (parameter_list) 110 | (compound_statement))))) 111 | 112 | ================================================================================ 113 | Explicit constructor definitions 114 | ================================================================================ 115 | 116 | class C { 117 | explicit C(int f) : f_(f) {} 118 | 119 | private: 120 | int f_; 121 | }; 122 | 123 | -------------------------------------------------------------------------------- 124 | 125 | (translation_unit 126 | (class_specifier 127 | (type_identifier) 128 | (field_declaration_list 129 | (function_definition 130 | (explicit_function_specifier) 131 | (function_declarator 132 | (identifier) 133 | (parameter_list 134 | (parameter_declaration 135 | (primitive_type) 136 | (identifier)))) 137 | (field_initializer_list 138 | (field_initializer 139 | (field_identifier) 140 | (argument_list 141 | (identifier)))) 142 | (compound_statement)) 143 | (access_specifier) 144 | (field_declaration 145 | (primitive_type) 146 | (field_identifier))))) 147 | 148 | ================================================================================ 149 | Explicit constructor declaration 150 | ================================================================================ 151 | 152 | class C { 153 | explicit C(int f); 154 | explicit(true) C(long f); 155 | }; 156 | 157 | -------------------------------------------------------------------------------- 158 | 159 | (translation_unit 160 | (class_specifier 161 | (type_identifier) 162 | (field_declaration_list 163 | (declaration 164 | (explicit_function_specifier) 165 | (function_declarator 166 | (identifier) 167 | (parameter_list 168 | (parameter_declaration 169 | (primitive_type) 170 | (identifier))))) 171 | (declaration 172 | (explicit_function_specifier 173 | (true)) 174 | (function_declarator 175 | (identifier) 176 | (parameter_list 177 | (parameter_declaration 178 | (sized_type_specifier) 179 | (identifier)))))))) 180 | 181 | ================================================================================ 182 | Default and deleted methods 183 | ================================================================================ 184 | 185 | class A : public B { 186 | A() = default; 187 | A(A &&) = delete; 188 | void f() = delete; 189 | A& operator=(const A&) = default; 190 | A& operator=(A&&) = delete; 191 | }; 192 | 193 | -------------------------------------------------------------------------------- 194 | 195 | (translation_unit 196 | (class_specifier 197 | (type_identifier) 198 | (base_class_clause 199 | (access_specifier) 200 | (type_identifier)) 201 | (field_declaration_list 202 | (function_definition 203 | (function_declarator 204 | (identifier) 205 | (parameter_list)) 206 | (default_method_clause)) 207 | (function_definition 208 | (function_declarator 209 | (identifier) 210 | (parameter_list 211 | (parameter_declaration 212 | (type_identifier) 213 | (abstract_reference_declarator)))) 214 | (delete_method_clause)) 215 | (function_definition 216 | (primitive_type) 217 | (function_declarator 218 | (field_identifier) 219 | (parameter_list)) 220 | (delete_method_clause)) 221 | (function_definition 222 | (type_identifier) 223 | (reference_declarator 224 | (function_declarator 225 | (operator_name) 226 | (parameter_list 227 | (parameter_declaration 228 | (type_qualifier) 229 | (type_identifier) 230 | (abstract_reference_declarator))))) 231 | (default_method_clause)) 232 | (function_definition 233 | (type_identifier) 234 | (reference_declarator 235 | (function_declarator 236 | (operator_name) 237 | (parameter_list 238 | (parameter_declaration 239 | (type_identifier) 240 | (abstract_reference_declarator))))) 241 | (delete_method_clause))))) 242 | 243 | ================================================================================ 244 | Destructor definitions 245 | ================================================================================ 246 | 247 | ~T() {} 248 | T::~T() {} 249 | 250 | -------------------------------------------------------------------------------- 251 | 252 | (translation_unit 253 | (function_definition 254 | (function_declarator 255 | (destructor_name 256 | (identifier)) 257 | (parameter_list)) 258 | (compound_statement)) 259 | (function_definition 260 | (function_declarator 261 | (qualified_identifier 262 | (namespace_identifier) 263 | (destructor_name 264 | (identifier))) 265 | (parameter_list)) 266 | (compound_statement))) 267 | 268 | ================================================================================ 269 | Function-try-block definitions 270 | ================================================================================ 271 | 272 | void foo() try {} catch(...) {} 273 | 274 | -------------------------------------------------------------------------------- 275 | 276 | (translation_unit 277 | (function_definition 278 | (primitive_type) 279 | (function_declarator 280 | (identifier) 281 | (parameter_list)) 282 | (try_statement 283 | (compound_statement) 284 | (catch_clause 285 | (parameter_list) 286 | (compound_statement))))) 287 | 288 | ================================================================================ 289 | Conversion operator definitions 290 | ================================================================================ 291 | 292 | T::operator int() try { throw 1; } catch (...) { return 2; } 293 | 294 | -------------------------------------------------------------------------------- 295 | 296 | (translation_unit 297 | (function_definition 298 | (qualified_identifier 299 | (namespace_identifier) 300 | (operator_cast 301 | (primitive_type) 302 | (abstract_function_declarator 303 | (parameter_list)))) 304 | (try_statement 305 | (compound_statement 306 | (throw_statement 307 | (number_literal))) 308 | (catch_clause 309 | (parameter_list) 310 | (compound_statement 311 | (return_statement 312 | (number_literal))))))) 313 | -------------------------------------------------------------------------------- /test/corpus/c/preprocessor.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Include directives 3 | ================================================================================ 4 | 5 | #include "some/path.h" 6 | #include 7 | #include MACRO 8 | #include MACRO(arg1, arg2) 9 | 10 | -------------------------------------------------------------------------------- 11 | 12 | (translation_unit 13 | (preproc_include 14 | path: (string_literal 15 | (string_content))) 16 | (preproc_include 17 | path: (system_lib_string)) 18 | (preproc_include 19 | path: (identifier)) 20 | (preproc_include 21 | path: (call_expression 22 | function: (identifier) 23 | arguments: (argument_list 24 | (identifier) 25 | (identifier))))) 26 | 27 | ================================================================================ 28 | Object-like macro definitions 29 | ================================================================================ 30 | 31 | #define ONE 32 | #define TWO int a = b; 33 | #define THREE \ 34 | c == d ? \ 35 | e : \ 36 | f 37 | #define FOUR (mno * pq) 38 | #define FIVE(a,b) x \ 39 | + y 40 | #define SIX(a, \ 41 | b) x \ 42 | + y 43 | #define SEVEN 7/* seven has an 44 | * annoying comment */ 45 | #define EIGHT(x) do { \ 46 | x = x + 1; \ 47 | x = x / 2; \ 48 | } while (x > 0); 49 | 50 | -------------------------------------------------------------------------------- 51 | 52 | (translation_unit 53 | (preproc_def 54 | name: (identifier)) 55 | (preproc_def 56 | name: (identifier) 57 | value: (preproc_arg)) 58 | (preproc_def 59 | name: (identifier) 60 | value: (preproc_arg)) 61 | (preproc_def 62 | name: (identifier) 63 | value: (preproc_arg)) 64 | (preproc_function_def 65 | name: (identifier) 66 | parameters: (preproc_params 67 | (identifier) 68 | (identifier)) 69 | value: (preproc_arg)) 70 | (preproc_function_def 71 | name: (identifier) 72 | parameters: (preproc_params 73 | (identifier) 74 | (identifier)) 75 | value: (preproc_arg)) 76 | (preproc_def 77 | name: (identifier) 78 | value: (preproc_arg) 79 | (comment)) 80 | (preproc_function_def 81 | name: (identifier) 82 | parameters: (preproc_params 83 | (identifier)) 84 | value: (preproc_arg))) 85 | 86 | ================================================================================ 87 | Function-like macro definitions 88 | ================================================================================ 89 | 90 | #define ONE() a 91 | #define TWO(b) c 92 | #define THREE(d, e) f 93 | #define FOUR(...) g 94 | #define FIVE(h, i, ...) j 95 | 96 | -------------------------------------------------------------------------------- 97 | 98 | (translation_unit 99 | (preproc_function_def 100 | name: (identifier) 101 | parameters: (preproc_params) 102 | value: (preproc_arg)) 103 | (preproc_function_def 104 | name: (identifier) 105 | parameters: (preproc_params 106 | (identifier)) 107 | value: (preproc_arg)) 108 | (preproc_function_def 109 | name: (identifier) 110 | parameters: (preproc_params 111 | (identifier) 112 | (identifier)) 113 | value: (preproc_arg)) 114 | (preproc_function_def 115 | name: (identifier) 116 | parameters: (preproc_params) 117 | value: (preproc_arg)) 118 | (preproc_function_def 119 | name: (identifier) 120 | parameters: (preproc_params 121 | (identifier) 122 | (identifier)) 123 | value: (preproc_arg))) 124 | 125 | ================================================================================ 126 | Ifdefs 127 | ================================================================================ 128 | 129 | #ifndef DEFINE1 130 | int j; 131 | #endif 132 | 133 | #ifdef DEFINE2 134 | ssize_t b; 135 | #define c 32 136 | #elif defined DEFINE3 137 | #else 138 | int b; 139 | #define c 16 140 | #endif 141 | 142 | #ifdef DEFINE2 143 | #else 144 | # ifdef DEFINE3 145 | # else 146 | # endif 147 | #endif 148 | 149 | -------------------------------------------------------------------------------- 150 | 151 | (translation_unit 152 | (preproc_ifdef 153 | name: (identifier) 154 | (declaration 155 | type: (primitive_type) 156 | declarator: (identifier))) 157 | (preproc_ifdef 158 | name: (identifier) 159 | (declaration 160 | type: (primitive_type) 161 | declarator: (identifier)) 162 | (preproc_def 163 | name: (identifier) 164 | value: (preproc_arg)) 165 | alternative: (preproc_elif 166 | condition: (preproc_defined 167 | (identifier)) 168 | alternative: (preproc_else 169 | (declaration 170 | type: (primitive_type) 171 | declarator: (identifier)) 172 | (preproc_def 173 | name: (identifier) 174 | value: (preproc_arg))))) 175 | (preproc_ifdef 176 | name: (identifier) 177 | alternative: (preproc_else 178 | (preproc_ifdef 179 | name: (identifier) 180 | alternative: (preproc_else))))) 181 | 182 | ================================================================================ 183 | Elifdefs 184 | ================================================================================ 185 | 186 | #ifndef DEFINE1 187 | int j; 188 | #elifndef DEFINE2 189 | int k; 190 | #endif 191 | 192 | #ifdef DEFINE2 193 | ssize_t b; 194 | #elifdef DEFINE3 195 | ssize_t c; 196 | #else 197 | int b; 198 | #endif 199 | 200 | -------------------------------------------------------------------------------- 201 | 202 | (translation_unit 203 | (preproc_ifdef 204 | (identifier) 205 | (declaration 206 | (primitive_type) 207 | (identifier)) 208 | (preproc_elifdef 209 | (identifier) 210 | (declaration 211 | (primitive_type) 212 | (identifier)))) 213 | (preproc_ifdef 214 | (identifier) 215 | (declaration 216 | (primitive_type) 217 | (identifier)) 218 | (preproc_elifdef 219 | (identifier) 220 | (declaration 221 | (primitive_type) 222 | (identifier)) 223 | (preproc_else 224 | (declaration 225 | (primitive_type) 226 | (identifier)))))) 227 | 228 | ================================================================================ 229 | General if blocks 230 | ================================================================================ 231 | 232 | #if defined(__GNUC__) && defined(__PIC__) 233 | #define inline inline __attribute__((always_inline)) 234 | #elif defined(_WIN32) 235 | #define something 236 | #elif !defined(SOMETHING_ELSE) 237 | #define SOMETHING_ELSE 238 | #else 239 | #include 240 | #endif 241 | 242 | -------------------------------------------------------------------------------- 243 | 244 | (translation_unit 245 | (preproc_if 246 | condition: (binary_expression 247 | left: (preproc_defined 248 | (identifier)) 249 | right: (preproc_defined 250 | (identifier))) 251 | (preproc_def 252 | name: (identifier) 253 | value: (preproc_arg)) 254 | alternative: (preproc_elif 255 | condition: (preproc_defined 256 | (identifier)) 257 | (preproc_def 258 | name: (identifier)) 259 | alternative: (preproc_elif 260 | condition: (unary_expression 261 | argument: (preproc_defined 262 | (identifier))) 263 | (preproc_def 264 | name: (identifier)) 265 | alternative: (preproc_else 266 | (preproc_include 267 | path: (system_lib_string))))))) 268 | 269 | ================================================================================ 270 | Preprocessor conditionals in functions 271 | ================================================================================ 272 | 273 | int main() { 274 | #if d 275 | puts("1"); 276 | #else 277 | puts("2"); 278 | #endif 279 | 280 | #if a 281 | return 0; 282 | #elif b 283 | return 1; 284 | #elif c 285 | return 2; 286 | #else 287 | return 3; 288 | #endif 289 | } 290 | 291 | -------------------------------------------------------------------------------- 292 | 293 | (translation_unit 294 | (function_definition 295 | (primitive_type) 296 | (function_declarator 297 | (identifier) 298 | (parameter_list)) 299 | (compound_statement 300 | (preproc_if 301 | (identifier) 302 | (expression_statement 303 | (call_expression 304 | (identifier) 305 | (argument_list 306 | (string_literal 307 | (string_content))))) 308 | (preproc_else 309 | (expression_statement 310 | (call_expression 311 | (identifier) 312 | (argument_list 313 | (string_literal 314 | (string_content))))))) 315 | (preproc_if 316 | (identifier) 317 | (return_statement 318 | (number_literal)) 319 | (preproc_elif 320 | (identifier) 321 | (return_statement 322 | (number_literal)) 323 | (preproc_elif 324 | (identifier) 325 | (return_statement 326 | (number_literal)) 327 | (preproc_else 328 | (return_statement 329 | (number_literal))))))))) 330 | 331 | ================================================================================ 332 | Preprocessor conditionals in struct/union bodies 333 | ================================================================================ 334 | 335 | struct S { 336 | #ifdef _WIN32 337 | LONG f2; 338 | #else 339 | uint32_t f2; 340 | #endif 341 | }; 342 | 343 | -------------------------------------------------------------------------------- 344 | 345 | (translation_unit 346 | (struct_specifier 347 | (type_identifier) 348 | (field_declaration_list 349 | (preproc_ifdef 350 | (identifier) 351 | (field_declaration 352 | (type_identifier) 353 | (field_identifier)) 354 | (preproc_else 355 | (field_declaration 356 | (primitive_type) 357 | (field_identifier))))))) 358 | 359 | ================================================================================ 360 | Unknown preprocessor directives 361 | ================================================================================ 362 | 363 | #pragma mark - UIViewController 364 | 365 | -------------------------------------------------------------------------------- 366 | 367 | (translation_unit 368 | (preproc_call 369 | directive: (preproc_directive) 370 | argument: (preproc_arg))) 371 | 372 | ================================================================================ 373 | Preprocessor expressions 374 | ================================================================================ 375 | 376 | #if A(B || C) && \ 377 | !D(F) 378 | 379 | uint32_t a; 380 | 381 | #endif 382 | 383 | -------------------------------------------------------------------------------- 384 | 385 | (translation_unit 386 | (preproc_if 387 | (binary_expression 388 | (call_expression 389 | (identifier) 390 | (argument_list 391 | (binary_expression 392 | (identifier) 393 | (identifier)))) 394 | (unary_expression 395 | (call_expression 396 | (identifier) 397 | (argument_list 398 | (identifier))))) 399 | (declaration 400 | (primitive_type) 401 | (identifier)))) 402 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/corpus/c/statements.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | If statements 3 | ================================================================================ 4 | 5 | int main() { 6 | if (a) 7 | 1; 8 | 9 | if (!a) { 10 | 2; 11 | } else { 12 | 3; 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- 17 | 18 | (translation_unit 19 | (function_definition 20 | (primitive_type) 21 | (function_declarator 22 | (identifier) 23 | (parameter_list)) 24 | (compound_statement 25 | (if_statement 26 | (condition_clause 27 | (identifier)) 28 | (expression_statement 29 | (number_literal))) 30 | (if_statement 31 | (condition_clause 32 | (unary_expression 33 | (identifier))) 34 | (compound_statement 35 | (expression_statement 36 | (number_literal))) 37 | (else_clause 38 | (compound_statement 39 | (expression_statement 40 | (number_literal)))))))) 41 | 42 | ================================================================================ 43 | For loops 44 | ================================================================================ 45 | 46 | int main() { 47 | for (;;) 48 | 1; 49 | 50 | for (int i = 0; i < 5; next(), i++) { 51 | 2; 52 | } 53 | 54 | for (start(); check(); step()) 55 | 3; 56 | 57 | for (i = 0, j = 0, k = 0, l = 0; i < 1, j < 1; i++, j++, k++, l++) 58 | 1; 59 | } 60 | 61 | -------------------------------------------------------------------------------- 62 | 63 | (translation_unit 64 | (function_definition 65 | (primitive_type) 66 | (function_declarator 67 | (identifier) 68 | (parameter_list)) 69 | (compound_statement 70 | (for_statement 71 | (expression_statement 72 | (number_literal))) 73 | (for_statement 74 | (declaration 75 | (primitive_type) 76 | (init_declarator 77 | (identifier) 78 | (number_literal))) 79 | (binary_expression 80 | (identifier) 81 | (number_literal)) 82 | (comma_expression 83 | (call_expression 84 | (identifier) 85 | (argument_list)) 86 | (update_expression 87 | (identifier))) 88 | (compound_statement 89 | (expression_statement 90 | (number_literal)))) 91 | (for_statement 92 | (call_expression 93 | (identifier) 94 | (argument_list)) 95 | (call_expression 96 | (identifier) 97 | (argument_list)) 98 | (call_expression 99 | (identifier) 100 | (argument_list)) 101 | (expression_statement 102 | (number_literal))) 103 | (for_statement 104 | (comma_expression 105 | (assignment_expression 106 | (identifier) 107 | (number_literal)) 108 | (comma_expression 109 | (assignment_expression 110 | (identifier) 111 | (number_literal)) 112 | (comma_expression 113 | (assignment_expression 114 | (identifier) 115 | (number_literal)) 116 | (assignment_expression 117 | (identifier) 118 | (number_literal))))) 119 | (comma_expression 120 | (binary_expression 121 | (identifier) 122 | (number_literal)) 123 | (binary_expression 124 | (identifier) 125 | (number_literal))) 126 | (comma_expression 127 | (update_expression 128 | (identifier)) 129 | (comma_expression 130 | (update_expression 131 | (identifier)) 132 | (comma_expression 133 | (update_expression 134 | (identifier)) 135 | (update_expression 136 | (identifier))))) 137 | (expression_statement 138 | (number_literal)))))) 139 | 140 | ================================================================================ 141 | While loops 142 | ================================================================================ 143 | 144 | int main() { 145 | while (x) 146 | printf("hi"); 147 | } 148 | 149 | -------------------------------------------------------------------------------- 150 | 151 | (translation_unit 152 | (function_definition 153 | (primitive_type) 154 | (function_declarator 155 | (identifier) 156 | (parameter_list)) 157 | (compound_statement 158 | (while_statement 159 | (condition_clause 160 | (identifier)) 161 | (expression_statement 162 | (call_expression 163 | (identifier) 164 | (argument_list 165 | (string_literal 166 | (string_content))))))))) 167 | 168 | ================================================================================ 169 | Labeled statements 170 | ================================================================================ 171 | 172 | void foo(T *t) { 173 | recur: 174 | t = t->next(); 175 | if (t) goto recur; 176 | } 177 | 178 | -------------------------------------------------------------------------------- 179 | 180 | (translation_unit 181 | (function_definition 182 | (primitive_type) 183 | (function_declarator 184 | (identifier) 185 | (parameter_list 186 | (parameter_declaration 187 | (type_identifier) 188 | (pointer_declarator 189 | (identifier))))) 190 | (compound_statement 191 | (labeled_statement 192 | (statement_identifier) 193 | (expression_statement 194 | (assignment_expression 195 | (identifier) 196 | (call_expression 197 | (field_expression 198 | (identifier) 199 | (field_identifier)) 200 | (argument_list))))) 201 | (if_statement 202 | (condition_clause 203 | (identifier)) 204 | (goto_statement 205 | (statement_identifier)))))) 206 | 207 | ================================================================================ 208 | Switch statements 209 | ================================================================================ 210 | 211 | void foo(int a) { 212 | switch (a) { 213 | puts("entered switch!"); 214 | 215 | case 3: 216 | case 5: 217 | if (b) { 218 | c(); 219 | } 220 | break; 221 | 222 | default: 223 | c(); 224 | break; 225 | } 226 | } 227 | 228 | -------------------------------------------------------------------------------- 229 | 230 | (translation_unit 231 | (function_definition 232 | (primitive_type) 233 | (function_declarator 234 | (identifier) 235 | (parameter_list 236 | (parameter_declaration 237 | (primitive_type) 238 | (identifier)))) 239 | (compound_statement 240 | (switch_statement 241 | (condition_clause 242 | (identifier)) 243 | (compound_statement 244 | (expression_statement 245 | (call_expression 246 | (identifier) 247 | (argument_list 248 | (string_literal 249 | (string_content))))) 250 | (case_statement 251 | (number_literal)) 252 | (case_statement 253 | (number_literal) 254 | (if_statement 255 | (condition_clause 256 | (identifier)) 257 | (compound_statement 258 | (expression_statement 259 | (call_expression 260 | (identifier) 261 | (argument_list))))) 262 | (break_statement)) 263 | (case_statement 264 | (expression_statement 265 | (call_expression 266 | (identifier) 267 | (argument_list))) 268 | (break_statement))))))) 269 | 270 | ================================================================================ 271 | Case statements separate from switch statements 272 | ================================================================================ 273 | 274 | int main() { 275 | switch (count % 8) { 276 | case 0: 277 | do { 278 | *to = *from++; 279 | case 2: *to = *from++; 280 | case 1: *to = *from++; 281 | } while (--n > 0); 282 | } 283 | } 284 | 285 | -------------------------------------------------------------------------------- 286 | 287 | (translation_unit 288 | (function_definition 289 | (primitive_type) 290 | (function_declarator 291 | (identifier) 292 | (parameter_list)) 293 | (compound_statement 294 | (switch_statement 295 | (condition_clause 296 | (binary_expression 297 | (identifier) 298 | (number_literal))) 299 | (compound_statement 300 | (case_statement 301 | (number_literal) 302 | (do_statement 303 | (compound_statement 304 | (expression_statement 305 | (assignment_expression 306 | (pointer_expression 307 | (identifier)) 308 | (pointer_expression 309 | (update_expression 310 | (identifier))))) 311 | (case_statement 312 | (number_literal) 313 | (expression_statement 314 | (assignment_expression 315 | (pointer_expression 316 | (identifier)) 317 | (pointer_expression 318 | (update_expression 319 | (identifier)))))) 320 | (case_statement 321 | (number_literal) 322 | (expression_statement 323 | (assignment_expression 324 | (pointer_expression 325 | (identifier)) 326 | (pointer_expression 327 | (update_expression 328 | (identifier))))))) 329 | (parenthesized_expression 330 | (binary_expression 331 | (update_expression 332 | (identifier)) 333 | (number_literal)))))))))) 334 | 335 | ================================================================================ 336 | Return statements 337 | ================================================================================ 338 | 339 | void foo() { 340 | return; 341 | return a; 342 | return a, b; 343 | } 344 | 345 | -------------------------------------------------------------------------------- 346 | 347 | (translation_unit 348 | (function_definition 349 | (primitive_type) 350 | (function_declarator 351 | (identifier) 352 | (parameter_list)) 353 | (compound_statement 354 | (return_statement) 355 | (return_statement 356 | (identifier)) 357 | (return_statement 358 | (comma_expression 359 | (identifier) 360 | (identifier)))))) 361 | 362 | ================================================================================ 363 | Comments with asterisks 364 | ================================================================================ 365 | 366 | /************************* 367 | * odd number of asterisks 368 | *************************/ 369 | int a; 370 | 371 | /************************** 372 | * even number of asterisks 373 | **************************/ 374 | int b; 375 | 376 | -------------------------------------------------------------------------------- 377 | 378 | (translation_unit 379 | (comment) 380 | (declaration 381 | (primitive_type) 382 | (identifier)) 383 | (comment) 384 | (declaration 385 | (primitive_type) 386 | (identifier))) 387 | 388 | ================================================================================ 389 | Comment with multiple backslashes 390 | ================================================================================ 391 | 392 | int a = 3; // Hello \\ 393 | World 394 | 395 | -------------------------------------------------------------------------------- 396 | 397 | (translation_unit 398 | (declaration 399 | (primitive_type) 400 | (init_declarator 401 | (identifier) 402 | (number_literal))) 403 | (comment)) 404 | 405 | ================================================================================ 406 | Attributes 407 | ================================================================================ 408 | 409 | void f() { 410 | [[a]] switch (b) { 411 | [[c]] case 1: {} 412 | case 2: 413 | [[fallthrough]]; 414 | default: 415 | } 416 | [[a]] while (true) {} 417 | [[a]] if (true) {} 418 | [[a]] for (;;) {} 419 | [[a]] return; 420 | [[a]] a; 421 | [[a]]; 422 | [[a]] label: {} 423 | [[a]] goto label; 424 | 425 | // these are c++ specific, but their bind locations should be c-compatible 426 | if (true) [[likely]] {} else [[unlikely]] {} 427 | do [[likely]] {} while (true); 428 | } 429 | 430 | -------------------------------------------------------------------------------- 431 | 432 | (translation_unit 433 | (function_definition 434 | (primitive_type) 435 | (function_declarator 436 | (identifier) 437 | (parameter_list)) 438 | (compound_statement 439 | (attributed_statement 440 | (attribute_declaration 441 | (attribute 442 | (identifier))) 443 | (switch_statement 444 | (condition_clause 445 | (identifier)) 446 | (compound_statement 447 | (attributed_statement 448 | (attribute_declaration 449 | (attribute 450 | (identifier))) 451 | (case_statement 452 | (number_literal) 453 | (compound_statement))) 454 | (case_statement 455 | (number_literal) 456 | (attributed_statement 457 | (attribute_declaration 458 | (attribute 459 | (identifier))) 460 | (expression_statement))) 461 | (case_statement)))) 462 | (attributed_statement 463 | (attribute_declaration 464 | (attribute 465 | (identifier))) 466 | (while_statement 467 | (condition_clause 468 | (true)) 469 | (compound_statement))) 470 | (attributed_statement 471 | (attribute_declaration 472 | (attribute 473 | (identifier))) 474 | (if_statement 475 | (condition_clause 476 | (true)) 477 | (compound_statement))) 478 | (attributed_statement 479 | (attribute_declaration 480 | (attribute 481 | (identifier))) 482 | (for_statement 483 | (compound_statement))) 484 | (attributed_statement 485 | (attribute_declaration 486 | (attribute 487 | (identifier))) 488 | (return_statement)) 489 | (attributed_statement 490 | (attribute_declaration 491 | (attribute 492 | (identifier))) 493 | (expression_statement 494 | (identifier))) 495 | (attributed_statement 496 | (attribute_declaration 497 | (attribute 498 | (identifier))) 499 | (expression_statement)) 500 | (attributed_statement 501 | (attribute_declaration 502 | (attribute 503 | (identifier))) 504 | (labeled_statement 505 | (statement_identifier) 506 | (compound_statement))) 507 | (attributed_statement 508 | (attribute_declaration 509 | (attribute 510 | (identifier))) 511 | (goto_statement 512 | (statement_identifier))) 513 | (comment) 514 | (if_statement 515 | (condition_clause 516 | (true)) 517 | (attributed_statement 518 | (attribute_declaration 519 | (attribute 520 | (identifier))) 521 | (compound_statement)) 522 | (else_clause 523 | (attributed_statement 524 | (attribute_declaration 525 | (attribute 526 | (identifier))) 527 | (compound_statement)))) 528 | (do_statement 529 | (attributed_statement 530 | (attribute_declaration 531 | (attribute 532 | (identifier))) 533 | (compound_statement)) 534 | (parenthesized_expression 535 | (true)))))) 536 | -------------------------------------------------------------------------------- /test/corpus/statements.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Returning braced initializer lists 3 | ================================================================================ 4 | 5 | T main() { 6 | return {0, 5}; 7 | } 8 | 9 | -------------------------------------------------------------------------------- 10 | 11 | (translation_unit 12 | (function_definition 13 | (type_identifier) 14 | (function_declarator 15 | (identifier) 16 | (parameter_list)) 17 | (compound_statement 18 | (return_statement 19 | (initializer_list 20 | (number_literal) 21 | (number_literal)))))) 22 | 23 | ================================================================================ 24 | Range-based for loops 25 | ================================================================================ 26 | 27 | T main() { 28 | for (Value &value : values) { 29 | cout << value; 30 | } 31 | 32 | for (const auto &value : values) { 33 | cout << value; 34 | } 35 | 36 | for (const auto &value : {1, 2, 3}) { 37 | cout << value; 38 | } 39 | 40 | for (auto n = v.size(); auto i : v) { 41 | cout << --n + i << ' '; 42 | } 43 | 44 | for (using elem_t = T::value_type; elem_t i : v) { 45 | cout << --n + i << ' '; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- 50 | 51 | (translation_unit 52 | (function_definition 53 | type: (type_identifier) 54 | declarator: (function_declarator 55 | declarator: (identifier) 56 | parameters: (parameter_list)) 57 | body: (compound_statement 58 | (for_range_loop 59 | type: (type_identifier) 60 | declarator: (reference_declarator 61 | (identifier)) 62 | right: (identifier) 63 | body: (compound_statement 64 | (expression_statement 65 | (binary_expression 66 | left: (identifier) 67 | right: (identifier))))) 68 | (for_range_loop 69 | (type_qualifier) 70 | type: (placeholder_type_specifier 71 | (auto)) 72 | declarator: (reference_declarator 73 | (identifier)) 74 | right: (identifier) 75 | body: (compound_statement 76 | (expression_statement 77 | (binary_expression 78 | left: (identifier) 79 | right: (identifier))))) 80 | (for_range_loop 81 | (type_qualifier) 82 | type: (placeholder_type_specifier 83 | (auto)) 84 | declarator: (reference_declarator 85 | (identifier)) 86 | right: (initializer_list 87 | (number_literal) 88 | (number_literal) 89 | (number_literal)) 90 | body: (compound_statement 91 | (expression_statement 92 | (binary_expression 93 | left: (identifier) 94 | right: (identifier))))) 95 | (for_range_loop 96 | initializer: (init_statement 97 | (declaration 98 | type: (placeholder_type_specifier 99 | (auto)) 100 | declarator: (init_declarator 101 | declarator: (identifier) 102 | value: (call_expression 103 | function: (field_expression 104 | argument: (identifier) 105 | field: (field_identifier)) 106 | arguments: (argument_list))))) 107 | type: (placeholder_type_specifier 108 | (auto)) 109 | declarator: (identifier) 110 | right: (identifier) 111 | body: (compound_statement 112 | (expression_statement 113 | (binary_expression 114 | left: (binary_expression 115 | left: (identifier) 116 | right: (binary_expression 117 | left: (update_expression 118 | argument: (identifier)) 119 | right: (identifier))) 120 | right: (char_literal 121 | (character)))))) 122 | (for_range_loop 123 | initializer: (init_statement 124 | (alias_declaration 125 | name: (type_identifier) 126 | type: (type_descriptor 127 | type: (qualified_identifier 128 | scope: (namespace_identifier) 129 | name: (type_identifier))))) 130 | type: (type_identifier) 131 | declarator: (identifier) 132 | right: (identifier) 133 | body: (compound_statement 134 | (expression_statement 135 | (binary_expression 136 | left: (binary_expression 137 | left: (identifier) 138 | right: (binary_expression 139 | left: (update_expression 140 | argument: (identifier)) 141 | right: (identifier))) 142 | right: (char_literal 143 | (character))))))))) 144 | 145 | ================================================================================ 146 | Constexpr if statements 147 | ================================================================================ 148 | 149 | T f() { 150 | if constexpr (std::is_pointer_v) 151 | return *t; 152 | else 153 | return t; 154 | } 155 | 156 | -------------------------------------------------------------------------------- 157 | 158 | (translation_unit 159 | (function_definition 160 | type: (type_identifier) 161 | declarator: (function_declarator 162 | declarator: (identifier) 163 | parameters: (parameter_list)) 164 | body: (compound_statement 165 | (if_statement 166 | condition: (condition_clause 167 | value: (qualified_identifier 168 | scope: (namespace_identifier) 169 | name: (template_function 170 | name: (identifier) 171 | arguments: (template_argument_list 172 | (type_descriptor 173 | type: (type_identifier)))))) 174 | consequence: (return_statement 175 | (pointer_expression 176 | argument: (identifier))) 177 | alternative: (else_clause 178 | (return_statement 179 | (identifier))))))) 180 | 181 | ================================================================================ 182 | If statements with declarations 183 | ================================================================================ 184 | 185 | void f() { 186 | if (const int x = foo()) { } 187 | if (const int x { foo() }) { } 188 | if (const int x = foo(); x != 0) { } 189 | } 190 | 191 | -------------------------------------------------------------------------------- 192 | 193 | (translation_unit 194 | (function_definition 195 | type: (primitive_type) 196 | declarator: (function_declarator 197 | declarator: (identifier) 198 | parameters: (parameter_list)) 199 | body: (compound_statement 200 | (if_statement 201 | condition: (condition_clause 202 | value: (declaration 203 | (type_qualifier) 204 | type: (primitive_type) 205 | declarator: (identifier) 206 | value: (call_expression 207 | function: (identifier) 208 | arguments: (argument_list)))) 209 | consequence: (compound_statement)) 210 | (if_statement 211 | condition: (condition_clause 212 | value: (declaration 213 | (type_qualifier) 214 | type: (primitive_type) 215 | declarator: (identifier) 216 | value: (initializer_list 217 | (call_expression 218 | function: (identifier) 219 | arguments: (argument_list))))) 220 | consequence: (compound_statement)) 221 | (if_statement 222 | condition: (condition_clause 223 | initializer: (init_statement 224 | (declaration 225 | (type_qualifier) 226 | type: (primitive_type) 227 | declarator: (init_declarator 228 | declarator: (identifier) 229 | value: (call_expression 230 | function: (identifier) 231 | arguments: (argument_list))))) 232 | value: (binary_expression 233 | left: (identifier) 234 | right: (number_literal))) 235 | consequence: (compound_statement))))) 236 | 237 | ================================================================================ 238 | Try/catch statements 239 | ================================================================================ 240 | 241 | void main() { 242 | try { 243 | f(); 244 | } catch (const std::overflow_error) { 245 | // f() throws std::overflow_error (same type rule) 246 | } catch (const exception &e) { 247 | // f() throws std::logic_error (base class rule) 248 | } catch (...) { 249 | // f() throws std::string or int or any other unrelated type 250 | } 251 | } 252 | 253 | -------------------------------------------------------------------------------- 254 | 255 | (translation_unit 256 | (function_definition 257 | (primitive_type) 258 | (function_declarator 259 | (identifier) 260 | (parameter_list)) 261 | (compound_statement 262 | (try_statement 263 | (compound_statement 264 | (expression_statement 265 | (call_expression 266 | (identifier) 267 | (argument_list)))) 268 | (catch_clause 269 | (parameter_list 270 | (parameter_declaration 271 | (type_qualifier) 272 | (qualified_identifier 273 | (namespace_identifier) 274 | (type_identifier)))) 275 | (compound_statement 276 | (comment))) 277 | (catch_clause 278 | (parameter_list 279 | (parameter_declaration 280 | (type_qualifier) 281 | (type_identifier) 282 | (reference_declarator 283 | (identifier)))) 284 | (compound_statement 285 | (comment))) 286 | (catch_clause 287 | (parameter_list) 288 | (compound_statement 289 | (comment))))))) 290 | 291 | ================================================================================ 292 | Throw statements 293 | ================================================================================ 294 | 295 | void main() { 296 | throw e; 297 | throw x + 1; 298 | throw "exception"; 299 | } 300 | 301 | -------------------------------------------------------------------------------- 302 | 303 | (translation_unit 304 | (function_definition 305 | (primitive_type) 306 | (function_declarator 307 | (identifier) 308 | (parameter_list)) 309 | (compound_statement 310 | (throw_statement 311 | (identifier)) 312 | (throw_statement 313 | (binary_expression 314 | (identifier) 315 | (number_literal))) 316 | (throw_statement 317 | (string_literal 318 | (string_content)))))) 319 | 320 | ================================================================================ 321 | Noexcept specifier 322 | ================================================================================ 323 | 324 | void foo() noexcept; 325 | void foo() noexcept(true); 326 | template T foo() noexcept(sizeof(T) < 4); 327 | 328 | -------------------------------------------------------------------------------- 329 | 330 | (translation_unit 331 | (declaration 332 | (primitive_type) 333 | (function_declarator 334 | (identifier) 335 | (parameter_list) 336 | (noexcept))) 337 | (declaration 338 | (primitive_type) 339 | (function_declarator 340 | (identifier) 341 | (parameter_list) 342 | (noexcept 343 | (true)))) 344 | (template_declaration 345 | (template_parameter_list 346 | (type_parameter_declaration 347 | (type_identifier))) 348 | (declaration 349 | (type_identifier) 350 | (function_declarator 351 | (identifier) 352 | (parameter_list) 353 | (noexcept 354 | (binary_expression 355 | (sizeof_expression 356 | (parenthesized_expression 357 | (identifier))) 358 | (number_literal))))))) 359 | 360 | ================================================================================ 361 | Throw specifier 362 | ================================================================================ 363 | 364 | void foo() throw(); 365 | void foo() throw(int); 366 | void foo() throw(std::string, char *); 367 | void foo() throw(float) { } 368 | 369 | -------------------------------------------------------------------------------- 370 | 371 | (translation_unit 372 | (declaration 373 | (primitive_type) 374 | (function_declarator 375 | (identifier) 376 | (parameter_list) 377 | (throw_specifier))) 378 | (declaration 379 | (primitive_type) 380 | (function_declarator 381 | (identifier) 382 | (parameter_list) 383 | (throw_specifier 384 | (type_descriptor 385 | (primitive_type))))) 386 | (declaration 387 | (primitive_type) 388 | (function_declarator 389 | (identifier) 390 | (parameter_list) 391 | (throw_specifier 392 | (type_descriptor 393 | (qualified_identifier 394 | (namespace_identifier) 395 | (type_identifier))) 396 | (type_descriptor 397 | (primitive_type) 398 | (abstract_pointer_declarator))))) 399 | (function_definition 400 | (primitive_type) 401 | (function_declarator 402 | (identifier) 403 | (parameter_list) 404 | (throw_specifier 405 | (type_descriptor 406 | (primitive_type)))) 407 | (compound_statement))) 408 | 409 | ================================================================================ 410 | Assignment 411 | ================================================================================ 412 | 413 | a::b::c = 1; 414 | 415 | -------------------------------------------------------------------------------- 416 | 417 | (translation_unit 418 | (expression_statement 419 | (assignment_expression 420 | (qualified_identifier 421 | (namespace_identifier) 422 | (qualified_identifier 423 | (namespace_identifier) 424 | (identifier))) 425 | (number_literal)))) 426 | 427 | ================================================================================ 428 | Attributes 429 | ================================================================================ 430 | 431 | void f() { 432 | [[a]] switch (b) { 433 | [[c]] case 1: {} 434 | } 435 | [[a]] while (true) {} 436 | [[a]] if (true) {} 437 | [[a]] for (auto x : y) {} 438 | [[a]] for (;;) {} 439 | [[a]] return; 440 | [[a]] a; 441 | [[a]]; 442 | [[a]] label: {} 443 | [[a]] goto label; 444 | } 445 | 446 | -------------------------------------------------------------------------------- 447 | 448 | (translation_unit 449 | (function_definition 450 | (primitive_type) 451 | (function_declarator 452 | (identifier) 453 | (parameter_list)) 454 | (compound_statement 455 | (attributed_statement 456 | (attribute_declaration 457 | (attribute 458 | (identifier))) 459 | (switch_statement 460 | (condition_clause 461 | (identifier)) 462 | (compound_statement 463 | (attributed_statement 464 | (attribute_declaration 465 | (attribute 466 | (identifier))) 467 | (case_statement 468 | (number_literal) 469 | (compound_statement)))))) 470 | (attributed_statement 471 | (attribute_declaration 472 | (attribute 473 | (identifier))) 474 | (while_statement 475 | (condition_clause 476 | (true)) 477 | (compound_statement))) 478 | (attributed_statement 479 | (attribute_declaration 480 | (attribute 481 | (identifier))) 482 | (if_statement 483 | (condition_clause 484 | (true)) 485 | (compound_statement))) 486 | (attributed_statement 487 | (attribute_declaration 488 | (attribute 489 | (identifier))) 490 | (for_range_loop 491 | (placeholder_type_specifier 492 | (auto)) 493 | (identifier) 494 | (identifier) 495 | (compound_statement))) 496 | (attributed_statement 497 | (attribute_declaration 498 | (attribute 499 | (identifier))) 500 | (for_statement 501 | (compound_statement))) 502 | (attributed_statement 503 | (attribute_declaration 504 | (attribute 505 | (identifier))) 506 | (return_statement)) 507 | (attributed_statement 508 | (attribute_declaration 509 | (attribute 510 | (identifier))) 511 | (expression_statement 512 | (identifier))) 513 | (attributed_statement 514 | (attribute_declaration 515 | (attribute 516 | (identifier))) 517 | (expression_statement)) 518 | (attributed_statement 519 | (attribute_declaration 520 | (attribute 521 | (identifier))) 522 | (labeled_statement 523 | (statement_identifier) 524 | (compound_statement))) 525 | (attributed_statement 526 | (attribute_declaration 527 | (attribute 528 | (identifier))) 529 | (goto_statement 530 | (statement_identifier)))))) 531 | 532 | ================================================================================ 533 | Coroutines 534 | ================================================================================ 535 | 536 | co_return 1; 537 | co_return; 538 | co_yield 1; 539 | 540 | -------------------------------------------------------------------------------- 541 | 542 | (translation_unit 543 | (co_return_statement 544 | (number_literal)) 545 | (co_return_statement) 546 | (co_yield_statement 547 | (number_literal))) 548 | 549 | ================================================================================ 550 | Switch statements 551 | ================================================================================ 552 | 553 | void foo(int a) { 554 | switch (a) { 555 | case 1: 556 | for (auto i : vec) {} 557 | case 2: 558 | try { 559 | // do something 560 | } catch(...) {} 561 | throw 1; 562 | case 3: 563 | co_return; 564 | default: 565 | co_yield a; 566 | } 567 | } 568 | 569 | -------------------------------------------------------------------------------- 570 | 571 | (translation_unit 572 | (function_definition 573 | (primitive_type) 574 | (function_declarator 575 | (identifier) 576 | (parameter_list 577 | (parameter_declaration 578 | (primitive_type) 579 | (identifier)))) 580 | (compound_statement 581 | (switch_statement 582 | (condition_clause 583 | (identifier)) 584 | (compound_statement 585 | (case_statement 586 | (number_literal) 587 | (for_range_loop 588 | (placeholder_type_specifier 589 | (auto)) 590 | (identifier) 591 | (identifier) 592 | (compound_statement))) 593 | (case_statement 594 | (number_literal) 595 | (try_statement 596 | (compound_statement 597 | (comment)) 598 | (catch_clause 599 | (parameter_list) 600 | (compound_statement))) 601 | (throw_statement 602 | (number_literal))) 603 | (case_statement 604 | (number_literal) 605 | (co_return_statement)) 606 | (case_statement 607 | (co_yield_statement 608 | (identifier)))))))) 609 | -------------------------------------------------------------------------------- /test/corpus/concepts.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Concept definition 3 | ================================================================================ 4 | 5 | template 6 | concept Derived = std::is_base_of::value; 7 | -------------------------------------------------------------------------------- 8 | 9 | (translation_unit 10 | (template_declaration 11 | (template_parameter_list 12 | (type_parameter_declaration 13 | (type_identifier)) 14 | (type_parameter_declaration 15 | (type_identifier))) 16 | (concept_definition 17 | (identifier) 18 | (qualified_identifier 19 | (namespace_identifier) 20 | (qualified_identifier 21 | (template_type 22 | (type_identifier) 23 | (template_argument_list 24 | (type_descriptor 25 | (type_identifier)) 26 | (type_descriptor 27 | (type_identifier)))) 28 | (identifier)))))) 29 | 30 | ================================================================================ 31 | Concept definition with requires expression 32 | ================================================================================ 33 | 34 | template 35 | concept Hashable = requires(T a) { 36 | { std::hash{}(a) } -> std::convertible_to; 37 | }; 38 | -------------------------------------------------------------------------------- 39 | 40 | (translation_unit 41 | (template_declaration 42 | (template_parameter_list 43 | (type_parameter_declaration 44 | (type_identifier))) 45 | (concept_definition 46 | (identifier) 47 | (requires_expression 48 | (parameter_list 49 | (parameter_declaration 50 | (type_identifier) 51 | (identifier))) 52 | (requirement_seq 53 | (compound_requirement 54 | (call_expression 55 | (compound_literal_expression 56 | (qualified_identifier 57 | (namespace_identifier) 58 | (template_type 59 | (type_identifier) 60 | (template_argument_list 61 | (type_descriptor 62 | (type_identifier))))) 63 | (initializer_list)) 64 | (argument_list 65 | (identifier))) 66 | (trailing_return_type 67 | (type_descriptor 68 | (qualified_identifier 69 | (namespace_identifier) 70 | (template_type 71 | (type_identifier) 72 | (template_argument_list 73 | (type_descriptor 74 | (qualified_identifier 75 | (namespace_identifier) 76 | (type_identifier)))))))))))))) 77 | 78 | ================================================================================ 79 | Requires clauses and expressions 80 | ================================================================================ 81 | 82 | template 83 | void f(T&&) requires Eq; // can appear as the last element of a function declarator 84 | 85 | template requires Addable // or right after a template parameter list 86 | T add(T a, T b) { return a + b; } 87 | 88 | template 89 | concept Addable = requires (T x) { x + x; }; // requires-expression 90 | 91 | template 92 | requires requires (T x) { x + x; } // ad-hoc constraint, note keyword used twice 93 | T add(T a, T b) { return a + b; } 94 | 95 | template 96 | requires (!std::is_same_v) // parenthesized expressions are allowed 97 | void f(T); 98 | 99 | template requires Addable && Subtractable // conjunctions 100 | T f(T); 101 | 102 | template requires Addable and Subtractable // conjunctions 103 | T f(T); 104 | 105 | template requires Addable || Subtractable // disjunctions 106 | T f(T); 107 | 108 | template requires Addable or Subtractable // conjunctions 109 | T f(T); 110 | 111 | template requires false || true // boolean literals 112 | T f(T); 113 | 114 | template requires (... && Addable) // fold expressions 115 | T f(T); 116 | 117 | -------------------------------------------------------------------------------- 118 | 119 | (translation_unit 120 | (template_declaration 121 | (template_parameter_list 122 | (type_parameter_declaration 123 | (type_identifier))) 124 | (declaration 125 | (primitive_type) 126 | (function_declarator 127 | (identifier) 128 | (parameter_list 129 | (parameter_declaration 130 | (type_identifier) 131 | (abstract_reference_declarator))) 132 | (requires_clause 133 | (template_type 134 | (type_identifier) 135 | (template_argument_list 136 | (type_descriptor 137 | (type_identifier)))))))) 138 | (comment) 139 | (template_declaration 140 | (template_parameter_list 141 | (type_parameter_declaration 142 | (type_identifier))) 143 | (requires_clause 144 | (template_type 145 | (type_identifier) 146 | (template_argument_list 147 | (type_descriptor 148 | (type_identifier))))) 149 | (comment) 150 | (function_definition 151 | (type_identifier) 152 | (function_declarator 153 | (identifier) 154 | (parameter_list 155 | (parameter_declaration 156 | (type_identifier) 157 | (identifier)) 158 | (parameter_declaration 159 | (type_identifier) 160 | (identifier)))) 161 | (compound_statement 162 | (return_statement 163 | (binary_expression 164 | (identifier) 165 | (identifier)))))) 166 | (template_declaration 167 | (template_parameter_list 168 | (type_parameter_declaration 169 | (type_identifier))) 170 | (concept_definition 171 | (identifier) 172 | (requires_expression 173 | (parameter_list 174 | (parameter_declaration 175 | (type_identifier) 176 | (identifier))) 177 | (requirement_seq 178 | (simple_requirement 179 | (binary_expression 180 | (identifier) 181 | (identifier))))))) 182 | (comment) 183 | (template_declaration 184 | (template_parameter_list 185 | (type_parameter_declaration 186 | (type_identifier))) 187 | (requires_clause 188 | (requires_expression 189 | (parameter_list 190 | (parameter_declaration 191 | (type_identifier) 192 | (identifier))) 193 | (requirement_seq 194 | (simple_requirement 195 | (binary_expression 196 | (identifier) 197 | (identifier)))))) 198 | (comment) 199 | (function_definition 200 | (type_identifier) 201 | (function_declarator 202 | (identifier) 203 | (parameter_list 204 | (parameter_declaration 205 | (type_identifier) 206 | (identifier)) 207 | (parameter_declaration 208 | (type_identifier) 209 | (identifier)))) 210 | (compound_statement 211 | (return_statement 212 | (binary_expression 213 | (identifier) 214 | (identifier)))))) 215 | (template_declaration 216 | (template_parameter_list 217 | (type_parameter_declaration 218 | (type_identifier))) 219 | (requires_clause 220 | (unary_expression 221 | (qualified_identifier 222 | (namespace_identifier) 223 | (template_function 224 | (identifier) 225 | (template_argument_list 226 | (type_descriptor 227 | (type_identifier)) 228 | (type_descriptor 229 | (primitive_type))))))) 230 | (comment) 231 | (declaration 232 | (primitive_type) 233 | (function_declarator 234 | (identifier) 235 | (parameter_list 236 | (parameter_declaration 237 | (type_identifier)))))) 238 | (template_declaration 239 | (template_parameter_list 240 | (type_parameter_declaration 241 | (type_identifier))) 242 | (requires_clause 243 | (constraint_conjunction 244 | (template_type 245 | (type_identifier) 246 | (template_argument_list 247 | (type_descriptor 248 | (type_identifier)))) 249 | (template_type 250 | (type_identifier) 251 | (template_argument_list 252 | (type_descriptor 253 | (type_identifier)))))) 254 | (comment) 255 | (declaration 256 | (type_identifier) 257 | (function_declarator 258 | (identifier) 259 | (parameter_list 260 | (parameter_declaration 261 | (type_identifier)))))) 262 | (template_declaration 263 | (template_parameter_list 264 | (type_parameter_declaration 265 | (type_identifier))) 266 | (requires_clause 267 | (constraint_conjunction 268 | (template_type 269 | (type_identifier) 270 | (template_argument_list 271 | (type_descriptor 272 | (type_identifier)))) 273 | (template_type 274 | (type_identifier) 275 | (template_argument_list 276 | (type_descriptor 277 | (type_identifier)))))) 278 | (comment) 279 | (declaration 280 | (type_identifier) 281 | (function_declarator 282 | (identifier) 283 | (parameter_list 284 | (parameter_declaration 285 | (type_identifier)))))) 286 | (template_declaration 287 | (template_parameter_list 288 | (type_parameter_declaration 289 | (type_identifier))) 290 | (requires_clause 291 | (constraint_disjunction 292 | (template_type 293 | (type_identifier) 294 | (template_argument_list 295 | (type_descriptor 296 | (type_identifier)))) 297 | (template_type 298 | (type_identifier) 299 | (template_argument_list 300 | (type_descriptor 301 | (type_identifier)))))) 302 | (comment) 303 | (declaration 304 | (type_identifier) 305 | (function_declarator 306 | (identifier) 307 | (parameter_list 308 | (parameter_declaration 309 | (type_identifier)))))) 310 | (template_declaration 311 | (template_parameter_list 312 | (type_parameter_declaration 313 | (type_identifier))) 314 | (requires_clause 315 | (constraint_disjunction 316 | (template_type 317 | (type_identifier) 318 | (template_argument_list 319 | (type_descriptor 320 | (type_identifier)))) 321 | (template_type 322 | (type_identifier) 323 | (template_argument_list 324 | (type_descriptor 325 | (type_identifier)))))) 326 | (comment) 327 | (declaration 328 | (type_identifier) 329 | (function_declarator 330 | (identifier) 331 | (parameter_list 332 | (parameter_declaration 333 | (type_identifier)))))) 334 | (template_declaration 335 | (template_parameter_list 336 | (type_parameter_declaration 337 | (type_identifier))) 338 | (requires_clause 339 | (constraint_disjunction 340 | (false) 341 | (true))) 342 | (comment) 343 | (declaration 344 | (type_identifier) 345 | (function_declarator 346 | (identifier) 347 | (parameter_list 348 | (parameter_declaration 349 | (type_identifier)))))) 350 | (template_declaration 351 | (template_parameter_list 352 | (variadic_type_parameter_declaration 353 | (type_identifier))) 354 | (requires_clause 355 | (fold_expression 356 | (template_function 357 | (identifier) 358 | (template_argument_list 359 | (type_descriptor 360 | (type_identifier)))))) 361 | (comment) 362 | (declaration 363 | (type_identifier) 364 | (function_declarator 365 | (identifier) 366 | (parameter_list 367 | (parameter_declaration 368 | (type_identifier))))))) 369 | 370 | ================================================================================ 371 | Compound requirements 372 | ================================================================================ 373 | 374 | template concept C2 = 375 | requires(T x) { 376 | {*x} -> std::convertible_to; // the expression *x must be valid 377 | // AND the type T::inner must be valid 378 | // AND the result of *x must be convertible to T::inner 379 | {x + 1} -> std::same_as; // the expression x + 1 must be valid 380 | // AND std::same_as must be satisfied 381 | // i.e., (x + 1) must be a prvalue of type int 382 | {x * 1} -> std::convertible_to; // the expression x * 1 must be valid 383 | // AND its result must be convertible to T 384 | }; 385 | 386 | -------------------------------------------------------------------------------- 387 | 388 | (translation_unit 389 | (template_declaration 390 | (template_parameter_list 391 | (type_parameter_declaration 392 | (type_identifier))) 393 | (concept_definition 394 | (identifier) 395 | (requires_expression 396 | (parameter_list 397 | (parameter_declaration 398 | (type_identifier) 399 | (identifier))) 400 | (requirement_seq 401 | (compound_requirement 402 | (pointer_expression 403 | (identifier)) 404 | (trailing_return_type 405 | (type_descriptor 406 | (qualified_identifier 407 | (namespace_identifier) 408 | (template_type 409 | (type_identifier) 410 | (template_argument_list 411 | (type_descriptor 412 | (dependent_type 413 | (qualified_identifier 414 | (namespace_identifier) 415 | (type_identifier)))))))))) 416 | (comment) 417 | (comment) 418 | (comment) 419 | (compound_requirement 420 | (binary_expression 421 | (identifier) 422 | (number_literal)) 423 | (trailing_return_type 424 | (type_descriptor 425 | (qualified_identifier 426 | (namespace_identifier) 427 | (template_type 428 | (type_identifier) 429 | (template_argument_list 430 | (type_descriptor 431 | (primitive_type)))))))) 432 | (comment) 433 | (comment) 434 | (comment) 435 | (compound_requirement 436 | (binary_expression 437 | (identifier) 438 | (number_literal)) 439 | (trailing_return_type 440 | (type_descriptor 441 | (qualified_identifier 442 | (namespace_identifier) 443 | (template_type 444 | (type_identifier) 445 | (template_argument_list 446 | (type_descriptor 447 | (type_identifier)))))))) 448 | (comment) 449 | (comment)))))) 450 | 451 | ================================================================================ 452 | Nested requirements 453 | ================================================================================ 454 | 455 | template 456 | concept Semiregular = DefaultConstructible && 457 | CopyConstructible && Destructible && CopyAssignable && 458 | requires(T a, size_t n) { 459 | requires Same; // nested: "Same<...> evaluates to true" 460 | { a.~T() } noexcept; // compound: "a.~T()" is a valid expression that doesn't throw 461 | requires Same; // nested: "Same<...> evaluates to true" 462 | requires Same; // nested 463 | { delete new T }; // compound 464 | { delete new T[n] }; // compound 465 | }; 466 | -------------------------------------------------------------------------------- 467 | 468 | (translation_unit 469 | (template_declaration 470 | (template_parameter_list 471 | (type_parameter_declaration 472 | (type_identifier))) 473 | (concept_definition 474 | (identifier) 475 | (binary_expression 476 | (binary_expression 477 | (binary_expression 478 | (binary_expression 479 | (template_function 480 | (identifier) 481 | (template_argument_list 482 | (type_descriptor 483 | (type_identifier)))) 484 | (template_function 485 | (identifier) 486 | (template_argument_list 487 | (type_descriptor 488 | (type_identifier))))) 489 | (template_function 490 | (identifier) 491 | (template_argument_list 492 | (type_descriptor 493 | (type_identifier))))) 494 | (template_function 495 | (identifier) 496 | (template_argument_list 497 | (type_descriptor 498 | (type_identifier))))) 499 | (requires_expression 500 | (parameter_list 501 | (parameter_declaration 502 | (type_identifier) 503 | (identifier)) 504 | (parameter_declaration 505 | (primitive_type) 506 | (identifier))) 507 | (requirement_seq 508 | (simple_requirement 509 | (requires_clause 510 | (template_type 511 | (type_identifier) 512 | (template_argument_list 513 | (type_descriptor 514 | (type_identifier) 515 | (abstract_pointer_declarator)) 516 | (type_descriptor 517 | (decltype 518 | (pointer_expression 519 | (identifier)))))))) 520 | (comment) 521 | (compound_requirement 522 | (call_expression 523 | (field_expression 524 | (identifier) 525 | (destructor_name 526 | (identifier))) 527 | (argument_list))) 528 | (comment) 529 | (simple_requirement 530 | (requires_clause 531 | (template_type 532 | (type_identifier) 533 | (template_argument_list 534 | (type_descriptor 535 | (type_identifier) 536 | (abstract_pointer_declarator)) 537 | (type_descriptor 538 | (decltype 539 | (new_expression 540 | (type_identifier)))))))) 541 | (comment) 542 | (simple_requirement 543 | (requires_clause 544 | (template_type 545 | (type_identifier) 546 | (template_argument_list 547 | (type_descriptor 548 | (type_identifier) 549 | (abstract_pointer_declarator)) 550 | (type_descriptor 551 | (decltype 552 | (new_expression 553 | (type_identifier) 554 | (new_declarator 555 | (identifier))))))))) 556 | (comment) 557 | (compound_requirement 558 | (delete_expression 559 | (new_expression 560 | (type_identifier)))) 561 | (comment) 562 | (compound_requirement 563 | (delete_expression 564 | (new_expression 565 | (type_identifier) 566 | (new_declarator 567 | (identifier))))) 568 | (comment))))))) 569 | 570 | ================================================================================ 571 | Constraints 572 | ================================================================================ 573 | 574 | template 575 | void f(const T&); // constrained function template declaration 576 | 577 | void f(const EqualityComparable auto&); // constrained function template declaration 578 | 579 | Sortable auto foo = f(); 580 | Sortable auto bar = g(); 581 | NS::Concept auto baz = h(); 582 | 583 | Sortable decltype(auto) foo = i(); 584 | 585 | --- 586 | 587 | (translation_unit 588 | (template_declaration 589 | (template_parameter_list 590 | (parameter_declaration 591 | (type_identifier) 592 | (identifier))) 593 | (declaration 594 | (primitive_type) 595 | (function_declarator 596 | (identifier) 597 | (parameter_list 598 | (parameter_declaration 599 | (type_qualifier) 600 | (type_identifier) 601 | (abstract_reference_declarator)))))) 602 | (comment) 603 | (declaration 604 | (primitive_type) 605 | (function_declarator 606 | (identifier) 607 | (parameter_list 608 | (parameter_declaration 609 | (type_qualifier) 610 | (placeholder_type_specifier 611 | (type_identifier) 612 | (auto)) 613 | (abstract_reference_declarator))))) 614 | (comment) 615 | (declaration 616 | (placeholder_type_specifier 617 | (type_identifier) 618 | (auto)) 619 | (init_declarator 620 | (identifier) 621 | (call_expression 622 | (identifier) 623 | (argument_list)))) 624 | (declaration 625 | (placeholder_type_specifier 626 | (template_type 627 | (type_identifier) 628 | (template_argument_list 629 | (type_descriptor 630 | (type_identifier)))) 631 | (auto)) 632 | (init_declarator 633 | (identifier) 634 | (call_expression 635 | (identifier) 636 | (argument_list)))) 637 | (declaration 638 | (placeholder_type_specifier 639 | (qualified_identifier 640 | (namespace_identifier) 641 | (template_type 642 | (type_identifier) 643 | (template_argument_list 644 | (type_descriptor 645 | (type_identifier))))) 646 | (auto)) 647 | (init_declarator 648 | (identifier) 649 | (call_expression 650 | (identifier) 651 | (argument_list)))) 652 | (declaration 653 | (placeholder_type_specifier 654 | (type_identifier) 655 | (decltype 656 | (auto))) 657 | (init_declarator 658 | (identifier) 659 | (call_expression 660 | (identifier) 661 | (argument_list))))) 662 | --------------------------------------------------------------------------------