Skip to content

Commit

Permalink
Merge pull request #1 from unsignedapps/swift-wrapper
Browse files Browse the repository at this point in the history
Swift Wrapper
  • Loading branch information
bok- authored Jan 5, 2021
2 parents 4c0fa29 + 1aff114 commit 9a560dd
Show file tree
Hide file tree
Showing 22 changed files with 1,529 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ log*.html

.idea
*.xcodeproj
.build
.swiftpm
.DS_Store

fuzz-results

Expand Down
33 changes: 33 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// swift-tools-version:5.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "TreeSitter",

products: [
.library(name: "TreeSitter", targets: [ "TreeSitter" ]),
],

dependencies: [],

targets: [
// Our Public Swift wrapper that lives in Sources/TreeSitter
.target(name: "TreeSitter", dependencies: [ "tree_sitter" ]),

// The original C tree-sitter library that lives in ./lib
.target (
name: "tree_sitter",
path: "lib",
sources: [ "src/lib.c" ],
publicHeadersPath: "include/tree_sitter",
cSettings: [
.headerSearchPath("include"),
.headerSearchPath("src")
]
)
],

cLanguageStandard: .gnu99
)
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,42 @@ Tree-sitter is a parser generator tool and an incremental parsing library. It ca
* **Dependency-free** so that the runtime library (which is written in pure C) can be embedded in any application

[Documentation](https://tree-sitter.github.io/tree-sitter/)


## Swift Wrapper

This fork of tree-sitter comes with a minimal Swift Wrapper thats designed to incorporate Swift conventions while staying out of the way of the fast C library underneath.

Documentation is copied from the C library where possible but there are a number of gaps. Consult `lib/include/tree_sitter/api.h` and the C source in `lib/src/` for accurate information on how things work.

### Installation

To include `swift-tree-sitter` in your Swift package add the following dependency to your Package.swift:

```swift
.package(url: "https://github.com/unsignedapps/swift-tree-sitter.git", from: "0.16.5.1")
```

**Note:** The first version that has Swift Package Manager support is 0.16.5.1.

Don't forget to include the library in your target:

```swift
.target(name: "BestExampleApp", dependencies: [ "TreeSitter" ])
```

And import the module in your code:

```swift
import Foundation
import TreeSitter
```

### TODO

This is a partial wrapper. Some things still to be done:

* Unit Tests
* Logging
* DOT graphs

44 changes: 44 additions & 0 deletions Sources/TreeSitter/Edit.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Edit.swift
// TreeSitter: Swift Wrapper for https://github.com/tree-sitter/tree-sitter
//
// Created by Rob Amos on 12/4/20.
//

import tree_sitter

public struct Edit {

// MARK: - Properties

public var startByte: UInt32
public var oldEndByte: UInt32
public var newEndByte: UInt32

public var startPoint: Point
public var oldEndPoint: Point
public var newEndPoint: Point

internal lazy var rawValue: TSInputEdit = {
return TSInputEdit (
start_byte: self.startByte,
old_end_byte: self.oldEndByte,
new_end_byte: self.newEndByte,
start_point: self.startPoint.rawValue,
old_end_point: self.oldEndPoint.rawValue,
new_end_point: self.newEndPoint.rawValue
)
}()


// MARK: - Initialisation

public init(startByte: UInt32, oldEndByte: UInt32, newEndByte: UInt32, startPoint: Point, oldEndPoint: Point, newEndPoint: Point) {
self.startByte = startByte
self.oldEndByte = oldEndByte
self.newEndByte = newEndByte
self.startPoint = startPoint
self.oldEndPoint = oldEndPoint
self.newEndPoint = newEndPoint
}
}
38 changes: 38 additions & 0 deletions Sources/TreeSitter/Field.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// Field.swift
// TreeSitter: Swift Wrapper for https://github.com/tree-sitter/tree-sitter
//
// Created by Rob Amos on 12/4/20.
//

import tree_sitter

public struct Field {

// MARK: - Properties

public var name: String?
internal var rawValue: TSFieldId


// MARK: - Initialisation

internal init (rawValue: TSFieldId, name: String? = nil) {
self.rawValue = rawValue
self.name = name
}

public init (name: String, in language: Language) {
self.name = name
self.rawValue = ts_language_field_id_for_name(language.rawValue, name, UInt32(name.utf8.count))
}


// MARK: - Field Names

public func name (in language: Language) -> String? {
guard let name = ts_language_field_name_for_id(language.rawValue, self.rawValue) else { return nil }
return String(cString: name)
}
}

41 changes: 41 additions & 0 deletions Sources/TreeSitter/InputEncoding.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// InputEncoding.swift
// TreeSitter: Swift Wrapper for https://github.com/tree-sitter/tree-sitter
//
// Created by Rob Amos on 12/4/20.
//

import tree_sitter

public enum InputEncoding {

// MARK: - Cases

case utf8
case utf16

}


// MARK: - Interoperability

internal extension InputEncoding {

var rawValue: TSInputEncoding {
switch self {
case .utf8: return TSInputEncodingUTF8
case .utf16: return TSInputEncodingUTF16
}
}

init? (rawValue: TSInputEncoding) {
switch rawValue {
case TSInputEncodingUTF8: self = .utf8
case TSInputEncodingUTF16: self = .utf16
default: return nil
}
}
}



49 changes: 49 additions & 0 deletions Sources/TreeSitter/Language.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Language.swift
// TreeSitter: Swift Wrapper for https://github.com/tree-sitter/tree-sitter
//
// Created by Rob Amos on 12/4/20.
//

import tree_sitter

public struct Language {

// MARK: - Properties

internal var rawValue: UnsafePointer<TSLanguage>


// MARK: - Initialisation

/// You shouldn't ever directly need to initialise `Language`, but
/// just in case you're pulling in your own library definitions, this is here.
///
public init (rawValue: UnsafePointer<TSLanguage>) {
self.rawValue = rawValue
}


// MARK: - Language Information

public var symbolCount: Int {
return Int(ts_language_symbol_count(self.rawValue))
}

public var fieldCount: Int {
return Int(ts_language_field_count(self.rawValue))
}

public var version: UInt32 {
return ts_language_version(self.rawValue)
}
}


// MARK: - Equatable Conformance

extension Language: Equatable {
public static func == (lhs: Language, rhs: Language) -> Bool {
return lhs.rawValue == rhs.rawValue
}
}
Loading

0 comments on commit 9a560dd

Please sign in to comment.