Add 'vendored_parsers/tree-sitter-godot-resource/' from commit '302c1895f54bf74d53a08572f7b26a6614209adc'

git-subtree-dir: vendored_parsers/tree-sitter-godot-resource
git-subtree-mainline: 6301ddf030
git-subtree-split: 302c1895f5
pull/904/head
fish 2025-10-13 14:16:38 +07:00
commit 9d2a4191e5
55 changed files with 6536 additions and 0 deletions

@ -0,0 +1,46 @@
root = true
[*]
charset = utf-8
[*.{json,toml,yml,gyp}]
indent_style = space
indent_size = 2
[*.js]
indent_style = space
indent_size = 2
[*.scm]
indent_style = space
indent_size = 2
[*.{c,cc,h}]
indent_style = space
indent_size = 4
[*.rs]
indent_style = space
indent_size = 4
[*.{py,pyi}]
indent_style = space
indent_size = 4
[*.swift]
indent_style = space
indent_size = 4
[*.go]
indent_style = tab
indent_size = 8
[Makefile]
indent_style = tab
indent_size = 8
[parser.c]
indent_size = 2
[{alloc,array,parser}.h]
indent_size = 2

@ -0,0 +1,37 @@
* text=auto eol=lf
# Generated source files
src/*.json linguist-generated
src/parser.c linguist-generated
src/tree_sitter/* linguist-generated
# C bindings
bindings/c/* linguist-generated
CMakeLists.txt linguist-generated
Makefile linguist-generated
# Rust bindings
bindings/rust/* linguist-generated
Cargo.toml linguist-generated
Cargo.lock linguist-generated
# Node.js bindings
bindings/node/* linguist-generated
binding.gyp linguist-generated
package.json linguist-generated
package-lock.json linguist-generated
# Python bindings
bindings/python/** linguist-generated
setup.py linguist-generated
pyproject.toml linguist-generated
# Go bindings
bindings/go/* linguist-generated
go.mod linguist-generated
go.sum linguist-generated
# Swift bindings
bindings/swift/** linguist-generated
Package.swift linguist-generated
Package.resolved linguist-generated

@ -0,0 +1,73 @@
# This workflow will
# - test tree sitter grammar
# - upload build native binaries as an artifact for each major platform
# - download artifacts for each major platform and bundle them to be published
# to npm
# when a new version tag is pushed to the master branch.
name: Test Build Publish
on:
push:
tags: [v*]
jobs:
build_native_binaries:
strategy:
matrix:
# Use macos-14 for arm, however the artifact upload name conflicts with
# macos-latest. There's probably a way to crossbuild for arm with
# prebuildify.
os: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
# Why is npm only occassionally installing peer dependencies?
# I cannot get consistent peer dependency installs with the same command runs.
# Should I always explicitly run npm i tree-sitter? The general consensus is yes.
# But then, why does it install peer deps sometimes?
- run: |
node --version
npm --version
- run: npm ci --include=peer --include=optional --include=dev
- run: npm i tree-sitter
- run: npm run versions
- run: npm test
- run: npm run prebuild
# upload-artifact@v4 requires each artifact name to be unique.
- uses: actions/upload-artifact@v4
with:
name: prebuilds-${{ matrix.os }}
path: prebuilds
retention-days: 1
publish_npm:
needs: build_native_binaries
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
# https://docs.github.com/en/actions/use-cases-and-examples/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry
# https://github.com/actions/setup-node/issues/342
# This is required to publish to npm.
registry-url: 'https://registry.npmjs.org'
- run: |
node --version
npm --version
- run: npm ci
# Download all artifacts and merge into prebuilds dir.
- uses: actions/download-artifact@v4
with:
path: prebuilds
pattern: prebuilds-*
merge-multiple: true
- run: ls -R prebuilds
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

@ -0,0 +1,22 @@
name: Test
on:
push:
paths:
- 'grammar.js'
- 'corpus/**'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- run: |
node --version
npm --version
- run: npm ci --include=dev --include=optional --include=peer
- run: npm test

@ -0,0 +1,41 @@
# Rust artifacts
target/
# Node artifacts
build/
prebuilds/
node_modules/
# Swift artifacts
.build/
# Go artifacts
_obj/
# Python artifacts
.venv/
dist/
*.egg-info
*.whl
# C artifacts
*.a
*.so
*.so.*
*.dylib
*.dll
*.pc
parser.exp
parser.lib
parser.obj
scanner.obj
# Grammar volatiles
*.wasm
*.obj
*.o
# Archives
*.tar.gz
*.tgz
*.zip

@ -0,0 +1,8 @@
corpus
examples
build
script
parser.exp
parser.lib
parser.obj
scanner.obj

@ -0,0 +1,58 @@
cmake_minimum_required(VERSION 3.13)
project(tree-sitter-godot-resource
VERSION "0.7.0"
DESCRIPTION "Grammar for the Godot game engine's resource format."
HOMEPAGE_URL "https://github.com/prestonknopp/tree-sitter-godot-resource"
LANGUAGES C)
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF)
set(TREE_SITTER_ABI_VERSION 14 CACHE STRING "Tree-sitter ABI version")
if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$")
unset(TREE_SITTER_ABI_VERSION CACHE)
message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer")
endif()
find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI")
add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json"
COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json
--abi=${TREE_SITTER_ABI_VERSION}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating parser.c")
add_library(tree-sitter-godot-resource src/parser.c)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c)
target_sources(tree-sitter-godot-resource PRIVATE src/scanner.c)
endif()
target_include_directories(tree-sitter-godot-resource PRIVATE src)
target_compile_definitions(tree-sitter-godot-resource PRIVATE
$<$<BOOL:${TREE_SITTER_REUSE_ALLOCATOR}>:TREE_SITTER_REUSE_ALLOCATOR>
$<$<CONFIG:Debug>:TREE_SITTER_DEBUG>)
set_target_properties(tree-sitter-godot-resource
PROPERTIES
C_STANDARD 11
POSITION_INDEPENDENT_CODE ON
SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}"
DEFINE_SYMBOL "")
configure_file(bindings/c/tree-sitter-godot-resource.pc.in
"${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-godot-resource.pc" @ONLY)
include(GNUInstallDirs)
install(FILES bindings/c/tree-sitter-godot-resource.h
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-godot-resource.pc"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig")
install(TARGETS tree-sitter-godot-resource
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
add_custom_target(ts-test "${TREE_SITTER_CLI}" test
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "tree-sitter test")

@ -0,0 +1,27 @@
[package]
name = "tree-sitter-godot-resource"
description = "Grammar for the Godot game engine's resource format."
version = "0.7.0"
authors = ["Preston Knopp"]
license = "MIT"
readme = "README.md"
keywords = ["incremental", "parsing", "tree-sitter", "godot-resource"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/prestonknopp/tree-sitter-godot-resource"
edition = "2021"
autoexamples = false
build = "bindings/rust/build.rs"
include = ["bindings/rust/*", "grammar.js", "queries/*", "src/*", "tree-sitter.json"]
[lib]
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter-language = "0.1"
[build-dependencies]
cc = "1.1.22"
[dev-dependencies]
tree-sitter = "0.24.6"

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Preston Knopp
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,94 @@
ifeq ($(OS),Windows_NT)
$(error Windows is not supported)
endif
LANGUAGE_NAME := tree-sitter-godot-resource
HOMEPAGE_URL := https://github.com/prestonknopp/tree-sitter-godot-resource
VERSION := 0.7.0
# repository
SRC_DIR := src
TS ?= tree-sitter
# install directory layout
PREFIX ?= /usr/local
INCLUDEDIR ?= $(PREFIX)/include
LIBDIR ?= $(PREFIX)/lib
PCLIBDIR ?= $(LIBDIR)/pkgconfig
# source/object files
PARSER := $(SRC_DIR)/parser.c
EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c))
OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS))
# flags
ARFLAGS ?= rcs
override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC
# ABI versioning
SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER))
SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION)))
# OS-specific bits
ifeq ($(shell uname),Darwin)
SOEXT = dylib
SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT)
SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT)
LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks
else
SOEXT = so
SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR)
SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR)
LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER)
endif
ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),)
PCLIBDIR := $(PREFIX)/libdata/pkgconfig
endif
all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc
lib$(LANGUAGE_NAME).a: $(OBJS)
$(AR) $(ARFLAGS) $@ $^
lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS)
$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
ifneq ($(STRIP),)
$(STRIP) $@
endif
$(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in
sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \
-e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \
-e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \
-e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \
-e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \
-e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@
$(PARSER): $(SRC_DIR)/grammar.json
$(TS) generate $^
install: all
install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'
install -m644 bindings/c/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h
install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a
install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER)
ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR)
ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT)
uninstall:
$(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \
'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \
'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \
'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \
'$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \
'$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
clean:
$(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT)
test:
$(TS) test
.PHONY: all install uninstall clean test

@ -0,0 +1,37 @@
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "TreeSitterGodotResource",
products: [
.library(name: "TreeSitterGodotResource", targets: ["TreeSitterGodotResource"]),
],
dependencies: [
.package(url: "https://github.com/ChimeHQ/SwiftTreeSitter", from: "0.8.0"),
],
targets: [
.target(
name: "TreeSitterGodotResource",
dependencies: [],
path: ".",
sources: [
"src/parser.c",
"src/scanner.c",
],
resources: [
.copy("queries")
],
publicHeadersPath: "bindings/swift",
cSettings: [.headerSearchPath("src")]
),
.testTarget(
name: "TreeSitterGodotResourceTests",
dependencies: [
"SwiftTreeSitter",
"TreeSitterGodotResource",
],
path: "bindings/swift/TreeSitterGodotResourceTests"
)
],
cLanguageStandard: .c11
)

@ -0,0 +1,5 @@
# tree-sitter-godot-resource
Godot resource grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter).
Parses tscn and tres files.

@ -0,0 +1,31 @@
{
"targets": [
{
"target_name": "tree_sitter_godot_resource_binding",
"dependencies": [
"<!(node -p \"require('node-addon-api').targets\"):node_addon_api_except",
],
"include_dirs": [
"src",
],
"sources": [
"bindings/node/binding.cc",
"src/parser.c",
# NOTE: if your language has an external scanner, add it here.
"src/scanner.c",
],
"conditions": [
["OS!='win'", {
"cflags_c": [
"-std=c11",
],
}, { # OS == "win"
"cflags_c": [
"/std:c11",
"/utf-8",
],
}],
],
}
]
}

@ -0,0 +1,16 @@
#ifndef TREE_SITTER_GODOT_RESOURCE_H_
#define TREE_SITTER_GODOT_RESOURCE_H_
typedef struct TSLanguage TSLanguage;
#ifdef __cplusplus
extern "C" {
#endif
const TSLanguage *tree_sitter_godot_resource(void);
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_GODOT_RESOURCE_H_

@ -0,0 +1,10 @@
prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: tree-sitter-godot-resource
Description: @PROJECT_DESCRIPTION@
URL: @PROJECT_HOMEPAGE_URL@
Version: @PROJECT_VERSION@
Libs: -L${libdir} -ltree-sitter-godot-resource
Cflags: -I${includedir}

@ -0,0 +1,14 @@
package tree_sitter_godot_resource
// #cgo CFLAGS: -std=c11 -fPIC
// #include "../../src/parser.c"
// // NOTE: if your language has an external scanner, add it here.
// #include "../../src/scanner.c"
import "C"
import "unsafe"
// Get the tree-sitter Language for this grammar.
func Language() unsafe.Pointer {
return unsafe.Pointer(C.tree_sitter_godot_resource())
}

@ -0,0 +1,15 @@
package tree_sitter_godot_resource_test
import (
"testing"
tree_sitter "github.com/tree-sitter/go-tree-sitter"
tree_sitter_godot_resource "github.com/prestonknopp/tree-sitter-godot-resource/bindings/go"
)
func TestCanLoadGrammar(t *testing.T) {
language := tree_sitter.NewLanguage(tree_sitter_godot_resource.Language())
if language == nil {
t.Errorf("Error loading GodotResource grammar")
}
}

@ -0,0 +1,9 @@
# This module, i.e. the nim bindings, can be placed anywhere in your nim project
# or kept in the bindings directory.
#
# However the following assumes that when compiling your project or main module that
# "tree-sitter-godot-resource/" is accessible from the current working directory.
{.passC: "-Itree-sitter-godot-resource/src".}
{.compile: "tree-sitter-godot-resource/src/parser.c".}
{.compile: "tree-sitter-godot-resource/src/scanner.c".}
proc tree_sitter_godot_resource*(): pointer {.importc.}

@ -0,0 +1,20 @@
#include <napi.h>
typedef struct TSLanguage TSLanguage;
extern "C" TSLanguage *tree_sitter_godot_resource();
// "tree-sitter", "language" hashed with BLAKE2
const napi_type_tag LANGUAGE_TYPE_TAG = {
0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports["name"] = Napi::String::New(env, "godot_resource");
auto language = Napi::External<TSLanguage>::New(env, tree_sitter_godot_resource());
language.TypeTag(&LANGUAGE_TYPE_TAG);
exports["language"] = language;
return exports;
}
NODE_API_MODULE(tree_sitter_godot_resource_binding, Init)

@ -0,0 +1,9 @@
const assert = require("node:assert");
const { test } = require("node:test");
const Parser = require("tree-sitter");
test("can load grammar", () => {
const parser = new Parser();
assert.doesNotThrow(() => parser.setLanguage(require(".")));
});

@ -0,0 +1,28 @@
type BaseNode = {
type: string;
named: boolean;
};
type ChildNode = {
multiple: boolean;
required: boolean;
types: BaseNode[];
};
type NodeInfo =
| (BaseNode & {
subtypes: BaseNode[];
})
| (BaseNode & {
fields: { [name: string]: ChildNode };
children: ChildNode[];
});
type Language = {
name: string;
language: unknown;
nodeTypeInfo: NodeInfo[];
};
declare const language: Language;
export = language;

@ -0,0 +1,11 @@
const root = require("path").join(__dirname, "..", "..");
module.exports =
typeof process.versions.bun === "string"
// Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time
? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-godot-resource.node`)
: require("node-gyp-build")(root);
try {
module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}

@ -0,0 +1,11 @@
from unittest import TestCase
import tree_sitter, tree_sitter_godot_resource
class TestLanguage(TestCase):
def test_can_load_grammar(self):
try:
tree_sitter.Language(tree_sitter_godot_resource.language())
except Exception:
self.fail("Error loading GodotResource grammar")

@ -0,0 +1,42 @@
"""Grammar for the Godot game engine's resource format."""
from importlib.resources import files as _files
from ._binding import language
def _get_query(name, file):
query = _files(f"{__package__}.queries") / file
globals()[name] = query.read_text()
return globals()[name]
def __getattr__(name):
# NOTE: uncomment these to include any queries that this grammar contains:
# if name == "HIGHLIGHTS_QUERY":
# return _get_query("HIGHLIGHTS_QUERY", "highlights.scm")
# if name == "INJECTIONS_QUERY":
# return _get_query("INJECTIONS_QUERY", "injections.scm")
# if name == "LOCALS_QUERY":
# return _get_query("LOCALS_QUERY", "locals.scm")
# if name == "TAGS_QUERY":
# return _get_query("TAGS_QUERY", "tags.scm")
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
__all__ = [
"language",
# "HIGHLIGHTS_QUERY",
# "INJECTIONS_QUERY",
# "LOCALS_QUERY",
# "TAGS_QUERY",
]
def __dir__():
return sorted(__all__ + [
"__all__", "__builtins__", "__cached__", "__doc__", "__file__",
"__loader__", "__name__", "__package__", "__path__", "__spec__",
])

@ -0,0 +1,10 @@
from typing import Final
# NOTE: uncomment these to include any queries that this grammar contains:
# HIGHLIGHTS_QUERY: Final[str]
# INJECTIONS_QUERY: Final[str]
# LOCALS_QUERY: Final[str]
# TAGS_QUERY: Final[str]
def language() -> object: ...

@ -0,0 +1,27 @@
#include <Python.h>
typedef struct TSLanguage TSLanguage;
TSLanguage *tree_sitter_godot_resource(void);
static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
return PyCapsule_New(tree_sitter_godot_resource(), "tree_sitter.Language", NULL);
}
static PyMethodDef methods[] = {
{"language", _binding_language, METH_NOARGS,
"Get the tree-sitter language for this grammar."},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "_binding",
.m_doc = NULL,
.m_size = -1,
.m_methods = methods
};
PyMODINIT_FUNC PyInit__binding(void) {
return PyModule_Create(&module);
}

@ -0,0 +1,20 @@
fn main() {
let src_dir = std::path::Path::new("src");
let mut c_config = cc::Build::new();
c_config.std("c11").include(src_dir);
#[cfg(target_env = "msvc")]
c_config.flag("-utf-8");
let parser_path = src_dir.join("parser.c");
c_config.file(&parser_path);
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
// NOTE: if your language uses an external scanner, uncomment this block:
let scanner_path = src_dir.join("scanner.c");
c_config.file(&scanner_path);
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
c_config.compile("tree-sitter-godot-resource");
}

@ -0,0 +1,53 @@
//! This crate provides GodotResource language support for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [LANGUAGE][] constant to add this language to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! let code = r#"
//! "#;
//! let mut parser = tree_sitter::Parser::new();
//! let language = tree_sitter_godot_resource::LANGUAGE;
//! parser
//! .set_language(&language.into())
//! .expect("Error loading GodotResource parser");
//! let tree = parser.parse(code, None).unwrap();
//! assert!(!tree.root_node().has_error());
//! ```
//!
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/
use tree_sitter_language::LanguageFn;
extern "C" {
fn tree_sitter_godot_resource() -> *const ();
}
/// The tree-sitter [`LanguageFn`][LanguageFn] for this grammar.
///
/// [LanguageFn]: https://docs.rs/tree-sitter-language/*/tree_sitter_language/struct.LanguageFn.html
pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_godot_resource) };
/// The content of the [`node-types.json`][] file for this grammar.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const NODE_TYPES: &str = include_str!("../../src/node-types.json");
// NOTE: uncomment these to include any queries that this grammar contains:
// pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm");
// pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm");
// pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm");
// pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm");
#[cfg(test)]
mod tests {
#[test]
fn test_can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&super::LANGUAGE.into())
.expect("Error loading GodotResource parser");
}
}

