Skip to content

Commit 2b2060b

Browse files
committed
Generate bindings
1 parent 28f1046 commit 2b2060b

25 files changed

+544
-119
lines changed

CMakeLists.txt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
cmake_minimum_required(VERSION 3.13)
2+
3+
project(tree-sitter-elm
4+
VERSION "5.7.0"
5+
DESCRIPTION "Tree sitter definitions for elm"
6+
HOMEPAGE_URL "https://github.com/elm-tooling/tree-sitter-elm"
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 14 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-elm src/parser.c)
28+
if(EXISTS src/scanner.c)
29+
target_sources(tree-sitter-elm PRIVATE src/scanner.c)
30+
endif()
31+
target_include_directories(tree-sitter-elm PRIVATE src)
32+
33+
target_compile_definitions(tree-sitter-elm PRIVATE
34+
$<$<BOOL:${TREE_SITTER_REUSE_ALLOCATOR}>:TREE_SITTER_REUSE_ALLOCATOR>
35+
$<$<CONFIG:Debug>:TREE_SITTER_DEBUG>)
36+
37+
set_target_properties(tree-sitter-elm
38+
PROPERTIES
39+
C_STANDARD 11
40+
POSITION_INDEPENDENT_CODE ON
41+
SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}"
42+
DEFINE_SYMBOL "")
43+
44+
configure_file(bindings/c/tree-sitter-elm.pc.in
45+
"${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-elm.pc" @ONLY)
46+
47+
include(GNUInstallDirs)
48+
49+
install(FILES bindings/c/tree-sitter-elm.h
50+
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter")
51+
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-elm.pc"
52+
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig")
53+
install(TARGETS tree-sitter-elm
54+
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
55+
56+
add_custom_target(test "${TREE_SITTER_CLI}" test
57+
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
58+
COMMENT "tree-sitter test")
59+
60+
# vim:ft=cmake:

Cargo.toml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,22 @@ authors = [
66
"Kolja Lampe <razzeee@gmail.com>"
77

88
]
9+
readme = "README.md"
910
homepage = "https://tree-sitter.github.io/tree-sitter/"
1011
repository = "https://github.com/elm-tooling/tree-sitter-elm"
11-
keywords = ["elm", "tree", "sitter", "parsing", "incremental"]
12-
categories = ["parser-implementations", "api-bindings", "text-editors", "parsing"]
13-
edition = "2018"
12+
keywords = ["incremental", "parsing", "tree-sitter", "elm"]
13+
categories = ["parsing", "text-editors"]
14+
edition = "2021"
1415
license = "MIT"
16+
autoexamples = false
17+
1518
build = "bindings/rust/build.rs"
1619
include = [
17-
"bindings/rust/*",
18-
"grammar.js",
19-
"queries/*",
20-
"src/*",
21-
"LICENSE.md",
20+
"bindings/rust/*",
21+
"grammar.js",
22+
"queries/*",
23+
"src/*",
24+
"LICENSE.md",
2225
]
2326

2427
# Keep in sync with package.json
@@ -28,7 +31,10 @@ version = "5.7.0"
2831
path = "bindings/rust/lib.rs"
2932

3033
[dependencies]
31-
tree-sitter = "0.24.3"
34+
tree-sitter-language = "0.1"
3235

3336
[build-dependencies]
34-
cc = "1.0"
37+
cc = "1.1.22"
38+
39+
[dev-dependencies]
40+
tree-sitter = "0.24.3"

Makefile

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
ifeq ($(OS),Windows_NT)
2+
$(error Windows is not supported)
3+
endif
4+
5+
LANGUAGE_NAME := tree-sitter-elm
6+
HOMEPAGE_URL := https://github.com/elm-tooling/tree-sitter-elm
7+
VERSION := 5.7.0
8+
9+
# repository
10+
SRC_DIR := src
11+
12+
TS ?= tree-sitter
13+
14+
# install directory layout
15+
PREFIX ?= /usr/local
16+
INCLUDEDIR ?= $(PREFIX)/include
17+
LIBDIR ?= $(PREFIX)/lib
18+
PCLIBDIR ?= $(LIBDIR)/pkgconfig
19+
20+
# source/object files
21+
PARSER := $(SRC_DIR)/parser.c
22+
EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c))
23+
OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS))
24+
25+
# flags
26+
ARFLAGS ?= rcs
27+
override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC
28+
29+
# ABI versioning
30+
SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER))
31+
SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION)))
32+
33+
# OS-specific bits
34+
ifeq ($(shell uname),Darwin)
35+
SOEXT = dylib
36+
SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT)
37+
SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT)
38+
LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks
39+
else
40+
SOEXT = so
41+
SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR)
42+
SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR)
43+
LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER)
44+
endif
45+
ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),)
46+
PCLIBDIR := $(PREFIX)/libdata/pkgconfig
47+
endif
48+
49+
all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc
50+
51+
lib$(LANGUAGE_NAME).a: $(OBJS)
52+
$(AR) $(ARFLAGS) $@ $^
53+
54+
lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS)
55+
$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
56+
ifneq ($(STRIP),)
57+
$(STRIP) $@
58+
endif
59+
60+
$(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in
61+
sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \
62+
-e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \
63+
-e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \
64+
-e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \
65+
-e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \
66+
-e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@
67+
68+
$(PARSER): $(SRC_DIR)/grammar.json
69+
$(TS) generate $^
70+
71+
install: all
72+
install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'
73+
install -m644 bindings/c/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h
74+
install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
75+
install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a
76+
install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER)
77+
ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR)
78+
ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT)
79+
80+
uninstall:
81+
$(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \
82+
'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \
83+
'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \
84+
'$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \
85+
'$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \
86+
'$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc
87+
88+
clean:
89+
$(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT)
90+
91+
test:
92+
$(TS) test
93+
94+
.PHONY: all install uninstall clean test

bindings/c/tree-sitter-elm.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef TREE_SITTER_ELM_H_
2+
#define TREE_SITTER_ELM_H_
3+
4+
typedef struct TSLanguage TSLanguage;
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
const TSLanguage *tree_sitter_elm(void);
11+
12+
#ifdef __cplusplus
13+
}
14+
#endif
15+
16+
#endif // TREE_SITTER_ELM_H_

