Repository: tree-sitter/tree-sitter-ruby Branch: master Commit: ad907a69da0c Files: 67 Total size: 15.1 MB Directory structure: gitextract_arlgabw0/ ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ ├── config.yml │ │ └── feature_request.yml │ └── workflows/ │ ├── ci.yml │ ├── fuzz.yml │ ├── lint.yml │ └── publish.yml ├── .gitignore ├── CMakeLists.txt ├── Cargo.toml ├── LICENSE ├── Makefile ├── Package.resolved ├── Package.swift ├── README.md ├── binding.gyp ├── bindings/ │ ├── c/ │ │ ├── tree-sitter-ruby.h │ │ └── tree-sitter-ruby.pc.in │ ├── go/ │ │ ├── binding.go │ │ └── binding_test.go │ ├── node/ │ │ ├── binding.cc │ │ ├── binding_test.js │ │ ├── index.d.ts │ │ └── index.js │ ├── python/ │ │ ├── tests/ │ │ │ └── test_binding.py │ │ └── tree_sitter_ruby/ │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ ├── binding.c │ │ └── py.typed │ ├── rust/ │ │ ├── build.rs │ │ └── lib.rs │ └── swift/ │ ├── TreeSitterRuby/ │ │ └── ruby.h │ └── TreeSitterRubyTests/ │ └── TreeSitterRubyTests.swift ├── eslint.config.mjs ├── go.mod ├── go.sum ├── grammar.js ├── package.json ├── pyproject.toml ├── queries/ │ ├── highlights.scm │ ├── locals.scm │ └── tags.scm ├── setup.py ├── src/ │ ├── grammar.json │ ├── node-types.json │ ├── parser.c │ ├── scanner.c │ └── tree_sitter/ │ ├── alloc.h │ ├── array.h │ └── parser.h ├── test/ │ ├── corpus/ │ │ ├── comments.txt │ │ ├── control-flow.txt │ │ ├── declarations.txt │ │ ├── expressions.txt │ │ ├── line-endings.txt │ │ ├── literals.txt │ │ ├── patterns.txt │ │ ├── single-cr-as-whitespace.txt │ │ └── statements.txt │ └── highlight/ │ ├── classes.rb │ ├── constants.rb │ ├── literals.rb │ ├── patterns.rb │ └── variables.rb └── tree-sitter.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 [*.{json,toml,yml,gyp}] indent_style = space indent_size = 2 [*.js] indent_style = space indent_size = 2 [*.scm] indent_style = space indent_size = 2 [*.{c,cc,h}] indent_style = space indent_size = 4 [*.rs] indent_style = space indent_size = 4 [*.{py,pyi}] indent_style = space indent_size = 4 [*.swift] indent_style = space indent_size = 4 [*.go] indent_style = tab indent_size = 8 [Makefile] indent_style = tab indent_size = 8 [parser.c] indent_size = 2 [{alloc,array,parser}.h] indent_size = 2 ================================================ FILE: .gitattributes ================================================ * text=auto eol=lf # Generated source files src/*.json linguist-generated src/parser.c linguist-generated src/tree_sitter/* linguist-generated # C bindings bindings/c/* linguist-generated CMakeLists.txt linguist-generated Makefile linguist-generated # Rust bindings bindings/rust/* linguist-generated Cargo.toml linguist-generated Cargo.lock linguist-generated # Node.js bindings bindings/node/* linguist-generated binding.gyp linguist-generated package.json linguist-generated package-lock.json linguist-generated # Python bindings bindings/python/** linguist-generated setup.py linguist-generated pyproject.toml linguist-generated # Go bindings bindings/go/* linguist-generated go.mod linguist-generated go.sum linguist-generated # Swift bindings bindings/swift/** linguist-generated Package.swift linguist-generated Package.resolved linguist-generated ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: Bug Report description: File a bug or issue title: "bug: " labels: [bug] body: - type: markdown attributes: value: | **Before** reporting an issue, make sure to search [existing issues](https://github.com/tree-sitter/tree-sitter-c/issues). Usage questions such as ***"How do I...?"*** either belong in [Discussions](https://github.com/tree-sitter/tree-sitter/discussions) upstream or in our [Discord server](https://discord.gg/w7nTvsVJhm) and will be closed. If your issue is related to a bug in your editor-experience because your editor *leverages* tree-sitter and this parser, then it is likely your issue does *NOT* belong here and belongs in the relevant editor's repository. - type: checkboxes attributes: label: Did you check existing issues? description: Make sure you've checked all of the below before submitting an issue options: - label: I have read all the [tree-sitter docs](https://tree-sitter.github.io/tree-sitter/using-parsers) if it relates to using the parser required: false - label: I have searched the existing issues of tree-sitter-c required: true - type: input attributes: label: "Tree-Sitter CLI Version, if relevant (output of `tree-sitter --version`)" placeholder: "tree-sitter 0.20.8 (6bbb50bef8249e6460e7d69e42cc8146622fa4fd)" validations: required: false - type: textarea attributes: label: Describe the bug description: A clear and concise description of what the bug is. Please include any related errors you see such as parsing errors or tree-sitter cli errors. validations: required: true - type: textarea attributes: label: Steps To Reproduce/Bad Parse Tree description: Steps to reproduce the behavior. If you have a bad parse tree, please include it here. You can get this by running `tree-sitter parse ` and copying the output. placeholder: | 1. 2. 3. validations: required: true - type: textarea attributes: label: Expected Behavior/Parse Tree description: A concise description of what you expected to happen, or in the case of a bad parse tree, the expected parse tree. validations: required: true - type: textarea attributes: label: Repro description: Minimal code to reproduce this issue. Ideally this should be reproducible with the C library or the tree-sitter cli, do not suggest an editor or external tool. value: | // Example code that causes the issue void foo() { // Code that fails to parse, or causes an error } render: C validations: required: false ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.yml ================================================ name: Feature Request description: Suggest a new feature title: "feature: " labels: [enhancement] body: - type: checkboxes attributes: label: Did you check the tree-sitter docs? description: Make sure you read all the docs before submitting a feature request options: - label: I have read all the [tree-sitter docs](https://tree-sitter.github.io/tree-sitter/using-parsers) if it relates to using the parser required: false - type: textarea validations: required: true attributes: label: Is your feature request related to a problem? Please describe. description: A clear and concise description of what the problem is. Ex. I think the grammar models this rule incorrectly and can be improved, or the C spec has officially added a new feature that should be added to the grammar. - type: textarea validations: required: true attributes: label: Describe the solution you'd like description: A clear and concise description of what you want to happen. - type: textarea validations: required: true attributes: label: Describe alternatives you've considered description: A clear and concise description of any alternative solutions or features you've considered. - type: textarea validations: required: false attributes: label: Additional context description: Add any other context or screenshots about the feature request here. If your feature request is related to a new C feature, please include a link to the relevant **official** C documentation. ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: branches: [master] paths: - grammar.js - src/** - test/** - bindings/** - binding.gyp pull_request: paths: - grammar.js - src/** - test/** - bindings/** - binding.gyp concurrency: group: ${{github.workflow}}-${{github.ref}} cancel-in-progress: true jobs: test: name: Test parser runs-on: ${{matrix.os}} strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-14] steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up tree-sitter uses: tree-sitter/setup-action/cli@v1 - name: Set up examples run: | git clone https://github.com/ruby/spec examples/ruby_spec --single-branch --depth=1 --filter=blob:none - name: Run tests uses: tree-sitter/parser-test-action@v2 with: test-rust: true test-node: true test-python: true test-go: true test-swift: true - name: Parse examples uses: tree-sitter/parse-action@v4 with: files: | examples/*.rb !examples/ruby_spec/command_line/fixtures/bad_syntax.rb !examples/ruby_spec/command_line/fixtures/freeze_flag_required_diff_enc.rb !examples/ruby_spec/core/enumerable/shared/inject.rb !examples/ruby_spec/language/fixtures/freeze_magic_comment_required_diff_enc.rb !examples/ruby_spec/language/string_spec.rb !examples/ruby_spec/core/proc/ruby2_keywords_spec.rb !examples/ruby_spec/language/fixtures/utf16-be-nobom.rb !examples/ruby_spec/language/fixtures/utf16-le-nobom.rb !examples/ruby_spec/language/lambda_spec.rb ================================================ FILE: .github/workflows/fuzz.yml ================================================ name: Fuzz Parser on: push: branches: [master] paths: - src/scanner.c pull_request: paths: - src/scanner.c jobs: fuzz: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Run fuzzer uses: tree-sitter/fuzz-action@v4 ================================================ FILE: .github/workflows/lint.yml ================================================ name: Lint on: push: branches: [master] paths: - grammar.js pull_request: paths: - grammar.js jobs: lint: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: cache: npm node-version: ${{vars.NODE_VERSION}} - name: Install modules run: npm ci --legacy-peer-deps - name: Run ESLint run: npm run lint ================================================ FILE: .github/workflows/publish.yml ================================================ name: Publish packages on: push: tags: ["*"] permissions: contents: write id-token: write attestations: write jobs: github: uses: tree-sitter/workflows/.github/workflows/release.yml@main with: generate: true attestations: true npm: uses: tree-sitter/workflows/.github/workflows/package-npm.yml@main secrets: NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} with: generate: true crates: uses: tree-sitter/workflows/.github/workflows/package-crates.yml@main secrets: CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_REGISTRY_TOKEN}} with: generate: true pypi: uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@main secrets: PYPI_API_TOKEN: ${{secrets.PYPI_API_TOKEN}} with: generate: true ================================================ FILE: .gitignore ================================================ # Rust artifacts target/ # Node artifacts build/ prebuilds/ node_modules/ # Swift artifacts .build/ # Go artifacts _obj/ # Python artifacts .venv/ dist/ *.egg-info *.whl # C artifacts *.a *.so *.so.* *.dylib *.dll *.pc # Example dirs /examples/*/ # Grammar volatiles *.wasm *.obj *.o # Archives *.tar.gz *.tgz *.zip ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.13) project(tree-sitter-ruby VERSION "0.23.1" DESCRIPTION "Ruby grammar for tree-sitter" HOMEPAGE_URL "https://github.com/tree-sitter/tree-sitter-ruby" LANGUAGES C) option(BUILD_SHARED_LIBS "Build using shared libraries" ON) option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF) set(TREE_SITTER_ABI_VERSION 14 CACHE STRING "Tree-sitter ABI version") if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$") unset(TREE_SITTER_ABI_VERSION CACHE) message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer") endif() find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI") add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json" COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json --abi=${TREE_SITTER_ABI_VERSION} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "Generating parser.c") add_library(tree-sitter-ruby src/parser.c) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c) target_sources(tree-sitter-ruby PRIVATE src/scanner.c) endif() target_include_directories(tree-sitter-ruby PRIVATE src) target_compile_definitions(tree-sitter-ruby PRIVATE $<$:TREE_SITTER_REUSE_ALLOCATOR> $<$:TREE_SITTER_DEBUG>) set_target_properties(tree-sitter-ruby PROPERTIES C_STANDARD 11 POSITION_INDEPENDENT_CODE ON SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}" DEFINE_SYMBOL "") configure_file(bindings/c/tree-sitter-ruby.pc.in "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-ruby.pc" @ONLY) include(GNUInstallDirs) install(FILES bindings/c/tree-sitter-ruby.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-ruby.pc" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig") install(TARGETS tree-sitter-ruby LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") add_custom_target(ts-test "${TREE_SITTER_CLI}" test WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "tree-sitter test") ================================================ FILE: Cargo.toml ================================================ [package] name = "tree-sitter-ruby" description = "Ruby grammar for tree-sitter" version = "0.23.1" authors = [ "Max Brunsfeld ", "Amaan Qureshi ", ] license = "MIT" readme = "README.md" keywords = ["incremental", "parsing", "tree-sitter", "ruby"] categories = ["parsing", "text-editors"] repository = "https://github.com/tree-sitter/tree-sitter-ruby" edition = "2021" autoexamples = false build = "bindings/rust/build.rs" include = ["LICENSE", "bindings/rust/*", "grammar.js", "queries/*", "src/*", "tree-sitter.json"] [lib] path = "bindings/rust/lib.rs" [dependencies] tree-sitter-language = "0.1" [build-dependencies] cc = "1.1" [dev-dependencies] tree-sitter = "0.24" ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2016 Rob Rix Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ ifeq ($(OS),Windows_NT) $(error Windows is not supported) endif LANGUAGE_NAME := tree-sitter-ruby HOMEPAGE_URL := https://github.com/tree-sitter/tree-sitter-ruby VERSION := 0.23.1 # repository SRC_DIR := src TS ?= tree-sitter # install directory layout PREFIX ?= /usr/local INCLUDEDIR ?= $(PREFIX)/include LIBDIR ?= $(PREFIX)/lib PCLIBDIR ?= $(LIBDIR)/pkgconfig # source/object files PARSER := $(SRC_DIR)/parser.c EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c)) OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS)) # flags ARFLAGS ?= rcs override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC # ABI versioning SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER)) SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION))) # OS-specific bits ifeq ($(shell uname),Darwin) SOEXT = dylib SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT) SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT) LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks else SOEXT = so SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR) SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR) LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER) endif ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),) PCLIBDIR := $(PREFIX)/libdata/pkgconfig endif all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a: $(OBJS) $(AR) $(ARFLAGS) $@ $^ lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS) $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@ ifneq ($(STRIP),) $(STRIP) $@ endif $(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \ -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \ -e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \ -e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \ -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \ -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@ $(PARSER): $(SRC_DIR)/grammar.json $(TS) generate $^ install: all install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)' install -m644 bindings/c/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) uninstall: $(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \ '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \ '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \ '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \ '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \ '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc clean: $(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) test: $(TS) test .PHONY: all install uninstall clean test ================================================ FILE: Package.resolved ================================================ { "object": { "pins": [ { "package": "SwiftTreeSitter", "repositoryURL": "https://github.com/ChimeHQ/SwiftTreeSitter", "state": { "branch": null, "revision": "2599e95310b3159641469d8a21baf2d3d200e61f", "version": "0.8.0" } } ] }, "version": 1 } ================================================ FILE: Package.swift ================================================ // swift-tools-version:5.3 import PackageDescription let package = Package( name: "TreeSitterRuby", products: [ .library(name: "TreeSitterRuby", targets: ["TreeSitterRuby"]), ], dependencies: [ .package(url: "https://github.com/ChimeHQ/SwiftTreeSitter", from: "0.8.0"), ], targets: [ .target( name: "TreeSitterRuby", dependencies: [], path: ".", sources: [ "src/parser.c", "src/scanner.c", ], resources: [ .copy("queries") ], publicHeadersPath: "bindings/swift", cSettings: [.headerSearchPath("src")] ), .testTarget( name: "TreeSitterRubyTests", dependencies: [ "SwiftTreeSitter", "TreeSitterRuby", ], path: "bindings/swift/TreeSitterRubyTests" ) ], cLanguageStandard: .c11 ) ================================================ FILE: README.md ================================================ # tree-sitter-ruby [![CI][ci]](https://github.com/tree-sitter/tree-sitter-ruby/actions/workflows/ci.yml) [![discord][discord]](https://discord.gg/w7nTvsVJhm) [![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org) [![crates][crates]](https://crates.io/crates/tree-sitter-ruby) [![npm][npm]](https://www.npmjs.com/package/tree-sitter-ruby) [![pypi][pypi]](https://pypi.org/project/tree-sitter-ruby) Ruby grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter). #### References - [AST Format of the Whitequark parser](https://github.com/whitequark/parser/blob/master/doc/AST_FORMAT.md) [ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter/tree-sitter-ruby/ci.yml?logo=github&label=CI [discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord [matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix [npm]: https://img.shields.io/npm/v/tree-sitter-ruby?logo=npm [crates]: https://img.shields.io/crates/v/tree-sitter-ruby?logo=rust [pypi]: https://img.shields.io/pypi/v/tree-sitter-ruby?logo=pypi&logoColor=ffd242 ================================================ FILE: binding.gyp ================================================ { "targets": [ { "target_name": "tree_sitter_ruby_binding", "dependencies": [ " typedef struct TSLanguage TSLanguage; extern "C" TSLanguage *tree_sitter_ruby(); // "tree-sitter", "language" hashed with BLAKE2 const napi_type_tag LANGUAGE_TYPE_TAG = { 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16 }; Napi::Object Init(Napi::Env env, Napi::Object exports) { exports["name"] = Napi::String::New(env, "ruby"); auto language = Napi::External::New(env, tree_sitter_ruby()); language.TypeTag(&LANGUAGE_TYPE_TAG); exports["language"] = language; return exports; } NODE_API_MODULE(tree_sitter_ruby_binding, Init) ================================================ FILE: bindings/node/binding_test.js ================================================ const assert = require("node:assert"); const { test } = require("node:test"); const Parser = require("tree-sitter"); test("can load grammar", () => { const parser = new Parser(); assert.doesNotThrow(() => parser.setLanguage(require("."))); }); ================================================ FILE: bindings/node/index.d.ts ================================================ type BaseNode = { type: string; named: boolean; }; type ChildNode = { multiple: boolean; required: boolean; types: BaseNode[]; }; type NodeInfo = | (BaseNode & { subtypes: BaseNode[]; }) | (BaseNode & { fields: { [name: string]: ChildNode }; children: ChildNode[]; }); type Language = { name: string; language: unknown; nodeTypeInfo: NodeInfo[]; }; declare const language: Language; export = language; ================================================ FILE: bindings/node/index.js ================================================ const root = require("path").join(__dirname, "..", ".."); module.exports = typeof process.versions.bun === "string" // Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time ? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-ruby.node`) : require("node-gyp-build")(root); try { module.exports.nodeTypeInfo = require("../../src/node-types.json"); } catch (_) {} ================================================ FILE: bindings/python/tests/test_binding.py ================================================ from unittest import TestCase import tree_sitter, tree_sitter_ruby class TestLanguage(TestCase): def test_can_load_grammar(self): try: tree_sitter.Language(tree_sitter_ruby.language()) except Exception: self.fail("Error loading Ruby grammar") ================================================ FILE: bindings/python/tree_sitter_ruby/__init__.py ================================================ """Ruby grammar for tree-sitter""" from importlib.resources import files as _files from ._binding import language def _get_query(name, file): query = _files(f"{__package__}.queries") / file globals()[name] = query.read_text() return globals()[name] def __getattr__(name): if name == "HIGHLIGHTS_QUERY": return _get_query("HIGHLIGHTS_QUERY", "highlights.scm") if name == "LOCALS_QUERY": return _get_query("LOCALS_QUERY", "locals.scm") if name == "TAGS_QUERY": return _get_query("TAGS_QUERY", "tags.scm") raise AttributeError(f"module {__name__!r} has no attribute {name!r}") __all__ = [ "language", "HIGHLIGHTS_QUERY", "LOCALS_QUERY", "TAGS_QUERY", ] def __dir__(): return sorted(__all__ + [ "__all__", "__builtins__", "__cached__", "__doc__", "__file__", "__loader__", "__name__", "__package__", "__path__", "__spec__", ]) ================================================ FILE: bindings/python/tree_sitter_ruby/__init__.pyi ================================================ from typing import Final HIGHLIGHTS_QUERY: Final[str] LOCALS_QUERY: Final[str] TAGS_QUERY: Final[str] def language() -> object: ... ================================================ FILE: bindings/python/tree_sitter_ruby/binding.c ================================================ #include typedef struct TSLanguage TSLanguage; TSLanguage *tree_sitter_ruby(void); static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { return PyCapsule_New(tree_sitter_ruby(), "tree_sitter.Language", NULL); } static PyMethodDef methods[] = { {"language", _binding_language, METH_NOARGS, "Get the tree-sitter language for this grammar."}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef module = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "_binding", .m_doc = NULL, .m_size = -1, .m_methods = methods }; PyMODINIT_FUNC PyInit__binding(void) { return PyModule_Create(&module); } ================================================ FILE: bindings/python/tree_sitter_ruby/py.typed ================================================ ================================================ FILE: bindings/rust/build.rs ================================================ fn main() { let src_dir = std::path::Path::new("src"); let mut c_config = cc::Build::new(); c_config .std("c11") .include(src_dir) .flag_if_supported("-Wno-unused-value"); #[cfg(target_env = "msvc")] c_config.flag("-utf-8"); if std::env::var("TARGET").unwrap() == "wasm32-unknown-unknown" { let Ok(wasm_headers) = std::env::var("DEP_TREE_SITTER_LANGUAGE_WASM_HEADERS") else { panic!("Environment variable DEP_TREE_SITTER_LANGUAGE_WASM_HEADERS must be set by the language crate"); }; let Ok(wasm_src) = std::env::var("DEP_TREE_SITTER_LANGUAGE_WASM_SRC").map(std::path::PathBuf::from) else { panic!("Environment variable DEP_TREE_SITTER_LANGUAGE_WASM_SRC must be set by the language crate"); }; c_config.include(&wasm_headers); c_config.files([ wasm_src.join("stdio.c"), wasm_src.join("stdlib.c"), wasm_src.join("string.c"), wasm_src.join("wctype.c"), ]); } let parser_path = src_dir.join("parser.c"); c_config.file(&parser_path); println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); let scanner_path = src_dir.join("scanner.c"); c_config.file(&scanner_path); println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); c_config.compile("tree-sitter-ruby"); } ================================================ FILE: bindings/rust/lib.rs ================================================ //! This crate provides Ruby language support for the [tree-sitter][] parsing library. //! //! Typically, you will use the [LANGUAGE][] constant to add this language to a //! tree-sitter [Parser][], and then use the parser to parse some code: //! //! ``` //! use tree_sitter::Parser; //! //! let code = r#" //! def hello(name) //! puts "Hello, #{name}!" //! end //! "#; //! let mut parser = Parser::new(); //! let language = tree_sitter_ruby::LANGUAGE; //! parser //! .set_language(&language.into()) //! .expect("Error loading Ruby parser"); //! let tree = parser.parse(code, None).unwrap(); //! assert!(!tree.root_node().has_error()); //! ``` //! //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html //! [tree-sitter]: https://tree-sitter.github.io/ use tree_sitter_language::LanguageFn; extern "C" { fn tree_sitter_ruby() -> *const (); } /// The tree-sitter [`LanguageFn`][LanguageFn] for this grammar. /// /// [LanguageFn]: https://docs.rs/tree-sitter-language/*/tree_sitter_language/struct.LanguageFn.html pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_ruby) }; /// The content of the [`node-types.json`][] file for this grammar. /// /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); /// The syntax highlighting query for this language. pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); /// The local-variable syntax highlighting query for this language. pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm"); /// The symbol tagging query for this language. pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm"); #[cfg(test)] mod tests { #[test] fn test_can_load_grammar() { let mut parser = tree_sitter::Parser::new(); parser .set_language(&super::LANGUAGE.into()) .expect("Error loading Ruby parser"); } } ================================================ FILE: bindings/swift/TreeSitterRuby/ruby.h ================================================ #ifndef TREE_SITTER_RUBY_H_ #define TREE_SITTER_RUBY_H_ typedef struct TSLanguage TSLanguage; #ifdef __cplusplus extern "C" { #endif const TSLanguage *tree_sitter_ruby(void); #ifdef __cplusplus } #endif #endif // TREE_SITTER_RUBY_H_ ================================================ FILE: bindings/swift/TreeSitterRubyTests/TreeSitterRubyTests.swift ================================================ import XCTest import SwiftTreeSitter import TreeSitterRuby final class TreeSitterRubyTests: XCTestCase { func testCanLoadGrammar() throws { let parser = Parser() let language = Language(language: tree_sitter_ruby()) XCTAssertNoThrow(try parser.setLanguage(language), "Error loading Ruby grammar") } } ================================================ FILE: eslint.config.mjs ================================================ import treesitter from 'eslint-config-treesitter'; export default [ ...treesitter, ]; ================================================ FILE: go.mod ================================================ module github.com/tree-sitter/tree-sitter-ruby go 1.22 require github.com/tree-sitter/go-tree-sitter v0.24.0 require github.com/mattn/go-pointer v0.0.1 // indirect ================================================ FILE: go.sum ================================================ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tree-sitter/go-tree-sitter v0.24.0 h1:kRZb6aBNfcI/u0Qh8XEt3zjNVnmxTisDBN+kXK0xRYQ= github.com/tree-sitter/go-tree-sitter v0.24.0/go.mod h1:x681iFVoLMEwOSIHA1chaLkXlroXEN7WY+VHGFaoDbk= github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb h1:A8425heRM8mylnv4H58FPUiH+aYivyitre0PzxrfmWs= github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb/go.mod h1:dOF6gtQiF9UwNh995T5OphYmtIypkjsp3ap7r9AN/iA= github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148 h1:AfFPZwtwGN01BW1jDdqBVqscTwetvMpydqYZz57RSlc= github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148/go.mod h1:Bh6U3viD57rFXRYIQ+kmiYtr+1Bx0AceypDLJJSyi9s= github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33 h1:TwqSV3qLp3tKSqirGLRHnjFk9Tc2oy57LIl+FQ4GjI4= github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33/go.mod h1:CvCKCt3v04Ufos1zZnNCelBDeCGRpPucaN8QczoUsN4= github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012 h1:Xvxck3tE5FW7F7bTS97iNM2ADMyCMJztVqn5HYKdJGo= github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012/go.mod h1:T40D0O1cPvUU/+AmiXVXy1cncYQT6wem4Z0g4SfAYvY= github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo= github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU= github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA= github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc= github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg= github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU= github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4= github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk= github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g= github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs= github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw= github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g= github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc= github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= ================================================ FILE: grammar.js ================================================ /// // @ts-check const PREC = { COMMENT: -2, CURLY_BLOCK: 1, DO_BLOCK: -1, AND: -2, OR: -2, NOT: 5, DEFINED: 10, ALIAS: 11, ASSIGN: 15, RESCUE: 16, CONDITIONAL: 20, RANGE: 25, BOOLEAN_OR: 30, BOOLEAN_AND: 35, RELATIONAL: 40, COMPARISON: 45, BITWISE_OR: 50, BITWISE_AND: 55, CALL: 56, SHIFT: 60, ADDITIVE: 65, MULTIPLICATIVE: 70, UNARY_MINUS: 75, EXPONENTIAL: 80, COMPLEMENT: 85, }; const IDENTIFIER_CHARS = /[^\x00-\x1F\s:;`"'@$#.,|^&<=>+\-*/\\%?!~()\[\]{}]*/; const LOWER_ALPHA_CHAR = /[^\x00-\x1F\sA-Z0-9:;`"'@$#.,|^&<=>+\-*/\\%?!~()\[\]{}]/; const ALPHA_CHAR = /[^\x00-\x1F\s0-9:;`"'@$#.,|^&<=>+\-*/\\%?!~()\[\]{}]/; module.exports = grammar({ name: 'ruby', inline: $ => [$._arg_rhs, $._call_operator], externals: $ => [ $._line_break, $._no_line_break, // Delimited literals $.simple_symbol, $._string_start, $._symbol_start, $._subshell_start, $._regex_start, $._string_array_start, $._symbol_array_start, $._heredoc_body_start, $.string_content, $.heredoc_content, $._string_end, $.heredoc_end, $.heredoc_beginning, // Tokens that require lookahead '/', $._block_ampersand, $._splat_star, $._unary_minus, $._unary_minus_num, $._binary_minus, $._binary_star, $._singleton_class_left_angle_left_langle, $.hash_key_symbol, $._identifier_suffix, $._constant_suffix, $._hash_splat_star_star, $._binary_star_star, $._element_reference_bracket, $._short_interpolation, ], extras: $ => [ $.comment, $.heredoc_body, /\s/, /\\\r?\n/, ], word: $ => $.identifier, supertypes: $ => [ $._statement, $._arg, $._call_operator, $._method_name, $._expression, $._variable, $._primary, $._simple_numeric, $._lhs, $._nonlocal_variable, $._pattern_top_expr_body, $._pattern_expr, $._pattern_expr_basic, $._pattern_primitive, $._pattern_constant, ], rules: { program: $ => seq( optional($._statements), optional( choice( seq(/__END__/, $.uninterpreted), ), ), ), uninterpreted: _ => /(.|\s)*/, block_body: $ => $._statements, _statements: $ => choice( seq( repeat1(choice( seq($._statement, $._terminator), $.empty_statement, )), optional($._statement), ), $._statement, ), begin_block: $ => seq('BEGIN', '{', optional($._statements), '}'), end_block: $ => seq('END', '{', optional($._statements), '}'), _statement: $ => choice( $.undef, $.alias, $.if_modifier, $.unless_modifier, $.while_modifier, $.until_modifier, $.rescue_modifier, $.begin_block, $.end_block, $._expression, ), method: $ => seq('def', $._method_rest), singleton_method: $ => seq( 'def', seq( choice( field('object', $._variable), seq('(', field('object', $._arg), ')'), ), choice('.', '::'), ), $._method_rest, ), _method_rest: $ => seq( field('name', $._method_name), choice( $._body_expr, seq( field('parameters', alias($.parameters, $.method_parameters)), choice( seq(optional($._terminator), optional(field('body', $.body_statement)), 'end'), $._body_expr, ), ), seq( optional( field('parameters', alias($.bare_parameters, $.method_parameters)), ), $._terminator, optional(field('body', $.body_statement)), 'end', ), ), ), rescue_modifier_arg: $ => prec(PREC.RESCUE, seq( field('body', $._arg), 'rescue', field('handler', $._arg), ), ), rescue_modifier_expression: $ => prec(PREC.RESCUE, seq( field('body', $._expression), 'rescue', field('handler', $._arg), ), ), _body_expr: $ => seq( '=', field('body', choice( $._arg, alias($.rescue_modifier_arg, $.rescue_modifier), )), ), parameters: $ => seq( '(', commaSep($._formal_parameter), ')', ), bare_parameters: $ => seq( $._simple_formal_parameter, repeat(seq(',', $._formal_parameter)), ), block_parameters: $ => seq( '|', seq(commaSep($._formal_parameter), optional(',')), optional(seq(';', sep1(field('locals', $.identifier), ','))), // Block shadow args e.g. {|; a, b| ...} '|', ), _formal_parameter: $ => choice( $._simple_formal_parameter, alias($.parameters, $.destructured_parameter), ), _simple_formal_parameter: $ => choice( $.identifier, $.splat_parameter, $.hash_splat_parameter, $.hash_splat_nil, $.forward_parameter, $.block_parameter, $.keyword_parameter, $.optional_parameter, ), forward_parameter: _ => '...', splat_parameter: $ => prec.right(-2, seq( '*', field('name', optional($.identifier)), )), hash_splat_parameter: $ => seq( '**', field('name', optional($.identifier)), ), hash_splat_nil: _ => seq('**', 'nil'), block_parameter: $ => seq( '&', field('name', optional($.identifier)), ), keyword_parameter: $ => prec.right(PREC.BITWISE_OR + 1, seq( field('name', $.identifier), token.immediate(':'), field('value', optional($._arg)), )), optional_parameter: $ => prec(PREC.BITWISE_OR + 1, seq( field('name', $.identifier), '=', field('value', $._arg), )), class: $ => seq( 'class', field('name', choice($.constant, $.scope_resolution)), choice( seq(field('superclass', $.superclass), $._terminator), optional($._terminator), ), optional(field('body', $.body_statement)), 'end', ), superclass: $ => seq('<', $._expression), singleton_class: $ => seq( 'class', alias($._singleton_class_left_angle_left_langle, '<<'), field('value', $._arg), $._terminator, optional(field('body', $.body_statement)), 'end', ), module: $ => seq( 'module', field('name', choice($.constant, $.scope_resolution)), optional($._terminator), optional(field('body', $.body_statement)), 'end', ), return_command: $ => prec.left(seq('return', alias($.command_argument_list, $.argument_list))), yield_command: $ => prec.left(seq('yield', alias($.command_argument_list, $.argument_list))), break_command: $ => prec.left(seq('break', alias($.command_argument_list, $.argument_list))), next_command: $ => prec.left(seq('next', alias($.command_argument_list, $.argument_list))), return: $ => prec.left(seq('return', optional($.argument_list))), yield: $ => prec.left(seq('yield', optional($.argument_list))), break: $ => prec.left(seq('break', optional($.argument_list))), next: $ => prec.left(seq('next', optional($.argument_list))), redo: $ => prec.left(seq('redo', optional($.argument_list))), retry: $ => prec.left(seq('retry', optional($.argument_list))), if_modifier: $ => prec(PREC.RESCUE, seq( field('body', $._statement), 'if', field('condition', $._expression), )), unless_modifier: $ => prec(PREC.RESCUE, seq( field('body', $._statement), 'unless', field('condition', $._expression), )), while_modifier: $ => prec(PREC.RESCUE, seq( field('body', $._statement), 'while', field('condition', $._expression), )), until_modifier: $ => prec(PREC.RESCUE, seq( field('body', $._statement), 'until', field('condition', $._expression), )), rescue_modifier: $ => prec(PREC.RESCUE, seq( field('body', $._statement), 'rescue', field('handler', $._expression), )), while: $ => seq( 'while', field('condition', $._statement), field('body', $.do), ), until: $ => seq( 'until', field('condition', $._statement), field('body', $.do), ), for: $ => seq( 'for', field('pattern', choice($._lhs, $.left_assignment_list)), field('value', $.in), field('body', $.do), ), in: $ => seq('in', $._arg), do: $ => seq( choice('do', $._terminator), optional($._statements), 'end', ), case: $ => seq( 'case', optional(seq(optional($._line_break), field('value', $._statement))), optional($._terminator), repeat($.when), optional($.else), 'end', ), case_match: $ => seq( 'case', seq(optional($._line_break), field('value', $._statement)), optional($._terminator), repeat1(field('clauses', $.in_clause)), optional(field('else', $.else)), 'end', ), when: $ => seq( 'when', commaSep1(field('pattern', $.pattern)), choice($._terminator, field('body', $.then)), ), in_clause: $ => seq( 'in', field('pattern', $._pattern_top_expr_body), field('guard', optional($._guard)), choice($._terminator, field('body', $.then)), ), pattern: $ => choice($._arg, $.splat_argument), _guard: $ => choice( $.if_guard, $.unless_guard, ), if_guard: $ => seq( 'if', field('condition', $._expression), ), unless_guard: $ => seq( 'unless', field('condition', $._expression), ), _pattern_top_expr_body: $ => prec(-1, choice( $._pattern_expr, alias($._array_pattern_n, $.array_pattern), alias($._find_pattern_body, $.find_pattern), alias($._hash_pattern_body, $.hash_pattern), )), _array_pattern_n: $ => prec.right(choice( seq($._pattern_expr, alias(',', $.splat_parameter)), seq($._pattern_expr, ',', choice($._pattern_expr, $._array_pattern_n)), seq($.splat_parameter, repeat(seq(',', $._pattern_expr))), )), _pattern_expr: $ => choice( $.as_pattern, $._pattern_expr_alt, ), as_pattern: $ => seq(field('value', $._pattern_expr), '=>', field('name', $.identifier)), _pattern_expr_alt: $ => choice( $.alternative_pattern, $._pattern_expr_basic, ), alternative_pattern: $ => seq(field('alternatives', $._pattern_expr_basic), repeat1(seq('|', field('alternatives', $._pattern_expr_basic)))), _array_pattern_body: $ => choice( $._pattern_expr, $._array_pattern_n, ), array_pattern: $ => prec.right(-1, choice( seq('[', optional($._array_pattern_body), ']'), seq(field('class', $._pattern_constant), token.immediate('['), optional($._array_pattern_body), ']'), seq(field('class', $._pattern_constant), token.immediate('('), optional($._array_pattern_body), ')'), )), _find_pattern_body: $ => seq($.splat_parameter, repeat1(seq(',', $._pattern_expr)), ',', $.splat_parameter), find_pattern: $ => choice( seq('[', $._find_pattern_body, ']'), seq(field('class', $._pattern_constant), token.immediate('['), $._find_pattern_body, ']'), seq(field('class', $._pattern_constant), token.immediate('('), $._find_pattern_body, ')'), ), _hash_pattern_body: $ => prec.right(choice( seq(commaSep1($.keyword_pattern), optional(',')), seq(commaSep1($.keyword_pattern), ',', $._hash_pattern_any_rest), $._hash_pattern_any_rest, )), keyword_pattern: $ => prec.right(-1, seq( field('key', choice( alias($.identifier, $.hash_key_symbol), alias($.constant, $.hash_key_symbol), alias($.identifier_suffix, $.hash_key_symbol), alias($.constant_suffix, $.hash_key_symbol), $.string, ), ), token.immediate(':'), optional(field('value', $._pattern_expr)), )), _hash_pattern_any_rest: $ => choice($.hash_splat_parameter, $.hash_splat_nil), hash_pattern: $ => prec.right(-1, choice( seq('{', optional($._hash_pattern_body), '}'), seq(field('class', $._pattern_constant), token.immediate('['), $._hash_pattern_body, ']'), seq(field('class', $._pattern_constant), token.immediate('('), $._hash_pattern_body, ')'), )), _pattern_expr_basic: $ => prec.right(-1, choice( $._pattern_value, $.identifier, $.array_pattern, $.find_pattern, $.hash_pattern, $.parenthesized_pattern, )), parenthesized_pattern: $ => seq('(', $._pattern_expr, ')'), _pattern_value: $ => prec.right(-1, choice( $._pattern_primitive, alias($._pattern_range, $.range), $.variable_reference_pattern, $.expression_reference_pattern, $._pattern_constant, )), _pattern_range: $ => { const begin = field('begin', $._pattern_primitive); const end = field('end', $._pattern_primitive); const operator = field('operator', choice('..', '...')); return choice( seq(begin, operator, end), seq(operator, end), seq(begin, operator), ); }, _pattern_primitive: $ => choice( $._pattern_literal, $._pattern_lambda, ), _pattern_lambda: $ => prec.right(-1, $.lambda), _pattern_literal: $ => prec.right(-1, choice( $._literal, $.string, $.subshell, $.heredoc_beginning, $.regex, $.string_array, $.symbol_array, $._keyword_variable, )), _keyword_variable: $ => prec.right(-1, choice( $.nil, $.self, $.true, $.false, $.line, $.file, $.encoding, )), line: _ => '__LINE__', file: _ => '__FILE__', encoding: _ => '__ENCODING__', variable_reference_pattern: $ => seq('^', field('name', choice($.identifier, $._nonlocal_variable))), expression_reference_pattern: $ => seq('^', '(', field('value', $._expression), ')'), _pattern_constant: $ => prec.right(-1, choice( $.constant, alias($._pattern_constant_resolution, $.scope_resolution), )), _pattern_constant_resolution: $ => seq( optional(field('scope', $._pattern_constant)), '::', field('name', $.constant), ), if: $ => seq( 'if', field('condition', $._statement), choice($._terminator, field('consequence', $.then)), field('alternative', optional(choice($.else, $.elsif))), 'end', ), unless: $ => seq( 'unless', field('condition', $._statement), choice($._terminator, field('consequence', $.then)), field('alternative', optional(choice($.else, $.elsif))), 'end', ), elsif: $ => seq( 'elsif', field('condition', $._statement), choice($._terminator, field('consequence', $.then)), field('alternative', optional(choice($.else, $.elsif))), ), else: $ => seq( 'else', optional($._terminator), optional($._statements), ), then: $ => choice( seq( $._terminator, $._statements, ), seq( optional($._terminator), 'then', optional($._statements), ), ), begin: $ => seq('begin', optional($._terminator), optional($._body_statement), 'end'), ensure: $ => seq('ensure', optional($._statements)), rescue: $ => seq( 'rescue', field('exceptions', optional($.exceptions)), field('variable', optional($.exception_variable)), choice( $._terminator, field('body', $.then), ), ), exceptions: $ => commaSep1(choice($._arg, $.splat_argument)), exception_variable: $ => seq('=>', $._lhs), body_statement: $ => $._body_statement, _body_statement: $ => choice( seq($._statements, repeat(choice($.rescue, $.else, $.ensure))), seq(optional($._statements), repeat1(choice($.rescue, $.else, $.ensure))), ), // Method calls without parentheses (aka "command calls") are only allowed // in certain positions, like the top-level of a statement, the condition // of a postfix control-flow operator like `if`, or as the value of a // control-flow statement like `return`. In many other places, they're not // allowed. // // Because of this distinction, a lot of rules have two variants: the // normal variant, which can appear anywhere that an expression is valid, // and the "command" varaint, which is only valid in a more limited set of // positions, because it can contain "command calls". // // The `_expression` rule can appear in relatively few places, but can // contain command calls. The `_arg` rule can appear in many more places, // but cannot contain command calls (unless they are wrapped in parens). // This naming convention is based on Ruby's standard grammar. _expression: $ => choice( alias($.command_binary, $.binary), alias($.command_unary, $.unary), alias($.command_assignment, $.assignment), alias($.command_operator_assignment, $.operator_assignment), alias($.command_call, $.call), alias($.command_call_with_block, $.call), prec.left(alias($._chained_command_call, $.call)), alias($.return_command, $.return), alias($.yield_command, $.yield), alias($.break_command, $.break), alias($.next_command, $.next), $.match_pattern, $.test_pattern, $._arg, ), match_pattern: $ => prec(100, seq(field('value', $._arg), '=>', field('pattern', $._pattern_top_expr_body))), test_pattern: $ => prec(100, seq(field('value', $._arg), 'in', field('pattern', $._pattern_top_expr_body))), _arg: $ => choice( alias($._unary_minus_pow, $.unary), $._primary, $.assignment, $.operator_assignment, $.conditional, $.range, $.binary, $.unary, ), _unary_minus_pow: $ => seq(field('operator', alias($._unary_minus_num, '-')), field('operand', alias($._pow, $.binary))), _pow: $ => prec.right(PREC.EXPONENTIAL, seq(field('left', $._simple_numeric), field('operator', alias($._binary_star_star, '**')), field('right', $._arg))), _primary: $ => choice( $.parenthesized_statements, $._lhs, alias($._function_identifier_call, $.call), $.call, $.array, $.string_array, $.symbol_array, $.hash, $.subshell, $._literal, $.string, $.character, $.chained_string, $.regex, $.lambda, $.method, $.singleton_method, $.class, $.singleton_class, $.module, $.begin, $.while, $.until, $.if, $.unless, $.for, $.case, $.case_match, $.return, $.yield, $.break, $.next, $.redo, $.retry, alias($.parenthesized_unary, $.unary), $.heredoc_beginning, ), parenthesized_statements: $ => seq('(', optional($._statements), ')'), element_reference: $ => prec.left(1, seq( field('object', $._primary), alias($._element_reference_bracket, '['), optional($._argument_list_with_trailing_comma), ']', optional(field('block', choice($.block, $.do_block))), )), scope_resolution: $ => prec.left(PREC.CALL + 1, seq( choice( '::', seq(field('scope', $._primary), token.immediate('::')), ), field('name', $.constant), )), _call_operator: _ => choice('.', '&.', token.immediate('::')), _call: $ => prec.left(PREC.CALL, seq( field('receiver', $._primary), field('operator', $._call_operator), field('method', choice($.identifier, $.operator, $.constant, $._function_identifier)), )), command_call: $ => seq( choice( $._call, $._chained_command_call, field('method', choice( $._variable, $._function_identifier, )), ), field('arguments', alias($.command_argument_list, $.argument_list)), ), command_call_with_block: $ => { const receiver = choice( $._call, field('method', choice($._variable, $._function_identifier)), ); const args = field('arguments', alias($.command_argument_list, $.argument_list)); const block = field('block', $.block); const doBlock = field('block', $.do_block); return choice( seq(receiver, prec(PREC.CURLY_BLOCK, seq(args, block))), seq(receiver, prec(PREC.DO_BLOCK, seq(args, doBlock))), ); }, _chained_command_call: $ => seq( field('receiver', alias($.command_call_with_block, $.call)), field('operator', $._call_operator), field('method', choice($.identifier, $._function_identifier, $.operator, $.constant)), ), call: $ => { const receiver = choice( $._call, field('method', choice( $._variable, $._function_identifier, )), ); const args = field('arguments', $.argument_list); const receiverArguments = seq( choice( receiver, prec.left(PREC.CALL, seq( field('receiver', $._primary), field('operator', $._call_operator), )), ), args, ); const block = field('block', $.block); const doBlock = field('block', $.do_block); return choice( receiverArguments, prec(PREC.CURLY_BLOCK, seq(receiverArguments, block)), prec(PREC.DO_BLOCK, seq(receiverArguments, doBlock)), prec(PREC.CURLY_BLOCK, seq(receiver, block)), prec(PREC.DO_BLOCK, seq(receiver, doBlock)), ); }, command_argument_list: $ => prec.right(commaSep1($._argument)), argument_list: $ => prec.right(seq( token.immediate('('), optional($._argument_list_with_trailing_comma), ')', )), _argument_list_with_trailing_comma: $ => prec.right(seq( commaSep1($._argument), optional(','), )), _argument: $ => prec.left(choice( $._expression, $.splat_argument, $.hash_splat_argument, $.forward_argument, $.block_argument, $.pair, )), forward_argument: _ => '...', splat_argument: $ => prec.right(seq(alias($._splat_star, '*'), optional($._arg))), hash_splat_argument: $ => prec.right(seq(alias($._hash_splat_star_star, '**'), optional($._arg))), block_argument: $ => prec.right(seq(alias($._block_ampersand, '&'), optional($._arg))), do_block: $ => seq( 'do', optional($._terminator), optional(seq( field('parameters', $.block_parameters), optional($._terminator), )), optional(field('body', $.body_statement)), 'end', ), block: $ => prec(PREC.CURLY_BLOCK, seq( '{', field('parameters', optional($.block_parameters)), optional(field('body', $.block_body)), '}', )), _arg_rhs: $ => choice($._arg, alias($.rescue_modifier_arg, $.rescue_modifier)), assignment: $ => prec.right(PREC.ASSIGN, choice( seq( field('left', choice($._lhs, $.left_assignment_list)), '=', field('right', choice( $._arg_rhs, $.splat_argument, $.right_assignment_list, )), ), )), command_assignment: $ => prec.right(PREC.ASSIGN, seq( field('left', choice($._lhs, $.left_assignment_list)), '=', field('right', choice($._expression, alias($.rescue_modifier_expression, $.rescue_modifier))), ), ), operator_assignment: $ => prec.right(PREC.ASSIGN, seq( field('left', $._lhs), field('operator', choice('+=', '-=', '*=', '**=', '/=', '||=', '|=', '&&=', '&=', '%=', '>>=', '<<=', '^=')), field('right', $._arg_rhs), )), command_operator_assignment: $ => prec.right(PREC.ASSIGN, seq( field('left', $._lhs), field('operator', choice('+=', '-=', '*=', '**=', '/=', '||=', '|=', '&&=', '&=', '%=', '>>=', '<<=', '^=')), field('right', choice($._expression, alias($.rescue_modifier_expression, $.rescue_modifier))), )), conditional: $ => prec.right(PREC.CONDITIONAL, seq( field('condition', $._arg), '?', field('consequence', $._arg), ':', field('alternative', $._arg), )), range: $ => { const begin = field('begin', $._arg); const end = field('end', $._arg); const operator = field('operator', choice('..', '...')); return prec.right(PREC.RANGE, choice( seq(begin, operator, end), seq(operator, end), seq(begin, operator), )); }, binary: $ => { const operators = [ [prec.left, PREC.AND, 'and'], [prec.left, PREC.OR, 'or'], [prec.left, PREC.BOOLEAN_OR, '||'], [prec.left, PREC.BOOLEAN_AND, '&&'], [prec.left, PREC.SHIFT, choice('<<', '>>')], [prec.left, PREC.COMPARISON, choice('<', '<=', '>', '>=')], [prec.left, PREC.BITWISE_AND, '&'], [prec.left, PREC.BITWISE_OR, choice('^', '|')], [prec.left, PREC.ADDITIVE, choice('+', alias($._binary_minus, '-'))], [prec.left, PREC.MULTIPLICATIVE, choice('/', '%', alias($._binary_star, '*'))], [prec.right, PREC.RELATIONAL, choice('==', '!=', '===', '<=>', '=~', '!~')], [prec.right, PREC.EXPONENTIAL, alias($._binary_star_star, '**')], ]; // @ts-ignore return choice(...operators.map(([fn, precedence, operator]) => fn(precedence, seq( field('left', $._arg), // @ts-ignore field('operator', operator), field('right', $._arg), )))); }, command_binary: $ => prec.left(seq( field('left', $._expression), field('operator', choice('or', 'and')), field('right', $._expression), )), unary: $ => { const operators = [ [prec, PREC.DEFINED, 'defined?'], [prec.right, PREC.NOT, 'not'], [prec.right, PREC.UNARY_MINUS, choice(alias($._unary_minus, '-'), alias($._binary_minus, '-'), '+')], [prec.right, PREC.COMPLEMENT, choice('!', '~')], ]; // @ts-ignore return choice(...operators.map(([fn, precedence, operator]) => fn(precedence, seq( // @ts-ignore field('operator', operator), field('operand', $._arg), )))); }, command_unary: $ => { const operators = [ [prec, PREC.DEFINED, 'defined?'], [prec.right, PREC.NOT, 'not'], [prec.right, PREC.UNARY_MINUS, choice(alias($._unary_minus, '-'), '+')], [prec.right, PREC.COMPLEMENT, choice('!', '~')], ]; // @ts-ignore return choice(...operators.map(([fn, precedence, operator]) => fn(precedence, seq( // @ts-ignore field('operator', operator), field('operand', $._expression), )))); }, parenthesized_unary: $ => prec(PREC.CALL, seq( field('operator', choice('defined?', 'not')), field('operand', $.parenthesized_statements), )), unary_literal: $ => prec.right(PREC.UNARY_MINUS, seq( field('operator', choice(alias($._unary_minus_num, '-'), '+')), field('operand', $._simple_numeric), )), _literal: $ => choice( $.simple_symbol, $.delimited_symbol, $._numeric, ), _numeric: $ => choice( $._simple_numeric, alias($.unary_literal, $.unary), ), _simple_numeric: $ => choice( $.integer, $.float, $.complex, $.rational, ), right_assignment_list: $ => prec(-1, commaSep1(choice($._arg, $.splat_argument))), left_assignment_list: $ => $._mlhs, _mlhs: $ => prec.left(-1, seq( commaSep1(choice($._lhs, $.rest_assignment, $.destructured_left_assignment)), optional(','), )), destructured_left_assignment: $ => prec(-1, seq('(', $._mlhs, ')')), rest_assignment: $ => prec(-1, seq('*', optional($._lhs))), _function_identifier: $ => choice(alias($.identifier_suffix, $.identifier), alias($.constant_suffix, $.constant)), _function_identifier_call: $ => prec.left(field('method', $._function_identifier)), _lhs: $ => prec.left(choice( $._variable, $.true, $.false, $.nil, $.scope_resolution, $.element_reference, alias($._call, $.call), )), _variable: $ => prec.right(choice( $.self, $.super, $._nonlocal_variable, $.identifier, $.constant, )), operator: _ => choice( '..', '|', '^', '&', '<=>', '==', '===', '=~', '>', '>=', '<', '<=', '+', '!=', '-', '*', '/', '%', '!', '!~', '**', '<<', '>>', '~', '+@', '-@', '~@', '[]', '[]=', '`', ), _method_name: $ => choice( $.identifier, $._function_identifier, $.constant, $.setter, $.simple_symbol, $.delimited_symbol, $.operator, $._nonlocal_variable, ), _nonlocal_variable: $ => choice( $.instance_variable, $.class_variable, $.global_variable, ), setter: $ => seq(field('name', $.identifier), token.immediate('=')), undef: $ => seq('undef', commaSep1($._method_name)), alias: $ => seq( 'alias', field('name', $._method_name), field('alias', $._method_name), ), comment: _ => token(prec(PREC.COMMENT, choice( seq('#', /.*/), seq( /=begin.*\r?\n/, repeat(choice( /[^=]/, /=[^e]/, /=e[^n]/, /=en[^d]/, )), /[\s*]*=end.*/, ), ))), integer: _ => /0[bB][01](_?[01])*|0[oO]?[0-7](_?[0-7])*|(0[dD])?\d(_?\d)*|0[xX][0-9a-fA-F](_?[0-9a-fA-F])*/, _int_or_float: $ => choice($.integer, $.float), float: _ => /\d(_?\d)*(\.\d)?(_?\d)*([eE][\+-]?\d(_?\d)*)?/, complex: $ => choice( seq($._int_or_float, token.immediate('i')), seq(alias($._int_or_float, $.rational), token.immediate('ri')), ), rational: $ => seq($._int_or_float, token.immediate('r')), super: _ => 'super', self: _ => 'self', true: _ => 'true', false: _ => 'false', nil: _ => 'nil', constant: _ => token(seq(/[A-Z]/, IDENTIFIER_CHARS)), constant_suffix: $ => choice(token(seq(/[A-Z]/, IDENTIFIER_CHARS, /[?]/)), $._constant_suffix), identifier: _ => token(seq(LOWER_ALPHA_CHAR, IDENTIFIER_CHARS)), identifier_suffix: $ => choice(token(seq(LOWER_ALPHA_CHAR, IDENTIFIER_CHARS, /[?]/)), $._identifier_suffix), instance_variable: _ => token(seq('@', ALPHA_CHAR, IDENTIFIER_CHARS)), class_variable: _ => token(seq('@@', ALPHA_CHAR, IDENTIFIER_CHARS)), global_variable: _ => /\$(-[a-zA-Z0-9_]|[!@&`'+~=/\\,;.<>*$?:"]|[0-9]+|[a-zA-Z_][a-zA-Z0-9_]*)/, chained_string: $ => seq($.string, repeat1($.string)), character: _ => /\?(\\\S(\{[0-9A-Fa-f]*\}|[0-9A-Fa-f]*|-\S([MC]-\S)?)?|\S)/, interpolation: $ => choice( seq('#{', optional($._statements), '}'), seq($._short_interpolation, $._nonlocal_variable), ), string: $ => seq( alias($._string_start, '"'), optional($._literal_contents), alias($._string_end, '"'), ), subshell: $ => seq( alias($._subshell_start, '`'), optional($._literal_contents), alias($._string_end, '`'), ), string_array: $ => seq( alias($._string_array_start, '%w('), optional(/\s+/), sep(alias($._literal_contents, $.bare_string), /\s+/), optional(/\s+/), alias($._string_end, ')'), ), symbol_array: $ => seq( alias($._symbol_array_start, '%i('), optional(/\s+/), sep(alias($._literal_contents, $.bare_symbol), /\s+/), optional(/\s+/), alias($._string_end, ')'), ), delimited_symbol: $ => seq( alias($._symbol_start, ':"'), optional($._literal_contents), alias($._string_end, '"'), ), regex: $ => seq( alias($._regex_start, '/'), optional($._literal_contents), alias($._string_end, '/'), ), heredoc_body: $ => seq( $._heredoc_body_start, repeat(choice( $.heredoc_content, $.interpolation, $.escape_sequence, )), $.heredoc_end, ), _literal_contents: $ => repeat1(choice( $.string_content, $.interpolation, $.escape_sequence, )), // https://ruby-doc.org/core-2.5.0/doc/syntax/literals_rdoc.html#label-Strings escape_sequence: _ => token(seq( '\\', choice( /[^ux0-7]/, // single character /x[0-9a-fA-F]{1,2}/, // hex code /[0-7]{1,3}/, // octal /u[0-9a-fA-F]{4}/, // single unicode /u\{[0-9a-fA-F ]+\}/, // multiple unicode ), )), array: $ => seq( '[', optional($._argument_list_with_trailing_comma), ']', ), hash: $ => seq( '{', optional(seq( commaSep1(choice($.pair, $.hash_splat_argument)), optional(','), )), '}', ), pair: $ => prec.right(choice( seq( field('key', $._arg), '=>', field('value', $._arg), ), seq( field('key', choice( $.string, )), token.immediate(':'), field('value', $._arg), ), seq( field('key', choice( $.hash_key_symbol, alias($.identifier, $.hash_key_symbol), alias($.constant, $.hash_key_symbol), alias($.identifier_suffix, $.hash_key_symbol), alias($.constant_suffix, $.hash_key_symbol), )), token.immediate(':'), choice( field('value', optional($._arg)), // This alternative never matches, because '_no_line_break' tokens do not exist. // The purpose is give a hint to the scanner that it should not produce any line-break // terminators at this point. $._no_line_break), ), )), lambda: $ => seq( '->', field('parameters', optional(choice( alias($.parameters, $.lambda_parameters), alias($.bare_parameters, $.lambda_parameters), ))), field('body', choice($.block, $.do_block)), ), empty_statement: _ => prec(-1, ';'), _terminator: $ => choice( $._line_break, ';', ), }, }); /** * Creates a rule to optionally match one or more of the rules separated by `separator` * * @param {RuleOrLiteral} rule * * @param {RuleOrLiteral} separator * * @returns {ChoiceRule} */ function sep(rule, separator) { return optional(sep1(rule, separator)); } /** * Creates a rule to match one or more of the rules separated by `separator` * * @param {RuleOrLiteral} rule * * @param {RuleOrLiteral} separator * * @returns {SeqRule} */ function sep1(rule, separator) { return seq(rule, repeat(seq(separator, rule))); } /** * Creates a rule to match one or more of the rules separated by a comma * * @param {RuleOrLiteral} rule * * @returns {SeqRule} */ function commaSep1(rule) { return sep1(rule, ','); } /** * Creates a rule to optionally match one or more of the rules separated by a comma * * @param {RuleOrLiteral} rule * * @returns {ChoiceRule} */ function commaSep(rule) { return optional(commaSep1(rule)); } ================================================ FILE: package.json ================================================ { "name": "tree-sitter-ruby", "version": "0.23.1", "description": "Ruby grammar for tree-sitter", "repository": "https://github.com/tree-sitter/tree-sitter-ruby", "license": "MIT", "author": { "name": "Rob Rix", "email": "rob.rix@gmail.com" }, "contributors": [ { "name": "Timothy Clem", "email": "timothy.clem@gmail.com" }, { "name": "Max Brunsfeld", "email": "maxbrunsfeld@gmail.com" }, { "name": "Arthur Baars", "email": "aibaars@github.com" }, { "name": "Amaan Qureshi", "email": "amaanq12@gmail.com" } ], "maintainers": [ { "name": "Amaan Qureshi", "email": "amaanq12@gmail.com" } ], "main": "bindings/node", "types": "bindings/node", "keywords": [ "incremental", "parsing", "tree-sitter", "ruby" ], "files": [ "grammar.js", "tree-sitter.json", "binding.gyp", "prebuilds/**", "bindings/node/*", "queries/*", "src/**", "*.wasm" ], "dependencies": { "node-addon-api": "^8.2.2", "node-gyp-build": "^4.8.2" }, "devDependencies": { "eslint": ">=9.14.0", "eslint-config-treesitter": "^1.0.2", "prebuildify": "^6.0.1", "tree-sitter-cli": "^0.24.4" }, "peerDependencies": { "tree-sitter": "^0.21.1" }, "peerDependenciesMeta": { "tree-sitter": { "optional": true } }, "scripts": { "install": "node-gyp-build", "prestart": "tree-sitter build --wasm", "start": "tree-sitter playground", "test": "node --test bindings/node/*_test.js" } } ================================================ FILE: pyproject.toml ================================================ [build-system] requires = ["setuptools>=42", "wheel"] build-backend = "setuptools.build_meta" [project] name = "tree-sitter-ruby" description = "Ruby grammar for tree-sitter" version = "0.23.1" keywords = ["incremental", "parsing", "tree-sitter", "ruby"] classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Compilers", "Topic :: Text Processing :: Linguistic", "Typing :: Typed", ] authors = [ { name = "Max Brunsfeld", email = "maxbrunsfeld@gmail.com" }, { name = "Amaan Qureshi", email = "amaanq12@gmail.com" }, ] requires-python = ">=3.9" license.text = "MIT" readme = "README.md" [project.urls] Homepage = "https://github.com/tree-sitter/tree-sitter-ruby" [project.optional-dependencies] core = ["tree-sitter~=0.22"] [tool.cibuildwheel] build = "cp39-*" build-frontend = "build" ================================================ FILE: queries/highlights.scm ================================================ (identifier) @variable ((identifier) @function.method (#is-not? local)) [ "alias" "and" "begin" "break" "case" "class" "def" "do" "else" "elsif" "end" "ensure" "for" "if" "in" "module" "next" "or" "rescue" "retry" "return" "then" "unless" "until" "when" "while" "yield" ] @keyword ((identifier) @keyword (#match? @keyword "^(private|protected|public)$")) (constant) @constructor ; Function calls "defined?" @function.method.builtin (call method: [(identifier) (constant)] @function.method) ((identifier) @function.method.builtin (#eq? @function.method.builtin "require")) ; Function definitions (alias (identifier) @function.method) (setter (identifier) @function.method) (method name: [(identifier) (constant)] @function.method) (singleton_method name: [(identifier) (constant)] @function.method) ; Identifiers [ (class_variable) (instance_variable) ] @property ((identifier) @constant.builtin (#match? @constant.builtin "^__(FILE|LINE|ENCODING)__$")) (file) @constant.builtin (line) @constant.builtin (encoding) @constant.builtin (hash_splat_nil "**" @operator) @constant.builtin ((constant) @constant (#match? @constant "^[A-Z\\d_]+$")) [ (self) (super) ] @variable.builtin (block_parameter (identifier) @variable.parameter) (block_parameters (identifier) @variable.parameter) (destructured_parameter (identifier) @variable.parameter) (hash_splat_parameter (identifier) @variable.parameter) (lambda_parameters (identifier) @variable.parameter) (method_parameters (identifier) @variable.parameter) (splat_parameter (identifier) @variable.parameter) (keyword_parameter name: (identifier) @variable.parameter) (optional_parameter name: (identifier) @variable.parameter) ; Literals [ (string) (bare_string) (subshell) (heredoc_body) (heredoc_beginning) ] @string [ (simple_symbol) (delimited_symbol) (hash_key_symbol) (bare_symbol) ] @string.special.symbol (regex) @string.special.regex (escape_sequence) @escape [ (integer) (float) ] @number [ (nil) (true) (false) ] @constant.builtin (interpolation "#{" @punctuation.special "}" @punctuation.special) @embedded (comment) @comment ; Operators [ "=" "=>" "->" ] @operator [ "," ";" "." ] @punctuation.delimiter [ "(" ")" "[" "]" "{" "}" "%w(" "%i(" ] @punctuation.bracket ================================================ FILE: queries/locals.scm ================================================ ((method) @local.scope (#set! local.scope-inherits false)) [ (lambda) (block) (do_block) ] @local.scope (block_parameter (identifier) @local.definition) (block_parameters (identifier) @local.definition) (destructured_parameter (identifier) @local.definition) (hash_splat_parameter (identifier) @local.definition) (lambda_parameters (identifier) @local.definition) (method_parameters (identifier) @local.definition) (splat_parameter (identifier) @local.definition) (keyword_parameter name: (identifier) @local.definition) (optional_parameter name: (identifier) @local.definition) (identifier) @local.reference (assignment left: (identifier) @local.definition) (operator_assignment left: (identifier) @local.definition) (left_assignment_list (identifier) @local.definition) (rest_assignment (identifier) @local.definition) (destructured_left_assignment (identifier) @local.definition) ================================================ FILE: queries/tags.scm ================================================ ; Method definitions ( (comment)* @doc . [ (method name: (_) @name) @definition.method (singleton_method name: (_) @name) @definition.method ] (#strip! @doc "^#\\s*") (#select-adjacent! @doc @definition.method) ) (alias name: (_) @name) @definition.method (setter (identifier) @ignore) ; Class definitions ( (comment)* @doc . [ (class name: [ (constant) @name (scope_resolution name: (_) @name) ]) @definition.class (singleton_class value: [ (constant) @name (scope_resolution name: (_) @name) ]) @definition.class ] (#strip! @doc "^#\\s*") (#select-adjacent! @doc @definition.class) ) ; Module definitions ( (module name: [ (constant) @name (scope_resolution name: (_) @name) ]) @definition.module ) ; Calls (call method: (identifier) @name) @reference.call ( [(identifier) (constant)] @name @reference.call (#is-not? local) (#not-match? @name "^(lambda|load|require|require_relative|__FILE__|__LINE__)$") ) ================================================ FILE: setup.py ================================================ from os.path import isdir, join from platform import system from setuptools import Extension, find_packages, setup from setuptools.command.build import build from wheel.bdist_wheel import bdist_wheel class Build(build): def run(self): if isdir("queries"): dest = join(self.build_lib, "tree_sitter_ruby", "queries") self.copy_tree("queries", dest) super().run() class BdistWheel(bdist_wheel): def get_tag(self): python, abi, platform = super().get_tag() if python.startswith("cp"): python, abi = "cp39", "abi3" return python, abi, platform setup( packages=find_packages("bindings/python"), package_dir={"": "bindings/python"}, package_data={ "tree_sitter_ruby": ["*.pyi", "py.typed"], "tree_sitter_ruby.queries": ["*.scm"], }, ext_package="tree_sitter_ruby", ext_modules=[ Extension( name="_binding", sources=[ "bindings/python/tree_sitter_ruby/binding.c", "src/parser.c", "src/scanner.c", ], extra_compile_args=[ "-std=c11", "-fvisibility=hidden", ] if system() != "Windows" else [ "/std:c11", "/utf-8", ], define_macros=[ ("Py_LIMITED_API", "0x03090000"), ("PY_SSIZE_T_CLEAN", None), ("TREE_SITTER_HIDE_SYMBOLS", None), ], include_dirs=["src"], py_limited_api=True, ) ], cmdclass={ "build": Build, "bdist_wheel": BdistWheel }, zip_safe=False ) ================================================ FILE: src/grammar.json ================================================ { "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json", "name": "ruby", "word": "identifier", "rules": { "program": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "__END__" }, { "type": "SYMBOL", "name": "uninterpreted" } ] } ] }, { "type": "BLANK" } ] } ] }, "uninterpreted": { "type": "PATTERN", "value": "(.|\\s)*" }, "block_body": { "type": "SYMBOL", "name": "_statements" }, "_statements": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "REPEAT1", "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_statement" }, { "type": "SYMBOL", "name": "_terminator" } ] }, { "type": "SYMBOL", "name": "empty_statement" } ] } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statement" }, { "type": "BLANK" } ] } ] }, { "type": "SYMBOL", "name": "_statement" } ] }, "begin_block": { "type": "SEQ", "members": [ { "type": "STRING", "value": "BEGIN" }, { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] }, "end_block": { "type": "SEQ", "members": [ { "type": "STRING", "value": "END" }, { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] }, "_statement": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "undef" }, { "type": "SYMBOL", "name": "alias" }, { "type": "SYMBOL", "name": "if_modifier" }, { "type": "SYMBOL", "name": "unless_modifier" }, { "type": "SYMBOL", "name": "while_modifier" }, { "type": "SYMBOL", "name": "until_modifier" }, { "type": "SYMBOL", "name": "rescue_modifier" }, { "type": "SYMBOL", "name": "begin_block" }, { "type": "SYMBOL", "name": "end_block" }, { "type": "SYMBOL", "name": "_expression" } ] }, "method": { "type": "SEQ", "members": [ { "type": "STRING", "value": "def" }, { "type": "SYMBOL", "name": "_method_rest" } ] }, "singleton_method": { "type": "SEQ", "members": [ { "type": "STRING", "value": "def" }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "object", "content": { "type": "SYMBOL", "name": "_variable" } }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "FIELD", "name": "object", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "STRING", "value": ")" } ] } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "." }, { "type": "STRING", "value": "::" } ] } ] }, { "type": "SYMBOL", "name": "_method_rest" } ] }, "_method_rest": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_method_name" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_body_expr" }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "parameters", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "parameters" }, "named": true, "value": "method_parameters" } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "body_statement" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, { "type": "SYMBOL", "name": "_body_expr" } ] } ] }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "parameters", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "bare_parameters" }, "named": true, "value": "method_parameters" } }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_terminator" }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "body_statement" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] } ] } ] }, "rescue_modifier_arg": { "type": "PREC", "value": 16, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "STRING", "value": "rescue" }, { "type": "FIELD", "name": "handler", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, "rescue_modifier_expression": { "type": "PREC", "value": 16, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_expression" } }, { "type": "STRING", "value": "rescue" }, { "type": "FIELD", "name": "handler", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, "_body_expr": { "type": "SEQ", "members": [ { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "rescue_modifier_arg" }, "named": true, "value": "rescue_modifier" } ] } } ] }, "parameters": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_formal_parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_formal_parameter" } ] } } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] }, "bare_parameters": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_formal_parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_formal_parameter" } ] } } ] }, "block_parameters": { "type": "SEQ", "members": [ { "type": "STRING", "value": "|" }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_formal_parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_formal_parameter" } ] } } ] }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": ";" }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "locals", "content": { "type": "SYMBOL", "name": "identifier" } }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "FIELD", "name": "locals", "content": { "type": "SYMBOL", "name": "identifier" } } ] } } ] } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "|" } ] }, "_formal_parameter": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_simple_formal_parameter" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "parameters" }, "named": true, "value": "destructured_parameter" } ] }, "_simple_formal_parameter": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "splat_parameter" }, { "type": "SYMBOL", "name": "hash_splat_parameter" }, { "type": "SYMBOL", "name": "hash_splat_nil" }, { "type": "SYMBOL", "name": "forward_parameter" }, { "type": "SYMBOL", "name": "block_parameter" }, { "type": "SYMBOL", "name": "keyword_parameter" }, { "type": "SYMBOL", "name": "optional_parameter" } ] }, "forward_parameter": { "type": "STRING", "value": "..." }, "splat_parameter": { "type": "PREC_RIGHT", "value": -2, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "*" }, { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "BLANK" } ] } } ] } }, "hash_splat_parameter": { "type": "SEQ", "members": [ { "type": "STRING", "value": "**" }, { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "BLANK" } ] } } ] }, "hash_splat_nil": { "type": "SEQ", "members": [ { "type": "STRING", "value": "**" }, { "type": "STRING", "value": "nil" } ] }, "block_parameter": { "type": "SEQ", "members": [ { "type": "STRING", "value": "&" }, { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "BLANK" } ] } } ] }, "keyword_parameter": { "type": "PREC_RIGHT", "value": 51, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "identifier" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": ":" } }, { "type": "FIELD", "name": "value", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "BLANK" } ] } } ] } }, "optional_parameter": { "type": "PREC", "value": 51, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "identifier" } }, { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, "class": { "type": "SEQ", "members": [ { "type": "STRING", "value": "class" }, { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "constant" }, { "type": "SYMBOL", "name": "scope_resolution" } ] } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "superclass", "content": { "type": "SYMBOL", "name": "superclass" } }, { "type": "SYMBOL", "name": "_terminator" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] } ] }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "body_statement" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, "superclass": { "type": "SEQ", "members": [ { "type": "STRING", "value": "<" }, { "type": "SYMBOL", "name": "_expression" } ] }, "singleton_class": { "type": "SEQ", "members": [ { "type": "STRING", "value": "class" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_singleton_class_left_angle_left_langle" }, "named": false, "value": "<<" }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "SYMBOL", "name": "_terminator" }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "body_statement" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, "module": { "type": "SEQ", "members": [ { "type": "STRING", "value": "module" }, { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "constant" }, { "type": "SYMBOL", "name": "scope_resolution" } ] } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "body_statement" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, "return_command": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "return" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_argument_list" }, "named": true, "value": "argument_list" } ] } }, "yield_command": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "yield" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_argument_list" }, "named": true, "value": "argument_list" } ] } }, "break_command": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "break" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_argument_list" }, "named": true, "value": "argument_list" } ] } }, "next_command": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "next" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_argument_list" }, "named": true, "value": "argument_list" } ] } }, "return": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "return" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "argument_list" }, { "type": "BLANK" } ] } ] } }, "yield": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "yield" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "argument_list" }, { "type": "BLANK" } ] } ] } }, "break": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "break" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "argument_list" }, { "type": "BLANK" } ] } ] } }, "next": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "next" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "argument_list" }, { "type": "BLANK" } ] } ] } }, "redo": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "redo" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "argument_list" }, { "type": "BLANK" } ] } ] } }, "retry": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "retry" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "argument_list" }, { "type": "BLANK" } ] } ] } }, "if_modifier": { "type": "PREC", "value": 16, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "STRING", "value": "if" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, "unless_modifier": { "type": "PREC", "value": 16, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "STRING", "value": "unless" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, "while_modifier": { "type": "PREC", "value": 16, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "STRING", "value": "while" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, "until_modifier": { "type": "PREC", "value": 16, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "STRING", "value": "until" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, "rescue_modifier": { "type": "PREC", "value": 16, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "STRING", "value": "rescue" }, { "type": "FIELD", "name": "handler", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, "while": { "type": "SEQ", "members": [ { "type": "STRING", "value": "while" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "do" } } ] }, "until": { "type": "SEQ", "members": [ { "type": "STRING", "value": "until" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "do" } } ] }, "for": { "type": "SEQ", "members": [ { "type": "STRING", "value": "for" }, { "type": "FIELD", "name": "pattern", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_lhs" }, { "type": "SYMBOL", "name": "left_assignment_list" } ] } }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "in" } }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "do" } } ] }, "in": { "type": "SEQ", "members": [ { "type": "STRING", "value": "in" }, { "type": "SYMBOL", "name": "_arg" } ] }, "do": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "do" }, { "type": "SYMBOL", "name": "_terminator" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, "case": { "type": "SEQ", "members": [ { "type": "STRING", "value": "case" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_line_break" }, { "type": "BLANK" } ] }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_statement" } } ] }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] }, { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "when" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "else" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, "case_match": { "type": "SEQ", "members": [ { "type": "STRING", "value": "case" }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_line_break" }, { "type": "BLANK" } ] }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_statement" } } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] }, { "type": "REPEAT1", "content": { "type": "FIELD", "name": "clauses", "content": { "type": "SYMBOL", "name": "in_clause" } } }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "else", "content": { "type": "SYMBOL", "name": "else" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, "when": { "type": "SEQ", "members": [ { "type": "STRING", "value": "when" }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "pattern" } }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "pattern" } } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "then" } } ] } ] }, "in_clause": { "type": "SEQ", "members": [ { "type": "STRING", "value": "in" }, { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "_pattern_top_expr_body" } }, { "type": "FIELD", "name": "guard", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_guard" }, { "type": "BLANK" } ] } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "then" } } ] } ] }, "pattern": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "SYMBOL", "name": "splat_argument" } ] }, "_guard": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "if_guard" }, { "type": "SYMBOL", "name": "unless_guard" } ] }, "if_guard": { "type": "SEQ", "members": [ { "type": "STRING", "value": "if" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_expression" } } ] }, "unless_guard": { "type": "SEQ", "members": [ { "type": "STRING", "value": "unless" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_expression" } } ] }, "_pattern_top_expr_body": { "type": "PREC", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_pattern_expr" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_array_pattern_n" }, "named": true, "value": "array_pattern" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_find_pattern_body" }, "named": true, "value": "find_pattern" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_hash_pattern_body" }, "named": true, "value": "hash_pattern" } ] } }, "_array_pattern_n": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_pattern_expr" }, { "type": "ALIAS", "content": { "type": "STRING", "value": "," }, "named": true, "value": "splat_parameter" } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_pattern_expr" }, { "type": "STRING", "value": "," }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_pattern_expr" }, { "type": "SYMBOL", "name": "_array_pattern_n" } ] } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "splat_parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_pattern_expr" } ] } } ] } ] } }, "_pattern_expr": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "as_pattern" }, { "type": "SYMBOL", "name": "_pattern_expr_alt" } ] }, "as_pattern": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_pattern_expr" } }, { "type": "STRING", "value": "=>" }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "identifier" } } ] }, "_pattern_expr_alt": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "alternative_pattern" }, { "type": "SYMBOL", "name": "_pattern_expr_basic" } ] }, "alternative_pattern": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "alternatives", "content": { "type": "SYMBOL", "name": "_pattern_expr_basic" } }, { "type": "REPEAT1", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "|" }, { "type": "FIELD", "name": "alternatives", "content": { "type": "SYMBOL", "name": "_pattern_expr_basic" } } ] } } ] }, "_array_pattern_body": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_pattern_expr" }, { "type": "SYMBOL", "name": "_array_pattern_n" } ] }, "array_pattern": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_array_pattern_body" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "]" } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "class", "content": { "type": "SYMBOL", "name": "_pattern_constant" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "[" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_array_pattern_body" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "]" } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "class", "content": { "type": "SYMBOL", "name": "_pattern_constant" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "(" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_array_pattern_body" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] } ] } }, "_find_pattern_body": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "splat_parameter" }, { "type": "REPEAT1", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_pattern_expr" } ] } }, { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "splat_parameter" } ] }, "find_pattern": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "SYMBOL", "name": "_find_pattern_body" }, { "type": "STRING", "value": "]" } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "class", "content": { "type": "SYMBOL", "name": "_pattern_constant" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "[" } }, { "type": "SYMBOL", "name": "_find_pattern_body" }, { "type": "STRING", "value": "]" } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "class", "content": { "type": "SYMBOL", "name": "_pattern_constant" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "(" } }, { "type": "SYMBOL", "name": "_find_pattern_body" }, { "type": "STRING", "value": ")" } ] } ] }, "_hash_pattern_body": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "keyword_pattern" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "keyword_pattern" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "keyword_pattern" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "keyword_pattern" } ] } } ] }, { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_hash_pattern_any_rest" } ] }, { "type": "SYMBOL", "name": "_hash_pattern_any_rest" } ] } }, "keyword_pattern": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "key", "content": { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "identifier" }, "named": true, "value": "hash_key_symbol" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "constant" }, "named": true, "value": "hash_key_symbol" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "identifier_suffix" }, "named": true, "value": "hash_key_symbol" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "constant_suffix" }, "named": true, "value": "hash_key_symbol" }, { "type": "SYMBOL", "name": "string" } ] } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": ":" } }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_pattern_expr" } }, { "type": "BLANK" } ] } ] } }, "_hash_pattern_any_rest": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "hash_splat_parameter" }, { "type": "SYMBOL", "name": "hash_splat_nil" } ] }, "hash_pattern": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_hash_pattern_body" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "class", "content": { "type": "SYMBOL", "name": "_pattern_constant" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "[" } }, { "type": "SYMBOL", "name": "_hash_pattern_body" }, { "type": "STRING", "value": "]" } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "class", "content": { "type": "SYMBOL", "name": "_pattern_constant" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "(" } }, { "type": "SYMBOL", "name": "_hash_pattern_body" }, { "type": "STRING", "value": ")" } ] } ] } }, "_pattern_expr_basic": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_pattern_value" }, { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "array_pattern" }, { "type": "SYMBOL", "name": "find_pattern" }, { "type": "SYMBOL", "name": "hash_pattern" }, { "type": "SYMBOL", "name": "parenthesized_pattern" } ] } }, "parenthesized_pattern": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SYMBOL", "name": "_pattern_expr" }, { "type": "STRING", "value": ")" } ] }, "_pattern_value": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_pattern_primitive" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_pattern_range" }, "named": true, "value": "range" }, { "type": "SYMBOL", "name": "variable_reference_pattern" }, { "type": "SYMBOL", "name": "expression_reference_pattern" }, { "type": "SYMBOL", "name": "_pattern_constant" } ] } }, "_pattern_range": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "begin", "content": { "type": "SYMBOL", "name": "_pattern_primitive" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": ".." }, { "type": "STRING", "value": "..." } ] } }, { "type": "FIELD", "name": "end", "content": { "type": "SYMBOL", "name": "_pattern_primitive" } } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": ".." }, { "type": "STRING", "value": "..." } ] } }, { "type": "FIELD", "name": "end", "content": { "type": "SYMBOL", "name": "_pattern_primitive" } } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "begin", "content": { "type": "SYMBOL", "name": "_pattern_primitive" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": ".." }, { "type": "STRING", "value": "..." } ] } } ] } ] }, "_pattern_primitive": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_pattern_literal" }, { "type": "SYMBOL", "name": "_pattern_lambda" } ] }, "_pattern_lambda": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "SYMBOL", "name": "lambda" } }, "_pattern_literal": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_literal" }, { "type": "SYMBOL", "name": "string" }, { "type": "SYMBOL", "name": "subshell" }, { "type": "SYMBOL", "name": "heredoc_beginning" }, { "type": "SYMBOL", "name": "regex" }, { "type": "SYMBOL", "name": "string_array" }, { "type": "SYMBOL", "name": "symbol_array" }, { "type": "SYMBOL", "name": "_keyword_variable" } ] } }, "_keyword_variable": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "nil" }, { "type": "SYMBOL", "name": "self" }, { "type": "SYMBOL", "name": "true" }, { "type": "SYMBOL", "name": "false" }, { "type": "SYMBOL", "name": "line" }, { "type": "SYMBOL", "name": "file" }, { "type": "SYMBOL", "name": "encoding" } ] } }, "line": { "type": "STRING", "value": "__LINE__" }, "file": { "type": "STRING", "value": "__FILE__" }, "encoding": { "type": "STRING", "value": "__ENCODING__" }, "variable_reference_pattern": { "type": "SEQ", "members": [ { "type": "STRING", "value": "^" }, { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "_nonlocal_variable" } ] } } ] }, "expression_reference_pattern": { "type": "SEQ", "members": [ { "type": "STRING", "value": "^" }, { "type": "STRING", "value": "(" }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_expression" } }, { "type": "STRING", "value": ")" } ] }, "_pattern_constant": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "constant" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_pattern_constant_resolution" }, "named": true, "value": "scope_resolution" } ] } }, "_pattern_constant_resolution": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "scope", "content": { "type": "SYMBOL", "name": "_pattern_constant" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "::" }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "constant" } } ] }, "if": { "type": "SEQ", "members": [ { "type": "STRING", "value": "if" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "FIELD", "name": "consequence", "content": { "type": "SYMBOL", "name": "then" } } ] }, { "type": "FIELD", "name": "alternative", "content": { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "else" }, { "type": "SYMBOL", "name": "elsif" } ] }, { "type": "BLANK" } ] } }, { "type": "STRING", "value": "end" } ] }, "unless": { "type": "SEQ", "members": [ { "type": "STRING", "value": "unless" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "FIELD", "name": "consequence", "content": { "type": "SYMBOL", "name": "then" } } ] }, { "type": "FIELD", "name": "alternative", "content": { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "else" }, { "type": "SYMBOL", "name": "elsif" } ] }, { "type": "BLANK" } ] } }, { "type": "STRING", "value": "end" } ] }, "elsif": { "type": "SEQ", "members": [ { "type": "STRING", "value": "elsif" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_statement" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "FIELD", "name": "consequence", "content": { "type": "SYMBOL", "name": "then" } } ] }, { "type": "FIELD", "name": "alternative", "content": { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "else" }, { "type": "SYMBOL", "name": "elsif" } ] }, { "type": "BLANK" } ] } } ] }, "else": { "type": "SEQ", "members": [ { "type": "STRING", "value": "else" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] } ] }, "then": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "SYMBOL", "name": "_statements" } ] }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "then" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] } ] } ] }, "begin": { "type": "SEQ", "members": [ { "type": "STRING", "value": "begin" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_body_statement" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, "ensure": { "type": "SEQ", "members": [ { "type": "STRING", "value": "ensure" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] } ] }, "rescue": { "type": "SEQ", "members": [ { "type": "STRING", "value": "rescue" }, { "type": "FIELD", "name": "exceptions", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "exceptions" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "variable", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "exception_variable" }, { "type": "BLANK" } ] } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "then" } } ] } ] }, "exceptions": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "SYMBOL", "name": "splat_argument" } ] }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "SYMBOL", "name": "splat_argument" } ] } ] } } ] }, "exception_variable": { "type": "SEQ", "members": [ { "type": "STRING", "value": "=>" }, { "type": "SYMBOL", "name": "_lhs" } ] }, "body_statement": { "type": "SYMBOL", "name": "_body_statement" }, "_body_statement": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "REPEAT", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "rescue" }, { "type": "SYMBOL", "name": "else" }, { "type": "SYMBOL", "name": "ensure" } ] } } ] }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] }, { "type": "REPEAT1", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "rescue" }, { "type": "SYMBOL", "name": "else" }, { "type": "SYMBOL", "name": "ensure" } ] } } ] } ] }, "_expression": { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_binary" }, "named": true, "value": "binary" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_unary" }, "named": true, "value": "unary" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_assignment" }, "named": true, "value": "assignment" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_operator_assignment" }, "named": true, "value": "operator_assignment" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_call" }, "named": true, "value": "call" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_call_with_block" }, "named": true, "value": "call" }, { "type": "PREC_LEFT", "value": 0, "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_chained_command_call" }, "named": true, "value": "call" } }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "return_command" }, "named": true, "value": "return" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "yield_command" }, "named": true, "value": "yield" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "break_command" }, "named": true, "value": "break" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "next_command" }, "named": true, "value": "next" }, { "type": "SYMBOL", "name": "match_pattern" }, { "type": "SYMBOL", "name": "test_pattern" }, { "type": "SYMBOL", "name": "_arg" } ] }, "match_pattern": { "type": "PREC", "value": 100, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "STRING", "value": "=>" }, { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "_pattern_top_expr_body" } } ] } }, "test_pattern": { "type": "PREC", "value": 100, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "STRING", "value": "in" }, { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "_pattern_top_expr_body" } } ] } }, "_arg": { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_unary_minus_pow" }, "named": true, "value": "unary" }, { "type": "SYMBOL", "name": "_primary" }, { "type": "SYMBOL", "name": "assignment" }, { "type": "SYMBOL", "name": "operator_assignment" }, { "type": "SYMBOL", "name": "conditional" }, { "type": "SYMBOL", "name": "range" }, { "type": "SYMBOL", "name": "binary" }, { "type": "SYMBOL", "name": "unary" } ] }, "_unary_minus_pow": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_unary_minus_num" }, "named": false, "value": "-" } }, { "type": "FIELD", "name": "operand", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_pow" }, "named": true, "value": "binary" } } ] }, "_pow": { "type": "PREC_RIGHT", "value": 80, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_simple_numeric" } }, { "type": "FIELD", "name": "operator", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_binary_star_star" }, "named": false, "value": "**" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, "_primary": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "parenthesized_statements" }, { "type": "SYMBOL", "name": "_lhs" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_function_identifier_call" }, "named": true, "value": "call" }, { "type": "SYMBOL", "name": "call" }, { "type": "SYMBOL", "name": "array" }, { "type": "SYMBOL", "name": "string_array" }, { "type": "SYMBOL", "name": "symbol_array" }, { "type": "SYMBOL", "name": "hash" }, { "type": "SYMBOL", "name": "subshell" }, { "type": "SYMBOL", "name": "_literal" }, { "type": "SYMBOL", "name": "string" }, { "type": "SYMBOL", "name": "character" }, { "type": "SYMBOL", "name": "chained_string" }, { "type": "SYMBOL", "name": "regex" }, { "type": "SYMBOL", "name": "lambda" }, { "type": "SYMBOL", "name": "method" }, { "type": "SYMBOL", "name": "singleton_method" }, { "type": "SYMBOL", "name": "class" }, { "type": "SYMBOL", "name": "singleton_class" }, { "type": "SYMBOL", "name": "module" }, { "type": "SYMBOL", "name": "begin" }, { "type": "SYMBOL", "name": "while" }, { "type": "SYMBOL", "name": "until" }, { "type": "SYMBOL", "name": "if" }, { "type": "SYMBOL", "name": "unless" }, { "type": "SYMBOL", "name": "for" }, { "type": "SYMBOL", "name": "case" }, { "type": "SYMBOL", "name": "case_match" }, { "type": "SYMBOL", "name": "return" }, { "type": "SYMBOL", "name": "yield" }, { "type": "SYMBOL", "name": "break" }, { "type": "SYMBOL", "name": "next" }, { "type": "SYMBOL", "name": "redo" }, { "type": "SYMBOL", "name": "retry" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "parenthesized_unary" }, "named": true, "value": "unary" }, { "type": "SYMBOL", "name": "heredoc_beginning" } ] }, "parenthesized_statements": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] }, "element_reference": { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "object", "content": { "type": "SYMBOL", "name": "_primary" } }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_element_reference_bracket" }, "named": false, "value": "[" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_argument_list_with_trailing_comma" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "]" }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "block", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "block" }, { "type": "SYMBOL", "name": "do_block" } ] } }, { "type": "BLANK" } ] } ] } }, "scope_resolution": { "type": "PREC_LEFT", "value": 57, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "::" }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "scope", "content": { "type": "SYMBOL", "name": "_primary" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "::" } } ] } ] }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "constant" } } ] } }, "_call_operator": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "." }, { "type": "STRING", "value": "&." }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "::" } } ] }, "_call": { "type": "PREC_LEFT", "value": 56, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "receiver", "content": { "type": "SYMBOL", "name": "_primary" } }, { "type": "FIELD", "name": "operator", "content": { "type": "SYMBOL", "name": "_call_operator" } }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "operator" }, { "type": "SYMBOL", "name": "constant" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] } }, "command_call": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_call" }, { "type": "SYMBOL", "name": "_chained_command_call" }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] }, { "type": "FIELD", "name": "arguments", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_argument_list" }, "named": true, "value": "argument_list" } } ] }, "command_call_with_block": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_call" }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] }, { "type": "PREC", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "arguments", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_argument_list" }, "named": true, "value": "argument_list" } }, { "type": "FIELD", "name": "block", "content": { "type": "SYMBOL", "name": "block" } } ] } } ] }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_call" }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] }, { "type": "PREC", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "arguments", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_argument_list" }, "named": true, "value": "argument_list" } }, { "type": "FIELD", "name": "block", "content": { "type": "SYMBOL", "name": "do_block" } } ] } } ] } ] }, "_chained_command_call": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "receiver", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "command_call_with_block" }, "named": true, "value": "call" } }, { "type": "FIELD", "name": "operator", "content": { "type": "SYMBOL", "name": "_call_operator" } }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "_function_identifier" }, { "type": "SYMBOL", "name": "operator" }, { "type": "SYMBOL", "name": "constant" } ] } } ] }, "call": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_call" }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] }, { "type": "PREC_LEFT", "value": 56, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "receiver", "content": { "type": "SYMBOL", "name": "_primary" } }, { "type": "FIELD", "name": "operator", "content": { "type": "SYMBOL", "name": "_call_operator" } } ] } } ] }, { "type": "FIELD", "name": "arguments", "content": { "type": "SYMBOL", "name": "argument_list" } } ] }, { "type": "PREC", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_call" }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] }, { "type": "PREC_LEFT", "value": 56, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "receiver", "content": { "type": "SYMBOL", "name": "_primary" } }, { "type": "FIELD", "name": "operator", "content": { "type": "SYMBOL", "name": "_call_operator" } } ] } } ] }, { "type": "FIELD", "name": "arguments", "content": { "type": "SYMBOL", "name": "argument_list" } } ] }, { "type": "FIELD", "name": "block", "content": { "type": "SYMBOL", "name": "block" } } ] } }, { "type": "PREC", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_call" }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] }, { "type": "PREC_LEFT", "value": 56, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "receiver", "content": { "type": "SYMBOL", "name": "_primary" } }, { "type": "FIELD", "name": "operator", "content": { "type": "SYMBOL", "name": "_call_operator" } } ] } } ] }, { "type": "FIELD", "name": "arguments", "content": { "type": "SYMBOL", "name": "argument_list" } } ] }, { "type": "FIELD", "name": "block", "content": { "type": "SYMBOL", "name": "do_block" } } ] } }, { "type": "PREC", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_call" }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] }, { "type": "FIELD", "name": "block", "content": { "type": "SYMBOL", "name": "block" } } ] } }, { "type": "PREC", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_call" }, { "type": "FIELD", "name": "method", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "_function_identifier" } ] } } ] }, { "type": "FIELD", "name": "block", "content": { "type": "SYMBOL", "name": "do_block" } } ] } } ] }, "command_argument_list": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_argument" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_argument" } ] } } ] } }, "argument_list": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "(" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_argument_list_with_trailing_comma" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] } }, "_argument_list_with_trailing_comma": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_argument" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_argument" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] } }, "_argument": { "type": "PREC_LEFT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_expression" }, { "type": "SYMBOL", "name": "splat_argument" }, { "type": "SYMBOL", "name": "hash_splat_argument" }, { "type": "SYMBOL", "name": "forward_argument" }, { "type": "SYMBOL", "name": "block_argument" }, { "type": "SYMBOL", "name": "pair" } ] } }, "forward_argument": { "type": "STRING", "value": "..." }, "splat_argument": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_splat_star" }, "named": false, "value": "*" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "BLANK" } ] } ] } }, "hash_splat_argument": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_hash_splat_star_star" }, "named": false, "value": "**" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "BLANK" } ] } ] } }, "block_argument": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_block_ampersand" }, "named": false, "value": "&" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "BLANK" } ] } ] } }, "do_block": { "type": "SEQ", "members": [ { "type": "STRING", "value": "do" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "parameters", "content": { "type": "SYMBOL", "name": "block_parameters" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_terminator" }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "body_statement" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "end" } ] }, "block": { "type": "PREC", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "FIELD", "name": "parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "block_parameters" }, { "type": "BLANK" } ] } }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "block_body" } }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] } }, "_arg_rhs": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "rescue_modifier_arg" }, "named": true, "value": "rescue_modifier" } ] }, "assignment": { "type": "PREC_RIGHT", "value": 15, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_lhs" }, { "type": "SYMBOL", "name": "left_assignment_list" } ] } }, { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "right", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg_rhs" }, { "type": "SYMBOL", "name": "splat_argument" }, { "type": "SYMBOL", "name": "right_assignment_list" } ] } } ] } ] } }, "command_assignment": { "type": "PREC_RIGHT", "value": 15, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_lhs" }, { "type": "SYMBOL", "name": "left_assignment_list" } ] } }, { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "right", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_expression" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "rescue_modifier_expression" }, "named": true, "value": "rescue_modifier" } ] } } ] } }, "operator_assignment": { "type": "PREC_RIGHT", "value": 15, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_lhs" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "+=" }, { "type": "STRING", "value": "-=" }, { "type": "STRING", "value": "*=" }, { "type": "STRING", "value": "**=" }, { "type": "STRING", "value": "/=" }, { "type": "STRING", "value": "||=" }, { "type": "STRING", "value": "|=" }, { "type": "STRING", "value": "&&=" }, { "type": "STRING", "value": "&=" }, { "type": "STRING", "value": "%=" }, { "type": "STRING", "value": ">>=" }, { "type": "STRING", "value": "<<=" }, { "type": "STRING", "value": "^=" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg_rhs" } } ] } }, "command_operator_assignment": { "type": "PREC_RIGHT", "value": 15, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_lhs" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "+=" }, { "type": "STRING", "value": "-=" }, { "type": "STRING", "value": "*=" }, { "type": "STRING", "value": "**=" }, { "type": "STRING", "value": "/=" }, { "type": "STRING", "value": "||=" }, { "type": "STRING", "value": "|=" }, { "type": "STRING", "value": "&&=" }, { "type": "STRING", "value": "&=" }, { "type": "STRING", "value": "%=" }, { "type": "STRING", "value": ">>=" }, { "type": "STRING", "value": "<<=" }, { "type": "STRING", "value": "^=" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_expression" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "rescue_modifier_expression" }, "named": true, "value": "rescue_modifier" } ] } } ] } }, "conditional": { "type": "PREC_RIGHT", "value": 20, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "STRING", "value": "?" }, { "type": "FIELD", "name": "consequence", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "alternative", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, "range": { "type": "PREC_RIGHT", "value": 25, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "begin", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": ".." }, { "type": "STRING", "value": "..." } ] } }, { "type": "FIELD", "name": "end", "content": { "type": "SYMBOL", "name": "_arg" } } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": ".." }, { "type": "STRING", "value": "..." } ] } }, { "type": "FIELD", "name": "end", "content": { "type": "SYMBOL", "name": "_arg" } } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "begin", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": ".." }, { "type": "STRING", "value": "..." } ] } } ] } ] } }, "binary": { "type": "CHOICE", "members": [ { "type": "PREC_LEFT", "value": -2, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "and" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": -2, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "or" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": 30, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "||" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": 35, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "&&" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": 60, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "<<" }, { "type": "STRING", "value": ">>" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": 45, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "<" }, { "type": "STRING", "value": "<=" }, { "type": "STRING", "value": ">" }, { "type": "STRING", "value": ">=" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": 55, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "&" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": 50, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "^" }, { "type": "STRING", "value": "|" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": 65, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "+" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_binary_minus" }, "named": false, "value": "-" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_LEFT", "value": 70, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "/" }, { "type": "STRING", "value": "%" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_binary_star" }, "named": false, "value": "*" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_RIGHT", "value": 40, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "==" }, { "type": "STRING", "value": "!=" }, { "type": "STRING", "value": "===" }, { "type": "STRING", "value": "<=>" }, { "type": "STRING", "value": "=~" }, { "type": "STRING", "value": "!~" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_RIGHT", "value": 80, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "FIELD", "name": "operator", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_binary_star_star" }, "named": false, "value": "**" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_arg" } } ] } } ] }, "command_binary": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_expression" } }, { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "or" }, { "type": "STRING", "value": "and" } ] } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, "unary": { "type": "CHOICE", "members": [ { "type": "PREC", "value": 10, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "defined?" } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_RIGHT", "value": 5, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "not" } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_RIGHT", "value": 75, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_unary_minus" }, "named": false, "value": "-" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_binary_minus" }, "named": false, "value": "-" }, { "type": "STRING", "value": "+" } ] } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_arg" } } ] } }, { "type": "PREC_RIGHT", "value": 85, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "!" }, { "type": "STRING", "value": "~" } ] } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_arg" } } ] } } ] }, "command_unary": { "type": "CHOICE", "members": [ { "type": "PREC", "value": 10, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "defined?" } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, { "type": "PREC_RIGHT", "value": 5, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "STRING", "value": "not" } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, { "type": "PREC_RIGHT", "value": 75, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_unary_minus" }, "named": false, "value": "-" }, { "type": "STRING", "value": "+" } ] } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_expression" } } ] } }, { "type": "PREC_RIGHT", "value": 85, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "!" }, { "type": "STRING", "value": "~" } ] } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_expression" } } ] } } ] }, "parenthesized_unary": { "type": "PREC", "value": 56, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "defined?" }, { "type": "STRING", "value": "not" } ] } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "parenthesized_statements" } } ] } }, "unary_literal": { "type": "PREC_RIGHT", "value": 75, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "operator", "content": { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_unary_minus_num" }, "named": false, "value": "-" }, { "type": "STRING", "value": "+" } ] } }, { "type": "FIELD", "name": "operand", "content": { "type": "SYMBOL", "name": "_simple_numeric" } } ] } }, "_literal": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "simple_symbol" }, { "type": "SYMBOL", "name": "delimited_symbol" }, { "type": "SYMBOL", "name": "_numeric" } ] }, "_numeric": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_simple_numeric" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "unary_literal" }, "named": true, "value": "unary" } ] }, "_simple_numeric": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "integer" }, { "type": "SYMBOL", "name": "float" }, { "type": "SYMBOL", "name": "complex" }, { "type": "SYMBOL", "name": "rational" } ] }, "right_assignment_list": { "type": "PREC", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "SYMBOL", "name": "splat_argument" } ] }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "SYMBOL", "name": "splat_argument" } ] } ] } } ] } }, "left_assignment_list": { "type": "SYMBOL", "name": "_mlhs" }, "_mlhs": { "type": "PREC_LEFT", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_lhs" }, { "type": "SYMBOL", "name": "rest_assignment" }, { "type": "SYMBOL", "name": "destructured_left_assignment" } ] }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_lhs" }, { "type": "SYMBOL", "name": "rest_assignment" }, { "type": "SYMBOL", "name": "destructured_left_assignment" } ] } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] } }, "destructured_left_assignment": { "type": "PREC", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SYMBOL", "name": "_mlhs" }, { "type": "STRING", "value": ")" } ] } }, "rest_assignment": { "type": "PREC", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "*" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_lhs" }, { "type": "BLANK" } ] } ] } }, "_function_identifier": { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "identifier_suffix" }, "named": true, "value": "identifier" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "constant_suffix" }, "named": true, "value": "constant" } ] }, "_function_identifier_call": { "type": "PREC_LEFT", "value": 0, "content": { "type": "FIELD", "name": "method", "content": { "type": "SYMBOL", "name": "_function_identifier" } } }, "_lhs": { "type": "PREC_LEFT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_variable" }, { "type": "SYMBOL", "name": "true" }, { "type": "SYMBOL", "name": "false" }, { "type": "SYMBOL", "name": "nil" }, { "type": "SYMBOL", "name": "scope_resolution" }, { "type": "SYMBOL", "name": "element_reference" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_call" }, "named": true, "value": "call" } ] } }, "_variable": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "self" }, { "type": "SYMBOL", "name": "super" }, { "type": "SYMBOL", "name": "_nonlocal_variable" }, { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "constant" } ] } }, "operator": { "type": "CHOICE", "members": [ { "type": "STRING", "value": ".." }, { "type": "STRING", "value": "|" }, { "type": "STRING", "value": "^" }, { "type": "STRING", "value": "&" }, { "type": "STRING", "value": "<=>" }, { "type": "STRING", "value": "==" }, { "type": "STRING", "value": "===" }, { "type": "STRING", "value": "=~" }, { "type": "STRING", "value": ">" }, { "type": "STRING", "value": ">=" }, { "type": "STRING", "value": "<" }, { "type": "STRING", "value": "<=" }, { "type": "STRING", "value": "+" }, { "type": "STRING", "value": "!=" }, { "type": "STRING", "value": "-" }, { "type": "STRING", "value": "*" }, { "type": "STRING", "value": "/" }, { "type": "STRING", "value": "%" }, { "type": "STRING", "value": "!" }, { "type": "STRING", "value": "!~" }, { "type": "STRING", "value": "**" }, { "type": "STRING", "value": "<<" }, { "type": "STRING", "value": ">>" }, { "type": "STRING", "value": "~" }, { "type": "STRING", "value": "+@" }, { "type": "STRING", "value": "-@" }, { "type": "STRING", "value": "~@" }, { "type": "STRING", "value": "[]" }, { "type": "STRING", "value": "[]=" }, { "type": "STRING", "value": "`" } ] }, "_method_name": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "_function_identifier" }, { "type": "SYMBOL", "name": "constant" }, { "type": "SYMBOL", "name": "setter" }, { "type": "SYMBOL", "name": "simple_symbol" }, { "type": "SYMBOL", "name": "delimited_symbol" }, { "type": "SYMBOL", "name": "operator" }, { "type": "SYMBOL", "name": "_nonlocal_variable" } ] }, "_nonlocal_variable": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "instance_variable" }, { "type": "SYMBOL", "name": "class_variable" }, { "type": "SYMBOL", "name": "global_variable" } ] }, "setter": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "identifier" } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "=" } } ] }, "undef": { "type": "SEQ", "members": [ { "type": "STRING", "value": "undef" }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_method_name" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_method_name" } ] } } ] } ] }, "alias": { "type": "SEQ", "members": [ { "type": "STRING", "value": "alias" }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_method_name" } }, { "type": "FIELD", "name": "alias", "content": { "type": "SYMBOL", "name": "_method_name" } } ] }, "comment": { "type": "TOKEN", "content": { "type": "PREC", "value": -2, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "#" }, { "type": "PATTERN", "value": ".*" } ] }, { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "=begin.*\\r?\\n" }, { "type": "REPEAT", "content": { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[^=]" }, { "type": "PATTERN", "value": "=[^e]" }, { "type": "PATTERN", "value": "=e[^n]" }, { "type": "PATTERN", "value": "=en[^d]" } ] } }, { "type": "PATTERN", "value": "[\\s*]*=end.*" } ] } ] } } }, "integer": { "type": "PATTERN", "value": "0[bB][01](_?[01])*|0[oO]?[0-7](_?[0-7])*|(0[dD])?\\d(_?\\d)*|0[xX][0-9a-fA-F](_?[0-9a-fA-F])*" }, "_int_or_float": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "integer" }, { "type": "SYMBOL", "name": "float" } ] }, "float": { "type": "PATTERN", "value": "\\d(_?\\d)*(\\.\\d)?(_?\\d)*([eE][\\+-]?\\d(_?\\d)*)?" }, "complex": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_int_or_float" }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "i" } } ] }, { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_int_or_float" }, "named": true, "value": "rational" }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "ri" } } ] } ] }, "rational": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_int_or_float" }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "r" } } ] }, "super": { "type": "STRING", "value": "super" }, "self": { "type": "STRING", "value": "self" }, "true": { "type": "STRING", "value": "true" }, "false": { "type": "STRING", "value": "false" }, "nil": { "type": "STRING", "value": "nil" }, "constant": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[A-Z]" }, { "type": "PATTERN", "value": "[^\\x00-\\x1F\\s:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]*" } ] } }, "constant_suffix": { "type": "CHOICE", "members": [ { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[A-Z]" }, { "type": "PATTERN", "value": "[^\\x00-\\x1F\\s:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]*" }, { "type": "PATTERN", "value": "[?]" } ] } }, { "type": "SYMBOL", "name": "_constant_suffix" } ] }, "identifier": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[^\\x00-\\x1F\\sA-Z0-9:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]" }, { "type": "PATTERN", "value": "[^\\x00-\\x1F\\s:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]*" } ] } }, "identifier_suffix": { "type": "CHOICE", "members": [ { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[^\\x00-\\x1F\\sA-Z0-9:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]" }, { "type": "PATTERN", "value": "[^\\x00-\\x1F\\s:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]*" }, { "type": "PATTERN", "value": "[?]" } ] } }, { "type": "SYMBOL", "name": "_identifier_suffix" } ] }, "instance_variable": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "@" }, { "type": "PATTERN", "value": "[^\\x00-\\x1F\\s0-9:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]" }, { "type": "PATTERN", "value": "[^\\x00-\\x1F\\s:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]*" } ] } }, "class_variable": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "@@" }, { "type": "PATTERN", "value": "[^\\x00-\\x1F\\s0-9:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]" }, { "type": "PATTERN", "value": "[^\\x00-\\x1F\\s:;`\"'@$#.,|^&<=>+\\-*/\\\\%?!~()\\[\\]{}]*" } ] } }, "global_variable": { "type": "PATTERN", "value": "\\$(-[a-zA-Z0-9_]|[!@&`'+~=/\\\\,;.<>*$?:\"]|[0-9]+|[a-zA-Z_][a-zA-Z0-9_]*)" }, "chained_string": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "string" }, { "type": "REPEAT1", "content": { "type": "SYMBOL", "name": "string" } } ] }, "character": { "type": "PATTERN", "value": "\\?(\\\\\\S(\\{[0-9A-Fa-f]*\\}|[0-9A-Fa-f]*|-\\S([MC]-\\S)?)?|\\S)" }, "interpolation": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "#{" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_statements" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_short_interpolation" }, { "type": "SYMBOL", "name": "_nonlocal_variable" } ] } ] }, "string": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_string_start" }, "named": false, "value": "\"" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_literal_contents" }, { "type": "BLANK" } ] }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_string_end" }, "named": false, "value": "\"" } ] }, "subshell": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_subshell_start" }, "named": false, "value": "`" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_literal_contents" }, { "type": "BLANK" } ] }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_string_end" }, "named": false, "value": "`" } ] }, "string_array": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_string_array_start" }, "named": false, "value": "%w(" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "\\s+" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_literal_contents" }, "named": true, "value": "bare_string" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "\\s+" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_literal_contents" }, "named": true, "value": "bare_string" } ] } } ] }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "\\s+" }, { "type": "BLANK" } ] }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_string_end" }, "named": false, "value": ")" } ] }, "symbol_array": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_symbol_array_start" }, "named": false, "value": "%i(" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "\\s+" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_literal_contents" }, "named": true, "value": "bare_symbol" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "\\s+" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_literal_contents" }, "named": true, "value": "bare_symbol" } ] } } ] }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "\\s+" }, { "type": "BLANK" } ] }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_string_end" }, "named": false, "value": ")" } ] }, "delimited_symbol": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_symbol_start" }, "named": false, "value": ":\"" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_literal_contents" }, { "type": "BLANK" } ] }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_string_end" }, "named": false, "value": "\"" } ] }, "regex": { "type": "SEQ", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_regex_start" }, "named": false, "value": "/" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_literal_contents" }, { "type": "BLANK" } ] }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_string_end" }, "named": false, "value": "/" } ] }, "heredoc_body": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_heredoc_body_start" }, { "type": "REPEAT", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "heredoc_content" }, { "type": "SYMBOL", "name": "interpolation" }, { "type": "SYMBOL", "name": "escape_sequence" } ] } }, { "type": "SYMBOL", "name": "heredoc_end" } ] }, "_literal_contents": { "type": "REPEAT1", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "string_content" }, { "type": "SYMBOL", "name": "interpolation" }, { "type": "SYMBOL", "name": "escape_sequence" } ] } }, "escape_sequence": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "\\" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[^ux0-7]" }, { "type": "PATTERN", "value": "x[0-9a-fA-F]{1,2}" }, { "type": "PATTERN", "value": "[0-7]{1,3}" }, { "type": "PATTERN", "value": "u[0-9a-fA-F]{4}" }, { "type": "PATTERN", "value": "u\\{[0-9a-fA-F ]+\\}" } ] } ] } }, "array": { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_argument_list_with_trailing_comma" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "]" } ] }, "hash": { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "pair" }, { "type": "SYMBOL", "name": "hash_splat_argument" } ] }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "pair" }, { "type": "SYMBOL", "name": "hash_splat_argument" } ] } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] }, "pair": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "key", "content": { "type": "SYMBOL", "name": "_arg" } }, { "type": "STRING", "value": "=>" }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_arg" } } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "key", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "string" } ] } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": ":" } }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_arg" } } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "key", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "hash_key_symbol" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "identifier" }, "named": true, "value": "hash_key_symbol" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "constant" }, "named": true, "value": "hash_key_symbol" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "identifier_suffix" }, "named": true, "value": "hash_key_symbol" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "constant_suffix" }, "named": true, "value": "hash_key_symbol" } ] } }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": ":" } }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "value", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_arg" }, { "type": "BLANK" } ] } }, { "type": "SYMBOL", "name": "_no_line_break" } ] } ] } ] } }, "lambda": { "type": "SEQ", "members": [ { "type": "STRING", "value": "->" }, { "type": "FIELD", "name": "parameters", "content": { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "parameters" }, "named": true, "value": "lambda_parameters" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "bare_parameters" }, "named": true, "value": "lambda_parameters" } ] }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "block" }, { "type": "SYMBOL", "name": "do_block" } ] } } ] }, "empty_statement": { "type": "PREC", "value": -1, "content": { "type": "STRING", "value": ";" } }, "_terminator": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_line_break" }, { "type": "STRING", "value": ";" } ] } }, "extras": [ { "type": "SYMBOL", "name": "comment" }, { "type": "SYMBOL", "name": "heredoc_body" }, { "type": "PATTERN", "value": "\\s" }, { "type": "PATTERN", "value": "\\\\\\r?\\n" } ], "conflicts": [], "precedences": [], "externals": [ { "type": "SYMBOL", "name": "_line_break" }, { "type": "SYMBOL", "name": "_no_line_break" }, { "type": "SYMBOL", "name": "simple_symbol" }, { "type": "SYMBOL", "name": "_string_start" }, { "type": "SYMBOL", "name": "_symbol_start" }, { "type": "SYMBOL", "name": "_subshell_start" }, { "type": "SYMBOL", "name": "_regex_start" }, { "type": "SYMBOL", "name": "_string_array_start" }, { "type": "SYMBOL", "name": "_symbol_array_start" }, { "type": "SYMBOL", "name": "_heredoc_body_start" }, { "type": "SYMBOL", "name": "string_content" }, { "type": "SYMBOL", "name": "heredoc_content" }, { "type": "SYMBOL", "name": "_string_end" }, { "type": "SYMBOL", "name": "heredoc_end" }, { "type": "SYMBOL", "name": "heredoc_beginning" }, { "type": "STRING", "value": "/" }, { "type": "SYMBOL", "name": "_block_ampersand" }, { "type": "SYMBOL", "name": "_splat_star" }, { "type": "SYMBOL", "name": "_unary_minus" }, { "type": "SYMBOL", "name": "_unary_minus_num" }, { "type": "SYMBOL", "name": "_binary_minus" }, { "type": "SYMBOL", "name": "_binary_star" }, { "type": "SYMBOL", "name": "_singleton_class_left_angle_left_langle" }, { "type": "SYMBOL", "name": "hash_key_symbol" }, { "type": "SYMBOL", "name": "_identifier_suffix" }, { "type": "SYMBOL", "name": "_constant_suffix" }, { "type": "SYMBOL", "name": "_hash_splat_star_star" }, { "type": "SYMBOL", "name": "_binary_star_star" }, { "type": "SYMBOL", "name": "_element_reference_bracket" }, { "type": "SYMBOL", "name": "_short_interpolation" } ], "inline": [ "_arg_rhs", "_call_operator" ], "supertypes": [ "_statement", "_arg", "_call_operator", "_method_name", "_expression", "_variable", "_primary", "_simple_numeric", "_lhs", "_nonlocal_variable", "_pattern_top_expr_body", "_pattern_expr", "_pattern_expr_basic", "_pattern_primitive", "_pattern_constant" ] } ================================================ FILE: src/node-types.json ================================================ [ { "type": "_arg", "named": true, "subtypes": [ { "type": "_primary", "named": true }, { "type": "assignment", "named": true }, { "type": "binary", "named": true }, { "type": "conditional", "named": true }, { "type": "operator_assignment", "named": true }, { "type": "range", "named": true }, { "type": "unary", "named": true } ] }, { "type": "_call_operator", "named": true, "subtypes": [ { "type": "&.", "named": false }, { "type": ".", "named": false }, { "type": "::", "named": false } ] }, { "type": "_expression", "named": true, "subtypes": [ { "type": "_arg", "named": true }, { "type": "assignment", "named": true }, { "type": "binary", "named": true }, { "type": "break", "named": true }, { "type": "call", "named": true }, { "type": "match_pattern", "named": true }, { "type": "next", "named": true }, { "type": "operator_assignment", "named": true }, { "type": "return", "named": true }, { "type": "test_pattern", "named": true }, { "type": "unary", "named": true }, { "type": "yield", "named": true } ] }, { "type": "_lhs", "named": true, "subtypes": [ { "type": "_variable", "named": true }, { "type": "call", "named": true }, { "type": "element_reference", "named": true }, { "type": "false", "named": true }, { "type": "nil", "named": true }, { "type": "scope_resolution", "named": true }, { "type": "true", "named": true } ] }, { "type": "_method_name", "named": true, "subtypes": [ { "type": "_nonlocal_variable", "named": true }, { "type": "constant", "named": true }, { "type": "delimited_symbol", "named": true }, { "type": "identifier", "named": true }, { "type": "operator", "named": true }, { "type": "setter", "named": true }, { "type": "simple_symbol", "named": true } ] }, { "type": "_nonlocal_variable", "named": true, "subtypes": [ { "type": "class_variable", "named": true }, { "type": "global_variable", "named": true }, { "type": "instance_variable", "named": true } ] }, { "type": "_pattern_constant", "named": true, "subtypes": [ { "type": "constant", "named": true }, { "type": "scope_resolution", "named": true } ] }, { "type": "_pattern_expr", "named": true, "subtypes": [ { "type": "_pattern_expr_basic", "named": true }, { "type": "alternative_pattern", "named": true }, { "type": "as_pattern", "named": true } ] }, { "type": "_pattern_expr_basic", "named": true, "subtypes": [ { "type": "_pattern_constant", "named": true }, { "type": "_pattern_primitive", "named": true }, { "type": "array_pattern", "named": true }, { "type": "expression_reference_pattern", "named": true }, { "type": "find_pattern", "named": true }, { "type": "hash_pattern", "named": true }, { "type": "identifier", "named": true }, { "type": "parenthesized_pattern", "named": true }, { "type": "range", "named": true }, { "type": "variable_reference_pattern", "named": true } ] }, { "type": "_pattern_primitive", "named": true, "subtypes": [ { "type": "_simple_numeric", "named": true }, { "type": "delimited_symbol", "named": true }, { "type": "encoding", "named": true }, { "type": "false", "named": true }, { "type": "file", "named": true }, { "type": "heredoc_beginning", "named": true }, { "type": "lambda", "named": true }, { "type": "line", "named": true }, { "type": "nil", "named": true }, { "type": "regex", "named": true }, { "type": "self", "named": true }, { "type": "simple_symbol", "named": true }, { "type": "string", "named": true }, { "type": "string_array", "named": true }, { "type": "subshell", "named": true }, { "type": "symbol_array", "named": true }, { "type": "true", "named": true }, { "type": "unary", "named": true } ] }, { "type": "_pattern_top_expr_body", "named": true, "subtypes": [ { "type": "_pattern_expr", "named": true }, { "type": "array_pattern", "named": true }, { "type": "find_pattern", "named": true }, { "type": "hash_pattern", "named": true } ] }, { "type": "_primary", "named": true, "subtypes": [ { "type": "_lhs", "named": true }, { "type": "_simple_numeric", "named": true }, { "type": "array", "named": true }, { "type": "begin", "named": true }, { "type": "break", "named": true }, { "type": "call", "named": true }, { "type": "case", "named": true }, { "type": "case_match", "named": true }, { "type": "chained_string", "named": true }, { "type": "character", "named": true }, { "type": "class", "named": true }, { "type": "delimited_symbol", "named": true }, { "type": "for", "named": true }, { "type": "hash", "named": true }, { "type": "heredoc_beginning", "named": true }, { "type": "if", "named": true }, { "type": "lambda", "named": true }, { "type": "method", "named": true }, { "type": "module", "named": true }, { "type": "next", "named": true }, { "type": "parenthesized_statements", "named": true }, { "type": "redo", "named": true }, { "type": "regex", "named": true }, { "type": "retry", "named": true }, { "type": "return", "named": true }, { "type": "simple_symbol", "named": true }, { "type": "singleton_class", "named": true }, { "type": "singleton_method", "named": true }, { "type": "string", "named": true }, { "type": "string_array", "named": true }, { "type": "subshell", "named": true }, { "type": "symbol_array", "named": true }, { "type": "unary", "named": true }, { "type": "unless", "named": true }, { "type": "until", "named": true }, { "type": "while", "named": true }, { "type": "yield", "named": true } ] }, { "type": "_simple_numeric", "named": true, "subtypes": [ { "type": "complex", "named": true }, { "type": "float", "named": true }, { "type": "integer", "named": true }, { "type": "rational", "named": true } ] }, { "type": "_statement", "named": true, "subtypes": [ { "type": "_expression", "named": true }, { "type": "alias", "named": true }, { "type": "begin_block", "named": true }, { "type": "end_block", "named": true }, { "type": "if_modifier", "named": true }, { "type": "rescue_modifier", "named": true }, { "type": "undef", "named": true }, { "type": "unless_modifier", "named": true }, { "type": "until_modifier", "named": true }, { "type": "while_modifier", "named": true } ] }, { "type": "_variable", "named": true, "subtypes": [ { "type": "_nonlocal_variable", "named": true }, { "type": "constant", "named": true }, { "type": "identifier", "named": true }, { "type": "self", "named": true }, { "type": "super", "named": true } ] }, { "type": "alias", "named": true, "fields": { "alias": { "multiple": false, "required": true, "types": [ { "type": "_method_name", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "_method_name", "named": true } ] } } }, { "type": "alternative_pattern", "named": true, "fields": { "alternatives": { "multiple": true, "required": true, "types": [ { "type": "_pattern_expr_basic", "named": true } ] } } }, { "type": "argument_list", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_expression", "named": true }, { "type": "block_argument", "named": true }, { "type": "forward_argument", "named": true }, { "type": "hash_splat_argument", "named": true }, { "type": "pair", "named": true }, { "type": "splat_argument", "named": true } ] } }, { "type": "array", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_expression", "named": true }, { "type": "block_argument", "named": true }, { "type": "forward_argument", "named": true }, { "type": "hash_splat_argument", "named": true }, { "type": "pair", "named": true }, { "type": "splat_argument", "named": true } ] } }, { "type": "array_pattern", "named": true, "fields": { "class": { "multiple": false, "required": false, "types": [ { "type": "_pattern_constant", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "_pattern_expr", "named": true }, { "type": "splat_parameter", "named": true } ] } }, { "type": "as_pattern", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "_pattern_expr", "named": true } ] } } }, { "type": "assignment", "named": true, "fields": { "left": { "multiple": false, "required": true, "types": [ { "type": "_lhs", "named": true }, { "type": "left_assignment_list", "named": true } ] }, "right": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true }, { "type": "rescue_modifier", "named": true }, { "type": "right_assignment_list", "named": true }, { "type": "splat_argument", "named": true } ] } } }, { "type": "bare_string", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "escape_sequence", "named": true }, { "type": "interpolation", "named": true }, { "type": "string_content", "named": true } ] } }, { "type": "bare_symbol", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "escape_sequence", "named": true }, { "type": "interpolation", "named": true }, { "type": "string_content", "named": true } ] } }, { "type": "begin", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "else", "named": true }, { "type": "empty_statement", "named": true }, { "type": "ensure", "named": true }, { "type": "rescue", "named": true } ] } }, { "type": "begin_block", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "binary", "named": true, "fields": { "left": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true }, { "type": "_simple_numeric", "named": true } ] }, "operator": { "multiple": false, "required": true, "types": [ { "type": "!=", "named": false }, { "type": "!~", "named": false }, { "type": "%", "named": false }, { "type": "&", "named": false }, { "type": "&&", "named": false }, { "type": "*", "named": false }, { "type": "**", "named": false }, { "type": "+", "named": false }, { "type": "-", "named": false }, { "type": "/", "named": false }, { "type": "<", "named": false }, { "type": "<<", "named": false }, { "type": "<=", "named": false }, { "type": "<=>", "named": false }, { "type": "==", "named": false }, { "type": "===", "named": false }, { "type": "=~", "named": false }, { "type": ">", "named": false }, { "type": ">=", "named": false }, { "type": ">>", "named": false }, { "type": "^", "named": false }, { "type": "and", "named": false }, { "type": "or", "named": false }, { "type": "|", "named": false }, { "type": "||", "named": false } ] }, "right": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "block", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "block_body", "named": true } ] }, "parameters": { "multiple": false, "required": false, "types": [ { "type": "block_parameters", "named": true } ] } } }, { "type": "block_argument", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true } ] } }, { "type": "block_body", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "block_parameter", "named": true, "fields": { "name": { "multiple": false, "required": false, "types": [ { "type": "identifier", "named": true } ] } } }, { "type": "block_parameters", "named": true, "fields": { "locals": { "multiple": true, "required": false, "types": [ { "type": "identifier", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "block_parameter", "named": true }, { "type": "destructured_parameter", "named": true }, { "type": "forward_parameter", "named": true }, { "type": "hash_splat_nil", "named": true }, { "type": "hash_splat_parameter", "named": true }, { "type": "identifier", "named": true }, { "type": "keyword_parameter", "named": true }, { "type": "optional_parameter", "named": true }, { "type": "splat_parameter", "named": true } ] } }, { "type": "body_statement", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_statement", "named": true }, { "type": "else", "named": true }, { "type": "empty_statement", "named": true }, { "type": "ensure", "named": true }, { "type": "rescue", "named": true } ] } }, { "type": "break", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "argument_list", "named": true } ] } }, { "type": "call", "named": true, "fields": { "arguments": { "multiple": false, "required": false, "types": [ { "type": "argument_list", "named": true } ] }, "block": { "multiple": false, "required": false, "types": [ { "type": "block", "named": true }, { "type": "do_block", "named": true } ] }, "method": { "multiple": false, "required": false, "types": [ { "type": "_variable", "named": true }, { "type": "operator", "named": true } ] }, "operator": { "multiple": false, "required": false, "types": [ { "type": "_call_operator", "named": true } ] }, "receiver": { "multiple": false, "required": false, "types": [ { "type": "_primary", "named": true } ] } } }, { "type": "case", "named": true, "fields": { "value": { "multiple": false, "required": false, "types": [ { "type": "_statement", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "else", "named": true }, { "type": "when", "named": true } ] } }, { "type": "case_match", "named": true, "fields": { "clauses": { "multiple": true, "required": true, "types": [ { "type": "in_clause", "named": true } ] }, "else": { "multiple": false, "required": false, "types": [ { "type": "else", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] } } }, { "type": "chained_string", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "string", "named": true } ] } }, { "type": "class", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "body_statement", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "constant", "named": true }, { "type": "scope_resolution", "named": true } ] }, "superclass": { "multiple": false, "required": false, "types": [ { "type": "superclass", "named": true } ] } } }, { "type": "complex", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "float", "named": true }, { "type": "integer", "named": true }, { "type": "rational", "named": true } ] } }, { "type": "conditional", "named": true, "fields": { "alternative": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true } ] }, "consequence": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true } ] } } }, { "type": "constant", "named": true, "fields": {} }, { "type": "delimited_symbol", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "escape_sequence", "named": true }, { "type": "interpolation", "named": true }, { "type": "string_content", "named": true } ] } }, { "type": "destructured_left_assignment", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_lhs", "named": true }, { "type": "destructured_left_assignment", "named": true }, { "type": "rest_assignment", "named": true } ] } }, { "type": "destructured_parameter", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "block_parameter", "named": true }, { "type": "destructured_parameter", "named": true }, { "type": "forward_parameter", "named": true }, { "type": "hash_splat_nil", "named": true }, { "type": "hash_splat_parameter", "named": true }, { "type": "identifier", "named": true }, { "type": "keyword_parameter", "named": true }, { "type": "optional_parameter", "named": true }, { "type": "splat_parameter", "named": true } ] } }, { "type": "do", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "do_block", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "body_statement", "named": true } ] }, "parameters": { "multiple": false, "required": false, "types": [ { "type": "block_parameters", "named": true } ] } } }, { "type": "element_reference", "named": true, "fields": { "block": { "multiple": false, "required": false, "types": [ { "type": "block", "named": true }, { "type": "do_block", "named": true } ] }, "object": { "multiple": false, "required": true, "types": [ { "type": "_primary", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "_expression", "named": true }, { "type": "block_argument", "named": true }, { "type": "forward_argument", "named": true }, { "type": "hash_splat_argument", "named": true }, { "type": "pair", "named": true }, { "type": "splat_argument", "named": true } ] } }, { "type": "else", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "elsif", "named": true, "fields": { "alternative": { "multiple": false, "required": false, "types": [ { "type": "else", "named": true }, { "type": "elsif", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] }, "consequence": { "multiple": false, "required": false, "types": [ { "type": "then", "named": true } ] } } }, { "type": "empty_statement", "named": true, "fields": {} }, { "type": "end_block", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "ensure", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "exception_variable", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "_lhs", "named": true } ] } }, { "type": "exceptions", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_arg", "named": true }, { "type": "splat_argument", "named": true } ] } }, { "type": "expression_reference_pattern", "named": true, "fields": { "value": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "find_pattern", "named": true, "fields": { "class": { "multiple": false, "required": false, "types": [ { "type": "_pattern_constant", "named": true } ] } }, "children": { "multiple": true, "required": true, "types": [ { "type": "_pattern_expr", "named": true }, { "type": "splat_parameter", "named": true } ] } }, { "type": "for", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "do", "named": true } ] }, "pattern": { "multiple": false, "required": true, "types": [ { "type": "_lhs", "named": true }, { "type": "left_assignment_list", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "in", "named": true } ] } } }, { "type": "forward_argument", "named": true, "fields": {} }, { "type": "forward_parameter", "named": true, "fields": {} }, { "type": "hash", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "hash_splat_argument", "named": true }, { "type": "pair", "named": true } ] } }, { "type": "hash_key_symbol", "named": true, "fields": {} }, { "type": "hash_pattern", "named": true, "fields": { "class": { "multiple": false, "required": false, "types": [ { "type": "_pattern_constant", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "hash_splat_nil", "named": true }, { "type": "hash_splat_parameter", "named": true }, { "type": "keyword_pattern", "named": true } ] } }, { "type": "hash_splat_argument", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true } ] } }, { "type": "hash_splat_nil", "named": true, "fields": {} }, { "type": "hash_splat_parameter", "named": true, "fields": { "name": { "multiple": false, "required": false, "types": [ { "type": "identifier", "named": true } ] } } }, { "type": "heredoc_body", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "escape_sequence", "named": true }, { "type": "heredoc_content", "named": true }, { "type": "heredoc_end", "named": true }, { "type": "interpolation", "named": true } ] } }, { "type": "identifier", "named": true, "fields": {} }, { "type": "if", "named": true, "fields": { "alternative": { "multiple": false, "required": false, "types": [ { "type": "else", "named": true }, { "type": "elsif", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] }, "consequence": { "multiple": false, "required": false, "types": [ { "type": "then", "named": true } ] } } }, { "type": "if_guard", "named": true, "fields": { "condition": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "if_modifier", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "in", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true } ] } }, { "type": "in_clause", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "then", "named": true } ] }, "guard": { "multiple": false, "required": false, "types": [ { "type": "if_guard", "named": true }, { "type": "unless_guard", "named": true } ] }, "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern_top_expr_body", "named": true } ] } } }, { "type": "interpolation", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_nonlocal_variable", "named": true }, { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "keyword_parameter", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true } ] }, "value": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true } ] } } }, { "type": "keyword_pattern", "named": true, "fields": { "key": { "multiple": false, "required": true, "types": [ { "type": "hash_key_symbol", "named": true }, { "type": "string", "named": true } ] }, "value": { "multiple": false, "required": false, "types": [ { "type": "_pattern_expr", "named": true } ] } } }, { "type": "lambda", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "do_block", "named": true } ] }, "parameters": { "multiple": false, "required": false, "types": [ { "type": "lambda_parameters", "named": true } ] } } }, { "type": "lambda_parameters", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "block_parameter", "named": true }, { "type": "destructured_parameter", "named": true }, { "type": "forward_parameter", "named": true }, { "type": "hash_splat_nil", "named": true }, { "type": "hash_splat_parameter", "named": true }, { "type": "identifier", "named": true }, { "type": "keyword_parameter", "named": true }, { "type": "optional_parameter", "named": true }, { "type": "splat_parameter", "named": true } ] } }, { "type": "left_assignment_list", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_lhs", "named": true }, { "type": "destructured_left_assignment", "named": true }, { "type": "rest_assignment", "named": true } ] } }, { "type": "match_pattern", "named": true, "fields": { "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern_top_expr_body", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true } ] } } }, { "type": "method", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true }, { "type": "body_statement", "named": true }, { "type": "rescue_modifier", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "_method_name", "named": true } ] }, "parameters": { "multiple": false, "required": false, "types": [ { "type": "method_parameters", "named": true } ] } } }, { "type": "method_parameters", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "block_parameter", "named": true }, { "type": "destructured_parameter", "named": true }, { "type": "forward_parameter", "named": true }, { "type": "hash_splat_nil", "named": true }, { "type": "hash_splat_parameter", "named": true }, { "type": "identifier", "named": true }, { "type": "keyword_parameter", "named": true }, { "type": "optional_parameter", "named": true }, { "type": "splat_parameter", "named": true } ] } }, { "type": "module", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "body_statement", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "constant", "named": true }, { "type": "scope_resolution", "named": true } ] } } }, { "type": "next", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "argument_list", "named": true } ] } }, { "type": "nil", "named": true, "fields": {} }, { "type": "operator", "named": true, "fields": {} }, { "type": "operator_assignment", "named": true, "fields": { "left": { "multiple": false, "required": true, "types": [ { "type": "_lhs", "named": true } ] }, "operator": { "multiple": false, "required": true, "types": [ { "type": "%=", "named": false }, { "type": "&&=", "named": false }, { "type": "&=", "named": false }, { "type": "**=", "named": false }, { "type": "*=", "named": false }, { "type": "+=", "named": false }, { "type": "-=", "named": false }, { "type": "/=", "named": false }, { "type": "<<=", "named": false }, { "type": ">>=", "named": false }, { "type": "^=", "named": false }, { "type": "|=", "named": false }, { "type": "||=", "named": false } ] }, "right": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true }, { "type": "rescue_modifier", "named": true } ] } } }, { "type": "optional_parameter", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true } ] } } }, { "type": "pair", "named": true, "fields": { "key": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true }, { "type": "hash_key_symbol", "named": true }, { "type": "string", "named": true } ] }, "value": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true } ] } } }, { "type": "parenthesized_pattern", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "_pattern_expr", "named": true } ] } }, { "type": "parenthesized_statements", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "pattern", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true }, { "type": "splat_argument", "named": true } ] } }, { "type": "program", "named": true, "root": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true }, { "type": "uninterpreted", "named": true } ] } }, { "type": "range", "named": true, "fields": { "begin": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true }, { "type": "_pattern_primitive", "named": true } ] }, "end": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true }, { "type": "_pattern_primitive", "named": true } ] }, "operator": { "multiple": false, "required": true, "types": [ { "type": "..", "named": false }, { "type": "...", "named": false } ] } } }, { "type": "rational", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "float", "named": true }, { "type": "integer", "named": true } ] } }, { "type": "redo", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "argument_list", "named": true } ] } }, { "type": "regex", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "escape_sequence", "named": true }, { "type": "interpolation", "named": true }, { "type": "string_content", "named": true } ] } }, { "type": "rescue", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "then", "named": true } ] }, "exceptions": { "multiple": false, "required": false, "types": [ { "type": "exceptions", "named": true } ] }, "variable": { "multiple": false, "required": false, "types": [ { "type": "exception_variable", "named": true } ] } } }, { "type": "rescue_modifier", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true }, { "type": "_statement", "named": true } ] }, "handler": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "rest_assignment", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "_lhs", "named": true } ] } }, { "type": "retry", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "argument_list", "named": true } ] } }, { "type": "return", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "argument_list", "named": true } ] } }, { "type": "right_assignment_list", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_arg", "named": true }, { "type": "splat_argument", "named": true } ] } }, { "type": "scope_resolution", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "constant", "named": true } ] }, "scope": { "multiple": false, "required": false, "types": [ { "type": "_pattern_constant", "named": true }, { "type": "_primary", "named": true } ] } } }, { "type": "setter", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true } ] } } }, { "type": "singleton_class", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "body_statement", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true } ] } } }, { "type": "singleton_method", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true }, { "type": "body_statement", "named": true }, { "type": "rescue_modifier", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "_method_name", "named": true } ] }, "object": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true }, { "type": "_variable", "named": true } ] }, "parameters": { "multiple": false, "required": false, "types": [ { "type": "method_parameters", "named": true } ] } } }, { "type": "splat_argument", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "_arg", "named": true } ] } }, { "type": "splat_parameter", "named": true, "fields": { "name": { "multiple": false, "required": false, "types": [ { "type": "identifier", "named": true } ] } } }, { "type": "string", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "escape_sequence", "named": true }, { "type": "interpolation", "named": true }, { "type": "string_content", "named": true } ] } }, { "type": "string_array", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "bare_string", "named": true } ] } }, { "type": "subshell", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "escape_sequence", "named": true }, { "type": "interpolation", "named": true }, { "type": "string_content", "named": true } ] } }, { "type": "superclass", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } }, { "type": "symbol_array", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "bare_symbol", "named": true } ] } }, { "type": "test_pattern", "named": true, "fields": { "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern_top_expr_body", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "_arg", "named": true } ] } } }, { "type": "then", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_statement", "named": true }, { "type": "empty_statement", "named": true } ] } }, { "type": "unary", "named": true, "fields": { "operand": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true }, { "type": "_simple_numeric", "named": true }, { "type": "parenthesized_statements", "named": true } ] }, "operator": { "multiple": false, "required": true, "types": [ { "type": "!", "named": false }, { "type": "+", "named": false }, { "type": "-", "named": false }, { "type": "defined?", "named": false }, { "type": "not", "named": false }, { "type": "~", "named": false } ] } } }, { "type": "undef", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_method_name", "named": true } ] } }, { "type": "unless", "named": true, "fields": { "alternative": { "multiple": false, "required": false, "types": [ { "type": "else", "named": true }, { "type": "elsif", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] }, "consequence": { "multiple": false, "required": false, "types": [ { "type": "then", "named": true } ] } } }, { "type": "unless_guard", "named": true, "fields": { "condition": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "unless_modifier", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "until", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "do", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] } } }, { "type": "until_modifier", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "variable_reference_pattern", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "_nonlocal_variable", "named": true }, { "type": "identifier", "named": true } ] } } }, { "type": "when", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "then", "named": true } ] }, "pattern": { "multiple": true, "required": true, "types": [ { "type": "pattern", "named": true } ] } } }, { "type": "while", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "do", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] } } }, { "type": "while_modifier", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "_statement", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "_expression", "named": true } ] } } }, { "type": "yield", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "argument_list", "named": true } ] } }, { "type": "!", "named": false }, { "type": "!=", "named": false }, { "type": "!~", "named": false }, { "type": "\"", "named": false }, { "type": "#{", "named": false }, { "type": "%", "named": false }, { "type": "%=", "named": false }, { "type": "%i(", "named": false }, { "type": "%w(", "named": false }, { "type": "&", "named": false }, { "type": "&&", "named": false }, { "type": "&&=", "named": false }, { "type": "&.", "named": false }, { "type": "&=", "named": false }, { "type": "(", "named": false }, { "type": ")", "named": false }, { "type": "*", "named": false }, { "type": "**", "named": false }, { "type": "**=", "named": false }, { "type": "*=", "named": false }, { "type": "+", "named": false }, { "type": "+=", "named": false }, { "type": "+@", "named": false }, { "type": ",", "named": false }, { "type": "-", "named": false }, { "type": "-=", "named": false }, { "type": "->", "named": false }, { "type": "-@", "named": false }, { "type": ".", "named": false }, { "type": "..", "named": false }, { "type": "...", "named": false }, { "type": "/", "named": false }, { "type": "/=", "named": false }, { "type": ":", "named": false }, { "type": ":\"", "named": false }, { "type": "::", "named": false }, { "type": ";", "named": false }, { "type": "<", "named": false }, { "type": "<<", "named": false }, { "type": "<<=", "named": false }, { "type": "<=", "named": false }, { "type": "<=>", "named": false }, { "type": "=", "named": false }, { "type": "==", "named": false }, { "type": "===", "named": false }, { "type": "=>", "named": false }, { "type": "=~", "named": false }, { "type": ">", "named": false }, { "type": ">=", "named": false }, { "type": ">>", "named": false }, { "type": ">>=", "named": false }, { "type": "?", "named": false }, { "type": "BEGIN", "named": false }, { "type": "END", "named": false }, { "type": "[", "named": false }, { "type": "[]", "named": false }, { "type": "[]=", "named": false }, { "type": "]", "named": false }, { "type": "^", "named": false }, { "type": "^=", "named": false }, { "type": "`", "named": false }, { "type": "alias", "named": false }, { "type": "and", "named": false }, { "type": "begin", "named": false }, { "type": "break", "named": false }, { "type": "case", "named": false }, { "type": "character", "named": true }, { "type": "class", "named": false }, { "type": "class_variable", "named": true }, { "type": "comment", "named": true }, { "type": "def", "named": false }, { "type": "defined?", "named": false }, { "type": "do", "named": false }, { "type": "else", "named": false }, { "type": "elsif", "named": false }, { "type": "encoding", "named": true }, { "type": "end", "named": false }, { "type": "ensure", "named": false }, { "type": "escape_sequence", "named": true }, { "type": "false", "named": true }, { "type": "file", "named": true }, { "type": "float", "named": true }, { "type": "for", "named": false }, { "type": "global_variable", "named": true }, { "type": "heredoc_beginning", "named": true }, { "type": "heredoc_content", "named": true }, { "type": "heredoc_end", "named": true }, { "type": "i", "named": false }, { "type": "if", "named": false }, { "type": "in", "named": false }, { "type": "instance_variable", "named": true }, { "type": "integer", "named": true }, { "type": "line", "named": true }, { "type": "module", "named": false }, { "type": "next", "named": false }, { "type": "nil", "named": false }, { "type": "not", "named": false }, { "type": "or", "named": false }, { "type": "r", "named": false }, { "type": "redo", "named": false }, { "type": "rescue", "named": false }, { "type": "retry", "named": false }, { "type": "return", "named": false }, { "type": "ri", "named": false }, { "type": "self", "named": true }, { "type": "simple_symbol", "named": true }, { "type": "string_content", "named": true }, { "type": "super", "named": true }, { "type": "then", "named": false }, { "type": "true", "named": true }, { "type": "undef", "named": false }, { "type": "uninterpreted", "named": true }, { "type": "unless", "named": false }, { "type": "until", "named": false }, { "type": "when", "named": false }, { "type": "while", "named": false }, { "type": "yield", "named": false }, { "type": "{", "named": false }, { "type": "|", "named": false }, { "type": "|=", "named": false }, { "type": "||", "named": false }, { "type": "||=", "named": false }, { "type": "}", "named": false }, { "type": "~", "named": false }, { "type": "~@", "named": false } ] ================================================ FILE: src/parser.c ================================================ [File too large to display: 14.6 MB] ================================================ FILE: src/scanner.c ================================================ #include "tree_sitter/alloc.h" #include "tree_sitter/array.h" #include "tree_sitter/parser.h" #include #include typedef enum { LINE_BREAK, NO_LINE_BREAK, // Delimited literals SIMPLE_SYMBOL, STRING_START, SYMBOL_START, SUBSHELL_START, REGEX_START, STRING_ARRAY_START, SYMBOL_ARRAY_START, HEREDOC_BODY_START, STRING_CONTENT, HEREDOC_CONTENT, STRING_END, HEREDOC_BODY_END, HEREDOC_START, // Whitespace-sensitive tokens FORWARD_SLASH, BLOCK_AMPERSAND, SPLAT_STAR, UNARY_MINUS, UNARY_MINUS_NUM, BINARY_MINUS, BINARY_STAR, SINGLETON_CLASS_LEFT_ANGLE_LEFT_ANGLE, HASH_KEY_SYMBOL, IDENTIFIER_SUFFIX, CONSTANT_SUFFIX, HASH_SPLAT_STAR_STAR, BINARY_STAR_STAR, ELEMENT_REFERENCE_BRACKET, SHORT_INTERPOLATION, NONE } TokenType; typedef Array(char) String; typedef struct { TokenType type; int32_t open_delimiter; int32_t close_delimiter; int32_t nesting_depth; bool allows_interpolation; } Literal; typedef struct { String word; bool end_word_indentation_allowed; bool allows_interpolation; bool started; } Heredoc; typedef struct { bool has_leading_whitespace; Array(Literal) literal_stack; Array(Heredoc) open_heredocs; } Scanner; const char NON_IDENTIFIER_CHARS[] = { '\0', '\n', '\r', '\t', ' ', ':', ';', '`', '"', '\'', '@', '$', '#', '.', ',', '|', '^', '&', '<', '=', '>', '+', '-', '*', '/', '\\', '%', '?', '!', '~', '(', ')', '[', ']', '{', '}', }; static inline void skip(Scanner *scanner, TSLexer *lexer) { scanner->has_leading_whitespace = true; lexer->advance(lexer, true); } static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); } static inline void reset(Scanner *scanner) { array_delete(&scanner->literal_stack); for (uint32_t i = 0; i < scanner->open_heredocs.size; i++) { array_delete(&array_get(&scanner->open_heredocs, i)->word); } array_delete(&scanner->open_heredocs); } static inline unsigned serialize(Scanner *scanner, char *buffer) { unsigned size = 0; if (scanner->literal_stack.size * 5 + 2 >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) { return 0; } buffer[size++] = (char)scanner->literal_stack.size; for (uint32_t i = 0; i < scanner->literal_stack.size; i++) { Literal *literal = array_get(&scanner->literal_stack, i); buffer[size++] = literal->type; buffer[size++] = (char)literal->open_delimiter; buffer[size++] = (char)literal->close_delimiter; buffer[size++] = (char)literal->nesting_depth; buffer[size++] = (char)literal->allows_interpolation; } buffer[size++] = (char)scanner->open_heredocs.size; for (uint32_t i = 0; i < scanner->open_heredocs.size; i++) { Heredoc *heredoc = array_get(&scanner->open_heredocs, i); if (size + 3 + sizeof(uint32_t) + heredoc->word.size >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) { return 0; } buffer[size++] = (char)heredoc->end_word_indentation_allowed; buffer[size++] = (char)heredoc->allows_interpolation; buffer[size++] = (char)heredoc->started; memcpy(&buffer[size], &heredoc->word.size, sizeof(uint32_t)); size += sizeof(uint32_t); memcpy(&buffer[size], heredoc->word.contents, heredoc->word.size); size += heredoc->word.size; } return size; } static inline void deserialize(Scanner *scanner, const char *buffer, unsigned length) { unsigned size = 0; scanner->has_leading_whitespace = false; reset(scanner); if (length == 0) { return; } uint8_t literal_depth = buffer[size++]; for (unsigned j = 0; j < literal_depth; j++) { Literal literal = {0}; literal.type = (TokenType)(buffer[size++]); literal.open_delimiter = (unsigned char)buffer[size++]; literal.close_delimiter = (unsigned char)buffer[size++]; literal.nesting_depth = (unsigned char)buffer[size++]; literal.allows_interpolation = buffer[size++]; array_push(&scanner->literal_stack, literal); } uint8_t open_heredoc_count = buffer[size++]; for (unsigned j = 0; j < open_heredoc_count; j++) { Heredoc heredoc = {0}; heredoc.end_word_indentation_allowed = buffer[size++]; heredoc.allows_interpolation = buffer[size++]; heredoc.started = buffer[size++]; heredoc.word = (String)array_new(); uint32_t word_length; memcpy(&word_length, &buffer[size], sizeof(uint32_t)); size += sizeof(uint32_t); array_reserve(&heredoc.word, word_length); memcpy(heredoc.word.contents, &buffer[size], word_length); heredoc.word.size = word_length; size += word_length; array_push(&scanner->open_heredocs, heredoc); } assert(size == length); } static inline bool scan_whitespace(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) { bool heredoc_body_start_is_valid = scanner->open_heredocs.size > 0 && !scanner->open_heredocs.contents[0].started && valid_symbols[HEREDOC_BODY_START]; bool crossed_newline = false; for (;;) { if (!valid_symbols[NO_LINE_BREAK] && valid_symbols[LINE_BREAK] && lexer->is_at_included_range_start(lexer)) { lexer->mark_end(lexer); lexer->result_symbol = LINE_BREAK; return true; } switch (lexer->lookahead) { case ' ': case '\t': skip(scanner, lexer); break; case '\r': if (heredoc_body_start_is_valid) { lexer->result_symbol = HEREDOC_BODY_START; scanner->open_heredocs.contents[0].started = true; return true; } else { skip(scanner, lexer); break; } case '\n': if (heredoc_body_start_is_valid) { lexer->result_symbol = HEREDOC_BODY_START; scanner->open_heredocs.contents[0].started = true; return true; } else if (!valid_symbols[NO_LINE_BREAK] && valid_symbols[LINE_BREAK] && !crossed_newline) { lexer->mark_end(lexer); advance(lexer); crossed_newline = true; } else { skip(scanner, lexer); } break; case '\\': advance(lexer); if (lexer->lookahead == '\r') { skip(scanner, lexer); } if (iswspace(lexer->lookahead)) { skip(scanner, lexer); } else { return false; } break; default: if (crossed_newline) { if (lexer->lookahead != '.' && lexer->lookahead != '&' && lexer->lookahead != '#') { lexer->result_symbol = LINE_BREAK; } else if (lexer->lookahead == '.') { // Don't return LINE_BREAK for the call operator (`.`) but do return one for range // operators // (`..` and `...`) advance(lexer); if (!lexer->eof(lexer) && lexer->lookahead == '.') { lexer->result_symbol = LINE_BREAK; } else { return false; } } } return true; } } } static inline bool scan_operator(TSLexer *lexer) { switch (lexer->lookahead) { // <, <=, <<, <=> case '<': advance(lexer); if (lexer->lookahead == '<') { advance(lexer); } else if (lexer->lookahead == '=') { advance(lexer); if (lexer->lookahead == '>') { advance(lexer); } } return true; // >, >=, >> case '>': advance(lexer); if (lexer->lookahead == '>' || lexer->lookahead == '=') { advance(lexer); } return true; // ==, ===, =~ case '=': advance(lexer); if (lexer->lookahead == '~') { advance(lexer); return true; } if (lexer->lookahead == '=') { advance(lexer); if (lexer->lookahead == '=') { advance(lexer); } return true; } return false; // +, -, ~, +@, -@, ~@ case '+': case '-': case '~': advance(lexer); if (lexer->lookahead == '@') { advance(lexer); } return true; // .. case '.': advance(lexer); if (lexer->lookahead == '.') { advance(lexer); return true; } return false; // &, ^, |, /, %` case '&': case '^': case '|': case '/': case '%': case '`': advance(lexer); return true; // !, !=, !~ case '!': advance(lexer); if (lexer->lookahead == '=' || lexer->lookahead == '~') { advance(lexer); } return true; // *, ** case '*': advance(lexer); if (lexer->lookahead == '*') { advance(lexer); } return true; // [], []= case '[': advance(lexer); if (lexer->lookahead == ']') { advance(lexer); } else { return false; } if (lexer->lookahead == '=') { advance(lexer); } return true; default: return false; } } static inline bool is_iden_char(char c) { return memchr(&NON_IDENTIFIER_CHARS, c, sizeof(NON_IDENTIFIER_CHARS)) == NULL; } static inline bool scan_symbol_identifier(TSLexer *lexer) { if (lexer->lookahead == '@') { advance(lexer); if (lexer->lookahead == '@') { advance(lexer); } } else if (lexer->lookahead == '$') { advance(lexer); } if (is_iden_char((char)lexer->lookahead)) { advance(lexer); } else if (!scan_operator(lexer)) { return false; } while (is_iden_char((char)lexer->lookahead)) { advance(lexer); } if (lexer->lookahead == '?' || lexer->lookahead == '!') { advance(lexer); } if (lexer->lookahead == '=') { lexer->mark_end(lexer); advance(lexer); if (lexer->lookahead != '>') { lexer->mark_end(lexer); } } return true; } static inline bool scan_open_delimiter(Scanner *scanner, TSLexer *lexer, Literal *literal, const bool *valid_symbols) { switch (lexer->lookahead) { case '"': literal->type = STRING_START; literal->open_delimiter = literal->close_delimiter = lexer->lookahead; literal->allows_interpolation = true; advance(lexer); return true; case '\'': literal->type = STRING_START; literal->open_delimiter = literal->close_delimiter = lexer->lookahead; literal->allows_interpolation = false; advance(lexer); return true; case '`': if (!valid_symbols[SUBSHELL_START]) { return false; } literal->type = SUBSHELL_START; literal->open_delimiter = literal->close_delimiter = lexer->lookahead; literal->allows_interpolation = true; advance(lexer); return true; case '/': if (!valid_symbols[REGEX_START]) { return false; } literal->type = REGEX_START; literal->open_delimiter = literal->close_delimiter = lexer->lookahead; literal->allows_interpolation = true; advance(lexer); if (valid_symbols[FORWARD_SLASH]) { if (!scanner->has_leading_whitespace) { return false; } if (lexer->lookahead == ' ' || lexer->lookahead == '\t' || lexer->lookahead == '\n' || lexer->lookahead == '\r') { return false; } if (lexer->lookahead == '=') { return false; } } return true; case '%': advance(lexer); switch (lexer->lookahead) { case 's': if (!valid_symbols[SIMPLE_SYMBOL]) { return false; } literal->type = SYMBOL_START; literal->allows_interpolation = false; advance(lexer); break; case 'r': if (!valid_symbols[REGEX_START]) { return false; } literal->type = REGEX_START; literal->allows_interpolation = true; advance(lexer); break; case 'x': if (!valid_symbols[SUBSHELL_START]) { return false; } literal->type = SUBSHELL_START; literal->allows_interpolation = true; advance(lexer); break; case 'q': if (!valid_symbols[STRING_START]) { return false; } literal->type = STRING_START; literal->allows_interpolation = false; advance(lexer); break; case 'Q': if (!valid_symbols[STRING_START]) { return false; } literal->type = STRING_START; literal->allows_interpolation = true; advance(lexer); break; case 'w': if (!valid_symbols[STRING_ARRAY_START]) { return false; } literal->type = STRING_ARRAY_START; literal->allows_interpolation = false; advance(lexer); break; case 'i': if (!valid_symbols[SYMBOL_ARRAY_START]) { return false; } literal->type = SYMBOL_ARRAY_START; literal->allows_interpolation = false; advance(lexer); break; case 'W': if (!valid_symbols[STRING_ARRAY_START]) { return false; } literal->type = STRING_ARRAY_START; literal->allows_interpolation = true; advance(lexer); break; case 'I': if (!valid_symbols[SYMBOL_ARRAY_START]) { return false; } literal->type = SYMBOL_ARRAY_START; literal->allows_interpolation = true; advance(lexer); break; default: if (!valid_symbols[STRING_START]) { return false; } literal->type = STRING_START; literal->allows_interpolation = true; break; } switch (lexer->lookahead) { case '(': literal->open_delimiter = '('; literal->close_delimiter = ')'; break; case '[': literal->open_delimiter = '['; literal->close_delimiter = ']'; break; case '{': literal->open_delimiter = '{'; literal->close_delimiter = '}'; break; case '<': literal->open_delimiter = '<'; literal->close_delimiter = '>'; break; case '\r': case '\n': case ' ': case '\t': // If the `/` operator is valid, then so is the `%` operator, which means // that a `%` followed by whitespace should be considered an operator, // not a percent string. if (valid_symbols[FORWARD_SLASH]) { return false; } break; case '|': case '!': case '#': case '/': case '\\': case '@': case '$': case '%': case '^': case '&': case '*': case ')': case ']': case '}': case '>': // TODO: Implement %= as external rule and re-enable = as a valid // unbalanced delimiter. That will be necessary due to ambiguity // between &= assignment operator and %=...= as string // content delimiter. // case '=': case '+': case '-': case '~': case '`': case ',': case '.': case '?': case ':': case ';': case '_': case '"': case '\'': literal->open_delimiter = lexer->lookahead; literal->close_delimiter = lexer->lookahead; break; default: return false; } advance(lexer); return true; default: return false; } } static inline void scan_heredoc_word(TSLexer *lexer, Heredoc *heredoc) { String word = array_new(); int32_t quote = 0; switch (lexer->lookahead) { case '\'': case '"': case '`': quote = lexer->lookahead; advance(lexer); while (lexer->lookahead != quote && !lexer->eof(lexer)) { array_push(&word, lexer->lookahead); advance(lexer); } advance(lexer); break; default: if (iswalnum(lexer->lookahead) || lexer->lookahead == '_') { array_push(&word, lexer->lookahead); advance(lexer); while (iswalnum(lexer->lookahead) || lexer->lookahead == '_') { array_push(&word, lexer->lookahead); advance(lexer); } } break; } heredoc->word = word; heredoc->allows_interpolation = quote != '\''; } static inline bool scan_short_interpolation(TSLexer *lexer, const bool has_content, const TSSymbol content_symbol) { char start = (char)lexer->lookahead; if (start == '@' || start == '$') { if (has_content) { lexer->result_symbol = content_symbol; return true; } lexer->mark_end(lexer); advance(lexer); bool is_short_interpolation = false; if (start == '$') { if (strchr("!@&`'+~=/\\,;.<>*$?:\"", lexer->lookahead) != NULL) { is_short_interpolation = true; } else { if (lexer->lookahead == '-') { advance(lexer); is_short_interpolation = iswalpha(lexer->lookahead) || lexer->lookahead == '_'; } else { is_short_interpolation = iswalnum(lexer->lookahead) || lexer->lookahead == '_'; } } } if (start == '@') { if (lexer->lookahead == '@') { advance(lexer); } is_short_interpolation = is_iden_char((char)lexer->lookahead) && !iswdigit(lexer->lookahead); } if (is_short_interpolation) { lexer->result_symbol = SHORT_INTERPOLATION; return true; } } return false; } static inline bool scan_heredoc_content(Scanner *scanner, TSLexer *lexer) { Heredoc *heredoc = array_get(&scanner->open_heredocs, 0); size_t position_in_word = 0; bool look_for_heredoc_end = true; bool has_content = false; for (;;) { if (position_in_word == heredoc->word.size) { if (!has_content) { lexer->mark_end(lexer); } while (lexer->lookahead == ' ' || lexer->lookahead == '\t') { advance(lexer); } if (lexer->lookahead == '\n' || lexer->lookahead == '\r') { if (has_content) { lexer->result_symbol = HEREDOC_CONTENT; } else { array_delete(&heredoc->word); array_erase(&scanner->open_heredocs, 0); lexer->result_symbol = HEREDOC_BODY_END; } return true; } has_content = true; position_in_word = 0; } if (lexer->eof(lexer)) { lexer->mark_end(lexer); if (has_content) { lexer->result_symbol = HEREDOC_CONTENT; } else { array_delete(&heredoc->word); array_erase(&scanner->open_heredocs, 0); lexer->result_symbol = HEREDOC_BODY_END; } return true; } if (lexer->lookahead == *array_get(&heredoc->word, position_in_word) && look_for_heredoc_end) { advance(lexer); position_in_word++; } else { position_in_word = 0; look_for_heredoc_end = false; if (heredoc->allows_interpolation && lexer->lookahead == '\\') { if (has_content) { lexer->result_symbol = HEREDOC_CONTENT; return true; } return false; } if (heredoc->allows_interpolation && lexer->lookahead == '#') { lexer->mark_end(lexer); advance(lexer); if (lexer->lookahead == '{') { if (has_content) { lexer->result_symbol = HEREDOC_CONTENT; return true; } return false; } if (scan_short_interpolation(lexer, has_content, HEREDOC_CONTENT)) { return true; } } else if (lexer->lookahead == '\r' || lexer->lookahead == '\n') { if (lexer->lookahead == '\r') { advance(lexer); if (lexer->lookahead == '\n') { advance(lexer); } } else { advance(lexer); } has_content = true; look_for_heredoc_end = true; while (lexer->lookahead == ' ' || lexer->lookahead == '\t') { advance(lexer); if (!heredoc->end_word_indentation_allowed) { look_for_heredoc_end = false; } } lexer->mark_end(lexer); } else { has_content = true; advance(lexer); lexer->mark_end(lexer); } } } } static inline bool scan_literal_content(Scanner *scanner, TSLexer *lexer) { Literal *literal = array_back(&scanner->literal_stack); bool has_content = false; bool stop_on_space = literal->type == SYMBOL_ARRAY_START || literal->type == STRING_ARRAY_START; for (;;) { if (stop_on_space && iswspace(lexer->lookahead)) { if (has_content) { lexer->mark_end(lexer); lexer->result_symbol = STRING_CONTENT; return true; } return false; } if (lexer->lookahead == literal->close_delimiter) { lexer->mark_end(lexer); if (literal->nesting_depth == 1) { if (has_content) { lexer->result_symbol = STRING_CONTENT; } else { advance(lexer); if (literal->type == REGEX_START) { while (iswlower(lexer->lookahead)) { advance(lexer); } } array_pop(&scanner->literal_stack); lexer->result_symbol = STRING_END; lexer->mark_end(lexer); } return true; } literal->nesting_depth--; advance(lexer); } else if (lexer->lookahead == literal->open_delimiter) { literal->nesting_depth++; advance(lexer); } else if (literal->allows_interpolation && lexer->lookahead == '#') { lexer->mark_end(lexer); advance(lexer); if (lexer->lookahead == '{') { if (has_content) { lexer->result_symbol = STRING_CONTENT; return true; } return false; } if (scan_short_interpolation(lexer, has_content, STRING_CONTENT)) { return true; } } else if (lexer->lookahead == '\\') { if (literal->allows_interpolation) { if (has_content) { lexer->mark_end(lexer); lexer->result_symbol = STRING_CONTENT; return true; } return false; } advance(lexer); advance(lexer); } else if (lexer->eof(lexer)) { advance(lexer); lexer->mark_end(lexer); return false; } else { advance(lexer); } has_content = true; } } static inline bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) { scanner->has_leading_whitespace = false; // Contents of literals, which match any character except for some close delimiter if (!valid_symbols[STRING_START]) { if ((valid_symbols[STRING_CONTENT] || valid_symbols[STRING_END]) && scanner->literal_stack.size > 0) { return scan_literal_content(scanner, lexer); } if ((valid_symbols[HEREDOC_CONTENT] || valid_symbols[HEREDOC_BODY_END]) && scanner->open_heredocs.size > 0) { return scan_heredoc_content(scanner, lexer); } } // Whitespace lexer->result_symbol = NONE; if (!scan_whitespace(scanner, lexer, valid_symbols)) { return false; } if (lexer->result_symbol != NONE) { return true; } switch (lexer->lookahead) { case '&': if (valid_symbols[BLOCK_AMPERSAND]) { advance(lexer); if (lexer->lookahead != '&' && lexer->lookahead != '.' && lexer->lookahead != '=' && !iswspace(lexer->lookahead)) { lexer->result_symbol = BLOCK_AMPERSAND; return true; } return false; } break; case '<': if (valid_symbols[SINGLETON_CLASS_LEFT_ANGLE_LEFT_ANGLE]) { advance(lexer); if (lexer->lookahead == '<') { advance(lexer); lexer->result_symbol = SINGLETON_CLASS_LEFT_ANGLE_LEFT_ANGLE; return true; } return false; } break; case '*': if (valid_symbols[SPLAT_STAR] || valid_symbols[BINARY_STAR] || valid_symbols[HASH_SPLAT_STAR_STAR] || valid_symbols[BINARY_STAR_STAR]) { advance(lexer); if (lexer->lookahead == '=') { return false; } if (lexer->lookahead == '*') { if (valid_symbols[HASH_SPLAT_STAR_STAR] || valid_symbols[BINARY_STAR_STAR]) { advance(lexer); if (lexer->lookahead == '=') { return false; } if (valid_symbols[BINARY_STAR_STAR] && !scanner->has_leading_whitespace) { lexer->result_symbol = BINARY_STAR_STAR; return true; } if (valid_symbols[HASH_SPLAT_STAR_STAR] && !iswspace(lexer->lookahead)) { lexer->result_symbol = HASH_SPLAT_STAR_STAR; return true; } if (valid_symbols[BINARY_STAR_STAR]) { lexer->result_symbol = BINARY_STAR_STAR; return true; } if (valid_symbols[HASH_SPLAT_STAR_STAR]) { lexer->result_symbol = HASH_SPLAT_STAR_STAR; return true; } return false; } return false; } if (valid_symbols[BINARY_STAR] && !scanner->has_leading_whitespace) { lexer->result_symbol = BINARY_STAR; return true; } if (valid_symbols[SPLAT_STAR] && !iswspace(lexer->lookahead)) { lexer->result_symbol = SPLAT_STAR; return true; } if (valid_symbols[BINARY_STAR]) { lexer->result_symbol = BINARY_STAR; return true; } if (valid_symbols[SPLAT_STAR]) { lexer->result_symbol = SPLAT_STAR; return true; } return false; } break; case '-': if (valid_symbols[UNARY_MINUS] || valid_symbols[UNARY_MINUS_NUM] || valid_symbols[BINARY_MINUS]) { advance(lexer); if (lexer->lookahead != '=' && lexer->lookahead != '>') { if (valid_symbols[UNARY_MINUS_NUM] && (!valid_symbols[BINARY_STAR] || scanner->has_leading_whitespace) && iswdigit(lexer->lookahead)) { lexer->result_symbol = UNARY_MINUS_NUM; return true; } if (valid_symbols[UNARY_MINUS] && scanner->has_leading_whitespace && !iswspace(lexer->lookahead)) { lexer->result_symbol = UNARY_MINUS; } else if (valid_symbols[BINARY_MINUS]) { lexer->result_symbol = BINARY_MINUS; } else { lexer->result_symbol = UNARY_MINUS; } return true; } return false; } break; case ':': if (valid_symbols[SYMBOL_START]) { Literal literal = {0}; literal.type = SYMBOL_START; literal.nesting_depth = 1; advance(lexer); switch (lexer->lookahead) { case '"': advance(lexer); literal.open_delimiter = '"'; literal.close_delimiter = '"'; literal.allows_interpolation = true; array_push(&scanner->literal_stack, literal); lexer->result_symbol = SYMBOL_START; return true; case '\'': advance(lexer); literal.open_delimiter = '\''; literal.close_delimiter = '\''; literal.allows_interpolation = false; array_push(&scanner->literal_stack, literal); lexer->result_symbol = SYMBOL_START; return true; default: if (scan_symbol_identifier(lexer)) { lexer->result_symbol = SIMPLE_SYMBOL; return true; } } return false; } break; case '[': // Treat a square bracket as an element reference if either: // * the bracket is not preceded by any whitespace // * an arbitrary expression is not valid at the current position. if (valid_symbols[ELEMENT_REFERENCE_BRACKET] && (!scanner->has_leading_whitespace || !valid_symbols[STRING_START])) { advance(lexer); lexer->result_symbol = ELEMENT_REFERENCE_BRACKET; return true; } break; default: break; } // Open delimiters for literals if (((valid_symbols[HASH_KEY_SYMBOL] || valid_symbols[IDENTIFIER_SUFFIX]) && (iswalpha(lexer->lookahead) || lexer->lookahead == '_')) || (valid_symbols[CONSTANT_SUFFIX] && iswupper(lexer->lookahead))) { TokenType validIdentifierSymbol = iswupper(lexer->lookahead) ? CONSTANT_SUFFIX : IDENTIFIER_SUFFIX; while (iswalnum(lexer->lookahead) || lexer->lookahead == '_') { advance(lexer); } if (valid_symbols[HASH_KEY_SYMBOL] && lexer->lookahead == ':') { lexer->mark_end(lexer); advance(lexer); if (lexer->lookahead != ':') { lexer->result_symbol = HASH_KEY_SYMBOL; return true; } } else if (valid_symbols[validIdentifierSymbol] && lexer->lookahead == '!') { advance(lexer); if (lexer->lookahead != '=') { lexer->result_symbol = validIdentifierSymbol; return true; } } return false; } // Open delimiters for literals if (valid_symbols[STRING_START]) { Literal literal = {0}; literal.nesting_depth = 1; if (lexer->lookahead == '<') { advance(lexer); if (lexer->lookahead != '<') { return false; } advance(lexer); Heredoc heredoc = {0}; if (lexer->lookahead == '-' || lexer->lookahead == '~') { advance(lexer); heredoc.end_word_indentation_allowed = true; } scan_heredoc_word(lexer, &heredoc); if (heredoc.word.size == 0) { array_delete(&heredoc.word); return false; } array_push(&scanner->open_heredocs, heredoc); lexer->result_symbol = HEREDOC_START; return true; } if (scan_open_delimiter(scanner, lexer, &literal, valid_symbols)) { array_push(&scanner->literal_stack, literal); lexer->result_symbol = literal.type; return true; } return false; } return false; } void *tree_sitter_ruby_external_scanner_create() { Scanner *scanner = (Scanner *)ts_calloc(1, sizeof(Scanner)); return scanner; } bool tree_sitter_ruby_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { Scanner *scanner = (Scanner *)payload; return scan(scanner, lexer, valid_symbols); } unsigned tree_sitter_ruby_external_scanner_serialize(void *payload, char *buffer) { Scanner *scanner = (Scanner *)payload; return serialize(scanner, buffer); } void tree_sitter_ruby_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) { Scanner *scanner = (Scanner *)payload; deserialize(scanner, buffer, length); } void tree_sitter_ruby_external_scanner_destroy(void *payload) { Scanner *scanner = (Scanner *)payload; for (uint32_t i = 0; i < scanner->open_heredocs.size; i++) { array_delete(&array_get(&scanner->open_heredocs, i)->word); } array_delete(&scanner->open_heredocs); array_delete(&scanner->literal_stack); ts_free(scanner); } ================================================ FILE: src/tree_sitter/alloc.h ================================================ #ifndef TREE_SITTER_ALLOC_H_ #define TREE_SITTER_ALLOC_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include // Allow clients to override allocation functions #ifdef TREE_SITTER_REUSE_ALLOCATOR extern void *(*ts_current_malloc)(size_t size); extern void *(*ts_current_calloc)(size_t count, size_t size); extern void *(*ts_current_realloc)(void *ptr, size_t size); extern void (*ts_current_free)(void *ptr); #ifndef ts_malloc #define ts_malloc ts_current_malloc #endif #ifndef ts_calloc #define ts_calloc ts_current_calloc #endif #ifndef ts_realloc #define ts_realloc ts_current_realloc #endif #ifndef ts_free #define ts_free ts_current_free #endif #else #ifndef ts_malloc #define ts_malloc malloc #endif #ifndef ts_calloc #define ts_calloc calloc #endif #ifndef ts_realloc #define ts_realloc realloc #endif #ifndef ts_free #define ts_free free #endif #endif #ifdef __cplusplus } #endif #endif // TREE_SITTER_ALLOC_H_ ================================================ FILE: src/tree_sitter/array.h ================================================ #ifndef TREE_SITTER_ARRAY_H_ #define TREE_SITTER_ARRAY_H_ #ifdef __cplusplus extern "C" { #endif #include "./alloc.h" #include #include #include #include #include #ifdef _MSC_VER #pragma warning(disable : 4101) #elif defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" #endif #define Array(T) \ struct { \ T *contents; \ uint32_t size; \ uint32_t capacity; \ } /// Initialize an array. #define array_init(self) \ ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) /// Create an empty array. #define array_new() \ { NULL, 0, 0 } /// Get a pointer to the element at a given `index` in the array. #define array_get(self, _index) \ (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) /// Get a pointer to the first element in the array. #define array_front(self) array_get(self, 0) /// Get a pointer to the last element in the array. #define array_back(self) array_get(self, (self)->size - 1) /// Clear the array, setting its size to zero. Note that this does not free any /// memory allocated for the array's contents. #define array_clear(self) ((self)->size = 0) /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is /// less than the array's current capacity, this function has no effect. #define array_reserve(self, new_capacity) \ _array__reserve((Array *)(self), array_elem_size(self), new_capacity) /// Free any memory allocated for this array. Note that this does not free any /// memory allocated for the array's contents. #define array_delete(self) _array__delete((Array *)(self)) /// Push a new `element` onto the end of the array. #define array_push(self, element) \ (_array__grow((Array *)(self), 1, array_elem_size(self)), \ (self)->contents[(self)->size++] = (element)) /// Increase the array's size by `count` elements. /// New elements are zero-initialized. #define array_grow_by(self, count) \ do { \ if ((count) == 0) break; \ _array__grow((Array *)(self), count, array_elem_size(self)); \ memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ (self)->size += (count); \ } while (0) /// Append all elements from one array to the end of another. #define array_push_all(self, other) \ array_extend((self), (other)->size, (other)->contents) /// Append `count` elements to the end of the array, reading their values from the /// `contents` pointer. #define array_extend(self, count, contents) \ _array__splice( \ (Array *)(self), array_elem_size(self), (self)->size, \ 0, count, contents \ ) /// Remove `old_count` elements from the array starting at the given `index`. At /// the same index, insert `new_count` new elements, reading their values from the /// `new_contents` pointer. #define array_splice(self, _index, old_count, new_count, new_contents) \ _array__splice( \ (Array *)(self), array_elem_size(self), _index, \ old_count, new_count, new_contents \ ) /// Insert one `element` into the array at the given `index`. #define array_insert(self, _index, element) \ _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) /// Remove one element from the array at the given `index`. #define array_erase(self, _index) \ _array__erase((Array *)(self), array_elem_size(self), _index) /// Pop the last element off the array, returning the element by value. #define array_pop(self) ((self)->contents[--(self)->size]) /// Assign the contents of one array to another, reallocating if necessary. #define array_assign(self, other) \ _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) /// Swap one array with another #define array_swap(self, other) \ _array__swap((Array *)(self), (Array *)(other)) /// Get the size of the array contents #define array_elem_size(self) (sizeof *(self)->contents) /// Search a sorted array for a given `needle` value, using the given `compare` /// callback to determine the order. /// /// If an existing element is found to be equal to `needle`, then the `index` /// out-parameter is set to the existing value's index, and the `exists` /// out-parameter is set to true. Otherwise, `index` is set to an index where /// `needle` should be inserted in order to preserve the sorting, and `exists` /// is set to false. #define array_search_sorted_with(self, compare, needle, _index, _exists) \ _array__search_sorted(self, 0, compare, , needle, _index, _exists) /// Search a sorted array for a given `needle` value, using integer comparisons /// of a given struct field (specified with a leading dot) to determine the order. /// /// See also `array_search_sorted_with`. #define array_search_sorted_by(self, field, needle, _index, _exists) \ _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) /// Insert a given `value` into a sorted array, using the given `compare` /// callback to determine the order. #define array_insert_sorted_with(self, compare, value) \ do { \ unsigned _index, _exists; \ array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ if (!_exists) array_insert(self, _index, value); \ } while (0) /// Insert a given `value` into a sorted array, using integer comparisons of /// a given struct field (specified with a leading dot) to determine the order. /// /// See also `array_search_sorted_by`. #define array_insert_sorted_by(self, field, value) \ do { \ unsigned _index, _exists; \ array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ if (!_exists) array_insert(self, _index, value); \ } while (0) // Private typedef Array(void) Array; /// This is not what you're looking for, see `array_delete`. static inline void _array__delete(Array *self) { if (self->contents) { ts_free(self->contents); self->contents = NULL; self->size = 0; self->capacity = 0; } } /// This is not what you're looking for, see `array_erase`. static inline void _array__erase(Array *self, size_t element_size, uint32_t index) { assert(index < self->size); char *contents = (char *)self->contents; memmove(contents + index * element_size, contents + (index + 1) * element_size, (self->size - index - 1) * element_size); self->size--; } /// This is not what you're looking for, see `array_reserve`. static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { if (new_capacity > self->capacity) { if (self->contents) { self->contents = ts_realloc(self->contents, new_capacity * element_size); } else { self->contents = ts_malloc(new_capacity * element_size); } self->capacity = new_capacity; } } /// This is not what you're looking for, see `array_assign`. static inline void _array__assign(Array *self, const Array *other, size_t element_size) { _array__reserve(self, element_size, other->size); self->size = other->size; memcpy(self->contents, other->contents, self->size * element_size); } /// This is not what you're looking for, see `array_swap`. static inline void _array__swap(Array *self, Array *other) { Array swap = *other; *other = *self; *self = swap; } /// This is not what you're looking for, see `array_push` or `array_grow_by`. static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { uint32_t new_size = self->size + count; if (new_size > self->capacity) { uint32_t new_capacity = self->capacity * 2; if (new_capacity < 8) new_capacity = 8; if (new_capacity < new_size) new_capacity = new_size; _array__reserve(self, element_size, new_capacity); } } /// This is not what you're looking for, see `array_splice`. static inline void _array__splice(Array *self, size_t element_size, uint32_t index, uint32_t old_count, uint32_t new_count, const void *elements) { uint32_t new_size = self->size + new_count - old_count; uint32_t old_end = index + old_count; uint32_t new_end = index + new_count; assert(old_end <= self->size); _array__reserve(self, element_size, new_size); char *contents = (char *)self->contents; if (self->size > old_end) { memmove( contents + new_end * element_size, contents + old_end * element_size, (self->size - old_end) * element_size ); } if (new_count > 0) { if (elements) { memcpy( (contents + index * element_size), elements, new_count * element_size ); } else { memset( (contents + index * element_size), 0, new_count * element_size ); } } self->size += new_count - old_count; } /// A binary search routine, based on Rust's `std::slice::binary_search_by`. /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ do { \ *(_index) = start; \ *(_exists) = false; \ uint32_t size = (self)->size - *(_index); \ if (size == 0) break; \ int comparison; \ while (size > 1) { \ uint32_t half_size = size / 2; \ uint32_t mid_index = *(_index) + half_size; \ comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ if (comparison <= 0) *(_index) = mid_index; \ size -= half_size; \ } \ comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ if (comparison == 0) *(_exists) = true; \ else if (comparison < 0) *(_index) += 1; \ } while (0) /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) /// parameter by reference in order to work with the generic sorting function above. #define _compare_int(a, b) ((int)*(a) - (int)(b)) #ifdef _MSC_VER #pragma warning(default : 4101) #elif defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif #ifdef __cplusplus } #endif #endif // TREE_SITTER_ARRAY_H_ ================================================ FILE: src/tree_sitter/parser.h ================================================ #ifndef TREE_SITTER_PARSER_H_ #define TREE_SITTER_PARSER_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #define ts_builtin_sym_error ((TSSymbol)-1) #define ts_builtin_sym_end 0 #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 #ifndef TREE_SITTER_API_H_ typedef uint16_t TSStateId; typedef uint16_t TSSymbol; typedef uint16_t TSFieldId; typedef struct TSLanguage TSLanguage; #endif typedef struct { TSFieldId field_id; uint8_t child_index; bool inherited; } TSFieldMapEntry; typedef struct { uint16_t index; uint16_t length; } TSFieldMapSlice; typedef struct { bool visible; bool named; bool supertype; } TSSymbolMetadata; typedef struct TSLexer TSLexer; struct TSLexer { int32_t lookahead; TSSymbol result_symbol; void (*advance)(TSLexer *, bool); void (*mark_end)(TSLexer *); uint32_t (*get_column)(TSLexer *); bool (*is_at_included_range_start)(const TSLexer *); bool (*eof)(const TSLexer *); void (*log)(const TSLexer *, const char *, ...); }; typedef enum { TSParseActionTypeShift, TSParseActionTypeReduce, TSParseActionTypeAccept, TSParseActionTypeRecover, } TSParseActionType; typedef union { struct { uint8_t type; TSStateId state; bool extra; bool repetition; } shift; struct { uint8_t type; uint8_t child_count; TSSymbol symbol; int16_t dynamic_precedence; uint16_t production_id; } reduce; uint8_t type; } TSParseAction; typedef struct { uint16_t lex_state; uint16_t external_lex_state; } TSLexMode; typedef union { TSParseAction action; struct { uint8_t count; bool reusable; } entry; } TSParseActionEntry; typedef struct { int32_t start; int32_t end; } TSCharacterRange; struct TSLanguage { uint32_t version; uint32_t symbol_count; uint32_t alias_count; uint32_t token_count; uint32_t external_token_count; uint32_t state_count; uint32_t large_state_count; uint32_t production_id_count; uint32_t field_count; uint16_t max_alias_sequence_length; const uint16_t *parse_table; const uint16_t *small_parse_table; const uint32_t *small_parse_table_map; const TSParseActionEntry *parse_actions; const char * const *symbol_names; const char * const *field_names; const TSFieldMapSlice *field_map_slices; const TSFieldMapEntry *field_map_entries; const TSSymbolMetadata *symbol_metadata; const TSSymbol *public_symbol_map; const uint16_t *alias_map; const TSSymbol *alias_sequences; const TSLexMode *lex_modes; bool (*lex_fn)(TSLexer *, TSStateId); bool (*keyword_lex_fn)(TSLexer *, TSStateId); TSSymbol keyword_capture_token; struct { const bool *states; const TSSymbol *symbol_map; void *(*create)(void); void (*destroy)(void *); bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); unsigned (*serialize)(void *, char *); void (*deserialize)(void *, const char *, unsigned); } external_scanner; const TSStateId *primary_state_ids; }; static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { uint32_t index = 0; uint32_t size = len - index; while (size > 1) { uint32_t half_size = size / 2; uint32_t mid_index = index + half_size; TSCharacterRange *range = &ranges[mid_index]; if (lookahead >= range->start && lookahead <= range->end) { return true; } else if (lookahead > range->end) { index = mid_index; } size -= half_size; } TSCharacterRange *range = &ranges[index]; return (lookahead >= range->start && lookahead <= range->end); } /* * Lexer Macros */ #ifdef _MSC_VER #define UNUSED __pragma(warning(suppress : 4101)) #else #define UNUSED __attribute__((unused)) #endif #define START_LEXER() \ bool result = false; \ bool skip = false; \ UNUSED \ bool eof = false; \ int32_t lookahead; \ goto start; \ next_state: \ lexer->advance(lexer, skip); \ start: \ skip = false; \ lookahead = lexer->lookahead; #define ADVANCE(state_value) \ { \ state = state_value; \ goto next_state; \ } #define ADVANCE_MAP(...) \ { \ static const uint16_t map[] = { __VA_ARGS__ }; \ for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ if (map[i] == lookahead) { \ state = map[i + 1]; \ goto next_state; \ } \ } \ } #define SKIP(state_value) \ { \ skip = true; \ state = state_value; \ goto next_state; \ } #define ACCEPT_TOKEN(symbol_value) \ result = true; \ lexer->result_symbol = symbol_value; \ lexer->mark_end(lexer); #define END_STATE() return result; /* * Parse Table Macros */ #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) #define STATE(id) id #define ACTIONS(id) id #define SHIFT(state_value) \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .state = (state_value) \ } \ }} #define SHIFT_REPEAT(state_value) \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .state = (state_value), \ .repetition = true \ } \ }} #define SHIFT_EXTRA() \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .extra = true \ } \ }} #define REDUCE(symbol_name, children, precedence, prod_id) \ {{ \ .reduce = { \ .type = TSParseActionTypeReduce, \ .symbol = symbol_name, \ .child_count = children, \ .dynamic_precedence = precedence, \ .production_id = prod_id \ }, \ }} #define RECOVER() \ {{ \ .type = TSParseActionTypeRecover \ }} #define ACCEPT_INPUT() \ {{ \ .type = TSParseActionTypeAccept \ }} #ifdef __cplusplus } #endif #endif // TREE_SITTER_PARSER_H_ ================================================ FILE: test/corpus/comments.txt ================================================ ======== comments ======== # anything else here should be ignored --- (program (comment)) =================== empty block comment =================== =begin =end --- (program (comment)) ====================== one-line block comment ====================== =begin whatever =end --- (program (comment)) ====================================== block comment with comment after begin ====================================== =begin rdoc =end --- (program (comment)) ====================================== block comment with comment after end ====================================== =begin =end rdoc --- (program (comment)) ========================= multi-line block comments ========================= =begin whatever multiple lines of whatever =end --- (program (comment)) ========================= multi-line block comments followed by standard comment ========================= =begin whatever multiple lines of whatever =end # Another comment --- (program (comment) (comment)) ========================= multi-line block comments with almost end ========================= =begin =e =en =end --- (program (comment)) ========================= block comment without newline after end ========================= =begin comment =end --- (program (comment)) ================================================ FILE: test/corpus/control-flow.txt ================================================ ===================== empty while statement ===================== while foo do end --- (program (while condition: (identifier) body: (do))) ================ while without do ================ while foo end --- (program (while condition: (identifier) body: (do))) ========================= while statement with body ========================= while foo do bar end --- (program (while condition: (identifier) body: (do (identifier)))) ===================== empty until statement ===================== until foo bar do end --- (program (until condition: (call method: (identifier) arguments: (argument_list (identifier))) body: (do))) ========================= until statement with body ========================= until foo do bar end --- (program (until (identifier) (do (identifier)))) ================== empty if statement ================== if foo end --- (program (if condition: (identifier))) ======================= empty if/else statement ======================= if foo then else end if true then ;; 123; end --- (program (if condition: (identifier) consequence: (then) alternative: (else)) (if condition: (true) consequence: (then (empty_statement) (empty_statement) (integer)))) ================================== single-line if then else statement ================================== if foo then bar else quux end --- (program (if (identifier) (then (identifier)) (else (identifier)))) ======== if elsif ======== if foo bar elsif quux baz end --- (program (if (identifier) (then (identifier)) (elsif (identifier) (then (identifier))))) ============= if elsif else ============= if foo bar elsif quux baz else bat end --- (program (if (identifier) (then (identifier)) (elsif (identifier) (then (identifier)) (else (identifier))))) ====================== empty unless statement ====================== unless foo end --- (program (unless (identifier))) ================================ empty unless statement with then ================================ unless foo then hi end --- (program (unless condition: (identifier) consequence: (then (identifier)))) ================================ empty unless statement with else ================================ unless foo else end --- (program (unless condition: (identifier) alternative: (else))) === for === for x in y do f end for x, in y f end for x, *y in z do f end for (k, v) in y do f end --- (program (for pattern: (identifier) value: (in (identifier)) body: (do (identifier))) (for pattern: (left_assignment_list (identifier)) value: (in (identifier)) body: (do (identifier))) (for pattern: (left_assignment_list (identifier) (rest_assignment (identifier))) value: (in (identifier)) body: (do (identifier))) (for pattern: (left_assignment_list (destructured_left_assignment (identifier) (identifier))) value: (in (identifier)) body: (do (identifier)))) ============== for without do ============== for x in y f end --- (program (for pattern: (identifier) value: (in (identifier)) body: (do (identifier)))) ============== next ============== for x in y next end --- (program (for (identifier) (in (identifier)) (do (next)))) ============== retry ============== for x in y retry end --- (program (for pattern: (identifier) value: (in (identifier)) body: (do (retry)))) ============== break ============== while b break end --- (program (while (identifier) (do (break)))) ============== redo ============== while b redo end --- (program (while (identifier) (do (redo)))) =========== empty begin =========== begin end --- (program (begin)) =============== begin with body =============== begin foo end --- (program (begin (identifier))) =============== begin with else =============== begin foo else bar end --- (program (begin (identifier) (else (identifier)))) =============== begin with ensure =============== begin foo ensure bar end --- (program (begin (identifier) (ensure (identifier)))) ======================= begin with empty rescue ======================= begin rescue end begin rescue then end begin rescue bar end --- (program (begin (rescue)) (begin (rescue (then))) (begin (rescue (then (identifier))))) =========================== begin with rescue with args =========================== begin rescue x end begin rescue x then end begin rescue x bar end begin rescue => x bar end begin rescue x, y bar end begin rescue Error => x end begin rescue Error => x bar end --- (program (begin (rescue (exceptions (identifier)))) (begin (rescue (exceptions (identifier)) (then))) (begin (rescue (exceptions (identifier)) (then (identifier)))) (begin (rescue (exception_variable (identifier)) (then (identifier)))) (begin (rescue (exceptions (identifier) (identifier)) (then (identifier)))) (begin (rescue (exceptions (constant)) (exception_variable (identifier)))) (begin (rescue (exceptions (constant)) (exception_variable (identifier)) (then (identifier))))) =========================== begin with rescue with splat args =========================== begin rescue *args end --- (program (begin (rescue (exceptions (splat_argument (identifier)))))) ================= rescue modifier ================= foo rescue nil if foo rescue nil elsif bar rescue nil end unless foo rescue nil end --- (program (rescue_modifier (identifier) (nil)) (if (rescue_modifier (identifier) (nil)) (elsif (rescue_modifier (identifier) (nil)))) (unless (rescue_modifier (identifier) (nil)))) ================= rescue modifier in assignments ================= x = foo rescue 1 x += foo rescue 1 x, y = foo rescue 1 x = bar, foo rescue 1 x = foo 1 rescue 2 x += foo 1 rescue 2 --- (program (assignment left: (identifier) right: (rescue_modifier body: (identifier) handler: (integer))) (operator_assignment left: (identifier) right: (rescue_modifier body: (identifier) handler: (integer))) (assignment left: (left_assignment_list (identifier) (identifier)) right: (rescue_modifier body: (identifier) handler: (integer))) (rescue_modifier body: (assignment left: (identifier) right: (right_assignment_list (identifier) (identifier))) handler: (integer)) (assignment left: (identifier) right: (rescue_modifier body: (call method: (identifier) arguments: (argument_list (integer))) handler: (integer))) (operator_assignment left: (identifier) right: (rescue_modifier body: (call method: (identifier) arguments: (argument_list (integer))) handler: (integer)))) ============================ begin with all the trimmings ============================ begin foo rescue x retry else quux ensure baz end --- (program (begin (identifier) (rescue (exceptions (identifier)) (then (retry))) (else (identifier)) (ensure (identifier)))) ====== return ====== return foo --- (program (return (argument_list (identifier)))) ==================== return without value ==================== return --- (program (return)) ==== case ==== case foo when bar end case foo when bar end --- (program (case (identifier) (when (pattern (identifier)))) (case (identifier) (when (pattern (identifier))))) ============== case with else ============== case foo when bar else end case key when bar else; leaf end --- (program (case (identifier) (when (pattern (identifier))) (else)) (case (identifier) (when (pattern (identifier))) (else (identifier)))) ============================== case with multiple when blocks ============================== case a when b c when d e else f end --- (program (case (identifier) (when (pattern (identifier)) (then (identifier))) (when (pattern (identifier)) (then (identifier))) (else (identifier)))) ============================== case without line break ============================== case a when b c end --- (program (case (identifier) (when (pattern (identifier)) (then (identifier))))) ============================== case with splat parameter in when ============================== case a when *foo c end --- (program (case (identifier) (when (pattern (splat_argument (identifier))) (then (identifier))))) ============== case with assignment ============== x = case foo when bar else end --- (program (assignment (identifier) (case (identifier) (when (pattern (identifier))) (else)))) ============== case with expression ============== x = case foo = bar | baz when bar else end --- (program (assignment (identifier) (case (assignment (identifier) (binary (identifier) (identifier))) (when (pattern (identifier))) (else)))) ============================== case without expression ============================== case when b c end case when b then c end --- (program (case (when (pattern (identifier)) (then (identifier)))) (case (when (pattern (identifier)) (then (identifier))))) ================================================ FILE: test/corpus/declarations.txt ================================================ ============ empty method ============ def foo end def foo? end def foo! end --- (program (method (identifier)) (method (identifier)) (method (identifier))) ===================== method with body ===================== def foo bar end --- (program (method (identifier) (body_statement (identifier)))) ===================== "end"-less method ===================== def foo = bar def foo() = bar def foo(x) = bar def Object.foo = bar def Object.foo (x) = bar def foo() = bar rescue (print "error") --- (program (method name: (identifier) body: (identifier)) (method name: (identifier) parameters: (method_parameters) body: (identifier)) (method name: (identifier) parameters: (method_parameters (identifier)) body: (identifier)) (singleton_method object: (constant) name: (identifier) body: (identifier)) (singleton_method object: (constant) name: (identifier) parameters: (method_parameters (identifier)) body: (identifier)) (method name: (identifier) parameters: (method_parameters) body: (rescue_modifier body: (identifier) handler: (parenthesized_statements (call method: (identifier) arguments: (argument_list (string (string_content))))) ) ) ) =========================== method as attribute setter =========================== def foo= end --- (program (method (setter (identifier)))) ============================== method definition of operators ============================== def `(a) "`" end def +@(a) end def -@(a) end def ~@(a) end def %(a) end def ..(a) end def !~(a) end --- (program (method (operator) (method_parameters (identifier)) (body_statement (string (string_content)))) (method (operator) (method_parameters (identifier))) (method (operator) (method_parameters (identifier))) (method (operator) (method_parameters (identifier))) (method (operator) (method_parameters (identifier))) (method (operator) (method_parameters (identifier))) (method (operator) (method_parameters (identifier)))) =================================================== method with forward slash name and regex ambiguity =================================================== puts /(/ def /(name) end def / name end --- (program (call (identifier) (argument_list (regex (string_content)))) (method (operator) (method_parameters (identifier))) (method (operator) (method_parameters (identifier)))) =========================== method with call to super =========================== def foo super end def foo bar.baz { super } end def foo super.bar a, b end --- (program (method (identifier) (body_statement (super))) (method (identifier) (body_statement (call (identifier) (identifier) (block (block_body (super)))))) (method (identifier) (body_statement (call (super) (identifier) (argument_list (identifier) (identifier)))))) =========================== method with args =========================== def foo(bar) end def foo(bar); end def foo(bar) end --- (program (method (identifier) (method_parameters (identifier))) (method (identifier) (method_parameters (identifier))) (method (identifier) (method_parameters (identifier)))) ================================ method with unparenthesized args ================================ def foo bar end --- (program (method (identifier) (method_parameters (identifier)))) ========================= method with multiple args ========================= def foo(bar, quux) end --- (program (method (identifier) (method_parameters (identifier) (identifier)))) ========================================= method with multiple unparenthesized args ========================================= def foo bar, quux end --- (program (method (identifier) (method_parameters (identifier) (identifier)))) ========================================= method with keyword parameters ========================================= def foo(bar: nil, baz:) end --- (program (method (identifier) (method_parameters (keyword_parameter (identifier) (nil)) (keyword_parameter (identifier))))) ========================================= method with default parameters ========================================= def foo(bar = nil) end def foo(bar=nil) end --- (program (method (identifier) (method_parameters (optional_parameter (identifier) (nil)))) (method (identifier) (method_parameters (optional_parameter (identifier) (nil))))) ========================================= method with interesting params ========================================= def foo(*options) end def foo(x, *options) end def foo(x, *options, y) end def foo(**options) end def foo(name:, **) end def foo(x, **nil) end def foo(&block) end def foo(&) end def foo(...) super(...) end def foo(a, b, ...) bar(b, ...) end def foo ... 3 end def foo ... 3 end def foo .. 3 end --- (program (method (identifier) (method_parameters (splat_parameter (identifier)))) (method (identifier) (method_parameters (identifier) (splat_parameter (identifier)))) (method (identifier) (method_parameters (identifier) (splat_parameter (identifier)) (identifier))) (method (identifier) (method_parameters (hash_splat_parameter (identifier)))) (method (identifier) (method_parameters (keyword_parameter (identifier)) (hash_splat_parameter))) (method (identifier) (method_parameters (identifier) (hash_splat_nil))) (method (identifier) (method_parameters (block_parameter (identifier)))) (method (identifier) (method_parameters (block_parameter))) (method (identifier) (method_parameters (forward_parameter)) (body_statement (call (super) (argument_list (forward_argument)))) ) (method (identifier) (method_parameters (identifier) (identifier) (forward_parameter)) (body_statement (call (identifier) (argument_list (identifier) (forward_argument)))) ) (method (identifier) (method_parameters (forward_parameter)) (body_statement (integer)) ) (method (identifier) (body_statement (range (integer)))) (method (identifier) (body_statement (range (integer)))) ) ========================================= singleton method ========================================= def self.foo end --- (program (singleton_method (self) (identifier))) ========================================= singleton method with body ========================================= def self.foo bar end --- (program (singleton_method (self) (identifier) (body_statement (identifier)))) ========================================= singleton method with arg ========================================= def self.foo(bar) end --- (program (singleton_method (self) (identifier) (method_parameters (identifier)))) ========================================= singleton method with un-parenthesized arg ========================================= def self.foo bar end --- (program (singleton_method (self) (identifier) (method_parameters (identifier)))) ========================================= singleton method with args ========================================= def self.foo(bar, baz) end --- (program (singleton_method (self) (identifier) (method_parameters (identifier) (identifier)))) ========================================= singleton method with un-parenthesized args ========================================= def self.foo bar, baz end --- (program (singleton_method (self) (identifier) (method_parameters (identifier) (identifier)))) =========== empty class =========== class Foo end class Foo; end class Foo::Bar end class ::Foo::Bar end class Cß end --- (program (class (constant)) (class (constant)) (class (scope_resolution (constant) (constant))) (class (scope_resolution (scope_resolution (constant)) (constant))) (class (constant))) ============== empty subclass ============== class Foo < Bar end --- (program (class (constant) (superclass (constant)))) ================================== empty subclass of namespaced class ================================== class Foo < Bar::Quux end class Foo < ::Bar end class Foo < Bar::Baz.new(foo) end --- (program (class (constant) (superclass (scope_resolution (constant) (constant)))) (class (constant) (superclass (scope_resolution (constant)))) (class (constant) (superclass (call (scope_resolution (constant) (constant)) (identifier) (argument_list (identifier)))))) ======================================= one-line class/module def without ; ======================================= module NoActiveModel class Resource; end; end class String def foo; end end --- (program (module name: (constant) body: (body_statement (class name: (constant)))) (class name: (constant) body: (body_statement (method name: (identifier))))) ======================================= unparenthesized call as superclass ======================================= class A < B.new \ :c, :d end --- (program (class name: (constant) superclass: (superclass (call receiver: (constant) method: (identifier) arguments: (argument_list (simple_symbol) (simple_symbol)))))) =============== class with body =============== class Foo def bar end end --- (program (class (constant) (body_statement (method (identifier))))) ==================== class with operators ==================== class A def ==; end def !=(other); end end --- (program (class name: (constant) body: (body_statement (method name: (operator)) (method name: (operator) parameters: (method_parameters (identifier)))))) ========================================= class within dynamically-computed module ========================================= class foo()::Bar end --- (program (class (scope_resolution (call (identifier) (argument_list)) (constant)))) =============== singleton class =============== class << self end class < 1, :c => 2 --- (program (assignment (identifier) (call (identifier) (argument_list (identifier) (identifier)))) (assignment (identifier) (call (identifier) (argument_list (identifier) (pair (simple_symbol) (integer)) (pair (simple_symbol) (integer)))))) ========== math assignment ========== x += y x -= y x *= y x **= y x /= y puts "/hi" --- (program (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (call (identifier) (argument_list (string (string_content))))) ========== operator assignment ========== x ||= y x &&= y x &= y x |= y x %= y x >>= y x <<= y x ^= y --- (program (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier)) (operator_assignment (identifier) (identifier))) =========== conditional =========== a ? b : c a ? b : c --- (program (conditional condition: (identifier) consequence: (identifier) alternative: (identifier)) (conditional condition: (identifier) consequence: (identifier) alternative: (identifier))) =========================================== conditional and character literal ambiguity =========================================== true ?")":"c" --- (program (conditional (true) (string (string_content)) (string (string_content)))) =========================================== conditional with reserved identifiers =========================================== foo ? true: false foo ? return: false --- (program (conditional (identifier) (true) (false)) (conditional (identifier) (return) (false))) =============== inclusive range =============== a..b --- (program (range (identifier) (identifier))) =============== exclusive range =============== a...b --- (program (range (identifier) (identifier))) ========== boolean or ========== a || b --- (program (binary (identifier) (identifier))) =========== boolean and =========== a && b --- (program (binary (identifier) (identifier))) =========== boolean and/or =========== a || b && c a && b || c --- (program (binary left: (identifier) right: (binary left: (identifier) right: (identifier))) (binary left: (binary left: (identifier) right: (identifier)) right: (identifier))) ========== relational ========== a == b a != b a === b a <=> b a =~ b a !~ b a==b a!=b a===b a<=>b a=~b a!~b # not a binary operation --- (program (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (call method: (identifier) arguments: (argument_list (unary operand: (identifier)))) (comment)) ========== comparison ========== a < b a <= b a > b a >= b --- (program (binary (identifier) (identifier)) (binary (identifier) (identifier)) (binary (identifier) (identifier)) (binary (identifier) (identifier))) ========== bitwise or ========== a | b --- (program (binary (identifier) (identifier))) =========== bitwise xor =========== a ^ b --- (program (binary (identifier) (identifier))) =========== bitwise and =========== a & b --- (program (binary (identifier) (identifier))) ===== shift ===== a >> b a << b --- (program (binary (identifier) (identifier)) (binary (identifier) (identifier))) ======== additive ======== a + b --- (program (binary (identifier) (identifier))) ============== multiplicative ============== a * b a*b a *b a* b --- (program (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (call method: (identifier) arguments: (argument_list (splat_argument (identifier)))) (binary left: (identifier) right: (identifier))) ============== binary operations ============== 2+2*2 --- (program (binary (integer) (binary (integer) (integer)))) =========== unary minus =========== -a foo -a, bar foo(-a, bar) --- (program (unary (identifier)) (call (identifier) (argument_list (unary (identifier)) (identifier))) (call (identifier) (argument_list (unary (identifier)) (identifier)))) =========== binary minus =========== foo-a @ivar-1 --- (program (binary (identifier) (identifier)) (binary (instance_variable) (integer))) =========== exponential =========== a ** b --- (program (binary (identifier) (identifier))) ==== minus, call, exponential, range ==== a - 1 a-1 a -1 a- 1 (-1.foo) a - b a-b a -b a- b (-b.foo) -2**10 -x**10 1..-1 1 .. -1 1.. -1 1 ..-1 --- (program (binary left: (identifier) right: (integer)) (binary left: (identifier) right: (integer)) (call method: (identifier) arguments: (argument_list (unary operand: (integer)))) (binary left: (identifier) right: (integer)) (parenthesized_statements (call receiver: (unary operand: (integer)) method: (identifier))) (binary left: (identifier) right: (identifier)) (binary left: (identifier) right: (identifier)) (call method: (identifier) arguments: (argument_list (unary operand: (identifier)))) (binary left: (identifier) right: (identifier)) (parenthesized_statements (unary operand: (call receiver: (identifier) method: (identifier)))) (unary operand: (binary left: (integer) right: (integer))) (unary operand: (binary left: (identifier) right: (integer))) (range begin: (integer) end: (unary operand: (integer))) (range begin: (integer) end: (unary operand: (integer))) (range begin: (integer) end: (unary operand: (integer))) (range begin: (integer) end: (unary operand: (integer)))) ========== complement ========== !a --- (program (unary (identifier))) =============================== method call =============================== foo foo() print "hello" print("hello") exit! exit!() include? include?("hello") include? "hello" exit! if done exit!() if done --- (program (identifier) (call method: (identifier) arguments: (argument_list)) (call method: (identifier) arguments: (argument_list (string (string_content)))) (call method: (identifier) arguments: (argument_list (string (string_content)))) (call method: (identifier)) (call method: (identifier) arguments: (argument_list)) (call method: (identifier)) (call method: (identifier) arguments: (argument_list (string (string_content)))) (call method: (identifier) arguments: (argument_list (string (string_content)))) (if_modifier body: (call method: (identifier)) condition: (identifier)) (if_modifier body: (call method: (identifier) arguments: (argument_list)) condition: (identifier))) ==================================== nested unparenthesized method calls ==================================== puts get_name self, true puts(get_name self, true) --- (program (call method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list (self) (true))))) (call method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list (self) (true)))))) =============================== method call with arguments on multiple lines =============================== foo a, b, c --- (program (call method: (identifier) arguments: (argument_list (identifier) (identifier) (identifier)))) =============================== method call with trailing comma =============================== foo(a, b,) foo(bar(a),) --- (program (call (identifier) (argument_list (identifier) (identifier))) (call (identifier) (argument_list (call (identifier) (argument_list (identifier)))))) ============================================== keyword arguments, no space, trailing comma ============================================== foo(a:b) foo(a_:b) foo(a2:b) foo(a_:b,) foo(a2:b,) --- (program (call (identifier) (argument_list (pair (hash_key_symbol) (identifier)))) (call (identifier) (argument_list (pair (hash_key_symbol) (identifier)))) (call (identifier) (argument_list (pair (hash_key_symbol) (identifier)))) (call (identifier) (argument_list (pair (hash_key_symbol) (identifier)))) (call (identifier) (argument_list (pair (hash_key_symbol) (identifier))))) =============================== method call with receiver =============================== foo.bar foo.bar() foo.bar "hi" foo.bar "hi", 2 foo.bar("hi") foo.bar("hi", 2) --- (program (call receiver: (identifier) method: (identifier)) (call receiver: (identifier) method: (identifier) arguments: (argument_list)) (call receiver: (identifier) method: (identifier) arguments: (argument_list (string (string_content)))) (call receiver: (identifier) method: (identifier) arguments: (argument_list (string (string_content)) (integer))) (call receiver: (identifier) method: (identifier) arguments: (argument_list (string (string_content)))) (call receiver: (identifier) method: (identifier) arguments: (argument_list (string (string_content)) (integer)))) =============================== implicit call =============================== foo[bar].() foo.(1, 2) --- (program (call receiver: (element_reference object: (identifier) (identifier)) arguments: (argument_list)) (call receiver: (identifier) arguments: (argument_list (integer) (integer)))) =============================== implicit call with block =============================== a.() {} a.(b: c) do d end --- (program (call receiver: (identifier) arguments: (argument_list) block: (block)) (call receiver: (identifier) arguments: (argument_list (pair key: (hash_key_symbol) value: (identifier))) block: (do_block body: (body_statement (identifier))))) =============================== call with operator method name =============================== foo.[]() --- (program (call receiver: (identifier) method: (operator) arguments: (argument_list))) =============================== method call with :: operator =============================== foo::bar ::Foo::bar Foo::Bar::baz --- (program (call (identifier) (identifier)) (call (scope_resolution (constant)) (identifier)) (call (scope_resolution (constant) (constant)) (identifier))) =============================== method call with safe navigation operator =============================== foo&.bar --- (program (call (identifier) (identifier))) =============================== calls to methods on negated literals =============================== -1.class.should eq(Fixnum) -0.1.class --- (program (call receiver: (call receiver: (unary operand: (integer)) method: (identifier)) method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list (constant))))) (call receiver: (unary operand: (float)) method: (identifier))) =============================== method call with hash args =============================== foo(:a => true) foo([] => 1) foo(bar => 1) foo :a => true, :c => 1 --- (program (call (identifier) (argument_list (pair (simple_symbol) (true)))) (call (identifier) (argument_list (pair (array) (integer)))) (call (identifier) (argument_list (pair (identifier) (integer)))) (call (identifier) (argument_list (pair (simple_symbol) (true)) (pair (simple_symbol) (integer))))) =============================== method call with keyword args =============================== foo(a: true) foo a: true foo B: true foo a: ; foo B: --- (program (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol)))) (call (identifier) (argument_list (pair (hash_key_symbol))))) =============================== method call with reserved keyword args =============================== foo(if: true) foo alias: true foo and: true foo begin: true foo break: true foo case: true foo class: true foo def: true foo defined: true foo do: true foo else: true foo elsif: true foo end: true foo ensure: true foo false: true foo for: true foo if: true foo in: true foo module: true foo next: true foo nil: true foo not: true foo or: true foo redo: true foo rescue: true foo retry: true foo return: true foo self: true foo super: true foo then: true foo true: true foo undef: true foo unless: true foo until: true foo when: true foo while: true foo yield: true foo yield: --- (program (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol) (true)))) (call (identifier) (argument_list (pair (hash_key_symbol))))) =============================== method call with paren args =============================== foo (b), a --- (program (call (identifier) (argument_list (parenthesized_statements (identifier)) (identifier)))) =============================== method call with block argument =============================== foo(&:sort) foo(&bar) foo(&bar, 1) foo &bar foo &bar, 1 foo(&) foo(&, 1) foo &; foo 1, &; --- (program (call (identifier) (argument_list (block_argument (simple_symbol)))) (call (identifier) (argument_list (block_argument (identifier)))) (call (identifier) (argument_list (block_argument (identifier)) (integer))) (call (identifier) (argument_list (block_argument (identifier)))) (call (identifier) (argument_list (block_argument (identifier)) (integer))) (call (identifier) (argument_list (block_argument))) (call (identifier) (argument_list (block_argument) (integer))) (call (identifier) (argument_list (block_argument))) (call (identifier) (argument_list (integer) (block_argument)))) =============================== method call with splat argument =============================== foo(*bar) foo *bar foo *%w{ .. lib } foo *(bar.baz) --- (program (call (identifier) (argument_list (splat_argument (identifier)))) (call (identifier) (argument_list (splat_argument (identifier)))) (call (identifier) (argument_list (splat_argument (string_array (bare_string (string_content)) (bare_string (string_content)))))) (call (identifier) (argument_list (splat_argument (parenthesized_statements (call (identifier) (identifier))))))) =============================== method call lambda argument =============================== foo :bar, -> (a) { 1 } foo :bar, -> (a) { where(:c => b) } --- (program (call (identifier) (argument_list (simple_symbol) (lambda (lambda_parameters (identifier)) (block (block_body (integer)))))) (call (identifier) (argument_list (simple_symbol) (lambda (lambda_parameters (identifier)) (block (block_body (call (identifier) (argument_list (pair (simple_symbol) (identifier)))))))))) =============================== method call lambda argument and do block =============================== foo :bar, -> (a) { 1 } do end --- (program (call (identifier) (argument_list (simple_symbol) (lambda (lambda_parameters (identifier)) (block (block_body (integer))))) (do_block))) =============================================== chained method calls with blocks but no parens =============================================== a.b c, *d do |e| f end.g h { |i| i }.j do k end --- (program (call receiver: (call receiver: (identifier) method: (identifier) arguments: (argument_list (identifier) (splat_argument (identifier))) block: (do_block parameters: (block_parameters (identifier)) body: (body_statement (identifier)))) method: (identifier) arguments: (argument_list (call receiver: (call method: (identifier) block: (block parameters: (block_parameters (identifier)) body: (block_body (identifier)))) method: (identifier) block: (do_block body: (body_statement (identifier))))))) =============================== method calls in binary expression =============================== one two or three four, five and six seven, eight, nine --- (program (binary left: (binary left: (call method: (identifier) arguments: (argument_list (identifier))) right: (call method: (identifier) arguments: (argument_list (identifier) (identifier)))) right: (call method: (identifier) arguments: (argument_list (identifier) (identifier) (identifier))))) =============================== method calls in unary expression =============================== !a.b c --- (program (unary operand: (call receiver: (identifier) method: (identifier) arguments: (argument_list (identifier))))) =============================== method calls with splat argument =============================== foo(*bar) foo(*[bar, baz].quoz) foo(x, *bar) foo(*bar.baz) foo(**baz) foo **bar, baz foo(*) foo(x, *) foo(**) foo x, ** --- (program (call (identifier) (argument_list (splat_argument (identifier)))) (call (identifier) (argument_list (splat_argument (call (array (identifier) (identifier)) (identifier))))) (call (identifier) (argument_list (identifier) (splat_argument (identifier)))) (call (identifier) (argument_list (splat_argument (call (identifier) (identifier))))) (call (identifier) (argument_list (hash_splat_argument (identifier)))) (call (identifier) (argument_list (hash_splat_argument (identifier)) (identifier))) (call (identifier) (argument_list (splat_argument))) (call (identifier) (argument_list (identifier) (splat_argument))) (call (identifier) (argument_list (hash_splat_argument))) (call (identifier) (argument_list (identifier) (hash_splat_argument)))) ============================ method call without parens ============================ include D::E.f --- (program (call (identifier) (argument_list (call (scope_resolution (constant) (constant)) (identifier))))) ============================ method call with line break ============================ Foo .bar! .baz Foo \ .bar Foo \ &.bar &.baz Foo # a comment .bar .baz --- (program (call (call (constant) (identifier)) (identifier)) (call (constant) (identifier)) (call (call (constant) (identifier)) (identifier)) (call (call (constant) (comment) (identifier)) (identifier))) ====================================== method call with block argument do end ====================================== foo do |i| bar rescue E baz ensure quux end foo do |i| i end foo do; end foo(a) do |i| foo end foo.bar a do |i| foo end foo(a) do |name: i, *args| end --- (program (call method: (identifier) block: (do_block parameters: (block_parameters (identifier)) body: (body_statement (identifier) (rescue exceptions: (exceptions (constant)) body: (then (identifier))) (ensure (identifier))))) (call method: (identifier) block: (do_block parameters: (block_parameters (identifier)) body: (body_statement (identifier)))) (call method: (identifier) block: (do_block)) (call method: (identifier) arguments: (argument_list (identifier)) block: (do_block parameters: (block_parameters (identifier)) body: (body_statement (identifier)))) (call receiver: (identifier) method: (identifier) arguments: (argument_list (identifier)) block: (do_block parameters: (block_parameters (identifier)) body: (body_statement (identifier)))) (call method: (identifier) arguments: (argument_list (identifier)) block: (do_block parameters: (block_parameters (keyword_parameter name: (identifier) value: (identifier)) (splat_parameter name: (identifier)))))) =============================== method call with block argument curly =============================== foo { |i| foo } foo items.any? { |i| i > 0 } foo(bar, baz) { quux } --- (program (call method: (identifier) block: (block parameters: (block_parameters (identifier)) body: (block_body (identifier)))) (call method: (identifier) arguments: (argument_list (call receiver: (identifier) method: (identifier) block: (block parameters: (block_parameters (identifier)) body: (block_body (binary left: (identifier) right: (integer))))))) (call method: (identifier) arguments: (argument_list (identifier) (identifier)) block: (block body: (block_body (identifier))))) =============================== method call with block shadow arguments =============================== foo { |; i, j| } foo { |x, y ; i, j| } --- (program (call method: (identifier) block: (block parameters: (block_parameters locals: (identifier) locals: (identifier)))) (call method: (identifier) block: (block parameters: (block_parameters (identifier) (identifier) locals: (identifier) locals: (identifier))))) =============================== method call with capitalized name =============================== request.GET --- (program (call (identifier) (constant))) =============================== destructured parameters =============================== -> (d, *f, (x, y)) {} def foo(d, *f, (x, y)) end def foo d, *f, (x, y) end foo do |a, (c, d, *f, (x, y)), *e| end --- (program (lambda (lambda_parameters (identifier) (splat_parameter (identifier)) (destructured_parameter (identifier) (identifier))) (block)) (method (identifier) (method_parameters (identifier) (splat_parameter (identifier)) (destructured_parameter (identifier) (identifier)))) (method (identifier) (method_parameters (identifier) (splat_parameter (identifier)) (destructured_parameter (identifier) (identifier)))) (call (identifier) (do_block (block_parameters (identifier) (destructured_parameter (identifier) (identifier) (splat_parameter (identifier)) (destructured_parameter (identifier) (identifier))) (splat_parameter (identifier)))))) ================================================== element reference and method with array arguments ================================================== foo [] foo [1] foo[1] --- (program (call method: (identifier) arguments: (argument_list (array))) (call method: (identifier) arguments: (argument_list (array (integer)))) (element_reference object: (identifier) (integer))) ===================================== element reference on call expression ===================================== d(a) [0] d.find { |x| x > 1 } [0] d.find { |x| x > 1 } [0] == 0 --- (program (element_reference (call (identifier) (argument_list (identifier))) (integer)) (element_reference (call (identifier) (identifier) (block (block_parameters (identifier)) (block_body (binary (identifier) (integer))))) (integer)) (binary (element_reference (call (identifier) (identifier) (block (block_parameters (identifier)) (block_body (binary (identifier) (integer))))) (integer)) (integer))) ============================ element reference with block ============================ foo[:bar] { |baz| baz } foo[:bar] do |baz| baz end --- (program (element_reference (identifier) (simple_symbol) (block (block_parameters (identifier)) (block_body (identifier)))) (element_reference (identifier) (simple_symbol) (do_block (block_parameters (identifier)) (body_statement (identifier))))) ====================================== call with array and block ====================================== fun [0] { |x| x } fun [0] do puts 1 end --- (program (call (identifier) (argument_list (array (integer))) (block (block_parameters (identifier)) (block_body (identifier)))) (call (identifier) (argument_list (array (integer))) (do_block (body_statement (call (identifier) (argument_list (integer))))))) ======================================================================== call with normal and keyword argument with value that looks like a block ======================================================================== render "foo/bars/show", locals: { } render "foo/bars/show", locals: { display_text: dt, safe_text: "hello" } --- (program (call (identifier) (argument_list (string (string_content)) (pair (hash_key_symbol) (hash)))) (call (identifier) (argument_list (string (string_content)) (pair (hash_key_symbol) (hash (pair (hash_key_symbol) (identifier)) (pair (hash_key_symbol) (string (string_content)))))))) ======================================================================== call with keyword argument on different lines ======================================================================== render :show_details, 5, description: "Some long " \ "piece of text.", dark_mode: false render "/foo/bar", params: { id: 3, title: "Hello world" }, headers: { Accept: "text/html" } render "/foo/bar", params: { id: 3, title: "Hello world" } --- (program (call method: (identifier) arguments: (argument_list (simple_symbol) (integer) (pair key: (hash_key_symbol) value: (chained_string (string (string_content)) (string (string_content)))) (pair key: (hash_key_symbol) value: (false)))) (call method: (identifier) arguments: (argument_list (string (string_content)) (pair key: (hash_key_symbol) value: (hash (pair key: (hash_key_symbol) value: (integer)) (pair key: (hash_key_symbol) value: (string (string_content))))) (pair key: (hash_key_symbol) value: (hash (pair key: (hash_key_symbol) value: (string (string_content))))))) (call method: (identifier) arguments: (argument_list (string (string_content)) (pair key: (hash_key_symbol) value: (hash (pair key: (hash_key_symbol) value: (integer)) (pair key: (hash_key_symbol) value: (string (string_content)))))))) ============== empty lambda expression ============== lambda {} --- (program (call (identifier) (block))) ================== lambda expressions ================== lambda { foo } lambda(&block) { foo } lambda(&lambda{}) --- (program (call (identifier) (block (block_body (identifier)))) (call (identifier) (argument_list (block_argument (identifier))) (block (block_body (identifier)))) (call (identifier) (argument_list (block_argument (call (identifier) (block)))))) ==================== lambda expression with an arg ==================== lambda { |foo| 1 } --- (program (call (identifier) (block (block_parameters (identifier)) (block_body (integer))))) =========================== lambda expression with multiple args =========================== lambda { |a, b, c| 1 2 } --- (program (call (identifier) (block (block_parameters (identifier) (identifier) (identifier)) (block_body (integer) (integer))))) =========================== lambda expression with trailing comma =========================== lambda { |a, b,| 1 } --- (program (call (identifier) (block (block_parameters (identifier) (identifier)) (block_body (integer))))) =========================== lambda expression with optional arg =========================== lambda { |a, b=nil| 1 } --- (program (call (identifier) (block (block_parameters (identifier) (optional_parameter (identifier) (nil))) (block_body (integer))))) =========================== lambda expression with keyword arg =========================== lambda { |a, b: nil| 1 } --- (program (call (identifier) (block (block_parameters (identifier) (keyword_parameter (identifier) (nil))) (block_body (integer))))) ==================== lambda expression with do end ==================== lambda do |foo| 1 end --- (program (call (identifier) (do_block (block_parameters (identifier)) (body_statement (integer))))) ============================ lambda and proc as variables ============================ proc = Proc.new lambda = lambda {} proc = proc {} --- (program (assignment (identifier) (call (constant) (identifier))) (assignment (identifier) (call (identifier) (block))) (assignment (identifier) (call (identifier) (block)))) =============================== backslash-newline as line continuation =============================== foo \ a, b "abc \ de" foo \ "abc" --- (program (call (identifier) (argument_list (identifier) (identifier))) (string (string_content) (escape_sequence) (string_content)) (call (identifier) (argument_list (string (string_content))))) =============================== basic division =============================== 10 / 5 x / y x / 5 --- (program (binary (integer) (integer)) (binary (identifier) (identifier)) (binary (identifier) (integer))) =============================== division without spaces =============================== h/w "#{foo}" Time.at(timestamp/1000) "#{timestamp}" --- (program (binary left: (identifier) right: (identifier)) (string (interpolation (identifier))) (call receiver: (constant) method: (identifier) arguments: (argument_list (binary left: (identifier) right: (integer)))) (string (interpolation (identifier)))) =============================== regex as parameter =============================== foo /bar/ --- (program (call (identifier) (argument_list (regex (string_content))))) =============================== regex with opening space =============================== foo / bar/ --- (program (identifier) (regex (string_content))) =============================== forward slash operator as method =============================== Foo / "bar" "/edit" --- (program (binary (constant) (string (string_content))) (string (string_content))) =============================== multiline regex =============================== / a b/ --- (program (regex (string_content))) ================================================ FILE: test/corpus/line-endings.txt ================================================ ================= CRLF line endings ================= puts 'hi' x = foo() --- (program (call (identifier) (argument_list (string (string_content)))) (assignment (identifier) (call (identifier) (argument_list)))) ======================= CRLF multiline comments ======================= =begin =end --- (program (comment)) ================================================ FILE: test/corpus/literals.txt ================================================ ====== symbol ====== :foo :foo! :foo? :foo= :@foo :@foo_0123_bar :@@foo :$foo :$0 :_bar :åäö :_ --- (program (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol)) ====== symbol operators ====== :+ :- :+@ :-@ :[] :[]= :& :! :` :^ :| :~ :/ :% :* :** :== :=== :=~ :> :>= :>> :< :<= :<< :<=> :!= :!~ --- (program (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol) (simple_symbol)) ==================== single quoted symbol ==================== :'' :'foo bar' :'#{' --- (program (delimited_symbol) (delimited_symbol (string_content)) (delimited_symbol (string_content))) ==================== double quoted symbol ==================== :"foo bar" :"#" --- (program (delimited_symbol (string_content)) (delimited_symbol (string_content))) ======================================= double quoted symbol with interpolation ======================================= :"foo #{bar}" --- (program (delimited_symbol (string_content) (interpolation (identifier)))) ======================================= interpolation with no content ======================================= :"foo #{}" --- (program (delimited_symbol (string_content) (interpolation))) ========================================= percent symbol with unbalanced delimiters ========================================= %s/a/ %s\a\ %s#a# --- (program (delimited_symbol (string_content)) (delimited_symbol (string_content)) (delimited_symbol (string_content))) ======================================= percent symbol with balanced delimiters ======================================= %s{a{b}c} %sc> %s(a(b)c) %s[a[b]c] --- (program (delimited_symbol (string_content)) (delimited_symbol (string_content)) (delimited_symbol (string_content)) (delimited_symbol (string_content))) ======================================= global variables ======================================= $foo $$ $! $@ $& $` $' $+ $~ $= $/ $\ $, $; $. $< $> $_ $0 $* $$ $? $: $" $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $0 $10 $stdin $stdout $stderr $DEBUG $FILENAME $LOAD_PATH $VERBOSE --- (program (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable) (global_variable)) ======= integer ======= 1234 --- (program (integer)) ======= integer as object ======= 3.times --- (program (call (integer) (identifier))) ======================= integer with underscore ======================= 1_234 --- (program (integer)) =========================== integer with decimal prefix =========================== 0d1_234 0D1_234 --- (program (integer) (integer)) =============================== integer with hexadecimal prefix =============================== 0xa_bcd_ef0_123_456_789 --- (program (integer)) =============================== integer with hexadecimal prefix capitalised =============================== 0Xa_bcd_ef0_123_456_789 --- (program (integer)) ========================= integer with octal prefix ========================= 01234567 0o1234567 --- (program (integer) (integer)) ========================== integer with binary prefix ========================== 0b1_0 0B1_0 --- (program (integer) (integer)) ===== float ===== 1.234_5e678_90 1E30 1.0e+6 1.0e-6 --- (program (float) (float) (float) (float)) ===== complex ===== -2i +2i 1+1i 1-10i 10+3i 12-34i -2.2i +2.2i 1+1.2i 1-10.2i 10+3.2i 12-34.2i -2ri +2.2ri 1+1ri 1-10.2ri 10+3ri 12-34.2ri --- (program (unary operand: (complex (integer))) (unary operand: (complex (integer))) (binary left: (integer) right: (complex (integer))) (binary left: (integer) right: (complex (integer))) (binary left: (integer) right: (complex (integer))) (binary left: (integer) right: (complex (integer))) (unary operand: (complex (float))) (unary operand: (complex (float))) (binary left: (integer) right: (complex (float))) (binary left: (integer) right: (complex (float))) (binary left: (integer) right: (complex (float))) (binary left: (integer) right: (complex (float))) (unary operand: (complex (rational (integer)))) (unary operand: (complex (rational (float)))) (binary left: (integer) right: (complex (rational (integer)))) (binary left: (integer) right: (complex (rational (float)))) (binary left: (integer) right: (complex (rational (integer)))) (binary left: (integer) right: (complex (rational (float))))) ======== rational ======== 2/3r 1.2r +1.2r -2r 0b01r 0o7r 0d1r 0x12r --- (program (binary (integer) (rational (integer))) (rational (float)) (unary (rational (float))) (unary (rational (integer))) (rational (integer)) (rational (integer)) (rational (integer)) (rational (integer))) ======= boolean ======= true false --- (program (true) (false)) === nil === nil --- (program (nil)) ==================== single-quoted string ==================== '' ' ' ' ' --- (program (string) (string (string_content)) (string (string_content))) ============================================== single-quoted strings with backslashes ============================================== '\'' '\\ \n' '\x00\x01\x02' --- (program (string (string_content)) (string (string_content)) (string (string_content))) ================================================= single-quoted string with pound and curly brace ================================================= '#{hello' --- (program (string (string_content))) ==================== double-quoted string ==================== "" " " " " --- (program (string) (string (string_content)) (string (string_content))) ============================================== double-quoted strings with escape sequences ============================================== "\"" "\\" "\d" "\#{foo}" "\u{1F600}" "\u{1F600 1F600}" --- (program (string (escape_sequence)) (string (escape_sequence)) (string (escape_sequence)) (string (escape_sequence) (string_content)) (string (escape_sequence)) (string (escape_sequence))) ================================= double-quoted string with just pound ================================= "#" --- (program (string (string_content))) ============= interpolation ============= "#{foo}" "foo#@foo" "#@@foo" "#$foo" "#$%" "#$1" "#$_1" "#$-AB" "#$-10" "#@1" "#@@1" "#{':foo' unless bar}" --- (program (string (interpolation (identifier))) (string (string_content) (interpolation (instance_variable))) (string (interpolation (class_variable))) (string (interpolation (global_variable))) (string (string_content)) (string (interpolation (global_variable))) (string (interpolation (global_variable))) (string (interpolation (global_variable)) (string_content)) (string (string_content)) (string (string_content)) (string (string_content)) (string (interpolation (unless_modifier (string (string_content)) (identifier))))) =========================================== percent q string with unbalanced delimiters =========================================== %q/a/ %q\a\ %q#a# --- (program (string (string_content)) (string (string_content)) (string (string_content))) ========================================= percent q string with balanced delimiters ========================================= %qc> %q{a{b}c} %q[a[b]c] %q(a(b)c) --- (program (string (string_content)) (string (string_content)) (string (string_content)) (string (string_content))) ========================================= percent string with unbalanced delimiters ========================================= %/a/ %\a\ %#a# --- (program (string (string_content)) (string (string_content)) (string (string_content))) ========================================= percent string with balanced delimiters ========================================= %c> %{a{b}c} %[a[b]c] %(a(b)c) --- (program (string (string_content)) (string (string_content)) (string (string_content)) (string (string_content))) =========================================== percent Q string with unbalanced delimiters =========================================== %Q#a# %Q/a/ %Q\a\ --- (program (string (string_content)) (string (string_content)) (string (string_content))) ========================================= percent Q string with balanced delimiters ========================================= %Qc> %Q{a{b}c} %Q[a[b]c] %Q(a(b)c) --- (program (string (string_content)) (string (string_content)) (string (string_content)) (string (string_content))) =============== string chaining =============== %q(a) "b" "c" "d" "e" --- (program (chained_string (string (string_content)) (string (string_content)) (string (string_content))) (chained_string (string (string_content)) (string (string_content)))) ========================== newline-delimited strings ========================== flash[:notice] = "Pattern addition failed for '%s' in '%s'", % [pattern, key] ---- (program (assignment (element_reference (identifier) (simple_symbol)) (right_assignment_list (string (string_content)) (string (string_content))))) ========================== % formatting that looks like a newline-delimited strings ========================== foo("%s '%s' " % [a, b]) ---- (program (call (identifier) (argument_list (binary (string (string_content)) (array (identifier) (identifier)))))) ======================================== Single character string literals ======================================== ?a ?? ?\n ?\\ ?\377 ?\u{41} ?\M-a ?\C-a ?\M-\C-a ?あ ?\u028f ?\u{028f} ?\xff foo(?/) --- (program (character) (character) (character) (character) (character) (character) (character) (character) (character) (character) (character) (character) (character) (call (identifier) (argument_list (character)))) ======================================== nested strings with different delimiters ======================================== "abc#{ %r(def(ghi#{ `whoami` })klm) }nop" --- (program (string (string_content) (interpolation (regex (string_content) (interpolation (subshell (string_content))) (string_content))) (string_content))) ======================================== basic heredocs ======================================== <255 chars) ======================================== <<~AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA content AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA --- (program (heredoc_beginning) (heredoc_body (heredoc_content) (heredoc_end))) ======================================== heredoc with interspersed end word ======================================== <<-eos repositories eos --- (program (heredoc_beginning) (heredoc_body (heredoc_content) (heredoc_end))) ======================================== heredoc with end word in content ======================================== < HTML < { select(<<-SQL) . SQL } --- (program (lambda (block (block_body (call (identifier) (argument_list (heredoc_beginning))) (heredoc_body (heredoc_content) (heredoc_end)))))) ======================================== un-terminated heredocs ======================================== <<-ONE --- (program (heredoc_beginning) (heredoc_body (heredoc_content) (heredoc_end))) ================================= no interpolation or escape sequences in single quoted heredoc ================================= <<'EOF' This is \not\ an interpolation: #{foo} EOF <<~'EOF' This is \not\ an interpolation: #{foo} EOF <<-'EOF' This is \not\ an interpolation: #{foo} EOF --- (program (heredoc_beginning) (heredoc_body (heredoc_content) (heredoc_end)) (heredoc_beginning) (heredoc_body (heredoc_content) (heredoc_end)) (heredoc_beginning) (heredoc_body (heredoc_content) (heredoc_end))) ================== backticks subshell ================== `/usr/bin/env test blah blah` --- (program (subshell (string_content))) ============================== backticks subshell with escape ============================== `/usr/bin/env test blah \`blah\`` --- (program (subshell (string_content) (escape_sequence) (string_content) (escape_sequence))) =========== empty array =========== [] --- (program (array)) ===== array ===== [ foo, bar ] [foo, *bar] [foo, *@bar] [foo, *$bar] [foo, :bar => 1] --- (program (array (identifier) (identifier)) (array (identifier) (splat_argument (identifier))) (array (identifier) (splat_argument (instance_variable))) (array (identifier) (splat_argument (global_variable))) (array (identifier) (pair (simple_symbol) (integer)))) ===== array as object ===== [1, 2].any? { |i| i > 1 } --- (program (call receiver: (array (integer) (integer)) method: (identifier) block: (block parameters: (block_parameters (identifier)) body: (block_body (binary left: (identifier) right: (integer)))))) ========================= array with trailing comma ========================= [ foo, ] --- (program (array (identifier))) ===================== empty percent w array ===================== %w() --- (program (string_array)) ========================== unbalanced percent w array ========================== %w/one two/ --- (program (string_array (bare_string (string_content)) (bare_string (string_content)))) =============== percent w array =============== %w(word word) --- (program (string_array (bare_string (string_content)) (bare_string (string_content)))) =================================== percent W array with interpolations =================================== %W(a #{b} c) --- (program (string_array (bare_string (string_content)) (bare_string (interpolation (identifier))) (bare_string (string_content)))) ===================== empty percent i array ===================== %i() --- (program (symbol_array)) ========================== unbalanced percent i array ========================== %i/one two/ --- (program (symbol_array (bare_symbol (string_content)) (bare_symbol (string_content)))) =============== percent i array =============== %i(word word) --- (program (symbol_array (bare_symbol (string_content)) (bare_symbol (string_content)))) ==================================== percent I array with interpolations ==================================== %I(a #{b} c) --- (program (symbol_array (bare_symbol (string_content)) (bare_symbol (interpolation (identifier))) (bare_symbol (string_content)))) ==================================== percent i array with spaces ==================================== %I{ * /#{something}+ ok } --- (program (symbol_array (bare_symbol (string_content)) (bare_symbol (string_content) (interpolation (identifier)) (string_content)) (bare_symbol (string_content)))) ========== empty hash ========== {} --- (program (hash)) ========================= hash with no spaces ========================= {:name=>"foo"} --- (program (hash (pair (simple_symbol) (string (string_content))))) ========================= hash with expression keys ========================= { "a" => 1, "b" => 2 } { [] => 1 } { foo => 1 } --- (program (hash (pair (string (string_content)) (integer)) (pair (string (string_content)) (integer))) (hash (pair (array) (integer))) (hash (pair (identifier) (integer)))) ========================= hash with reserved word key ========================= { alias: :foo, and: :foo, begin: :foo, break: :foo, case: :foo, class: :foo, def: :foo, defined: :foo, do: :foo, else: :foo, elsif: :foo, end: :foo, ensure: :foo, false: :foo, for: :foo, in: :foo, module: :foo, next: :foo, nil: :foo, not: :foo, or: :foo, redo: :foo, rescue: :foo, retry: :foo, return: :foo, self: :foo, super: :foo, then: :foo, true: :foo, undef: :foo, when: :foo, yield: :foo, if: :foo, unless: :foo, while: :foo, until: :foo, until: } --- (program (hash (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol) (simple_symbol)) (pair (hash_key_symbol)))) ====================== hash with keyword keys ====================== { a: 1, b: 2, "c": 3 } {a: 1, B:2, "c":3 } { a:, B: } --- (program (hash (pair (hash_key_symbol) (integer)) (pair (hash_key_symbol) (integer)) (pair (string (string_content)) (integer))) (hash (pair (hash_key_symbol) (integer)) (pair (hash_key_symbol) (integer)) (pair (string (string_content)) (integer))) (hash (pair (hash_key_symbol)) (pair (hash_key_symbol)))) ======================== hash with trailing comma ======================== { a: 1, } --- (program (hash (pair (hash_key_symbol) (integer)))) ======================== hash initialization with hash splat ======================== {a: 1, **{b: 2}} --- (program (hash (pair (hash_key_symbol) (integer)) (hash_splat_argument (hash (pair (hash_key_symbol) (integer)))))) ======================== hash with line breaks and inline comments ======================== { :pusher => pusher, # Only warm caches if there are fewer than 10 tags and branches. :should_warm_caches_after => 10, } --- (program (hash (pair (simple_symbol) (identifier)) (comment) (pair (simple_symbol) (integer)))) ================== regular expression ================== /^(foo|bar[^_])$/i --- (program (regex (string_content))) ===================================== regular expression with interpolation ===================================== /word#{foo}word/ /word#word/ /#/ --- (program (regex (string_content) (interpolation (identifier)) (string_content)) (regex (string_content)) (regex (string_content))) ======================================================= percent r regular expression with unbalanced delimiters ======================================================= %r/a/ %r\a\ %r#a# --- (program (regex (string_content)) (regex (string_content)) (regex (string_content))) ===================================================== percent r regular expression with balanced delimiters ===================================================== %rc> %r{a{b}c} %r[a[b]c] %r(a(b)c) %r(#) --- (program (regex (string_content)) (regex (string_content)) (regex (string_content)) (regex (string_content)) (regex (string_content))) ========================================================================= percent r regular expression with unbalanced delimiters and interpolation ========================================================================= %r/a#{b}c/ --- (program (regex (string_content) (interpolation (identifier)) (string_content))) ======================================================================= percent r regular expression with balanced delimiters and interpolation ======================================================================= %r(a#{b}c) --- (program (regex (string_content) (interpolation (identifier)) (string_content))) ============== empty function ============== -> {} --- (program (lambda (block))) ================== lambda literal with body ================== -> { foo } --- (program (lambda (block (block_body (identifier))))) ==================== lambda literal with an arg ==================== -> foo { 1 } -> (foo) { 1 } -> *foo { 1 } -> foo: 1 { 2 } -> foo, bar { 2 } --- (program (lambda (lambda_parameters (identifier)) (block (block_body (integer)))) (lambda (lambda_parameters (identifier)) (block (block_body (integer)))) (lambda (lambda_parameters (splat_parameter (identifier))) (block (block_body (integer)))) (lambda (lambda_parameters (keyword_parameter (identifier) (integer))) (block (block_body (integer)))) (lambda (lambda_parameters (identifier) (identifier)) (block (block_body (integer))))) =========================== lambda literal with multiple args =========================== -> (a, b, c) { 1 2 } --- (program (lambda (lambda_parameters (identifier) (identifier) (identifier)) (block (block_body (integer) (integer))))) ==================== lambda literal with do end ==================== -> (foo) do 1 end --- (program (lambda (lambda_parameters (identifier)) (do_block (body_statement (integer))))) ==================== non-ascii identifiers ==================== Cß @äö @@äö :äö äö --- (program (constant) (instance_variable) (class_variable) (simple_symbol) (identifier)) ================================================ FILE: test/corpus/patterns.txt ================================================ ================ pattern matching ================ case expr in 5 then true else false end case expr in x unless x < 0 then true in x if x < 0 then true else false end case expr in 5 in 5, in 1, 2 in 1, 2, in 1, 2, 3 in 1, 2, 3, in 1, 2, 3, * in 1, *x, 3 in * in *, 3, 4 in *, 3, * in *a, 3, *b in a: in a: 5 in a: 5, in a: 5, b:, ** in a: 5, b:, **map in a: 5, b:, **nil in **nil in [5] in [5,] in [1, 2] in [1, 2,] in [1, 2, 3] in [1, 2, 3,] in [1, 2, 3, *] in [1, *x, 3] in [*] in [*, 3, 4] in [*, 3, *] in [*a, 3, *b] in {a:} in {a: 5} in {a: 5,} in {a: 5, b:, **} in {a: 5, b:, **map} in {a: 5, b:, **nil} in {**nil} in {} in [] end ----- (program (case_match (identifier) (in_clause (integer) (then (true)) ) (else (false))) (case_match (identifier) (in_clause (identifier) (unless_guard (binary (identifier) (integer))) (then (true)) ) (in_clause (identifier) (if_guard (binary (identifier) (integer))) (then (true)) ) (else (false)) ) (case_match (identifier) (in_clause (integer)) (in_clause (array_pattern (integer) (splat_parameter))) (in_clause (array_pattern (integer) (integer))) (in_clause (array_pattern (integer) (integer) (splat_parameter))) (in_clause (array_pattern (integer) (integer) (integer))) (in_clause (array_pattern (integer) (integer) (integer) (splat_parameter))) (in_clause (array_pattern (integer) (integer) (integer) (splat_parameter))) (in_clause (array_pattern (integer) (splat_parameter (identifier)) (integer))) (in_clause (array_pattern (splat_parameter))) (in_clause (array_pattern (splat_parameter) (integer) (integer))) (in_clause (find_pattern (splat_parameter) (integer) (splat_parameter))) (in_clause (find_pattern (splat_parameter (identifier)) (integer) (splat_parameter (identifier)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter (identifier)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_nil))) (in_clause (hash_pattern (hash_splat_nil))) (in_clause (array_pattern (integer))) (in_clause (array_pattern (integer) (splat_parameter))) (in_clause (array_pattern (integer) (integer))) (in_clause (array_pattern (integer) (integer) (splat_parameter))) (in_clause (array_pattern (integer) (integer) (integer))) (in_clause (array_pattern (integer) (integer) (integer) (splat_parameter))) (in_clause (array_pattern (integer) (integer) (integer) (splat_parameter))) (in_clause (array_pattern (integer) (splat_parameter (identifier)) (integer))) (in_clause (array_pattern (splat_parameter))) (in_clause (array_pattern (splat_parameter) (integer) (integer))) (in_clause (find_pattern (splat_parameter) (integer) (splat_parameter))) (in_clause (find_pattern (splat_parameter (identifier)) (integer) (splat_parameter (identifier)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter (identifier)))) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_nil))) (in_clause (hash_pattern (hash_splat_nil))) (in_clause (hash_pattern)) (in_clause (array_pattern)) ) ) ===================== more pattern matching ===================== case expr in 5 in ^foo in ^$foo in ^@foo in ^@@foo in ^(1+1) in ^(foo) in ^(Foo::Bar) in var in "string" in %w(foo bar) in %i(foo bar) in /.*abc[0-9]/ in 5 .. 10 in .. 10 in 5 .. in 5 => x in 5 | ^foo | var | "string" in Foo in Foo::Bar in ::Foo::Bar in (nil | self | true | false | __LINE__ | __FILE__ | __ENCODING__) in -> x { x == 10 } in :foo in :"foo bar" in -5 | +10 end -------- (program (case_match (identifier) (in_clause (integer)) (in_clause (variable_reference_pattern (identifier))) (in_clause (variable_reference_pattern (global_variable))) (in_clause (variable_reference_pattern (instance_variable))) (in_clause (variable_reference_pattern (class_variable))) (in_clause (expression_reference_pattern (binary (integer) (integer)))) (in_clause (expression_reference_pattern (identifier))) (in_clause (expression_reference_pattern (scope_resolution (constant) (constant)))) (in_clause (identifier)) (in_clause (string (string_content))) (in_clause (string_array (bare_string (string_content)) (bare_string (string_content)))) (in_clause (symbol_array (bare_symbol (string_content)) (bare_symbol (string_content)))) (in_clause (regex (string_content))) (in_clause (range (integer) (integer))) (in_clause (range (integer))) (in_clause (range (integer))) (in_clause (as_pattern (integer) (identifier))) (in_clause (alternative_pattern (integer) (variable_reference_pattern (identifier)) (identifier) (string (string_content)) ) ) (in_clause (constant)) (in_clause (scope_resolution (constant) (constant))) (in_clause (scope_resolution (scope_resolution (constant)) (constant))) (in_clause (parenthesized_pattern (alternative_pattern (nil) (self) (true) (false) (line) (file) (encoding) ) ) ) (in_clause (lambda (lambda_parameters (identifier)) (block (block_body (binary (identifier) (integer)))))) (in_clause (simple_symbol)) (in_clause (delimited_symbol (string_content))) (in_clause (alternative_pattern (unary (integer)) (unary (integer)) ) ) ) ) ============== array patterns ============== case expr in []; in [x]; in [x, ]; in Foo::Bar[]; in Foo(); in Bar(*); in Bar(a, b, *c, d, e); end -------------- (program (case_match (identifier) (in_clause (array_pattern)) (in_clause (array_pattern (identifier))) (in_clause (array_pattern (identifier) (splat_parameter))) (in_clause (array_pattern (scope_resolution (constant) (constant)))) (in_clause (array_pattern (constant))) (in_clause (array_pattern (constant) (splat_parameter))) (in_clause (array_pattern (constant) (identifier) (identifier) (splat_parameter (identifier)) (identifier) (identifier) ) ) ) ) ============= find patterns ============= case expr in [*, x, *]; in [*x, 1, 2, *y]; in Foo::Bar[*, 1, *]; in Foo(*, Bar, *); end ------------- (program (case_match (identifier) (in_clause (find_pattern (splat_parameter) (identifier) (splat_parameter))) (in_clause (find_pattern (splat_parameter (identifier)) (integer) (integer) (splat_parameter (identifier)))) (in_clause (find_pattern (scope_resolution (constant) (constant)) (splat_parameter) (integer) (splat_parameter)) ) (in_clause (find_pattern (constant) (splat_parameter) (constant) (splat_parameter))) ) ) ============= hash patterns ============= case expr in {}; in {x:}; in Foo::Bar[ x:1 ]; in Foo::Bar[ x:1, a:, **rest ]; in Foo( y:); in Bar( ** ); in Bar( a: 1, **nil); end ------------- (program (case_match (identifier) (in_clause (hash_pattern)) (in_clause (hash_pattern (keyword_pattern (hash_key_symbol)))) (in_clause (hash_pattern (scope_resolution (constant) (constant)) (keyword_pattern (hash_key_symbol) (integer)) )) (in_clause (hash_pattern (scope_resolution (constant) (constant)) (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter (identifier)) )) (in_clause (hash_pattern (constant) (keyword_pattern (hash_key_symbol)))) (in_clause (hash_pattern (constant) (hash_splat_parameter))) (in_clause (hash_pattern (constant) (keyword_pattern (hash_key_symbol) (integer)) (hash_splat_nil))) ) ) ===================== pattern matching with fancy string literals ===================== case expr in "string"; in `ls`; in <<"DOC" then end some text DOC --- (program (case_match value: (identifier) clauses: (in_clause pattern: (string (string_content))) clauses: (in_clause pattern: (subshell (string_content))) clauses: (in_clause pattern: (heredoc_beginning) body: (then))) (heredoc_body (heredoc_content) (heredoc_end))) ================= one-line patterns ================= x in Foo(y:) case foo in 5 in true then 1 end case foo in 5; in true then 1 end case (foo x) in 5; in true then 1 end x => 6 | 7 return x => 6 | 7 ----------------- (program (test_pattern (identifier) (hash_pattern (constant) (keyword_pattern (hash_key_symbol)))) (case_match (test_pattern (identifier) (integer)) (in_clause (true) (then (integer)))) (case_match (test_pattern (identifier) (integer)) (in_clause (true) (then (integer)))) (case_match (test_pattern (parenthesized_statements (call (identifier) (argument_list (identifier)))) (integer)) (in_clause (true) (then (integer)))) (match_pattern (identifier) (alternative_pattern (integer) (integer))) (return (argument_list (pair (identifier) (binary (integer) (integer))))) ) ===================================== one-line patterns: incorrectly parsed ===================================== foo x in 5 # FIXME: should be parsed as `(foo x) in 5` instead of `foo (x in 5)` ----------------- (program (call (identifier) (argument_list (test_pattern (identifier) (integer)))) (comment) ) ================================================ FILE: test/corpus/single-cr-as-whitespace.txt ================================================ ================================== Single CR characters as whitespace ================================== puts "hi" --- (program (call (identifier) (argument_list (string (string_content))))) ================================================ FILE: test/corpus/statements.txt ================================================ ==================== conditional modifier ==================== foo if bar return if false return true if foo bar return nil if foo --- (program (if_modifier (identifier) (identifier)) (if_modifier (return) (false)) (if_modifier (return (argument_list (true))) (call (identifier) (argument_list (identifier)))) (if_modifier (return (argument_list (nil))) (identifier))) ============== while modifier ============== foo while bar --- (program (while_modifier body: (identifier) condition: (identifier))) =============== unless modifier =============== foo unless bar --- (program (unless_modifier body: (identifier) condition: (identifier))) ============== until modifier ============== foo until bar --- (program (until_modifier (identifier) (identifier))) ======== alias ======== alias :foo :bar alias foo bar alias $FOO $& alias foo + --- (program (alias (simple_symbol) (simple_symbol)) (alias (identifier) (identifier)) (alias (global_variable) (global_variable)) (alias (identifier) (operator))) ======== undef ======== undef :foo undef foo undef + undef :foo, :bar --- (program (undef (simple_symbol)) (undef (identifier)) (undef (operator)) (undef (simple_symbol) (simple_symbol))) ================================================ FILE: test/highlight/classes.rb ================================================ require "a" # ^ function.method.builtin class Car < Vehicle # <- keyword # ^ constructor def init(id) # <- keyword # ^ function.method @id = id # <- property # ^ variable.parameter yield # <- keyword return # <- keyword next # <- keyword end private # ^ keyword public # ^ keyword protected # ^ keyword end # <- keyword ================================================ FILE: test/highlight/constants.rb ================================================ class MyClass # ^ constructor ELEMENT8 = 8 # ^ constant ELEMENT16 = 16 # ^ constant def OtherClass # ^ function.method @other.OtherClass(Something.new).inspect # ^ property # ^ function.method # ^ constructor # ^ function.method # ^ function.method end end if __FILE__ == $0 # ^ constant.builtin end ================================================ FILE: test/highlight/literals.rb ================================================ "hello" # ^ string %(hello) # ^ string %w(hello goodbye) # ^ string # ^ string :hello # ^ string.special.symbol %s(hello) # ^ string.special.symbol %I(hello goodbye) # ^ string.special.symbol # ^ string.special.symbol /hello/ # ^ string.special.regex %r(hello) # ^ string.special.regex 12345 # ^ number 12.345 # ^ number nil # ^ constant.builtin true # ^ constant.builtin TRUE # ^ constant false # ^ constant.builtin FALSE # ^ constant ================================================ FILE: test/highlight/patterns.rb ================================================ expr = [false | __LINE__ | __FILE__ | __ENCODING__] # ^ constant.builtin # ^ constant.builtin # ^ constant.builtin # ^ constant.builtin case expr in {a: 5, b:, **nil} # ^ operator # ^ constant.builtin in [false | __LINE__ | __FILE__ | __ENCODING__] # ^ constant.builtin # ^ constant.builtin # ^ constant.builtin # ^ constant.builtin else end ================================================ FILE: test/highlight/variables.rb ================================================ one = 1 # <- variable def two() three = one # ^ variable # ^ function.method four = three # ^ variable # ^ variable four.each do |i| puts i, three, five # ^ variable.parameter # ^ variable (because blocks are closures) # ^ function.method end four.each do |(a, b), c: d, e = f| # ^ variable.parameter # ^ variable.parameter # ^ variable.parameter # ^ function.method # ^ variable.parameter # ^ function.method puts a, b, c, d, e, f # ^ variable.parameter # ^ variable.parameter # ^ variable.parameter # ^ function.method # ^ variable.parameter # ^ function.method end five ||= 1 # ^ variable six -> (seven) { eight(seven, five) } # ^ function.method # ^ variable.parameter # ^ function.method # ^ variable.parameter # ^ variable seven # ^ function.method (because the `seven` above was in the scope of the lambda) end ================================================ FILE: tree-sitter.json ================================================ { "grammars": [ { "name": "ruby", "camelcase": "Ruby", "scope": "source.ruby", "path": ".", "file-types": [ "rb" ], "highlights": "queries/highlights.scm", "tags": "queries/tags.scm", "injection-regex": "ruby" } ], "metadata": { "version": "0.23.1", "license": "MIT", "description": "Ruby grammar for tree-sitter", "authors": [ { "name": "Rob Rix", "email": "rob.rix@github.com" }, { "name": "Max Brunsfeld", "email": "maxbrunsfeld@gmail.com" }, { "name": "Amaan Qureshi", "email": "amaanq12@gmail.com" } ], "links": { "repository": "https://github.com/tree-sitter/tree-sitter-ruby" } }, "bindings": { "c": true, "go": true, "node": true, "python": true, "rust": true, "swift": true } }