@ -0,0 +1,16 @@
#ifndef TREE_SITTER_GODOT_RESOURCE_H_
#define TREE_SITTER_GODOT_RESOURCE_H_
typedef struct TSLanguage TSLanguage;
#ifdef __cplusplus
extern "C" {
#endif
const TSLanguage *tree_sitter_godot_resource(void);
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_GODOT_RESOURCE_H_

@ -0,0 +1,12 @@
import XCTest
import SwiftTreeSitter
import TreeSitterGodotResource
final class TreeSitterGodotResourceTests: XCTestCase {
func testCanLoadGrammar() throws {
let parser = Parser()
let language = Language(language: tree_sitter_godot_resource())
XCTAssertNoThrow(try parser.setLanguage(language),
"Error loading GodotResource grammar")
}
}

@ -0,0 +1,250 @@
[gd_scene load_steps=10 format=2]
[ext_resource path="res://scripts/NodeStateMachine.gd" type="Script" id=1]
[ext_resource path="res://phases/farming_phase.gd" type="Script" id=2]
[ext_resource path="res://phases/defending_phase.gd" type="Script" id=3]
[ext_resource path="res://phases/spawner.gd" type="Script" id=4]
[ext_resource path="res://entities/enemy/enemy.tscn" type="PackedScene" id=5]
[ext_resource path="res://phases/upgrading_phase.gd" type="Script" id=6]
[ext_resource path="res://farm/farm.tscn" type="PackedScene" id=7]
[ext_resource path="res://entities/player/player.tscn" type="PackedScene" id=8]
[ext_resource path="res://forest_ambiance.ogg" type="AudioStream" id=9]
[node name="main" type="Node"]
[node name="game" type="Node2D" parent="."]
__meta__ = {
"_edit_lock_": true
}
[node name="phases" type="Node" parent="game"]
script = ExtResource( 1 )
starting_state = 0
[node name="farming" type="Node" parent="game/phases"]
editor/display_folded = true
script = ExtResource( 2 )
[node name="farming_label" type="Label" parent="game/phases/farming"]
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 63.0
margin_bottom = 14.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "farming"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="ProgressBar" type="ProgressBar" parent="game/phases/farming"]
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 1.0
margin_top = 19.0
margin_right = 237.0
margin_bottom = 33.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 0
min_value = 0.0
max_value = 5.0
step = 0.0
page = 0.0
value = 0.0
exp_edit = false
rounded = false
allow_greater = false
allow_lesser = false
percent_visible = true
[node name="defending" type="Node" parent="game/phases"]
editor/display_folded = true
script = ExtResource( 3 )
[node name="defending_label" type="Label" parent="game/phases/defending"]
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 40.0
margin_bottom = 14.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "defending"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="spawner" type="Node" parent="game/phases/defending"]
script = ExtResource( 4 )
count = 20
over_time = 20.0
enemy_scene = ExtResource( 5 )
[node name="spawn_timer" type="Timer" parent="game/phases/defending/spawner"]
process_mode = 1
wait_time = 1.0
one_shot = true
autostart = false
[node name="upgrading" type="Node" parent="game/phases"]
editor/display_folded = true
script = ExtResource( 6 )
[node name="CanvasLayer" type="CanvasLayer" parent="game/phases/upgrading"]
layer = 1
offset = Vector2( 0, 0 )
rotation = 0.0
scale = Vector2( 1, 1 )
transform = Transform2D( 1, 0, 0, 1, 0, 0 )
[node name="upgrading_label" type="Label" parent="game/phases/upgrading/CanvasLayer"]
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 63.0
margin_bottom = 14.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "upgrading"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="upgrade_dialog" type="AcceptDialog" parent="game/phases/upgrading/CanvasLayer"]
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 20.0
margin_top = 40.0
margin_right = -20.0
margin_bottom = -20.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
popup_exclusive = false
window_title = "Upgrade"
resizable = false
dialog_hide_on_ok = true
[node name="VBoxContainer" type="VBoxContainer" parent="game/phases/upgrading/CanvasLayer/upgrade_dialog"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 8.0
margin_top = 8.0
margin_right = 976.0
margin_bottom = 480.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
alignment = 0
[node name="upgrade_plot_butt" type="Button" parent="game/phases/upgrading/CanvasLayer/upgrade_dialog/VBoxContainer"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 968.0
margin_bottom = 20.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "upgrade plot"
flat = false
align = 1
[node name="buy_seeds_butt" type="Button" parent="game/phases/upgrading/CanvasLayer/upgrade_dialog/VBoxContainer"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 24.0
margin_right = 968.0
margin_bottom = 44.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
focus_mode = 2
mouse_filter = 0
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
toggle_mode = false
enabled_focus_mode = 2
shortcut = null
group = null
text = "buy seeds"
flat = false
align = 1
[node name="farm" parent="game" instance=ExtResource( 7 )]
[node name="player" parent="game" instance=ExtResource( 8 )]
position = Vector2( 532.068, 267.483 )
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="game"]
stream = ExtResource( 9 )
volume_db = 0.0
pitch_scale = 1.0
autoplay = true
stream_paused = false
mix_target = 0
bus = "Master"
[connection signal="entered" from="game/phases/farming" to="game/phases/farming/ProgressBar" method="show"]
[connection signal="entered" from="game/phases/farming" to="game/phases/farming/farming_label" method="show"]
[connection signal="exited" from="game/phases/farming" to="game/phases/farming/ProgressBar" method="hide"]
[connection signal="exited" from="game/phases/farming" to="game/phases/farming/farming_label" method="hide"]
[connection signal="entered" from="game/phases/defending" to="game/phases/defending/defending_label" method="show"]
[connection signal="exited" from="game/phases/defending" to="game/phases/defending/defending_label" method="hide"]
[connection signal="spawns_dead" from="game/phases/defending/spawner" to="game/phases/defending" method="_on_spawner_spawns_dead"]
[connection signal="timeout" from="game/phases/defending/spawner/spawn_timer" to="game/phases/defending/spawner" method="_on_spawn_timer_timeout"]
[connection signal="entered" from="game/phases/upgrading" to="game/phases/upgrading/CanvasLayer/upgrading_label" method="show"]
[connection signal="entered" from="game/phases/upgrading" to="game/phases/upgrading/CanvasLayer/upgrade_dialog" method="popup_centered"]
[connection signal="exited" from="game/phases/upgrading" to="game/phases/upgrading/CanvasLayer/upgrading_label" method="hide"]
[connection signal="confirmed" from="game/phases/upgrading/CanvasLayer/upgrade_dialog" to="game/phases/upgrading" method="_on_AcceptDialog_confirmed"]
[connection signal="pressed" from="game/phases/upgrading/CanvasLayer/upgrade_dialog/VBoxContainer/upgrade_plot_butt" to="game/phases/upgrading" method="_on_upgrade_plot_butt_pressed"]
[connection signal="pressed" from="game/phases/upgrading/CanvasLayer/upgrade_dialog/VBoxContainer/upgrade_plot_butt" to="game/farm" method="upgrade_plot"]
[connection signal="pressed" from="game/phases/upgrading/CanvasLayer/upgrade_dialog/VBoxContainer/buy_seeds_butt" to="game/phases/upgrading" method="_on_buy_seeds_butt_pressed"]

@ -0,0 +1,193 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=4
_global_script_classes=[ {
"base": "Reference",
"class": "CellInfo",
"language": "GDScript",
"path": "res://farm/cell_info.gd"
}, {
"base": "Resource",
"class": "CellOrientation",
"language": "GDScript",
"path": "res://farm/cell_orientation.gd"
}, {
"base": "Reference",
"class": "CellVariant",
"language": "GDScript",
"path": "res://farm/cell_variant.gd"
}, {
"base": "Node",
"class": "Component",
"language": "GDScript",
"path": "res://entities/Component.gd"
}, {
"base": "Node",
"class": "ComponentRegistration",
"language": "GDScript",
"path": "res://scripts/ComponentRegistration.gd"
}, {
"base": "Node",
"class": "HealthNode",
"language": "GDScript",
"path": "res://entities/health.gd"
}, {
"base": "Reference",
"class": "InventoryItem",
"language": "GDScript",
"path": "res://entities/player/inventory/inventory_item.gd"
}, {
"base": "TileMap",
"class": "LandMap",
"language": "GDScript",
"path": "res://farm/land_map.gd"
}, {
"base": "Resource",
"class": "MatrixRule",
"language": "GDScript",
"path": "res://farm/resources/sources/MatrixRule.gd"
}, {
"base": "Resource",
"class": "MatrixRuleSet",
"language": "GDScript",
"path": "res://farm/resources/sources/MatrixRuleSet.gd"
}, {
"base": "Node",
"class": "NodeStateMachine",
"language": "GDScript",
"path": "res://scripts/NodeStateMachine.gd"
}, {
"base": "Node",
"class": "PivotRotator",
"language": "GDScript",
"path": "res://entities/player/pivot_rotator.gd"
}, {
"base": "Node2D",
"class": "Plant",
"language": "GDScript",
"path": "res://botany/Plant.gd"
}, {
"base": "Node",
"class": "stc",
"language": "GDScript",
"path": "res://scripts/static.gd"
} ]
_global_script_class_icons={
"CellInfo": "",
"CellOrientation": "",
"CellVariant": "",
"Component": "",
"ComponentRegistration": "",
"HealthNode": "",
"InventoryItem": "",
"LandMap": "",
"MatrixRule": "",
"MatrixRuleSet": "",
"NodeStateMachine": "",
"PivotRotator": "",
"Plant": "",
"stc": ""
}
[application]
config/name="Farmer Shooter"
run/main_scene="res://main.tscn"
config/icon="res://icon.png"
[debug]
gdscript/warnings/enable=false
gdscript/warnings/unused_variable=false
gdscript/warnings/unused_class_variable=false
gdscript/warnings/unused_argument=false
gdscript/warnings/narrowing_conversion=false
gdscript/warnings/unused_signal=false
[display]
window/size/height=576
window/stretch/mode="2d"
[importer_defaults]
texture={
"compress/bptc_ldr": 0,
"compress/hdr_mode": 0,
"compress/lossy_quality": 0.7,
"compress/mode": 0,
"compress/normal_map": 0,
"detect_3d": false,
"flags/anisotropic": false,
"flags/filter": false,
"flags/mipmaps": false,
"flags/repeat": 0,
"flags/srgb": 2,
"process/HDR_as_SRGB": false,
"process/fix_alpha_border": true,
"process/invert_color": false,
"process/premult_alpha": false,
"size_limit": 0,
"stream": false,
"svg/scale": 1.0
}
ogg_vorbis={
"loop": false,
"loop_offset": 0
}
[input]
movement_left={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null)
]
}
movement_right={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":69,"unicode":0,"echo":false,"script":null)
]
}
movement_up={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":44,"unicode":0,"echo":false,"script":null)
]
}
movement_down={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":79,"unicode":0,"echo":false,"script":null)
]
}
inventory_left={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":39,"unicode":0,"echo":false,"script":null)
]
}
inventory_right={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":46,"unicode":0,"echo":false,"script":null)
]
}
action={
"deadzone": 0.5,
"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
]
}
[layer_names]
2d_physics/layer_1="player"
2d_physics/layer_2="enemies"
2d_physics/layer_3="farms"
2d_physics/layer_4="pickups"
[rendering]
environment/default_environment="res://default_env.tres"