bindings/c/tree-sitter-elm.pc.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
prefix=@CMAKE_INSTALL_PREFIX@
2+
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
3+
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
4+
5+
Name: tree-sitter-elm
6+
Description: @PROJECT_DESCRIPTION@
7+
URL: @PROJECT_HOMEPAGE_URL@
8+
Version: @PROJECT_VERSION@
9+
Requires: @TS_REQUIRES@
10+
Libs: -L${libdir} -ltree-sitter-elm
11+
Cflags: -I${includedir}

bindings/go/binding.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package tree_sitter_elm
2+
3+
// #cgo CFLAGS: -std=c11 -fPIC
4+
// #include "../../src/parser.c"
5+
// // NOTE: if your language has an external scanner, add it here.
6+
import "C"
7+
8+
import "unsafe"
9+
10+
// Get the tree-sitter Language for this grammar.
11+
func Language() unsafe.Pointer {
12+
return unsafe.Pointer(C.tree_sitter_elm())
13+
}

bindings/go/binding_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package tree_sitter_elm_test
2+
3+
import (
4+
"testing"
5+
6+
tree_sitter "github.com/tree-sitter/go-tree-sitter"
7+
tree_sitter_elm "github.com/elm-tooling/tree-sitter-elm/bindings/go"
8+
)
9+
10+
func TestCanLoadGrammar(t *testing.T) {
11+
language := tree_sitter.NewLanguage(tree_sitter_elm.Language())
12+
if language == nil {
13+
t.Errorf("Error loading Elm grammar")
14+
}
15+
}

bindings/node/binding.cc

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,20 @@
1-
#include "tree_sitter/parser.h"
2-
#include <node.h>
3-
#include "nan.h"
1+
#include <napi.h>
42

5-
using namespace v8;
3+
typedef struct TSLanguage TSLanguage;
64

7-
extern "C" TSLanguage * tree_sitter_elm();
5+
extern "C" TSLanguage *tree_sitter_elm();
86

9-
namespace {
7+
// "tree-sitter", "language" hashed with BLAKE2
8+
const napi_type_tag LANGUAGE_TYPE_TAG = {
9+
0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
10+
};
1011

11-
NAN_METHOD(New) {}
12-
13-
void Init(Local<Object> exports, Local<Object> module) {
14-
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
15-
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
16-
tpl->InstanceTemplate()->SetInternalFieldCount(1);
17-
18-
Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
19-
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
20-
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_elm());
21-
22-
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("elm").ToLocalChecked());
23-
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
12+
Napi::Object Init(Napi::Env env, Napi::Object exports) {
13+
exports["name"] = Napi::String::New(env, "elm");
14+
auto language = Napi::External<TSLanguage>::New(env, tree_sitter_elm());
15+
language.TypeTag(&LANGUAGE_TYPE_TAG);
16+
exports["language"] = language;
17+
return exports;
2418
}
2519

26-
NODE_MODULE(tree_sitter_elm_binding, Init)
27-
28-
} // namespace
20+
NODE_API_MODULE(tree_sitter_elm_binding, Init)

bindings/node/binding_test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// <reference types="node" />
2+
3+
const assert = require("node:assert");
4+
const { test } = require("node:test");
5+
6+
test("can load grammar", () => {
7+
const parser = new (require("tree-sitter"))();
8+
assert.doesNotThrow(() => parser.setLanguage(require(".")));
9+
});

bindings/node/index.d.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
name: string;
23+
language: unknown;
24+
nodeTypeInfo: NodeInfo[];
25+
};
26+
27+
declare const language: Language;
28+
export = language;

bindings/node/index.js

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
1-
try {
2-
module.exports = require("../../build/Release/tree_sitter_elm_binding");
3-
} catch (error1) {
4-
if (error1.code !== 'MODULE_NOT_FOUND') {
5-
throw error1;
6-
}
7-
try {
8-
module.exports = require("../../build/Debug/tree_sitter_elm_binding");
9-
} catch (error2) {
10-
if (error2.code !== 'MODULE_NOT_FOUND') {
11-
throw error2;
12-
}
13-
throw error1
14-
}
15-
}
1+
const root = require("path").join(__dirname, "..", "..");
2+
3+
module.exports = require("node-gyp-build")(root);
164

175
try {
186
module.exports.nodeTypeInfo = require("../../src/node-types.json");

bindings/python/tests/test_binding.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from unittest import TestCase
2+
3+
import tree_sitter, tree_sitter_elm
4+
5+
6+
class TestLanguage(TestCase):
7+
def test_can_load_grammar(self):
8+
try:
9+
tree_sitter.Language(tree_sitter_elm.language())
10+
except Exception:
11+
self.fail("Error loading Elm grammar")

0 commit comments

Comments
 (0)