├── .editorconfig ├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── CMakeLists.txt ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Makefile ├── Package.resolved ├── Package.swift ├── README.md ├── binding.gyp ├── bindings ├── c │ ├── tree-sitter-hyprlang.pc.in │ └── tree_sitter │ │ └── tree-sitter-hyprlang.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_hyprlang │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ ├── binding.c │ │ └── py.typed ├── rust │ ├── build.rs │ └── lib.rs └── swift │ ├── TreeSitterHyprlang │ └── hyprlang.h │ └── TreeSitterHyprlangTests │ └── TreeSitterHyprlangTests.swift ├── go.mod ├── go.sum ├── grammar.js ├── package-lock.json ├── package.json ├── pyproject.toml ├── queries └── hyprlang │ ├── folds.scm │ ├── highlights.scm │ ├── indents.scm │ └── injections.scm ├── setup.py ├── src ├── grammar.json ├── node-types.json ├── parser.c └── tree_sitter │ ├── alloc.h │ ├── array.h │ └── parser.h ├── test ├── corpus │ └── config.txt └── highlight │ └── config.conf └── 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: 6 | - master 7 | paths: 8 | - grammar.js 9 | - src/** 10 | - test/** 11 | - bindings/** 12 | - binding.gyp 13 | pull_request: 14 | paths: 15 | - grammar.js 16 | - src/** 17 | - test/** 18 | - bindings/** 19 | - binding.gyp 20 | 21 | concurrency: 22 | group: ${{github.workflow}}-${{github.ref}} 23 | cancel-in-progress: true 24 | 25 | jobs: 26 | test: 27 | name: Test parser 28 | runs-on: ${{matrix.os}} 29 | strategy: 30 | fail-fast: false 31 | matrix: 32 | os: [ubuntu-latest, windows-latest, macos-14] 33 | steps: 34 | - name: Checkout repository 35 | uses: actions/checkout@v4 36 | - name: Set up tree-sitter 37 | uses: tree-sitter/setup-action/cli@v1 38 | - name: Run parser tests 39 | uses: tree-sitter/parser-test-action@v2 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create release 2 | 3 | on: 4 | push: 5 | tags: ["*"] 6 | 7 | concurrency: 8 | group: ${{github.workflow}}-${{github.ref}} 9 | cancel-in-progress: true 10 | 11 | permissions: 12 | contents: write 13 | id-token: write 14 | attestations: write 15 | 16 | jobs: 17 | release: 18 | uses: tree-sitter/workflows/.github/workflows/release.yml@main 19 | with: 20 | attestations: true 21 | -------------------------------------------------------------------------------- /.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-hyprlang 4 | VERSION "3.1.0" 5 | DESCRIPTION "hyprlang grammar for the tree-sitter parsing library" 6 | HOMEPAGE_URL "https://github.com/tree-sitter-grammars/tree-sitter-hyprlang" 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-hyprlang src/parser.c) 28 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c) 29 | target_sources(tree-sitter-hyprlang PRIVATE src/scanner.c) 30 | endif() 31 | target_include_directories(tree-sitter-hyprlang 32 | PRIVATE src 33 | INTERFACE $ 34 | $) 35 | 36 | target_compile_definitions(tree-sitter-hyprlang PRIVATE 37 | $<$:TREE_SITTER_REUSE_ALLOCATOR> 38 | $<$:TREE_SITTER_DEBUG>) 39 | 40 | set_target_properties(tree-sitter-hyprlang 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-hyprlang.pc.in 48 | "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-hyprlang.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-hyprlang.pc" 56 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig") 57 | install(TARGETS tree-sitter-hyprlang 58 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") 59 | 60 | install(DIRECTORY queries/hyprlang 61 | DESTINATION "${CMAKE_INSTALL_DATADIR}/tree-sitter/queries" 62 | FILES_MATCHING PATTERN "*.scm") 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.21" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" 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.3" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "b9ac5ea5e7f2f1700842ec071401010b9c59bf735295f6e9fa079c3dc035b167" 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-hyprlang" 182 | version = "3.1.0" 183 | dependencies = [ 184 | "cc", 185 | "tree-sitter", 186 | "tree-sitter-language", 187 | ] 188 | 189 | [[package]] 190 | name = "tree-sitter-language" 191 | version = "0.1.5" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "c4013970217383f67b18aef68f6fb2e8d409bc5755227092d32efb0422ba24b8" 194 | 195 | [[package]] 196 | name = "unicode-ident" 197 | version = "1.0.18" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 200 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tree-sitter-hyprlang" 3 | description = "hyprlang grammar for the tree-sitter parsing library" 4 | version = "3.1.0" 5 | authors = ["LIOKA Ranarison Fiderana"] 6 | license = "MIT" 7 | readme = "README.md" 8 | keywords = ["incremental", "parsing", "tree-sitter", "hyprlang"] 9 | categories = ["parser-implementations", "parsing", "text-editors"] 10 | repository = "https://github.com/tree-sitter-grammars/tree-sitter-hyprlang" 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: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 LIOKA Ranarison Fiderana 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-hyprlang 6 | HOMEPAGE_URL := https://github.com/tree-sitter-grammars/tree-sitter-hyprlang 7 | VERSION := 3.1.0 8 | 9 | # repository 10 | SRC_DIR := src 11 | 12 | TS ?= tree-sitter 13 | 14 | # install directory layout 15 | PREFIX ?= /usr/local 16 | DATADIR ?= $(PREFIX)/share 17 | INCLUDEDIR ?= $(PREFIX)/include 18 | LIBDIR ?= $(PREFIX)/lib 19 | PCLIBDIR ?= $(LIBDIR)/pkgconfig 20 | 21 | # source/object files 22 | PARSER := $(SRC_DIR)/parser.c 23 | EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c)) 24 | OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS)) 25 | 26 | # flags 27 | ARFLAGS ?= rcs 28 | override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC 29 | 30 | # ABI versioning 31 | SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER)) 32 | SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION))) 33 | 34 | # OS-specific bits 35 | ifeq ($(shell uname),Darwin) 36 | SOEXT = dylib 37 | SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT) 38 | SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT) 39 | LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks 40 | else 41 | SOEXT = so 42 | SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR) 43 | SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR) 44 | LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER) 45 | endif 46 | ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),) 47 | PCLIBDIR := $(PREFIX)/libdata/pkgconfig 48 | endif 49 | 50 | all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc 51 | 52 | lib$(LANGUAGE_NAME).a: $(OBJS) 53 | $(AR) $(ARFLAGS) $@ $^ 54 | 55 | lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS) 56 | $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@ 57 | ifneq ($(STRIP),) 58 | $(STRIP) $@ 59 | endif 60 | 61 | $(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in 62 | sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \ 63 | -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \ 64 | -e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \ 65 | -e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \ 66 | -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \ 67 | -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@ 68 | 69 | $(PARSER): $(SRC_DIR)/grammar.json 70 | $(TS) generate $^ 71 | 72 | install: all 73 | install -d '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/hyprlang '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)' 74 | install -m644 bindings/c/tree_sitter/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h 75 | install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc 76 | install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a 77 | install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) 78 | ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) 79 | ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) 80 | install -m644 queries/hyprlang/*.scm '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/hyprlang 81 | 82 | uninstall: 83 | $(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \ 84 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \ 85 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \ 86 | '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \ 87 | '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \ 88 | '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc 89 | $(RM) -r '$(DESTDIR)$(DATADIR)'/tree-sitter/queries/hyprlang 90 | 91 | clean: 92 | $(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) 93 | 94 | test: 95 | $(TS) test 96 | 97 | .PHONY: all install uninstall clean test 98 | -------------------------------------------------------------------------------- /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: "TreeSitterHyprlang", 13 | products: [ 14 | .library(name: "TreeSitterHyprlang", targets: ["TreeSitterHyprlang"]), 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: "TreeSitterHyprlang", 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: "TreeSitterHyprlangTests", 33 | dependencies: [ 34 | "SwiftTreeSitter", 35 | "TreeSitterHyprlang", 36 | ], 37 | path: "bindings/swift/TreeSitterHyprlangTests" 38 | ) 39 | ], 40 | cLanguageStandard: .c11 41 | ) 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-hyprlang 2 | 3 | [hyprlang](https://github.com/hyprwm/hyprlang) grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter). 4 | 5 | ## Neovim 6 | 7 | You can install the hyprlang parser in neovim using [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) and use the following code snippet for automatic filetype detection: 8 | 9 | ```lua 10 | vim.filetype.add({ 11 | pattern = { [".*/hypr/.*%.conf"] = "hyprlang" }, 12 | }) 13 | ``` 14 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_hyprlang_binding", 5 | "dependencies": [ 6 | " 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | extern "C" TSLanguage *tree_sitter_hyprlang(); 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_hyprlang()); 14 | language.TypeTag(&LANGUAGE_TYPE_TAG); 15 | exports["language"] = language; 16 | return exports; 17 | } 18 | 19 | NODE_API_MODULE(tree_sitter_hyprlang_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-hyprlang.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_hyprlang 5 | 6 | 7 | class TestLanguage(TestCase): 8 | def test_can_load_grammar(self): 9 | try: 10 | tree_sitter.Language(tree_sitter_hyprlang.language()) 11 | except Exception: 12 | self.fail("Error loading Hyprlang grammar") 13 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_hyprlang/__init__.py: -------------------------------------------------------------------------------- 1 | """hyprlang grammar for the tree-sitter parsing library""" 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 | 20 | raise AttributeError(f"module {__name__!r} has no attribute {name!r}") 21 | 22 | 23 | __all__ = [ 24 | "language", 25 | "HIGHLIGHTS_QUERY", 26 | "INJECTIONS_QUERY", 27 | ] 28 | 29 | 30 | def __dir__(): 31 | return sorted(__all__ + [ 32 | "__all__", "__builtins__", "__cached__", "__doc__", "__file__", 33 | "__loader__", "__name__", "__package__", "__path__", "__spec__", 34 | ]) 35 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_hyprlang/__init__.pyi: -------------------------------------------------------------------------------- 1 | from typing import Final 2 | 3 | HIGHLIGHTS_QUERY: Final[str] 4 | INJECTIONS_QUERY: Final[str] 5 | 6 | def language() -> object: ... 7 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_hyprlang/binding.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | TSLanguage *tree_sitter_hyprlang(void); 6 | 7 | static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { 8 | return PyCapsule_New(tree_sitter_hyprlang(), "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_hyprlang/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tree-sitter-grammars/tree-sitter-hyprlang/d626ec06e4d876fc41200a30b3e6f2b4714c7367/bindings/python/tree_sitter_hyprlang/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-hyprlang"); 21 | } 22 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides Hyprlang language support for the [tree-sitter] parsing library. 2 | //! 3 | //! Typically, you will use the [`LANGUAGE`] constant to add this language to a 4 | //! tree-sitter [`Parser`], and then use the parser to parse some code: 5 | //! 6 | //! ``` 7 | //! let code = r#" 8 | //! "#; 9 | //! let mut parser = tree_sitter::Parser::new(); 10 | //! let language = tree_sitter_hyprlang::LANGUAGE; 11 | //! parser 12 | //! .set_language(&language.into()) 13 | //! .expect("Error loading Hyprlang parser"); 14 | //! let tree = parser.parse(code, None).unwrap(); 15 | //! assert!(!tree.root_node().has_error()); 16 | //! ``` 17 | //! 18 | //! [`Parser`]: https://docs.rs/tree-sitter/0.25.3/tree_sitter/struct.Parser.html 19 | //! [tree-sitter]: https://tree-sitter.github.io/ 20 | 21 | use tree_sitter_language::LanguageFn; 22 | 23 | extern "C" { 24 | fn tree_sitter_hyprlang() -> *const (); 25 | } 26 | 27 | /// The tree-sitter [`LanguageFn`] for this grammar. 28 | pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_hyprlang) }; 29 | 30 | /// The content of the [`node-types.json`] file for this grammar. 31 | /// 32 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types 33 | pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); 34 | 35 | /// The highlight queries for this grammar. 36 | pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/hyprlang/highlights.scm"); 37 | 38 | /// The injection queries for this grammar. 39 | pub const INJECTIONS_QUERY: &str = include_str!("../../queries/hyprlang/injections.scm"); 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | #[test] 44 | fn test_can_load_grammar() { 45 | let mut parser = tree_sitter::Parser::new(); 46 | parser 47 | .set_language(&super::LANGUAGE.into()) 48 | .expect("Error loading Hyprlang parser"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterHyprlang/hyprlang.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_HYPRLANG_H_ 2 | #define TREE_SITTER_HYPRLANG_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | const TSLanguage *tree_sitter_hyprlang(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_HYPRLANG_H_ 17 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterHyprlangTests/TreeSitterHyprlangTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import SwiftTreeSitter 3 | import TreeSitterHyprlang 4 | 5 | final class TreeSitterHyprlangTests: XCTestCase { 6 | func testCanLoadGrammar() throws { 7 | let parser = Parser() 8 | let language = Language(language: tree_sitter_hyprlang()) 9 | XCTAssertNoThrow(try parser.setLanguage(language), 10 | "Error loading Hyprlang grammar") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tree-sitter-grammars/tree-sitter-hyprlang 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 Hyprlang grammar for tree-sitter 3 | * @author LIOKA Ranarison Fiderana 4 | * @license MIT 5 | */ 6 | 7 | /// 8 | // @ts-check 9 | 10 | module.exports = grammar({ 11 | name: "hyprlang", 12 | 13 | extras: ($) => [/[ \t]/, $.comment], 14 | 15 | conflicts: ($) => [[$.number, $.legacy_hex]], 16 | 17 | word: ($) => $.string, 18 | 19 | rules: { 20 | configuration: ($) => 21 | repeat( 22 | choice( 23 | $.source, 24 | $.exec, 25 | $.declaration, 26 | $.assignment, 27 | $.keyword, 28 | $.section, 29 | $._linebreak 30 | ) 31 | ), 32 | 33 | declaration: ($) => 34 | seq( 35 | $.variable, 36 | "=", 37 | choice($.mod, $.number, $.string_literal), 38 | $._linebreak 39 | ), 40 | 41 | assignment: ($) => seq($.name, "=", optional($._value), $._linebreak), 42 | 43 | keyword: ($) => seq($.name, "=", $.params, $._linebreak), 44 | 45 | section: ($) => 46 | seq( 47 | choice($.name, seq($.name, ":", field("device", $.device_name))), 48 | "{", 49 | $._linebreak, 50 | repeat(choice($.assignment, $.keyword, $.section, $._linebreak)), 51 | "}", 52 | $._linebreak 53 | ), 54 | 55 | source: ($) => seq("source", "=", $.string, $._linebreak), 56 | 57 | exec: ($) => 58 | seq( 59 | choice("exec-once", "execr-once", "exec", "execr", "exec-shutdown"), 60 | "=", 61 | $.string, 62 | $._linebreak, 63 | ), 64 | 65 | _value: ($) => 66 | choice( 67 | $.boolean, 68 | $.number, 69 | $.vec2, 70 | $.display, 71 | $.gradient, 72 | $.mod, 73 | $.keys, 74 | $.string, 75 | $.variable, 76 | prec(1, $.color), 77 | prec(1, $.position) 78 | ), 79 | 80 | boolean: () => choice("true", "false", "on", "off", "yes", "no"), 81 | 82 | number: ($) => 83 | choice($._zero, seq(optional(choice("+", "-")), /[0-9][0-9\.]*/)), 84 | 85 | vec2: ($) => seq($.number, $.number), 86 | 87 | color: ($) => choice($.legacy_hex, $.rgb), 88 | 89 | legacy_hex: ($) => seq($._zero, "x", $.hex), 90 | 91 | rgb: ($) => 92 | seq(choice("rgb", "rgba"), "(", choice($.hex, $.number_tuple), ")"), 93 | 94 | gradient: ($) => seq($.color, repeat($.color), optional($.angle)), 95 | 96 | number_tuple: ($) => seq($.number, repeat(seq(",", $.number))), 97 | 98 | display: ($) => seq($.position, optional(seq("@", $.number))), 99 | 100 | position: ($) => seq($.number, "x", $.number), 101 | 102 | hex: () => /[0-9a-fA-F]{6,8}/, 103 | 104 | angle: () => seq(/[0-9]{1,3}/, "deg"), 105 | 106 | mod: () => 107 | choice( 108 | "SHIFT", 109 | "CAPS", 110 | "CTRL", 111 | "CONTROL", 112 | "ALT", 113 | "ALT_L", 114 | "MOD2", 115 | "MOD3", 116 | "SUPER", 117 | "WIN", 118 | "LOGO", 119 | "MOD4", 120 | "MOD5", 121 | "TAB" 122 | ), 123 | 124 | keys: ($) => choice(seq($.mod, $.mod), seq($.variable, $.mod)), 125 | 126 | string: () => token(prec(-1, /[^\n,#]+|.*##.*/)), 127 | 128 | string_literal: () => token(prec(-1, /[^\n#]+|.*##.*/)), 129 | 130 | params: ($) => 131 | prec(-1, seq($._value, repeat(seq(",", optional($._value))))), 132 | 133 | name: () => /[\w][\w\d\.\-]*/, 134 | 135 | device_name: () => /[\w\d][\w\d\/\.\-:]*/, 136 | 137 | variable: () => seq("$", /\w[\w\d]*/), 138 | 139 | _zero: () => "0", 140 | 141 | _linebreak: () => "\n", 142 | 143 | comment: () => seq("#", /.*/), 144 | }, 145 | }); 146 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-hyprlang", 3 | "version": "3.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "tree-sitter-hyprlang", 9 | "version": "3.1.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.1", 289 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", 290 | "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", 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.3", 312 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", 313 | "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", 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": { 341 | "version": "0.22.4", 342 | "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.22.4.tgz", 343 | "integrity": "sha512-usbHZP9/oxNsUY65MQUsduGRqDHQOou1cagUSwjhoSYAmSahjQDAVsh9s+SlZkn8X8+O1FULRGwHu7AFP3kjzg==", 344 | "hasInstallScript": true, 345 | "license": "MIT", 346 | "optional": true, 347 | "peer": true, 348 | "dependencies": { 349 | "node-addon-api": "^8.3.0", 350 | "node-gyp-build": "^4.8.4" 351 | } 352 | }, 353 | "node_modules/tree-sitter-cli": { 354 | "version": "0.25.3", 355 | "resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.25.3.tgz", 356 | "integrity": "sha512-Bk6ZUXG+cKnwZpfR/te4NDrKld90p6350eqWlbLwSpV9/8vmL/x8LCw+3k7quY9oMDaYoMXHMvokXJbkM5A7bA==", 357 | "dev": true, 358 | "hasInstallScript": true, 359 | "license": "MIT", 360 | "bin": { 361 | "tree-sitter": "cli.js" 362 | }, 363 | "engines": { 364 | "node": ">=12.0.0" 365 | } 366 | }, 367 | "node_modules/util-deprecate": { 368 | "version": "1.0.2", 369 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 370 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 371 | "dev": true, 372 | "license": "MIT" 373 | }, 374 | "node_modules/wrappy": { 375 | "version": "1.0.2", 376 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 377 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 378 | "dev": true, 379 | "license": "ISC" 380 | } 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-hyprlang", 3 | "version": "3.1.0", 4 | "description": "hyprlang grammar for the tree-sitter parsing library", 5 | "repository": "https://github.com/tree-sitter-grammars/tree-sitter-hyprlang", 6 | "license": "MIT", 7 | "author": { 8 | "name": "LIOKA Ranarison Fiderana" 9 | }, 10 | "main": "bindings/node", 11 | "types": "bindings/node", 12 | "keywords": [ 13 | "incremental", 14 | "parsing", 15 | "tree-sitter", 16 | "hyprlang" 17 | ], 18 | "files": [ 19 | "grammar.js", 20 | "tree-sitter.json", 21 | "binding.gyp", 22 | "prebuilds/**", 23 | "bindings/node/*", 24 | "queries/**", 25 | "src/**", 26 | "*.wasm" 27 | ], 28 | "dependencies": { 29 | "node-addon-api": "^8.3.1", 30 | "node-gyp-build": "^4.8.4" 31 | }, 32 | "devDependencies": { 33 | "prebuildify": "^6.0.1", 34 | "tree-sitter-cli": "^0.25.3" 35 | }, 36 | "peerDependencies": { 37 | "tree-sitter": "^0.22.4" 38 | }, 39 | "peerDependenciesMeta": { 40 | "tree-sitter": { 41 | "optional": true 42 | } 43 | }, 44 | "scripts": { 45 | "install": "node-gyp-build", 46 | "prestart": "tree-sitter build --wasm", 47 | "start": "tree-sitter playground", 48 | "test": "node --test bindings/node/*_test.js" 49 | }, 50 | "prettier": { 51 | "tabWidth": 2, 52 | "useTabs": false 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "tree-sitter-hyprlang" 7 | description = "hyprlang grammar for the tree-sitter parsing library" 8 | version = "3.1.0" 9 | keywords = ["incremental", "parsing", "tree-sitter", "hyprlang"] 10 | classifiers = [ 11 | "Intended Audience :: Developers", 12 | "Topic :: Software Development :: Compilers", 13 | "Topic :: Text Processing :: Linguistic", 14 | "Typing :: Typed", 15 | ] 16 | authors = [{ name = "LIOKA Ranarison Fiderana" }] 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-hyprlang" 23 | 24 | [project.optional-dependencies] 25 | core = ["tree-sitter~=0.24"] 26 | 27 | [tool.cibuildwheel] 28 | build = "cp310-*" 29 | build-frontend = "build" 30 | -------------------------------------------------------------------------------- /queries/hyprlang/folds.scm: -------------------------------------------------------------------------------- 1 | (section) @fold 2 | -------------------------------------------------------------------------------- /queries/hyprlang/highlights.scm: -------------------------------------------------------------------------------- 1 | (comment) @comment @spell 2 | 3 | [ 4 | "source" 5 | "exec-once" 6 | "execr-once" 7 | "exec" 8 | "execr" 9 | "exec-shutdown" 10 | ] @keyword 11 | 12 | (keyword 13 | (name) @keyword) 14 | 15 | (assignment 16 | (name) @property) 17 | 18 | (section 19 | (name) @module) 20 | 21 | (section 22 | device: (device_name) @type) 23 | 24 | (variable) @variable 25 | 26 | "$" @punctuation.special 27 | 28 | (boolean) @boolean 29 | 30 | (mod) @constant 31 | 32 | [ 33 | "rgb" 34 | "rgba" 35 | ] @function.builtin 36 | 37 | [ 38 | (number) 39 | (legacy_hex) 40 | (angle) 41 | (hex) 42 | (display) 43 | (position) 44 | ] @number 45 | 46 | "deg" @type 47 | 48 | "," @punctuation.delimiter 49 | 50 | [ 51 | "(" 52 | ")" 53 | "{" 54 | "}" 55 | ] @punctuation.bracket 56 | 57 | [ 58 | "=" 59 | "-" 60 | "+" 61 | ] @operator 62 | -------------------------------------------------------------------------------- /queries/hyprlang/indents.scm: -------------------------------------------------------------------------------- 1 | (section) @indent.begin 2 | 3 | (section 4 | "}" @indent.end) 5 | 6 | "}" @indent.branch 7 | -------------------------------------------------------------------------------- /queries/hyprlang/injections.scm: -------------------------------------------------------------------------------- 1 | (exec 2 | (string) @injection.content 3 | (#set! injection.language "bash")) 4 | 5 | (keyword 6 | (name) @_name 7 | (#any-of? @_name "windowrule" "windowrulev2") 8 | (params 9 | (string) 10 | (string) @injection.content 11 | (#set! injection.combined) 12 | (#set! injection.language "regex"))) 13 | 14 | (keyword 15 | (name) @_name 16 | (#match? @_name "bind(l|r|e|n|m|t|i)*") 17 | (params 18 | (_)+ 19 | (string) @_function 20 | (#match? @_function ".*exec") 21 | (string) @injection.content 22 | (#set! injection.language "bash"))) 23 | -------------------------------------------------------------------------------- /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_hyprlang/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_hyprlang", "queries") 34 | self.copy_tree("queries/hyprlang", 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_hyprlang": ["*.pyi", "py.typed"], 58 | "tree_sitter_hyprlang.queries": ["*.scm"], 59 | }, 60 | ext_package="tree_sitter_hyprlang", 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/grammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json", 3 | "name": "hyprlang", 4 | "word": "string", 5 | "rules": { 6 | "configuration": { 7 | "type": "REPEAT", 8 | "content": { 9 | "type": "CHOICE", 10 | "members": [ 11 | { 12 | "type": "SYMBOL", 13 | "name": "source" 14 | }, 15 | { 16 | "type": "SYMBOL", 17 | "name": "exec" 18 | }, 19 | { 20 | "type": "SYMBOL", 21 | "name": "declaration" 22 | }, 23 | { 24 | "type": "SYMBOL", 25 | "name": "assignment" 26 | }, 27 | { 28 | "type": "SYMBOL", 29 | "name": "keyword" 30 | }, 31 | { 32 | "type": "SYMBOL", 33 | "name": "section" 34 | }, 35 | { 36 | "type": "SYMBOL", 37 | "name": "_linebreak" 38 | } 39 | ] 40 | } 41 | }, 42 | "declaration": { 43 | "type": "SEQ", 44 | "members": [ 45 | { 46 | "type": "SYMBOL", 47 | "name": "variable" 48 | }, 49 | { 50 | "type": "STRING", 51 | "value": "=" 52 | }, 53 | { 54 | "type": "CHOICE", 55 | "members": [ 56 | { 57 | "type": "SYMBOL", 58 | "name": "mod" 59 | }, 60 | { 61 | "type": "SYMBOL", 62 | "name": "number" 63 | }, 64 | { 65 | "type": "SYMBOL", 66 | "name": "string_literal" 67 | } 68 | ] 69 | }, 70 | { 71 | "type": "SYMBOL", 72 | "name": "_linebreak" 73 | } 74 | ] 75 | }, 76 | "assignment": { 77 | "type": "SEQ", 78 | "members": [ 79 | { 80 | "type": "SYMBOL", 81 | "name": "name" 82 | }, 83 | { 84 | "type": "STRING", 85 | "value": "=" 86 | }, 87 | { 88 | "type": "CHOICE", 89 | "members": [ 90 | { 91 | "type": "SYMBOL", 92 | "name": "_value" 93 | }, 94 | { 95 | "type": "BLANK" 96 | } 97 | ] 98 | }, 99 | { 100 | "type": "SYMBOL", 101 | "name": "_linebreak" 102 | } 103 | ] 104 | }, 105 | "keyword": { 106 | "type": "SEQ", 107 | "members": [ 108 | { 109 | "type": "SYMBOL", 110 | "name": "name" 111 | }, 112 | { 113 | "type": "STRING", 114 | "value": "=" 115 | }, 116 | { 117 | "type": "SYMBOL", 118 | "name": "params" 119 | }, 120 | { 121 | "type": "SYMBOL", 122 | "name": "_linebreak" 123 | } 124 | ] 125 | }, 126 | "section": { 127 | "type": "SEQ", 128 | "members": [ 129 | { 130 | "type": "CHOICE", 131 | "members": [ 132 | { 133 | "type": "SYMBOL", 134 | "name": "name" 135 | }, 136 | { 137 | "type": "SEQ", 138 | "members": [ 139 | { 140 | "type": "SYMBOL", 141 | "name": "name" 142 | }, 143 | { 144 | "type": "STRING", 145 | "value": ":" 146 | }, 147 | { 148 | "type": "FIELD", 149 | "name": "device", 150 | "content": { 151 | "type": "SYMBOL", 152 | "name": "device_name" 153 | } 154 | } 155 | ] 156 | } 157 | ] 158 | }, 159 | { 160 | "type": "STRING", 161 | "value": "{" 162 | }, 163 | { 164 | "type": "SYMBOL", 165 | "name": "_linebreak" 166 | }, 167 | { 168 | "type": "REPEAT", 169 | "content": { 170 | "type": "CHOICE", 171 | "members": [ 172 | { 173 | "type": "SYMBOL", 174 | "name": "assignment" 175 | }, 176 | { 177 | "type": "SYMBOL", 178 | "name": "keyword" 179 | }, 180 | { 181 | "type": "SYMBOL", 182 | "name": "section" 183 | }, 184 | { 185 | "type": "SYMBOL", 186 | "name": "_linebreak" 187 | } 188 | ] 189 | } 190 | }, 191 | { 192 | "type": "STRING", 193 | "value": "}" 194 | }, 195 | { 196 | "type": "SYMBOL", 197 | "name": "_linebreak" 198 | } 199 | ] 200 | }, 201 | "source": { 202 | "type": "SEQ", 203 | "members": [ 204 | { 205 | "type": "STRING", 206 | "value": "source" 207 | }, 208 | { 209 | "type": "STRING", 210 | "value": "=" 211 | }, 212 | { 213 | "type": "SYMBOL", 214 | "name": "string" 215 | }, 216 | { 217 | "type": "SYMBOL", 218 | "name": "_linebreak" 219 | } 220 | ] 221 | }, 222 | "exec": { 223 | "type": "SEQ", 224 | "members": [ 225 | { 226 | "type": "CHOICE", 227 | "members": [ 228 | { 229 | "type": "STRING", 230 | "value": "exec-once" 231 | }, 232 | { 233 | "type": "STRING", 234 | "value": "execr-once" 235 | }, 236 | { 237 | "type": "STRING", 238 | "value": "exec" 239 | }, 240 | { 241 | "type": "STRING", 242 | "value": "execr" 243 | }, 244 | { 245 | "type": "STRING", 246 | "value": "exec-shutdown" 247 | } 248 | ] 249 | }, 250 | { 251 | "type": "STRING", 252 | "value": "=" 253 | }, 254 | { 255 | "type": "SYMBOL", 256 | "name": "string" 257 | }, 258 | { 259 | "type": "SYMBOL", 260 | "name": "_linebreak" 261 | } 262 | ] 263 | }, 264 | "_value": { 265 | "type": "CHOICE", 266 | "members": [ 267 | { 268 | "type": "SYMBOL", 269 | "name": "boolean" 270 | }, 271 | { 272 | "type": "SYMBOL", 273 | "name": "number" 274 | }, 275 | { 276 | "type": "SYMBOL", 277 | "name": "vec2" 278 | }, 279 | { 280 | "type": "SYMBOL", 281 | "name": "display" 282 | }, 283 | { 284 | "type": "SYMBOL", 285 | "name": "gradient" 286 | }, 287 | { 288 | "type": "SYMBOL", 289 | "name": "mod" 290 | }, 291 | { 292 | "type": "SYMBOL", 293 | "name": "keys" 294 | }, 295 | { 296 | "type": "SYMBOL", 297 | "name": "string" 298 | }, 299 | { 300 | "type": "SYMBOL", 301 | "name": "variable" 302 | }, 303 | { 304 | "type": "PREC", 305 | "value": 1, 306 | "content": { 307 | "type": "SYMBOL", 308 | "name": "color" 309 | } 310 | }, 311 | { 312 | "type": "PREC", 313 | "value": 1, 314 | "content": { 315 | "type": "SYMBOL", 316 | "name": "position" 317 | } 318 | } 319 | ] 320 | }, 321 | "boolean": { 322 | "type": "CHOICE", 323 | "members": [ 324 | { 325 | "type": "STRING", 326 | "value": "true" 327 | }, 328 | { 329 | "type": "STRING", 330 | "value": "false" 331 | }, 332 | { 333 | "type": "STRING", 334 | "value": "on" 335 | }, 336 | { 337 | "type": "STRING", 338 | "value": "off" 339 | }, 340 | { 341 | "type": "STRING", 342 | "value": "yes" 343 | }, 344 | { 345 | "type": "STRING", 346 | "value": "no" 347 | } 348 | ] 349 | }, 350 | "number": { 351 | "type": "CHOICE", 352 | "members": [ 353 | { 354 | "type": "SYMBOL", 355 | "name": "_zero" 356 | }, 357 | { 358 | "type": "SEQ", 359 | "members": [ 360 | { 361 | "type": "CHOICE", 362 | "members": [ 363 | { 364 | "type": "CHOICE", 365 | "members": [ 366 | { 367 | "type": "STRING", 368 | "value": "+" 369 | }, 370 | { 371 | "type": "STRING", 372 | "value": "-" 373 | } 374 | ] 375 | }, 376 | { 377 | "type": "BLANK" 378 | } 379 | ] 380 | }, 381 | { 382 | "type": "PATTERN", 383 | "value": "[0-9][0-9\\.]*" 384 | } 385 | ] 386 | } 387 | ] 388 | }, 389 | "vec2": { 390 | "type": "SEQ", 391 | "members": [ 392 | { 393 | "type": "SYMBOL", 394 | "name": "number" 395 | }, 396 | { 397 | "type": "SYMBOL", 398 | "name": "number" 399 | } 400 | ] 401 | }, 402 | "color": { 403 | "type": "CHOICE", 404 | "members": [ 405 | { 406 | "type": "SYMBOL", 407 | "name": "legacy_hex" 408 | }, 409 | { 410 | "type": "SYMBOL", 411 | "name": "rgb" 412 | } 413 | ] 414 | }, 415 | "legacy_hex": { 416 | "type": "SEQ", 417 | "members": [ 418 | { 419 | "type": "SYMBOL", 420 | "name": "_zero" 421 | }, 422 | { 423 | "type": "STRING", 424 | "value": "x" 425 | }, 426 | { 427 | "type": "SYMBOL", 428 | "name": "hex" 429 | } 430 | ] 431 | }, 432 | "rgb": { 433 | "type": "SEQ", 434 | "members": [ 435 | { 436 | "type": "CHOICE", 437 | "members": [ 438 | { 439 | "type": "STRING", 440 | "value": "rgb" 441 | }, 442 | { 443 | "type": "STRING", 444 | "value": "rgba" 445 | } 446 | ] 447 | }, 448 | { 449 | "type": "STRING", 450 | "value": "(" 451 | }, 452 | { 453 | "type": "CHOICE", 454 | "members": [ 455 | { 456 | "type": "SYMBOL", 457 | "name": "hex" 458 | }, 459 | { 460 | "type": "SYMBOL", 461 | "name": "number_tuple" 462 | } 463 | ] 464 | }, 465 | { 466 | "type": "STRING", 467 | "value": ")" 468 | } 469 | ] 470 | }, 471 | "gradient": { 472 | "type": "SEQ", 473 | "members": [ 474 | { 475 | "type": "SYMBOL", 476 | "name": "color" 477 | }, 478 | { 479 | "type": "REPEAT", 480 | "content": { 481 | "type": "SYMBOL", 482 | "name": "color" 483 | } 484 | }, 485 | { 486 | "type": "CHOICE", 487 | "members": [ 488 | { 489 | "type": "SYMBOL", 490 | "name": "angle" 491 | }, 492 | { 493 | "type": "BLANK" 494 | } 495 | ] 496 | } 497 | ] 498 | }, 499 | "number_tuple": { 500 | "type": "SEQ", 501 | "members": [ 502 | { 503 | "type": "SYMBOL", 504 | "name": "number" 505 | }, 506 | { 507 | "type": "REPEAT", 508 | "content": { 509 | "type": "SEQ", 510 | "members": [ 511 | { 512 | "type": "STRING", 513 | "value": "," 514 | }, 515 | { 516 | "type": "SYMBOL", 517 | "name": "number" 518 | } 519 | ] 520 | } 521 | } 522 | ] 523 | }, 524 | "display": { 525 | "type": "SEQ", 526 | "members": [ 527 | { 528 | "type": "SYMBOL", 529 | "name": "position" 530 | }, 531 | { 532 | "type": "CHOICE", 533 | "members": [ 534 | { 535 | "type": "SEQ", 536 | "members": [ 537 | { 538 | "type": "STRING", 539 | "value": "@" 540 | }, 541 | { 542 | "type": "SYMBOL", 543 | "name": "number" 544 | } 545 | ] 546 | }, 547 | { 548 | "type": "BLANK" 549 | } 550 | ] 551 | } 552 | ] 553 | }, 554 | "position": { 555 | "type": "SEQ", 556 | "members": [ 557 | { 558 | "type": "SYMBOL", 559 | "name": "number" 560 | }, 561 | { 562 | "type": "STRING", 563 | "value": "x" 564 | }, 565 | { 566 | "type": "SYMBOL", 567 | "name": "number" 568 | } 569 | ] 570 | }, 571 | "hex": { 572 | "type": "PATTERN", 573 | "value": "[0-9a-fA-F]{6,8}" 574 | }, 575 | "angle": { 576 | "type": "SEQ", 577 | "members": [ 578 | { 579 | "type": "PATTERN", 580 | "value": "[0-9]{1,3}" 581 | }, 582 | { 583 | "type": "STRING", 584 | "value": "deg" 585 | } 586 | ] 587 | }, 588 | "mod": { 589 | "type": "CHOICE", 590 | "members": [ 591 | { 592 | "type": "STRING", 593 | "value": "SHIFT" 594 | }, 595 | { 596 | "type": "STRING", 597 | "value": "CAPS" 598 | }, 599 | { 600 | "type": "STRING", 601 | "value": "CTRL" 602 | }, 603 | { 604 | "type": "STRING", 605 | "value": "CONTROL" 606 | }, 607 | { 608 | "type": "STRING", 609 | "value": "ALT" 610 | }, 611 | { 612 | "type": "STRING", 613 | "value": "ALT_L" 614 | }, 615 | { 616 | "type": "STRING", 617 | "value": "MOD2" 618 | }, 619 | { 620 | "type": "STRING", 621 | "value": "MOD3" 622 | }, 623 | { 624 | "type": "STRING", 625 | "value": "SUPER" 626 | }, 627 | { 628 | "type": "STRING", 629 | "value": "WIN" 630 | }, 631 | { 632 | "type": "STRING", 633 | "value": "LOGO" 634 | }, 635 | { 636 | "type": "STRING", 637 | "value": "MOD4" 638 | }, 639 | { 640 | "type": "STRING", 641 | "value": "MOD5" 642 | }, 643 | { 644 | "type": "STRING", 645 | "value": "TAB" 646 | } 647 | ] 648 | }, 649 | "keys": { 650 | "type": "CHOICE", 651 | "members": [ 652 | { 653 | "type": "SEQ", 654 | "members": [ 655 | { 656 | "type": "SYMBOL", 657 | "name": "mod" 658 | }, 659 | { 660 | "type": "SYMBOL", 661 | "name": "mod" 662 | } 663 | ] 664 | }, 665 | { 666 | "type": "SEQ", 667 | "members": [ 668 | { 669 | "type": "SYMBOL", 670 | "name": "variable" 671 | }, 672 | { 673 | "type": "SYMBOL", 674 | "name": "mod" 675 | } 676 | ] 677 | } 678 | ] 679 | }, 680 | "string": { 681 | "type": "TOKEN", 682 | "content": { 683 | "type": "PREC", 684 | "value": -1, 685 | "content": { 686 | "type": "PATTERN", 687 | "value": "[^\\n,#]+|.*##.*" 688 | } 689 | } 690 | }, 691 | "string_literal": { 692 | "type": "TOKEN", 693 | "content": { 694 | "type": "PREC", 695 | "value": -1, 696 | "content": { 697 | "type": "PATTERN", 698 | "value": "[^\\n#]+|.*##.*" 699 | } 700 | } 701 | }, 702 | "params": { 703 | "type": "PREC", 704 | "value": -1, 705 | "content": { 706 | "type": "SEQ", 707 | "members": [ 708 | { 709 | "type": "SYMBOL", 710 | "name": "_value" 711 | }, 712 | { 713 | "type": "REPEAT", 714 | "content": { 715 | "type": "SEQ", 716 | "members": [ 717 | { 718 | "type": "STRING", 719 | "value": "," 720 | }, 721 | { 722 | "type": "CHOICE", 723 | "members": [ 724 | { 725 | "type": "SYMBOL", 726 | "name": "_value" 727 | }, 728 | { 729 | "type": "BLANK" 730 | } 731 | ] 732 | } 733 | ] 734 | } 735 | } 736 | ] 737 | } 738 | }, 739 | "name": { 740 | "type": "PATTERN", 741 | "value": "[\\w][\\w\\d\\.\\-]*" 742 | }, 743 | "device_name": { 744 | "type": "PATTERN", 745 | "value": "[\\w\\d][\\w\\d\\/\\.\\-:]*" 746 | }, 747 | "variable": { 748 | "type": "SEQ", 749 | "members": [ 750 | { 751 | "type": "STRING", 752 | "value": "$" 753 | }, 754 | { 755 | "type": "PATTERN", 756 | "value": "\\w[\\w\\d]*" 757 | } 758 | ] 759 | }, 760 | "_zero": { 761 | "type": "STRING", 762 | "value": "0" 763 | }, 764 | "_linebreak": { 765 | "type": "STRING", 766 | "value": "\n" 767 | }, 768 | "comment": { 769 | "type": "SEQ", 770 | "members": [ 771 | { 772 | "type": "STRING", 773 | "value": "#" 774 | }, 775 | { 776 | "type": "PATTERN", 777 | "value": ".*" 778 | } 779 | ] 780 | } 781 | }, 782 | "extras": [ 783 | { 784 | "type": "PATTERN", 785 | "value": "[ \\t]" 786 | }, 787 | { 788 | "type": "SYMBOL", 789 | "name": "comment" 790 | } 791 | ], 792 | "conflicts": [ 793 | [ 794 | "number", 795 | "legacy_hex" 796 | ] 797 | ], 798 | "precedences": [], 799 | "externals": [], 800 | "inline": [], 801 | "supertypes": [], 802 | "reserved": {} 803 | } -------------------------------------------------------------------------------- /src/node-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "angle", 4 | "named": true, 5 | "fields": {} 6 | }, 7 | { 8 | "type": "assignment", 9 | "named": true, 10 | "fields": {}, 11 | "children": { 12 | "multiple": true, 13 | "required": true, 14 | "types": [ 15 | { 16 | "type": "boolean", 17 | "named": true 18 | }, 19 | { 20 | "type": "color", 21 | "named": true 22 | }, 23 | { 24 | "type": "display", 25 | "named": true 26 | }, 27 | { 28 | "type": "gradient", 29 | "named": true 30 | }, 31 | { 32 | "type": "keys", 33 | "named": true 34 | }, 35 | { 36 | "type": "mod", 37 | "named": true 38 | }, 39 | { 40 | "type": "name", 41 | "named": true 42 | }, 43 | { 44 | "type": "number", 45 | "named": true 46 | }, 47 | { 48 | "type": "position", 49 | "named": true 50 | }, 51 | { 52 | "type": "string", 53 | "named": true 54 | }, 55 | { 56 | "type": "variable", 57 | "named": true 58 | }, 59 | { 60 | "type": "vec2", 61 | "named": true 62 | } 63 | ] 64 | } 65 | }, 66 | { 67 | "type": "boolean", 68 | "named": true, 69 | "fields": {} 70 | }, 71 | { 72 | "type": "color", 73 | "named": true, 74 | "fields": {}, 75 | "children": { 76 | "multiple": false, 77 | "required": true, 78 | "types": [ 79 | { 80 | "type": "legacy_hex", 81 | "named": true 82 | }, 83 | { 84 | "type": "rgb", 85 | "named": true 86 | } 87 | ] 88 | } 89 | }, 90 | { 91 | "type": "comment", 92 | "named": true, 93 | "fields": {} 94 | }, 95 | { 96 | "type": "configuration", 97 | "named": true, 98 | "root": true, 99 | "fields": {}, 100 | "children": { 101 | "multiple": true, 102 | "required": false, 103 | "types": [ 104 | { 105 | "type": "assignment", 106 | "named": true 107 | }, 108 | { 109 | "type": "declaration", 110 | "named": true 111 | }, 112 | { 113 | "type": "exec", 114 | "named": true 115 | }, 116 | { 117 | "type": "keyword", 118 | "named": true 119 | }, 120 | { 121 | "type": "section", 122 | "named": true 123 | }, 124 | { 125 | "type": "source", 126 | "named": true 127 | } 128 | ] 129 | } 130 | }, 131 | { 132 | "type": "declaration", 133 | "named": true, 134 | "fields": {}, 135 | "children": { 136 | "multiple": true, 137 | "required": true, 138 | "types": [ 139 | { 140 | "type": "mod", 141 | "named": true 142 | }, 143 | { 144 | "type": "number", 145 | "named": true 146 | }, 147 | { 148 | "type": "string_literal", 149 | "named": true 150 | }, 151 | { 152 | "type": "variable", 153 | "named": true 154 | } 155 | ] 156 | } 157 | }, 158 | { 159 | "type": "display", 160 | "named": true, 161 | "fields": {}, 162 | "children": { 163 | "multiple": true, 164 | "required": true, 165 | "types": [ 166 | { 167 | "type": "number", 168 | "named": true 169 | }, 170 | { 171 | "type": "position", 172 | "named": true 173 | } 174 | ] 175 | } 176 | }, 177 | { 178 | "type": "exec", 179 | "named": true, 180 | "fields": {}, 181 | "children": { 182 | "multiple": false, 183 | "required": true, 184 | "types": [ 185 | { 186 | "type": "string", 187 | "named": true 188 | } 189 | ] 190 | } 191 | }, 192 | { 193 | "type": "gradient", 194 | "named": true, 195 | "fields": {}, 196 | "children": { 197 | "multiple": true, 198 | "required": true, 199 | "types": [ 200 | { 201 | "type": "angle", 202 | "named": true 203 | }, 204 | { 205 | "type": "color", 206 | "named": true 207 | } 208 | ] 209 | } 210 | }, 211 | { 212 | "type": "keys", 213 | "named": true, 214 | "fields": {}, 215 | "children": { 216 | "multiple": true, 217 | "required": true, 218 | "types": [ 219 | { 220 | "type": "mod", 221 | "named": true 222 | }, 223 | { 224 | "type": "variable", 225 | "named": true 226 | } 227 | ] 228 | } 229 | }, 230 | { 231 | "type": "keyword", 232 | "named": true, 233 | "fields": {}, 234 | "children": { 235 | "multiple": true, 236 | "required": true, 237 | "types": [ 238 | { 239 | "type": "name", 240 | "named": true 241 | }, 242 | { 243 | "type": "params", 244 | "named": true 245 | } 246 | ] 247 | } 248 | }, 249 | { 250 | "type": "legacy_hex", 251 | "named": true, 252 | "fields": {}, 253 | "children": { 254 | "multiple": false, 255 | "required": true, 256 | "types": [ 257 | { 258 | "type": "hex", 259 | "named": true 260 | } 261 | ] 262 | } 263 | }, 264 | { 265 | "type": "mod", 266 | "named": true, 267 | "fields": {} 268 | }, 269 | { 270 | "type": "number", 271 | "named": true, 272 | "fields": {} 273 | }, 274 | { 275 | "type": "number_tuple", 276 | "named": true, 277 | "fields": {}, 278 | "children": { 279 | "multiple": true, 280 | "required": true, 281 | "types": [ 282 | { 283 | "type": "number", 284 | "named": true 285 | } 286 | ] 287 | } 288 | }, 289 | { 290 | "type": "params", 291 | "named": true, 292 | "fields": {}, 293 | "children": { 294 | "multiple": true, 295 | "required": true, 296 | "types": [ 297 | { 298 | "type": "boolean", 299 | "named": true 300 | }, 301 | { 302 | "type": "color", 303 | "named": true 304 | }, 305 | { 306 | "type": "display", 307 | "named": true 308 | }, 309 | { 310 | "type": "gradient", 311 | "named": true 312 | }, 313 | { 314 | "type": "keys", 315 | "named": true 316 | }, 317 | { 318 | "type": "mod", 319 | "named": true 320 | }, 321 | { 322 | "type": "number", 323 | "named": true 324 | }, 325 | { 326 | "type": "position", 327 | "named": true 328 | }, 329 | { 330 | "type": "string", 331 | "named": true 332 | }, 333 | { 334 | "type": "variable", 335 | "named": true 336 | }, 337 | { 338 | "type": "vec2", 339 | "named": true 340 | } 341 | ] 342 | } 343 | }, 344 | { 345 | "type": "position", 346 | "named": true, 347 | "fields": {}, 348 | "children": { 349 | "multiple": true, 350 | "required": true, 351 | "types": [ 352 | { 353 | "type": "number", 354 | "named": true 355 | } 356 | ] 357 | } 358 | }, 359 | { 360 | "type": "rgb", 361 | "named": true, 362 | "fields": {}, 363 | "children": { 364 | "multiple": false, 365 | "required": true, 366 | "types": [ 367 | { 368 | "type": "hex", 369 | "named": true 370 | }, 371 | { 372 | "type": "number_tuple", 373 | "named": true 374 | } 375 | ] 376 | } 377 | }, 378 | { 379 | "type": "section", 380 | "named": true, 381 | "fields": { 382 | "device": { 383 | "multiple": false, 384 | "required": false, 385 | "types": [ 386 | { 387 | "type": "device_name", 388 | "named": true 389 | } 390 | ] 391 | } 392 | }, 393 | "children": { 394 | "multiple": true, 395 | "required": true, 396 | "types": [ 397 | { 398 | "type": "assignment", 399 | "named": true 400 | }, 401 | { 402 | "type": "keyword", 403 | "named": true 404 | }, 405 | { 406 | "type": "name", 407 | "named": true 408 | }, 409 | { 410 | "type": "section", 411 | "named": true 412 | } 413 | ] 414 | } 415 | }, 416 | { 417 | "type": "source", 418 | "named": true, 419 | "fields": {}, 420 | "children": { 421 | "multiple": false, 422 | "required": true, 423 | "types": [ 424 | { 425 | "type": "string", 426 | "named": true 427 | } 428 | ] 429 | } 430 | }, 431 | { 432 | "type": "variable", 433 | "named": true, 434 | "fields": {} 435 | }, 436 | { 437 | "type": "vec2", 438 | "named": true, 439 | "fields": {}, 440 | "children": { 441 | "multiple": true, 442 | "required": true, 443 | "types": [ 444 | { 445 | "type": "number", 446 | "named": true 447 | } 448 | ] 449 | } 450 | }, 451 | { 452 | "type": "\n", 453 | "named": false 454 | }, 455 | { 456 | "type": "#", 457 | "named": false 458 | }, 459 | { 460 | "type": "$", 461 | "named": false 462 | }, 463 | { 464 | "type": "(", 465 | "named": false 466 | }, 467 | { 468 | "type": ")", 469 | "named": false 470 | }, 471 | { 472 | "type": "+", 473 | "named": false 474 | }, 475 | { 476 | "type": ",", 477 | "named": false 478 | }, 479 | { 480 | "type": "-", 481 | "named": false 482 | }, 483 | { 484 | "type": "0", 485 | "named": false 486 | }, 487 | { 488 | "type": ":", 489 | "named": false 490 | }, 491 | { 492 | "type": "=", 493 | "named": false 494 | }, 495 | { 496 | "type": "@", 497 | "named": false 498 | }, 499 | { 500 | "type": "ALT", 501 | "named": false 502 | }, 503 | { 504 | "type": "ALT_L", 505 | "named": false 506 | }, 507 | { 508 | "type": "CAPS", 509 | "named": false 510 | }, 511 | { 512 | "type": "CONTROL", 513 | "named": false 514 | }, 515 | { 516 | "type": "CTRL", 517 | "named": false 518 | }, 519 | { 520 | "type": "LOGO", 521 | "named": false 522 | }, 523 | { 524 | "type": "MOD2", 525 | "named": false 526 | }, 527 | { 528 | "type": "MOD3", 529 | "named": false 530 | }, 531 | { 532 | "type": "MOD4", 533 | "named": false 534 | }, 535 | { 536 | "type": "MOD5", 537 | "named": false 538 | }, 539 | { 540 | "type": "SHIFT", 541 | "named": false 542 | }, 543 | { 544 | "type": "SUPER", 545 | "named": false 546 | }, 547 | { 548 | "type": "TAB", 549 | "named": false 550 | }, 551 | { 552 | "type": "WIN", 553 | "named": false 554 | }, 555 | { 556 | "type": "deg", 557 | "named": false 558 | }, 559 | { 560 | "type": "device_name", 561 | "named": true 562 | }, 563 | { 564 | "type": "exec", 565 | "named": false 566 | }, 567 | { 568 | "type": "exec-once", 569 | "named": false 570 | }, 571 | { 572 | "type": "exec-shutdown", 573 | "named": false 574 | }, 575 | { 576 | "type": "execr", 577 | "named": false 578 | }, 579 | { 580 | "type": "execr-once", 581 | "named": false 582 | }, 583 | { 584 | "type": "false", 585 | "named": false 586 | }, 587 | { 588 | "type": "hex", 589 | "named": true 590 | }, 591 | { 592 | "type": "name", 593 | "named": true 594 | }, 595 | { 596 | "type": "no", 597 | "named": false 598 | }, 599 | { 600 | "type": "off", 601 | "named": false 602 | }, 603 | { 604 | "type": "on", 605 | "named": false 606 | }, 607 | { 608 | "type": "rgb", 609 | "named": false 610 | }, 611 | { 612 | "type": "rgba", 613 | "named": false 614 | }, 615 | { 616 | "type": "source", 617 | "named": false 618 | }, 619 | { 620 | "type": "string", 621 | "named": true 622 | }, 623 | { 624 | "type": "string_literal", 625 | "named": true 626 | }, 627 | { 628 | "type": "true", 629 | "named": false 630 | }, 631 | { 632 | "type": "x", 633 | "named": false 634 | }, 635 | { 636 | "type": "yes", 637 | "named": false 638 | }, 639 | { 640 | "type": "{", 641 | "named": false 642 | }, 643 | { 644 | "type": "}", 645 | "named": false 646 | } 647 | ] -------------------------------------------------------------------------------- /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 TSLanguageMetadata; 22 | typedef struct TSLanguageMetadata { 23 | uint8_t major_version; 24 | uint8_t minor_version; 25 | uint8_t patch_version; 26 | } TSLanguageMetadata; 27 | #endif 28 | 29 | typedef struct { 30 | TSFieldId field_id; 31 | uint8_t child_index; 32 | bool inherited; 33 | } TSFieldMapEntry; 34 | 35 | // Used to index the field and supertype maps. 36 | typedef struct { 37 | uint16_t index; 38 | uint16_t length; 39 | } TSMapSlice; 40 | 41 | typedef struct { 42 | bool visible; 43 | bool named; 44 | bool supertype; 45 | } TSSymbolMetadata; 46 | 47 | typedef struct TSLexer TSLexer; 48 | 49 | struct TSLexer { 50 | int32_t lookahead; 51 | TSSymbol result_symbol; 52 | void (*advance)(TSLexer *, bool); 53 | void (*mark_end)(TSLexer *); 54 | uint32_t (*get_column)(TSLexer *); 55 | bool (*is_at_included_range_start)(const TSLexer *); 56 | bool (*eof)(const TSLexer *); 57 | void (*log)(const TSLexer *, const char *, ...); 58 | }; 59 | 60 | typedef enum { 61 | TSParseActionTypeShift, 62 | TSParseActionTypeReduce, 63 | TSParseActionTypeAccept, 64 | TSParseActionTypeRecover, 65 | } TSParseActionType; 66 | 67 | typedef union { 68 | struct { 69 | uint8_t type; 70 | TSStateId state; 71 | bool extra; 72 | bool repetition; 73 | } shift; 74 | struct { 75 | uint8_t type; 76 | uint8_t child_count; 77 | TSSymbol symbol; 78 | int16_t dynamic_precedence; 79 | uint16_t production_id; 80 | } reduce; 81 | uint8_t type; 82 | } TSParseAction; 83 | 84 | typedef struct { 85 | uint16_t lex_state; 86 | uint16_t external_lex_state; 87 | } TSLexMode; 88 | 89 | typedef struct { 90 | uint16_t lex_state; 91 | uint16_t external_lex_state; 92 | uint16_t reserved_word_set_id; 93 | } TSLexerMode; 94 | 95 | typedef union { 96 | TSParseAction action; 97 | struct { 98 | uint8_t count; 99 | bool reusable; 100 | } entry; 101 | } TSParseActionEntry; 102 | 103 | typedef struct { 104 | int32_t start; 105 | int32_t end; 106 | } TSCharacterRange; 107 | 108 | struct TSLanguage { 109 | uint32_t abi_version; 110 | uint32_t symbol_count; 111 | uint32_t alias_count; 112 | uint32_t token_count; 113 | uint32_t external_token_count; 114 | uint32_t state_count; 115 | uint32_t large_state_count; 116 | uint32_t production_id_count; 117 | uint32_t field_count; 118 | uint16_t max_alias_sequence_length; 119 | const uint16_t *parse_table; 120 | const uint16_t *small_parse_table; 121 | const uint32_t *small_parse_table_map; 122 | const TSParseActionEntry *parse_actions; 123 | const char * const *symbol_names; 124 | const char * const *field_names; 125 | const TSMapSlice *field_map_slices; 126 | const TSFieldMapEntry *field_map_entries; 127 | const TSSymbolMetadata *symbol_metadata; 128 | const TSSymbol *public_symbol_map; 129 | const uint16_t *alias_map; 130 | const TSSymbol *alias_sequences; 131 | const TSLexerMode *lex_modes; 132 | bool (*lex_fn)(TSLexer *, TSStateId); 133 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 134 | TSSymbol keyword_capture_token; 135 | struct { 136 | const bool *states; 137 | const TSSymbol *symbol_map; 138 | void *(*create)(void); 139 | void (*destroy)(void *); 140 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 141 | unsigned (*serialize)(void *, char *); 142 | void (*deserialize)(void *, const char *, unsigned); 143 | } external_scanner; 144 | const TSStateId *primary_state_ids; 145 | const char *name; 146 | const TSSymbol *reserved_words; 147 | uint16_t max_reserved_word_set_size; 148 | uint32_t supertype_count; 149 | const TSSymbol *supertype_symbols; 150 | const TSMapSlice *supertype_map_slices; 151 | const TSSymbol *supertype_map_entries; 152 | TSLanguageMetadata metadata; 153 | }; 154 | 155 | static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 156 | uint32_t index = 0; 157 | uint32_t size = len - index; 158 | while (size > 1) { 159 | uint32_t half_size = size / 2; 160 | uint32_t mid_index = index + half_size; 161 | const TSCharacterRange *range = &ranges[mid_index]; 162 | if (lookahead >= range->start && lookahead <= range->end) { 163 | return true; 164 | } else if (lookahead > range->end) { 165 | index = mid_index; 166 | } 167 | size -= half_size; 168 | } 169 | const TSCharacterRange *range = &ranges[index]; 170 | return (lookahead >= range->start && lookahead <= range->end); 171 | } 172 | 173 | /* 174 | * Lexer Macros 175 | */ 176 | 177 | #ifdef _MSC_VER 178 | #define UNUSED __pragma(warning(suppress : 4101)) 179 | #else 180 | #define UNUSED __attribute__((unused)) 181 | #endif 182 | 183 | #define START_LEXER() \ 184 | bool result = false; \ 185 | bool skip = false; \ 186 | UNUSED \ 187 | bool eof = false; \ 188 | int32_t lookahead; \ 189 | goto start; \ 190 | next_state: \ 191 | lexer->advance(lexer, skip); \ 192 | start: \ 193 | skip = false; \ 194 | lookahead = lexer->lookahead; 195 | 196 | #define ADVANCE(state_value) \ 197 | { \ 198 | state = state_value; \ 199 | goto next_state; \ 200 | } 201 | 202 | #define ADVANCE_MAP(...) \ 203 | { \ 204 | static const uint16_t map[] = { __VA_ARGS__ }; \ 205 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 206 | if (map[i] == lookahead) { \ 207 | state = map[i + 1]; \ 208 | goto next_state; \ 209 | } \ 210 | } \ 211 | } 212 | 213 | #define SKIP(state_value) \ 214 | { \ 215 | skip = true; \ 216 | state = state_value; \ 217 | goto next_state; \ 218 | } 219 | 220 | #define ACCEPT_TOKEN(symbol_value) \ 221 | result = true; \ 222 | lexer->result_symbol = symbol_value; \ 223 | lexer->mark_end(lexer); 224 | 225 | #define END_STATE() return result; 226 | 227 | /* 228 | * Parse Table Macros 229 | */ 230 | 231 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 232 | 233 | #define STATE(id) id 234 | 235 | #define ACTIONS(id) id 236 | 237 | #define SHIFT(state_value) \ 238 | {{ \ 239 | .shift = { \ 240 | .type = TSParseActionTypeShift, \ 241 | .state = (state_value) \ 242 | } \ 243 | }} 244 | 245 | #define SHIFT_REPEAT(state_value) \ 246 | {{ \ 247 | .shift = { \ 248 | .type = TSParseActionTypeShift, \ 249 | .state = (state_value), \ 250 | .repetition = true \ 251 | } \ 252 | }} 253 | 254 | #define SHIFT_EXTRA() \ 255 | {{ \ 256 | .shift = { \ 257 | .type = TSParseActionTypeShift, \ 258 | .extra = true \ 259 | } \ 260 | }} 261 | 262 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 263 | {{ \ 264 | .reduce = { \ 265 | .type = TSParseActionTypeReduce, \ 266 | .symbol = symbol_name, \ 267 | .child_count = children, \ 268 | .dynamic_precedence = precedence, \ 269 | .production_id = prod_id \ 270 | }, \ 271 | }} 272 | 273 | #define RECOVER() \ 274 | {{ \ 275 | .type = TSParseActionTypeRecover \ 276 | }} 277 | 278 | #define ACCEPT_INPUT() \ 279 | {{ \ 280 | .type = TSParseActionTypeAccept \ 281 | }} 282 | 283 | #ifdef __cplusplus 284 | } 285 | #endif 286 | 287 | #endif // TREE_SITTER_PARSER_H_ 288 | -------------------------------------------------------------------------------- /test/corpus/config.txt: -------------------------------------------------------------------------------- 1 | ================================================= 2 | Basics 3 | ================================================= 4 | 5 | # comment 6 | 7 | $variable = value # inline comment 8 | 9 | section { 10 | key = not a ##comment 11 | } 12 | 13 | section:device { 14 | key = 15 | } 16 | 17 | --- 18 | 19 | (configuration 20 | (comment) 21 | (declaration 22 | (variable) 23 | (string_literal) 24 | (comment)) 25 | (section 26 | (name) 27 | (assignment 28 | (name) 29 | (string))) 30 | (section 31 | (name) 32 | device: (device_name) 33 | (assignment 34 | (name)))) 35 | 36 | ================================================= 37 | Data types 38 | ================================================= 39 | 40 | boolean = true 41 | number = 1.2 42 | vec2 = 1 2 43 | string = hyprland 44 | color_hex = 0xffffff 45 | color_rgb = rgb(000fff) 46 | color_rgb2 = rgb(122, 176, 91, 0.1) 47 | gradient = rgb(000fff) 0xfff000 45deg 48 | mod = SUPER 49 | variable = $variable 50 | keyword = str, 1, 4, true 51 | monitor=DP-1,1378x1024@60,0x0,1 52 | 53 | --- 54 | 55 | (configuration 56 | (assignment 57 | (name) 58 | (boolean)) 59 | (assignment 60 | (name) 61 | (number)) 62 | (assignment 63 | (name) 64 | (vec2 65 | (number) 66 | (number))) 67 | (assignment 68 | (name) 69 | (string)) 70 | (assignment 71 | (name) 72 | (color 73 | (legacy_hex 74 | (hex)))) 75 | (assignment 76 | (name) 77 | (color 78 | (rgb 79 | (hex)))) 80 | (assignment 81 | (name) 82 | (color 83 | (rgb 84 | (number_tuple 85 | (number) 86 | (number) 87 | (number) 88 | (number))))) 89 | (assignment 90 | (name) 91 | (gradient 92 | (color 93 | (rgb 94 | (hex))) 95 | (color 96 | (legacy_hex 97 | (hex))) 98 | (angle))) 99 | (assignment 100 | (name) 101 | (mod)) 102 | (assignment 103 | (name) 104 | (variable)) 105 | (keyword 106 | (name) 107 | (params 108 | (string) 109 | (number) 110 | (number) 111 | (boolean))) 112 | (keyword 113 | (name) 114 | (params 115 | (string) 116 | (display 117 | (position 118 | (number) 119 | (number)) 120 | (number)) 121 | (position 122 | (number) 123 | (number)) 124 | (number)))) 125 | 126 | ================================================= 127 | Keyword `exec` 128 | ================================================= 129 | 130 | exec-once = command 131 | execr-once = command 132 | exec = command 133 | execr = command 134 | exec-shutdown = command 135 | 136 | ------------------------------------------------- 137 | 138 | (configuration 139 | (exec 140 | (string)) 141 | (exec 142 | (string)) 143 | (exec 144 | (string)) 145 | (exec 146 | (string)) 147 | (exec 148 | (string))) 149 | -------------------------------------------------------------------------------- /test/highlight/config.conf: -------------------------------------------------------------------------------- 1 | $variable = SUPER 2 | # ^variable 3 | # ^operator 4 | # ^constant 5 | 6 | exec-once = hyprpaper & waybar 7 | # ^keyword 8 | 9 | monitor=DP-1,1378x1024@60,0x0,1 10 | # ^number 11 | # ^number 12 | 13 | decoration { 14 | # ^module 15 | # ^punctuation.bracket 16 | col.shadow = rgba(1a1a1aee) 17 | # ^property 18 | # ^function.builtin 19 | # ^punctuation.bracket 20 | # ^number 21 | } 22 | 23 | section:device { 24 | # ^type 25 | flag = true 26 | # ^boolean 27 | } 28 | -------------------------------------------------------------------------------- /tree-sitter.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/config.schema.json", 3 | "grammars": [ 4 | { 5 | "name": "hyprlang", 6 | "camelcase": "Hyprlang", 7 | "scope": "source.hypr", 8 | "path": ".", 9 | "file-types": [ 10 | "conf" 11 | ], 12 | "highlights": "queries/hyprlang/highlights.scm", 13 | "injections": "queries/hyprlang/injections.scm" 14 | } 15 | ], 16 | "metadata": { 17 | "version": "3.1.0", 18 | "license": "MIT", 19 | "description": "hyprlang grammar for the tree-sitter parsing library", 20 | "authors": [ 21 | { 22 | "name": "LIOKA Ranarison Fiderana" 23 | } 24 | ], 25 | "links": { 26 | "repository": "https://github.com/tree-sitter-grammars/tree-sitter-hyprlang" 27 | } 28 | }, 29 | "bindings": { 30 | "c": true, 31 | "go": true, 32 | "node": true, 33 | "python": true, 34 | "rust": true, 35 | "swift": true 36 | } 37 | } 38 | --------------------------------------------------------------------------------