@ -0,0 +1,4 @@
[node type="Node"]
s = "hello
\"My World\" world"
other = "Okay"

@ -0,0 +1,5 @@
module github.com/prestonknopp/tree-sitter-godot-resource
go 1.22
require github.com/tree-sitter/go-tree-sitter v0.24.0

@ -0,0 +1,127 @@
module.exports = grammar({
name: "godot_resource",
word: ($) => $._identifier,
extras: ($) => [$.comment, /[\s\uFEFF\u2060\u200B]|\\\r?\n/],
externals: ($) => [$.string],
rules: {
resource: ($) => seq(repeat($.property), repeat($.section)),
// -----------------------------------------------------------------------------
// - Atoms -
// -----------------------------------------------------------------------------
_identifier: ($) => /[a-zA-Z_][a-zA-Z_0-9]*/,
identifier: ($) => $._identifier,
comment: ($) => token(seq(";", /.*/)),
true: ($) => "true",
false: ($) => "false",
null: ($) => "null",
float: ($) => {
const digits = repeat1(/-?[0-9]+_?/);
const exponent = seq(/[eE][\+-]?/, digits);
return token(
choice(
seq(digits, ".", optional(digits), optional(exponent)),
seq(optional(digits), ".", digits, optional(exponent)),
seq(digits, exponent),
),
);
},
integer: ($) =>
token(
choice(
seq(choice("0x", "0X"), repeat1(/_?[A-Fa-f0-9]+/)),
seq(choice("0o", "0O"), repeat1(/_?[0-7]+/)),
seq(choice("0b", "0B"), repeat1(/_?[0-1]+/)),
repeat1(/-?[0-9]+_?/),
),
),
string_name: ($) => seq("&", alias($.string, "string")),
// -----------------------------------------------------------------------------
// - Compound -
// -----------------------------------------------------------------------------
_value: ($) =>
choice(
$.float,
$.integer,
$.string,
$.string_name,
$.true,
$.false,
$.null,
$.dictionary,
$.array,
$.constructor,
$.identifier,
),
// -----------------------------------------------------------------------------
// - Sections -
// -----------------------------------------------------------------------------
// e.g.
// [gd_scene load_steps=10 format=2]
// [node name="main" type="Node"]
section: ($) =>
seq(
"[",
$.identifier,
optional($._attributes),
"]",
optional($._properties),
),
// e.g.
// name="main"
// id=1
_attributes: ($) => repeat1($.attribute),
attribute: ($) => seq($.identifier, "=", $._value),
// e.g.
// script = ExtResource( 1 )
// 0/texture = ExtResource( 2 )
_properties: ($) => repeat1($.property),
property: ($) => seq($.path, "=", $._value),
path: ($) => /[a-zA-Z_0-9][a-zA-Z_:/0-9]*/,
// -----------------------------------------------------------------------------
// - Data Structs -
// -----------------------------------------------------------------------------
pair: ($) => seq($._value, ":", $._value),
dictionary: ($) => seq("{", optional(commaSep1($.pair)), "}"),
array: ($) => seq("[", optional(commaSep1($._value)), "]"),
// -----------------------------------------------------------------------------
// - Constructor -
// -----------------------------------------------------------------------------
arguments: ($) =>
seq("(", optional(commaSep1(choice($._value, $.pair))), ")"),
// Generic type arguments are parsed as arbitrary values.
// I haven't seen attributes, e.g. "Type.SubType", in the wild. Not sure if resources parse them.
_type_args: ($) => seq("[", commaSep1($._value), "]"),
constructor: ($) =>
prec.right(1, seq($.identifier, optional($._type_args), $.arguments)),
}, // end rules
});
function commaSep1(rule) {
return sep1(rule, ",");
}
function sep1(rule, separator) {
return seq(rule, repeat(seq(separator, rule)));
}

