├── bindings ├── python │ ├── tree_sitter_go │ │ ├── py.typed │ │ ├── __init__.pyi │ │ ├── __init__.py │ │ └── binding.c │ └── tests │ │ └── test_binding.py ├── node │ ├── binding_test.js │ ├── index.js │ ├── index.d.ts │ └── binding.cc ├── swift │ ├── TreeSitterGo │ │ └── go.h │ └── TreeSitterGoTests │ │ └── TreeSitterGoTests.swift ├── c │ ├── tree_sitter │ │ └── tree-sitter-go.h │ └── tree-sitter-go.pc.in ├── go │ ├── binding.go │ └── binding_test.go └── rust │ ├── build.rs │ └── lib.rs ├── eslint.config.mjs ├── go.mod ├── .github ├── dependabot.yml ├── workflows │ ├── lint.yml │ ├── publish.yml │ └── ci.yml └── FUNDING.yml ├── examples ├── no_newline_at_eof.go └── letter_test.go ├── Package.resolved ├── .gitignore ├── .editorconfig ├── binding.gyp ├── Cargo.toml ├── pyproject.toml ├── tree-sitter.json ├── README.md ├── LICENSE ├── .gitattributes ├── src └── tree_sitter │ ├── alloc.h │ ├── parser.h │ └── array.h ├── Package.swift ├── queries ├── tags.scm └── highlights.scm ├── package.json ├── test └── corpus │ ├── errors.txt │ ├── source_files.txt │ ├── expressions.txt │ ├── types.txt │ ├── literals.txt │ ├── declarations.txt │ └── statements.txt ├── setup.py ├── CMakeLists.txt ├── Makefile ├── go.sum ├── Cargo.lock └── grammar.js /bindings/python/tree_sitter_go/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import treesitter from 'eslint-config-treesitter'; 2 | 3 | export default [ 4 | ...treesitter, 5 | ]; 6 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_go/__init__.pyi: -------------------------------------------------------------------------------- 1 | from typing import Final 2 | 3 | HIGHLIGHTS_QUERY: Final[str] 4 | TAGS_QUERY: Final[str] 5 | 6 | def language() -> object: ... 7 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tree-sitter/tree-sitter-go 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 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | commit-message: 8 | prefix: "ci" 9 | -------------------------------------------------------------------------------- /bindings/node/binding_test.js: -------------------------------------------------------------------------------- 1 | const assert = require("node:assert"); 2 | const { test } = require("node:test"); 3 | 4 | const Parser = require("tree-sitter"); 5 | 6 | test("can load grammar", () => { 7 | const parser = new Parser(); 8 | assert.doesNotThrow(() => parser.setLanguage(require("."))); 9 | }); 10 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterGo/go.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_GO_H_ 2 | #define TREE_SITTER_GO_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | const TSLanguage *tree_sitter_go(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_GO_H_ 17 | -------------------------------------------------------------------------------- /bindings/c/tree_sitter/tree-sitter-go.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_GO_H_ 2 | #define TREE_SITTER_GO_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | const TSLanguage *tree_sitter_go(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_GO_H_ 17 | -------------------------------------------------------------------------------- /bindings/c/tree-sitter-go.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ 3 | includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ 4 | 5 | Name: tree-sitter-go 6 | Description: @PROJECT_DESCRIPTION@ 7 | URL: @PROJECT_HOMEPAGE_URL@ 8 | Version: @PROJECT_VERSION@ 9 | Libs: -L${libdir} -ltree-sitter-go 10 | Cflags: -I${includedir} 11 | -------------------------------------------------------------------------------- /bindings/python/tests/test_binding.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import tree_sitter 4 | import tree_sitter_go 5 | 6 | 7 | class TestLanguage(TestCase): 8 | def test_can_load_grammar(self): 9 | try: 10 | tree_sitter.Language(tree_sitter_go.language()) 11 | except Exception: 12 | self.fail("Error loading Go grammar") 13 | -------------------------------------------------------------------------------- /examples/no_newline_at_eof.go: -------------------------------------------------------------------------------- 1 | // run 2 | 3 | // Copyright 2015 The Go Authors. All rights reserved. 4 | // Use of this source code is governed by a BSD-style 5 | // license that can be found in the LICENSE file. 6 | 7 | package main 8 | 9 | func main() { 10 | x := 0 11 | func() { 12 | x = 1 13 | }() 14 | func() { 15 | if x != 1 { 16 | panic("x != 1") 17 | } 18 | }() 19 | } -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "SwiftTreeSitter", 6 | "repositoryURL": "https://github.com/ChimeHQ/SwiftTreeSitter", 7 | "state": { 8 | "branch": null, 9 | "revision": "2599e95310b3159641469d8a21baf2d3d200e61f", 10 | "version": "0.8.0" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /bindings/go/binding.go: -------------------------------------------------------------------------------- 1 | package tree_sitter_go 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_go()) 15 | } 16 | -------------------------------------------------------------------------------- /bindings/go/binding_test.go: -------------------------------------------------------------------------------- 1 | package tree_sitter_go_test 2 | 3 | import ( 4 | "testing" 5 | 6 | tree_sitter "github.com/tree-sitter/go-tree-sitter" 7 | tree_sitter_go "github.com/tree-sitter/tree-sitter-go/bindings/go" 8 | ) 9 | 10 | func TestCanLoadGrammar(t *testing.T) { 11 | language := tree_sitter.NewLanguage(tree_sitter_go.Language()) 12 | if language == nil { 13 | t.Errorf("Error loading Go grammar") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterGoTests/TreeSitterGoTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import SwiftTreeSitter 3 | import TreeSitterGo 4 | 5 | final class TreeSitterGoTests: XCTestCase { 6 | func testCanLoadGrammar() throws { 7 | let parser = Parser() 8 | let language = Language(language: tree_sitter_go()) 9 | XCTAssertNoThrow(try parser.setLanguage(language), 10 | "Error loading Go 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-go.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_go(); 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_go()); 14 | language.TypeTag(&LANGUAGE_TYPE_TAG); 15 | exports["language"] = language; 16 | return exports; 17 | } 18 | 19 | NODE_API_MODULE(tree_sitter_go_binding, Init) 20 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - grammar.js 8 | pull_request: 9 | paths: 10 | - grammar.js 11 | 12 | jobs: 13 | lint: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v5 18 | - name: Set up Node.js 19 | uses: actions/setup-node@v5 20 | with: 21 | cache: npm 22 | node-version: ${{vars.NODE_VERSION}} 23 | - name: Install modules 24 | run: npm ci --legacy-peer-deps 25 | - name: Run ESLint 26 | run: npm run lint 27 | -------------------------------------------------------------------------------- /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-go"); 21 | } 22 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | 6 | [*.{json,toml,yml,gyp}] 7 | indent_style = space 8 | indent_size = 2 9 | 10 | [*.js] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.scm] 15 | indent_style = space 16 | indent_size = 2 17 | 18 | [*.{c,cc,h}] 19 | indent_style = space 20 | indent_size = 4 21 | 22 | [*.rs] 23 | indent_style = space 24 | indent_size = 4 25 | 26 | [*.{py,pyi}] 27 | indent_style = space 28 | indent_size = 4 29 | 30 | [*.swift] 31 | indent_style = space 32 | indent_size = 4 33 | 34 | [*.go] 35 | indent_style = tab 36 | indent_size = 8 37 | 38 | [Makefile] 39 | indent_style = tab 40 | indent_size = 8 41 | 42 | [parser.c] 43 | indent_size = 2 44 | 45 | [{alloc,array,parser}.h] 46 | indent_size = 2 47 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: tree-sitter 4 | patreon: # Replace with a single Patreon username 5 | open_collective: tree-sitter # Replace with a single Open Collective username 6 | ko_fi: amaanq 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_go_binding", 5 | "dependencies": [ 6 | "", 7 | "Amaan Qureshi ", 8 | ] 9 | license = "MIT" 10 | readme = "README.md" 11 | keywords = ["incremental", "parsing", "tree-sitter", "go"] 12 | categories = ["parser-implementations", "parsing", "text-editors"] 13 | repository = "https://github.com/tree-sitter/tree-sitter-go" 14 | edition = "2021" 15 | autoexamples = false 16 | 17 | build = "bindings/rust/build.rs" 18 | include = ["LICENSE", "bindings/rust/*", 19 | "grammar.js", 20 | "queries/*", 21 | "src/*", 22 | "tree-sitter.json", 23 | "LICENSE", 24 | ] 25 | 26 | [lib] 27 | path = "bindings/rust/lib.rs" 28 | 29 | [dependencies] 30 | tree-sitter-language = "0.1" 31 | 32 | [build-dependencies] 33 | cc = "1.2" 34 | 35 | [dev-dependencies] 36 | tree-sitter = "0.25.8" 37 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish packages 2 | 3 | on: 4 | push: 5 | tags: ["*"] 6 | 7 | permissions: 8 | contents: write 9 | id-token: write 10 | attestations: write 11 | 12 | jobs: 13 | github: 14 | uses: tree-sitter/workflows/.github/workflows/release.yml@main 15 | with: 16 | generate: true 17 | attestations: true 18 | npm: 19 | uses: tree-sitter/workflows/.github/workflows/package-npm.yml@main 20 | secrets: 21 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 22 | with: 23 | generate: true 24 | crates: 25 | uses: tree-sitter/workflows/.github/workflows/package-crates.yml@main 26 | secrets: 27 | CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_REGISTRY_TOKEN}} 28 | with: 29 | generate: true 30 | pypi: 31 | uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@main 32 | secrets: 33 | PYPI_API_TOKEN: ${{secrets.PYPI_API_TOKEN}} 34 | with: 35 | generate: true 36 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=62.4.0", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "tree-sitter-go" 7 | description = "Go grammar for tree-sitter" 8 | version = "0.25.0" 9 | keywords = ["incremental", "parsing", "tree-sitter", "go"] 10 | classifiers = [ 11 | "Intended Audience :: Developers", 12 | "Topic :: Software Development :: Compilers", 13 | "Topic :: Text Processing :: Linguistic", 14 | "Typing :: Typed", 15 | ] 16 | authors = [ 17 | { name = "Max Brunsfeld", email = "maxbrunsfeld@gmail.com" }, 18 | { name = "Amaan Qureshi", email = "amaanq12@gmail.com" }, 19 | ] 20 | requires-python = ">=3.10" 21 | license.text = "MIT" 22 | readme = "README.md" 23 | 24 | [project.urls] 25 | Homepage = "https://github.com/tree-sitter/tree-sitter-go" 26 | 27 | [project.optional-dependencies] 28 | core = ["tree-sitter~=0.24"] 29 | 30 | [tool.cibuildwheel] 31 | build = "cp310-*" 32 | build-frontend = "build" 33 | -------------------------------------------------------------------------------- /tree-sitter.json: -------------------------------------------------------------------------------- 1 | { 2 | "grammars": [ 3 | { 4 | "name": "go", 5 | "camelcase": "Go", 6 | "scope": "source.go", 7 | "path": ".", 8 | "file-types": [ 9 | "go" 10 | ], 11 | "highlights": "queries/highlights.scm", 12 | "tags": "queries/tags.scm" 13 | } 14 | ], 15 | "metadata": { 16 | "version": "0.25.0", 17 | "license": "MIT", 18 | "description": "Go grammar for tree-sitter", 19 | "authors": [ 20 | { 21 | "name": "Max Brunsfeld", 22 | "email": "maxbrunsfeld@gmail.com" 23 | }, 24 | { 25 | "name": "Amaan Qureshi", 26 | "email": "amaanq12@gmail.com" 27 | } 28 | ], 29 | "links": { 30 | "repository": "https://github.com/tree-sitter/tree-sitter-go" 31 | } 32 | }, 33 | "bindings": { 34 | "c": true, 35 | "go": true, 36 | "node": true, 37 | "python": true, 38 | "rust": true, 39 | "swift": true 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_go/__init__.py: -------------------------------------------------------------------------------- 1 | """Go grammar for tree-sitter""" 2 | 3 | from importlib.resources import files as _files 4 | 5 | from ._binding import language 6 | 7 | 8 | def _get_query(name, file): 9 | query = _files(f"{__package__}.queries") / file 10 | globals()[name] = query.read_text() 11 | return globals()[name] 12 | 13 | 14 | def __getattr__(name): 15 | if name == "HIGHLIGHTS_QUERY": 16 | return _get_query("HIGHLIGHTS_QUERY", "highlights.scm") 17 | if name == "TAGS_QUERY": 18 | return _get_query("TAGS_QUERY", "tags.scm") 19 | 20 | raise AttributeError(f"module {__name__!r} has no attribute {name!r}") 21 | 22 | 23 | __all__ = [ 24 | "language", 25 | "HIGHLIGHTS_QUERY", 26 | "TAGS_QUERY", 27 | ] 28 | 29 | 30 | def __dir__(): 31 | return sorted(__all__ + [ 32 | "__all__", "__builtins__", "__cached__", "__doc__", "__file__", 33 | "__loader__", "__name__", "__package__", "__path__", "__spec__", 34 | ]) 35 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_go/binding.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | TSLanguage *tree_sitter_go(void); 6 | 7 | static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { 8 | return PyCapsule_New(tree_sitter_go(), "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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-go 2 | 3 | [![CI][ci]](https://github.com/tree-sitter/tree-sitter-go/actions/workflows/ci.yml) 4 | [![discord][discord]](https://discord.gg/w7nTvsVJhm) 5 | [![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org) 6 | [![crates][crates]](https://crates.io/crates/tree-sitter-go) 7 | [![npm][npm]](https://www.npmjs.com/package/tree-sitter-go) 8 | [![pypi][pypi]](https://pypi.org/project/tree-sitter-go) 9 | 10 | [Go](https://go.dev/ref/spec) grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter). 11 | 12 | [ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter/tree-sitter-go/ci.yml?logo=github&label=CI 13 | [discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord 14 | [matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix 15 | [npm]: https://img.shields.io/npm/v/tree-sitter-go?logo=npm 16 | [crates]: https://img.shields.io/crates/v/tree-sitter-go?logo=rust 17 | [pypi]: https://img.shields.io/pypi/v/tree-sitter-go?logo=pypi&logoColor=ffd242 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Max Brunsfeld 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.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 | bindings/zig/* linguist-generated 41 | build.zig linguist-generated 42 | build.zig.zon linguist-generated 43 | -------------------------------------------------------------------------------- /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: "TreeSitterGo", 13 | products: [ 14 | .library(name: "TreeSitterGo", targets: ["TreeSitterGo"]), 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: "TreeSitterGo", 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: "TreeSitterGoTests", 33 | dependencies: [ 34 | "SwiftTreeSitter", 35 | "TreeSitterGo", 36 | ], 37 | path: "bindings/swift/TreeSitterGoTests" 38 | ) 39 | ], 40 | cLanguageStandard: .c11 41 | ) 42 | -------------------------------------------------------------------------------- /queries/tags.scm: -------------------------------------------------------------------------------- 1 | ( 2 | (comment)* @doc 3 | . 4 | (function_declaration 5 | name: (identifier) @name) @definition.function 6 | (#strip! @doc "^//\\s*") 7 | (#set-adjacent! @doc @definition.function) 8 | ) 9 | 10 | ( 11 | (comment)* @doc 12 | . 13 | (method_declaration 14 | name: (field_identifier) @name) @definition.method 15 | (#strip! @doc "^//\\s*") 16 | (#set-adjacent! @doc @definition.method) 17 | ) 18 | 19 | (call_expression 20 | function: [ 21 | (identifier) @name 22 | (parenthesized_expression (identifier) @name) 23 | (selector_expression field: (field_identifier) @name) 24 | (parenthesized_expression (selector_expression field: (field_identifier) @name)) 25 | ]) @reference.call 26 | 27 | (type_spec 28 | name: (type_identifier) @name) @definition.type 29 | 30 | (type_identifier) @name @reference.type 31 | 32 | (package_clause "package" (package_identifier) @name) 33 | 34 | (type_declaration (type_spec name: (type_identifier) @name type: (interface_type))) 35 | 36 | (type_declaration (type_spec name: (type_identifier) @name type: (struct_type))) 37 | 38 | (import_declaration (import_spec) @name) 39 | 40 | (var_declaration (var_spec name: (identifier) @name)) 41 | 42 | (const_declaration (const_spec name: (identifier) @name)) 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-go", 3 | "version": "0.25.0", 4 | "description": "Go grammar for tree-sitter", 5 | "repository": "https://github.com/tree-sitter/tree-sitter-go", 6 | "license": "MIT", 7 | "author": { 8 | "name": "Max Brunsfeld", 9 | "email": "maxbrunsfeld@gmail.com" 10 | }, 11 | "maintainers": [ 12 | { 13 | "name": "Amaan Qureshi", 14 | "email": "amaanq12@gmail.com" 15 | } 16 | ], 17 | "main": "bindings/node", 18 | "types": "bindings/node", 19 | "keywords": [ 20 | "incremental", 21 | "parsing", 22 | "tree-sitter", 23 | "go" 24 | ], 25 | "files": [ 26 | "grammar.js", 27 | "tree-sitter.json", 28 | "binding.gyp", 29 | "prebuilds/**", 30 | "bindings/node/*", 31 | "queries/*", 32 | "src/**", 33 | "*.wasm" 34 | ], 35 | "dependencies": { 36 | "node-addon-api": "^8.3.1", 37 | "node-gyp-build": "^4.8.4" 38 | }, 39 | "devDependencies": { 40 | "eslint": "^9.12.0", 41 | "eslint-config-treesitter": "^1.0.2", 42 | "prebuildify": "^6.0.1", 43 | "tree-sitter-cli": "^0.25.8" 44 | }, 45 | "peerDependencies": { 46 | "tree-sitter": "^0.25.0" 47 | }, 48 | "peerDependenciesMeta": { 49 | "tree-sitter": { 50 | "optional": true 51 | } 52 | }, 53 | "scripts": { 54 | "install": "node-gyp-build", 55 | "lint": "eslint grammar.js", 56 | "prestart": "tree-sitter build --wasm", 57 | "start": "tree-sitter playground", 58 | "test": "node --test bindings/node/*_test.js" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/corpus/errors.txt: -------------------------------------------------------------------------------- 1 | ================================================= 2 | Error detected at globally reserved keyword 3 | ================================================= 4 | 5 | func a() { 6 | a. // Should error here, and not use 'if' as a field 7 | 8 | if b > c { 9 | d() 10 | } 11 | } 12 | 13 | 14 | func b() { 15 | b. // Should error here, and not use 'switch' as a field 16 | 17 | switch v { 18 | case 1: 19 | doSomething() 20 | } 21 | } 22 | 23 | --- 24 | 25 | (source_file 26 | (function_declaration 27 | (identifier) 28 | (parameter_list) 29 | (block 30 | (ERROR 31 | (identifier)) 32 | (comment) 33 | (statement_list 34 | (if_statement 35 | (binary_expression 36 | (identifier) 37 | (identifier)) 38 | (block 39 | (statement_list 40 | (expression_statement 41 | (call_expression 42 | (identifier) 43 | (argument_list))))))))) 44 | (function_declaration 45 | (identifier) 46 | (parameter_list) 47 | (block 48 | (ERROR 49 | (identifier)) 50 | (comment) 51 | (statement_list 52 | (expression_switch_statement 53 | (identifier) 54 | (expression_case 55 | (expression_list 56 | (int_literal)) 57 | (statement_list 58 | (expression_statement 59 | (call_expression 60 | (identifier) 61 | (argument_list)))))))))) 62 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides Go 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 | //! func add(a, b int) int { 9 | //! return a + b 10 | //! } 11 | //! "#; 12 | //! let mut parser = tree_sitter::Parser::new(); 13 | //! let language = tree_sitter_go::LANGUAGE; 14 | //! parser 15 | //! .set_language(&language.into()) 16 | //! .expect("Error loading Go parser"); 17 | //! let tree = parser.parse(code, None).unwrap(); 18 | //! assert!(!tree.root_node().has_error()); 19 | //! ``` 20 | //! 21 | //! [`Parser`]: https://docs.rs/tree-sitter/0.25.8/tree_sitter/struct.Parser.html 22 | //! [tree-sitter]: https://tree-sitter.github.io/ 23 | 24 | use tree_sitter_language::LanguageFn; 25 | 26 | extern "C" { 27 | fn tree_sitter_go() -> *const (); 28 | } 29 | 30 | /// The tree-sitter [`LanguageFn`] for this grammar. 31 | pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_go) }; 32 | 33 | /// The content of the [`node-types.json`] file for this grammar. 34 | /// 35 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types 36 | pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); 37 | 38 | /// The syntax highlighting query for this language. 39 | pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); 40 | 41 | /// The symbol tagging query for this language. 42 | pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm"); 43 | 44 | #[cfg(test)] 45 | mod tests { 46 | #[test] 47 | fn test_can_load_grammar() { 48 | let mut parser = tree_sitter::Parser::new(); 49 | parser 50 | .set_language(&super::LANGUAGE.into()) 51 | .expect("Error loading Go parser"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /queries/highlights.scm: -------------------------------------------------------------------------------- 1 | ; Function calls 2 | 3 | (call_expression 4 | function: (identifier) @function) 5 | 6 | (call_expression 7 | function: (identifier) @function.builtin 8 | (#match? @function.builtin "^(append|cap|close|complex|copy|delete|imag|len|make|new|panic|print|println|real|recover)$")) 9 | 10 | (call_expression 11 | function: (selector_expression 12 | field: (field_identifier) @function.method)) 13 | 14 | ; Function definitions 15 | 16 | (function_declaration 17 | name: (identifier) @function) 18 | 19 | (method_declaration 20 | name: (field_identifier) @function.method) 21 | 22 | ; Identifiers 23 | 24 | (type_identifier) @type 25 | (field_identifier) @property 26 | (identifier) @variable 27 | 28 | ; Operators 29 | 30 | [ 31 | "--" 32 | "-" 33 | "-=" 34 | ":=" 35 | "!" 36 | "!=" 37 | "..." 38 | "*" 39 | "*" 40 | "*=" 41 | "/" 42 | "/=" 43 | "&" 44 | "&&" 45 | "&=" 46 | "%" 47 | "%=" 48 | "^" 49 | "^=" 50 | "+" 51 | "++" 52 | "+=" 53 | "<-" 54 | "<" 55 | "<<" 56 | "<<=" 57 | "<=" 58 | "=" 59 | "==" 60 | ">" 61 | ">=" 62 | ">>" 63 | ">>=" 64 | "|" 65 | "|=" 66 | "||" 67 | "~" 68 | ] @operator 69 | 70 | ; Keywords 71 | 72 | [ 73 | "break" 74 | "case" 75 | "chan" 76 | "const" 77 | "continue" 78 | "default" 79 | "defer" 80 | "else" 81 | "fallthrough" 82 | "for" 83 | "func" 84 | "go" 85 | "goto" 86 | "if" 87 | "import" 88 | "interface" 89 | "map" 90 | "package" 91 | "range" 92 | "return" 93 | "select" 94 | "struct" 95 | "switch" 96 | "type" 97 | "var" 98 | ] @keyword 99 | 100 | ; Literals 101 | 102 | [ 103 | (interpreted_string_literal) 104 | (raw_string_literal) 105 | (rune_literal) 106 | ] @string 107 | 108 | (escape_sequence) @escape 109 | 110 | [ 111 | (int_literal) 112 | (float_literal) 113 | (imaginary_literal) 114 | ] @number 115 | 116 | [ 117 | (true) 118 | (false) 119 | (nil) 120 | (iota) 121 | ] @constant.builtin 122 | 123 | (comment) @comment 124 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | from platform import system 3 | from sysconfig import get_config_var 4 | 5 | from setuptools import Extension, find_packages, setup 6 | from setuptools.command.build import build 7 | from setuptools.command.egg_info import egg_info 8 | from wheel.bdist_wheel import bdist_wheel 9 | 10 | sources = [ 11 | "bindings/python/tree_sitter_go/binding.c", 12 | "src/parser.c", 13 | ] 14 | if path.exists("src/scanner.c"): 15 | sources.append("src/scanner.c") 16 | 17 | macros: list[tuple[str, str | None]] = [ 18 | ("PY_SSIZE_T_CLEAN", None), 19 | ("TREE_SITTER_HIDE_SYMBOLS", None), 20 | ] 21 | if limited_api := not get_config_var("Py_GIL_DISABLED"): 22 | macros.append(("Py_LIMITED_API", "0x030A0000")) 23 | 24 | if system() != "Windows": 25 | cflags = ["-std=c11", "-fvisibility=hidden"] 26 | else: 27 | cflags = ["/std:c11", "/utf-8"] 28 | 29 | 30 | class Build(build): 31 | def run(self): 32 | if path.isdir("queries"): 33 | dest = path.join(self.build_lib, "tree_sitter_go", "queries") 34 | self.copy_tree("queries", dest) 35 | super().run() 36 | 37 | 38 | class BdistWheel(bdist_wheel): 39 | def get_tag(self): 40 | python, abi, platform = super().get_tag() 41 | if python.startswith("cp"): 42 | python, abi = "cp310", "abi3" 43 | return python, abi, platform 44 | 45 | 46 | class EggInfo(egg_info): 47 | def find_sources(self): 48 | super().find_sources() 49 | self.filelist.recursive_include("queries", "*.scm") 50 | self.filelist.include("src/tree_sitter/*.h") 51 | 52 | 53 | setup( 54 | packages=find_packages("bindings/python"), 55 | package_dir={"": "bindings/python"}, 56 | package_data={ 57 | "tree_sitter_go": ["*.pyi", "py.typed"], 58 | "tree_sitter_go.queries": ["*.scm"], 59 | }, 60 | ext_package="tree_sitter_go", 61 | ext_modules=[ 62 | Extension( 63 | name="_binding", 64 | sources=sources, 65 | extra_compile_args=cflags, 66 | define_macros=macros, 67 | include_dirs=["src"], 68 | py_limited_api=limited_api, 69 | ) 70 | ], 71 | cmdclass={ 72 | "build": Build, 73 | "bdist_wheel": BdistWheel, 74 | "egg_info": EggInfo, 75 | }, 76 | zip_safe=False 77 | ) 78 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | project(tree-sitter-go 4 | VERSION "0.25.0" 5 | DESCRIPTION "Go grammar for tree-sitter" 6 | HOMEPAGE_URL "https://github.com/tree-sitter/tree-sitter-go" 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 | include(GNUInstallDirs) 19 | 20 | find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI") 21 | 22 | add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c" 23 | DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json" 24 | COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json 25 | --abi=${TREE_SITTER_ABI_VERSION} 26 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 27 | COMMENT "Generating parser.c") 28 | 29 | add_library(tree-sitter-go src/parser.c) 30 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c) 31 | target_sources(tree-sitter-go PRIVATE src/scanner.c) 32 | endif() 33 | target_include_directories(tree-sitter-go 34 | PRIVATE src 35 | INTERFACE $ 36 | $) 37 | 38 | target_compile_definitions(tree-sitter-go PRIVATE 39 | $<$:TREE_SITTER_REUSE_ALLOCATOR> 40 | $<$:TREE_SITTER_DEBUG>) 41 | 42 | set_target_properties(tree-sitter-go 43 | PROPERTIES 44 | C_STANDARD 11 45 | POSITION_INDEPENDENT_CODE ON 46 | SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}" 47 | DEFINE_SYMBOL "") 48 | 49 | configure_file(bindings/c/tree-sitter-go.pc.in 50 | "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-go.pc" @ONLY) 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-go.pc" 56 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") 57 | install(TARGETS tree-sitter-go 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/go") 63 | 64 | add_custom_target(ts-test "${TREE_SITTER_CLI}" test 65 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 66 | COMMENT "tree-sitter test") 67 | -------------------------------------------------------------------------------- /.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 | pull_request: 13 | paths: 14 | - grammar.js 15 | - src/** 16 | - test/** 17 | - bindings/** 18 | - binding.gyp 19 | 20 | concurrency: 21 | group: ${{github.workflow}}-${{github.ref}} 22 | cancel-in-progress: true 23 | 24 | jobs: 25 | test: 26 | name: Test parser 27 | runs-on: ${{matrix.os}} 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | os: [ubuntu-latest, windows-latest, macos-15] 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v5 35 | - name: Set up tree-sitter 36 | uses: tree-sitter/setup-action/cli@v2 37 | - name: Set up examples 38 | run: |- 39 | git clone https://github.com/golang/go examples/go --single-branch --depth=1 --filter=blob:none 40 | git clone https://github.com/moby/moby examples/moby --single-branch --depth=1 --filter=blob:none 41 | - name: Run tests 42 | uses: tree-sitter/parser-test-action@v3 43 | with: 44 | test-rust: true 45 | test-node: true 46 | test-python: true 47 | test-go: true 48 | test-swift: true 49 | - name: Parse examples 50 | id: examples 51 | continue-on-error: true 52 | uses: tree-sitter/parse-action@v4 53 | with: 54 | files: examples/**/*.go 55 | invalid-files: | 56 | examples/go/src/cmd/compile/internal/syntax/testdata/*.go 57 | examples/go/src/cmd/compile/internal/types2/testdata/local/issue47996.go 58 | examples/go/src/cmd/compile/internal/types2/testdata/local/issue68183.go 59 | examples/go/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go 60 | examples/go/src/encoding/json/v2/arshal_test.go 61 | examples/go/src/internal/types/testdata/**/*.go 62 | examples/go/test/bombad.go 63 | examples/go/test/const2.go 64 | examples/go/test/ddd1.go 65 | examples/go/test/fixedbugs/**/*.go 66 | examples/go/test/import5.go 67 | examples/go/test/makenew.go 68 | examples/go/test/method4.dir/prog.go 69 | examples/go/test/method7.go 70 | examples/go/test/slice3err.go 71 | examples/go/test/switch2.go 72 | examples/go/test/syntax/chan.go 73 | examples/go/test/syntax/chan1.go 74 | examples/go/test/syntax/ddd.go 75 | examples/go/test/syntax/else.go 76 | examples/go/test/syntax/if.go 77 | examples/go/test/syntax/import.go 78 | examples/go/test/syntax/initvar.go 79 | examples/go/test/syntax/semi*.go 80 | examples/go/test/syntax/vareq.go 81 | examples/go/test/syntax/vareq1.go 82 | examples/go/test/typeparam/issue*.go 83 | examples/moby/daemon/logger/journald/read_test.go 84 | - uses: actions/upload-artifact@v4 85 | if: steps.examples.outputs.failures != '' 86 | with: 87 | name: failures-${{matrix.os}} 88 | path: ${{steps.examples.outputs.failures}} 89 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | $(error Windows is not supported) 3 | endif 4 | 5 | LANGUAGE_NAME := tree-sitter-go 6 | HOMEPAGE_URL := https://github.com/tree-sitter/tree-sitter-go 7 | VERSION := 0.25.0 8 | 9 | # repository 10 | SRC_DIR := src 11 | 12 | TS ?= tree-sitter 13 | 14 | # install directory layout 15 | PREFIX ?= /usr/local 16 | DATADIR ?= $(PREFIX)/share 17 | INCLUDEDIR ?= $(PREFIX)/include 18 | LIBDIR ?= $(PREFIX)/lib 19 | PCLIBDIR ?= $(LIBDIR)/pkgconfig 20 | 21 | # source/object files 22 | PARSER := $(SRC_DIR)/parser.c 23 | EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c)) 24 | OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS)) 25 | 26 | # flags 27 | ARFLAGS ?= rcs 28 | override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC 29 | 30 | # ABI versioning 31 | SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER)) 32 | SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION))) 33 | 34 | # OS-specific bits 35 | ifeq ($(shell uname),Darwin) 36 | SOEXT = dylib 37 | SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT) 38 | SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT) 39 | LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks 40 | else 41 | SOEXT = so 42 | SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR) 43 | SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR) 44 | LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER) 45 | endif 46 | ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),) 47 | PCLIBDIR := $(PREFIX)/libdata/pkgconfig 48 | endif 49 | 50 | all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc 51 | 52 | lib$(LANGUAGE_NAME).a: $(OBJS) 53 | $(AR) $(ARFLAGS) $@ $^ 54 | 55 | lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS) 56 | $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@ 57 | ifneq ($(STRIP),) 58 | $(STRIP) $@ 59 | endif 60 | 61 | $(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in 62 | sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \ 63 | -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \ 64 | -e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \ 65 | -e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \ 66 | -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \ 67 | -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@ 68 | 69 | $(PARSER): $(SRC_DIR)/grammar.json 70 | $(TS) generate $^ 71 | 72 | install: all 73 | install -d '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/go '$(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/go 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/go 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-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo= 18 | github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU= 19 | github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA= 20 | github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc= 21 | github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg= 22 | github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU= 23 | github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4= 24 | github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk= 25 | github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g= 26 | github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs= 27 | github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw= 28 | github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g= 29 | github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d h1:fcYCvoXdcP1uRQYXqJHRy6Hec+uKScQdKVtMwK9JeCI= 30 | github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d/go.mod h1:T1nShQ4v5AJtozZ8YyAS4uzUtDAJj/iv4YfwXSbUHzg= 31 | github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc= 32 | github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc= 33 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 34 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 35 | -------------------------------------------------------------------------------- /test/corpus/source_files.txt: -------------------------------------------------------------------------------- 1 | ============================================ 2 | Package clauses 3 | ============================================ 4 | 5 | package main 6 | 7 | ---- 8 | 9 | (source_file 10 | (package_clause 11 | (package_identifier))) 12 | 13 | ============================================ 14 | Single import declarations 15 | ============================================ 16 | 17 | package a 18 | 19 | import "net/http" 20 | import . "some/dsl" 21 | import _ "os" 22 | import alias "some/package" 23 | 24 | ---- 25 | 26 | (source_file 27 | (package_clause 28 | (package_identifier)) 29 | (import_declaration 30 | (import_spec 31 | (interpreted_string_literal 32 | (interpreted_string_literal_content)))) 33 | (import_declaration 34 | (import_spec 35 | (dot) 36 | (interpreted_string_literal 37 | (interpreted_string_literal_content)))) 38 | (import_declaration 39 | (import_spec 40 | (blank_identifier) 41 | (interpreted_string_literal 42 | (interpreted_string_literal_content)))) 43 | (import_declaration 44 | (import_spec 45 | (package_identifier) 46 | (interpreted_string_literal 47 | (interpreted_string_literal_content))))) 48 | 49 | ============================================ 50 | Grouped import declarations 51 | ============================================ 52 | 53 | package a 54 | 55 | import() 56 | import ("fmt") 57 | import ( 58 | "net/http" 59 | . "some/dsl" 60 | _ "os" 61 | alias "some/package" 62 | ) 63 | 64 | ---- 65 | 66 | (source_file 67 | (package_clause 68 | (package_identifier)) 69 | (import_declaration 70 | (import_spec_list)) 71 | (import_declaration 72 | (import_spec_list 73 | (import_spec 74 | (interpreted_string_literal 75 | (interpreted_string_literal_content))))) 76 | (import_declaration 77 | (import_spec_list 78 | (import_spec 79 | (interpreted_string_literal 80 | (interpreted_string_literal_content))) 81 | (import_spec 82 | (dot) 83 | (interpreted_string_literal 84 | (interpreted_string_literal_content))) 85 | (import_spec 86 | (blank_identifier) 87 | (interpreted_string_literal 88 | (interpreted_string_literal_content))) 89 | (import_spec 90 | (package_identifier) 91 | (interpreted_string_literal 92 | (interpreted_string_literal_content)))))) 93 | 94 | ============================================ 95 | Block comments 96 | ============================================ 97 | 98 | /* 99 | * This is a great package 100 | */ 101 | package a 102 | 103 | ---- 104 | 105 | (source_file 106 | (comment) 107 | (package_clause 108 | (package_identifier))) 109 | 110 | ============================================ 111 | Comments with asterisks 112 | ============================================ 113 | 114 | package main 115 | 116 | /* a */ 117 | const a 118 | 119 | /* b **/ 120 | const b 121 | 122 | /* c ***/ 123 | const c 124 | 125 | /* d 126 | 127 | ***/ 128 | const d 129 | 130 | --- 131 | 132 | (source_file 133 | (package_clause 134 | (package_identifier)) 135 | (comment) 136 | (const_declaration 137 | (const_spec 138 | (identifier))) 139 | (comment) 140 | (const_declaration 141 | (const_spec 142 | (identifier))) 143 | (comment) 144 | (const_declaration 145 | (const_spec 146 | (identifier))) 147 | (comment) 148 | (const_declaration 149 | (const_spec 150 | (identifier)))) 151 | 152 | ============================================ 153 | Non-ascii variable names 154 | ============================================ 155 | 156 | package main 157 | 158 | const ( 159 | α 160 | Α 161 | µs // micro sign (not mu) 162 | δ1 163 | ΔΔΔ 164 | ω_omega 165 | Ω_OMEGA 166 | ) 167 | 168 | --- 169 | 170 | (source_file 171 | (package_clause 172 | (package_identifier)) 173 | (const_declaration 174 | (const_spec 175 | (identifier)) 176 | (const_spec 177 | (identifier)) 178 | (const_spec 179 | (identifier)) 180 | (comment) 181 | (const_spec 182 | (identifier)) 183 | (const_spec 184 | (identifier)) 185 | (const_spec 186 | (identifier)) 187 | (const_spec 188 | (identifier)))) 189 | -------------------------------------------------------------------------------- /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.34" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" 19 | dependencies = [ 20 | "shlex", 21 | ] 22 | 23 | [[package]] 24 | name = "equivalent" 25 | version = "1.0.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 28 | 29 | [[package]] 30 | name = "hashbrown" 31 | version = "0.15.5" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" 34 | 35 | [[package]] 36 | name = "indexmap" 37 | version = "2.11.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" 40 | dependencies = [ 41 | "equivalent", 42 | "hashbrown", 43 | ] 44 | 45 | [[package]] 46 | name = "itoa" 47 | version = "1.0.15" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 50 | 51 | [[package]] 52 | name = "memchr" 53 | version = "2.7.5" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 56 | 57 | [[package]] 58 | name = "proc-macro2" 59 | version = "1.0.95" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 62 | dependencies = [ 63 | "unicode-ident", 64 | ] 65 | 66 | [[package]] 67 | name = "quote" 68 | version = "1.0.40" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 71 | dependencies = [ 72 | "proc-macro2", 73 | ] 74 | 75 | [[package]] 76 | name = "regex" 77 | version = "1.11.2" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" 80 | dependencies = [ 81 | "aho-corasick", 82 | "memchr", 83 | "regex-automata", 84 | "regex-syntax", 85 | ] 86 | 87 | [[package]] 88 | name = "regex-automata" 89 | version = "0.4.10" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" 92 | dependencies = [ 93 | "aho-corasick", 94 | "memchr", 95 | "regex-syntax", 96 | ] 97 | 98 | [[package]] 99 | name = "regex-syntax" 100 | version = "0.8.6" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" 103 | 104 | [[package]] 105 | name = "ryu" 106 | version = "1.0.20" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 109 | 110 | [[package]] 111 | name = "serde" 112 | version = "1.0.219" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 115 | dependencies = [ 116 | "serde_derive", 117 | ] 118 | 119 | [[package]] 120 | name = "serde_derive" 121 | version = "1.0.219" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 124 | dependencies = [ 125 | "proc-macro2", 126 | "quote", 127 | "syn", 128 | ] 129 | 130 | [[package]] 131 | name = "serde_json" 132 | version = "1.0.143" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" 135 | dependencies = [ 136 | "indexmap", 137 | "itoa", 138 | "memchr", 139 | "ryu", 140 | "serde", 141 | ] 142 | 143 | [[package]] 144 | name = "shlex" 145 | version = "1.3.0" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 148 | 149 | [[package]] 150 | name = "streaming-iterator" 151 | version = "0.1.9" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" 154 | 155 | [[package]] 156 | name = "syn" 157 | version = "2.0.104" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" 160 | dependencies = [ 161 | "proc-macro2", 162 | "quote", 163 | "unicode-ident", 164 | ] 165 | 166 | [[package]] 167 | name = "tree-sitter" 168 | version = "0.25.8" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "6d7b8994f367f16e6fa14b5aebbcb350de5d7cbea82dc5b00ae997dd71680dd2" 171 | dependencies = [ 172 | "cc", 173 | "regex", 174 | "regex-syntax", 175 | "serde_json", 176 | "streaming-iterator", 177 | "tree-sitter-language", 178 | ] 179 | 180 | [[package]] 181 | name = "tree-sitter-go" 182 | version = "0.25.0" 183 | dependencies = [ 184 | "cc", 185 | "tree-sitter", 186 | "tree-sitter-language", 187 | ] 188 | 189 | [[package]] 190 | name = "tree-sitter-language" 191 | version = "0.1.5" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8" 194 | 195 | [[package]] 196 | name = "unicode-ident" 197 | version = "1.0.18" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 200 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/expressions.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Call expressions 3 | ================================================================================ 4 | 5 | package main 6 | 7 | func main() { 8 | a(b, c...) 9 | 10 | a( 11 | b, 12 | c, 13 | ) 14 | 15 | a( 16 | b, 17 | c..., 18 | ) 19 | } 20 | 21 | -------------------------------------------------------------------------------- 22 | 23 | (source_file 24 | (package_clause 25 | (package_identifier)) 26 | (function_declaration 27 | (identifier) 28 | (parameter_list) 29 | (block 30 | (statement_list 31 | (expression_statement 32 | (call_expression 33 | (identifier) 34 | (argument_list 35 | (identifier) 36 | (variadic_argument 37 | (identifier))))) 38 | (expression_statement 39 | (call_expression 40 | (identifier) 41 | (argument_list 42 | (identifier) 43 | (identifier)))) 44 | (expression_statement 45 | (call_expression 46 | (identifier) 47 | (argument_list 48 | (identifier) 49 | (variadic_argument 50 | (identifier))))))))) 51 | 52 | ================================================================================ 53 | Nested call expressions 54 | ================================================================================ 55 | 56 | package main 57 | 58 | func main() { 59 | a(b(c(d))) 60 | } 61 | 62 | -------------------------------------------------------------------------------- 63 | 64 | (source_file 65 | (package_clause 66 | (package_identifier)) 67 | (function_declaration 68 | (identifier) 69 | (parameter_list) 70 | (block 71 | (statement_list 72 | (expression_statement 73 | (call_expression 74 | (identifier) 75 | (argument_list 76 | (call_expression 77 | (identifier) 78 | (argument_list 79 | (call_expression 80 | (identifier) 81 | (argument_list 82 | (identifier)))))))))))) 83 | 84 | ================================================================================ 85 | Generic call expressions 86 | ================================================================================ 87 | 88 | package main 89 | 90 | func main() { 91 | a[b](c) 92 | a[b, c](d) 93 | a[b[c], d](e[f]) 94 | } 95 | 96 | -------------------------------------------------------------------------------- 97 | 98 | (source_file 99 | (package_clause 100 | (package_identifier)) 101 | (function_declaration 102 | (identifier) 103 | (parameter_list) 104 | (block 105 | (statement_list 106 | (expression_statement 107 | (type_conversion_expression 108 | (generic_type 109 | (type_identifier) 110 | (type_arguments 111 | (type_elem 112 | (type_identifier)))) 113 | (identifier))) 114 | (expression_statement 115 | (type_conversion_expression 116 | (generic_type 117 | (type_identifier) 118 | (type_arguments 119 | (type_elem 120 | (type_identifier)) 121 | (type_elem 122 | (type_identifier)))) 123 | (identifier))) 124 | (expression_statement 125 | (type_conversion_expression 126 | (generic_type 127 | (type_identifier) 128 | (type_arguments 129 | (type_elem 130 | (generic_type 131 | (type_identifier) 132 | (type_arguments 133 | (type_elem 134 | (type_identifier))))) 135 | (type_elem 136 | (type_identifier)))) 137 | (index_expression 138 | (identifier) 139 | (identifier)))))))) 140 | 141 | ================================================================================ 142 | Calls to 'make' and 'new' 143 | ================================================================================ 144 | 145 | package main 146 | 147 | func main() { 148 | make(chan<- int) 149 | 150 | // `new` and `make` can also be used as variable names 151 | make(chan<- int, (new - old), make.stuff) 152 | 153 | make(chan<- int, 5, 10) 154 | new(map[string]string) 155 | } 156 | 157 | func fake_new(new func() int) int { 158 | return new() 159 | } 160 | 161 | -------------------------------------------------------------------------------- 162 | 163 | (source_file 164 | (package_clause 165 | (package_identifier)) 166 | (function_declaration 167 | (identifier) 168 | (parameter_list) 169 | (block 170 | (statement_list 171 | (expression_statement 172 | (call_expression 173 | (identifier) 174 | (argument_list 175 | (channel_type 176 | (type_identifier))))) 177 | (comment) 178 | (expression_statement 179 | (call_expression 180 | (identifier) 181 | (argument_list 182 | (channel_type 183 | (type_identifier)) 184 | (parenthesized_expression 185 | (binary_expression 186 | (identifier) 187 | (identifier))) 188 | (selector_expression 189 | (identifier) 190 | (field_identifier))))) 191 | (expression_statement 192 | (call_expression 193 | (identifier) 194 | (argument_list 195 | (channel_type 196 | (type_identifier)) 197 | (int_literal) 198 | (int_literal)))) 199 | (expression_statement 200 | (call_expression 201 | (identifier) 202 | (argument_list 203 | (map_type 204 | (type_identifier) 205 | (type_identifier)))))))) 206 | (function_declaration 207 | (identifier) 208 | (parameter_list 209 | (parameter_declaration 210 | (identifier) 211 | (function_type 212 | (parameter_list) 213 | (type_identifier)))) 214 | (type_identifier) 215 | (block 216 | (statement_list 217 | (return_statement 218 | (expression_list 219 | (call_expression 220 | (identifier) 221 | (argument_list)))))))) 222 | 223 | ================================================================================ 224 | Selector expressions 225 | ================================================================================ 226 | 227 | package main 228 | 229 | func main() { 230 | a.b.c() 231 | } 232 | 233 | -------------------------------------------------------------------------------- 234 | 235 | (source_file 236 | (package_clause 237 | (package_identifier)) 238 | (function_declaration 239 | (identifier) 240 | (parameter_list) 241 | (block 242 | (statement_list 243 | (expression_statement 244 | (call_expression 245 | (selector_expression 246 | (selector_expression 247 | (identifier) 248 | (field_identifier)) 249 | (field_identifier)) 250 | (argument_list))))))) 251 | 252 | ================================================================================ 253 | Indexing expressions 254 | ================================================================================ 255 | 256 | package main 257 | 258 | func main() { 259 | _ = a[1] 260 | _ = b[:] 261 | _ = c[1:] 262 | _ = d[1:2] 263 | _ = e[:2:3] 264 | _ = f[1:2:3] 265 | } 266 | 267 | -------------------------------------------------------------------------------- 268 | 269 | (source_file 270 | (package_clause 271 | (package_identifier)) 272 | (function_declaration 273 | (identifier) 274 | (parameter_list) 275 | (block 276 | (statement_list 277 | (assignment_statement 278 | (expression_list 279 | (identifier)) 280 | (expression_list 281 | (index_expression 282 | (identifier) 283 | (int_literal)))) 284 | (assignment_statement 285 | (expression_list 286 | (identifier)) 287 | (expression_list 288 | (slice_expression 289 | (identifier)))) 290 | (assignment_statement 291 | (expression_list 292 | (identifier)) 293 | (expression_list 294 | (slice_expression 295 | (identifier) 296 | (int_literal)))) 297 | (assignment_statement 298 | (expression_list 299 | (identifier)) 300 | (expression_list 301 | (slice_expression 302 | (identifier) 303 | (int_literal) 304 | (int_literal)))) 305 | (assignment_statement 306 | (expression_list 307 | (identifier)) 308 | (expression_list 309 | (slice_expression 310 | (identifier) 311 | (int_literal) 312 | (int_literal)))) 313 | (assignment_statement 314 | (expression_list 315 | (identifier)) 316 | (expression_list 317 | (slice_expression 318 | (identifier) 319 | (int_literal) 320 | (int_literal) 321 | (int_literal)))))))) 322 | 323 | ================================================================================ 324 | Type assertion expressions 325 | ================================================================================ 326 | 327 | package main 328 | 329 | func main() { 330 | _ = a.(p.Person) 331 | } 332 | 333 | -------------------------------------------------------------------------------- 334 | 335 | (source_file 336 | (package_clause 337 | (package_identifier)) 338 | (function_declaration 339 | (identifier) 340 | (parameter_list) 341 | (block 342 | (statement_list 343 | (assignment_statement 344 | (expression_list 345 | (identifier)) 346 | (expression_list 347 | (type_assertion_expression 348 | (identifier) 349 | (qualified_type 350 | (package_identifier) 351 | (type_identifier))))))))) 352 | 353 | ================================================================================ 354 | Type conversion expressions 355 | ================================================================================ 356 | 357 | package main 358 | 359 | func main() { 360 | _ = []a.b(c.d) 361 | _ = ([]a.b)(c.d) 362 | _ = <-chan int(c) // conversion to channel type 363 | <-(chan int(c)) // receive statement 364 | // These type conversions cannot be distinguished from call expressions 365 | T(x) 366 | (*Point)(p) 367 | e.f(g) 368 | (e.f)(g) 369 | } 370 | 371 | -------------------------------------------------------------------------------- 372 | 373 | (source_file 374 | (package_clause 375 | (package_identifier)) 376 | (function_declaration 377 | (identifier) 378 | (parameter_list) 379 | (block 380 | (statement_list 381 | (assignment_statement 382 | (expression_list 383 | (identifier)) 384 | (expression_list 385 | (type_conversion_expression 386 | (slice_type 387 | (qualified_type 388 | (package_identifier) 389 | (type_identifier))) 390 | (selector_expression 391 | (identifier) 392 | (field_identifier))))) 393 | (assignment_statement 394 | (expression_list 395 | (identifier)) 396 | (expression_list 397 | (type_conversion_expression 398 | (parenthesized_type 399 | (slice_type 400 | (qualified_type 401 | (package_identifier) 402 | (type_identifier)))) 403 | (selector_expression 404 | (identifier) 405 | (field_identifier))))) 406 | (assignment_statement 407 | (expression_list 408 | (identifier)) 409 | (expression_list 410 | (type_conversion_expression 411 | (channel_type 412 | (type_identifier)) 413 | (identifier)))) 414 | (comment) 415 | (expression_statement 416 | (unary_expression 417 | (parenthesized_expression 418 | (type_conversion_expression 419 | (channel_type 420 | (type_identifier)) 421 | (identifier))))) 422 | (comment) 423 | (comment) 424 | (expression_statement 425 | (call_expression 426 | (identifier) 427 | (argument_list 428 | (identifier)))) 429 | (expression_statement 430 | (call_expression 431 | (parenthesized_expression 432 | (unary_expression 433 | (identifier))) 434 | (argument_list 435 | (identifier)))) 436 | (expression_statement 437 | (call_expression 438 | (selector_expression 439 | (identifier) 440 | (field_identifier)) 441 | (argument_list 442 | (identifier)))) 443 | (expression_statement 444 | (call_expression 445 | (parenthesized_expression 446 | (selector_expression 447 | (identifier) 448 | (field_identifier))) 449 | (argument_list 450 | (identifier)))))))) 451 | 452 | ================================================================================ 453 | Unary expressions 454 | ================================================================================ 455 | 456 | package main 457 | 458 | func main() { 459 | _ = !<-a 460 | _ = *foo() 461 | } 462 | 463 | -------------------------------------------------------------------------------- 464 | 465 | (source_file 466 | (package_clause 467 | (package_identifier)) 468 | (function_declaration 469 | (identifier) 470 | (parameter_list) 471 | (block 472 | (statement_list 473 | (assignment_statement 474 | (expression_list 475 | (identifier)) 476 | (expression_list 477 | (unary_expression 478 | (unary_expression 479 | (identifier))))) 480 | (assignment_statement 481 | (expression_list 482 | (identifier)) 483 | (expression_list 484 | (unary_expression 485 | (call_expression 486 | (identifier) 487 | (argument_list))))))))) 488 | -------------------------------------------------------------------------------- /examples/letter_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package unicode_test 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "runtime" 11 | "sort" 12 | "testing" 13 | . "unicode" 14 | ) 15 | 16 | var upperTest = []rune{ 17 | 0x41, 18 | 0xc0, 19 | 0xd8, 20 | 0x100, 21 | 0x139, 22 | 0x14a, 23 | 0x178, 24 | 0x181, 25 | 0x376, 26 | 0x3cf, 27 | 0x13bd, 28 | 0x1f2a, 29 | 0x2102, 30 | 0x2c00, 31 | 0x2c10, 32 | 0x2c20, 33 | 0xa650, 34 | 0xa722, 35 | 0xff3a, 36 | 0x10400, 37 | 0x1d400, 38 | 0x1d7ca, 39 | } 40 | 41 | var notupperTest = []rune{ 42 | 0x40, 43 | 0x5b, 44 | 0x61, 45 | 0x185, 46 | 0x1b0, 47 | 0x377, 48 | 0x387, 49 | 0x2150, 50 | 0xab7d, 51 | 0xffff, 52 | 0x10000, 53 | } 54 | 55 | var letterTest = []rune{ 56 | 0x41, 57 | 0x61, 58 | 0xaa, 59 | 0xba, 60 | 0xc8, 61 | 0xdb, 62 | 0xf9, 63 | 0x2ec, 64 | 0x535, 65 | 0x620, 66 | 0x6e6, 67 | 0x93d, 68 | 0xa15, 69 | 0xb99, 70 | 0xdc0, 71 | 0xedd, 72 | 0x1000, 73 | 0x1200, 74 | 0x1312, 75 | 0x1401, 76 | 0x1885, 77 | 0x2c00, 78 | 0xa800, 79 | 0xf900, 80 | 0xfa30, 81 | 0xffda, 82 | 0xffdc, 83 | 0x10000, 84 | 0x10300, 85 | 0x10400, 86 | 0x20000, 87 | 0x2f800, 88 | 0x2fa1d, 89 | } 90 | 91 | var notletterTest = []rune{ 92 | 0x20, 93 | 0x35, 94 | 0x375, 95 | 0x619, 96 | 0x700, 97 | 0xfffe, 98 | 0x1ffff, 99 | 0x10ffff, 100 | } 101 | 102 | // Contains all the special cased Latin-1 chars. 103 | var spaceTest = []rune{ 104 | 0x09, 105 | 0x0a, 106 | 0x0b, 107 | 0x0c, 108 | 0x0d, 109 | 0x20, 110 | 0x85, 111 | 0xA0, 112 | 0x2000, 113 | 0x3000, 114 | } 115 | 116 | type caseT struct { 117 | cas int 118 | in, out rune 119 | } 120 | 121 | var caseTest = []caseT{ 122 | // errors 123 | {-1, '\n', 0xFFFD}, 124 | {UpperCase, -1, -1}, 125 | {UpperCase, 1 << 30, 1 << 30}, 126 | 127 | // ASCII (special-cased so test carefully) 128 | {UpperCase, '\n', '\n'}, 129 | {UpperCase, 'a', 'A'}, 130 | {UpperCase, 'A', 'A'}, 131 | {UpperCase, '7', '7'}, 132 | {LowerCase, '\n', '\n'}, 133 | {LowerCase, 'a', 'a'}, 134 | {LowerCase, 'A', 'a'}, 135 | {LowerCase, '7', '7'}, 136 | {TitleCase, '\n', '\n'}, 137 | {TitleCase, 'a', 'A'}, 138 | {TitleCase, 'A', 'A'}, 139 | {TitleCase, '7', '7'}, 140 | 141 | // Latin-1: easy to read the tests! 142 | {UpperCase, 0x80, 0x80}, 143 | {UpperCase, 'Å', 'Å'}, 144 | {UpperCase, 'å', 'Å'}, 145 | {LowerCase, 0x80, 0x80}, 146 | {LowerCase, 'Å', 'å'}, 147 | {LowerCase, 'å', 'å'}, 148 | {TitleCase, 0x80, 0x80}, 149 | {TitleCase, 'Å', 'Å'}, 150 | {TitleCase, 'å', 'Å'}, 151 | 152 | // 0131;LATIN SMALL LETTER DOTLESS I;Ll;0;L;;;;;N;;;0049;;0049 153 | {UpperCase, 0x0131, 'I'}, 154 | {LowerCase, 0x0131, 0x0131}, 155 | {TitleCase, 0x0131, 'I'}, 156 | 157 | // 0133;LATIN SMALL LIGATURE IJ;Ll;0;L; 0069 006A;;;;N;LATIN SMALL LETTER I J;;0132;;0132 158 | {UpperCase, 0x0133, 0x0132}, 159 | {LowerCase, 0x0133, 0x0133}, 160 | {TitleCase, 0x0133, 0x0132}, 161 | 162 | // 212A;KELVIN SIGN;Lu;0;L;004B;;;;N;DEGREES KELVIN;;;006B; 163 | {UpperCase, 0x212A, 0x212A}, 164 | {LowerCase, 0x212A, 'k'}, 165 | {TitleCase, 0x212A, 0x212A}, 166 | 167 | // From an UpperLower sequence 168 | // A640;CYRILLIC CAPITAL LETTER ZEMLYA;Lu;0;L;;;;;N;;;;A641; 169 | {UpperCase, 0xA640, 0xA640}, 170 | {LowerCase, 0xA640, 0xA641}, 171 | {TitleCase, 0xA640, 0xA640}, 172 | // A641;CYRILLIC SMALL LETTER ZEMLYA;Ll;0;L;;;;;N;;;A640;;A640 173 | {UpperCase, 0xA641, 0xA640}, 174 | {LowerCase, 0xA641, 0xA641}, 175 | {TitleCase, 0xA641, 0xA640}, 176 | // A64E;CYRILLIC CAPITAL LETTER NEUTRAL YER;Lu;0;L;;;;;N;;;;A64F; 177 | {UpperCase, 0xA64E, 0xA64E}, 178 | {LowerCase, 0xA64E, 0xA64F}, 179 | {TitleCase, 0xA64E, 0xA64E}, 180 | // A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E 181 | {UpperCase, 0xA65F, 0xA65E}, 182 | {LowerCase, 0xA65F, 0xA65F}, 183 | {TitleCase, 0xA65F, 0xA65E}, 184 | 185 | // From another UpperLower sequence 186 | // 0139;LATIN CAPITAL LETTER L WITH ACUTE;Lu;0;L;004C 0301;;;;N;LATIN CAPITAL LETTER L ACUTE;;;013A; 187 | {UpperCase, 0x0139, 0x0139}, 188 | {LowerCase, 0x0139, 0x013A}, 189 | {TitleCase, 0x0139, 0x0139}, 190 | // 013F;LATIN CAPITAL LETTER L WITH MIDDLE DOT;Lu;0;L; 004C 00B7;;;;N;;;;0140; 191 | {UpperCase, 0x013f, 0x013f}, 192 | {LowerCase, 0x013f, 0x0140}, 193 | {TitleCase, 0x013f, 0x013f}, 194 | // 0148;LATIN SMALL LETTER N WITH CARON;Ll;0;L;006E 030C;;;;N;LATIN SMALL LETTER N HACEK;;0147;;0147 195 | {UpperCase, 0x0148, 0x0147}, 196 | {LowerCase, 0x0148, 0x0148}, 197 | {TitleCase, 0x0148, 0x0147}, 198 | 199 | // Lowercase lower than uppercase. 200 | // AB78;CHEROKEE SMALL LETTER GE;Ll;0;L;;;;;N;;;13A8;;13A8 201 | {UpperCase, 0xab78, 0x13a8}, 202 | {LowerCase, 0xab78, 0xab78}, 203 | {TitleCase, 0xab78, 0x13a8}, 204 | {UpperCase, 0x13a8, 0x13a8}, 205 | {LowerCase, 0x13a8, 0xab78}, 206 | {TitleCase, 0x13a8, 0x13a8}, 207 | 208 | // Last block in the 5.1.0 table 209 | // 10400;DESERET CAPITAL LETTER LONG I;Lu;0;L;;;;;N;;;;10428; 210 | {UpperCase, 0x10400, 0x10400}, 211 | {LowerCase, 0x10400, 0x10428}, 212 | {TitleCase, 0x10400, 0x10400}, 213 | // 10427;DESERET CAPITAL LETTER EW;Lu;0;L;;;;;N;;;;1044F; 214 | {UpperCase, 0x10427, 0x10427}, 215 | {LowerCase, 0x10427, 0x1044F}, 216 | {TitleCase, 0x10427, 0x10427}, 217 | // 10428;DESERET SMALL LETTER LONG I;Ll;0;L;;;;;N;;;10400;;10400 218 | {UpperCase, 0x10428, 0x10400}, 219 | {LowerCase, 0x10428, 0x10428}, 220 | {TitleCase, 0x10428, 0x10400}, 221 | // 1044F;DESERET SMALL LETTER EW;Ll;0;L;;;;;N;;;10427;;10427 222 | {UpperCase, 0x1044F, 0x10427}, 223 | {LowerCase, 0x1044F, 0x1044F}, 224 | {TitleCase, 0x1044F, 0x10427}, 225 | 226 | // First one not in the 5.1.0 table 227 | // 10450;SHAVIAN LETTER PEEP;Lo;0;L;;;;;N;;;;; 228 | {UpperCase, 0x10450, 0x10450}, 229 | {LowerCase, 0x10450, 0x10450}, 230 | {TitleCase, 0x10450, 0x10450}, 231 | 232 | // Non-letters with case. 233 | {LowerCase, 0x2161, 0x2171}, 234 | {UpperCase, 0x0345, 0x0399}, 235 | } 236 | 237 | func TestIsLetter(t *testing.T) { 238 | for _, r := range upperTest { 239 | if !IsLetter(r) { 240 | t.Errorf("IsLetter(U+%04X) = false, want true", r) 241 | } 242 | } 243 | for _, r := range letterTest { 244 | if !IsLetter(r) { 245 | t.Errorf("IsLetter(U+%04X) = false, want true", r) 246 | } 247 | } 248 | for _, r := range notletterTest { 249 | if IsLetter(r) { 250 | t.Errorf("IsLetter(U+%04X) = true, want false", r) 251 | } 252 | } 253 | } 254 | 255 | func TestIsUpper(t *testing.T) { 256 | for _, r := range upperTest { 257 | if !IsUpper(r) { 258 | t.Errorf("IsUpper(U+%04X) = false, want true", r) 259 | } 260 | } 261 | for _, r := range notupperTest { 262 | if IsUpper(r) { 263 | t.Errorf("IsUpper(U+%04X) = true, want false", r) 264 | } 265 | } 266 | for _, r := range notletterTest { 267 | if IsUpper(r) { 268 | t.Errorf("IsUpper(U+%04X) = true, want false", r) 269 | } 270 | } 271 | } 272 | 273 | func caseString(c int) string { 274 | switch c { 275 | case UpperCase: 276 | return "UpperCase" 277 | case LowerCase: 278 | return "LowerCase" 279 | case TitleCase: 280 | return "TitleCase" 281 | } 282 | return "ErrorCase" 283 | } 284 | 285 | func TestTo(t *testing.T) { 286 | for _, c := range caseTest { 287 | r := To(c.cas, c.in) 288 | if c.out != r { 289 | t.Errorf("To(U+%04X, %s) = U+%04X want U+%04X", c.in, caseString(c.cas), r, c.out) 290 | } 291 | } 292 | } 293 | 294 | func TestToUpperCase(t *testing.T) { 295 | for _, c := range caseTest { 296 | if c.cas != UpperCase { 297 | continue 298 | } 299 | r := ToUpper(c.in) 300 | if c.out != r { 301 | t.Errorf("ToUpper(U+%04X) = U+%04X want U+%04X", c.in, r, c.out) 302 | } 303 | } 304 | } 305 | 306 | func TestToLowerCase(t *testing.T) { 307 | for _, c := range caseTest { 308 | if c.cas != LowerCase { 309 | continue 310 | } 311 | r := ToLower(c.in) 312 | if c.out != r { 313 | t.Errorf("ToLower(U+%04X) = U+%04X want U+%04X", c.in, r, c.out) 314 | } 315 | } 316 | } 317 | 318 | func TestToTitleCase(t *testing.T) { 319 | for _, c := range caseTest { 320 | if c.cas != TitleCase { 321 | continue 322 | } 323 | r := ToTitle(c.in) 324 | if c.out != r { 325 | t.Errorf("ToTitle(U+%04X) = U+%04X want U+%04X", c.in, r, c.out) 326 | } 327 | } 328 | } 329 | 330 | func TestIsSpace(t *testing.T) { 331 | for _, c := range spaceTest { 332 | if !IsSpace(c) { 333 | t.Errorf("IsSpace(U+%04X) = false; want true", c) 334 | } 335 | } 336 | for _, c := range letterTest { 337 | if IsSpace(c) { 338 | t.Errorf("IsSpace(U+%04X) = true; want false", c) 339 | } 340 | } 341 | } 342 | 343 | // Check that the optimizations for IsLetter etc. agree with the tables. 344 | // We only need to check the Latin-1 range. 345 | func TestLetterOptimizations(t *testing.T) { 346 | for i := rune(0); i <= MaxLatin1; i++ { 347 | if Is(Letter, i) != IsLetter(i) { 348 | t.Errorf("IsLetter(U+%04X) disagrees with Is(Letter)", i) 349 | } 350 | if Is(Upper, i) != IsUpper(i) { 351 | t.Errorf("IsUpper(U+%04X) disagrees with Is(Upper)", i) 352 | } 353 | if Is(Lower, i) != IsLower(i) { 354 | t.Errorf("IsLower(U+%04X) disagrees with Is(Lower)", i) 355 | } 356 | if Is(Title, i) != IsTitle(i) { 357 | t.Errorf("IsTitle(U+%04X) disagrees with Is(Title)", i) 358 | } 359 | if Is(White_Space, i) != IsSpace(i) { 360 | t.Errorf("IsSpace(U+%04X) disagrees with Is(White_Space)", i) 361 | } 362 | if To(UpperCase, i) != ToUpper(i) { 363 | t.Errorf("ToUpper(U+%04X) disagrees with To(Upper)", i) 364 | } 365 | if To(LowerCase, i) != ToLower(i) { 366 | t.Errorf("ToLower(U+%04X) disagrees with To(Lower)", i) 367 | } 368 | if To(TitleCase, i) != ToTitle(i) { 369 | t.Errorf("ToTitle(U+%04X) disagrees with To(Title)", i) 370 | } 371 | } 372 | } 373 | 374 | func TestTurkishCase(t *testing.T) { 375 | lower := []rune("abcçdefgğhıijklmnoöprsştuüvyz") 376 | upper := []rune("ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ") 377 | for i, l := range lower { 378 | u := upper[i] 379 | if TurkishCase.ToLower(l) != l { 380 | t.Errorf("lower(U+%04X) is U+%04X not U+%04X", l, TurkishCase.ToLower(l), l) 381 | } 382 | if TurkishCase.ToUpper(u) != u { 383 | t.Errorf("upper(U+%04X) is U+%04X not U+%04X", u, TurkishCase.ToUpper(u), u) 384 | } 385 | if TurkishCase.ToUpper(l) != u { 386 | t.Errorf("upper(U+%04X) is U+%04X not U+%04X", l, TurkishCase.ToUpper(l), u) 387 | } 388 | if TurkishCase.ToLower(u) != l { 389 | t.Errorf("lower(U+%04X) is U+%04X not U+%04X", u, TurkishCase.ToLower(l), l) 390 | } 391 | if TurkishCase.ToTitle(u) != u { 392 | t.Errorf("title(U+%04X) is U+%04X not U+%04X", u, TurkishCase.ToTitle(u), u) 393 | } 394 | if TurkishCase.ToTitle(l) != u { 395 | t.Errorf("title(U+%04X) is U+%04X not U+%04X", l, TurkishCase.ToTitle(l), u) 396 | } 397 | } 398 | } 399 | 400 | var simpleFoldTests = []string{ 401 | // SimpleFold(x) returns the next equivalent rune > x or wraps 402 | // around to smaller values. 403 | 404 | // Easy cases. 405 | "Aa", 406 | "δΔ", 407 | 408 | // ASCII special cases. 409 | "KkK", 410 | "Ssſ", 411 | 412 | // Non-ASCII special cases. 413 | "ρϱΡ", 414 | "ͅΙιι", 415 | 416 | // Extra special cases: has lower/upper but no case fold. 417 | "İ", 418 | "ı", 419 | 420 | // Upper comes before lower (Cherokee). 421 | "\u13b0\uab80", 422 | } 423 | 424 | func TestSimpleFold(t *testing.T) { 425 | for _, tt := range simpleFoldTests { 426 | cycle := []rune(tt) 427 | r := cycle[len(cycle)-1] 428 | for _, out := range cycle { 429 | if r := SimpleFold(r); r != out { 430 | t.Errorf("SimpleFold(%#U) = %#U, want %#U", r, r, out) 431 | } 432 | r = out 433 | } 434 | } 435 | } 436 | 437 | // Running 'go test -calibrate' runs the calibration to find a plausible 438 | // cutoff point for linear search of a range list vs. binary search. 439 | // We create a fake table and then time how long it takes to do a 440 | // sequence of searches within that table, for all possible inputs 441 | // relative to the ranges (something before all, in each, between each, after all). 442 | // This assumes that all possible runes are equally likely. 443 | // In practice most runes are ASCII so this is a conservative estimate 444 | // of an effective cutoff value. In practice we could probably set it higher 445 | // than what this function recommends. 446 | 447 | var calibrate = flag.Bool("calibrate", false, "compute crossover for linear vs. binary search") 448 | 449 | func TestCalibrate(t *testing.T) { 450 | if !*calibrate { 451 | return 452 | } 453 | 454 | if runtime.GOARCH == "amd64" { 455 | fmt.Printf("warning: running calibration on %s\n", runtime.GOARCH) 456 | } 457 | 458 | // Find the point where binary search wins by more than 10%. 459 | // The 10% bias gives linear search an edge when they're close, 460 | // because on predominantly ASCII inputs linear search is even 461 | // better than our benchmarks measure. 462 | n := sort.Search(64, func(n int) bool { 463 | tab := fakeTable(n) 464 | blinear := func(b *testing.B) { 465 | tab := tab 466 | max := n*5 + 20 467 | for i := 0; i < b.N; i++ { 468 | for j := 0; j <= max; j++ { 469 | linear(tab, uint16(j)) 470 | } 471 | } 472 | } 473 | bbinary := func(b *testing.B) { 474 | tab := tab 475 | max := n*5 + 20 476 | for i := 0; i < b.N; i++ { 477 | for j := 0; j <= max; j++ { 478 | binary(tab, uint16(j)) 479 | } 480 | } 481 | } 482 | bmlinear := testing.Benchmark(blinear) 483 | bmbinary := testing.Benchmark(bbinary) 484 | fmt.Printf("n=%d: linear=%d binary=%d\n", n, bmlinear.NsPerOp(), bmbinary.NsPerOp()) 485 | return bmlinear.NsPerOp()*100 > bmbinary.NsPerOp()*110 486 | }) 487 | fmt.Printf("calibration: linear cutoff = %d\n", n) 488 | } 489 | 490 | func fakeTable(n int) []Range16 { 491 | var r16 []Range16 492 | for i := 0; i < n; i++ { 493 | r16 = append(r16, Range16{uint16(i*5 + 10), uint16(i*5 + 12), 1}) 494 | } 495 | return r16 496 | } 497 | 498 | func linear(ranges []Range16, r uint16) bool { 499 | for i := range ranges { 500 | range_ := &ranges[i] 501 | if r < range_.Lo { 502 | return false 503 | } 504 | if r <= range_.Hi { 505 | return (r-range_.Lo)%range_.Stride == 0 506 | } 507 | } 508 | return false 509 | } 510 | 511 | func binary(ranges []Range16, r uint16) bool { 512 | // binary search over ranges 513 | lo := 0 514 | hi := len(ranges) 515 | for lo < hi { 516 | m := lo + (hi-lo)/2 517 | range_ := &ranges[m] 518 | if range_.Lo <= r && r <= range_.Hi { 519 | return (r-range_.Lo)%range_.Stride == 0 520 | } 521 | if r < range_.Lo { 522 | hi = m 523 | } else { 524 | lo = m + 1 525 | } 526 | } 527 | return false 528 | } 529 | 530 | func TestLatinOffset(t *testing.T) { 531 | var maps = []map[string]*RangeTable{ 532 | Categories, 533 | FoldCategory, 534 | FoldScript, 535 | Properties, 536 | Scripts, 537 | } 538 | for _, m := range maps { 539 | for name, tab := range m { 540 | i := 0 541 | for i < len(tab.R16) && tab.R16[i].Hi <= MaxLatin1 { 542 | i++ 543 | } 544 | if tab.LatinOffset != i { 545 | t.Errorf("%s: LatinOffset=%d, want %d", name, tab.LatinOffset, i) 546 | } 547 | } 548 | } 549 | } 550 | -------------------------------------------------------------------------------- /test/corpus/types.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Qualified type names 3 | ================================================================================ 4 | 5 | type a b.c 6 | 7 | -------------------------------------------------------------------------------- 8 | 9 | (source_file 10 | (type_declaration 11 | (type_spec 12 | name: (type_identifier) 13 | type: (qualified_type 14 | package: (package_identifier) 15 | name: (type_identifier))))) 16 | 17 | ================================================================================ 18 | Array types 19 | ================================================================================ 20 | 21 | type a [2+2]c 22 | 23 | -------------------------------------------------------------------------------- 24 | 25 | (source_file 26 | (type_declaration 27 | (type_spec 28 | name: (type_identifier) 29 | type: (array_type 30 | length: (binary_expression 31 | left: (int_literal) 32 | right: (int_literal)) 33 | element: (type_identifier))))) 34 | 35 | ================================================================================ 36 | Slice types 37 | ================================================================================ 38 | 39 | package main 40 | 41 | type a []c 42 | type b [][]d 43 | 44 | -------------------------------------------------------------------------------- 45 | 46 | (source_file 47 | (package_clause 48 | (package_identifier)) 49 | (type_declaration 50 | (type_spec 51 | (type_identifier) 52 | (slice_type 53 | (type_identifier)))) 54 | (type_declaration 55 | (type_spec 56 | (type_identifier) 57 | (slice_type 58 | (slice_type 59 | (type_identifier)))))) 60 | 61 | ================================================================================ 62 | Struct types 63 | ================================================================================ 64 | 65 | package main 66 | 67 | type s1 struct {} 68 | 69 | type s2 struct { Person } 70 | 71 | type s2 struct { 72 | f, g int 73 | } 74 | 75 | type s3 struct { 76 | // an embedded struct 77 | p.s1 78 | 79 | // a tag 80 | h int `json:"h"` 81 | } 82 | 83 | type g1 struct { 84 | normal Array[T] 85 | nested Array[Array[T]] 86 | } 87 | 88 | type g2[T, U any, V interface{}, W Foo[Bar[T]]] struct {} 89 | 90 | -------------------------------------------------------------------------------- 91 | 92 | (source_file 93 | (package_clause 94 | (package_identifier)) 95 | (type_declaration 96 | (type_spec 97 | (type_identifier) 98 | (struct_type 99 | (field_declaration_list)))) 100 | (type_declaration 101 | (type_spec 102 | (type_identifier) 103 | (struct_type 104 | (field_declaration_list 105 | (field_declaration 106 | (type_identifier)))))) 107 | (type_declaration 108 | (type_spec 109 | (type_identifier) 110 | (struct_type 111 | (field_declaration_list 112 | (field_declaration 113 | (field_identifier) 114 | (field_identifier) 115 | (type_identifier)))))) 116 | (type_declaration 117 | (type_spec 118 | (type_identifier) 119 | (struct_type 120 | (field_declaration_list 121 | (comment) 122 | (field_declaration 123 | (qualified_type 124 | (package_identifier) 125 | (type_identifier))) 126 | (comment) 127 | (field_declaration 128 | (field_identifier) 129 | (type_identifier) 130 | (raw_string_literal 131 | (raw_string_literal_content))))))) 132 | (type_declaration 133 | (type_spec 134 | (type_identifier) 135 | (struct_type 136 | (field_declaration_list 137 | (field_declaration 138 | (field_identifier) 139 | (generic_type 140 | (type_identifier) 141 | (type_arguments 142 | (type_elem 143 | (type_identifier))))) 144 | (field_declaration 145 | (field_identifier) 146 | (generic_type 147 | (type_identifier) 148 | (type_arguments 149 | (type_elem 150 | (generic_type 151 | (type_identifier) 152 | (type_arguments 153 | (type_elem 154 | (type_identifier)))))))))))) 155 | (type_declaration 156 | (type_spec 157 | (type_identifier) 158 | (type_parameter_list 159 | (type_parameter_declaration 160 | (identifier) 161 | (identifier) 162 | (type_constraint 163 | (type_identifier))) 164 | (type_parameter_declaration 165 | (identifier) 166 | (type_constraint 167 | (interface_type))) 168 | (type_parameter_declaration 169 | (identifier) 170 | (type_constraint 171 | (generic_type 172 | (type_identifier) 173 | (type_arguments 174 | (type_elem 175 | (generic_type 176 | (type_identifier) 177 | (type_arguments 178 | (type_elem 179 | (type_identifier)))))))))) 180 | (struct_type 181 | (field_declaration_list))))) 182 | 183 | ================================================================================ 184 | Interface types 185 | ================================================================================ 186 | 187 | package main 188 | 189 | type i1 interface {} 190 | 191 | type i1 interface { io.Reader } 192 | 193 | type i2 interface { 194 | i1 195 | io.Reader 196 | SomeMethod(s string) error 197 | OtherMethod(int, ...bool) bool 198 | } 199 | 200 | type SignedInteger interface { 201 | int | int8 | ~uint | ~uint8 202 | } 203 | 204 | -------------------------------------------------------------------------------- 205 | 206 | (source_file 207 | (package_clause 208 | (package_identifier)) 209 | (type_declaration 210 | (type_spec 211 | (type_identifier) 212 | (interface_type))) 213 | (type_declaration 214 | (type_spec 215 | (type_identifier) 216 | (interface_type 217 | (type_elem 218 | (qualified_type 219 | (package_identifier) 220 | (type_identifier)))))) 221 | (type_declaration 222 | (type_spec 223 | (type_identifier) 224 | (interface_type 225 | (type_elem 226 | (type_identifier)) 227 | (type_elem 228 | (qualified_type 229 | (package_identifier) 230 | (type_identifier))) 231 | (method_elem 232 | (field_identifier) 233 | (parameter_list 234 | (parameter_declaration 235 | (identifier) 236 | (type_identifier))) 237 | (type_identifier)) 238 | (method_elem 239 | (field_identifier) 240 | (parameter_list 241 | (parameter_declaration 242 | (type_identifier)) 243 | (variadic_parameter_declaration 244 | (type_identifier))) 245 | (type_identifier))))) 246 | (type_declaration 247 | (type_spec 248 | (type_identifier) 249 | (interface_type 250 | (type_elem 251 | (type_identifier) 252 | (type_identifier) 253 | (negated_type 254 | (type_identifier)) 255 | (negated_type 256 | (type_identifier))))))) 257 | 258 | ================================================================================ 259 | Interface embedded struct types 260 | ================================================================================ 261 | 262 | package main 263 | 264 | type NewEmbeddings interface { 265 | struct{ f int } 266 | ~struct{ f int } 267 | *struct{ f int } 268 | struct{ f int } | ~struct{ f int } 269 | struct{ f int } | string 270 | } 271 | 272 | -------------------------------------------------------------------------------- 273 | 274 | (source_file 275 | (package_clause 276 | (package_identifier)) 277 | (type_declaration 278 | (type_spec 279 | (type_identifier) 280 | (interface_type 281 | (type_elem 282 | (struct_type 283 | (field_declaration_list 284 | (field_declaration 285 | (field_identifier) 286 | (type_identifier))))) 287 | (type_elem 288 | (negated_type 289 | (struct_type 290 | (field_declaration_list 291 | (field_declaration 292 | (field_identifier) 293 | (type_identifier)))))) 294 | (type_elem 295 | (pointer_type 296 | (struct_type 297 | (field_declaration_list 298 | (field_declaration 299 | (field_identifier) 300 | (type_identifier)))))) 301 | (type_elem 302 | (struct_type 303 | (field_declaration_list 304 | (field_declaration 305 | (field_identifier) 306 | (type_identifier)))) 307 | (negated_type 308 | (struct_type 309 | (field_declaration_list 310 | (field_declaration 311 | (field_identifier) 312 | (type_identifier)))))) 313 | (type_elem 314 | (struct_type 315 | (field_declaration_list 316 | (field_declaration 317 | (field_identifier) 318 | (type_identifier)))) 319 | (type_identifier)))))) 320 | 321 | ================================================================================ 322 | Map types 323 | ================================================================================ 324 | 325 | package main 326 | 327 | type m1 map[string]error 328 | 329 | -------------------------------------------------------------------------------- 330 | 331 | (source_file 332 | (package_clause 333 | (package_identifier)) 334 | (type_declaration 335 | (type_spec 336 | (type_identifier) 337 | (map_type 338 | (type_identifier) 339 | (type_identifier))))) 340 | 341 | ================================================================================ 342 | Pointer types 343 | ================================================================================ 344 | 345 | package main 346 | 347 | type ( 348 | p1 *string 349 | p2 **p1 350 | ) 351 | 352 | -------------------------------------------------------------------------------- 353 | 354 | (source_file 355 | (package_clause 356 | (package_identifier)) 357 | (type_declaration 358 | (type_spec 359 | (type_identifier) 360 | (pointer_type 361 | (type_identifier))) 362 | (type_spec 363 | (type_identifier) 364 | (pointer_type 365 | (pointer_type 366 | (type_identifier)))))) 367 | 368 | ================================================================================ 369 | Channel types 370 | ================================================================================ 371 | 372 | package main 373 | 374 | type ( 375 | c1 chan<- chan int 376 | c2 chan<- chan<- struct{} 377 | c3 chan<- <-chan int 378 | ) 379 | 380 | -------------------------------------------------------------------------------- 381 | 382 | (source_file 383 | (package_clause 384 | (package_identifier)) 385 | (type_declaration 386 | (type_spec 387 | (type_identifier) 388 | (channel_type 389 | (channel_type 390 | (type_identifier)))) 391 | (type_spec 392 | (type_identifier) 393 | (channel_type 394 | (channel_type 395 | (struct_type 396 | (field_declaration_list))))) 397 | (type_spec 398 | (type_identifier) 399 | (channel_type 400 | (channel_type 401 | (type_identifier)))))) 402 | 403 | ================================================================================ 404 | Function types 405 | ================================================================================ 406 | 407 | package main 408 | 409 | type ( 410 | a func(int) int 411 | b func(int, *string) (bool, error) 412 | c func(int, ...*string) bool 413 | ) 414 | 415 | -------------------------------------------------------------------------------- 416 | 417 | (source_file 418 | (package_clause 419 | (package_identifier)) 420 | (type_declaration 421 | (type_spec 422 | (type_identifier) 423 | (function_type 424 | (parameter_list 425 | (parameter_declaration 426 | (type_identifier))) 427 | (type_identifier))) 428 | (type_spec 429 | (type_identifier) 430 | (function_type 431 | (parameter_list 432 | (parameter_declaration 433 | (type_identifier)) 434 | (parameter_declaration 435 | (pointer_type 436 | (type_identifier)))) 437 | (parameter_list 438 | (parameter_declaration 439 | (type_identifier)) 440 | (parameter_declaration 441 | (type_identifier))))) 442 | (type_spec 443 | (type_identifier) 444 | (function_type 445 | (parameter_list 446 | (parameter_declaration 447 | (type_identifier)) 448 | (variadic_parameter_declaration 449 | (pointer_type 450 | (type_identifier)))) 451 | (type_identifier))))) 452 | 453 | ================================================================================ 454 | Type Aliases 455 | ================================================================================ 456 | 457 | package main 458 | 459 | type H1 = G1 460 | type _ = G2 461 | type _ = struct{} 462 | type ( 463 | A0 = T0 464 | A1 = int 465 | A2 = struct{} 466 | A3 = reflect.Value 467 | A4 = Value 468 | A5 = Value 469 | ) 470 | type G3[T any, C Constraint] = G4[T, string, C] 471 | 472 | -------------------------------------------------------------------------------- 473 | 474 | (source_file 475 | (package_clause 476 | (package_identifier)) 477 | (type_declaration 478 | (type_alias 479 | (type_identifier) 480 | (type_identifier))) 481 | (type_declaration 482 | (type_alias 483 | (type_identifier) 484 | (type_identifier))) 485 | (type_declaration 486 | (type_alias 487 | (type_identifier) 488 | (struct_type 489 | (field_declaration_list)))) 490 | (type_declaration 491 | (type_alias 492 | (type_identifier) 493 | (type_identifier)) 494 | (type_alias 495 | (type_identifier) 496 | (type_identifier)) 497 | (type_alias 498 | (type_identifier) 499 | (struct_type 500 | (field_declaration_list))) 501 | (type_alias 502 | (type_identifier) 503 | (qualified_type 504 | (package_identifier) 505 | (type_identifier))) 506 | (type_alias 507 | (type_identifier) 508 | (type_identifier)) 509 | (type_alias 510 | (type_identifier) 511 | (type_identifier))) 512 | (type_declaration 513 | (type_alias 514 | (type_identifier) 515 | (type_parameter_list 516 | (type_parameter_declaration 517 | (identifier) 518 | (type_constraint 519 | (type_identifier))) 520 | (type_parameter_declaration 521 | (identifier) 522 | (type_constraint 523 | (type_identifier)))) 524 | (generic_type 525 | (type_identifier) 526 | (type_arguments 527 | (type_elem 528 | (type_identifier)) 529 | (type_elem 530 | (type_identifier)) 531 | (type_elem 532 | (type_identifier))))))) 533 | -------------------------------------------------------------------------------- /test/corpus/literals.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Int literals 3 | ================================================================================ 4 | 5 | package main 6 | 7 | const ( 8 | i1 = 42 9 | i2 = 4_2 10 | i3 = 0600 11 | i4 = 0_600 12 | i5 = 0o600 13 | i6 = 0O600 14 | i7 = 0xBadFace 15 | i8 = 0xBad_Face 16 | i9 = 0x_67_7a_2f_cc_40_c6 17 | i10 = 170141183460469231731687303715884105727 18 | i11 = 170_141183_460469_231731_687303_715884_105727 19 | ) 20 | 21 | -------------------------------------------------------------------------------- 22 | 23 | (source_file 24 | (package_clause 25 | (package_identifier)) 26 | (const_declaration 27 | (const_spec 28 | (identifier) 29 | (expression_list 30 | (int_literal))) 31 | (const_spec 32 | (identifier) 33 | (expression_list 34 | (int_literal))) 35 | (const_spec 36 | (identifier) 37 | (expression_list 38 | (int_literal))) 39 | (const_spec 40 | (identifier) 41 | (expression_list 42 | (int_literal))) 43 | (const_spec 44 | (identifier) 45 | (expression_list 46 | (int_literal))) 47 | (const_spec 48 | (identifier) 49 | (expression_list 50 | (int_literal))) 51 | (const_spec 52 | (identifier) 53 | (expression_list 54 | (int_literal))) 55 | (const_spec 56 | (identifier) 57 | (expression_list 58 | (int_literal))) 59 | (const_spec 60 | (identifier) 61 | (expression_list 62 | (int_literal))) 63 | (const_spec 64 | (identifier) 65 | (expression_list 66 | (int_literal))) 67 | (const_spec 68 | (identifier) 69 | (expression_list 70 | (int_literal))))) 71 | 72 | ================================================================================ 73 | Float literals 74 | ================================================================================ 75 | 76 | package main 77 | 78 | const ( 79 | f1 = 0. 80 | f2 = 72.40 81 | f3 = 072.40 82 | f4 = 2.71828 83 | f5 = 1.e+0 84 | f6 = 6.67428e-11 85 | f7 = 1E6 86 | f8 = .25 87 | f9 = .12345E+5 88 | f10 = 1_5. 89 | f11 = 0.15e+0_2 90 | f12 = 0x1p-2 91 | f13 = 0x2.p10 92 | f14 = 0x1.Fp+0 93 | f15 = 0X.8p-0 94 | f16 = 0X_1FFFP-16 95 | ) 96 | 97 | -------------------------------------------------------------------------------- 98 | 99 | (source_file 100 | (package_clause 101 | (package_identifier)) 102 | (const_declaration 103 | (const_spec 104 | (identifier) 105 | (expression_list 106 | (float_literal))) 107 | (const_spec 108 | (identifier) 109 | (expression_list 110 | (float_literal))) 111 | (const_spec 112 | (identifier) 113 | (expression_list 114 | (float_literal))) 115 | (const_spec 116 | (identifier) 117 | (expression_list 118 | (float_literal))) 119 | (const_spec 120 | (identifier) 121 | (expression_list 122 | (float_literal))) 123 | (const_spec 124 | (identifier) 125 | (expression_list 126 | (float_literal))) 127 | (const_spec 128 | (identifier) 129 | (expression_list 130 | (float_literal))) 131 | (const_spec 132 | (identifier) 133 | (expression_list 134 | (float_literal))) 135 | (const_spec 136 | (identifier) 137 | (expression_list 138 | (float_literal))) 139 | (const_spec 140 | (identifier) 141 | (expression_list 142 | (float_literal))) 143 | (const_spec 144 | (identifier) 145 | (expression_list 146 | (float_literal))) 147 | (const_spec 148 | (identifier) 149 | (expression_list 150 | (float_literal))) 151 | (const_spec 152 | (identifier) 153 | (expression_list 154 | (float_literal))) 155 | (const_spec 156 | (identifier) 157 | (expression_list 158 | (float_literal))) 159 | (const_spec 160 | (identifier) 161 | (expression_list 162 | (float_literal))) 163 | (const_spec 164 | (identifier) 165 | (expression_list 166 | (float_literal))))) 167 | 168 | ================================================================================ 169 | Rune literals 170 | ================================================================================ 171 | 172 | package main 173 | 174 | const ( 175 | a = '0' 176 | b = '\'' 177 | c = '\\' 178 | c = '\n' 179 | c = '\u0000' 180 | c = '\U01234567' 181 | ) 182 | 183 | -------------------------------------------------------------------------------- 184 | 185 | (source_file 186 | (package_clause 187 | (package_identifier)) 188 | (const_declaration 189 | (const_spec 190 | (identifier) 191 | (expression_list 192 | (rune_literal))) 193 | (const_spec 194 | (identifier) 195 | (expression_list 196 | (rune_literal))) 197 | (const_spec 198 | (identifier) 199 | (expression_list 200 | (rune_literal))) 201 | (const_spec 202 | (identifier) 203 | (expression_list 204 | (rune_literal))) 205 | (const_spec 206 | (identifier) 207 | (expression_list 208 | (rune_literal))) 209 | (const_spec 210 | (identifier) 211 | (expression_list 212 | (rune_literal))))) 213 | 214 | ================================================================================ 215 | Imaginary literals 216 | ================================================================================ 217 | 218 | package main 219 | 220 | const ( 221 | a = 0i 222 | b = 0123i 223 | c = 0o123i 224 | d = 0xabci 225 | e = 0.i 226 | f = 2.71828i 227 | g = 1.e+0i 228 | h = 6.67428e-11i 229 | i = 1E6i 230 | j = .25i 231 | k = .12345E+5i 232 | l = 0x1p-2i 233 | ) 234 | 235 | -------------------------------------------------------------------------------- 236 | 237 | (source_file 238 | (package_clause 239 | (package_identifier)) 240 | (const_declaration 241 | (const_spec 242 | (identifier) 243 | (expression_list 244 | (imaginary_literal))) 245 | (const_spec 246 | (identifier) 247 | (expression_list 248 | (imaginary_literal))) 249 | (const_spec 250 | (identifier) 251 | (expression_list 252 | (imaginary_literal))) 253 | (const_spec 254 | (identifier) 255 | (expression_list 256 | (imaginary_literal))) 257 | (const_spec 258 | (identifier) 259 | (expression_list 260 | (imaginary_literal))) 261 | (const_spec 262 | (identifier) 263 | (expression_list 264 | (imaginary_literal))) 265 | (const_spec 266 | (identifier) 267 | (expression_list 268 | (imaginary_literal))) 269 | (const_spec 270 | (identifier) 271 | (expression_list 272 | (imaginary_literal))) 273 | (const_spec 274 | (identifier) 275 | (expression_list 276 | (imaginary_literal))) 277 | (const_spec 278 | (identifier) 279 | (expression_list 280 | (imaginary_literal))) 281 | (const_spec 282 | (identifier) 283 | (expression_list 284 | (imaginary_literal))) 285 | (const_spec 286 | (identifier) 287 | (expression_list 288 | (imaginary_literal))))) 289 | 290 | ================================================================================ 291 | String literals 292 | ================================================================================ 293 | 294 | package main 295 | 296 | const ( 297 | a = "0" 298 | b = "`\"`" 299 | c = "\x0c" 300 | d = `//` 301 | e = "errorstring 302 | " 303 | ) 304 | 305 | -------------------------------------------------------------------------------- 306 | 307 | (source_file 308 | (package_clause 309 | (package_identifier)) 310 | (const_declaration 311 | (const_spec 312 | (identifier) 313 | (expression_list 314 | (interpreted_string_literal 315 | (interpreted_string_literal_content)))) 316 | (const_spec 317 | (identifier) 318 | (expression_list 319 | (interpreted_string_literal 320 | (interpreted_string_literal_content) 321 | (escape_sequence) 322 | (interpreted_string_literal_content)))) 323 | (const_spec 324 | (identifier) 325 | (expression_list 326 | (interpreted_string_literal 327 | (escape_sequence)))) 328 | (const_spec 329 | (identifier) 330 | (expression_list 331 | (raw_string_literal 332 | (raw_string_literal_content)))) 333 | (ERROR 334 | (identifier) 335 | (interpreted_string_literal_content)))) 336 | 337 | ================================================================================ 338 | Slice literals 339 | ================================================================================ 340 | 341 | package main 342 | 343 | const s1 = []string{} 344 | 345 | const s2 = []string{"hi"} 346 | 347 | const s3 = []string{ 348 | "hi", 349 | "hello", 350 | } 351 | 352 | -------------------------------------------------------------------------------- 353 | 354 | (source_file 355 | (package_clause 356 | (package_identifier)) 357 | (const_declaration 358 | (const_spec 359 | (identifier) 360 | (expression_list 361 | (composite_literal 362 | (slice_type 363 | (type_identifier)) 364 | (literal_value))))) 365 | (const_declaration 366 | (const_spec 367 | (identifier) 368 | (expression_list 369 | (composite_literal 370 | (slice_type 371 | (type_identifier)) 372 | (literal_value 373 | (literal_element 374 | (interpreted_string_literal 375 | (interpreted_string_literal_content)))))))) 376 | (const_declaration 377 | (const_spec 378 | (identifier) 379 | (expression_list 380 | (composite_literal 381 | (slice_type 382 | (type_identifier)) 383 | (literal_value 384 | (literal_element 385 | (interpreted_string_literal 386 | (interpreted_string_literal_content))) 387 | (literal_element 388 | (interpreted_string_literal 389 | (interpreted_string_literal_content))))))))) 390 | 391 | ================================================================================ 392 | Array literals with implicit length 393 | ================================================================================ 394 | 395 | package main 396 | 397 | const a1 = [...]int{1, 2, 3} 398 | 399 | -------------------------------------------------------------------------------- 400 | 401 | (source_file 402 | (package_clause 403 | (package_identifier)) 404 | (const_declaration 405 | (const_spec 406 | (identifier) 407 | (expression_list 408 | (composite_literal 409 | (implicit_length_array_type 410 | (type_identifier)) 411 | (literal_value 412 | (literal_element 413 | (int_literal)) 414 | (literal_element 415 | (int_literal)) 416 | (literal_element 417 | (int_literal)))))))) 418 | 419 | ================================================================================ 420 | Map literals 421 | ================================================================================ 422 | 423 | package main 424 | 425 | const s = map[string]string{ 426 | "hi": "hello", 427 | "bye": "goodbye", 428 | } 429 | 430 | -------------------------------------------------------------------------------- 431 | 432 | (source_file 433 | (package_clause 434 | (package_identifier)) 435 | (const_declaration 436 | (const_spec 437 | (identifier) 438 | (expression_list 439 | (composite_literal 440 | (map_type 441 | (type_identifier) 442 | (type_identifier)) 443 | (literal_value 444 | (keyed_element 445 | (literal_element 446 | (interpreted_string_literal 447 | (interpreted_string_literal_content))) 448 | (literal_element 449 | (interpreted_string_literal 450 | (interpreted_string_literal_content)))) 451 | (keyed_element 452 | (literal_element 453 | (interpreted_string_literal 454 | (interpreted_string_literal_content))) 455 | (literal_element 456 | (interpreted_string_literal 457 | (interpreted_string_literal_content)))))))))) 458 | 459 | ================================================================================ 460 | Struct literals 461 | ================================================================================ 462 | 463 | package main 464 | 465 | const s1 = Person{ 466 | name: "Frank", 467 | Age: "5 months", 468 | } 469 | 470 | const s2 = struct{i int;}{i: 5} 471 | 472 | const s3 = time.Time{} 473 | 474 | const g1 = Foo[float64, Bar[int]] { } 475 | 476 | -------------------------------------------------------------------------------- 477 | 478 | (source_file 479 | (package_clause 480 | (package_identifier)) 481 | (const_declaration 482 | (const_spec 483 | (identifier) 484 | (expression_list 485 | (composite_literal 486 | (type_identifier) 487 | (literal_value 488 | (keyed_element 489 | (literal_element 490 | (identifier)) 491 | (literal_element 492 | (interpreted_string_literal 493 | (interpreted_string_literal_content)))) 494 | (keyed_element 495 | (literal_element 496 | (identifier)) 497 | (literal_element 498 | (interpreted_string_literal 499 | (interpreted_string_literal_content))))))))) 500 | (const_declaration 501 | (const_spec 502 | (identifier) 503 | (expression_list 504 | (composite_literal 505 | (struct_type 506 | (field_declaration_list 507 | (field_declaration 508 | (field_identifier) 509 | (type_identifier)))) 510 | (literal_value 511 | (keyed_element 512 | (literal_element 513 | (identifier)) 514 | (literal_element 515 | (int_literal)))))))) 516 | (const_declaration 517 | (const_spec 518 | (identifier) 519 | (expression_list 520 | (composite_literal 521 | (qualified_type 522 | (package_identifier) 523 | (type_identifier)) 524 | (literal_value))))) 525 | (const_declaration 526 | (const_spec 527 | (identifier) 528 | (expression_list 529 | (composite_literal 530 | (generic_type 531 | (type_identifier) 532 | (type_arguments 533 | (type_elem 534 | (type_identifier)) 535 | (type_elem 536 | (generic_type 537 | (type_identifier) 538 | (type_arguments 539 | (type_elem 540 | (type_identifier))))))) 541 | (literal_value)))))) 542 | 543 | ================================================================================ 544 | Function literals 545 | ================================================================================ 546 | 547 | package main 548 | 549 | const s1 = func(s string) (int, int) { 550 | return 1, 2 551 | } 552 | 553 | -------------------------------------------------------------------------------- 554 | 555 | (source_file 556 | (package_clause 557 | (package_identifier)) 558 | (const_declaration 559 | (const_spec 560 | (identifier) 561 | (expression_list 562 | (func_literal 563 | (parameter_list 564 | (parameter_declaration 565 | (identifier) 566 | (type_identifier))) 567 | (parameter_list 568 | (parameter_declaration 569 | (type_identifier)) 570 | (parameter_declaration 571 | (type_identifier))) 572 | (block 573 | (statement_list 574 | (return_statement 575 | (expression_list 576 | (int_literal) 577 | (int_literal)))))))))) 578 | -------------------------------------------------------------------------------- /test/corpus/declarations.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Single const declarations without types 3 | ================================================================================ 4 | 5 | package main 6 | 7 | const zero = 0 8 | const one, two = 1, 2 9 | const three, four, five = 3, 4, 5 10 | 11 | -------------------------------------------------------------------------------- 12 | 13 | (source_file 14 | (package_clause 15 | (package_identifier)) 16 | (const_declaration 17 | (const_spec 18 | (identifier) 19 | (expression_list 20 | (int_literal)))) 21 | (const_declaration 22 | (const_spec 23 | (identifier) 24 | (identifier) 25 | (expression_list 26 | (int_literal) 27 | (int_literal)))) 28 | (const_declaration 29 | (const_spec 30 | (identifier) 31 | (identifier) 32 | (identifier) 33 | (expression_list 34 | (int_literal) 35 | (int_literal) 36 | (int_literal))))) 37 | 38 | ================================================================================ 39 | Single const declarations with types 40 | ================================================================================ 41 | 42 | package main 43 | 44 | const zero int = 0 45 | const one, two uint64 = 1, 2 46 | 47 | -------------------------------------------------------------------------------- 48 | 49 | (source_file 50 | (package_clause 51 | (package_identifier)) 52 | (const_declaration 53 | (const_spec 54 | (identifier) 55 | (type_identifier) 56 | (expression_list 57 | (int_literal)))) 58 | (const_declaration 59 | (const_spec 60 | (identifier) 61 | (identifier) 62 | (type_identifier) 63 | (expression_list 64 | (int_literal) 65 | (int_literal))))) 66 | 67 | ================================================================================ 68 | Grouped const declarations 69 | ================================================================================ 70 | 71 | package main 72 | 73 | const ( 74 | zero = 0 75 | one = 1 76 | ) 77 | 78 | -------------------------------------------------------------------------------- 79 | 80 | (source_file 81 | (package_clause 82 | (package_identifier)) 83 | (const_declaration 84 | (const_spec 85 | (identifier) 86 | (expression_list 87 | (int_literal))) 88 | (const_spec 89 | (identifier) 90 | (expression_list 91 | (int_literal))))) 92 | 93 | ================================================================================ 94 | Const declarations with implicit values 95 | ================================================================================ 96 | 97 | package main 98 | 99 | const ( 100 | zero = iota 101 | one 102 | two 103 | ) 104 | 105 | -------------------------------------------------------------------------------- 106 | 107 | (source_file 108 | (package_clause 109 | (package_identifier)) 110 | (const_declaration 111 | (const_spec 112 | (identifier) 113 | (expression_list 114 | (iota))) 115 | (const_spec 116 | (identifier)) 117 | (const_spec 118 | (identifier)))) 119 | 120 | ================================================================================ 121 | Var declarations without types 122 | ================================================================================ 123 | 124 | package main 125 | 126 | var zero = 0 127 | var one, two = 1, 2 128 | var three, four, five = 3, 4, 5 129 | 130 | -------------------------------------------------------------------------------- 131 | 132 | (source_file 133 | (package_clause 134 | (package_identifier)) 135 | (var_declaration 136 | (var_spec 137 | (identifier) 138 | (expression_list 139 | (int_literal)))) 140 | (var_declaration 141 | (var_spec 142 | (identifier) 143 | (identifier) 144 | (expression_list 145 | (int_literal) 146 | (int_literal)))) 147 | (var_declaration 148 | (var_spec 149 | (identifier) 150 | (identifier) 151 | (identifier) 152 | (expression_list 153 | (int_literal) 154 | (int_literal) 155 | (int_literal))))) 156 | 157 | ================================================================================ 158 | Var declarations with types 159 | ================================================================================ 160 | 161 | package main 162 | 163 | var zero int = 0 164 | var one, two uint64 = 1, 2 165 | 166 | -------------------------------------------------------------------------------- 167 | 168 | (source_file 169 | (package_clause 170 | (package_identifier)) 171 | (var_declaration 172 | (var_spec 173 | (identifier) 174 | (type_identifier) 175 | (expression_list 176 | (int_literal)))) 177 | (var_declaration 178 | (var_spec 179 | (identifier) 180 | (identifier) 181 | (type_identifier) 182 | (expression_list 183 | (int_literal) 184 | (int_literal))))) 185 | 186 | ================================================================================ 187 | Var declarations with no expressions 188 | ================================================================================ 189 | 190 | package main 191 | 192 | var zero int 193 | var one, two uint64 194 | 195 | -------------------------------------------------------------------------------- 196 | 197 | (source_file 198 | (package_clause 199 | (package_identifier)) 200 | (var_declaration 201 | (var_spec 202 | (identifier) 203 | (type_identifier))) 204 | (var_declaration 205 | (var_spec 206 | (identifier) 207 | (identifier) 208 | (type_identifier)))) 209 | 210 | ================================================================================ 211 | Grouped var declarations 212 | ================================================================================ 213 | 214 | package main 215 | 216 | var ( 217 | zero = 0 218 | one = 1 219 | ) 220 | 221 | -------------------------------------------------------------------------------- 222 | 223 | (source_file 224 | (package_clause 225 | (package_identifier)) 226 | (var_declaration 227 | (var_spec_list 228 | (var_spec 229 | (identifier) 230 | (expression_list 231 | (int_literal))) 232 | (var_spec 233 | (identifier) 234 | (expression_list 235 | (int_literal)))))) 236 | 237 | ================================================================================ 238 | Function declarations 239 | ================================================================================ 240 | 241 | package main 242 | 243 | func f1() {} 244 | func f2(a File, b, c, d Thing) int {} 245 | func f2() (File, Thing) {} 246 | func f2() (result int, err error) {} 247 | func f(x ... int, y ... int) 248 | func g1[T, U any, V interface{}, W Foo[Bar[T]]](a Foo[T]) {} 249 | func g1[T, U any, V interface{}, W Foo[Bar[T]]](a Foo[T]) {} 250 | func g2(a foo.bar[int]) {} 251 | func f[A int|string, B ~int, C ~int|~string]() 252 | func f2(a File, b, c, d Thing) int {} 253 | func f3([]string, int, map[int]int, error) {} 254 | func f4() ([]string, int, map[int]int, error) {} 255 | 256 | -------------------------------------------------------------------------------- 257 | 258 | (source_file 259 | (package_clause 260 | (package_identifier)) 261 | (function_declaration 262 | (identifier) 263 | (parameter_list) 264 | (block)) 265 | (function_declaration 266 | (identifier) 267 | (parameter_list 268 | (parameter_declaration 269 | (identifier) 270 | (type_identifier)) 271 | (parameter_declaration 272 | (identifier) 273 | (identifier) 274 | (identifier) 275 | (type_identifier))) 276 | (type_identifier) 277 | (block)) 278 | (function_declaration 279 | (identifier) 280 | (parameter_list) 281 | (parameter_list 282 | (parameter_declaration 283 | (type_identifier)) 284 | (parameter_declaration 285 | (type_identifier))) 286 | (block)) 287 | (function_declaration 288 | (identifier) 289 | (parameter_list) 290 | (parameter_list 291 | (parameter_declaration 292 | (identifier) 293 | (type_identifier)) 294 | (parameter_declaration 295 | (identifier) 296 | (type_identifier))) 297 | (block)) 298 | (function_declaration 299 | (identifier) 300 | (parameter_list 301 | (variadic_parameter_declaration 302 | (identifier) 303 | (type_identifier)) 304 | (variadic_parameter_declaration 305 | (identifier) 306 | (type_identifier)))) 307 | (function_declaration 308 | (identifier) 309 | (type_parameter_list 310 | (type_parameter_declaration 311 | (identifier) 312 | (identifier) 313 | (type_constraint 314 | (type_identifier))) 315 | (type_parameter_declaration 316 | (identifier) 317 | (type_constraint 318 | (interface_type))) 319 | (type_parameter_declaration 320 | (identifier) 321 | (type_constraint 322 | (generic_type 323 | (type_identifier) 324 | (type_arguments 325 | (type_elem 326 | (generic_type 327 | (type_identifier) 328 | (type_arguments 329 | (type_elem 330 | (type_identifier)))))))))) 331 | (parameter_list 332 | (parameter_declaration 333 | (identifier) 334 | (generic_type 335 | (type_identifier) 336 | (type_arguments 337 | (type_elem 338 | (type_identifier)))))) 339 | (block)) 340 | (function_declaration 341 | (identifier) 342 | (type_parameter_list 343 | (type_parameter_declaration 344 | (identifier) 345 | (identifier) 346 | (type_constraint 347 | (type_identifier))) 348 | (type_parameter_declaration 349 | (identifier) 350 | (type_constraint 351 | (interface_type))) 352 | (type_parameter_declaration 353 | (identifier) 354 | (type_constraint 355 | (generic_type 356 | (type_identifier) 357 | (type_arguments 358 | (type_elem 359 | (generic_type 360 | (type_identifier) 361 | (type_arguments 362 | (type_elem 363 | (type_identifier)))))))))) 364 | (parameter_list 365 | (parameter_declaration 366 | (identifier) 367 | (generic_type 368 | (type_identifier) 369 | (type_arguments 370 | (type_elem 371 | (type_identifier)))))) 372 | (block)) 373 | (function_declaration 374 | (identifier) 375 | (parameter_list 376 | (parameter_declaration 377 | (identifier) 378 | (generic_type 379 | (qualified_type 380 | (package_identifier) 381 | (type_identifier)) 382 | (type_arguments 383 | (type_elem 384 | (type_identifier)))))) 385 | (block)) 386 | (function_declaration 387 | (identifier) 388 | (type_parameter_list 389 | (type_parameter_declaration 390 | (identifier) 391 | (type_constraint 392 | (type_identifier) 393 | (type_identifier))) 394 | (type_parameter_declaration 395 | (identifier) 396 | (type_constraint 397 | (negated_type 398 | (type_identifier)))) 399 | (type_parameter_declaration 400 | (identifier) 401 | (type_constraint 402 | (negated_type 403 | (type_identifier)) 404 | (negated_type 405 | (type_identifier))))) 406 | (parameter_list)) 407 | (function_declaration 408 | (identifier) 409 | (parameter_list 410 | (parameter_declaration 411 | (identifier) 412 | (type_identifier)) 413 | (parameter_declaration 414 | (identifier) 415 | (identifier) 416 | (identifier) 417 | (type_identifier))) 418 | (type_identifier) 419 | (block)) 420 | (function_declaration 421 | (identifier) 422 | (parameter_list 423 | (parameter_declaration 424 | (slice_type 425 | (type_identifier))) 426 | (parameter_declaration 427 | (type_identifier)) 428 | (parameter_declaration 429 | (map_type 430 | (type_identifier) 431 | (type_identifier))) 432 | (parameter_declaration 433 | (type_identifier))) 434 | (block)) 435 | (function_declaration 436 | (identifier) 437 | (parameter_list) 438 | (parameter_list 439 | (parameter_declaration 440 | (slice_type 441 | (type_identifier))) 442 | (parameter_declaration 443 | (type_identifier)) 444 | (parameter_declaration 445 | (map_type 446 | (type_identifier) 447 | (type_identifier))) 448 | (parameter_declaration 449 | (type_identifier))) 450 | (block))) 451 | 452 | ================================================================================ 453 | Single-line function declarations 454 | ================================================================================ 455 | 456 | package main 457 | 458 | func f1() { a() } 459 | func f2() { a(); b() } 460 | func f3() { a(); b(); } 461 | 462 | -------------------------------------------------------------------------------- 463 | 464 | (source_file 465 | (package_clause 466 | (package_identifier)) 467 | (function_declaration 468 | (identifier) 469 | (parameter_list) 470 | (block 471 | (statement_list 472 | (expression_statement 473 | (call_expression 474 | (identifier) 475 | (argument_list)))))) 476 | (function_declaration 477 | (identifier) 478 | (parameter_list) 479 | (block 480 | (statement_list 481 | (expression_statement 482 | (call_expression 483 | (identifier) 484 | (argument_list))) 485 | (expression_statement 486 | (call_expression 487 | (identifier) 488 | (argument_list)))))) 489 | (function_declaration 490 | (identifier) 491 | (parameter_list) 492 | (block 493 | (statement_list 494 | (expression_statement 495 | (call_expression 496 | (identifier) 497 | (argument_list))) 498 | (expression_statement 499 | (call_expression 500 | (identifier) 501 | (argument_list))))))) 502 | 503 | ================================================================================ 504 | Variadic function declarations 505 | ================================================================================ 506 | 507 | package main 508 | 509 | func f1(a ...*int) {} 510 | func f2(a int, b ...int) {} 511 | func f3(...bool) {} 512 | 513 | -------------------------------------------------------------------------------- 514 | 515 | (source_file 516 | (package_clause 517 | (package_identifier)) 518 | (function_declaration 519 | (identifier) 520 | (parameter_list 521 | (variadic_parameter_declaration 522 | (identifier) 523 | (pointer_type 524 | (type_identifier)))) 525 | (block)) 526 | (function_declaration 527 | (identifier) 528 | (parameter_list 529 | (parameter_declaration 530 | (identifier) 531 | (type_identifier)) 532 | (variadic_parameter_declaration 533 | (identifier) 534 | (type_identifier))) 535 | (block)) 536 | (function_declaration 537 | (identifier) 538 | (parameter_list 539 | (variadic_parameter_declaration 540 | (type_identifier))) 541 | (block))) 542 | 543 | ================================================================================ 544 | Method declarations 545 | ================================================================================ 546 | 547 | package main 548 | 549 | func (self Person) Equals(other Person) bool {} 550 | func (v *Value) ObjxMap(optionalDefault ...(Map)) Map {} 551 | func (p *T1) M1() 552 | 553 | -------------------------------------------------------------------------------- 554 | 555 | (source_file 556 | (package_clause 557 | (package_identifier)) 558 | (method_declaration 559 | (parameter_list 560 | (parameter_declaration 561 | (identifier) 562 | (type_identifier))) 563 | (field_identifier) 564 | (parameter_list 565 | (parameter_declaration 566 | (identifier) 567 | (type_identifier))) 568 | (type_identifier) 569 | (block)) 570 | (method_declaration 571 | (parameter_list 572 | (parameter_declaration 573 | (identifier) 574 | (pointer_type 575 | (type_identifier)))) 576 | (field_identifier) 577 | (parameter_list 578 | (variadic_parameter_declaration 579 | (identifier) 580 | (parenthesized_type 581 | (type_identifier)))) 582 | (type_identifier) 583 | (block)) 584 | (method_declaration 585 | (parameter_list 586 | (parameter_declaration 587 | (identifier) 588 | (pointer_type 589 | (type_identifier)))) 590 | (field_identifier) 591 | (parameter_list))) 592 | 593 | ================================================================================ 594 | Type declarations 595 | ================================================================================ 596 | 597 | package main 598 | 599 | type a b 600 | type ( 601 | a b 602 | c d 603 | ) 604 | 605 | -------------------------------------------------------------------------------- 606 | 607 | (source_file 608 | (package_clause 609 | (package_identifier)) 610 | (type_declaration 611 | (type_spec 612 | (type_identifier) 613 | (type_identifier))) 614 | (type_declaration 615 | (type_spec 616 | (type_identifier) 617 | (type_identifier)) 618 | (type_spec 619 | (type_identifier) 620 | (type_identifier)))) 621 | -------------------------------------------------------------------------------- /test/corpus/statements.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | Declaration statements 3 | ================================================================================ 4 | 5 | package main 6 | 7 | func main() { 8 | var x = y 9 | const x = 5 10 | } 11 | 12 | -------------------------------------------------------------------------------- 13 | 14 | (source_file 15 | (package_clause 16 | (package_identifier)) 17 | (function_declaration 18 | (identifier) 19 | (parameter_list) 20 | (block 21 | (statement_list 22 | (var_declaration 23 | (var_spec 24 | (identifier) 25 | (expression_list 26 | (identifier)))) 27 | (const_declaration 28 | (const_spec 29 | (identifier) 30 | (expression_list 31 | (int_literal)))))))) 32 | 33 | ================================================================================ 34 | Expression statements 35 | ================================================================================ 36 | 37 | package main 38 | 39 | func main() { 40 | foo(5) 41 | } 42 | 43 | -------------------------------------------------------------------------------- 44 | 45 | (source_file 46 | (package_clause 47 | (package_identifier)) 48 | (function_declaration 49 | (identifier) 50 | (parameter_list) 51 | (block 52 | (statement_list 53 | (expression_statement 54 | (call_expression 55 | (identifier) 56 | (argument_list 57 | (int_literal)))))))) 58 | 59 | ================================================================================ 60 | Send statements 61 | ================================================================================ 62 | 63 | package main 64 | 65 | func main() { 66 | foo <- 5 67 | } 68 | 69 | -------------------------------------------------------------------------------- 70 | 71 | (source_file 72 | (package_clause 73 | (package_identifier)) 74 | (function_declaration 75 | (identifier) 76 | (parameter_list) 77 | (block 78 | (statement_list 79 | (send_statement 80 | (identifier) 81 | (int_literal)))))) 82 | 83 | ================================================================================ 84 | Increment/Decrement statements 85 | ================================================================================ 86 | 87 | package main 88 | 89 | func main() { 90 | i++ 91 | j-- 92 | } 93 | 94 | -------------------------------------------------------------------------------- 95 | 96 | (source_file 97 | (package_clause 98 | (package_identifier)) 99 | (function_declaration 100 | (identifier) 101 | (parameter_list) 102 | (block 103 | (statement_list 104 | (inc_statement 105 | (identifier)) 106 | (dec_statement 107 | (identifier)))))) 108 | 109 | ================================================================================ 110 | Assignment statements 111 | ================================================================================ 112 | 113 | package main 114 | 115 | func main() { 116 | a = 1 117 | b, c += 2, 3 118 | d *= 3 119 | e += 1 120 | f /= 2 121 | g <<= 1 122 | h >>= 1 123 | i %= 1 124 | j &= 2 125 | k &^= 3 126 | l -= 1 127 | m |= 2 128 | n ^= 2 129 | } 130 | 131 | -------------------------------------------------------------------------------- 132 | 133 | (source_file 134 | (package_clause 135 | (package_identifier)) 136 | (function_declaration 137 | (identifier) 138 | (parameter_list) 139 | (block 140 | (statement_list 141 | (assignment_statement 142 | (expression_list 143 | (identifier)) 144 | (expression_list 145 | (int_literal))) 146 | (assignment_statement 147 | (expression_list 148 | (identifier) 149 | (identifier)) 150 | (expression_list 151 | (int_literal) 152 | (int_literal))) 153 | (assignment_statement 154 | (expression_list 155 | (identifier)) 156 | (expression_list 157 | (int_literal))) 158 | (assignment_statement 159 | (expression_list 160 | (identifier)) 161 | (expression_list 162 | (int_literal))) 163 | (assignment_statement 164 | (expression_list 165 | (identifier)) 166 | (expression_list 167 | (int_literal))) 168 | (assignment_statement 169 | (expression_list 170 | (identifier)) 171 | (expression_list 172 | (int_literal))) 173 | (assignment_statement 174 | (expression_list 175 | (identifier)) 176 | (expression_list 177 | (int_literal))) 178 | (assignment_statement 179 | (expression_list 180 | (identifier)) 181 | (expression_list 182 | (int_literal))) 183 | (assignment_statement 184 | (expression_list 185 | (identifier)) 186 | (expression_list 187 | (int_literal))) 188 | (assignment_statement 189 | (expression_list 190 | (identifier)) 191 | (expression_list 192 | (int_literal))) 193 | (assignment_statement 194 | (expression_list 195 | (identifier)) 196 | (expression_list 197 | (int_literal))) 198 | (assignment_statement 199 | (expression_list 200 | (identifier)) 201 | (expression_list 202 | (int_literal))) 203 | (assignment_statement 204 | (expression_list 205 | (identifier)) 206 | (expression_list 207 | (int_literal))))))) 208 | 209 | ================================================================================ 210 | Short var declarations 211 | ================================================================================ 212 | 213 | package main 214 | 215 | func main() { 216 | a, b := 1, 2 217 | } 218 | 219 | -------------------------------------------------------------------------------- 220 | 221 | (source_file 222 | (package_clause 223 | (package_identifier)) 224 | (function_declaration 225 | (identifier) 226 | (parameter_list) 227 | (block 228 | (statement_list 229 | (short_var_declaration 230 | (expression_list 231 | (identifier) 232 | (identifier)) 233 | (expression_list 234 | (int_literal) 235 | (int_literal))))))) 236 | 237 | ================================================================================ 238 | If statements 239 | ================================================================================ 240 | 241 | package main 242 | 243 | func main() { 244 | if a { 245 | b() 246 | } 247 | 248 | if a := b(); c { 249 | d() 250 | } 251 | 252 | if a { 253 | b() 254 | } else { 255 | c() 256 | } 257 | 258 | if b { 259 | c() 260 | } else if d { 261 | e() 262 | } else { 263 | f() 264 | } 265 | } 266 | 267 | -------------------------------------------------------------------------------- 268 | 269 | (source_file 270 | (package_clause 271 | (package_identifier)) 272 | (function_declaration 273 | name: (identifier) 274 | parameters: (parameter_list) 275 | body: (block 276 | (statement_list 277 | (if_statement 278 | condition: (identifier) 279 | consequence: (block 280 | (statement_list 281 | (expression_statement 282 | (call_expression 283 | function: (identifier) 284 | arguments: (argument_list)))))) 285 | (if_statement 286 | initializer: (short_var_declaration 287 | left: (expression_list 288 | (identifier)) 289 | right: (expression_list 290 | (call_expression 291 | function: (identifier) 292 | arguments: (argument_list)))) 293 | condition: (identifier) 294 | consequence: (block 295 | (statement_list 296 | (expression_statement 297 | (call_expression 298 | function: (identifier) 299 | arguments: (argument_list)))))) 300 | (if_statement 301 | condition: (identifier) 302 | consequence: (block 303 | (statement_list 304 | (expression_statement 305 | (call_expression 306 | function: (identifier) 307 | arguments: (argument_list))))) 308 | alternative: (block 309 | (statement_list 310 | (expression_statement 311 | (call_expression 312 | function: (identifier) 313 | arguments: (argument_list)))))) 314 | (if_statement 315 | condition: (identifier) 316 | consequence: (block 317 | (statement_list 318 | (expression_statement 319 | (call_expression 320 | function: (identifier) 321 | arguments: (argument_list))))) 322 | alternative: (if_statement 323 | condition: (identifier) 324 | consequence: (block 325 | (statement_list 326 | (expression_statement 327 | (call_expression 328 | function: (identifier) 329 | arguments: (argument_list))))) 330 | alternative: (block 331 | (statement_list 332 | (expression_statement 333 | (call_expression 334 | function: (identifier) 335 | arguments: (argument_list))))))))))) 336 | 337 | ================================================================================ 338 | For statements 339 | ================================================================================ 340 | 341 | package main 342 | 343 | func main() { 344 | for { 345 | a() 346 | goto loop 347 | } 348 | 349 | loop: for i := 0; i < 5; i++ { 350 | a() 351 | break loop 352 | } 353 | 354 | loop2: 355 | for ; i < 10; i++ { 356 | a() 357 | continue loop2 358 | } 359 | 360 | for ;; { 361 | a() 362 | continue 363 | } 364 | 365 | for x := range y { 366 | a(x) 367 | break 368 | } 369 | } 370 | 371 | -------------------------------------------------------------------------------- 372 | 373 | (source_file 374 | (package_clause 375 | (package_identifier)) 376 | (function_declaration 377 | (identifier) 378 | (parameter_list) 379 | (block 380 | (statement_list 381 | (for_statement 382 | (block 383 | (statement_list 384 | (expression_statement 385 | (call_expression 386 | (identifier) 387 | (argument_list))) 388 | (goto_statement 389 | (label_name))))) 390 | (labeled_statement 391 | (label_name) 392 | (for_statement 393 | (for_clause 394 | (short_var_declaration 395 | (expression_list 396 | (identifier)) 397 | (expression_list 398 | (int_literal))) 399 | (binary_expression 400 | (identifier) 401 | (int_literal)) 402 | (inc_statement 403 | (identifier))) 404 | (block 405 | (statement_list 406 | (expression_statement 407 | (call_expression 408 | (identifier) 409 | (argument_list))) 410 | (break_statement 411 | (label_name)))))) 412 | (labeled_statement 413 | (label_name) 414 | (for_statement 415 | (for_clause 416 | (binary_expression 417 | (identifier) 418 | (int_literal)) 419 | (inc_statement 420 | (identifier))) 421 | (block 422 | (statement_list 423 | (expression_statement 424 | (call_expression 425 | (identifier) 426 | (argument_list))) 427 | (continue_statement 428 | (label_name)))))) 429 | (for_statement 430 | (for_clause) 431 | (block 432 | (statement_list 433 | (expression_statement 434 | (call_expression 435 | (identifier) 436 | (argument_list))) 437 | (continue_statement)))) 438 | (for_statement 439 | (range_clause 440 | (expression_list 441 | (identifier)) 442 | (identifier)) 443 | (block 444 | (statement_list 445 | (expression_statement 446 | (call_expression 447 | (identifier) 448 | (argument_list 449 | (identifier)))) 450 | (break_statement)))))))) 451 | 452 | ================================================================================ 453 | Switch statements 454 | ================================================================================ 455 | 456 | func main() { 457 | switch e { 458 | case 1, 2: 459 | a() 460 | fallthrough 461 | case 3: 462 | d() 463 | default: 464 | c() 465 | break 466 | } 467 | 468 | switch { 469 | case true: 470 | return 471 | } 472 | 473 | switch f := y(); f { 474 | } 475 | } 476 | 477 | -------------------------------------------------------------------------------- 478 | 479 | (source_file 480 | (function_declaration 481 | name: (identifier) 482 | parameters: (parameter_list) 483 | body: (block 484 | (statement_list 485 | (expression_switch_statement 486 | value: (identifier) 487 | (expression_case 488 | value: (expression_list 489 | (int_literal) 490 | (int_literal)) 491 | (statement_list 492 | (expression_statement 493 | (call_expression 494 | function: (identifier) 495 | arguments: (argument_list))) 496 | (fallthrough_statement))) 497 | (expression_case 498 | value: (expression_list 499 | (int_literal)) 500 | (statement_list 501 | (expression_statement 502 | (call_expression 503 | function: (identifier) 504 | arguments: (argument_list))))) 505 | (default_case 506 | (statement_list 507 | (expression_statement 508 | (call_expression 509 | function: (identifier) 510 | arguments: (argument_list))) 511 | (break_statement)))) 512 | (expression_switch_statement 513 | (expression_case 514 | value: (expression_list 515 | (true)) 516 | (statement_list 517 | (return_statement)))) 518 | (expression_switch_statement 519 | initializer: (short_var_declaration 520 | left: (expression_list 521 | (identifier)) 522 | right: (expression_list 523 | (call_expression 524 | function: (identifier) 525 | arguments: (argument_list)))) 526 | value: (identifier)))))) 527 | 528 | ================================================================================ 529 | Type switch statements 530 | ================================================================================ 531 | 532 | func main() { 533 | switch e.(type) { 534 | case []Person: 535 | a() 536 | case *Dog: 537 | break 538 | } 539 | switch i := x.(type) { 540 | case nil: 541 | printString("x is nil") 542 | case int: 543 | printInt(i) 544 | case float64: 545 | printFloat64(i) 546 | case func(int) float64: 547 | printFunction(i) 548 | case bool, string: 549 | printString("type is bool or string") 550 | default: 551 | printString("don't know the type") 552 | } 553 | } 554 | 555 | -------------------------------------------------------------------------------- 556 | 557 | (source_file 558 | (function_declaration 559 | name: (identifier) 560 | parameters: (parameter_list) 561 | body: (block 562 | (statement_list 563 | (type_switch_statement 564 | value: (identifier) 565 | (type_case 566 | type: (slice_type 567 | element: (type_identifier)) 568 | (statement_list 569 | (expression_statement 570 | (call_expression 571 | function: (identifier) 572 | arguments: (argument_list))))) 573 | (type_case 574 | type: (pointer_type 575 | (type_identifier)) 576 | (statement_list 577 | (break_statement)))) 578 | (type_switch_statement 579 | alias: (expression_list 580 | (identifier)) 581 | value: (identifier) 582 | (type_case 583 | type: (type_identifier) 584 | (statement_list 585 | (expression_statement 586 | (call_expression 587 | function: (identifier) 588 | arguments: (argument_list 589 | (interpreted_string_literal 590 | (interpreted_string_literal_content))))))) 591 | (type_case 592 | type: (type_identifier) 593 | (statement_list 594 | (expression_statement 595 | (call_expression 596 | function: (identifier) 597 | arguments: (argument_list 598 | (identifier)))))) 599 | (type_case 600 | type: (type_identifier) 601 | (statement_list 602 | (expression_statement 603 | (call_expression 604 | function: (identifier) 605 | arguments: (argument_list 606 | (identifier)))))) 607 | (type_case 608 | type: (function_type 609 | parameters: (parameter_list 610 | (parameter_declaration 611 | type: (type_identifier))) 612 | result: (type_identifier)) 613 | (statement_list 614 | (expression_statement 615 | (call_expression 616 | function: (identifier) 617 | arguments: (argument_list 618 | (identifier)))))) 619 | (type_case 620 | type: (type_identifier) 621 | type: (type_identifier) 622 | (statement_list 623 | (expression_statement 624 | (call_expression 625 | function: (identifier) 626 | arguments: (argument_list 627 | (interpreted_string_literal 628 | (interpreted_string_literal_content))))))) 629 | (default_case 630 | (statement_list 631 | (expression_statement 632 | (call_expression 633 | function: (identifier) 634 | arguments: (argument_list 635 | (interpreted_string_literal 636 | (interpreted_string_literal_content)))))))))))) 637 | 638 | ================================================================================ 639 | Select statements 640 | ================================================================================ 641 | 642 | package main 643 | 644 | func main() { 645 | select { 646 | case x := <-c: 647 | println(x) 648 | case y <- c: 649 | println(5) 650 | case <-time.After(1): 651 | println(6) 652 | default: 653 | return 654 | } 655 | } 656 | 657 | -------------------------------------------------------------------------------- 658 | 659 | (source_file 660 | (package_clause 661 | (package_identifier)) 662 | (function_declaration 663 | name: (identifier) 664 | parameters: (parameter_list) 665 | body: (block 666 | (statement_list 667 | (select_statement 668 | (communication_case 669 | communication: (receive_statement 670 | left: (expression_list 671 | (identifier)) 672 | right: (unary_expression 673 | operand: (identifier))) 674 | (statement_list 675 | (expression_statement 676 | (call_expression 677 | function: (identifier) 678 | arguments: (argument_list 679 | (identifier)))))) 680 | (communication_case 681 | communication: (send_statement 682 | channel: (identifier) 683 | value: (identifier)) 684 | (statement_list 685 | (expression_statement 686 | (call_expression 687 | function: (identifier) 688 | arguments: (argument_list 689 | (int_literal)))))) 690 | (communication_case 691 | communication: (receive_statement 692 | right: (unary_expression 693 | operand: (call_expression 694 | function: (selector_expression 695 | operand: (identifier) 696 | field: (field_identifier)) 697 | arguments: (argument_list 698 | (int_literal))))) 699 | (statement_list 700 | (expression_statement 701 | (call_expression 702 | function: (identifier) 703 | arguments: (argument_list 704 | (int_literal)))))) 705 | (default_case 706 | (statement_list 707 | (return_statement)))))))) 708 | 709 | ================================================================================ 710 | Go and defer statements 711 | ================================================================================ 712 | 713 | package main 714 | 715 | func main() { 716 | defer x.y() 717 | go x.y() 718 | } 719 | 720 | -------------------------------------------------------------------------------- 721 | 722 | (source_file 723 | (package_clause 724 | (package_identifier)) 725 | (function_declaration 726 | (identifier) 727 | (parameter_list) 728 | (block 729 | (statement_list 730 | (defer_statement 731 | (call_expression 732 | (selector_expression 733 | (identifier) 734 | (field_identifier)) 735 | (argument_list))) 736 | (go_statement 737 | (call_expression 738 | (selector_expression 739 | (identifier) 740 | (field_identifier)) 741 | (argument_list))))))) 742 | 743 | ================================================================================ 744 | Nested statement blocks 745 | ================================================================================ 746 | 747 | func main() { 748 | { 749 | println("hi") 750 | } 751 | { 752 | println("bye") 753 | } 754 | } 755 | 756 | -------------------------------------------------------------------------------- 757 | 758 | (source_file 759 | (function_declaration 760 | (identifier) 761 | (parameter_list) 762 | (block 763 | (statement_list 764 | (block 765 | (statement_list 766 | (expression_statement 767 | (call_expression 768 | (identifier) 769 | (argument_list 770 | (interpreted_string_literal 771 | (interpreted_string_literal_content))))))) 772 | (block 773 | (statement_list 774 | (expression_statement 775 | (call_expression 776 | (identifier) 777 | (argument_list 778 | (interpreted_string_literal 779 | (interpreted_string_literal_content))))))))))) 780 | 781 | ================================================================================ 782 | Labels at the ends of statement blocks 783 | ================================================================================ 784 | 785 | func main() { 786 | { 787 | end_of_block: 788 | } 789 | } 790 | 791 | -------------------------------------------------------------------------------- 792 | 793 | (source_file 794 | (function_declaration 795 | name: (identifier) 796 | parameters: (parameter_list) 797 | body: (block 798 | (statement_list 799 | (block 800 | (statement_list 801 | (labeled_statement 802 | label: (label_name)))))))) 803 | 804 | ================================================================================ 805 | Empty statements 806 | ================================================================================ 807 | 808 | package main 809 | 810 | func main() { 811 | ; 812 | } 813 | 814 | -------------------------------------------------------------------------------- 815 | 816 | (source_file 817 | (package_clause 818 | (package_identifier)) 819 | (function_declaration 820 | (identifier) 821 | (parameter_list) 822 | (block 823 | (statement_list 824 | (empty_statement))))) 825 | 826 | ================================================================================ 827 | Nested control statements 828 | ================================================================================ 829 | 830 | package main 831 | 832 | func main() { 833 | for i, v := range vectors { 834 | func() { 835 | if v == v { 836 | fmt.Println("something: %v", vectors[i]) 837 | } 838 | }() 839 | } 840 | } 841 | 842 | -------------------------------------------------------------------------------- 843 | 844 | (source_file 845 | (package_clause 846 | (package_identifier)) 847 | (function_declaration 848 | (identifier) 849 | (parameter_list) 850 | (block 851 | (statement_list 852 | (for_statement 853 | (range_clause 854 | (expression_list 855 | (identifier) 856 | (identifier)) 857 | (identifier)) 858 | (block 859 | (statement_list 860 | (expression_statement 861 | (call_expression 862 | (func_literal 863 | (parameter_list) 864 | (block 865 | (statement_list 866 | (if_statement 867 | (binary_expression 868 | (identifier) 869 | (identifier)) 870 | (block 871 | (statement_list 872 | (expression_statement 873 | (call_expression 874 | (selector_expression 875 | (identifier) 876 | (field_identifier)) 877 | (argument_list 878 | (interpreted_string_literal 879 | (interpreted_string_literal_content)) 880 | (index_expression 881 | (identifier) 882 | (identifier))))))))))) 883 | (argument_list)))))))))) 884 | 885 | ================================================================================ 886 | Top-level statements 887 | ================================================================================ 888 | 889 | foo(5) 890 | x := T { a: b } 891 | 892 | -------------------------------------------------------------------------------- 893 | 894 | (source_file 895 | (expression_statement 896 | (call_expression 897 | (identifier) 898 | (argument_list 899 | (int_literal)))) 900 | (short_var_declaration 901 | (expression_list 902 | (identifier)) 903 | (expression_list 904 | (composite_literal 905 | (type_identifier) 906 | (literal_value 907 | (keyed_element 908 | (literal_element 909 | (identifier)) 910 | (literal_element 911 | (identifier)))))))) 912 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Go grammar for tree-sitter 3 | * @author Max Brunsfeld 4 | * @author Amaan Qureshi 5 | * @license MIT 6 | */ 7 | 8 | /// 9 | // @ts-check 10 | 11 | const PREC = { 12 | primary: 7, 13 | unary: 6, 14 | multiplicative: 5, 15 | additive: 4, 16 | comparative: 3, 17 | and: 2, 18 | or: 1, 19 | composite_literal: -1, 20 | }; 21 | 22 | const multiplicativeOperators = ['*', '/', '%', '<<', '>>', '&', '&^']; 23 | const additiveOperators = ['+', '-', '|', '^']; 24 | const comparativeOperators = ['==', '!=', '<', '<=', '>', '>=']; 25 | const assignmentOperators = multiplicativeOperators.concat(additiveOperators).map(operator => operator + '=').concat('='); 26 | 27 | 28 | const newline = /\n/; 29 | const terminator = choice(newline, ';', '\0'); 30 | 31 | const hexDigit = /[0-9a-fA-F]/; 32 | const octalDigit = /[0-7]/; 33 | const decimalDigit = /[0-9]/; 34 | const binaryDigit = /[01]/; 35 | 36 | const hexDigits = seq(hexDigit, repeat(seq(optional('_'), hexDigit))); 37 | const octalDigits = seq(octalDigit, repeat(seq(optional('_'), octalDigit))); 38 | const decimalDigits = seq(decimalDigit, repeat(seq(optional('_'), decimalDigit))); 39 | const binaryDigits = seq(binaryDigit, repeat(seq(optional('_'), binaryDigit))); 40 | 41 | const hexLiteral = seq('0', choice('x', 'X'), optional('_'), hexDigits); 42 | const octalLiteral = seq('0', optional(choice('o', 'O')), optional('_'), octalDigits); 43 | const decimalLiteral = choice('0', seq(/[1-9]/, optional(seq(optional('_'), decimalDigits)))); 44 | const binaryLiteral = seq('0', choice('b', 'B'), optional('_'), binaryDigits); 45 | 46 | const intLiteral = choice(binaryLiteral, decimalLiteral, octalLiteral, hexLiteral); 47 | 48 | const decimalExponent = seq(choice('e', 'E'), optional(choice('+', '-')), decimalDigits); 49 | const decimalFloatLiteral = choice( 50 | seq(decimalDigits, '.', optional(decimalDigits), optional(decimalExponent)), 51 | seq(decimalDigits, decimalExponent), 52 | seq('.', decimalDigits, optional(decimalExponent)), 53 | ); 54 | 55 | const hexExponent = seq(choice('p', 'P'), optional(choice('+', '-')), decimalDigits); 56 | const hexMantissa = choice( 57 | seq(optional('_'), hexDigits, '.', optional(hexDigits)), 58 | seq(optional('_'), hexDigits), 59 | seq('.', hexDigits), 60 | ); 61 | const hexFloatLiteral = seq('0', choice('x', 'X'), hexMantissa, hexExponent); 62 | 63 | const floatLiteral = choice(decimalFloatLiteral, hexFloatLiteral); 64 | 65 | const imaginaryLiteral = seq(choice(decimalDigits, intLiteral, floatLiteral), 'i'); 66 | 67 | module.exports = grammar({ 68 | name: 'go', 69 | 70 | extras: $ => [ 71 | $.comment, 72 | /\s/, 73 | ], 74 | 75 | inline: $ => [ 76 | $._type, 77 | $._type_identifier, 78 | $._field_identifier, 79 | $._package_identifier, 80 | $._top_level_declaration, 81 | $._string_literal, 82 | $._interface_elem, 83 | ], 84 | 85 | word: $ => $.identifier, 86 | 87 | conflicts: $ => [ 88 | [$._simple_type, $._expression], 89 | [$._simple_type, $.generic_type, $._expression], 90 | [$.qualified_type, $._expression], 91 | [$.generic_type, $._simple_type], 92 | [$.parameter_declaration, $._simple_type], 93 | [$.type_parameter_declaration, $._simple_type, $._expression], 94 | [$.type_parameter_declaration, $._expression], 95 | [$.type_parameter_declaration, $._simple_type, $.generic_type, $._expression], 96 | ], 97 | 98 | reserved: { 99 | global: $ => [ 100 | // https://go.dev/ref/spec#Keywords 101 | 'break', 'default', 'func', 'interface', 'select', 102 | 'case', 'defer', 'go', 'map', 'struct', 103 | 'chan', 'else', 'goto', 'package', 'switch', 104 | 'const', 'fallthrough', 'if', 'range', 'type', 105 | 'continue', 'for', 'import', 'return', 'var', 106 | ], 107 | }, 108 | 109 | supertypes: $ => [ 110 | $._expression, 111 | $._type, 112 | $._simple_type, 113 | $._statement, 114 | $._simple_statement, 115 | ], 116 | 117 | rules: { 118 | source_file: $ => seq( 119 | repeat(choice( 120 | // Unlike a Go compiler, we accept statements at top-level to enable 121 | // parsing of partial code snippets in documentation (see #63). 122 | seq($._statement, terminator), 123 | seq($._top_level_declaration, terminator), 124 | )), 125 | optional($._top_level_declaration), 126 | ), 127 | 128 | _top_level_declaration: $ => choice( 129 | $.package_clause, 130 | $.function_declaration, 131 | $.method_declaration, 132 | $.import_declaration, 133 | ), 134 | 135 | package_clause: $ => seq( 136 | 'package', 137 | $._package_identifier, 138 | ), 139 | 140 | import_declaration: $ => seq( 141 | 'import', 142 | choice( 143 | $.import_spec, 144 | $.import_spec_list, 145 | ), 146 | ), 147 | 148 | import_spec: $ => seq( 149 | optional(field('name', choice( 150 | $.dot, 151 | $.blank_identifier, 152 | $._package_identifier, 153 | ))), 154 | field('path', $._string_literal), 155 | ), 156 | dot: _ => '.', 157 | blank_identifier: _ => '_', 158 | 159 | import_spec_list: $ => seq( 160 | '(', 161 | optional(seq( 162 | $.import_spec, 163 | repeat(seq(terminator, $.import_spec)), 164 | optional(terminator), 165 | )), 166 | ')', 167 | ), 168 | 169 | _declaration: $ => choice( 170 | $.const_declaration, 171 | $.type_declaration, 172 | $.var_declaration, 173 | ), 174 | 175 | const_declaration: $ => seq( 176 | 'const', 177 | choice( 178 | $.const_spec, 179 | seq( 180 | '(', 181 | repeat(seq($.const_spec, terminator)), 182 | ')', 183 | ), 184 | ), 185 | ), 186 | 187 | const_spec: $ => prec.left(seq( 188 | field('name', commaSep1($.identifier)), 189 | optional(seq( 190 | optional(field('type', $._type)), 191 | '=', 192 | field('value', $.expression_list), 193 | )), 194 | )), 195 | 196 | var_declaration: $ => seq( 197 | 'var', 198 | choice( 199 | $.var_spec, 200 | $.var_spec_list, 201 | ), 202 | ), 203 | 204 | var_spec: $ => seq( 205 | commaSep1(field('name', $.identifier)), 206 | choice( 207 | seq( 208 | field('type', $._type), 209 | optional(seq('=', field('value', $.expression_list))), 210 | ), 211 | seq('=', field('value', $.expression_list)), 212 | ), 213 | ), 214 | 215 | var_spec_list: $ => seq( 216 | '(', 217 | repeat(seq($.var_spec, terminator)), 218 | ')', 219 | ), 220 | 221 | function_declaration: $ => prec.right(1, seq( 222 | 'func', 223 | field('name', $.identifier), 224 | field('type_parameters', optional($.type_parameter_list)), 225 | field('parameters', $.parameter_list), 226 | field('result', optional(choice($.parameter_list, $._simple_type))), 227 | field('body', optional($.block)), 228 | )), 229 | 230 | method_declaration: $ => prec.right(1, seq( 231 | 'func', 232 | field('receiver', $.parameter_list), 233 | field('name', $._field_identifier), 234 | field('parameters', $.parameter_list), 235 | field('result', optional(choice($.parameter_list, $._simple_type))), 236 | field('body', optional($.block)), 237 | )), 238 | 239 | type_parameter_list: $ => seq( 240 | '[', 241 | commaSep1($.type_parameter_declaration), 242 | optional(','), 243 | ']', 244 | ), 245 | 246 | type_parameter_declaration: $ => seq( 247 | commaSep1(field('name', $.identifier)), 248 | field('type', alias($.type_elem, $.type_constraint)), 249 | ), 250 | 251 | parameter_list: $ => seq( 252 | '(', 253 | optional(seq( 254 | commaSep(choice($.parameter_declaration, $.variadic_parameter_declaration)), 255 | optional(','), 256 | )), 257 | ')', 258 | ), 259 | 260 | parameter_declaration: $ => seq( 261 | commaSep(field('name', $.identifier)), 262 | field('type', $._type), 263 | ), 264 | 265 | variadic_parameter_declaration: $ => seq( 266 | field('name', optional($.identifier)), 267 | '...', 268 | field('type', $._type), 269 | ), 270 | 271 | type_alias: $ => seq( 272 | field('name', $._type_identifier), 273 | field('type_parameters', optional($.type_parameter_list)), 274 | '=', 275 | field('type', $._type), 276 | ), 277 | 278 | type_declaration: $ => seq( 279 | 'type', 280 | choice( 281 | $.type_spec, 282 | $.type_alias, 283 | seq( 284 | '(', 285 | optionalTrailingSep(choice($.type_spec, $.type_alias), terminator), 286 | ')', 287 | ), 288 | ), 289 | ), 290 | 291 | type_spec: $ => seq( 292 | field('name', $._type_identifier), 293 | field('type_parameters', optional($.type_parameter_list)), 294 | field('type', $._type), 295 | ), 296 | 297 | field_name_list: $ => commaSep1($._field_identifier), 298 | 299 | expression_list: $ => commaSep1($._expression), 300 | 301 | _type: $ => choice( 302 | $._simple_type, 303 | $.parenthesized_type, 304 | ), 305 | 306 | parenthesized_type: $ => seq('(', $._type, ')'), 307 | 308 | _simple_type: $ => choice( 309 | prec.dynamic(-1, $._type_identifier), 310 | $.generic_type, 311 | $.qualified_type, 312 | $.pointer_type, 313 | $.struct_type, 314 | $.interface_type, 315 | $.array_type, 316 | $.slice_type, 317 | prec.dynamic(3, $.map_type), 318 | $.channel_type, 319 | $.function_type, 320 | $.negated_type, 321 | ), 322 | 323 | generic_type: $ => prec.dynamic(1, seq( 324 | field('type', choice($._type_identifier, $.qualified_type, $.negated_type)), 325 | field('type_arguments', $.type_arguments), 326 | )), 327 | 328 | type_arguments: $ => prec.dynamic(2, seq( 329 | '[', 330 | commaSep1($.type_elem), 331 | optional(','), 332 | ']', 333 | )), 334 | 335 | pointer_type: $ => prec(PREC.unary, seq('*', $._type)), 336 | 337 | array_type: $ => prec.right(seq( 338 | '[', 339 | field('length', $._expression), 340 | ']', 341 | field('element', $._type), 342 | )), 343 | 344 | implicit_length_array_type: $ => seq( 345 | '[', 346 | '...', 347 | ']', 348 | field('element', $._type), 349 | ), 350 | 351 | slice_type: $ => prec.right(seq( 352 | '[', 353 | ']', 354 | field('element', $._type), 355 | )), 356 | 357 | struct_type: $ => seq( 358 | 'struct', 359 | $.field_declaration_list, 360 | ), 361 | 362 | negated_type: $ => prec.left(seq( 363 | '~', 364 | $._type, 365 | )), 366 | 367 | field_declaration_list: $ => seq( 368 | '{', 369 | optional(seq( 370 | $.field_declaration, 371 | repeat(seq(terminator, $.field_declaration)), 372 | optional(terminator), 373 | )), 374 | '}', 375 | ), 376 | 377 | field_declaration: $ => seq( 378 | choice( 379 | seq( 380 | commaSep1(field('name', $._field_identifier)), 381 | field('type', $._type), 382 | ), 383 | seq( 384 | optional('*'), 385 | field('type', choice( 386 | $._type_identifier, 387 | $.qualified_type, 388 | $.generic_type, 389 | )), 390 | ), 391 | ), 392 | field('tag', optional($._string_literal)), 393 | ), 394 | 395 | interface_type: $ => seq( 396 | 'interface', 397 | '{', 398 | optional(seq( 399 | $._interface_elem, 400 | repeat(seq(terminator, $._interface_elem)), 401 | optional(terminator), 402 | )), 403 | '}', 404 | ), 405 | 406 | _interface_elem: $ => choice( 407 | $.method_elem, 408 | $.type_elem, 409 | ), 410 | 411 | method_elem: $ => seq( 412 | field('name', $._field_identifier), 413 | field('parameters', $.parameter_list), 414 | field('result', optional(choice($.parameter_list, $._simple_type))), 415 | ), 416 | 417 | type_elem: $ => sep1($._type, '|'), 418 | 419 | map_type: $ => prec.right(seq( 420 | 'map', 421 | '[', 422 | field('key', $._type), 423 | ']', 424 | field('value', $._type), 425 | )), 426 | 427 | channel_type: $ => prec.left(choice( 428 | seq('chan', field('value', $._type)), 429 | seq('chan', '<-', field('value', $._type)), 430 | prec(PREC.unary, seq('<-', 'chan', field('value', $._type))), 431 | )), 432 | 433 | function_type: $ => prec.right(seq( 434 | 'func', 435 | field('parameters', $.parameter_list), 436 | field('result', optional(choice($.parameter_list, $._simple_type))), 437 | )), 438 | 439 | block: $ => seq( 440 | '{', 441 | optional($.statement_list), 442 | '}', 443 | ), 444 | 445 | statement_list: $ => choice( 446 | seq( 447 | $._statement, 448 | repeat(seq(terminator, $._statement)), 449 | optional(seq( 450 | terminator, 451 | optional(alias($.empty_labeled_statement, $.labeled_statement)), 452 | )), 453 | ), 454 | alias($.empty_labeled_statement, $.labeled_statement), 455 | ), 456 | 457 | _statement: $ => choice( 458 | $._declaration, 459 | $._simple_statement, 460 | $.return_statement, 461 | $.go_statement, 462 | $.defer_statement, 463 | $.if_statement, 464 | $.for_statement, 465 | $.expression_switch_statement, 466 | $.type_switch_statement, 467 | $.select_statement, 468 | $.labeled_statement, 469 | $.fallthrough_statement, 470 | $.break_statement, 471 | $.continue_statement, 472 | $.goto_statement, 473 | $.block, 474 | $.empty_statement, 475 | ), 476 | 477 | empty_statement: _ => ';', 478 | 479 | _simple_statement: $ => choice( 480 | $.expression_statement, 481 | $.send_statement, 482 | $.inc_statement, 483 | $.dec_statement, 484 | $.assignment_statement, 485 | $.short_var_declaration, 486 | ), 487 | 488 | expression_statement: $ => $._expression, 489 | 490 | send_statement: $ => seq( 491 | field('channel', $._expression), 492 | '<-', 493 | field('value', $._expression), 494 | ), 495 | 496 | receive_statement: $ => seq( 497 | optional(seq( 498 | field('left', $.expression_list), 499 | choice('=', ':='), 500 | )), 501 | field('right', $._expression), 502 | ), 503 | 504 | inc_statement: $ => seq( 505 | $._expression, 506 | '++', 507 | ), 508 | 509 | dec_statement: $ => seq( 510 | $._expression, 511 | '--', 512 | ), 513 | 514 | assignment_statement: $ => seq( 515 | field('left', $.expression_list), 516 | field('operator', choice(...assignmentOperators)), 517 | field('right', $.expression_list), 518 | ), 519 | 520 | short_var_declaration: $ => seq( 521 | // TODO: this should really only allow identifier lists, but that causes 522 | // conflicts between identifiers as expressions vs identifiers here. 523 | field('left', $.expression_list), 524 | ':=', 525 | field('right', $.expression_list), 526 | ), 527 | 528 | labeled_statement: $ => seq( 529 | field('label', alias($.identifier, $.label_name)), 530 | ':', 531 | $._statement, 532 | ), 533 | 534 | empty_labeled_statement: $ => seq( 535 | field('label', alias($.identifier, $.label_name)), 536 | ':', 537 | ), 538 | 539 | // This is a hack to prevent `fallthrough_statement` from being parsed as 540 | // a single token. For consistency with `break_statement` etc it should 541 | // be parsed as a parent node that *contains* a `fallthrough` token. 542 | fallthrough_statement: _ => prec.left('fallthrough'), 543 | 544 | break_statement: $ => seq('break', optional(alias($.identifier, $.label_name))), 545 | 546 | continue_statement: $ => seq('continue', optional(alias($.identifier, $.label_name))), 547 | 548 | goto_statement: $ => seq('goto', alias($.identifier, $.label_name)), 549 | 550 | return_statement: $ => seq('return', optional($.expression_list)), 551 | 552 | go_statement: $ => seq('go', $._expression), 553 | 554 | defer_statement: $ => seq('defer', $._expression), 555 | 556 | if_statement: $ => seq( 557 | 'if', 558 | optional(seq( 559 | field('initializer', $._simple_statement), 560 | ';', 561 | )), 562 | field('condition', $._expression), 563 | field('consequence', $.block), 564 | optional(seq( 565 | 'else', 566 | field('alternative', choice($.block, $.if_statement)), 567 | )), 568 | ), 569 | 570 | for_statement: $ => seq( 571 | 'for', 572 | optional(choice($._expression, $.for_clause, $.range_clause)), 573 | field('body', $.block), 574 | ), 575 | 576 | for_clause: $ => seq( 577 | field('initializer', optional($._simple_statement)), 578 | ';', 579 | field('condition', optional($._expression)), 580 | ';', 581 | field('update', optional($._simple_statement)), 582 | ), 583 | 584 | range_clause: $ => seq( 585 | optional(seq( 586 | field('left', $.expression_list), 587 | choice('=', ':='), 588 | )), 589 | 'range', 590 | field('right', $._expression), 591 | ), 592 | 593 | expression_switch_statement: $ => seq( 594 | 'switch', 595 | optional(seq( 596 | field('initializer', $._simple_statement), 597 | ';', 598 | )), 599 | field('value', optional($._expression)), 600 | '{', 601 | repeat(choice($.expression_case, $.default_case)), 602 | '}', 603 | ), 604 | 605 | expression_case: $ => seq( 606 | 'case', 607 | field('value', $.expression_list), 608 | ':', 609 | optional($.statement_list), 610 | ), 611 | 612 | default_case: $ => seq( 613 | 'default', 614 | ':', 615 | optional($.statement_list), 616 | ), 617 | 618 | type_switch_statement: $ => seq( 619 | 'switch', 620 | $._type_switch_header, 621 | '{', 622 | repeat(choice($.type_case, $.default_case)), 623 | '}', 624 | ), 625 | 626 | _type_switch_header: $ => seq( 627 | optional(seq( 628 | field('initializer', $._simple_statement), 629 | ';', 630 | )), 631 | optional(seq(field('alias', $.expression_list), ':=')), 632 | field('value', $._expression), 633 | '.', 634 | '(', 635 | 'type', 636 | ')', 637 | ), 638 | 639 | type_case: $ => seq( 640 | 'case', 641 | field('type', commaSep1($._type)), 642 | ':', 643 | optional($.statement_list), 644 | ), 645 | 646 | select_statement: $ => seq( 647 | 'select', 648 | '{', 649 | repeat(choice($.communication_case, $.default_case)), 650 | '}', 651 | ), 652 | 653 | communication_case: $ => seq( 654 | 'case', 655 | field('communication', choice($.send_statement, $.receive_statement)), 656 | ':', 657 | optional($.statement_list), 658 | ), 659 | 660 | _expression: $ => choice( 661 | $.unary_expression, 662 | $.binary_expression, 663 | $.selector_expression, 664 | $.index_expression, 665 | $.slice_expression, 666 | $.call_expression, 667 | $.type_assertion_expression, 668 | $.type_conversion_expression, 669 | $.type_instantiation_expression, 670 | $.identifier, 671 | alias(choice('new', 'make'), $.identifier), 672 | $.composite_literal, 673 | $.func_literal, 674 | $._string_literal, 675 | $.int_literal, 676 | $.float_literal, 677 | $.imaginary_literal, 678 | $.rune_literal, 679 | $.nil, 680 | $.true, 681 | $.false, 682 | $.iota, 683 | $.parenthesized_expression, 684 | ), 685 | 686 | parenthesized_expression: $ => seq( 687 | '(', 688 | $._expression, 689 | ')', 690 | ), 691 | 692 | call_expression: $ => prec(PREC.primary, choice( 693 | seq( 694 | field('function', alias(choice('new', 'make'), $.identifier)), 695 | field('arguments', alias($.special_argument_list, $.argument_list)), 696 | ), 697 | seq( 698 | field('function', $._expression), 699 | field('type_arguments', optional($.type_arguments)), 700 | field('arguments', $.argument_list), 701 | ), 702 | )), 703 | 704 | variadic_argument: $ => prec.right(seq( 705 | $._expression, 706 | '...', 707 | )), 708 | 709 | special_argument_list: $ => seq( 710 | '(', 711 | optional(seq( 712 | $._type, 713 | repeat(seq(',', $._expression)), 714 | optional(','), 715 | )), 716 | ')', 717 | ), 718 | 719 | argument_list: $ => seq( 720 | '(', 721 | optional(seq( 722 | choice($._expression, $.variadic_argument), 723 | repeat(seq(',', choice($._expression, $.variadic_argument))), 724 | optional(','), 725 | )), 726 | ')', 727 | ), 728 | 729 | selector_expression: $ => prec(PREC.primary, seq( 730 | field('operand', $._expression), 731 | '.', 732 | field('field', $._field_identifier), 733 | )), 734 | 735 | index_expression: $ => prec(PREC.primary, prec.dynamic(1, seq( 736 | field('operand', $._expression), 737 | '[', 738 | field('index', $._expression), 739 | ']', 740 | ))), 741 | 742 | slice_expression: $ => prec(PREC.primary, seq( 743 | field('operand', $._expression), 744 | '[', 745 | choice( 746 | seq( 747 | field('start', optional($._expression)), 748 | ':', 749 | field('end', optional($._expression)), 750 | ), 751 | seq( 752 | field('start', optional($._expression)), 753 | ':', 754 | field('end', $._expression), 755 | ':', 756 | field('capacity', $._expression), 757 | ), 758 | ), 759 | ']', 760 | )), 761 | 762 | type_assertion_expression: $ => prec(PREC.primary, seq( 763 | field('operand', $._expression), 764 | '.', 765 | '(', 766 | field('type', $._type), 767 | ')', 768 | )), 769 | 770 | type_conversion_expression: $ => prec.dynamic(-1, seq( 771 | field('type', $._type), 772 | '(', 773 | field('operand', $._expression), 774 | optional(','), 775 | ')', 776 | )), 777 | 778 | type_instantiation_expression: $ => prec.dynamic(-1, seq( 779 | field('type', $._type), 780 | '[', 781 | commaSep1($._type), 782 | optional(','), 783 | ']', 784 | )), 785 | 786 | composite_literal: $ => prec(PREC.composite_literal, seq( 787 | field('type', choice( 788 | $.map_type, 789 | $.slice_type, 790 | $.array_type, 791 | $.implicit_length_array_type, 792 | $.struct_type, 793 | $._type_identifier, 794 | $.generic_type, 795 | $.qualified_type, 796 | )), 797 | field('body', $.literal_value), 798 | )), 799 | 800 | literal_value: $ => seq( 801 | '{', 802 | optional( 803 | seq( 804 | commaSep(choice($.literal_element, $.keyed_element)), 805 | optional(','))), 806 | '}', 807 | ), 808 | 809 | literal_element: $ => choice($._expression, $.literal_value), 810 | 811 | // In T{k: v}, the key k may be: 812 | // - any expression (when T is a map, slice or array), 813 | // - a field identifier (when T is a struct), or 814 | // - a literal_element (when T is an array). 815 | // The first two cases cannot be distinguished without type information. 816 | keyed_element: $ => seq( 817 | field('key', $.literal_element), 818 | ':', 819 | field('value', $.literal_element), 820 | ), 821 | 822 | func_literal: $ => seq( 823 | 'func', 824 | field('parameters', $.parameter_list), 825 | field('result', optional(choice($.parameter_list, $._simple_type))), 826 | field('body', $.block), 827 | ), 828 | 829 | unary_expression: $ => prec(PREC.unary, seq( 830 | field('operator', choice('+', '-', '!', '^', '*', '&', '<-')), 831 | field('operand', $._expression), 832 | )), 833 | 834 | binary_expression: $ => { 835 | const table = [ 836 | [PREC.multiplicative, choice(...multiplicativeOperators)], 837 | [PREC.additive, choice(...additiveOperators)], 838 | [PREC.comparative, choice(...comparativeOperators)], 839 | [PREC.and, '&&'], 840 | [PREC.or, '||'], 841 | ]; 842 | 843 | return choice(...table.map(([precedence, operator]) => 844 | // @ts-ignore 845 | prec.left(precedence, seq( 846 | field('left', $._expression), 847 | // @ts-ignore 848 | field('operator', operator), 849 | field('right', $._expression), 850 | )), 851 | )); 852 | }, 853 | 854 | qualified_type: $ => seq( 855 | field('package', $._package_identifier), 856 | '.', 857 | field('name', $._type_identifier), 858 | ), 859 | 860 | identifier: _ => /[_\p{XID_Start}][_\p{XID_Continue}]*/, 861 | 862 | _type_identifier: $ => alias($.identifier, $.type_identifier), 863 | _field_identifier: $ => alias($.identifier, $.field_identifier), 864 | _package_identifier: $ => alias($.identifier, $.package_identifier), 865 | 866 | _string_literal: $ => choice( 867 | $.raw_string_literal, 868 | $.interpreted_string_literal, 869 | ), 870 | 871 | raw_string_literal: $ => seq( 872 | '`', 873 | alias(token(prec(1, /[^`]*/)), $.raw_string_literal_content), 874 | '`', 875 | ), 876 | 877 | interpreted_string_literal: $ => seq( 878 | '"', 879 | repeat(choice( 880 | alias(token.immediate(prec(1, /[^"\n\\]+/)), $.interpreted_string_literal_content), 881 | $.escape_sequence, 882 | )), 883 | token.immediate('"'), 884 | ), 885 | 886 | escape_sequence: _ => token.immediate(seq( 887 | '\\', 888 | choice( 889 | /[^xuU]/, 890 | /\d{2,3}/, 891 | /x[0-9a-fA-F]{2,}/, 892 | /u[0-9a-fA-F]{4}/, 893 | /U[0-9a-fA-F]{8}/, 894 | ), 895 | )), 896 | 897 | int_literal: _ => token(intLiteral), 898 | 899 | float_literal: _ => token(floatLiteral), 900 | 901 | imaginary_literal: _ => token(imaginaryLiteral), 902 | 903 | rune_literal: _ => token(seq( 904 | '\'', 905 | choice( 906 | /[^'\\]/, 907 | seq( 908 | '\\', 909 | choice( 910 | seq('x', hexDigit, hexDigit), 911 | seq(octalDigit, octalDigit, octalDigit), 912 | seq('u', hexDigit, hexDigit, hexDigit, hexDigit), 913 | seq('U', hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit, hexDigit), 914 | seq(choice('a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '\'', '"')), 915 | ), 916 | ), 917 | ), 918 | '\'', 919 | )), 920 | 921 | nil: _ => 'nil', 922 | true: _ => 'true', 923 | false: _ => 'false', 924 | iota: _ => 'iota', 925 | 926 | // http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890 927 | comment: _ => token(choice( 928 | seq('//', /.*/), 929 | seq( 930 | '/*', 931 | /[^*]*\*+([^/*][^*]*\*+)*/, 932 | '/', 933 | ), 934 | )), 935 | }, 936 | }); 937 | 938 | /** 939 | * Creates a rule to match one or more occurrences of `rule` separated by `sep` 940 | * 941 | * @param {RuleOrLiteral} rule 942 | * 943 | * @param {RuleOrLiteral} separator 944 | * 945 | * @returns {SeqRule} 946 | */ 947 | function sep1(rule, separator) { 948 | return seq(rule, repeat(seq(separator, rule))); 949 | } 950 | 951 | /** 952 | * Creates a rule to match zero or more of the rules separated by {sep}, 953 | * with an optional one at the end. 954 | * 955 | * @param {RuleOrLiteral} rule 956 | * 957 | * @param {RuleOrLiteral} separator 958 | */ 959 | function optionalTrailingSep(rule, separator) { 960 | return optional(seq(rule, repeat(seq(separator, rule)), optional(separator))); 961 | } 962 | 963 | /** 964 | * Creates a rule to match one or more of the rules separated by a comma 965 | * 966 | * @param {Rule} rule 967 | * 968 | * @returns {SeqRule} 969 | */ 970 | function commaSep1(rule) { 971 | return seq(rule, repeat(seq(',', rule))); 972 | } 973 | 974 | /** 975 | * Creates a rule to optionally match one or more of the rules separated by a comma 976 | * 977 | * @param {Rule} rule 978 | * 979 | * @returns {ChoiceRule} 980 | */ 981 | function commaSep(rule) { 982 | return optional(commaSep1(rule)); 983 | } 984 | --------------------------------------------------------------------------------