├── .editorconfig ├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ ├── publish.yml │ └── release.yml ├── .gitignore ├── CMakeLists.txt ├── Cargo.lock ├── Cargo.toml ├── LICENSE.md ├── Makefile ├── Package.resolved ├── Package.swift ├── README.md ├── binding.gyp ├── bindings ├── c │ ├── tree-sitter-lua.pc.in │ └── tree_sitter │ │ └── tree-sitter-lua.h ├── go │ ├── binding.go │ └── binding_test.go ├── node │ ├── binding.cc │ ├── binding_test.js │ ├── index.d.ts │ └── index.js ├── python │ ├── tests │ │ └── test_binding.py │ └── tree_sitter_lua │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ ├── binding.c │ │ └── py.typed ├── rust │ ├── build.rs │ └── lib.rs └── swift │ ├── TreeSitterLua │ └── lua.h │ └── TreeSitterLuaTests │ └── TreeSitterLuaTests.swift ├── go.mod ├── go.sum ├── grammar.js ├── package-lock.json ├── package.json ├── pyproject.toml ├── queries ├── highlights.scm ├── injections.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 │ ├── chunk.txt │ ├── comments.txt │ ├── expressions.txt │ └── statements.txt ├── highlight │ └── string.lua └── tags │ └── functions.lua └── tree-sitter.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | 6 | [*.{json,toml,yml,gyp}] 7 | indent_style = space 8 | indent_size = 2 9 | 10 | [*.js] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.scm] 15 | indent_style = space 16 | indent_size = 2 17 | 18 | [*.{c,cc,h}] 19 | indent_style = space 20 | indent_size = 4 21 | 22 | [*.rs] 23 | indent_style = space 24 | indent_size = 4 25 | 26 | [*.{py,pyi}] 27 | indent_style = space 28 | indent_size = 4 29 | 30 | [*.swift] 31 | indent_style = space 32 | indent_size = 4 33 | 34 | [*.go] 35 | indent_style = tab 36 | indent_size = 8 37 | 38 | [Makefile] 39 | indent_style = tab 40 | indent_size = 8 41 | 42 | [parser.c] 43 | indent_size = 2 44 | 45 | [{alloc,array,parser}.h] 46 | indent_size = 2 47 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | # Generated source files 4 | src/*.json linguist-generated 5 | src/parser.c linguist-generated 6 | src/tree_sitter/* linguist-generated 7 | 8 | # C bindings 9 | bindings/c/** linguist-generated 10 | CMakeLists.txt linguist-generated 11 | Makefile linguist-generated 12 | 13 | # Rust bindings 14 | bindings/rust/* linguist-generated 15 | Cargo.toml linguist-generated 16 | Cargo.lock linguist-generated 17 | 18 | # Node.js bindings 19 | bindings/node/* linguist-generated 20 | binding.gyp linguist-generated 21 | package.json linguist-generated 22 | package-lock.json linguist-generated 23 | 24 | # Python bindings 25 | bindings/python/** linguist-generated 26 | setup.py linguist-generated 27 | pyproject.toml linguist-generated 28 | 29 | # Go bindings 30 | bindings/go/* linguist-generated 31 | go.mod linguist-generated 32 | go.sum linguist-generated 33 | 34 | # Swift bindings 35 | bindings/swift/** linguist-generated 36 | Package.swift linguist-generated 37 | Package.resolved linguist-generated 38 | 39 | # Zig bindings 40 | build.zig linguist-generated 41 | build.zig.zon linguist-generated 42 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | workflow_dispatch: 8 | 9 | concurrency: 10 | group: ${{github.workflow}}-${{github.ref}} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | test: 15 | name: Test parser 16 | runs-on: ${{matrix.os}} 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | os: [ubuntu-latest, windows-latest, macos-latest] 21 | steps: 22 | - name: Checkout repository 23 | uses: actions/checkout@v4 24 | 25 | - name: Set up tree-sitter 26 | uses: tree-sitter/setup-action@v2 27 | with: 28 | install-lib: false 29 | 30 | - name: Run tests 31 | uses: tree-sitter/parser-test-action@v2 32 | 33 | - name: Clone apisix corpus 34 | uses: actions/checkout@v4 35 | with: 36 | path: examples/apisix 37 | repository: apache/apisix 38 | sparse-checkout: apisix/ 39 | - name: Clone kong corpus 40 | uses: actions/checkout@v4 41 | with: 42 | path: examples/kong 43 | repository: Kong/kong 44 | sparse-checkout: kong/ 45 | - name: Clone lua corpus 46 | uses: actions/checkout@v4 47 | with: 48 | path: examples/lua 49 | repository: lua/lua 50 | ref: e05590591410a5e007a1e3f1691f6c1cf9d8fe45 51 | sparse-checkout: testes/ 52 | - name: Clone luvit corpus 53 | uses: actions/checkout@v4 54 | with: 55 | path: examples/luvit 56 | repository: luvit/luvit 57 | - name: Clone neovim corpus 58 | uses: actions/checkout@v4 59 | with: 60 | path: examples/neovim 61 | repository: neovim/neovim 62 | sparse-checkout-cone-mode: false 63 | sparse-checkout: |- 64 | /test/**/*.lua 65 | /scripts/**/*.lua 66 | /runtime/**/*.lua 67 | - name: Clone xmake corpus 68 | uses: actions/checkout@v4 69 | if: runner.os != 'Windows' 70 | with: 71 | path: examples/xmake 72 | repository: xmake-io/xmake 73 | 74 | - name: Parse examples 75 | uses: tree-sitter/parse-action@v4 76 | with: 77 | files: |- 78 | examples/apisix/**/*.lua 79 | examples/kong/**/*.lua 80 | examples/lua/**/*.lua 81 | examples/luvit/**/*.lua 82 | examples/neovim/**/*.lua 83 | examples/xmake/**/*.lua 84 | # FIXME: these fail to parse on Windows 85 | !examples/lua/testes/api.lua 86 | !examples/lua/testes/calls.lua 87 | !examples/lua/testes/db.lua 88 | invalid-files: |- 89 | examples/neovim/test/functional/fixtures/lua/syntax_error.lua 90 | 91 | fuzz: 92 | runs-on: ubuntu-latest 93 | steps: 94 | - name: Checkout repository 95 | uses: actions/checkout@v4 96 | with: 97 | fetch-depth: 2 98 | - name: Check for scanner changes 99 | id: scanner-changes 100 | run: |- 101 | if git diff --quiet HEAD^ -- src/scanner.c; then 102 | printf 'changed=false\n' >> "$GITHUB_OUTPUT" 103 | else 104 | printf 'changed=true\n' >> "$GITHUB_OUTPUT" 105 | fi 106 | - name: Fuzz parser 107 | uses: tree-sitter/fuzz-action@v4 108 | if: steps.scanner-changes.outputs.changed == 'true' 109 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish package 2 | 3 | on: 4 | push: 5 | tags: ["*"] 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: write 10 | id-token: write 11 | 12 | jobs: 13 | npm: 14 | uses: tree-sitter/workflows/.github/workflows/package-npm.yml@main 15 | with: 16 | package-name: "@tree-sitter-grammars/tree-sitter-lua" 17 | secrets: 18 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 19 | crates: 20 | uses: tree-sitter/workflows/.github/workflows/package-crates.yml@main 21 | secrets: 22 | CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_TOKEN}} 23 | pypi: 24 | uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@main 25 | secrets: 26 | PYPI_API_TOKEN: ${{secrets.PYPI_TOKEN}} 27 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create release 2 | 3 | on: 4 | push: 5 | tags: ["*"] 6 | workflow_dispatch: 7 | 8 | concurrency: 9 | group: ${{github.workflow}}-${{github.ref}} 10 | cancel-in-progress: true 11 | 12 | permissions: 13 | contents: write 14 | id-token: write 15 | attestations: write 16 | 17 | jobs: 18 | release: 19 | uses: tree-sitter/workflows/.github/workflows/release.yml@main 20 | with: 21 | attestations: true 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Rust artifacts 2 | target/ 3 | 4 | # Node artifacts 5 | build/ 6 | prebuilds/ 7 | node_modules/ 8 | 9 | # Swift artifacts 10 | .build/ 11 | 12 | # Go artifacts 13 | _obj/ 14 | 15 | # Python artifacts 16 | .venv/ 17 | dist/ 18 | *.egg-info 19 | *.whl 20 | 21 | # C artifacts 22 | *.a 23 | *.so 24 | *.so.* 25 | *.dylib 26 | *.dll 27 | *.pc 28 | *.exp 29 | *.lib 30 | 31 | # Zig artifacts 32 | .zig-cache/ 33 | zig-cache/ 34 | zig-out/ 35 | 36 | # Example dirs 37 | /examples/*/ 38 | 39 | # Grammar volatiles 40 | *.wasm 41 | *.obj 42 | *.o 43 | 44 | # Archives 45 | *.tar.gz 46 | *.tgz 47 | *.zip 48 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | project(tree-sitter-lua 4 | VERSION "0.4.0" 5 | DESCRIPTION "Lua grammar for tree-sitter" 6 | HOMEPAGE_URL "https://github.com/tree-sitter-grammars/tree-sitter-lua" 7 | LANGUAGES C) 8 | 9 | option(BUILD_SHARED_LIBS "Build using shared libraries" ON) 10 | option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF) 11 | 12 | set(TREE_SITTER_ABI_VERSION 15 CACHE STRING "Tree-sitter ABI version") 13 | if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$") 14 | unset(TREE_SITTER_ABI_VERSION CACHE) 15 | message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer") 16 | endif() 17 | 18 | find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI") 19 | 20 | add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c" 21 | DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json" 22 | COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json 23 | --abi=${TREE_SITTER_ABI_VERSION} 24 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 25 | COMMENT "Generating parser.c") 26 | 27 | add_library(tree-sitter-lua src/parser.c) 28 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c) 29 | target_sources(tree-sitter-lua PRIVATE src/scanner.c) 30 | endif() 31 | target_include_directories(tree-sitter-lua 32 | PRIVATE src 33 | INTERFACE $ 34 | $) 35 | 36 | target_compile_definitions(tree-sitter-lua PRIVATE 37 | $<$:TREE_SITTER_REUSE_ALLOCATOR> 38 | $<$:TREE_SITTER_DEBUG>) 39 | 40 | set_target_properties(tree-sitter-lua 41 | PROPERTIES 42 | C_STANDARD 11 43 | POSITION_INDEPENDENT_CODE ON 44 | SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}" 45 | DEFINE_SYMBOL "") 46 | 47 | configure_file(bindings/c/tree-sitter-lua.pc.in 48 | "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-lua.pc" @ONLY) 49 | 50 | include(GNUInstallDirs) 51 | 52 | install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bindings/c/tree_sitter" 53 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 54 | FILES_MATCHING PATTERN "*.h") 55 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-lua.pc" 56 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig") 57 | install(TARGETS tree-sitter-lua 58 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") 59 | 60 | file(GLOB QUERIES queries/*.scm) 61 | install(FILES ${QUERIES} 62 | DESTINATION "${CMAKE_INSTALL_DATADIR}/tree-sitter/queries/lua") 63 | 64 | add_custom_target(ts-test "${TREE_SITTER_CLI}" test 65 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 66 | COMMENT "tree-sitter test") 67 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "cc" 16 | version = "1.2.23" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" 19 | dependencies = [ 20 | "shlex", 21 | ] 22 | 23 | [[package]] 24 | name = "equivalent" 25 | version = "1.0.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 28 | 29 | [[package]] 30 | name = "hashbrown" 31 | version = "0.15.3" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" 34 | 35 | [[package]] 36 | name = "indexmap" 37 | version = "2.9.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 40 | dependencies = [ 41 | "equivalent", 42 | "hashbrown", 43 | ] 44 | 45 | [[package]] 46 | name = "itoa" 47 | version = "1.0.15" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 50 | 51 | [[package]] 52 | name = "memchr" 53 | version = "2.7.4" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 56 | 57 | [[package]] 58 | name = "proc-macro2" 59 | version = "1.0.95" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 62 | dependencies = [ 63 | "unicode-ident", 64 | ] 65 | 66 | [[package]] 67 | name = "quote" 68 | version = "1.0.40" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 71 | dependencies = [ 72 | "proc-macro2", 73 | ] 74 | 75 | [[package]] 76 | name = "regex" 77 | version = "1.11.1" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 80 | dependencies = [ 81 | "aho-corasick", 82 | "memchr", 83 | "regex-automata", 84 | "regex-syntax", 85 | ] 86 | 87 | [[package]] 88 | name = "regex-automata" 89 | version = "0.4.9" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 92 | dependencies = [ 93 | "aho-corasick", 94 | "memchr", 95 | "regex-syntax", 96 | ] 97 | 98 | [[package]] 99 | name = "regex-syntax" 100 | version = "0.8.5" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 103 | 104 | [[package]] 105 | name = "ryu" 106 | version = "1.0.20" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 109 | 110 | [[package]] 111 | name = "serde" 112 | version = "1.0.219" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 115 | dependencies = [ 116 | "serde_derive", 117 | ] 118 | 119 | [[package]] 120 | name = "serde_derive" 121 | version = "1.0.219" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 124 | dependencies = [ 125 | "proc-macro2", 126 | "quote", 127 | "syn", 128 | ] 129 | 130 | [[package]] 131 | name = "serde_json" 132 | version = "1.0.140" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 135 | dependencies = [ 136 | "indexmap", 137 | "itoa", 138 | "memchr", 139 | "ryu", 140 | "serde", 141 | ] 142 | 143 | [[package]] 144 | name = "shlex" 145 | version = "1.3.0" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 148 | 149 | [[package]] 150 | name = "streaming-iterator" 151 | version = "0.1.9" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" 154 | 155 | [[package]] 156 | name = "syn" 157 | version = "2.0.101" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 160 | dependencies = [ 161 | "proc-macro2", 162 | "quote", 163 | "unicode-ident", 164 | ] 165 | 166 | [[package]] 167 | name = "tree-sitter" 168 | version = "0.25.4" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "69aff09fea9a41fb061ae6b206cb87cac1b8db07df31be3ba271fbc26760f213" 171 | dependencies = [ 172 | "cc", 173 | "regex", 174 | "regex-syntax", 175 | "serde_json", 176 | "streaming-iterator", 177 | "tree-sitter-language", 178 | ] 179 | 180 | [[package]] 181 | name = "tree-sitter-language" 182 | version = "0.1.5" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8" 185 | 186 | [[package]] 187 | name = "tree-sitter-lua" 188 | version = "0.4.0" 189 | dependencies = [ 190 | "cc", 191 | "tree-sitter", 192 | "tree-sitter-language", 193 | ] 194 | 195 | [[package]] 196 | name = "unicode-ident" 197 | version = "1.0.18" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 200 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tree-sitter-lua" 3 | description = "Lua grammar for tree-sitter" 4 | version = "0.4.0" 5 | authors = ["Munif Tanjim "] 6 | license = "MIT" 7 | readme = "README.md" 8 | keywords = ["incremental", "parsing", "tree-sitter", "lua"] 9 | categories = ["parser-implementations", "parsing", "text-editors"] 10 | repository = "https://github.com/tree-sitter-grammars/tree-sitter-lua" 11 | edition = "2021" 12 | autoexamples = false 13 | 14 | build = "bindings/rust/build.rs" 15 | include = [ 16 | "bindings/rust/*", 17 | "grammar.js", 18 | "queries/*", 19 | "src/*", 20 | "tree-sitter.json", 21 | "LICENSE", 22 | ] 23 | 24 | [lib] 25 | path = "bindings/rust/lib.rs" 26 | 27 | [dependencies] 28 | tree-sitter-language = "0.1" 29 | 30 | [build-dependencies] 31 | cc = "1.2" 32 | 33 | [dev-dependencies] 34 | tree-sitter = "0.25.3" 35 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Munif Tanjim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | $(error Windows is not supported) 3 | endif 4 | 5 | LANGUAGE_NAME := tree-sitter-lua 6 | HOMEPAGE_URL := https://github.com/tree-sitter-grammars/tree-sitter-lua 7 | VERSION := 0.4.0 8 | 9 | # repository 10 | SRC_DIR := src 11 | 12 | TS ?= tree-sitter 13 | 14 | # install directory layout 15 | PREFIX ?= /usr/local 16 | DATADIR ?= $(PREFIX)/share 17 | INCLUDEDIR ?= $(PREFIX)/include 18 | LIBDIR ?= $(PREFIX)/lib 19 | PCLIBDIR ?= $(LIBDIR)/pkgconfig 20 | 21 | # source/object files 22 | PARSER := $(SRC_DIR)/parser.c 23 | EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c)) 24 | OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS)) 25 | 26 | # flags 27 | ARFLAGS ?= rcs 28 | override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC 29 | 30 | # ABI versioning 31 | SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER)) 32 | SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION))) 33 | 34 | # OS-specific bits 35 | ifeq ($(shell uname),Darwin) 36 | SOEXT = dylib 37 | SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT) 38 | SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT) 39 | LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks 40 | else 41 | SOEXT = so 42 | SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR) 43 | SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR) 44 | LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER) 45 | endif 46 | ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),) 47 | PCLIBDIR := $(PREFIX)/libdata/pkgconfig 48 | endif 49 | 50 | all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc 51 | 52 | lib$(LANGUAGE_NAME).a: $(OBJS) 53 | $(AR) $(ARFLAGS) $@ $^ 54 | 55 | lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS) 56 | $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@ 57 | ifneq ($(STRIP),) 58 | $(STRIP) $@ 59 | endif 60 | 61 | $(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in 62 | sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \ 63 | -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \ 64 | -e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \ 65 | -e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \ 66 | -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \ 67 | -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@ 68 | 69 | $(PARSER): $(SRC_DIR)/grammar.json 70 | $(TS) generate $^ 71 | 72 | install: all 73 | install -d '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/lua '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)' 74 | install -m644 bindings/c/tree_sitter/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h 75 | install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc 76 | install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a 77 | install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) 78 | ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) 79 | ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) 80 | ifneq ($(wildcard queries/*.scm),) 81 | install -m644 queries/*.scm '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/lua 82 | endif 83 | 84 | uninstall: 85 | $(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \ 86 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \ 87 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \ 88 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \ 89 | '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \ 90 | '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc 91 | $(RM) -r '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/lua 92 | 93 | clean: 94 | $(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) 95 | 96 | test: 97 | $(TS) test 98 | 99 | .PHONY: all install uninstall clean test 100 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "SwiftTreeSitter", 6 | "repositoryURL": "https://github.com/tree-sitter/swift-tree-sitter", 7 | "state": { 8 | "branch": null, 9 | "revision": "36aa61d1b531f744f35229f010efba9c6d6cbbdd", 10 | "version": "0.9.0" 11 | } 12 | }, 13 | { 14 | "package": "TreeSitter", 15 | "repositoryURL": "https://github.com/tree-sitter/tree-sitter", 16 | "state": { 17 | "branch": null, 18 | "revision": "d97db6d63507eb62c536bcb2c4ac7d70c8ec665e", 19 | "version": "0.23.2" 20 | } 21 | } 22 | ] 23 | }, 24 | "version": 1 25 | } 26 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | 3 | import Foundation 4 | import PackageDescription 5 | 6 | var sources = ["src/parser.c"] 7 | if FileManager.default.fileExists(atPath: "src/scanner.c") { 8 | sources.append("src/scanner.c") 9 | } 10 | 11 | let package = Package( 12 | name: "TreeSitterLua", 13 | products: [ 14 | .library(name: "TreeSitterLua", targets: ["TreeSitterLua"]), 15 | ], 16 | dependencies: [ 17 | .package(name: "SwiftTreeSitter", url: "https://github.com/tree-sitter/swift-tree-sitter", from: "0.9.0"), 18 | ], 19 | targets: [ 20 | .target( 21 | name: "TreeSitterLua", 22 | dependencies: [], 23 | path: ".", 24 | sources: sources, 25 | resources: [ 26 | .copy("queries") 27 | ], 28 | publicHeadersPath: "bindings/swift", 29 | cSettings: [.headerSearchPath("src")] 30 | ), 31 | .testTarget( 32 | name: "TreeSitterLuaTests", 33 | dependencies: [ 34 | "SwiftTreeSitter", 35 | "TreeSitterLua", 36 | ], 37 | path: "bindings/swift/TreeSitterLuaTests" 38 | ) 39 | ], 40 | cLanguageStandard: .c11 41 | ) 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-lua 2 | 3 | [![CI][ci]](https://github.com/tree-sitter-grammars/tree-sitter-lua/actions/workflows/ci.yml) 4 | [![discord][discord]](https://discord.gg/w7nTvsVJhm) 5 | [![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org) 6 | [![npm][npm]](https://www.npmjs.com/package/%40tree-sitter-grammars%2Ftree-sitter-lua) 7 | [![crates][crates]](https://crates.io/crates/tree-sitter-lua) 8 | 9 | Lua grammar for tree-sitter. 10 | 11 | - Lua 5.x 12 | - LuaJIT 2.x 13 | 14 | ## References 15 | 16 | - [Lua Documentation](https://www.lua.org/docs.html) 17 | 18 | ## Acknowledgement 19 | 20 | The [external scanner](/src/scanner.c) was initially based on these repositories: 21 | 22 | - [Azganoth/tree-sitter-lua](https://github.com/Azganoth/tree-sitter-lua) 23 | - [euclidianAce/tree-sitter-teal](https://github.com/euclidianAce/tree-sitter-teal) 24 | 25 | [ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter-grammars/tree-sitter-lua/ci.yml?logo=github&label=CI 26 | [discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord 27 | [matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix 28 | [npm]: https://img.shields.io/npm/v/%40tree-sitter-grammars%2Ftree-sitter-lua?logo=npm 29 | [crates]: https://img.shields.io/crates/v/tree-sitter-lua?logo=rust 30 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_lua_binding", 5 | "dependencies": [ 6 | " 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | extern "C" TSLanguage *tree_sitter_lua(); 6 | 7 | // "tree-sitter", "language" hashed with BLAKE2 8 | const napi_type_tag LANGUAGE_TYPE_TAG = { 9 | 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16 10 | }; 11 | 12 | Napi::Object Init(Napi::Env env, Napi::Object exports) { 13 | auto language = Napi::External::New(env, tree_sitter_lua()); 14 | language.TypeTag(&LANGUAGE_TYPE_TAG); 15 | exports["language"] = language; 16 | return exports; 17 | } 18 | 19 | NODE_API_MODULE(tree_sitter_lua_binding, Init) 20 | -------------------------------------------------------------------------------- /bindings/node/binding_test.js: -------------------------------------------------------------------------------- 1 | const assert = require("node:assert"); 2 | const { test } = require("node:test"); 3 | 4 | const Parser = require("tree-sitter"); 5 | 6 | test("can load grammar", () => { 7 | const parser = new Parser(); 8 | assert.doesNotThrow(() => parser.setLanguage(require("."))); 9 | }); 10 | -------------------------------------------------------------------------------- /bindings/node/index.d.ts: -------------------------------------------------------------------------------- 1 | type BaseNode = { 2 | type: string; 3 | named: boolean; 4 | }; 5 | 6 | type ChildNode = { 7 | multiple: boolean; 8 | required: boolean; 9 | types: BaseNode[]; 10 | }; 11 | 12 | type NodeInfo = 13 | | (BaseNode & { 14 | subtypes: BaseNode[]; 15 | }) 16 | | (BaseNode & { 17 | fields: { [name: string]: ChildNode }; 18 | children: ChildNode[]; 19 | }); 20 | 21 | type Language = { 22 | language: unknown; 23 | nodeTypeInfo: NodeInfo[]; 24 | }; 25 | 26 | declare const language: Language; 27 | export = language; 28 | -------------------------------------------------------------------------------- /bindings/node/index.js: -------------------------------------------------------------------------------- 1 | const root = require("path").join(__dirname, "..", ".."); 2 | 3 | module.exports = 4 | typeof process.versions.bun === "string" 5 | // Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time 6 | ? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-lua.node`) 7 | : require("node-gyp-build")(root); 8 | 9 | try { 10 | module.exports.nodeTypeInfo = require("../../src/node-types.json"); 11 | } catch (_) {} 12 | -------------------------------------------------------------------------------- /bindings/python/tests/test_binding.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import tree_sitter 4 | import tree_sitter_lua 5 | 6 | 7 | class TestLanguage(TestCase): 8 | def test_can_load_grammar(self): 9 | try: 10 | tree_sitter.Language(tree_sitter_lua.language()) 11 | except Exception: 12 | self.fail("Error loading Lua grammar") 13 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_lua/__init__.py: -------------------------------------------------------------------------------- 1 | """Lua grammar for tree-sitter""" 2 | 3 | from importlib.resources import files as _files 4 | 5 | from ._binding import language 6 | 7 | 8 | def _get_query(name, file): 9 | query = _files(f"{__package__}.queries") / file 10 | globals()[name] = query.read_text() 11 | return globals()[name] 12 | 13 | 14 | def __getattr__(name): 15 | if name == "HIGHLIGHTS_QUERY": 16 | return _get_query("HIGHLIGHTS_QUERY", "highlights.scm") 17 | if name == "INJECTIONS_QUERY": 18 | return _get_query("INJECTIONS_QUERY", "injections.scm") 19 | if name == "LOCALS_QUERY": 20 | return _get_query("LOCALS_QUERY", "locals.scm") 21 | if name == "TAGS_QUERY": 22 | return _get_query("TAGS_QUERY", "tags.scm") 23 | 24 | raise AttributeError(f"module {__name__!r} has no attribute {name!r}") 25 | 26 | 27 | __all__ = [ 28 | "language", 29 | "HIGHLIGHTS_QUERY", 30 | "INJECTIONS_QUERY", 31 | "LOCALS_QUERY", 32 | "TAGS_QUERY", 33 | ] 34 | 35 | 36 | def __dir__(): 37 | return sorted(__all__ + [ 38 | "__all__", "__builtins__", "__cached__", "__doc__", "__file__", 39 | "__loader__", "__name__", "__package__", "__path__", "__spec__", 40 | ]) 41 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_lua/__init__.pyi: -------------------------------------------------------------------------------- 1 | from typing import Final 2 | 3 | HIGHLIGHTS_QUERY: Final[str] 4 | INJECTIONS_QUERY: Final[str] 5 | LOCALS_QUERY: Final[str] 6 | TAGS_QUERY: Final[str] 7 | 8 | def language() -> object: ... 9 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_lua/binding.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | TSLanguage *tree_sitter_lua(void); 6 | 7 | static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { 8 | return PyCapsule_New(tree_sitter_lua(), "tree_sitter.Language", NULL); 9 | } 10 | 11 | static struct PyModuleDef_Slot slots[] = { 12 | #ifdef Py_GIL_DISABLED 13 | {Py_mod_gil, Py_MOD_GIL_NOT_USED}, 14 | #endif 15 | {0, NULL} 16 | }; 17 | 18 | static PyMethodDef methods[] = { 19 | {"language", _binding_language, METH_NOARGS, 20 | "Get the tree-sitter language for this grammar."}, 21 | {NULL, NULL, 0, NULL} 22 | }; 23 | 24 | static struct PyModuleDef module = { 25 | .m_base = PyModuleDef_HEAD_INIT, 26 | .m_name = "_binding", 27 | .m_doc = NULL, 28 | .m_size = 0, 29 | .m_methods = methods, 30 | .m_slots = slots, 31 | }; 32 | 33 | PyMODINIT_FUNC PyInit__binding(void) { 34 | return PyModuleDef_Init(&module); 35 | } 36 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_lua/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tree-sitter-grammars/tree-sitter-lua/e5e406935ff3e36529545955e2972646ed97f9e2/bindings/python/tree_sitter_lua/py.typed -------------------------------------------------------------------------------- /bindings/rust/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let src_dir = std::path::Path::new("src"); 3 | 4 | let mut c_config = cc::Build::new(); 5 | c_config.std("c11").include(src_dir); 6 | 7 | #[cfg(target_env = "msvc")] 8 | c_config.flag("-utf-8"); 9 | 10 | let parser_path = src_dir.join("parser.c"); 11 | c_config.file(&parser_path); 12 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); 13 | 14 | let scanner_path = src_dir.join("scanner.c"); 15 | if scanner_path.exists() { 16 | c_config.file(&scanner_path); 17 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 18 | } 19 | 20 | c_config.compile("tree-sitter-lua"); 21 | } 22 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides Lua language support for the [tree-sitter] parsing library. 2 | //! 3 | //! Typically, you will use the [`LANGUAGE`] constant to add this language to a 4 | //! tree-sitter [`Parser`], and then use the parser to parse some code: 5 | //! 6 | //! ``` 7 | //! let code = r#" 8 | //! return 42 9 | //! "#; 10 | //! let mut parser = tree_sitter::Parser::new(); 11 | //! let language = tree_sitter_lua::LANGUAGE; 12 | //! parser 13 | //! .set_language(&language.into()) 14 | //! .expect("Error loading Lua parser"); 15 | //! let tree = parser.parse(code, None).unwrap(); 16 | //! assert!(!tree.root_node().has_error()); 17 | //! ``` 18 | //! 19 | //! [`Parser`]: https://docs.rs/tree-sitter/0.25.3/tree_sitter/struct.Parser.html 20 | //! [tree-sitter]: https://tree-sitter.github.io/ 21 | 22 | use tree_sitter_language::LanguageFn; 23 | 24 | extern "C" { 25 | fn tree_sitter_lua() -> *const (); 26 | } 27 | 28 | /// The tree-sitter [`LanguageFn`] for this grammar. 29 | pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_lua) }; 30 | 31 | /// The content of the [`node-types.json`] file for this grammar. 32 | /// 33 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types 34 | pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); 35 | 36 | /// The syntax highlighting query for this language. 37 | pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); 38 | 39 | /// The injection query for this language. 40 | pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm"); 41 | 42 | /// The local-variable syntax highlighting query for this language. 43 | pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm"); 44 | 45 | /// The symbol tagging query for this language. 46 | pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm"); 47 | 48 | #[cfg(test)] 49 | mod tests { 50 | #[test] 51 | fn test_can_load_grammar() { 52 | let mut parser = tree_sitter::Parser::new(); 53 | parser 54 | .set_language(&super::LANGUAGE.into()) 55 | .expect("Error loading Lua parser"); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterLua/lua.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_LUA_H_ 2 | #define TREE_SITTER_LUA_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | const TSLanguage *tree_sitter_lua(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_LUA_H_ 17 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterLuaTests/TreeSitterLuaTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import SwiftTreeSitter 3 | import TreeSitterLua 4 | 5 | final class TreeSitterLuaTests: XCTestCase { 6 | func testCanLoadGrammar() throws { 7 | let parser = Parser() 8 | let language = Language(language: tree_sitter_lua()) 9 | XCTAssertNoThrow(try parser.setLanguage(language), 10 | "Error loading Lua grammar") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tree-sitter-grammars/tree-sitter-lua 2 | 3 | go 1.22 4 | 5 | require github.com/tree-sitter/go-tree-sitter v0.24.0 6 | 7 | require github.com/mattn/go-pointer v0.0.1 // indirect 8 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= 4 | github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 8 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 9 | github.com/tree-sitter/go-tree-sitter v0.24.0 h1:kRZb6aBNfcI/u0Qh8XEt3zjNVnmxTisDBN+kXK0xRYQ= 10 | github.com/tree-sitter/go-tree-sitter v0.24.0/go.mod h1:x681iFVoLMEwOSIHA1chaLkXlroXEN7WY+VHGFaoDbk= 11 | github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb h1:A8425heRM8mylnv4H58FPUiH+aYivyitre0PzxrfmWs= 12 | github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb/go.mod h1:dOF6gtQiF9UwNh995T5OphYmtIypkjsp3ap7r9AN/iA= 13 | github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148 h1:AfFPZwtwGN01BW1jDdqBVqscTwetvMpydqYZz57RSlc= 14 | github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148/go.mod h1:Bh6U3viD57rFXRYIQ+kmiYtr+1Bx0AceypDLJJSyi9s= 15 | github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33 h1:TwqSV3qLp3tKSqirGLRHnjFk9Tc2oy57LIl+FQ4GjI4= 16 | github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33/go.mod h1:CvCKCt3v04Ufos1zZnNCelBDeCGRpPucaN8QczoUsN4= 17 | github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012 h1:Xvxck3tE5FW7F7bTS97iNM2ADMyCMJztVqn5HYKdJGo= 18 | github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012/go.mod h1:T40D0O1cPvUU/+AmiXVXy1cncYQT6wem4Z0g4SfAYvY= 19 | github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo= 20 | github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU= 21 | github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA= 22 | github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc= 23 | github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg= 24 | github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU= 25 | github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4= 26 | github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk= 27 | github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g= 28 | github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs= 29 | github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw= 30 | github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g= 31 | github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d h1:fcYCvoXdcP1uRQYXqJHRy6Hec+uKScQdKVtMwK9JeCI= 32 | github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d/go.mod h1:T1nShQ4v5AJtozZ8YyAS4uzUtDAJj/iv4YfwXSbUHzg= 33 | github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc= 34 | github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc= 35 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 36 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 37 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Lua grammar for tree-sitter 3 | * @author Munif Tanjim 4 | * @license MIT 5 | */ 6 | 7 | /// 8 | // @ts-check 9 | 10 | const PREC = { 11 | OR: 1, // or 12 | AND: 2, // and 13 | COMPARE: 3, // < > <= >= ~= == 14 | BIT_OR: 4, // | 15 | BIT_NOT: 5, // ~ 16 | BIT_AND: 6, // & 17 | BIT_SHIFT: 7, // << >> 18 | CONCAT: 8, // .. 19 | PLUS: 9, // + - 20 | MULTI: 10, // * / // % 21 | UNARY: 11, // not # - ~ 22 | POWER: 12, // ^ 23 | }; 24 | 25 | const list_seq = (rule, separator, trailing_separator = false) => 26 | trailing_separator 27 | ? seq(rule, repeat(seq(separator, rule)), optional(separator)) 28 | : seq(rule, repeat(seq(separator, rule))); 29 | 30 | const optional_block = ($) => alias(optional($._block), $.block); 31 | 32 | // namelist ::= Name {',' Name} 33 | const name_list = ($) => list_seq(field('name', $.identifier), ','); 34 | 35 | module.exports = grammar({ 36 | name: 'lua', 37 | 38 | extras: ($) => [$.comment, /\s/], 39 | 40 | externals: ($) => [ 41 | $._block_comment_start, 42 | $._block_comment_content, 43 | $._block_comment_end, 44 | 45 | $._block_string_start, 46 | $._block_string_content, 47 | $._block_string_end, 48 | ], 49 | 50 | supertypes: ($) => [$.statement, $.expression, $.declaration, $.variable], 51 | 52 | word: ($) => $.identifier, 53 | 54 | rules: { 55 | // chunk ::= block 56 | chunk: ($) => 57 | seq( 58 | optional($.hash_bang_line), 59 | repeat($.statement), 60 | optional($.return_statement) 61 | ), 62 | 63 | hash_bang_line: (_) => /#.*/, 64 | 65 | // block ::= {stat} [retstat] 66 | _block: ($) => 67 | choice( 68 | seq(repeat1($.statement), optional($.return_statement)), 69 | seq(repeat($.statement), $.return_statement) 70 | ), 71 | 72 | /* 73 | stat ::= ';' | 74 | varlist '=' explist | 75 | functioncall | 76 | label | 77 | break | 78 | goto Name | 79 | do block end | 80 | while exp do block end | 81 | repeat block until exp | 82 | if exp then block {elseif exp then block} [else block] end | 83 | for Name '=' exp ',' exp [',' exp] do block end | 84 | for namelist in explist do block end | 85 | function funcname funcbody | 86 | local function Name funcbody | 87 | local namelist ['=' explist] 88 | */ 89 | statement: ($) => 90 | choice( 91 | $.empty_statement, 92 | $.assignment_statement, 93 | $.function_call, 94 | $.label_statement, 95 | $.break_statement, 96 | $.goto_statement, 97 | $.do_statement, 98 | $.while_statement, 99 | $.repeat_statement, 100 | $.if_statement, 101 | $.for_statement, 102 | $.declaration 103 | ), 104 | 105 | // retstat ::= return [explist] [';'] 106 | return_statement: ($) => 107 | seq( 108 | 'return', 109 | optional(alias($._expression_list, $.expression_list)), 110 | optional(';') 111 | ), 112 | 113 | // ';' 114 | empty_statement: (_) => ';', 115 | 116 | // varlist '=' explist 117 | assignment_statement: ($) => 118 | seq( 119 | alias($._variable_assignment_varlist, $.variable_list), 120 | '=', 121 | alias($._variable_assignment_explist, $.expression_list) 122 | ), 123 | // varlist ::= var {',' var} 124 | _variable_assignment_varlist: ($) => 125 | list_seq(field('name', $.variable), ','), 126 | // explist ::= exp {',' exp} 127 | _variable_assignment_explist: ($) => 128 | list_seq(field('value', $.expression), ','), 129 | 130 | // label ::= '::' Name '::' 131 | label_statement: ($) => seq('::', $.identifier, '::'), 132 | 133 | // break 134 | break_statement: (_) => 'break', 135 | 136 | // goto Name 137 | goto_statement: ($) => seq('goto', $.identifier), 138 | 139 | // do block end 140 | do_statement: ($) => seq('do', field('body', optional_block($)), 'end'), 141 | 142 | // while exp do block end 143 | while_statement: ($) => 144 | seq( 145 | 'while', 146 | field('condition', $.expression), 147 | 'do', 148 | field('body', optional_block($)), 149 | 'end' 150 | ), 151 | 152 | // repeat block until exp 153 | repeat_statement: ($) => 154 | seq( 155 | 'repeat', 156 | field('body', optional_block($)), 157 | 'until', 158 | field('condition', $.expression) 159 | ), 160 | 161 | // if exp then block {elseif exp then block} [else block] end 162 | if_statement: ($) => 163 | seq( 164 | 'if', 165 | field('condition', $.expression), 166 | 'then', 167 | field('consequence', optional_block($)), 168 | repeat(field('alternative', $.elseif_statement)), 169 | optional(field('alternative', $.else_statement)), 170 | 'end' 171 | ), 172 | // elseif exp then block 173 | elseif_statement: ($) => 174 | seq( 175 | 'elseif', 176 | field('condition', $.expression), 177 | 'then', 178 | field('consequence', optional_block($)) 179 | ), 180 | // else block 181 | else_statement: ($) => seq('else', field('body', optional_block($))), 182 | 183 | // for Name '=' exp ',' exp [',' exp] do block end 184 | // for namelist in explist do block end 185 | for_statement: ($) => 186 | seq( 187 | 'for', 188 | field('clause', choice($.for_generic_clause, $.for_numeric_clause)), 189 | 'do', 190 | field('body', optional_block($)), 191 | 'end' 192 | ), 193 | // namelist in explist 194 | for_generic_clause: ($) => 195 | seq( 196 | alias($._name_list, $.variable_list), 197 | 'in', 198 | alias($._expression_list, $.expression_list) 199 | ), 200 | // Name '=' exp ',' exp [',' exp] 201 | for_numeric_clause: ($) => 202 | seq( 203 | field('name', $.identifier), 204 | '=', 205 | field('start', $.expression), 206 | ',', 207 | field('end', $.expression), 208 | optional(seq(',', field('step', $.expression))) 209 | ), 210 | 211 | // function funcname funcbody 212 | // local function Name funcbody 213 | // local namelist ['=' explist] 214 | declaration: ($) => 215 | choice( 216 | $.function_declaration, 217 | field( 218 | 'local_declaration', 219 | alias($._local_function_declaration, $.function_declaration) 220 | ), 221 | field('local_declaration', $.variable_declaration) 222 | ), 223 | // function funcname funcbody 224 | function_declaration: ($) => 225 | seq('function', field('name', $._function_name), $._function_body), 226 | // local function Name funcbody 227 | _local_function_declaration: ($) => 228 | seq('local', 'function', field('name', $.identifier), $._function_body), 229 | // funcname ::= Name {'.' Name} [':' Name] 230 | _function_name: ($) => 231 | choice( 232 | $._function_name_prefix_expression, 233 | alias( 234 | $._function_name_method_index_expression, 235 | $.method_index_expression 236 | ) 237 | ), 238 | _function_name_prefix_expression: ($) => 239 | choice( 240 | $.identifier, 241 | alias($._function_name_dot_index_expression, $.dot_index_expression) 242 | ), 243 | _function_name_dot_index_expression: ($) => 244 | seq( 245 | field('table', $._function_name_prefix_expression), 246 | '.', 247 | field('field', $.identifier) 248 | ), 249 | _function_name_method_index_expression: ($) => 250 | seq( 251 | field('table', $._function_name_prefix_expression), 252 | ':', 253 | field('method', $.identifier) 254 | ), 255 | 256 | // local namelist ['=' explist] 257 | variable_declaration: ($) => 258 | seq( 259 | 'local', 260 | choice( 261 | alias($._att_name_list, $.variable_list), 262 | alias($._local_variable_assignment, $.assignment_statement) 263 | ) 264 | ), 265 | _local_variable_assignment: ($) => 266 | seq( 267 | alias($._att_name_list, $.variable_list), 268 | '=', 269 | alias($._variable_assignment_explist, $.expression_list) 270 | ), 271 | // namelist ::= Name {',' Name} 272 | _name_list: ($) => name_list($), 273 | 274 | // attnamelist ::= Name attrib {‘,’ Name attrib} 275 | _att_name_list: ($) => 276 | list_seq( 277 | seq( 278 | field('name', $.identifier), 279 | optional(field('attribute', alias($._attrib, $.attribute))) 280 | ), 281 | ',' 282 | ), 283 | // attrib ::= [‘<’ Name ‘>’] 284 | _attrib: ($) => seq('<', $.identifier, '>'), 285 | 286 | // explist ::= exp {',' exp} 287 | _expression_list: ($) => list_seq($.expression, ','), 288 | 289 | /* 290 | exp ::= nil | false | true | Numeral | LiteralString | '...' | functiondef | 291 | prefixexp | tableconstructor | exp binop exp | unop exp 292 | */ 293 | expression: ($) => 294 | choice( 295 | $.nil, 296 | $.false, 297 | $.true, 298 | $.number, 299 | $.string, 300 | $.vararg_expression, 301 | $.function_definition, 302 | $.variable, 303 | $.function_call, 304 | $.parenthesized_expression, 305 | $.table_constructor, 306 | $.binary_expression, 307 | $.unary_expression 308 | ), 309 | 310 | // nil 311 | nil: (_) => 'nil', 312 | 313 | // false 314 | false: (_) => 'false', 315 | 316 | // true 317 | true: (_) => 'true', 318 | 319 | // Numeral 320 | number: (_) => { 321 | function number_literal(digits, exponent_marker, exponent_digits) { 322 | return choice( 323 | seq(digits, /U?LL/i), 324 | seq( 325 | choice( 326 | seq(optional(digits), optional('.'), digits), 327 | seq(digits, optional('.'), optional(digits)) 328 | ), 329 | optional( 330 | seq( 331 | choice( 332 | exponent_marker.toLowerCase(), 333 | exponent_marker.toUpperCase() 334 | ), 335 | seq(optional(choice('-', '+')), exponent_digits) 336 | ) 337 | ), 338 | optional(choice('i', 'I')) 339 | ) 340 | ); 341 | } 342 | 343 | const decimal_digits = /[0-9]+/; 344 | const decimal_literal = number_literal( 345 | decimal_digits, 346 | 'e', 347 | decimal_digits 348 | ); 349 | 350 | const hex_digits = /[a-fA-F0-9]+/; 351 | const hex_literal = seq( 352 | choice('0x', '0X'), 353 | number_literal(hex_digits, 'p', decimal_digits) 354 | ); 355 | 356 | const bin_digits = /[01]+/; 357 | const bin_literal = seq( 358 | choice('0b', '0B'), 359 | choice( 360 | seq(bin_digits, /U?LL/i), 361 | seq(bin_digits, optional(choice('i', 'I'))) 362 | ) 363 | ); 364 | 365 | return token(choice(decimal_literal, hex_literal, bin_literal)); 366 | }, 367 | 368 | // LiteralString 369 | string: ($) => choice($._quote_string, $._block_string), 370 | 371 | _quote_string: ($) => 372 | choice( 373 | seq( 374 | field('start', alias('"', '"')), 375 | field( 376 | 'content', 377 | optional(alias($._doublequote_string_content, $.string_content)) 378 | ), 379 | field('end', alias('"', '"')) 380 | ), 381 | seq( 382 | field('start', alias("'", "'")), 383 | field( 384 | 'content', 385 | optional(alias($._singlequote_string_content, $.string_content)) 386 | ), 387 | field('end', alias("'", "'")) 388 | ) 389 | ), 390 | 391 | _doublequote_string_content: ($) => 392 | repeat1(choice(token.immediate(prec(1, /[^"\\]+/)), $.escape_sequence)), 393 | 394 | _singlequote_string_content: ($) => 395 | repeat1(choice(token.immediate(prec(1, /[^'\\]+/)), $.escape_sequence)), 396 | 397 | _block_string: ($) => 398 | seq( 399 | field('start', alias($._block_string_start, '[[')), 400 | field('content', alias($._block_string_content, $.string_content)), 401 | field('end', alias($._block_string_end, ']]')) 402 | ), 403 | 404 | escape_sequence: () => 405 | token.immediate( 406 | seq( 407 | '\\', 408 | choice( 409 | /[\nabfnrtv\\'"]/, 410 | /z\s*/, 411 | /[0-9]{1,3}/, 412 | /x[0-9a-fA-F]{2}/, 413 | /u\{[0-9a-fA-F]+\}/ 414 | ) 415 | ) 416 | ), 417 | 418 | // '...' 419 | vararg_expression: (_) => '...', 420 | 421 | // functiondef ::= function funcbody 422 | function_definition: ($) => seq('function', $._function_body), 423 | // funcbody ::= '(' [parlist] ')' block end 424 | _function_body: ($) => 425 | seq( 426 | field('parameters', $.parameters), 427 | field('body', optional_block($)), 428 | 'end' 429 | ), 430 | // '(' [parlist] ')' 431 | parameters: ($) => seq('(', optional($._parameter_list), ')'), 432 | // parlist ::= namelist [',' '...'] | '...' 433 | _parameter_list: ($) => 434 | choice( 435 | seq(name_list($), optional(seq(',', $.vararg_expression))), 436 | $.vararg_expression 437 | ), 438 | 439 | // prefixexp ::= var | functioncall | '(' exp ')' 440 | _prefix_expression: ($) => 441 | prec(1, choice($.variable, $.function_call, $.parenthesized_expression)), 442 | 443 | // var ::= Name | prefixexp [ exp ] | prefixexp . Name 444 | variable: ($) => 445 | choice($.identifier, $.bracket_index_expression, $.dot_index_expression), 446 | // prefixexp [ exp ] 447 | bracket_index_expression: ($) => 448 | seq( 449 | field('table', $._prefix_expression), 450 | '[', 451 | field('field', $.expression), 452 | ']' 453 | ), 454 | // prefixexp . Name 455 | dot_index_expression: ($) => 456 | seq( 457 | field('table', $._prefix_expression), 458 | '.', 459 | field('field', $.identifier) 460 | ), 461 | 462 | // functioncall ::= prefixexp args | prefixexp ':' Name args 463 | function_call: ($) => 464 | seq( 465 | field('name', choice($._prefix_expression, $.method_index_expression)), 466 | field('arguments', $.arguments) 467 | ), 468 | // prefixexp ':' Name 469 | method_index_expression: ($) => 470 | seq( 471 | field('table', $._prefix_expression), 472 | ':', 473 | field('method', $.identifier) 474 | ), 475 | // args ::= '(' [explist] ')' | tableconstructor | LiteralString 476 | arguments: ($) => 477 | choice( 478 | seq('(', optional(list_seq($.expression, ',')), ')'), 479 | $.table_constructor, 480 | $.string 481 | ), 482 | 483 | // '(' exp ')' 484 | parenthesized_expression: ($) => seq('(', $.expression, ')'), 485 | 486 | // tableconstructor ::= '{' [fieldlist] '}' 487 | table_constructor: ($) => seq('{', optional($._field_list), '}'), 488 | // fieldlist ::= field {fieldsep field} [fieldsep] 489 | _field_list: ($) => list_seq($.field, $._field_sep, true), 490 | // fieldsep ::= ',' | ';' 491 | _field_sep: (_) => choice(',', ';'), 492 | // field ::= '[' exp ']' '=' exp | Name '=' exp | exp 493 | field: ($) => 494 | choice( 495 | seq( 496 | '[', 497 | field('name', $.expression), 498 | ']', 499 | '=', 500 | field('value', $.expression) 501 | ), 502 | seq(field('name', $.identifier), '=', field('value', $.expression)), 503 | field('value', $.expression) 504 | ), 505 | 506 | // exp binop exp 507 | binary_expression: ($) => 508 | choice( 509 | ...[ 510 | ['or', PREC.OR], 511 | ['and', PREC.AND], 512 | ['<', PREC.COMPARE], 513 | ['<=', PREC.COMPARE], 514 | ['==', PREC.COMPARE], 515 | ['~=', PREC.COMPARE], 516 | ['>=', PREC.COMPARE], 517 | ['>', PREC.COMPARE], 518 | ['|', PREC.BIT_OR], 519 | ['~', PREC.BIT_NOT], 520 | ['&', PREC.BIT_AND], 521 | ['<<', PREC.BIT_SHIFT], 522 | ['>>', PREC.BIT_SHIFT], 523 | ['+', PREC.PLUS], 524 | ['-', PREC.PLUS], 525 | ['*', PREC.MULTI], 526 | ['/', PREC.MULTI], 527 | ['//', PREC.MULTI], 528 | ['%', PREC.MULTI], 529 | ].map(([operator, precedence]) => 530 | prec.left( 531 | precedence, 532 | seq( 533 | field('left', $.expression), 534 | operator, 535 | field('right', $.expression) 536 | ) 537 | ) 538 | ), 539 | ...[ 540 | ['..', PREC.CONCAT], 541 | ['^', PREC.POWER], 542 | ].map(([operator, precedence]) => 543 | prec.right( 544 | precedence, 545 | seq( 546 | field('left', $.expression), 547 | operator, 548 | field('right', $.expression) 549 | ) 550 | ) 551 | ) 552 | ), 553 | 554 | // unop exp 555 | unary_expression: ($) => 556 | prec.left( 557 | PREC.UNARY, 558 | seq(choice('not', '#', '-', '~'), field('operand', $.expression)) 559 | ), 560 | 561 | // Name 562 | identifier: (_) => { 563 | const identifier_start = 564 | /[^\p{Control}\s+\-*/%^#&~|<>=(){}\[\];:,.\\'"\d]/; 565 | const identifier_continue = 566 | /[^\p{Control}\s+\-*/%^#&~|<>=(){}\[\];:,.\\'"]*/; 567 | return token(seq(identifier_start, identifier_continue)); 568 | }, 569 | 570 | // comment 571 | comment: ($) => 572 | choice( 573 | seq( 574 | field('start', '--'), 575 | field('content', alias(/[^\r\n]*/, $.comment_content)) 576 | ), 577 | seq( 578 | field('start', alias($._block_comment_start, '[[')), 579 | field('content', alias($._block_comment_content, $.comment_content)), 580 | field('end', alias($._block_comment_end, ']]')) 581 | ) 582 | ), 583 | }, 584 | }); 585 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tree-sitter-grammars/tree-sitter-lua", 3 | "version": "0.4.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@tree-sitter-grammars/tree-sitter-lua", 9 | "version": "0.4.0", 10 | "hasInstallScript": true, 11 | "license": "MIT", 12 | "dependencies": { 13 | "node-addon-api": "^8.3.1", 14 | "node-gyp-build": "^4.8.4" 15 | }, 16 | "devDependencies": { 17 | "prebuildify": "^6.0.1", 18 | "tree-sitter-cli": "^0.25.3" 19 | }, 20 | "peerDependencies": { 21 | "tree-sitter": "^0.22.4" 22 | }, 23 | "peerDependenciesMeta": { 24 | "tree-sitter": { 25 | "optional": true 26 | } 27 | } 28 | }, 29 | "node_modules/base64-js": { 30 | "version": "1.5.1", 31 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 32 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 33 | "dev": true, 34 | "funding": [ 35 | { 36 | "type": "github", 37 | "url": "https://github.com/sponsors/feross" 38 | }, 39 | { 40 | "type": "patreon", 41 | "url": "https://www.patreon.com/feross" 42 | }, 43 | { 44 | "type": "consulting", 45 | "url": "https://feross.org/support" 46 | } 47 | ], 48 | "license": "MIT" 49 | }, 50 | "node_modules/bl": { 51 | "version": "4.1.0", 52 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 53 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 54 | "dev": true, 55 | "license": "MIT", 56 | "dependencies": { 57 | "buffer": "^5.5.0", 58 | "inherits": "^2.0.4", 59 | "readable-stream": "^3.4.0" 60 | } 61 | }, 62 | "node_modules/buffer": { 63 | "version": "5.7.1", 64 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 65 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 66 | "dev": true, 67 | "funding": [ 68 | { 69 | "type": "github", 70 | "url": "https://github.com/sponsors/feross" 71 | }, 72 | { 73 | "type": "patreon", 74 | "url": "https://www.patreon.com/feross" 75 | }, 76 | { 77 | "type": "consulting", 78 | "url": "https://feross.org/support" 79 | } 80 | ], 81 | "license": "MIT", 82 | "dependencies": { 83 | "base64-js": "^1.3.1", 84 | "ieee754": "^1.1.13" 85 | } 86 | }, 87 | "node_modules/chownr": { 88 | "version": "1.1.4", 89 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 90 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", 91 | "dev": true, 92 | "license": "ISC" 93 | }, 94 | "node_modules/end-of-stream": { 95 | "version": "1.4.4", 96 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 97 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 98 | "dev": true, 99 | "license": "MIT", 100 | "dependencies": { 101 | "once": "^1.4.0" 102 | } 103 | }, 104 | "node_modules/fs-constants": { 105 | "version": "1.0.0", 106 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 107 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", 108 | "dev": true, 109 | "license": "MIT" 110 | }, 111 | "node_modules/ieee754": { 112 | "version": "1.2.1", 113 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 114 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 115 | "dev": true, 116 | "funding": [ 117 | { 118 | "type": "github", 119 | "url": "https://github.com/sponsors/feross" 120 | }, 121 | { 122 | "type": "patreon", 123 | "url": "https://www.patreon.com/feross" 124 | }, 125 | { 126 | "type": "consulting", 127 | "url": "https://feross.org/support" 128 | } 129 | ], 130 | "license": "BSD-3-Clause" 131 | }, 132 | "node_modules/inherits": { 133 | "version": "2.0.4", 134 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 135 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 136 | "dev": true, 137 | "license": "ISC" 138 | }, 139 | "node_modules/minimist": { 140 | "version": "1.2.8", 141 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 142 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 143 | "dev": true, 144 | "license": "MIT", 145 | "funding": { 146 | "url": "https://github.com/sponsors/ljharb" 147 | } 148 | }, 149 | "node_modules/mkdirp-classic": { 150 | "version": "0.5.3", 151 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 152 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", 153 | "dev": true, 154 | "license": "MIT" 155 | }, 156 | "node_modules/node-abi": { 157 | "version": "3.75.0", 158 | "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", 159 | "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", 160 | "dev": true, 161 | "license": "MIT", 162 | "dependencies": { 163 | "semver": "^7.3.5" 164 | }, 165 | "engines": { 166 | "node": ">=10" 167 | } 168 | }, 169 | "node_modules/node-addon-api": { 170 | "version": "8.3.1", 171 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz", 172 | "integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==", 173 | "license": "MIT", 174 | "engines": { 175 | "node": "^18 || ^20 || >= 21" 176 | } 177 | }, 178 | "node_modules/node-gyp-build": { 179 | "version": "4.8.4", 180 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", 181 | "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", 182 | "license": "MIT", 183 | "bin": { 184 | "node-gyp-build": "bin.js", 185 | "node-gyp-build-optional": "optional.js", 186 | "node-gyp-build-test": "build-test.js" 187 | } 188 | }, 189 | "node_modules/npm-run-path": { 190 | "version": "3.1.0", 191 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", 192 | "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", 193 | "dev": true, 194 | "license": "MIT", 195 | "dependencies": { 196 | "path-key": "^3.0.0" 197 | }, 198 | "engines": { 199 | "node": ">=8" 200 | } 201 | }, 202 | "node_modules/once": { 203 | "version": "1.4.0", 204 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 205 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 206 | "dev": true, 207 | "license": "ISC", 208 | "dependencies": { 209 | "wrappy": "1" 210 | } 211 | }, 212 | "node_modules/path-key": { 213 | "version": "3.1.1", 214 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 215 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 216 | "dev": true, 217 | "license": "MIT", 218 | "engines": { 219 | "node": ">=8" 220 | } 221 | }, 222 | "node_modules/prebuildify": { 223 | "version": "6.0.1", 224 | "resolved": "https://registry.npmjs.org/prebuildify/-/prebuildify-6.0.1.tgz", 225 | "integrity": "sha512-8Y2oOOateom/s8dNBsGIcnm6AxPmLH4/nanQzL5lQMU+sC0CMhzARZHizwr36pUPLdvBnOkCNQzxg4djuFSgIw==", 226 | "dev": true, 227 | "license": "MIT", 228 | "dependencies": { 229 | "minimist": "^1.2.5", 230 | "mkdirp-classic": "^0.5.3", 231 | "node-abi": "^3.3.0", 232 | "npm-run-path": "^3.1.0", 233 | "pump": "^3.0.0", 234 | "tar-fs": "^2.1.0" 235 | }, 236 | "bin": { 237 | "prebuildify": "bin.js" 238 | } 239 | }, 240 | "node_modules/pump": { 241 | "version": "3.0.2", 242 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", 243 | "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", 244 | "dev": true, 245 | "license": "MIT", 246 | "dependencies": { 247 | "end-of-stream": "^1.1.0", 248 | "once": "^1.3.1" 249 | } 250 | }, 251 | "node_modules/readable-stream": { 252 | "version": "3.6.2", 253 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 254 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 255 | "dev": true, 256 | "license": "MIT", 257 | "dependencies": { 258 | "inherits": "^2.0.3", 259 | "string_decoder": "^1.1.1", 260 | "util-deprecate": "^1.0.1" 261 | }, 262 | "engines": { 263 | "node": ">= 6" 264 | } 265 | }, 266 | "node_modules/safe-buffer": { 267 | "version": "5.2.1", 268 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 269 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 270 | "dev": true, 271 | "funding": [ 272 | { 273 | "type": "github", 274 | "url": "https://github.com/sponsors/feross" 275 | }, 276 | { 277 | "type": "patreon", 278 | "url": "https://www.patreon.com/feross" 279 | }, 280 | { 281 | "type": "consulting", 282 | "url": "https://feross.org/support" 283 | } 284 | ], 285 | "license": "MIT" 286 | }, 287 | "node_modules/semver": { 288 | "version": "7.7.2", 289 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", 290 | "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", 291 | "dev": true, 292 | "license": "ISC", 293 | "bin": { 294 | "semver": "bin/semver.js" 295 | }, 296 | "engines": { 297 | "node": ">=10" 298 | } 299 | }, 300 | "node_modules/string_decoder": { 301 | "version": "1.3.0", 302 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 303 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 304 | "dev": true, 305 | "license": "MIT", 306 | "dependencies": { 307 | "safe-buffer": "~5.2.0" 308 | } 309 | }, 310 | "node_modules/tar-fs": { 311 | "version": "2.1.2", 312 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", 313 | "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", 314 | "dev": true, 315 | "license": "MIT", 316 | "dependencies": { 317 | "chownr": "^1.1.1", 318 | "mkdirp-classic": "^0.5.2", 319 | "pump": "^3.0.0", 320 | "tar-stream": "^2.1.4" 321 | } 322 | }, 323 | "node_modules/tar-stream": { 324 | "version": "2.2.0", 325 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", 326 | "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", 327 | "dev": true, 328 | "license": "MIT", 329 | "dependencies": { 330 | "bl": "^4.0.3", 331 | "end-of-stream": "^1.4.1", 332 | "fs-constants": "^1.0.0", 333 | "inherits": "^2.0.3", 334 | "readable-stream": "^3.1.1" 335 | }, 336 | "engines": { 337 | "node": ">=6" 338 | } 339 | }, 340 | "node_modules/tree-sitter-cli": { 341 | "version": "0.25.4", 342 | "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.25.4.tgz", 343 | "integrity": "sha512-tSOgiUuNH1xgSopWHMb+2EPuzIawj7/7/k0cNTNInBde21R0e53ElygJ+76PLjai2BOjnCzy9n8W0o7Eo9GVgA==", 344 | "dev": true, 345 | "hasInstallScript": true, 346 | "license": "MIT", 347 | "bin": { 348 | "tree-sitter": "cli.js" 349 | }, 350 | "engines": { 351 | "node": ">=12.0.0" 352 | } 353 | }, 354 | "node_modules/util-deprecate": { 355 | "version": "1.0.2", 356 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 357 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 358 | "dev": true, 359 | "license": "MIT" 360 | }, 361 | "node_modules/wrappy": { 362 | "version": "1.0.2", 363 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 364 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 365 | "dev": true, 366 | "license": "ISC" 367 | } 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tree-sitter-grammars/tree-sitter-lua", 3 | "version": "0.4.0", 4 | "description": "Lua grammar for tree-sitter", 5 | "repository": "https://github.com/tree-sitter-grammars/tree-sitter-lua", 6 | "license": "MIT", 7 | "author": { 8 | "name": "Munif Tanjim", 9 | "email": "hello@muniftanjim.dev", 10 | "url": "https://muniftanjim.dev" 11 | }, 12 | "main": "bindings/node", 13 | "types": "bindings/node", 14 | "keywords": [ 15 | "incremental", 16 | "parsing", 17 | "tree-sitter", 18 | "lua" 19 | ], 20 | "files": [ 21 | "grammar.js", 22 | "tree-sitter.json", 23 | "binding.gyp", 24 | "prebuilds/**", 25 | "bindings/node/*", 26 | "queries/*", 27 | "src/**", 28 | "*.wasm" 29 | ], 30 | "dependencies": { 31 | "node-addon-api": "^8.3.1", 32 | "node-gyp-build": "^4.8.4" 33 | }, 34 | "devDependencies": { 35 | "prebuildify": "^6.0.1", 36 | "tree-sitter-cli": "^0.25.3" 37 | }, 38 | "peerDependencies": { 39 | "tree-sitter": "^0.22.4" 40 | }, 41 | "peerDependenciesMeta": { 42 | "tree-sitter": { 43 | "optional": true 44 | } 45 | }, 46 | "scripts": { 47 | "install": "node-gyp-build", 48 | "prestart": "tree-sitter build --wasm", 49 | "start": "tree-sitter playground", 50 | "test": "node --test bindings/node/*_test.js" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "tree-sitter-lua" 7 | description = "Lua grammar for tree-sitter" 8 | version = "0.4.0" 9 | keywords = ["incremental", "parsing", "tree-sitter", "lua"] 10 | classifiers = [ 11 | "Intended Audience :: Developers", 12 | "Topic :: Software Development :: Compilers", 13 | "Topic :: Text Processing :: Linguistic", 14 | "Typing :: Typed", 15 | ] 16 | authors = [{ name = "Munif Tanjim", email = "hello@muniftanjim.dev" }] 17 | requires-python = ">=3.10" 18 | license.text = "MIT" 19 | readme = "README.md" 20 | 21 | [project.urls] 22 | Homepage = "https://github.com/tree-sitter-grammars/tree-sitter-lua" 23 | 24 | [project.optional-dependencies] 25 | core = ["tree-sitter~=0.24"] 26 | 27 | [tool.cibuildwheel] 28 | build = "cp310-*" 29 | build-frontend = "build" 30 | -------------------------------------------------------------------------------- /queries/highlights.scm: -------------------------------------------------------------------------------- 1 | ;; Keywords 2 | 3 | "return" @keyword.return 4 | 5 | [ 6 | "goto" 7 | "in" 8 | "local" 9 | ] @keyword 10 | 11 | (label_statement) @label 12 | 13 | (break_statement) @keyword 14 | 15 | (do_statement 16 | [ 17 | "do" 18 | "end" 19 | ] @keyword) 20 | 21 | (while_statement 22 | [ 23 | "while" 24 | "do" 25 | "end" 26 | ] @repeat) 27 | 28 | (repeat_statement 29 | [ 30 | "repeat" 31 | "until" 32 | ] @repeat) 33 | 34 | (if_statement 35 | [ 36 | "if" 37 | "elseif" 38 | "else" 39 | "then" 40 | "end" 41 | ] @conditional) 42 | 43 | (elseif_statement 44 | [ 45 | "elseif" 46 | "then" 47 | "end" 48 | ] @conditional) 49 | 50 | (else_statement 51 | [ 52 | "else" 53 | "end" 54 | ] @conditional) 55 | 56 | (for_statement 57 | [ 58 | "for" 59 | "do" 60 | "end" 61 | ] @repeat) 62 | 63 | (function_declaration 64 | [ 65 | "function" 66 | "end" 67 | ] @keyword.function) 68 | 69 | (function_definition 70 | [ 71 | "function" 72 | "end" 73 | ] @keyword.function) 74 | 75 | ;; Operators 76 | 77 | [ 78 | "and" 79 | "not" 80 | "or" 81 | ] @keyword.operator 82 | 83 | [ 84 | "+" 85 | "-" 86 | "*" 87 | "/" 88 | "%" 89 | "^" 90 | "#" 91 | "==" 92 | "~=" 93 | "<=" 94 | ">=" 95 | "<" 96 | ">" 97 | "=" 98 | "&" 99 | "~" 100 | "|" 101 | "<<" 102 | ">>" 103 | "//" 104 | ".." 105 | ] @operator 106 | 107 | ;; Punctuations 108 | 109 | [ 110 | ";" 111 | ":" 112 | "," 113 | "." 114 | ] @punctuation.delimiter 115 | 116 | ;; Brackets 117 | 118 | [ 119 | "(" 120 | ")" 121 | "[" 122 | "]" 123 | "{" 124 | "}" 125 | ] @punctuation.bracket 126 | 127 | ;; Variables 128 | 129 | (identifier) @variable 130 | 131 | ((identifier) @variable.builtin 132 | (#eq? @variable.builtin "self")) 133 | 134 | (variable_list 135 | (attribute 136 | "<" @punctuation.bracket 137 | (identifier) @attribute 138 | ">" @punctuation.bracket)) 139 | 140 | ;; Constants 141 | 142 | ((identifier) @constant 143 | (#match? @constant "^[A-Z][A-Z_0-9]*$")) 144 | 145 | (vararg_expression) @constant 146 | 147 | (nil) @constant.builtin 148 | 149 | [ 150 | (false) 151 | (true) 152 | ] @boolean 153 | 154 | ;; Tables 155 | 156 | (field name: (identifier) @field) 157 | 158 | (dot_index_expression field: (identifier) @field) 159 | 160 | (table_constructor 161 | [ 162 | "{" 163 | "}" 164 | ] @constructor) 165 | 166 | ;; Functions 167 | 168 | (parameters (identifier) @parameter) 169 | 170 | (function_declaration 171 | name: [ 172 | (identifier) @function 173 | (dot_index_expression 174 | field: (identifier) @function) 175 | ]) 176 | 177 | (function_declaration 178 | name: (method_index_expression 179 | method: (identifier) @method)) 180 | 181 | (assignment_statement 182 | (variable_list . 183 | name: [ 184 | (identifier) @function 185 | (dot_index_expression 186 | field: (identifier) @function) 187 | ]) 188 | (expression_list . 189 | value: (function_definition))) 190 | 191 | (table_constructor 192 | (field 193 | name: (identifier) @function 194 | value: (function_definition))) 195 | 196 | (function_call 197 | name: [ 198 | (identifier) @function.call 199 | (dot_index_expression 200 | field: (identifier) @function.call) 201 | (method_index_expression 202 | method: (identifier) @method.call) 203 | ]) 204 | 205 | (function_call 206 | (identifier) @function.builtin 207 | (#any-of? @function.builtin 208 | ;; built-in functions in Lua 5.1 209 | "assert" "collectgarbage" "dofile" "error" "getfenv" "getmetatable" "ipairs" 210 | "load" "loadfile" "loadstring" "module" "next" "pairs" "pcall" "print" 211 | "rawequal" "rawget" "rawset" "require" "select" "setfenv" "setmetatable" 212 | "tonumber" "tostring" "type" "unpack" "xpcall")) 213 | 214 | ;; Others 215 | 216 | (comment) @comment 217 | 218 | (hash_bang_line) @preproc 219 | 220 | (number) @number 221 | 222 | (string) @string 223 | 224 | (escape_sequence) @string.escape 225 | -------------------------------------------------------------------------------- /queries/injections.scm: -------------------------------------------------------------------------------- 1 | ((function_call 2 | name: [ 3 | (identifier) @_cdef_identifier 4 | (_ _ (identifier) @_cdef_identifier) 5 | ] 6 | arguments: (arguments (string content: _ @injection.content 7 | (#set! injection.language "c")))) 8 | (#eq? @_cdef_identifier "cdef")) 9 | -------------------------------------------------------------------------------- /queries/locals.scm: -------------------------------------------------------------------------------- 1 | ; Scopes 2 | 3 | [ 4 | (chunk) 5 | (do_statement) 6 | (while_statement) 7 | (repeat_statement) 8 | (if_statement) 9 | (for_statement) 10 | (function_declaration) 11 | (function_definition) 12 | ] @local.scope 13 | 14 | ; Definitions 15 | 16 | (assignment_statement 17 | (variable_list 18 | (identifier) @local.definition)) 19 | 20 | (function_declaration 21 | name: (identifier) @local.definition) 22 | 23 | (for_generic_clause 24 | (variable_list 25 | (identifier) @local.definition)) 26 | 27 | (for_numeric_clause 28 | name: (identifier) @local.definition) 29 | 30 | (parameters (identifier) @local.definition) 31 | 32 | ; References 33 | 34 | [ 35 | (identifier) 36 | ] @local.reference 37 | -------------------------------------------------------------------------------- /queries/tags.scm: -------------------------------------------------------------------------------- 1 | (function_declaration 2 | name: [ 3 | (identifier) @name 4 | (dot_index_expression 5 | field: (identifier) @name) 6 | ]) @definition.function 7 | 8 | (function_declaration 9 | name: (method_index_expression 10 | method: (identifier) @name)) @definition.method 11 | 12 | (assignment_statement 13 | (variable_list . 14 | name: [ 15 | (identifier) @name 16 | (dot_index_expression 17 | field: (identifier) @name) 18 | ]) 19 | (expression_list . 20 | value: (function_definition))) @definition.function 21 | 22 | (table_constructor 23 | (field 24 | name: (identifier) @name 25 | value: (function_definition))) @definition.function 26 | 27 | (function_call 28 | name: [ 29 | (identifier) @name 30 | (dot_index_expression 31 | field: (identifier) @name) 32 | (method_index_expression 33 | method: (identifier) @name) 34 | ]) @reference.call 35 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | from platform import system 3 | from sysconfig import get_config_var 4 | 5 | from setuptools import Extension, find_packages, setup 6 | from setuptools.command.build import build 7 | from setuptools.command.egg_info import egg_info 8 | from wheel.bdist_wheel import bdist_wheel 9 | 10 | sources = [ 11 | "bindings/python/tree_sitter_lua/binding.c", 12 | "src/parser.c", 13 | ] 14 | if path.exists("src/scanner.c"): 15 | sources.append("src/scanner.c") 16 | 17 | macros: list[tuple[str, str | None]] = [ 18 | ("PY_SSIZE_T_CLEAN", None), 19 | ("TREE_SITTER_HIDE_SYMBOLS", None), 20 | ] 21 | if limited_api := not get_config_var("Py_GIL_DISABLED"): 22 | macros.append(("Py_LIMITED_API", "0x030A0000")) 23 | 24 | if system() != "Windows": 25 | cflags = ["-std=c11", "-fvisibility=hidden"] 26 | else: 27 | cflags = ["/std:c11", "/utf-8"] 28 | 29 | 30 | class Build(build): 31 | def run(self): 32 | if path.isdir("queries"): 33 | dest = path.join(self.build_lib, "tree_sitter_lua", "queries") 34 | self.copy_tree("queries", dest) 35 | super().run() 36 | 37 | 38 | class BdistWheel(bdist_wheel): 39 | def get_tag(self): 40 | python, abi, platform = super().get_tag() 41 | if python.startswith("cp"): 42 | python, abi = "cp310", "abi3" 43 | return python, abi, platform 44 | 45 | 46 | class EggInfo(egg_info): 47 | def find_sources(self): 48 | super().find_sources() 49 | self.filelist.recursive_include("queries", "*.scm") 50 | self.filelist.include("src/tree_sitter/*.h") 51 | 52 | 53 | setup( 54 | packages=find_packages("bindings/python"), 55 | package_dir={"": "bindings/python"}, 56 | package_data={ 57 | "tree_sitter_lua": ["*.pyi", "py.typed"], 58 | "tree_sitter_lua.queries": ["*.scm"], 59 | }, 60 | ext_package="tree_sitter_lua", 61 | ext_modules=[ 62 | Extension( 63 | name="_binding", 64 | sources=sources, 65 | extra_compile_args=cflags, 66 | define_macros=macros, 67 | include_dirs=["src"], 68 | py_limited_api=limited_api, 69 | ) 70 | ], 71 | cmdclass={ 72 | "build": Build, 73 | "bdist_wheel": BdistWheel, 74 | "egg_info": EggInfo, 75 | }, 76 | zip_safe=False 77 | ) 78 | -------------------------------------------------------------------------------- /src/node-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "declaration", 4 | "named": true, 5 | "subtypes": [ 6 | { 7 | "type": "function_declaration", 8 | "named": true 9 | }, 10 | { 11 | "type": "variable_declaration", 12 | "named": true 13 | } 14 | ] 15 | }, 16 | { 17 | "type": "expression", 18 | "named": true, 19 | "subtypes": [ 20 | { 21 | "type": "binary_expression", 22 | "named": true 23 | }, 24 | { 25 | "type": "false", 26 | "named": true 27 | }, 28 | { 29 | "type": "function_call", 30 | "named": true 31 | }, 32 | { 33 | "type": "function_definition", 34 | "named": true 35 | }, 36 | { 37 | "type": "nil", 38 | "named": true 39 | }, 40 | { 41 | "type": "number", 42 | "named": true 43 | }, 44 | { 45 | "type": "parenthesized_expression", 46 | "named": true 47 | }, 48 | { 49 | "type": "string", 50 | "named": true 51 | }, 52 | { 53 | "type": "table_constructor", 54 | "named": true 55 | }, 56 | { 57 | "type": "true", 58 | "named": true 59 | }, 60 | { 61 | "type": "unary_expression", 62 | "named": true 63 | }, 64 | { 65 | "type": "vararg_expression", 66 | "named": true 67 | }, 68 | { 69 | "type": "variable", 70 | "named": true 71 | } 72 | ] 73 | }, 74 | { 75 | "type": "statement", 76 | "named": true, 77 | "subtypes": [ 78 | { 79 | "type": "assignment_statement", 80 | "named": true 81 | }, 82 | { 83 | "type": "break_statement", 84 | "named": true 85 | }, 86 | { 87 | "type": "declaration", 88 | "named": true 89 | }, 90 | { 91 | "type": "do_statement", 92 | "named": true 93 | }, 94 | { 95 | "type": "empty_statement", 96 | "named": true 97 | }, 98 | { 99 | "type": "for_statement", 100 | "named": true 101 | }, 102 | { 103 | "type": "function_call", 104 | "named": true 105 | }, 106 | { 107 | "type": "goto_statement", 108 | "named": true 109 | }, 110 | { 111 | "type": "if_statement", 112 | "named": true 113 | }, 114 | { 115 | "type": "label_statement", 116 | "named": true 117 | }, 118 | { 119 | "type": "repeat_statement", 120 | "named": true 121 | }, 122 | { 123 | "type": "while_statement", 124 | "named": true 125 | } 126 | ] 127 | }, 128 | { 129 | "type": "variable", 130 | "named": true, 131 | "subtypes": [ 132 | { 133 | "type": "bracket_index_expression", 134 | "named": true 135 | }, 136 | { 137 | "type": "dot_index_expression", 138 | "named": true 139 | }, 140 | { 141 | "type": "identifier", 142 | "named": true 143 | } 144 | ] 145 | }, 146 | { 147 | "type": "arguments", 148 | "named": true, 149 | "fields": {}, 150 | "children": { 151 | "multiple": true, 152 | "required": false, 153 | "types": [ 154 | { 155 | "type": "expression", 156 | "named": true 157 | } 158 | ] 159 | } 160 | }, 161 | { 162 | "type": "assignment_statement", 163 | "named": true, 164 | "fields": {}, 165 | "children": { 166 | "multiple": true, 167 | "required": true, 168 | "types": [ 169 | { 170 | "type": "expression_list", 171 | "named": true 172 | }, 173 | { 174 | "type": "variable_list", 175 | "named": true 176 | } 177 | ] 178 | } 179 | }, 180 | { 181 | "type": "attribute", 182 | "named": true, 183 | "fields": {}, 184 | "children": { 185 | "multiple": false, 186 | "required": true, 187 | "types": [ 188 | { 189 | "type": "identifier", 190 | "named": true 191 | } 192 | ] 193 | } 194 | }, 195 | { 196 | "type": "binary_expression", 197 | "named": true, 198 | "fields": { 199 | "left": { 200 | "multiple": false, 201 | "required": true, 202 | "types": [ 203 | { 204 | "type": "expression", 205 | "named": true 206 | } 207 | ] 208 | }, 209 | "right": { 210 | "multiple": false, 211 | "required": true, 212 | "types": [ 213 | { 214 | "type": "expression", 215 | "named": true 216 | } 217 | ] 218 | } 219 | } 220 | }, 221 | { 222 | "type": "block", 223 | "named": true, 224 | "fields": {}, 225 | "children": { 226 | "multiple": true, 227 | "required": true, 228 | "types": [ 229 | { 230 | "type": "return_statement", 231 | "named": true 232 | }, 233 | { 234 | "type": "statement", 235 | "named": true 236 | } 237 | ] 238 | } 239 | }, 240 | { 241 | "type": "bracket_index_expression", 242 | "named": true, 243 | "fields": { 244 | "field": { 245 | "multiple": false, 246 | "required": true, 247 | "types": [ 248 | { 249 | "type": "expression", 250 | "named": true 251 | } 252 | ] 253 | }, 254 | "table": { 255 | "multiple": false, 256 | "required": true, 257 | "types": [ 258 | { 259 | "type": "function_call", 260 | "named": true 261 | }, 262 | { 263 | "type": "parenthesized_expression", 264 | "named": true 265 | }, 266 | { 267 | "type": "variable", 268 | "named": true 269 | } 270 | ] 271 | } 272 | } 273 | }, 274 | { 275 | "type": "chunk", 276 | "named": true, 277 | "root": true, 278 | "fields": {}, 279 | "children": { 280 | "multiple": true, 281 | "required": false, 282 | "types": [ 283 | { 284 | "type": "hash_bang_line", 285 | "named": true 286 | }, 287 | { 288 | "type": "return_statement", 289 | "named": true 290 | }, 291 | { 292 | "type": "statement", 293 | "named": true 294 | } 295 | ] 296 | } 297 | }, 298 | { 299 | "type": "comment", 300 | "named": true, 301 | "fields": { 302 | "content": { 303 | "multiple": false, 304 | "required": true, 305 | "types": [ 306 | { 307 | "type": "comment_content", 308 | "named": true 309 | } 310 | ] 311 | }, 312 | "end": { 313 | "multiple": false, 314 | "required": false, 315 | "types": [ 316 | { 317 | "type": "]]", 318 | "named": false 319 | } 320 | ] 321 | }, 322 | "start": { 323 | "multiple": false, 324 | "required": true, 325 | "types": [ 326 | { 327 | "type": "--", 328 | "named": false 329 | }, 330 | { 331 | "type": "[[", 332 | "named": false 333 | } 334 | ] 335 | } 336 | } 337 | }, 338 | { 339 | "type": "do_statement", 340 | "named": true, 341 | "fields": { 342 | "body": { 343 | "multiple": false, 344 | "required": false, 345 | "types": [ 346 | { 347 | "type": "block", 348 | "named": true 349 | } 350 | ] 351 | } 352 | } 353 | }, 354 | { 355 | "type": "dot_index_expression", 356 | "named": true, 357 | "fields": { 358 | "field": { 359 | "multiple": false, 360 | "required": true, 361 | "types": [ 362 | { 363 | "type": "identifier", 364 | "named": true 365 | } 366 | ] 367 | }, 368 | "table": { 369 | "multiple": false, 370 | "required": true, 371 | "types": [ 372 | { 373 | "type": "function_call", 374 | "named": true 375 | }, 376 | { 377 | "type": "parenthesized_expression", 378 | "named": true 379 | }, 380 | { 381 | "type": "variable", 382 | "named": true 383 | } 384 | ] 385 | } 386 | } 387 | }, 388 | { 389 | "type": "else_statement", 390 | "named": true, 391 | "fields": { 392 | "body": { 393 | "multiple": false, 394 | "required": false, 395 | "types": [ 396 | { 397 | "type": "block", 398 | "named": true 399 | } 400 | ] 401 | } 402 | } 403 | }, 404 | { 405 | "type": "elseif_statement", 406 | "named": true, 407 | "fields": { 408 | "condition": { 409 | "multiple": false, 410 | "required": true, 411 | "types": [ 412 | { 413 | "type": "expression", 414 | "named": true 415 | } 416 | ] 417 | }, 418 | "consequence": { 419 | "multiple": false, 420 | "required": false, 421 | "types": [ 422 | { 423 | "type": "block", 424 | "named": true 425 | } 426 | ] 427 | } 428 | } 429 | }, 430 | { 431 | "type": "empty_statement", 432 | "named": true, 433 | "fields": {} 434 | }, 435 | { 436 | "type": "expression_list", 437 | "named": true, 438 | "fields": { 439 | "value": { 440 | "multiple": true, 441 | "required": false, 442 | "types": [ 443 | { 444 | "type": "expression", 445 | "named": true 446 | } 447 | ] 448 | } 449 | }, 450 | "children": { 451 | "multiple": true, 452 | "required": false, 453 | "types": [ 454 | { 455 | "type": "expression", 456 | "named": true 457 | } 458 | ] 459 | } 460 | }, 461 | { 462 | "type": "field", 463 | "named": true, 464 | "fields": { 465 | "name": { 466 | "multiple": false, 467 | "required": false, 468 | "types": [ 469 | { 470 | "type": "expression", 471 | "named": true 472 | }, 473 | { 474 | "type": "identifier", 475 | "named": true 476 | } 477 | ] 478 | }, 479 | "value": { 480 | "multiple": false, 481 | "required": true, 482 | "types": [ 483 | { 484 | "type": "expression", 485 | "named": true 486 | } 487 | ] 488 | } 489 | } 490 | }, 491 | { 492 | "type": "for_generic_clause", 493 | "named": true, 494 | "fields": {}, 495 | "children": { 496 | "multiple": true, 497 | "required": true, 498 | "types": [ 499 | { 500 | "type": "expression_list", 501 | "named": true 502 | }, 503 | { 504 | "type": "variable_list", 505 | "named": true 506 | } 507 | ] 508 | } 509 | }, 510 | { 511 | "type": "for_numeric_clause", 512 | "named": true, 513 | "fields": { 514 | "end": { 515 | "multiple": false, 516 | "required": true, 517 | "types": [ 518 | { 519 | "type": "expression", 520 | "named": true 521 | } 522 | ] 523 | }, 524 | "name": { 525 | "multiple": false, 526 | "required": true, 527 | "types": [ 528 | { 529 | "type": "identifier", 530 | "named": true 531 | } 532 | ] 533 | }, 534 | "start": { 535 | "multiple": false, 536 | "required": true, 537 | "types": [ 538 | { 539 | "type": "expression", 540 | "named": true 541 | } 542 | ] 543 | }, 544 | "step": { 545 | "multiple": false, 546 | "required": false, 547 | "types": [ 548 | { 549 | "type": "expression", 550 | "named": true 551 | } 552 | ] 553 | } 554 | } 555 | }, 556 | { 557 | "type": "for_statement", 558 | "named": true, 559 | "fields": { 560 | "body": { 561 | "multiple": false, 562 | "required": false, 563 | "types": [ 564 | { 565 | "type": "block", 566 | "named": true 567 | } 568 | ] 569 | }, 570 | "clause": { 571 | "multiple": false, 572 | "required": true, 573 | "types": [ 574 | { 575 | "type": "for_generic_clause", 576 | "named": true 577 | }, 578 | { 579 | "type": "for_numeric_clause", 580 | "named": true 581 | } 582 | ] 583 | } 584 | } 585 | }, 586 | { 587 | "type": "function_call", 588 | "named": true, 589 | "fields": { 590 | "arguments": { 591 | "multiple": false, 592 | "required": true, 593 | "types": [ 594 | { 595 | "type": "arguments", 596 | "named": true 597 | } 598 | ] 599 | }, 600 | "name": { 601 | "multiple": false, 602 | "required": true, 603 | "types": [ 604 | { 605 | "type": "function_call", 606 | "named": true 607 | }, 608 | { 609 | "type": "method_index_expression", 610 | "named": true 611 | }, 612 | { 613 | "type": "parenthesized_expression", 614 | "named": true 615 | }, 616 | { 617 | "type": "variable", 618 | "named": true 619 | } 620 | ] 621 | } 622 | } 623 | }, 624 | { 625 | "type": "function_declaration", 626 | "named": true, 627 | "fields": { 628 | "body": { 629 | "multiple": false, 630 | "required": false, 631 | "types": [ 632 | { 633 | "type": "block", 634 | "named": true 635 | } 636 | ] 637 | }, 638 | "name": { 639 | "multiple": false, 640 | "required": true, 641 | "types": [ 642 | { 643 | "type": "dot_index_expression", 644 | "named": true 645 | }, 646 | { 647 | "type": "identifier", 648 | "named": true 649 | }, 650 | { 651 | "type": "method_index_expression", 652 | "named": true 653 | } 654 | ] 655 | }, 656 | "parameters": { 657 | "multiple": false, 658 | "required": true, 659 | "types": [ 660 | { 661 | "type": "parameters", 662 | "named": true 663 | } 664 | ] 665 | } 666 | } 667 | }, 668 | { 669 | "type": "function_definition", 670 | "named": true, 671 | "fields": { 672 | "body": { 673 | "multiple": false, 674 | "required": false, 675 | "types": [ 676 | { 677 | "type": "block", 678 | "named": true 679 | } 680 | ] 681 | }, 682 | "parameters": { 683 | "multiple": false, 684 | "required": true, 685 | "types": [ 686 | { 687 | "type": "parameters", 688 | "named": true 689 | } 690 | ] 691 | } 692 | } 693 | }, 694 | { 695 | "type": "goto_statement", 696 | "named": true, 697 | "fields": {}, 698 | "children": { 699 | "multiple": false, 700 | "required": true, 701 | "types": [ 702 | { 703 | "type": "identifier", 704 | "named": true 705 | } 706 | ] 707 | } 708 | }, 709 | { 710 | "type": "if_statement", 711 | "named": true, 712 | "fields": { 713 | "alternative": { 714 | "multiple": true, 715 | "required": false, 716 | "types": [ 717 | { 718 | "type": "else_statement", 719 | "named": true 720 | }, 721 | { 722 | "type": "elseif_statement", 723 | "named": true 724 | } 725 | ] 726 | }, 727 | "condition": { 728 | "multiple": false, 729 | "required": true, 730 | "types": [ 731 | { 732 | "type": "expression", 733 | "named": true 734 | } 735 | ] 736 | }, 737 | "consequence": { 738 | "multiple": false, 739 | "required": false, 740 | "types": [ 741 | { 742 | "type": "block", 743 | "named": true 744 | } 745 | ] 746 | } 747 | } 748 | }, 749 | { 750 | "type": "label_statement", 751 | "named": true, 752 | "fields": {}, 753 | "children": { 754 | "multiple": false, 755 | "required": true, 756 | "types": [ 757 | { 758 | "type": "identifier", 759 | "named": true 760 | } 761 | ] 762 | } 763 | }, 764 | { 765 | "type": "method_index_expression", 766 | "named": true, 767 | "fields": { 768 | "method": { 769 | "multiple": false, 770 | "required": true, 771 | "types": [ 772 | { 773 | "type": "identifier", 774 | "named": true 775 | } 776 | ] 777 | }, 778 | "table": { 779 | "multiple": false, 780 | "required": true, 781 | "types": [ 782 | { 783 | "type": "function_call", 784 | "named": true 785 | }, 786 | { 787 | "type": "parenthesized_expression", 788 | "named": true 789 | }, 790 | { 791 | "type": "variable", 792 | "named": true 793 | } 794 | ] 795 | } 796 | } 797 | }, 798 | { 799 | "type": "parameters", 800 | "named": true, 801 | "fields": { 802 | "name": { 803 | "multiple": true, 804 | "required": false, 805 | "types": [ 806 | { 807 | "type": "identifier", 808 | "named": true 809 | } 810 | ] 811 | } 812 | }, 813 | "children": { 814 | "multiple": false, 815 | "required": false, 816 | "types": [ 817 | { 818 | "type": "vararg_expression", 819 | "named": true 820 | } 821 | ] 822 | } 823 | }, 824 | { 825 | "type": "parenthesized_expression", 826 | "named": true, 827 | "fields": {}, 828 | "children": { 829 | "multiple": false, 830 | "required": true, 831 | "types": [ 832 | { 833 | "type": "expression", 834 | "named": true 835 | } 836 | ] 837 | } 838 | }, 839 | { 840 | "type": "repeat_statement", 841 | "named": true, 842 | "fields": { 843 | "body": { 844 | "multiple": false, 845 | "required": false, 846 | "types": [ 847 | { 848 | "type": "block", 849 | "named": true 850 | } 851 | ] 852 | }, 853 | "condition": { 854 | "multiple": false, 855 | "required": true, 856 | "types": [ 857 | { 858 | "type": "expression", 859 | "named": true 860 | } 861 | ] 862 | } 863 | } 864 | }, 865 | { 866 | "type": "return_statement", 867 | "named": true, 868 | "fields": {}, 869 | "children": { 870 | "multiple": false, 871 | "required": false, 872 | "types": [ 873 | { 874 | "type": "expression_list", 875 | "named": true 876 | } 877 | ] 878 | } 879 | }, 880 | { 881 | "type": "string", 882 | "named": true, 883 | "fields": { 884 | "content": { 885 | "multiple": false, 886 | "required": false, 887 | "types": [ 888 | { 889 | "type": "string_content", 890 | "named": true 891 | } 892 | ] 893 | }, 894 | "end": { 895 | "multiple": false, 896 | "required": true, 897 | "types": [ 898 | { 899 | "type": "\"", 900 | "named": false 901 | }, 902 | { 903 | "type": "'", 904 | "named": false 905 | }, 906 | { 907 | "type": "]]", 908 | "named": false 909 | } 910 | ] 911 | }, 912 | "start": { 913 | "multiple": false, 914 | "required": true, 915 | "types": [ 916 | { 917 | "type": "\"", 918 | "named": false 919 | }, 920 | { 921 | "type": "'", 922 | "named": false 923 | }, 924 | { 925 | "type": "[[", 926 | "named": false 927 | } 928 | ] 929 | } 930 | } 931 | }, 932 | { 933 | "type": "string_content", 934 | "named": true, 935 | "fields": {}, 936 | "children": { 937 | "multiple": true, 938 | "required": false, 939 | "types": [ 940 | { 941 | "type": "escape_sequence", 942 | "named": true 943 | } 944 | ] 945 | } 946 | }, 947 | { 948 | "type": "table_constructor", 949 | "named": true, 950 | "fields": {}, 951 | "children": { 952 | "multiple": true, 953 | "required": false, 954 | "types": [ 955 | { 956 | "type": "field", 957 | "named": true 958 | } 959 | ] 960 | } 961 | }, 962 | { 963 | "type": "unary_expression", 964 | "named": true, 965 | "fields": { 966 | "operand": { 967 | "multiple": false, 968 | "required": true, 969 | "types": [ 970 | { 971 | "type": "expression", 972 | "named": true 973 | } 974 | ] 975 | } 976 | } 977 | }, 978 | { 979 | "type": "variable_declaration", 980 | "named": true, 981 | "fields": {}, 982 | "children": { 983 | "multiple": false, 984 | "required": true, 985 | "types": [ 986 | { 987 | "type": "assignment_statement", 988 | "named": true 989 | }, 990 | { 991 | "type": "variable_list", 992 | "named": true 993 | } 994 | ] 995 | } 996 | }, 997 | { 998 | "type": "variable_list", 999 | "named": true, 1000 | "fields": { 1001 | "attribute": { 1002 | "multiple": true, 1003 | "required": false, 1004 | "types": [ 1005 | { 1006 | "type": "attribute", 1007 | "named": true 1008 | } 1009 | ] 1010 | }, 1011 | "name": { 1012 | "multiple": true, 1013 | "required": true, 1014 | "types": [ 1015 | { 1016 | "type": "variable", 1017 | "named": true 1018 | } 1019 | ] 1020 | } 1021 | } 1022 | }, 1023 | { 1024 | "type": "while_statement", 1025 | "named": true, 1026 | "fields": { 1027 | "body": { 1028 | "multiple": false, 1029 | "required": false, 1030 | "types": [ 1031 | { 1032 | "type": "block", 1033 | "named": true 1034 | } 1035 | ] 1036 | }, 1037 | "condition": { 1038 | "multiple": false, 1039 | "required": true, 1040 | "types": [ 1041 | { 1042 | "type": "expression", 1043 | "named": true 1044 | } 1045 | ] 1046 | } 1047 | } 1048 | }, 1049 | { 1050 | "type": "\"", 1051 | "named": false 1052 | }, 1053 | { 1054 | "type": "#", 1055 | "named": false 1056 | }, 1057 | { 1058 | "type": "%", 1059 | "named": false 1060 | }, 1061 | { 1062 | "type": "&", 1063 | "named": false 1064 | }, 1065 | { 1066 | "type": "'", 1067 | "named": false 1068 | }, 1069 | { 1070 | "type": "(", 1071 | "named": false 1072 | }, 1073 | { 1074 | "type": ")", 1075 | "named": false 1076 | }, 1077 | { 1078 | "type": "*", 1079 | "named": false 1080 | }, 1081 | { 1082 | "type": "+", 1083 | "named": false 1084 | }, 1085 | { 1086 | "type": ",", 1087 | "named": false 1088 | }, 1089 | { 1090 | "type": "-", 1091 | "named": false 1092 | }, 1093 | { 1094 | "type": "--", 1095 | "named": false 1096 | }, 1097 | { 1098 | "type": ".", 1099 | "named": false 1100 | }, 1101 | { 1102 | "type": "..", 1103 | "named": false 1104 | }, 1105 | { 1106 | "type": "/", 1107 | "named": false 1108 | }, 1109 | { 1110 | "type": "//", 1111 | "named": false 1112 | }, 1113 | { 1114 | "type": ":", 1115 | "named": false 1116 | }, 1117 | { 1118 | "type": "::", 1119 | "named": false 1120 | }, 1121 | { 1122 | "type": ";", 1123 | "named": false 1124 | }, 1125 | { 1126 | "type": "<", 1127 | "named": false 1128 | }, 1129 | { 1130 | "type": "<<", 1131 | "named": false 1132 | }, 1133 | { 1134 | "type": "<=", 1135 | "named": false 1136 | }, 1137 | { 1138 | "type": "=", 1139 | "named": false 1140 | }, 1141 | { 1142 | "type": "==", 1143 | "named": false 1144 | }, 1145 | { 1146 | "type": ">", 1147 | "named": false 1148 | }, 1149 | { 1150 | "type": ">=", 1151 | "named": false 1152 | }, 1153 | { 1154 | "type": ">>", 1155 | "named": false 1156 | }, 1157 | { 1158 | "type": "[", 1159 | "named": false 1160 | }, 1161 | { 1162 | "type": "[[", 1163 | "named": false 1164 | }, 1165 | { 1166 | "type": "]", 1167 | "named": false 1168 | }, 1169 | { 1170 | "type": "]]", 1171 | "named": false 1172 | }, 1173 | { 1174 | "type": "^", 1175 | "named": false 1176 | }, 1177 | { 1178 | "type": "and", 1179 | "named": false 1180 | }, 1181 | { 1182 | "type": "break_statement", 1183 | "named": true 1184 | }, 1185 | { 1186 | "type": "comment_content", 1187 | "named": true 1188 | }, 1189 | { 1190 | "type": "do", 1191 | "named": false 1192 | }, 1193 | { 1194 | "type": "else", 1195 | "named": false 1196 | }, 1197 | { 1198 | "type": "elseif", 1199 | "named": false 1200 | }, 1201 | { 1202 | "type": "end", 1203 | "named": false 1204 | }, 1205 | { 1206 | "type": "escape_sequence", 1207 | "named": true 1208 | }, 1209 | { 1210 | "type": "false", 1211 | "named": true 1212 | }, 1213 | { 1214 | "type": "for", 1215 | "named": false 1216 | }, 1217 | { 1218 | "type": "function", 1219 | "named": false 1220 | }, 1221 | { 1222 | "type": "goto", 1223 | "named": false 1224 | }, 1225 | { 1226 | "type": "hash_bang_line", 1227 | "named": true 1228 | }, 1229 | { 1230 | "type": "identifier", 1231 | "named": true 1232 | }, 1233 | { 1234 | "type": "if", 1235 | "named": false 1236 | }, 1237 | { 1238 | "type": "in", 1239 | "named": false 1240 | }, 1241 | { 1242 | "type": "local", 1243 | "named": false 1244 | }, 1245 | { 1246 | "type": "nil", 1247 | "named": true 1248 | }, 1249 | { 1250 | "type": "not", 1251 | "named": false 1252 | }, 1253 | { 1254 | "type": "number", 1255 | "named": true 1256 | }, 1257 | { 1258 | "type": "or", 1259 | "named": false 1260 | }, 1261 | { 1262 | "type": "repeat", 1263 | "named": false 1264 | }, 1265 | { 1266 | "type": "return", 1267 | "named": false 1268 | }, 1269 | { 1270 | "type": "then", 1271 | "named": false 1272 | }, 1273 | { 1274 | "type": "true", 1275 | "named": true 1276 | }, 1277 | { 1278 | "type": "until", 1279 | "named": false 1280 | }, 1281 | { 1282 | "type": "vararg_expression", 1283 | "named": true 1284 | }, 1285 | { 1286 | "type": "while", 1287 | "named": false 1288 | }, 1289 | { 1290 | "type": "{", 1291 | "named": false 1292 | }, 1293 | { 1294 | "type": "|", 1295 | "named": false 1296 | }, 1297 | { 1298 | "type": "}", 1299 | "named": false 1300 | }, 1301 | { 1302 | "type": "~", 1303 | "named": false 1304 | }, 1305 | { 1306 | "type": "~=", 1307 | "named": false 1308 | } 1309 | ] -------------------------------------------------------------------------------- /src/scanner.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tree_sitter/alloc.h" 3 | #include "tree_sitter/parser.h" 4 | #include 5 | 6 | enum TokenType { 7 | BLOCK_COMMENT_START, 8 | BLOCK_COMMENT_CONTENT, 9 | BLOCK_COMMENT_END, 10 | 11 | BLOCK_STRING_START, 12 | BLOCK_STRING_CONTENT, 13 | BLOCK_STRING_END, 14 | }; 15 | 16 | static inline void consume(TSLexer *lexer) { lexer->advance(lexer, false); } 17 | 18 | static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); } 19 | 20 | static inline bool consume_char(char c, TSLexer *lexer) { 21 | if (lexer->lookahead != c) { 22 | return false; 23 | } 24 | 25 | consume(lexer); 26 | return true; 27 | } 28 | 29 | static inline uint8_t consume_and_count_char(char c, TSLexer *lexer) { 30 | uint8_t count = 0; 31 | while (lexer->lookahead == c) { 32 | ++count; 33 | consume(lexer); 34 | } 35 | return count; 36 | } 37 | 38 | static inline void skip_whitespaces(TSLexer *lexer) { 39 | while (iswspace(lexer->lookahead)) { 40 | skip(lexer); 41 | } 42 | } 43 | 44 | typedef struct { 45 | char ending_char; 46 | uint8_t level_count; 47 | } Scanner; 48 | 49 | static inline void reset_state(Scanner *scanner) { 50 | scanner->ending_char = 0; 51 | scanner->level_count = 0; 52 | } 53 | 54 | void *tree_sitter_lua_external_scanner_create() { 55 | Scanner *scanner = ts_calloc(1, sizeof(Scanner)); 56 | return scanner; 57 | } 58 | 59 | void tree_sitter_lua_external_scanner_destroy(void *payload) { 60 | Scanner *scanner = (Scanner *)payload; 61 | ts_free(scanner); 62 | } 63 | 64 | unsigned tree_sitter_lua_external_scanner_serialize(void *payload, char *buffer) { 65 | Scanner *scanner = (Scanner *)payload; 66 | buffer[0] = scanner->ending_char; 67 | buffer[1] = (char)scanner->level_count; 68 | return 2; 69 | } 70 | 71 | void tree_sitter_lua_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) { 72 | Scanner *scanner = (Scanner *)payload; 73 | if (length == 0) return; 74 | scanner->ending_char = buffer[0]; 75 | if (length == 1) return; 76 | scanner->level_count = buffer[1]; 77 | } 78 | 79 | static bool scan_block_start(Scanner *scanner, TSLexer *lexer) { 80 | if (consume_char('[', lexer)) { 81 | uint8_t level = consume_and_count_char('=', lexer); 82 | 83 | if (consume_char('[', lexer)) { 84 | scanner->level_count = level; 85 | return true; 86 | } 87 | } 88 | 89 | return false; 90 | } 91 | 92 | static bool scan_block_end(Scanner *scanner, TSLexer *lexer) { 93 | if (consume_char(']', lexer)) { 94 | uint8_t level = consume_and_count_char('=', lexer); 95 | 96 | if (scanner->level_count == level && consume_char(']', lexer)) { 97 | return true; 98 | } 99 | } 100 | 101 | return false; 102 | } 103 | 104 | static bool scan_block_content(Scanner *scanner, TSLexer *lexer) { 105 | while (lexer->lookahead != 0) { 106 | if (lexer->lookahead == ']') { 107 | lexer->mark_end(lexer); 108 | 109 | if (scan_block_end(scanner, lexer)) { 110 | return true; 111 | } 112 | } else { 113 | consume(lexer); 114 | } 115 | } 116 | 117 | return false; 118 | } 119 | 120 | static bool scan_comment_start(Scanner *scanner, TSLexer *lexer) { 121 | if (consume_char('-', lexer) && consume_char('-', lexer)) { 122 | lexer->mark_end(lexer); 123 | 124 | if (scan_block_start(scanner, lexer)) { 125 | lexer->mark_end(lexer); 126 | lexer->result_symbol = BLOCK_COMMENT_START; 127 | return true; 128 | } 129 | } 130 | 131 | return false; 132 | } 133 | 134 | static bool scan_comment_content(Scanner *scanner, TSLexer *lexer) { 135 | if (scanner->ending_char == 0) { // block comment 136 | if (scan_block_content(scanner, lexer)) { 137 | lexer->result_symbol = BLOCK_COMMENT_CONTENT; 138 | return true; 139 | } 140 | 141 | return false; 142 | } 143 | 144 | while (lexer->lookahead != 0) { 145 | if (lexer->lookahead == scanner->ending_char) { 146 | reset_state(scanner); 147 | lexer->result_symbol = BLOCK_COMMENT_CONTENT; 148 | return true; 149 | } 150 | 151 | consume(lexer); 152 | } 153 | 154 | return false; 155 | } 156 | 157 | bool tree_sitter_lua_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { 158 | Scanner *scanner = (Scanner *)payload; 159 | 160 | if (valid_symbols[BLOCK_STRING_END] && scan_block_end(scanner, lexer)) { 161 | reset_state(scanner); 162 | lexer->result_symbol = BLOCK_STRING_END; 163 | return true; 164 | } 165 | 166 | if (valid_symbols[BLOCK_STRING_CONTENT] && scan_block_content(scanner, lexer)) { 167 | lexer->result_symbol = BLOCK_STRING_CONTENT; 168 | return true; 169 | } 170 | 171 | if (valid_symbols[BLOCK_COMMENT_END] && scanner->ending_char == 0 && scan_block_end(scanner, lexer)) { 172 | reset_state(scanner); 173 | lexer->result_symbol = BLOCK_COMMENT_END; 174 | return true; 175 | } 176 | 177 | if (valid_symbols[BLOCK_COMMENT_CONTENT] && scan_comment_content(scanner, lexer)) { 178 | return true; 179 | } 180 | 181 | skip_whitespaces(lexer); 182 | 183 | if (valid_symbols[BLOCK_STRING_START] && scan_block_start(scanner, lexer)) { 184 | lexer->result_symbol = BLOCK_STRING_START; 185 | return true; 186 | } 187 | 188 | if (valid_symbols[BLOCK_COMMENT_START]) { 189 | if (scan_comment_start(scanner, lexer)) { 190 | return true; 191 | } 192 | } 193 | 194 | return false; 195 | } 196 | -------------------------------------------------------------------------------- /src/tree_sitter/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ALLOC_H_ 2 | #define TREE_SITTER_ALLOC_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // Allow clients to override allocation functions 13 | #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 | 15 | extern void *(*ts_current_malloc)(size_t size); 16 | extern void *(*ts_current_calloc)(size_t count, size_t size); 17 | extern void *(*ts_current_realloc)(void *ptr, size_t size); 18 | extern void (*ts_current_free)(void *ptr); 19 | 20 | #ifndef ts_malloc 21 | #define ts_malloc ts_current_malloc 22 | #endif 23 | #ifndef ts_calloc 24 | #define ts_calloc ts_current_calloc 25 | #endif 26 | #ifndef ts_realloc 27 | #define ts_realloc ts_current_realloc 28 | #endif 29 | #ifndef ts_free 30 | #define ts_free ts_current_free 31 | #endif 32 | 33 | #else 34 | 35 | #ifndef ts_malloc 36 | #define ts_malloc malloc 37 | #endif 38 | #ifndef ts_calloc 39 | #define ts_calloc calloc 40 | #endif 41 | #ifndef ts_realloc 42 | #define ts_realloc realloc 43 | #endif 44 | #ifndef ts_free 45 | #define ts_free free 46 | #endif 47 | 48 | #endif 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif // TREE_SITTER_ALLOC_H_ 55 | -------------------------------------------------------------------------------- /src/tree_sitter/array.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ARRAY_H_ 2 | #define TREE_SITTER_ARRAY_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./alloc.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | #pragma warning(push) 18 | #pragma warning(disable : 4101) 19 | #elif defined(__GNUC__) || defined(__clang__) 20 | #pragma GCC diagnostic push 21 | #pragma GCC diagnostic ignored "-Wunused-variable" 22 | #endif 23 | 24 | #define Array(T) \ 25 | struct { \ 26 | T *contents; \ 27 | uint32_t size; \ 28 | uint32_t capacity; \ 29 | } 30 | 31 | /// Initialize an array. 32 | #define array_init(self) \ 33 | ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 34 | 35 | /// Create an empty array. 36 | #define array_new() \ 37 | { NULL, 0, 0 } 38 | 39 | /// Get a pointer to the element at a given `index` in the array. 40 | #define array_get(self, _index) \ 41 | (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 42 | 43 | /// Get a pointer to the first element in the array. 44 | #define array_front(self) array_get(self, 0) 45 | 46 | /// Get a pointer to the last element in the array. 47 | #define array_back(self) array_get(self, (self)->size - 1) 48 | 49 | /// Clear the array, setting its size to zero. Note that this does not free any 50 | /// memory allocated for the array's contents. 51 | #define array_clear(self) ((self)->size = 0) 52 | 53 | /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 54 | /// less than the array's current capacity, this function has no effect. 55 | #define array_reserve(self, new_capacity) \ 56 | _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 57 | 58 | /// Free any memory allocated for this array. Note that this does not free any 59 | /// memory allocated for the array's contents. 60 | #define array_delete(self) _array__delete((Array *)(self)) 61 | 62 | /// Push a new `element` onto the end of the array. 63 | #define array_push(self, element) \ 64 | (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 65 | (self)->contents[(self)->size++] = (element)) 66 | 67 | /// Increase the array's size by `count` elements. 68 | /// New elements are zero-initialized. 69 | #define array_grow_by(self, count) \ 70 | do { \ 71 | if ((count) == 0) break; \ 72 | _array__grow((Array *)(self), count, array_elem_size(self)); \ 73 | memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 74 | (self)->size += (count); \ 75 | } while (0) 76 | 77 | /// Append all elements from one array to the end of another. 78 | #define array_push_all(self, other) \ 79 | array_extend((self), (other)->size, (other)->contents) 80 | 81 | /// Append `count` elements to the end of the array, reading their values from the 82 | /// `contents` pointer. 83 | #define array_extend(self, count, contents) \ 84 | _array__splice( \ 85 | (Array *)(self), array_elem_size(self), (self)->size, \ 86 | 0, count, contents \ 87 | ) 88 | 89 | /// Remove `old_count` elements from the array starting at the given `index`. At 90 | /// the same index, insert `new_count` new elements, reading their values from the 91 | /// `new_contents` pointer. 92 | #define array_splice(self, _index, old_count, new_count, new_contents) \ 93 | _array__splice( \ 94 | (Array *)(self), array_elem_size(self), _index, \ 95 | old_count, new_count, new_contents \ 96 | ) 97 | 98 | /// Insert one `element` into the array at the given `index`. 99 | #define array_insert(self, _index, element) \ 100 | _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 101 | 102 | /// Remove one element from the array at the given `index`. 103 | #define array_erase(self, _index) \ 104 | _array__erase((Array *)(self), array_elem_size(self), _index) 105 | 106 | /// Pop the last element off the array, returning the element by value. 107 | #define array_pop(self) ((self)->contents[--(self)->size]) 108 | 109 | /// Assign the contents of one array to another, reallocating if necessary. 110 | #define array_assign(self, other) \ 111 | _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 112 | 113 | /// Swap one array with another 114 | #define array_swap(self, other) \ 115 | _array__swap((Array *)(self), (Array *)(other)) 116 | 117 | /// Get the size of the array contents 118 | #define array_elem_size(self) (sizeof *(self)->contents) 119 | 120 | /// Search a sorted array for a given `needle` value, using the given `compare` 121 | /// callback to determine the order. 122 | /// 123 | /// If an existing element is found to be equal to `needle`, then the `index` 124 | /// out-parameter is set to the existing value's index, and the `exists` 125 | /// out-parameter is set to true. Otherwise, `index` is set to an index where 126 | /// `needle` should be inserted in order to preserve the sorting, and `exists` 127 | /// is set to false. 128 | #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 129 | _array__search_sorted(self, 0, compare, , needle, _index, _exists) 130 | 131 | /// Search a sorted array for a given `needle` value, using integer comparisons 132 | /// of a given struct field (specified with a leading dot) to determine the order. 133 | /// 134 | /// See also `array_search_sorted_with`. 135 | #define array_search_sorted_by(self, field, needle, _index, _exists) \ 136 | _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 137 | 138 | /// Insert a given `value` into a sorted array, using the given `compare` 139 | /// callback to determine the order. 140 | #define array_insert_sorted_with(self, compare, value) \ 141 | do { \ 142 | unsigned _index, _exists; \ 143 | array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 144 | if (!_exists) array_insert(self, _index, value); \ 145 | } while (0) 146 | 147 | /// Insert a given `value` into a sorted array, using integer comparisons of 148 | /// a given struct field (specified with a leading dot) to determine the order. 149 | /// 150 | /// See also `array_search_sorted_by`. 151 | #define array_insert_sorted_by(self, field, value) \ 152 | do { \ 153 | unsigned _index, _exists; \ 154 | array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 155 | if (!_exists) array_insert(self, _index, value); \ 156 | } while (0) 157 | 158 | // Private 159 | 160 | typedef Array(void) Array; 161 | 162 | /// This is not what you're looking for, see `array_delete`. 163 | static inline void _array__delete(Array *self) { 164 | if (self->contents) { 165 | ts_free(self->contents); 166 | self->contents = NULL; 167 | self->size = 0; 168 | self->capacity = 0; 169 | } 170 | } 171 | 172 | /// This is not what you're looking for, see `array_erase`. 173 | static inline void _array__erase(Array *self, size_t element_size, 174 | uint32_t index) { 175 | assert(index < self->size); 176 | char *contents = (char *)self->contents; 177 | memmove(contents + index * element_size, contents + (index + 1) * element_size, 178 | (self->size - index - 1) * element_size); 179 | self->size--; 180 | } 181 | 182 | /// This is not what you're looking for, see `array_reserve`. 183 | static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 184 | if (new_capacity > self->capacity) { 185 | if (self->contents) { 186 | self->contents = ts_realloc(self->contents, new_capacity * element_size); 187 | } else { 188 | self->contents = ts_malloc(new_capacity * element_size); 189 | } 190 | self->capacity = new_capacity; 191 | } 192 | } 193 | 194 | /// This is not what you're looking for, see `array_assign`. 195 | static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 196 | _array__reserve(self, element_size, other->size); 197 | self->size = other->size; 198 | memcpy(self->contents, other->contents, self->size * element_size); 199 | } 200 | 201 | /// This is not what you're looking for, see `array_swap`. 202 | static inline void _array__swap(Array *self, Array *other) { 203 | Array swap = *other; 204 | *other = *self; 205 | *self = swap; 206 | } 207 | 208 | /// This is not what you're looking for, see `array_push` or `array_grow_by`. 209 | static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 210 | uint32_t new_size = self->size + count; 211 | if (new_size > self->capacity) { 212 | uint32_t new_capacity = self->capacity * 2; 213 | if (new_capacity < 8) new_capacity = 8; 214 | if (new_capacity < new_size) new_capacity = new_size; 215 | _array__reserve(self, element_size, new_capacity); 216 | } 217 | } 218 | 219 | /// This is not what you're looking for, see `array_splice`. 220 | static inline void _array__splice(Array *self, size_t element_size, 221 | uint32_t index, uint32_t old_count, 222 | uint32_t new_count, const void *elements) { 223 | uint32_t new_size = self->size + new_count - old_count; 224 | uint32_t old_end = index + old_count; 225 | uint32_t new_end = index + new_count; 226 | assert(old_end <= self->size); 227 | 228 | _array__reserve(self, element_size, new_size); 229 | 230 | char *contents = (char *)self->contents; 231 | if (self->size > old_end) { 232 | memmove( 233 | contents + new_end * element_size, 234 | contents + old_end * element_size, 235 | (self->size - old_end) * element_size 236 | ); 237 | } 238 | if (new_count > 0) { 239 | if (elements) { 240 | memcpy( 241 | (contents + index * element_size), 242 | elements, 243 | new_count * element_size 244 | ); 245 | } else { 246 | memset( 247 | (contents + index * element_size), 248 | 0, 249 | new_count * element_size 250 | ); 251 | } 252 | } 253 | self->size += new_count - old_count; 254 | } 255 | 256 | /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 257 | /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 258 | #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 259 | do { \ 260 | *(_index) = start; \ 261 | *(_exists) = false; \ 262 | uint32_t size = (self)->size - *(_index); \ 263 | if (size == 0) break; \ 264 | int comparison; \ 265 | while (size > 1) { \ 266 | uint32_t half_size = size / 2; \ 267 | uint32_t mid_index = *(_index) + half_size; \ 268 | comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 269 | if (comparison <= 0) *(_index) = mid_index; \ 270 | size -= half_size; \ 271 | } \ 272 | comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 273 | if (comparison == 0) *(_exists) = true; \ 274 | else if (comparison < 0) *(_index) += 1; \ 275 | } while (0) 276 | 277 | /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 278 | /// parameter by reference in order to work with the generic sorting function above. 279 | #define _compare_int(a, b) ((int)*(a) - (int)(b)) 280 | 281 | #ifdef _MSC_VER 282 | #pragma warning(pop) 283 | #elif defined(__GNUC__) || defined(__clang__) 284 | #pragma GCC diagnostic pop 285 | #endif 286 | 287 | #ifdef __cplusplus 288 | } 289 | #endif 290 | 291 | #endif // TREE_SITTER_ARRAY_H_ 292 | -------------------------------------------------------------------------------- /src/tree_sitter/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_PARSER_H_ 2 | #define TREE_SITTER_PARSER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define ts_builtin_sym_error ((TSSymbol)-1) 13 | #define ts_builtin_sym_end 0 14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 | 16 | #ifndef TREE_SITTER_API_H_ 17 | typedef uint16_t TSStateId; 18 | typedef uint16_t TSSymbol; 19 | typedef uint16_t TSFieldId; 20 | typedef struct TSLanguage TSLanguage; 21 | typedef struct TSLanguageMetadata { 22 | uint8_t major_version; 23 | uint8_t minor_version; 24 | uint8_t patch_version; 25 | } TSLanguageMetadata; 26 | #endif 27 | 28 | typedef struct { 29 | TSFieldId field_id; 30 | uint8_t child_index; 31 | bool inherited; 32 | } TSFieldMapEntry; 33 | 34 | // Used to index the field and supertype maps. 35 | typedef struct { 36 | uint16_t index; 37 | uint16_t length; 38 | } TSMapSlice; 39 | 40 | typedef struct { 41 | bool visible; 42 | bool named; 43 | bool supertype; 44 | } TSSymbolMetadata; 45 | 46 | typedef struct TSLexer TSLexer; 47 | 48 | struct TSLexer { 49 | int32_t lookahead; 50 | TSSymbol result_symbol; 51 | void (*advance)(TSLexer *, bool); 52 | void (*mark_end)(TSLexer *); 53 | uint32_t (*get_column)(TSLexer *); 54 | bool (*is_at_included_range_start)(const TSLexer *); 55 | bool (*eof)(const TSLexer *); 56 | void (*log)(const TSLexer *, const char *, ...); 57 | }; 58 | 59 | typedef enum { 60 | TSParseActionTypeShift, 61 | TSParseActionTypeReduce, 62 | TSParseActionTypeAccept, 63 | TSParseActionTypeRecover, 64 | } TSParseActionType; 65 | 66 | typedef union { 67 | struct { 68 | uint8_t type; 69 | TSStateId state; 70 | bool extra; 71 | bool repetition; 72 | } shift; 73 | struct { 74 | uint8_t type; 75 | uint8_t child_count; 76 | TSSymbol symbol; 77 | int16_t dynamic_precedence; 78 | uint16_t production_id; 79 | } reduce; 80 | uint8_t type; 81 | } TSParseAction; 82 | 83 | typedef struct { 84 | uint16_t lex_state; 85 | uint16_t external_lex_state; 86 | } TSLexMode; 87 | 88 | typedef struct { 89 | uint16_t lex_state; 90 | uint16_t external_lex_state; 91 | uint16_t reserved_word_set_id; 92 | } TSLexerMode; 93 | 94 | typedef union { 95 | TSParseAction action; 96 | struct { 97 | uint8_t count; 98 | bool reusable; 99 | } entry; 100 | } TSParseActionEntry; 101 | 102 | typedef struct { 103 | int32_t start; 104 | int32_t end; 105 | } TSCharacterRange; 106 | 107 | struct TSLanguage { 108 | uint32_t abi_version; 109 | uint32_t symbol_count; 110 | uint32_t alias_count; 111 | uint32_t token_count; 112 | uint32_t external_token_count; 113 | uint32_t state_count; 114 | uint32_t large_state_count; 115 | uint32_t production_id_count; 116 | uint32_t field_count; 117 | uint16_t max_alias_sequence_length; 118 | const uint16_t *parse_table; 119 | const uint16_t *small_parse_table; 120 | const uint32_t *small_parse_table_map; 121 | const TSParseActionEntry *parse_actions; 122 | const char * const *symbol_names; 123 | const char * const *field_names; 124 | const TSMapSlice *field_map_slices; 125 | const TSFieldMapEntry *field_map_entries; 126 | const TSSymbolMetadata *symbol_metadata; 127 | const TSSymbol *public_symbol_map; 128 | const uint16_t *alias_map; 129 | const TSSymbol *alias_sequences; 130 | const TSLexerMode *lex_modes; 131 | bool (*lex_fn)(TSLexer *, TSStateId); 132 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 133 | TSSymbol keyword_capture_token; 134 | struct { 135 | const bool *states; 136 | const TSSymbol *symbol_map; 137 | void *(*create)(void); 138 | void (*destroy)(void *); 139 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 140 | unsigned (*serialize)(void *, char *); 141 | void (*deserialize)(void *, const char *, unsigned); 142 | } external_scanner; 143 | const TSStateId *primary_state_ids; 144 | const char *name; 145 | const TSSymbol *reserved_words; 146 | uint16_t max_reserved_word_set_size; 147 | uint32_t supertype_count; 148 | const TSSymbol *supertype_symbols; 149 | const TSMapSlice *supertype_map_slices; 150 | const TSSymbol *supertype_map_entries; 151 | TSLanguageMetadata metadata; 152 | }; 153 | 154 | static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 155 | uint32_t index = 0; 156 | uint32_t size = len - index; 157 | while (size > 1) { 158 | uint32_t half_size = size / 2; 159 | uint32_t mid_index = index + half_size; 160 | const TSCharacterRange *range = &ranges[mid_index]; 161 | if (lookahead >= range->start && lookahead <= range->end) { 162 | return true; 163 | } else if (lookahead > range->end) { 164 | index = mid_index; 165 | } 166 | size -= half_size; 167 | } 168 | const TSCharacterRange *range = &ranges[index]; 169 | return (lookahead >= range->start && lookahead <= range->end); 170 | } 171 | 172 | /* 173 | * Lexer Macros 174 | */ 175 | 176 | #ifdef _MSC_VER 177 | #define UNUSED __pragma(warning(suppress : 4101)) 178 | #else 179 | #define UNUSED __attribute__((unused)) 180 | #endif 181 | 182 | #define START_LEXER() \ 183 | bool result = false; \ 184 | bool skip = false; \ 185 | UNUSED \ 186 | bool eof = false; \ 187 | int32_t lookahead; \ 188 | goto start; \ 189 | next_state: \ 190 | lexer->advance(lexer, skip); \ 191 | start: \ 192 | skip = false; \ 193 | lookahead = lexer->lookahead; 194 | 195 | #define ADVANCE(state_value) \ 196 | { \ 197 | state = state_value; \ 198 | goto next_state; \ 199 | } 200 | 201 | #define ADVANCE_MAP(...) \ 202 | { \ 203 | static const uint16_t map[] = { __VA_ARGS__ }; \ 204 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 205 | if (map[i] == lookahead) { \ 206 | state = map[i + 1]; \ 207 | goto next_state; \ 208 | } \ 209 | } \ 210 | } 211 | 212 | #define SKIP(state_value) \ 213 | { \ 214 | skip = true; \ 215 | state = state_value; \ 216 | goto next_state; \ 217 | } 218 | 219 | #define ACCEPT_TOKEN(symbol_value) \ 220 | result = true; \ 221 | lexer->result_symbol = symbol_value; \ 222 | lexer->mark_end(lexer); 223 | 224 | #define END_STATE() return result; 225 | 226 | /* 227 | * Parse Table Macros 228 | */ 229 | 230 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 231 | 232 | #define STATE(id) id 233 | 234 | #define ACTIONS(id) id 235 | 236 | #define SHIFT(state_value) \ 237 | {{ \ 238 | .shift = { \ 239 | .type = TSParseActionTypeShift, \ 240 | .state = (state_value) \ 241 | } \ 242 | }} 243 | 244 | #define SHIFT_REPEAT(state_value) \ 245 | {{ \ 246 | .shift = { \ 247 | .type = TSParseActionTypeShift, \ 248 | .state = (state_value), \ 249 | .repetition = true \ 250 | } \ 251 | }} 252 | 253 | #define SHIFT_EXTRA() \ 254 | {{ \ 255 | .shift = { \ 256 | .type = TSParseActionTypeShift, \ 257 | .extra = true \ 258 | } \ 259 | }} 260 | 261 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 262 | {{ \ 263 | .reduce = { \ 264 | .type = TSParseActionTypeReduce, \ 265 | .symbol = symbol_name, \ 266 | .child_count = children, \ 267 | .dynamic_precedence = precedence, \ 268 | .production_id = prod_id \ 269 | }, \ 270 | }} 271 | 272 | #define RECOVER() \ 273 | {{ \ 274 | .type = TSParseActionTypeRecover \ 275 | }} 276 | 277 | #define ACCEPT_INPUT() \ 278 | {{ \ 279 | .type = TSParseActionTypeAccept \ 280 | }} 281 | 282 | #ifdef __cplusplus 283 | } 284 | #endif 285 | 286 | #endif // TREE_SITTER_PARSER_H_ 287 | -------------------------------------------------------------------------------- /test/corpus/chunk.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | chunk 3 | ================================================================================ 4 | 5 | -------------------------------------------------------------------------------- 6 | 7 | (chunk) 8 | 9 | ================================================================================ 10 | hash_bang_line 11 | ================================================================================ 12 | 13 | #!/usr/bin/env lua 14 | 15 | -------------------------------------------------------------------------------- 16 | 17 | (chunk 18 | (hash_bang_line)) 19 | 20 | ================================================================================ 21 | hash_bang_line: ignored first line 22 | ================================================================================ 23 | 24 | # ignored first line 25 | 26 | -------------------------------------------------------------------------------- 27 | 28 | (chunk 29 | (hash_bang_line)) 30 | 31 | ================================================================================ 32 | return_statement 33 | ================================================================================ 34 | 35 | return 42 36 | 37 | -------------------------------------------------------------------------------- 38 | 39 | (chunk 40 | (return_statement 41 | (expression_list 42 | (number)))) 43 | -------------------------------------------------------------------------------- /test/corpus/comments.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | comment 3 | ================================================================================ 4 | 5 | -- 6 | -- single-line comment, below an empty single-line comment 7 | 8 | --[[]] 9 | 10 | --[[ 11 | print("block comment") 12 | --]] 13 | 14 | --[[ 15 | print("block comment") 16 | ]] 17 | 18 | -- [[ 19 | print("not block comment") 20 | --]] 21 | 22 | --[=[[print("level 1 block comment")]]=] 23 | 24 | --[=[ 25 | [print("level 1 block comment")] 26 | ]=] 27 | 28 | --[=[ 29 | [print("level 1 block comment") 30 | ]=] 31 | 32 | --[=[ 33 | print("level 1 block comment")] 34 | ]=] 35 | 36 | --[=[ 37 | [[print("level 1 block comment") 38 | ]=] 39 | 40 | --[=[ 41 | print("level 1 block comment")]] 42 | ]=] 43 | 44 | --[==[ 45 | print("level 2 block comment") 46 | -- ]==] 47 | 48 | --[==[ 49 | print("level 2 block comment") 50 | ]==] 51 | 52 | -- [==[ 53 | print("not level 2 block comment") 54 | --]==] 55 | 56 | -------------------------------------------------------------------------------- 57 | 58 | (chunk 59 | (comment 60 | content: (comment_content)) 61 | (comment 62 | content: (comment_content)) 63 | (comment 64 | content: (comment_content)) 65 | (comment 66 | content: (comment_content)) 67 | (comment 68 | content: (comment_content)) 69 | (comment 70 | content: (comment_content)) 71 | (function_call 72 | name: (identifier) 73 | arguments: (arguments 74 | (string 75 | content: (string_content)))) 76 | (comment 77 | content: (comment_content)) 78 | (comment 79 | content: (comment_content)) 80 | (comment 81 | content: (comment_content)) 82 | (comment 83 | content: (comment_content)) 84 | (comment 85 | content: (comment_content)) 86 | (comment 87 | content: (comment_content)) 88 | (comment 89 | content: (comment_content)) 90 | (comment 91 | content: (comment_content)) 92 | (comment 93 | content: (comment_content)) 94 | (comment 95 | content: (comment_content)) 96 | (function_call 97 | name: (identifier) 98 | arguments: (arguments 99 | (string 100 | content: (string_content)))) 101 | (comment 102 | content: (comment_content))) 103 | -------------------------------------------------------------------------------- /test/corpus/expressions.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | nil 3 | ================================================================================ 4 | 5 | exp(nil) 6 | 7 | -------------------------------------------------------------------------------- 8 | 9 | (chunk 10 | (function_call 11 | name: (identifier) 12 | arguments: (arguments 13 | (nil)))) 14 | 15 | ================================================================================ 16 | false 17 | ================================================================================ 18 | 19 | exp(false) 20 | 21 | -------------------------------------------------------------------------------- 22 | 23 | (chunk 24 | (function_call 25 | name: (identifier) 26 | arguments: (arguments 27 | (false)))) 28 | 29 | ================================================================================ 30 | true 31 | ================================================================================ 32 | 33 | exp(true) 34 | 35 | -------------------------------------------------------------------------------- 36 | 37 | (chunk 38 | (function_call 39 | name: (identifier) 40 | arguments: (arguments 41 | (true)))) 42 | 43 | ================================================================================ 44 | number 45 | ================================================================================ 46 | 47 | exp( 48 | 3, 49 | 345, 50 | 0xff, 51 | 0xBEBADA, 52 | .0, 53 | 3., 54 | 3.0, 55 | 3.1416, 56 | 314.16e-2, 57 | 0.31416E1, 58 | 34e1, 59 | 0x0.1E, 60 | 0xA23p-4, 61 | 0x.0p-3, 62 | 0x.FfffFFFF, 63 | 0X1.921FB54442D18P+1, 64 | 42LL, 65 | 0x2aULL, 66 | 12.5i, 67 | 0x.01p-1I, 68 | 0b0, 69 | 0B10, 70 | 0b0LL, 71 | 0B10ull, 72 | 0b0I, 73 | 0B0i 74 | ) 75 | 76 | -------------------------------------------------------------------------------- 77 | 78 | (chunk 79 | (function_call 80 | name: (identifier) 81 | arguments: (arguments 82 | (number) 83 | (number) 84 | (number) 85 | (number) 86 | (number) 87 | (number) 88 | (number) 89 | (number) 90 | (number) 91 | (number) 92 | (number) 93 | (number) 94 | (number) 95 | (number) 96 | (number) 97 | (number) 98 | (number) 99 | (number) 100 | (number) 101 | (number) 102 | (number) 103 | (number) 104 | (number) 105 | (number) 106 | (number) 107 | (number)))) 108 | 109 | ================================================================================ 110 | string 111 | ================================================================================ 112 | 113 | exp( 114 | "string", 115 | 'string', 116 | "c", 117 | 'c', 118 | "0", 119 | [[ string ]], 120 | [[ 121 | string 122 | string 123 | ]], 124 | [=[ 125 | string 126 | string 127 | ]=], 128 | [=[[string]]=], 129 | [=[ 130 | [string] 131 | ]=], 132 | [=[ 133 | [string 134 | ]=], 135 | [=[ 136 | string] 137 | ]=], 138 | [=[ 139 | [[string 140 | ]=], 141 | [=[ 142 | string]] 143 | ]=] 144 | ) 145 | 146 | 147 | -------------------------------------------------------------------------------- 148 | 149 | (chunk 150 | (function_call 151 | (identifier) 152 | (arguments 153 | (string 154 | (string_content)) 155 | (string 156 | (string_content)) 157 | (string 158 | (string_content)) 159 | (string 160 | (string_content)) 161 | (string 162 | (string_content)) 163 | (string 164 | (string_content)) 165 | (string 166 | (string_content)) 167 | (string 168 | (string_content)) 169 | (string 170 | (string_content)) 171 | (string 172 | (string_content)) 173 | (string 174 | (string_content)) 175 | (string 176 | (string_content)) 177 | (string 178 | (string_content)) 179 | (string 180 | (string_content))))) 181 | 182 | ================================================================================ 183 | string :: escape_sequence 184 | ================================================================================ 185 | 186 | exp( 187 | "a\ 188 | b", 189 | 'a\z', 190 | 'a\z 191 | ', 192 | 'a\z 193 | b', 194 | "'a\z\ 195 | b'" 196 | ) 197 | 198 | 199 | -------------------------------------------------------------------------------- 200 | 201 | (chunk 202 | (function_call 203 | name: (identifier) 204 | arguments: (arguments 205 | (string 206 | content: (string_content 207 | (escape_sequence))) 208 | (string 209 | content: (string_content 210 | (escape_sequence))) 211 | (string 212 | content: (string_content 213 | (escape_sequence))) 214 | (string 215 | content: (string_content 216 | (escape_sequence))) 217 | (string 218 | content: (string_content 219 | (escape_sequence) 220 | (escape_sequence)))))) 221 | 222 | ================================================================================ 223 | vararg_expression 224 | ================================================================================ 225 | 226 | exp(...) 227 | 228 | -------------------------------------------------------------------------------- 229 | 230 | (chunk 231 | (function_call 232 | name: (identifier) 233 | arguments: (arguments 234 | (vararg_expression)))) 235 | 236 | ================================================================================ 237 | function_definition 238 | ================================================================================ 239 | 240 | f1 = function() end 241 | 242 | f2 = function() return end 243 | 244 | f3 = function(...) 245 | return ... 246 | end 247 | 248 | f4 = function(a1, ...) 249 | print(...) 250 | return a1 251 | end 252 | 253 | -------------------------------------------------------------------------------- 254 | 255 | (chunk 256 | (assignment_statement 257 | (variable_list 258 | name: (identifier)) 259 | (expression_list 260 | value: (function_definition 261 | parameters: (parameters)))) 262 | (assignment_statement 263 | (variable_list 264 | name: (identifier)) 265 | (expression_list 266 | value: (function_definition 267 | parameters: (parameters) 268 | body: (block 269 | (return_statement))))) 270 | (assignment_statement 271 | (variable_list 272 | name: (identifier)) 273 | (expression_list 274 | value: (function_definition 275 | parameters: (parameters 276 | (vararg_expression)) 277 | body: (block 278 | (return_statement 279 | (expression_list 280 | (vararg_expression))))))) 281 | (assignment_statement 282 | (variable_list 283 | name: (identifier)) 284 | (expression_list 285 | value: (function_definition 286 | parameters: (parameters 287 | name: (identifier) 288 | (vararg_expression)) 289 | body: (block 290 | (function_call 291 | name: (identifier) 292 | arguments: (arguments 293 | (vararg_expression))) 294 | (return_statement 295 | (expression_list 296 | (identifier)))))))) 297 | 298 | ================================================================================ 299 | variable ::: identifier 300 | ================================================================================ 301 | 302 | v1 = n1 303 | 304 | v2, v3 = n2, n3 305 | 306 | পাই = π 307 | 308 | 🙂 = 🙃 309 | 310 | -------------------------------------------------------------------------------- 311 | 312 | (chunk 313 | (assignment_statement 314 | (variable_list 315 | name: (identifier)) 316 | (expression_list 317 | value: (identifier))) 318 | (assignment_statement 319 | (variable_list 320 | name: (identifier) 321 | name: (identifier)) 322 | (expression_list 323 | value: (identifier) 324 | value: (identifier))) 325 | (assignment_statement 326 | (variable_list 327 | name: (identifier)) 328 | (expression_list 329 | value: (identifier))) 330 | (assignment_statement 331 | (variable_list 332 | name: (identifier)) 333 | (expression_list 334 | value: (identifier)))) 335 | 336 | ================================================================================ 337 | variable ::: bracket_index_expression 338 | ================================================================================ 339 | 340 | v1 = tbl[k1] 341 | 342 | v2, v3[v] = tbl[k1]["k2"] 343 | 344 | v4 = tbk[getK1()][getK2()] 345 | 346 | -------------------------------------------------------------------------------- 347 | 348 | (chunk 349 | (assignment_statement 350 | (variable_list 351 | name: (identifier)) 352 | (expression_list 353 | value: (bracket_index_expression 354 | table: (identifier) 355 | field: (identifier)))) 356 | (assignment_statement 357 | (variable_list 358 | name: (identifier) 359 | name: (bracket_index_expression 360 | table: (identifier) 361 | field: (identifier))) 362 | (expression_list 363 | value: (bracket_index_expression 364 | table: (bracket_index_expression 365 | table: (identifier) 366 | field: (identifier)) 367 | field: (string 368 | content: (string_content))))) 369 | (assignment_statement 370 | (variable_list 371 | name: (identifier)) 372 | (expression_list 373 | value: (bracket_index_expression 374 | table: (bracket_index_expression 375 | table: (identifier) 376 | field: (function_call 377 | name: (identifier) 378 | arguments: (arguments))) 379 | field: (function_call 380 | name: (identifier) 381 | arguments: (arguments)))))) 382 | 383 | ================================================================================ 384 | variable ::: dot_index_expression 385 | ================================================================================ 386 | 387 | v1 = tbl.k1 388 | 389 | v2 = tbl.k1.k2 390 | 391 | -------------------------------------------------------------------------------- 392 | 393 | (chunk 394 | (assignment_statement 395 | (variable_list 396 | name: (identifier)) 397 | (expression_list 398 | value: (dot_index_expression 399 | table: (identifier) 400 | field: (identifier)))) 401 | (assignment_statement 402 | (variable_list 403 | name: (identifier)) 404 | (expression_list 405 | value: (dot_index_expression 406 | table: (dot_index_expression 407 | table: (identifier) 408 | field: (identifier)) 409 | field: (identifier))))) 410 | 411 | ================================================================================ 412 | function_call ::: bracket_index_expression | dot_index_expression 413 | ================================================================================ 414 | 415 | v1 = tbl[k1].k2(a1, "a2", a3()) 416 | 417 | v2 = tbl[k1] { f1 = true } 418 | 419 | v3 = tbl[k1] "a1" 420 | 421 | -------------------------------------------------------------------------------- 422 | 423 | (chunk 424 | (assignment_statement 425 | (variable_list 426 | name: (identifier)) 427 | (expression_list 428 | value: (function_call 429 | name: (dot_index_expression 430 | table: (bracket_index_expression 431 | table: (identifier) 432 | field: (identifier)) 433 | field: (identifier)) 434 | arguments: (arguments 435 | (identifier) 436 | (string 437 | content: (string_content)) 438 | (function_call 439 | name: (identifier) 440 | arguments: (arguments)))))) 441 | (assignment_statement 442 | (variable_list 443 | name: (identifier)) 444 | (expression_list 445 | value: (function_call 446 | name: (bracket_index_expression 447 | table: (identifier) 448 | field: (identifier)) 449 | arguments: (arguments 450 | (table_constructor 451 | (field 452 | name: (identifier) 453 | value: (true))))))) 454 | (assignment_statement 455 | (variable_list 456 | name: (identifier)) 457 | (expression_list 458 | value: (function_call 459 | name: (bracket_index_expression 460 | table: (identifier) 461 | field: (identifier)) 462 | arguments: (arguments 463 | (string 464 | content: (string_content))))))) 465 | 466 | ================================================================================ 467 | function_call ::: method_index_expression 468 | ================================================================================ 469 | 470 | tbl.k1:m1(a1, "a2") 471 | 472 | tbl[k1]:m1 { f1, "f2" } 473 | 474 | tbl:m1 "a1" 475 | 476 | -------------------------------------------------------------------------------- 477 | 478 | (chunk 479 | (function_call 480 | name: (method_index_expression 481 | table: (dot_index_expression 482 | table: (identifier) 483 | field: (identifier)) 484 | method: (identifier)) 485 | arguments: (arguments 486 | (identifier) 487 | (string 488 | content: (string_content)))) 489 | (function_call 490 | name: (method_index_expression 491 | table: (bracket_index_expression 492 | table: (identifier) 493 | field: (identifier)) 494 | method: (identifier)) 495 | arguments: (arguments 496 | (table_constructor 497 | (field 498 | value: (identifier)) 499 | (field 500 | value: (string 501 | content: (string_content)))))) 502 | (function_call 503 | name: (method_index_expression 504 | table: (identifier) 505 | method: (identifier)) 506 | arguments: (arguments 507 | (string 508 | content: (string_content))))) 509 | 510 | ================================================================================ 511 | parenthesized_expression 512 | ================================================================================ 513 | 514 | v = ( true ) 515 | 516 | v = ( ( false ) ) 517 | 518 | -------------------------------------------------------------------------------- 519 | 520 | (chunk 521 | (assignment_statement 522 | (variable_list 523 | name: (identifier)) 524 | (expression_list 525 | value: (parenthesized_expression 526 | (true)))) 527 | (assignment_statement 528 | (variable_list 529 | name: (identifier)) 530 | (expression_list 531 | value: (parenthesized_expression 532 | (parenthesized_expression 533 | (false)))))) 534 | 535 | ================================================================================ 536 | table_constructor 537 | ================================================================================ 538 | 539 | tbl1 = { 540 | ["k1"] = { 541 | ['k2'] = true, 542 | k3 = false 543 | } 544 | } 545 | 546 | local tbl2 = { 547 | k1 = { 548 | { 'v1', "v2" } 549 | } 550 | } 551 | 552 | local tbl3 = { "v1", k1 = "v2" } 553 | 554 | -------------------------------------------------------------------------------- 555 | 556 | (chunk 557 | (assignment_statement 558 | (variable_list 559 | name: (identifier)) 560 | (expression_list 561 | value: (table_constructor 562 | (field 563 | name: (string 564 | content: (string_content)) 565 | value: (table_constructor 566 | (field 567 | name: (string 568 | content: (string_content)) 569 | value: (true)) 570 | (field 571 | name: (identifier) 572 | value: (false))))))) 573 | local_declaration: (variable_declaration 574 | (assignment_statement 575 | (variable_list 576 | name: (identifier)) 577 | (expression_list 578 | value: (table_constructor 579 | (field 580 | name: (identifier) 581 | value: (table_constructor 582 | (field 583 | value: (table_constructor 584 | (field 585 | value: (string 586 | content: (string_content))) 587 | (field 588 | value: (string 589 | content: (string_content))))))))))) 590 | local_declaration: (variable_declaration 591 | (assignment_statement 592 | (variable_list 593 | name: (identifier)) 594 | (expression_list 595 | value: (table_constructor 596 | (field 597 | value: (string 598 | content: (string_content))) 599 | (field 600 | name: (identifier) 601 | value: (string 602 | content: (string_content)))))))) 603 | 604 | ================================================================================ 605 | binary_expression 606 | ================================================================================ 607 | 608 | a = i + j * 3 - k % 5 609 | 610 | b = i + j % 3 ^ 2 611 | 612 | c = i * 2 ^ j 613 | 614 | -------------------------------------------------------------------------------- 615 | 616 | (chunk 617 | (assignment_statement 618 | (variable_list 619 | name: (identifier)) 620 | (expression_list 621 | value: (binary_expression 622 | left: (binary_expression 623 | left: (identifier) 624 | right: (binary_expression 625 | left: (identifier) 626 | right: (number))) 627 | right: (binary_expression 628 | left: (identifier) 629 | right: (number))))) 630 | (assignment_statement 631 | (variable_list 632 | name: (identifier)) 633 | (expression_list 634 | value: (binary_expression 635 | left: (identifier) 636 | right: (binary_expression 637 | left: (identifier) 638 | right: (binary_expression 639 | left: (number) 640 | right: (number)))))) 641 | (assignment_statement 642 | (variable_list 643 | name: (identifier)) 644 | (expression_list 645 | value: (binary_expression 646 | left: (identifier) 647 | right: (binary_expression 648 | left: (number) 649 | right: (identifier)))))) 650 | 651 | ================================================================================ 652 | unary_expression 653 | ================================================================================ 654 | 655 | v1 = #l 656 | 657 | v2 = -n 658 | 659 | v3 = not c1 and r1 or r2 660 | 661 | -------------------------------------------------------------------------------- 662 | 663 | (chunk 664 | (assignment_statement 665 | (variable_list 666 | name: (identifier)) 667 | (expression_list 668 | value: (unary_expression 669 | operand: (identifier)))) 670 | (assignment_statement 671 | (variable_list 672 | name: (identifier)) 673 | (expression_list 674 | value: (unary_expression 675 | operand: (identifier)))) 676 | (assignment_statement 677 | (variable_list 678 | name: (identifier)) 679 | (expression_list 680 | value: (binary_expression 681 | left: (binary_expression 682 | left: (unary_expression 683 | operand: (identifier)) 684 | right: (identifier)) 685 | right: (identifier))))) 686 | -------------------------------------------------------------------------------- /test/corpus/statements.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | empty_statement 3 | ================================================================================ 4 | 5 | ; 6 | ;; 7 | 8 | -------------------------------------------------------------------------------- 9 | 10 | (chunk 11 | (empty_statement) 12 | (empty_statement) 13 | (empty_statement)) 14 | 15 | ================================================================================ 16 | assignment_statement 17 | ================================================================================ 18 | 19 | i = 1 20 | j, tbl[k()] = 2, i + 1 21 | x, y = y, x 22 | 23 | -------------------------------------------------------------------------------- 24 | 25 | (chunk 26 | (assignment_statement 27 | (variable_list 28 | name: (identifier)) 29 | (expression_list 30 | value: (number))) 31 | (assignment_statement 32 | (variable_list 33 | name: (identifier) 34 | name: (bracket_index_expression 35 | table: (identifier) 36 | field: (function_call 37 | name: (identifier) 38 | arguments: (arguments)))) 39 | (expression_list 40 | value: (number) 41 | value: (binary_expression 42 | left: (identifier) 43 | right: (number)))) 44 | (assignment_statement 45 | (variable_list 46 | name: (identifier) 47 | name: (identifier)) 48 | (expression_list 49 | value: (identifier) 50 | value: (identifier)))) 51 | 52 | ================================================================================ 53 | function_call 54 | ================================================================================ 55 | 56 | f1() 57 | 58 | tbl.f2() 59 | 60 | tbl["f2"]() 61 | 62 | tbl.k1:f3() 63 | 64 | f4(a1)("a2") { a3 = "a3" } 65 | 66 | -------------------------------------------------------------------------------- 67 | 68 | (chunk 69 | (function_call 70 | name: (identifier) 71 | arguments: (arguments)) 72 | (function_call 73 | name: (dot_index_expression 74 | table: (identifier) 75 | field: (identifier)) 76 | arguments: (arguments)) 77 | (function_call 78 | name: (bracket_index_expression 79 | table: (identifier) 80 | field: (string 81 | content: (string_content))) 82 | arguments: (arguments)) 83 | (function_call 84 | name: (method_index_expression 85 | table: (dot_index_expression 86 | table: (identifier) 87 | field: (identifier)) 88 | method: (identifier)) 89 | arguments: (arguments)) 90 | (function_call 91 | name: (function_call 92 | name: (function_call 93 | name: (identifier) 94 | arguments: (arguments 95 | (identifier))) 96 | arguments: (arguments 97 | (string 98 | content: (string_content)))) 99 | arguments: (arguments 100 | (table_constructor 101 | (field 102 | name: (identifier) 103 | value: (string 104 | content: (string_content))))))) 105 | 106 | ================================================================================ 107 | label_statement 108 | ================================================================================ 109 | 110 | :: label_name :: 111 | 112 | -------------------------------------------------------------------------------- 113 | 114 | (chunk 115 | (label_statement 116 | (identifier))) 117 | 118 | ================================================================================ 119 | break_statement 120 | ================================================================================ 121 | 122 | for k, v in pairs(kv) do 123 | if not v then 124 | break 125 | end 126 | end 127 | 128 | -------------------------------------------------------------------------------- 129 | 130 | (chunk 131 | (for_statement 132 | clause: (for_generic_clause 133 | (variable_list 134 | name: (identifier) 135 | name: (identifier)) 136 | (expression_list 137 | (function_call 138 | name: (identifier) 139 | arguments: (arguments 140 | (identifier))))) 141 | body: (block 142 | (if_statement 143 | condition: (unary_expression 144 | operand: (identifier)) 145 | consequence: (block 146 | (break_statement)))))) 147 | 148 | ================================================================================ 149 | goto_statement 150 | ================================================================================ 151 | 152 | goto label_name 153 | 154 | -------------------------------------------------------------------------------- 155 | 156 | (chunk 157 | (goto_statement 158 | (identifier))) 159 | 160 | ================================================================================ 161 | do_statement 162 | ================================================================================ 163 | 164 | do 165 | f1() 166 | return f2() 167 | end 168 | 169 | do end 170 | 171 | -------------------------------------------------------------------------------- 172 | 173 | (chunk 174 | (do_statement 175 | body: (block 176 | (function_call 177 | name: (identifier) 178 | arguments: (arguments)) 179 | (return_statement 180 | (expression_list 181 | (function_call 182 | name: (identifier) 183 | arguments: (arguments)))))) 184 | (do_statement)) 185 | 186 | ================================================================================ 187 | while_statement 188 | ================================================================================ 189 | 190 | while i < 9 do 191 | i = i + 1 192 | end 193 | 194 | while false do end 195 | 196 | -------------------------------------------------------------------------------- 197 | 198 | (chunk 199 | (while_statement 200 | condition: (binary_expression 201 | left: (identifier) 202 | right: (number)) 203 | body: (block 204 | (assignment_statement 205 | (variable_list 206 | name: (identifier)) 207 | (expression_list 208 | value: (binary_expression 209 | left: (identifier) 210 | right: (number)))))) 211 | (while_statement 212 | condition: (false))) 213 | 214 | ================================================================================ 215 | repeat_statement 216 | ================================================================================ 217 | 218 | repeat 219 | f1() 220 | i = i - 1 221 | until i == 0 222 | 223 | repeat until false 224 | 225 | -------------------------------------------------------------------------------- 226 | 227 | (chunk 228 | (repeat_statement 229 | body: (block 230 | (function_call 231 | name: (identifier) 232 | arguments: (arguments)) 233 | (assignment_statement 234 | (variable_list 235 | name: (identifier)) 236 | (expression_list 237 | value: (binary_expression 238 | left: (identifier) 239 | right: (number))))) 240 | condition: (binary_expression 241 | left: (identifier) 242 | right: (number))) 243 | (repeat_statement 244 | condition: (false))) 245 | 246 | ================================================================================ 247 | if_statement 248 | ================================================================================ 249 | 250 | if num % 2 == 0 then 251 | print("even") 252 | elseif num % 2 ~= 0 then 253 | print("odd") 254 | else 255 | error("!") 256 | end 257 | 258 | if c1 then end 259 | 260 | if c1 then else end 261 | 262 | if c1 then elseif c2 then else end 263 | 264 | -------------------------------------------------------------------------------- 265 | 266 | (chunk 267 | (if_statement 268 | condition: (binary_expression 269 | left: (binary_expression 270 | left: (identifier) 271 | right: (number)) 272 | right: (number)) 273 | consequence: (block 274 | (function_call 275 | name: (identifier) 276 | arguments: (arguments 277 | (string 278 | content: (string_content))))) 279 | alternative: (elseif_statement 280 | condition: (binary_expression 281 | left: (binary_expression 282 | left: (identifier) 283 | right: (number)) 284 | right: (number)) 285 | consequence: (block 286 | (function_call 287 | name: (identifier) 288 | arguments: (arguments 289 | (string 290 | content: (string_content)))))) 291 | alternative: (else_statement 292 | body: (block 293 | (function_call 294 | name: (identifier) 295 | arguments: (arguments 296 | (string 297 | content: (string_content))))))) 298 | (if_statement 299 | condition: (identifier)) 300 | (if_statement 301 | condition: (identifier) 302 | alternative: (else_statement)) 303 | (if_statement 304 | condition: (identifier) 305 | alternative: (elseif_statement 306 | condition: (identifier)) 307 | alternative: (else_statement))) 308 | 309 | ================================================================================ 310 | for_statement ::: for_generic_clause 311 | ================================================================================ 312 | 313 | for k, v in pairs(kv) do 314 | print(k, v) 315 | end 316 | 317 | for i in ipairs(iv) do end 318 | 319 | -------------------------------------------------------------------------------- 320 | 321 | (chunk 322 | (for_statement 323 | clause: (for_generic_clause 324 | (variable_list 325 | name: (identifier) 326 | name: (identifier)) 327 | (expression_list 328 | (function_call 329 | name: (identifier) 330 | arguments: (arguments 331 | (identifier))))) 332 | body: (block 333 | (function_call 334 | name: (identifier) 335 | arguments: (arguments 336 | (identifier) 337 | (identifier))))) 338 | (for_statement 339 | clause: (for_generic_clause 340 | (variable_list 341 | name: (identifier)) 342 | (expression_list 343 | (function_call 344 | name: (identifier) 345 | arguments: (arguments 346 | (identifier))))))) 347 | 348 | ================================================================================ 349 | for_statement ::: for_numeric_clause 350 | ================================================================================ 351 | 352 | for n = 1, 10 do 353 | print(n) 354 | end 355 | 356 | for n = 1, 10, 2 do end 357 | 358 | -------------------------------------------------------------------------------- 359 | 360 | (chunk 361 | (for_statement 362 | clause: (for_numeric_clause 363 | name: (identifier) 364 | start: (number) 365 | end: (number)) 366 | body: (block 367 | (function_call 368 | name: (identifier) 369 | arguments: (arguments 370 | (identifier))))) 371 | (for_statement 372 | clause: (for_numeric_clause 373 | name: (identifier) 374 | start: (number) 375 | end: (number) 376 | step: (number)))) 377 | 378 | ================================================================================ 379 | function_declaration 380 | ================================================================================ 381 | 382 | function tbl.f1() end 383 | 384 | function tbl:f2() end 385 | 386 | function tbl.k1:f3() end 387 | 388 | function f4() 389 | print('f4') 390 | end 391 | 392 | local function f5() end 393 | 394 | -------------------------------------------------------------------------------- 395 | 396 | (chunk 397 | (function_declaration 398 | name: (dot_index_expression 399 | table: (identifier) 400 | field: (identifier)) 401 | parameters: (parameters)) 402 | (function_declaration 403 | name: (method_index_expression 404 | table: (identifier) 405 | method: (identifier)) 406 | parameters: (parameters)) 407 | (function_declaration 408 | name: (method_index_expression 409 | table: (dot_index_expression 410 | table: (identifier) 411 | field: (identifier)) 412 | method: (identifier)) 413 | parameters: (parameters)) 414 | (function_declaration 415 | name: (identifier) 416 | parameters: (parameters) 417 | body: (block 418 | (function_call 419 | name: (identifier) 420 | arguments: (arguments 421 | (string 422 | content: (string_content)))))) 423 | local_declaration: (function_declaration 424 | name: (identifier) 425 | parameters: (parameters))) 426 | 427 | ================================================================================ 428 | variable_declaration 429 | ================================================================================ 430 | 431 | local v1 = 1 432 | local v2, v3 = 2, 3 433 | 434 | local v4, v4 = f1(), tbl:f2() 435 | 436 | -------------------------------------------------------------------------------- 437 | 438 | (chunk 439 | local_declaration: (variable_declaration 440 | (assignment_statement 441 | (variable_list 442 | name: (identifier)) 443 | (expression_list 444 | value: (number)))) 445 | local_declaration: (variable_declaration 446 | (assignment_statement 447 | (variable_list 448 | name: (identifier) 449 | name: (identifier)) 450 | (expression_list 451 | value: (number) 452 | value: (number)))) 453 | local_declaration: (variable_declaration 454 | (assignment_statement 455 | (variable_list 456 | name: (identifier) 457 | name: (identifier)) 458 | (expression_list 459 | value: (function_call 460 | name: (identifier) 461 | arguments: (arguments)) 462 | value: (function_call 463 | name: (method_index_expression 464 | table: (identifier) 465 | method: (identifier)) 466 | arguments: (arguments)))))) 467 | 468 | ================================================================================ 469 | variable_declaration ::: attribute [Lua 5.4] 470 | ================================================================================ 471 | 472 | local c , x = 42 473 | local f = io.open('/file.lua') 474 | 475 | -------------------------------------------------------------------------------- 476 | 477 | (chunk 478 | local_declaration: (variable_declaration 479 | (assignment_statement 480 | (variable_list 481 | name: (identifier) 482 | attribute: (attribute 483 | (identifier)) 484 | name: (identifier) 485 | attribute: (attribute 486 | (identifier))) 487 | (expression_list 488 | value: (number)))) 489 | local_declaration: (variable_declaration 490 | (assignment_statement 491 | (variable_list 492 | name: (identifier) 493 | attribute: (attribute 494 | (identifier))) 495 | (expression_list 496 | value: (function_call 497 | name: (dot_index_expression 498 | table: (identifier) 499 | field: (identifier)) 500 | arguments: (arguments 501 | (string 502 | content: (string_content)))))))) 503 | -------------------------------------------------------------------------------- /test/highlight/string.lua: -------------------------------------------------------------------------------- 1 | -- stylua: ignore start 2 | 3 | local _ 4 | 5 | _ = "x" 6 | -- ^ string 7 | 8 | _ = 'x' 9 | -- ^ string 10 | 11 | _ = "x\ty" 12 | -- ^ string 13 | -- ^ string.escape 14 | -- ^ string.escape 15 | -- ^ string 16 | 17 | _ = "x\"y" 18 | -- ^ string 19 | -- ^ string.escape 20 | -- ^ string.escape 21 | -- ^ string 22 | 23 | _ = 'x\'y' 24 | -- ^ string 25 | -- ^ string.escape 26 | -- ^ string.escape 27 | -- ^ string 28 | 29 | _ = "x\z 30 | y" 31 | -- ^ string 32 | --<- string.escape 33 | 34 | _ = "x\x5Ay" 35 | -- ^ string.escape 36 | -- ^ string.escape 37 | 38 | _ = "x\0900y" 39 | -- ^ string.escape 40 | -- ^ string 41 | 42 | _ = "x\09y" 43 | -- ^ string.escape 44 | -- ^ string 45 | 46 | _ = "x\0y" 47 | -- ^ string.escape 48 | -- ^ string 49 | 50 | _ = "x\u{1f602}y" 51 | -- ^ string.escape 52 | -- ^ string.escape 53 | -- ^ string 54 | 55 | _ = [[x]] 56 | -- ^ string 57 | 58 | _ = [=[x]=] 59 | -- ^ string 60 | -------------------------------------------------------------------------------- /test/tags/functions.lua: -------------------------------------------------------------------------------- 1 | local function func_one() end 2 | -- ^ definition.function 3 | 4 | func_one() 5 | -- ^ reference.call 6 | 7 | local func_two = function() end 8 | -- ^ definition.function 9 | 10 | func_two() 11 | -- ^ reference.call 12 | 13 | local tbl = { 14 | func_one = function() end, 15 | -- ^ definition.function 16 | } 17 | 18 | tbl.func_one() 19 | -- ^ reference.call 20 | 21 | function tbl.func_two() end 22 | -- ^ definition.function 23 | 24 | tbl.func_two() 25 | -- ^ reference.call 26 | 27 | function tbl:func_three() end 28 | -- ^ definition.method 29 | 30 | tbl:func_three() 31 | -- ^ reference.call 32 | 33 | tbl.func_four = function() end 34 | -- ^ definition.function 35 | 36 | tbl.func_four() 37 | -- ^ reference.call 38 | -------------------------------------------------------------------------------- /tree-sitter.json: -------------------------------------------------------------------------------- 1 | { 2 | "grammars": [ 3 | { 4 | "name": "lua", 5 | "path": ".", 6 | "scope": "source.lua", 7 | "file-types": [ 8 | "lua" 9 | ], 10 | "injection-regex": "^lua$", 11 | "highlights": "queries/highlights.scm", 12 | "injections": "queries/injections.scm", 13 | "locals": "queries/locals.scm", 14 | "tags": "queries/tags.scm" 15 | } 16 | ], 17 | "metadata": { 18 | "version": "0.4.0", 19 | "license": "MIT", 20 | "authors": [ 21 | { 22 | "name": "Munif Tanjim", 23 | "email": "hello@muniftanjim.dev", 24 | "url": "https://muniftanjim.dev" 25 | } 26 | ], 27 | "links": { 28 | "repository": "https://github.com/tree-sitter-grammars/tree-sitter-lua" 29 | } 30 | } 31 | } 32 | --------------------------------------------------------------------------------