@ -0,0 +1,399 @@
{
"name": "tree-sitter-godot-resource",
"version": "0.7.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "tree-sitter-godot-resource",
"version": "0.7.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"node-addon-api": "^8.3.1",
"node-gyp-build": "^4.8.4"
},
"devDependencies": {
"prebuildify": "^6.0.1",
"prettier": "^3.5.3",
"tree-sitter-cli": "^0.24.7"
},
"peerDependencies": {
"tree-sitter": "^0.21.1"
},
"peerDependenciesMeta": {
"tree-sitter": {
"optional": true
}
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/chownr": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
"dev": true,
"license": "ISC"
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
"dev": true,
"license": "MIT"
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "BSD-3-Clause"
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true,
"license": "ISC"
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
"dev": true,
"license": "MIT"
},
"node_modules/node-abi": {
"version": "3.75.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz",
"integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==",
"dev": true,
"license": "MIT",
"dependencies": {
"semver": "^7.3.5"
},
"engines": {
"node": ">=10"
}
},
"node_modules/node-addon-api": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz",
"integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==",
"license": "MIT",
"engines": {
"node": "^18 || ^20 || >= 21"
}
},
"node_modules/node-gyp-build": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
"license": "MIT",
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/npm-run-path": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz",
"integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==",
"dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/prebuildify": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/prebuildify/-/prebuildify-6.0.1.tgz",
"integrity": "sha512-8Y2oOOateom/s8dNBsGIcnm6AxPmLH4/nanQzL5lQMU+sC0CMhzARZHizwr36pUPLdvBnOkCNQzxg4djuFSgIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"minimist": "^1.2.5",
"mkdirp-classic": "^0.5.3",
"node-abi": "^3.3.0",
"npm-run-path": "^3.1.0",
"pump": "^3.0.0",
"tar-fs": "^2.1.0"
},
"bin": {
"prebuildify": "bin.js"
}
},
"node_modules/prettier": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/pump": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
"dev": true,
"license": "MIT",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dev": true,
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dev": true,
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/tar-fs": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
"integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"chownr": "^1.1.1",
"mkdirp-classic": "^0.5.2",
"pump": "^3.0.0",
"tar-stream": "^2.1.4"
}
},
"node_modules/tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/tree-sitter": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz",
"integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"node-addon-api": "^8.0.0",
"node-gyp-build": "^4.8.0"
}
},
"node_modules/tree-sitter-cli": {
"version": "0.24.7",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.24.7.tgz",
"integrity": "sha512-o4gnE82pVmMMhJbWwD6+I9yr4lXii5Ci5qEQ2pFpUbVy1YiD8cizTJaqdcznA0qEbo7l2OneI1GocChPrI4YGQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"tree-sitter": "cli.js"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true,
"license": "MIT"
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true,
"license": "ISC"
}
}
}

@ -0,0 +1,60 @@
{
"name": "tree-sitter-godot-resource",
"version": "0.7.0",
"description": "Grammar for the Godot game engine's text resource format.",
"repository": "https://github.com/prestonknopp/tree-sitter-godot-resource",
"license": "MIT",
"author": {
"name": "Preston Knopp"
},
"main": "bindings/node",
"types": "bindings/node",
"keywords": [
"incremental",
"parsing",
"tree-sitter",
"godot",
"tscn",
"tres"
],
"files": [
"grammar.js",
"tree-sitter.json",
"binding.gyp",
"prebuilds/**",
"bindings/node/*",
"queries/*",
"src/**",
"*.wasm"
],
"dependencies": {
"node-addon-api": "^8.3.1",
"node-gyp-build": "^4.8.4"
},
"devDependencies": {
"prebuildify": "^6.0.1",
"prettier": "^3.5.3",
"tree-sitter-cli": "^0.24.7"
},
"peerDependencies": {
"tree-sitter": "^0.21.1"
},
"peerDependenciesMeta": {
"tree-sitter": {
"optional": true
}
},
"scripts": {
"install": "node-gyp-build",
"prebuild": "prebuildify --strip -t electron@34.5.5 -t electron@35.3.0 -t electron@36.2.0 -t v20.19.1 -t v22.15.0 -t v23.11.0 -t v24.0.1",
"prestart": "tree-sitter build --wasm",
"start": "tree-sitter playground",
"versions": "node --version && npm --version && tree-sitter --version",
"test": "tree-sitter test && node --test bindings/node/*_test.js",
"generate": "tree-sitter generate",
"genTest": "tree-sitter generate && npm test",
"parse": "tree-sitter parse",
"ts": "tree-sitter",
"format": "prettier -w grammar.js package.json"
}
}

@ -0,0 +1,29 @@
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "tree-sitter-godot-resource"
description = "Grammar for the Godot game engine's resource format."
version = "0.7.0"
keywords = ["incremental", "parsing", "tree-sitter", "godot-resource"]
classifiers = [
"Intended Audience :: Developers",
"Topic :: Software Development :: Compilers",
"Topic :: Text Processing :: Linguistic",
"Typing :: Typed",
]
authors = [{ name = "Preston Knopp" }]
requires-python = ">=3.9"
license.text = "MIT"
readme = "README.md"
[project.urls]
Homepage = "https://github.com/prestonknopp/tree-sitter-godot-resource"
[project.optional-dependencies]
core = ["tree-sitter~=0.22"]
[tool.cibuildwheel]
build = "cp39-*"
build-frontend = "build"

@ -0,0 +1,63 @@
from os.path import isdir, join
from platform import system
from setuptools import Extension, find_packages, setup
from setuptools.command.build import build
from wheel.bdist_wheel import bdist_wheel
class Build(build):
def run(self):
if isdir("queries"):
dest = join(self.build_lib, "tree_sitter_godot_resource", "queries")
self.copy_tree("queries", dest)
super().run()
class BdistWheel(bdist_wheel):
def get_tag(self):
python, abi, platform = super().get_tag()
if python.startswith("cp"):
python, abi = "cp39", "abi3"
return python, abi, platform
setup(
packages=find_packages("bindings/python"),
package_dir={"": "bindings/python"},
package_data={
"tree_sitter_godot_resource": ["*.pyi", "py.typed"],
"tree_sitter_godot_resource.queries": ["*.scm"],
},
ext_package="tree_sitter_godot_resource",
ext_modules=[
Extension(
name="_binding",
sources=[
"bindings/python/tree_sitter_godot_resource/binding.c",
"src/parser.c",
# NOTE: if your language uses an external scanner, add it here.
"src/scanner.c",
],
extra_compile_args=[
"-std=c11",
"-fvisibility=hidden",
] if system() != "Windows" else [
"/std:c11",
"/utf-8",
],
define_macros=[
("Py_LIMITED_API", "0x03090000"),
("PY_SSIZE_T_CLEAN", None),
("TREE_SITTER_HIDE_SYMBOLS", None),
],
include_dirs=["src"],
py_limited_api=True,
)
],
cmdclass={
"build": Build,
"bdist_wheel": BdistWheel
},
zip_safe=False
)

@ -0,0 +1,718 @@
{
"$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json",
"name": "godot_resource",
"word": "_identifier",
"rules": {
"resource": {
"type": "SEQ",
"members": [
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "property"
}
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "section"
}
}
]
},
"_identifier": {
"type": "PATTERN",
"value": "[a-zA-Z_][a-zA-Z_0-9]*"
},
"identifier": {
"type": "SYMBOL",
"name": "_identifier"
},
"comment": {
"type": "TOKEN",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ";"
},
{
"type": "PATTERN",
"value": ".*"
}
]
}
},
"true": {
"type": "STRING",
"value": "true"
},
"false": {
"type": "STRING",
"value": "false"
},
"null": {
"type": "STRING",
"value": "null"
},
"float": {
"type": "TOKEN",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
},
{
"type": "STRING",
"value": "."
},
{
"type": "CHOICE",
"members": [
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
},
{
"type": "BLANK"
}
]
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "PATTERN",
"value": "[eE][\\+-]?"
},
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
}
]
},
{
"type": "BLANK"
}
]
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "."
},
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "PATTERN",
"value": "[eE][\\+-]?"
},
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
}
]
},
{
"type": "BLANK"
}
]
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
},
{
"type": "SEQ",
"members": [
{
"type": "PATTERN",
"value": "[eE][\\+-]?"
},
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
}
]
}
]
}
]
}
},
"integer": {
"type": "TOKEN",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "0x"
},
{
"type": "STRING",
"value": "0X"
}
]
},
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "_?[A-Fa-f0-9]+"
}
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "0o"
},
{
"type": "STRING",
"value": "0O"
}
]
},
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "_?[0-7]+"
}
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "0b"
},
{
"type": "STRING",
"value": "0B"
}
]
},
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "_?[0-1]+"
}
}
]
},
{
"type": "REPEAT1",
"content": {
"type": "PATTERN",
"value": "-?[0-9]+_?"
}
}
]
}
},
"string_name": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "&"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "string"
},
"named": false,
"value": "string"
}
]
},
"_value": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "float"
},
{
"type": "SYMBOL",
"name": "integer"
},
{
"type": "SYMBOL",
"name": "string"
},
{
"type": "SYMBOL",
"name": "string_name"
},
{
"type": "SYMBOL",
"name": "true"
},
{
"type": "SYMBOL",
"name": "false"
},
{
"type": "SYMBOL",
"name": "null"
},
{
"type": "SYMBOL",
"name": "dictionary"
},
{
"type": "SYMBOL",
"name": "array"
},
{
"type": "SYMBOL",
"name": "constructor"
},
{
"type": "SYMBOL",
"name": "identifier"
}
]
},
"section": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "["
},
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_attributes"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "]"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_properties"
},
{
"type": "BLANK"
}
]
}
]
},
"_attributes": {
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "attribute"
}
},
"attribute": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "_value"
}
]
},
"_properties": {
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "property"
}
},
"property": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "path"
},
{
"type": "STRING",
"value": "="
},
{
"type": "SYMBOL",
"name": "_value"
}
]
},
"path": {
"type": "PATTERN",
"value": "[a-zA-Z_0-9][a-zA-Z_:/0-9]*"
},
"pair": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_value"
},
{
"type": "STRING",
"value": ":"
},
{
"type": "SYMBOL",
"name": "_value"
}
]
},
"dictionary": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "pair"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "SYMBOL",
"name": "pair"
}
]
}
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "}"
}
]
},
"array": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "["
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_value"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "SYMBOL",
"name": "_value"
}
]
}
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "]"
}
]
},
"arguments": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_value"
},
{
"type": "SYMBOL",
"name": "pair"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_value"
},
{
"type": "SYMBOL",
"name": "pair"
}
]
}
]
}
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": ")"
}
]
},
"_type_args": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "["
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_value"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "SYMBOL",
"name": "_value"
}
]
}
}
]
},
{
"type": "STRING",
"value": "]"
}
]
},
"constructor": {
"type": "PREC_RIGHT",
"value": 1,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_type_args"
},
{
"type": "BLANK"
}
]
},
{
"type": "SYMBOL",
"name": "arguments"
}
]
}
}
},
"extras": [
{
"type": "SYMBOL",
"name": "comment"
},
{
"type": "PATTERN",
"value": "[\\s\\uFEFF\\u2060\\u200B]|\\\\\\r?\\n"
}
],
"conflicts": [],
"precedences": [],
"externals": [
{
"type": "SYMBOL",
"name": "string"
}
],
"inline": [],
"supertypes": []
}

@ -0,0 +1,488 @@
[
{
"type": "arguments",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "array",
"named": true
},
{
"type": "constructor",
"named": true
},
{
"type": "dictionary",
"named": true
},
{
"type": "false",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "identifier",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "null",
"named": true
},
{
"type": "pair",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_name",
"named": true
},
{
"type": "true",
"named": true
}
]
}
},
{
"type": "array",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "array",
"named": true
},
{
"type": "constructor",
"named": true
},
{
"type": "dictionary",
"named": true
},
{
"type": "false",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "identifier",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "null",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_name",
"named": true
},
{
"type": "true",
"named": true
}
]
}
},
{
"type": "attribute",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "array",
"named": true
},
{
"type": "constructor",
"named": true
},
{
"type": "dictionary",
"named": true
},
{
"type": "false",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "identifier",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "null",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_name",
"named": true
},
{
"type": "true",
"named": true
}
]
}
},
{
"type": "constructor",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "arguments",
"named": true
},
{
"type": "array",
"named": true
},
{
"type": "constructor",
"named": true
},
{
"type": "dictionary",
"named": true
},
{
"type": "false",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "identifier",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "null",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_name",
"named": true
},
{
"type": "true",
"named": true
}
]
}
},
{
"type": "dictionary",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "pair",
"named": true
}
]
}
},
{
"type": "identifier",
"named": true,
"fields": {}
},
{
"type": "pair",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "array",
"named": true
},
{
"type": "constructor",
"named": true
},
{
"type": "dictionary",
"named": true
},
{
"type": "false",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "identifier",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "null",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_name",
"named": true
},
{
"type": "true",
"named": true
}
]
}
},
{
"type": "property",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "array",
"named": true
},
{
"type": "constructor",
"named": true
},
{
"type": "dictionary",
"named": true
},
{
"type": "false",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "identifier",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "null",
"named": true
},
{
"type": "path",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string_name",
"named": true
},
{
"type": "true",
"named": true
}
]
}
},
{
"type": "resource",
"named": true,
"root": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "property",
"named": true
},
{
"type": "section",
"named": true
}
]
}
},
{
"type": "section",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "attribute",
"named": true
},
{
"type": "identifier",
"named": true
},
{
"type": "property",
"named": true
}
]
}
},
{
"type": "string_name",
"named": true,
"fields": {}
},
{
"type": "&",
"named": false
},
{
"type": "(",
"named": false
},
{
"type": ")",
"named": false
},
{
"type": ",",
"named": false
},
{
"type": ":",
"named": false
},
{
"type": "=",
"named": false
},
{
"type": "[",
"named": false
},
{
"type": "]",
"named": false
},
{
"type": "comment",
"named": true
},
{
"type": "false",
"named": true
},
{
"type": "float",
"named": true
},
{
"type": "integer",
"named": true
},
{
"type": "null",
"named": true
},
{
"type": "path",
"named": true
},
{
"type": "string",
"named": true
},
{
"type": "string",
"named": false
},
{
"type": "true",
"named": true
},
{
"type": "{",
"named": false
},
{
"type": "}",
"named": false
}
]

File diff suppressed because it is too large Load Diff

@ -0,0 +1,48 @@
/* Author: Preston Knopp
* Description: Parse multiline double quote strings without state
*/
#include <tree_sitter/parser.h>
#include <wctype.h>
// using wctype::iswspace
enum TokenType {
STRING
};
bool tree_sitter_godot_resource_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
if (!valid_symbols[STRING]) {
return false;
}
while (iswspace(lexer->lookahead)) {
lexer->advance(lexer, true);
}
if (lexer->lookahead != '"') {
return false;
}
uint32_t last_char = '"';
lexer->advance(lexer, false);
while (lexer->lookahead) {
if (last_char != '\\' && lexer->lookahead == '"') {
lexer->advance(lexer, false);
lexer->result_symbol = STRING;
return true;
}
last_char = lexer->lookahead;
lexer->advance(lexer, false);
}
return false;
}
void *tree_sitter_godot_resource_external_scanner_create() { return NULL; }
unsigned tree_sitter_godot_resource_external_scanner_serialize(void *payload, char *buffer) { return 0; }
void tree_sitter_godot_resource_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {}
void tree_sitter_godot_resource_external_scanner_destroy(void *payload) {}

@ -0,0 +1,54 @@
#ifndef TREE_SITTER_ALLOC_H_
#define TREE_SITTER_ALLOC_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
// Allow clients to override allocation functions
#ifdef TREE_SITTER_REUSE_ALLOCATOR
extern void *(*ts_current_malloc)(size_t size);
extern void *(*ts_current_calloc)(size_t count, size_t size);
extern void *(*ts_current_realloc)(void *ptr, size_t size);
extern void (*ts_current_free)(void *ptr);
#ifndef ts_malloc
#define ts_malloc ts_current_malloc
#endif
#ifndef ts_calloc
#define ts_calloc ts_current_calloc
#endif
#ifndef ts_realloc
#define ts_realloc ts_current_realloc
#endif
#ifndef ts_free
#define ts_free ts_current_free
#endif
#else
#ifndef ts_malloc
#define ts_malloc malloc
#endif
#ifndef ts_calloc
#define ts_calloc calloc
#endif
#ifndef ts_realloc
#define ts_realloc realloc
#endif
#ifndef ts_free
#define ts_free free
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_ALLOC_H_

@ -0,0 +1,291 @@
#ifndef TREE_SITTER_ARRAY_H_
#define TREE_SITTER_ARRAY_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "./alloc.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4101)
#elif defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
#define Array(T) \
struct { \
T *contents; \
uint32_t size; \
uint32_t capacity; \
}
/// Initialize an array.
#define array_init(self) \
((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)
/// Create an empty array.
#define array_new() \
{ NULL, 0, 0 }
/// Get a pointer to the element at a given `index` in the array.
#define array_get(self, _index) \
(assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index])
/// Get a pointer to the first element in the array.
#define array_front(self) array_get(self, 0)
/// Get a pointer to the last element in the array.
#define array_back(self) array_get(self, (self)->size - 1)
/// Clear the array, setting its size to zero. Note that this does not free any
/// memory allocated for the array's contents.
#define array_clear(self) ((self)->size = 0)
/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
/// less than the array's current capacity, this function has no effect.
#define array_reserve(self, new_capacity) \
_array__reserve((Array *)(self), array_elem_size(self), new_capacity)
/// Free any memory allocated for this array. Note that this does not free any
/// memory allocated for the array's contents.
#define array_delete(self) _array__delete((Array *)(self))
/// Push a new `element` onto the end of the array.
#define array_push(self, element) \
(_array__grow((Array *)(self), 1, array_elem_size(self)), \
(self)->contents[(self)->size++] = (element))
/// Increase the array's size by `count` elements.
/// New elements are zero-initialized.
#define array_grow_by(self, count) \
do { \
if ((count) == 0) break; \
_array__grow((Array *)(self), count, array_elem_size(self)); \
memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
(self)->size += (count); \
} while (0)
/// Append all elements from one array to the end of another.
#define array_push_all(self, other) \
array_extend((self), (other)->size, (other)->contents)
/// Append `count` elements to the end of the array, reading their values from the
/// `contents` pointer.
#define array_extend(self, count, contents) \
_array__splice( \
(Array *)(self), array_elem_size(self), (self)->size, \
0, count, contents \
)
/// Remove `old_count` elements from the array starting at the given `index`. At
/// the same index, insert `new_count` new elements, reading their values from the
/// `new_contents` pointer.
#define array_splice(self, _index, old_count, new_count, new_contents) \
_array__splice( \
(Array *)(self), array_elem_size(self), _index, \
old_count, new_count, new_contents \
)
/// Insert one `element` into the array at the given `index`.
#define array_insert(self, _index, element) \
_array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))
/// Remove one element from the array at the given `index`.
#define array_erase(self, _index) \
_array__erase((Array *)(self), array_elem_size(self), _index)
/// Pop the last element off the array, returning the element by value.
#define array_pop(self) ((self)->contents[--(self)->size])
/// Assign the contents of one array to another, reallocating if necessary.
#define array_assign(self, other) \
_array__assign((Array *)(self), (const Array *)(other), array_elem_size(self))
/// Swap one array with another
#define array_swap(self, other) \
_array__swap((Array *)(self), (Array *)(other))
/// Get the size of the array contents
#define array_elem_size(self) (sizeof *(self)->contents)
/// Search a sorted array for a given `needle` value, using the given `compare`
/// callback to determine the order.
///
/// If an existing element is found to be equal to `needle`, then the `index`
/// out-parameter is set to the existing value's index, and the `exists`
/// out-parameter is set to true. Otherwise, `index` is set to an index where
/// `needle` should be inserted in order to preserve the sorting, and `exists`
/// is set to false.
#define array_search_sorted_with(self, compare, needle, _index, _exists) \
_array__search_sorted(self, 0, compare, , needle, _index, _exists)
/// Search a sorted array for a given `needle` value, using integer comparisons
/// of a given struct field (specified with a leading dot) to determine the order.
///
/// See also `array_search_sorted_with`.
#define array_search_sorted_by(self, field, needle, _index, _exists) \
_array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists)
/// Insert a given `value` into a sorted array, using the given `compare`
/// callback to determine the order.
#define array_insert_sorted_with(self, compare, value) \
do { \
unsigned _index, _exists; \
array_search_sorted_with(self, compare, &(value), &_index, &_exists); \
if (!_exists) array_insert(self, _index, value); \
} while (0)
/// Insert a given `value` into a sorted array, using integer comparisons of
/// a given struct field (specified with a leading dot) to determine the order.
///
/// See also `array_search_sorted_by`.
#define array_insert_sorted_by(self, field, value) \
do { \
unsigned _index, _exists; \
array_search_sorted_by(self, field, (value) field, &_index, &_exists); \
if (!_exists) array_insert(self, _index, value); \
} while (0)
// Private
typedef Array(void) Array;
/// This is not what you're looking for, see `array_delete`.
static inline void _array__delete(Array *self) {
if (self->contents) {
ts_free(self->contents);
self->contents = NULL;
self->size = 0;
self->capacity = 0;
}
}
/// This is not what you're looking for, see `array_erase`.
static inline void _array__erase(Array *self, size_t element_size,
uint32_t index) {
assert(index < self->size);
char *contents = (char *)self->contents;
memmove(contents + index * element_size, contents + (index + 1) * element_size,
(self->size - index - 1) * element_size);
self->size--;
}
/// This is not what you're looking for, see `array_reserve`.
static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) {
if (new_capacity > self->capacity) {
if (self->contents) {
self->contents = ts_realloc(self->contents, new_capacity * element_size);
} else {
self->contents = ts_malloc(new_capacity * element_size);
}
self->capacity = new_capacity;
}
}
/// This is not what you're looking for, see `array_assign`.
static inline void _array__assign(Array *self, const Array *other, size_t element_size) {
_array__reserve(self, element_size, other->size);
self->size = other->size;
memcpy(self->contents, other->contents, self->size * element_size);
}
/// This is not what you're looking for, see `array_swap`.
static inline void _array__swap(Array *self, Array *other) {
Array swap = *other;
*other = *self;
*self = swap;
}
/// This is not what you're looking for, see `array_push` or `array_grow_by`.
static inline void _array__grow(Array *self, uint32_t count, size_t element_size) {
uint32_t new_size = self->size + count;
if (new_size > self->capacity) {
uint32_t new_capacity = self->capacity * 2;
if (new_capacity < 8) new_capacity = 8;
if (new_capacity < new_size) new_capacity = new_size;
_array__reserve(self, element_size, new_capacity);
}
}
/// This is not what you're looking for, see `array_splice`.
static inline void _array__splice(Array *self, size_t element_size,
uint32_t index, uint32_t old_count,
uint32_t new_count, const void *elements) {
uint32_t new_size = self->size + new_count - old_count;
uint32_t old_end = index + old_count;
uint32_t new_end = index + new_count;
assert(old_end <= self->size);
_array__reserve(self, element_size, new_size);
char *contents = (char *)self->contents;
if (self->size > old_end) {
memmove(
contents + new_end * element_size,
contents + old_end * element_size,
(self->size - old_end) * element_size
);
}
if (new_count > 0) {
if (elements) {
memcpy(
(contents + index * element_size),
elements,
new_count * element_size
);
} else {
memset(
(contents + index * element_size),
0,
new_count * element_size
);
}
}
self->size += new_count - old_count;
}
/// A binary search routine, based on Rust's `std::slice::binary_search_by`.
/// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`.
#define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \
do { \
*(_index) = start; \
*(_exists) = false; \
uint32_t size = (self)->size - *(_index); \
if (size == 0) break; \
int comparison; \
while (size > 1) { \
uint32_t half_size = size / 2; \
uint32_t mid_index = *(_index) + half_size; \
comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \
if (comparison <= 0) *(_index) = mid_index; \
size -= half_size; \
} \
comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \
if (comparison == 0) *(_exists) = true; \
else if (comparison < 0) *(_index) += 1; \
} while (0)
/// Helper macro for the `_sorted_by` routines below. This takes the left (existing)
/// parameter by reference in order to work with the generic sorting function above.
#define _compare_int(a, b) ((int)*(a) - (int)(b))
#ifdef _MSC_VER
#pragma warning(pop)
#elif defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_ARRAY_H_

@ -0,0 +1,266 @@
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
#ifndef TREE_SITTER_API_H_
typedef uint16_t TSStateId;
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
#endif
typedef struct {
TSFieldId field_id;
uint8_t child_index;
bool inherited;
} TSFieldMapEntry;
typedef struct {
uint16_t index;
uint16_t length;
} TSFieldMapSlice;
typedef struct {
bool visible;
bool named;
bool supertype;
} TSSymbolMetadata;
typedef struct TSLexer TSLexer;
struct TSLexer {
int32_t lookahead;
TSSymbol result_symbol;
void (*advance)(TSLexer *, bool);
void (*mark_end)(TSLexer *);
uint32_t (*get_column)(TSLexer *);
bool (*is_at_included_range_start)(const TSLexer *);
bool (*eof)(const TSLexer *);
void (*log)(const TSLexer *, const char *, ...);
};
typedef enum {
TSParseActionTypeShift,
TSParseActionTypeReduce,
TSParseActionTypeAccept,
TSParseActionTypeRecover,
} TSParseActionType;
typedef union {
struct {
uint8_t type;
TSStateId state;
bool extra;
bool repetition;
} shift;
struct {
uint8_t type;
uint8_t child_count;
TSSymbol symbol;
int16_t dynamic_precedence;
uint16_t production_id;
} reduce;
uint8_t type;
} TSParseAction;
typedef struct {
uint16_t lex_state;
uint16_t external_lex_state;
} TSLexMode;
typedef union {
TSParseAction action;
struct {
uint8_t count;
bool reusable;
} entry;
} TSParseActionEntry;
typedef struct {
int32_t start;
int32_t end;
} TSCharacterRange;
struct TSLanguage {
uint32_t version;
uint32_t symbol_count;
uint32_t alias_count;
uint32_t token_count;
uint32_t external_token_count;
uint32_t state_count;
uint32_t large_state_count;
uint32_t production_id_count;
uint32_t field_count;
uint16_t max_alias_sequence_length;
const uint16_t *parse_table;
const uint16_t *small_parse_table;
const uint32_t *small_parse_table_map;
const TSParseActionEntry *parse_actions;
const char * const *symbol_names;
const char * const *field_names;
const TSFieldMapSlice *field_map_slices;
const TSFieldMapEntry *field_map_entries;
const TSSymbolMetadata *symbol_metadata;
const TSSymbol *public_symbol_map;
const uint16_t *alias_map;
const TSSymbol *alias_sequences;
const TSLexMode *lex_modes;
bool (*lex_fn)(TSLexer *, TSStateId);
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
TSSymbol keyword_capture_token;
struct {
const bool *states;
const TSSymbol *symbol_map;
void *(*create)(void);
void (*destroy)(void *);
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
unsigned (*serialize)(void *, char *);
void (*deserialize)(void *, const char *, unsigned);
} external_scanner;
const TSStateId *primary_state_ids;
};
static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) {
uint32_t index = 0;
uint32_t size = len - index;
while (size > 1) {
uint32_t half_size = size / 2;
uint32_t mid_index = index + half_size;
TSCharacterRange *range = &ranges[mid_index];
if (lookahead >= range->start && lookahead <= range->end) {
return true;
} else if (lookahead > range->end) {
index = mid_index;
}
size -= half_size;
}
TSCharacterRange *range = &ranges[index];
return (lookahead >= range->start && lookahead <= range->end);
}
/*
* Lexer Macros
*/
#ifdef _MSC_VER
#define UNUSED __pragma(warning(suppress : 4101))
#else
#define UNUSED __attribute__((unused))
#endif
#define START_LEXER() \
bool result = false; \
bool skip = false; \
UNUSED \
bool eof = false; \
int32_t lookahead; \
goto start; \
next_state: \
lexer->advance(lexer, skip); \
start: \
skip = false; \
lookahead = lexer->lookahead;
#define ADVANCE(state_value) \
{ \
state = state_value; \
goto next_state; \
}
#define ADVANCE_MAP(...) \
{ \
static const uint16_t map[] = { __VA_ARGS__ }; \
for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \
if (map[i] == lookahead) { \
state = map[i + 1]; \
goto next_state; \
} \
} \
}
#define SKIP(state_value) \
{ \
skip = true; \
state = state_value; \
goto next_state; \
}
#define ACCEPT_TOKEN(symbol_value) \
result = true; \
lexer->result_symbol = symbol_value; \
lexer->mark_end(lexer);
#define END_STATE() return result;
/*
* Parse Table Macros
*/
#define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT)
#define STATE(id) id
#define ACTIONS(id) id
#define SHIFT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = (state_value) \
} \
}}
#define SHIFT_REPEAT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = (state_value), \
.repetition = true \
} \
}}
#define SHIFT_EXTRA() \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.extra = true \
} \
}}
#define REDUCE(symbol_name, children, precedence, prod_id) \
{{ \
.reduce = { \
.type = TSParseActionTypeReduce, \
.symbol = symbol_name, \
.child_count = children, \
.dynamic_precedence = precedence, \
.production_id = prod_id \
}, \
}}
#define RECOVER() \
{{ \
.type = TSParseActionTypeRecover \
}}
#define ACCEPT_INPUT() \
{{ \
.type = TSParseActionTypeAccept \
}}
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_PARSER_H_

@ -0,0 +1,37 @@
=====================================
Handle String Names #12
=====================================
[resource]
test_string_name = &"test stringname"
test_dict = Dictionary[int, StringName]({1: &"first value",2: &"second value",3: &"with escaped quote\""})
test_string = "String with a literal newline and an
&"
---
(resource
(section
(identifier)
(property
(path)
(string_name))
(property
(path)
(constructor
(identifier)
(identifier)
(identifier)
(arguments
(dictionary
(pair
(integer)
(string_name))
(pair
(integer)
(string_name))
(pair
(integer)
(string_name))))))
(property
(path)
(string))))

@ -0,0 +1,21 @@
=====================================
Constructors accept type arguments #3
=====================================
[resource]
test_array = Array[int]([42, 76])
---
(resource
(section
(identifier)
(property
(path)
(constructor
(identifier)
(identifier)
(arguments
(array
(integer)
(integer)))))))

@ -0,0 +1,29 @@
=====================================
Constructors accept type arguments #4
=====================================
[resource]
test_array = Dictionary[int, String]({1: "first value",2: "second value",3: "etc"})
---
(resource
(section
(identifier)
(property
(path)
(constructor
(identifier)
(identifier)
(identifier)
(arguments
(dictionary
(pair
(integer)
(string))
(pair
(integer)
(string))
(pair
(integer)
(string))))))))

@ -0,0 +1,44 @@
=====================================
Dictionaries can have any variant as a key #5
=====================================
[resource]
test_untyped_dict = {
1: "first value",
{ 1: 5.2 }: "second value",
[0, 1, 2]: "third value",
PackedStringArray("foo", "bar", "baz"): "fourth value"
}
---
(resource
(section
(identifier)
(property
(path)
(dictionary
(pair
(integer)
(string))
(pair
(dictionary
(pair
(integer)
(float)))
(string))
(pair
(array
(integer)
(integer)
(integer))
(string))
(pair
(constructor
(identifier)
(arguments
(string)
(string)
(string)))
(string))))))

@ -0,0 +1,20 @@
=====================================
Generic type arguments can accept call syntax #9
=====================================
[node name="Node" type="Node"]
property/0/index = Array[ExtResource("2_k17ep")]([SubResource("Resource_ji6et")])
---
(resource
(section
(identifier)
(attribute (identifier) (string))
(attribute (identifier) (string))
(property (path)
(constructor
(identifier)
(constructor (identifier) (arguments (string)))
(arguments (array (constructor (identifier) (arguments (string)))))
))))

@ -0,0 +1,45 @@
=====================================
Resource File
=====================================
[gd_scene load_steps=10 format=2]
[ext_resource path="path" type="type" id=1]
[node]
[node name="game"]
__meta__ = {
"_edit_lock_": true
}
[node parent="game/test"]
script = ExtResource( 1 )
editor/display_folded = true
float = 10000390.03230329
bool = false
str = "hello
world \"okay\""
---
(resource
(section (identifier)
(attribute (identifier) (integer))
(attribute (identifier) (integer)))
(section (identifier)
(attribute (identifier) (string))
(attribute (identifier) (string))
(attribute (identifier) (integer)))
(section (identifier))
(section (identifier)
(attribute (identifier) (string))
(property (path) (dictionary
(pair (string) (true)))))
(section (identifier)
(attribute (identifier) (string))
(property (path) (constructor
(identifier) (arguments (integer))))
(property (path) (true))
(property (path) (float))
(property (path) (false))
(property (path) (string))))

@ -0,0 +1,256 @@
=====================================
Lonely Section
=====================================
[id]
---
(resource
(section (identifier)))
=====================================
Section with Attributes
=====================================
[id a=1 b="s"]
---
(resource
(section (identifier)
(attribute (identifier) (integer))
(attribute (identifier) (string))))
=====================================
Section Properties
=====================================
[id]
a = 1
b = 2
---
(resource
(section (identifier)
(property (path) (integer))
(property (path) (integer))))
=====================================
Section with Attributes Properties
=====================================
[id a=1 b="s"]
a = 1
b = 2
---
(resource
(section (identifier)
(attribute (identifier) (integer))
(attribute (identifier) (string))
(property (path) (integer))
(property (path) (integer))))
=====================================
Dictionary Properties
=====================================
[id]
dict = {}
dict = {
"a": 1,
"b": 2
}
---
(resource
(section (identifier)
(property (path) (dictionary))
(property (path)
(dictionary
(pair (string) (integer))
(pair (string) (integer))))))
=====================================
Sub Dictionary Properties
=====================================
[id]
dict = {
"a": {
"b": 1
}
}
---
(resource
(section (identifier)
(property (path)
(dictionary
(pair
(string)
(dictionary
(pair
(string)
(integer))))))))
=====================================
Indented Dictionary Properties
=====================================
[id]
dict = {
"a": 1,
"b": 2
}
---
(resource
(section (identifier)
(property (path)
(dictionary
(pair (string) (integer))
(pair (string) (integer))))))
=====================================
Section with String Attr and Prop
=====================================
[id a="a/b"]
dict = {
"a": true
}
---
(resource
(section (identifier)
(attribute (identifier) (string))
(property (path)
(dictionary
(pair (string) (true))))))
=====================================
Constructor Property
=====================================
[id a=1.0]
a = Constructor( 1 )
---
(resource
(section
(identifier)
(attribute (identifier) (float))
(property (path)
(constructor (identifier)
(arguments (integer))))))
=====================================
Constructor Generic Type Arguments
=====================================
[id]
b = Constructor[TypeArg1]()
c = Constructor[TypeArg1, TypeArgC(1)]("value")
---
(resource
(section (identifier)
(property (path)
(constructor
(identifier)
(identifier)
(arguments)))
(property (path)
(constructor
(identifier)
(identifier)
(constructor
(identifier)
(arguments (integer)))
(arguments (string))))))
=====================================
Underscore Property
=====================================
[id]
__dict__ = {
"a": true
}
---
(resource
(section (identifier)
(property (path)
(dictionary
(pair (string) (true))))))
=====================================
Object Constructor Property
=====================================
[id]
testObject = Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":79,"unicode":0,"echo":false,"script":null)
---
(resource
(section
(identifier)
(property
(path)
(constructor
(identifier)
(arguments
(identifier)
(pair
(string)
(false))
(pair
(string)
(string))
(pair
(string)
(integer))
(pair
(string)
(false))
(pair
(string)
(false))
(pair
(string)
(false))
(pair
(string)
(false))
(pair
(string)
(false))
(pair
(string)
(false))
(pair
(string)
(integer))
(pair
(string)
(integer))
(pair
(string)
(false))
(pair
(string)
(null)))))))

@ -0,0 +1,36 @@
{
"grammars": [
{
"name": "godot_resource",
"camelcase": "GodotResource",
"scope": "source.godot_resource",
"file-types": [
".tscn",
".tres",
".godot"
],
"injection-regex": "^godot_resource$"
}
],
"metadata": {
"version": "0.7.0",
"license": "MIT",
"description": "Grammar for the Godot game engine's resource format.",
"authors": [
{
"name": "Preston Knopp"
}
],
"links": {
"repository": "https://github.com/PrestonKnopp/tree-sitter-godot-resource"
}
},
"bindings": {
"c": true,
"go": true,
"node": true,
"python": true,
"rust": true,
"swift": true
}
}