Skip to content

Commit

Permalink
Tutorial: queries, doc fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mattmassicotte committed Sep 22, 2022
1 parent b1eceac commit 0e413d6
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import SwiftTreeSitter
import TreeSitterSwift

let language = Language(language: tree_sitter_swift())

let parser = Parser()
try parser.setLanguage(language)

let source = """
func hello() {
print("hello from tree-sitter")
}
"""

let tree = parser.parse(source)

print("tree: ", tree)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import SwiftTreeSitter
import TreeSitterSwift

let language = Language(language: tree_sitter_swift())

let parser = Parser()
try parser.setLanguage(language)

let source = """
func hello() {
print("hello from tree-sitter")
}
"""

let tree = parser.parse(source)

print("tree: ", tree)

let url = Bundle.main
.resourceURL
.appendingPathComponent("TreeSitterSwift_TreeSitterSwift.bundle")
.appendingPathComponent("queries/highlights.scm")
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import SwiftTreeSitter
import TreeSitterSwift

let language = Language(language: tree_sitter_swift())

let parser = Parser()
try parser.setLanguage(language)

let source = """
func hello() {
print("hello from tree-sitter")
}
"""

let tree = parser.parse(source)

print("tree: ", tree)

let url = Bundle.main
.resourceURL
.appendingPathComponent("TreeSitterSwift_TreeSitterSwift.bundle")
.appendingPathComponent("queries/highlights.scm")

let query = try language.query(contentsOf: url!)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import SwiftTreeSitter
import TreeSitterSwift

let language = Language(language: tree_sitter_swift())

let parser = Parser()
try parser.setLanguage(language)

let source = """
func hello() {
print("hello from tree-sitter")
}
"""

let tree = parser.parse(source)

print("tree: ", tree)

let url = Bundle.main
.resourceURL
.appendingPathComponent("TreeSitterSwift_TreeSitterSwift.bundle")
.appendingPathComponent("queries/highlights.scm")

let query = try language.query(contentsOf: url!)

let cursor = query.execute(node: tree.rootNode!)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import SwiftTreeSitter
import TreeSitterSwift

let language = Language(language: tree_sitter_swift())

let parser = Parser()
try parser.setLanguage(language)

let source = """
func hello() {
print("hello from tree-sitter")
}
"""

let tree = parser.parse(source)

print("tree: ", tree)

let url = Bundle.main
.resourceURL
.appendingPathComponent("TreeSitterSwift_TreeSitterSwift.bundle")
.appendingPathComponent("queries/highlights.scm")

let query = try language.query(contentsOf: url!)

let cursor = query.execute(node: tree.rootNode!)

for match in cursor {
print("match: ", match)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@Tutorial(time: 10) {
@Intro(title: "Parsing") {
Set up a language and get parse results.
Tree-sitter is all about parsing. Learn how to set up and use a language parser to generate a syntax tree.
}

@Section(title: "Adding Dependencies") {
Expand Down Expand Up @@ -46,13 +46,17 @@

@Step {
Import the language parser

Remember the names are close. This is the parser for the Swift language.

@Code(name: "TreeSitterExample.swift", file: "using-essentials-2-2-example.swift")
}

@Step {
Create a `Language` object.


Note the call to `tree_sitter_swift`. That function is defined in the Swift language module.

@Code(name: "TreeSitterExample.swift", file: "using-essentials-2-3-example.swift")
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,52 @@
@Tutorial(time: 10) {
@Intro(title: "Queries") {
Use the tree-sitter query system to inspect the syntax tree.
@Intro(title: "Running Queries") {
Building and maintaing a parse tree on its own isn't very useful. You'll probably want to inspect the tree using language-specific patterns and matches. The tree-sitter query system is built to do exactly that.
}

@Section(title: "Getting Query Definitions") {
@ContentAndMedia {
text
Let's build on our original example by running queries against our tree. You can write your own queries. Here, we'll use `highlights.scm`, a file many parser include for synatx highlighting.
}

@Steps {
@Step {
one
Here we've parsed some text and have tree object set up.

@Code(name: "TreeSitterExample.swift", file: "using-essentials-4-1-queries.swift")
@Code(name: "TreeSitterExample.swift", file: "using-essentials-4-1-example.swift")
}

@Step {
Create a `URL` to the query definition file.

These are copied into the Swift packages. Their locations differ for macOS and iOS.

@Code(name: "TreeSitterExample.swift", file: "using-essentials-4-2-example.swift")
}

@Step {
Initialize the `query` object.

This can be expensive, depending on the language grammar/queries.

@Code(name: "TreeSitterExample.swift", file: "using-essentials-4-3-example.swift")
}

@Step {
Execute the query.

Queries must be run against a tree
This produces a `QueryCursor`, which can be used to iterate over the results.

@Code(name: "TreeSitterExample.swift", file: "using-essentials-4-4-example.swift")
}

@Step {
Use a loop to print all of the matches.

`QueryCursor` conforms to `Sequence`.

@Code(name: "TreeSitterExample.swift", file: "using-essentials-4-5-example.swift")
}
}
}

@Section(title: "Executing Queries") {
@ContentAndMedia {
text
}

@Steps {
@Step {
one

@Code(name: "TreeSitterExample.swift", file: "using-essentials-4-1-queries.swift")
}
}
}

@Section(title: "Using ResolvingQueryCursor") {
@ContentAndMedia {
text
}

@Steps {
@Step {
one

@Code(name: "TreeSitterExample.swift", file: "using-essentials-4-1-queries.swift")
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
@Tutorials(name: "Using SwiftTreeSitter") {
@Intro(title: "Using SwiftTreeSitter") {
SwiftTreeSitter provides a Swift interface to the tree-sitter incremental parsing system. You can use it to parse language text and get information about the syntatic elements contained.
SwiftTreeSitter provides a Swift interface to the tree-sitter incremental parsing system. You can use it to parse language text, reparse it as it changes, and query the syntax tree.
}

@Chapter(name: "Essentials") {
@Chapter(name: "Tree-Sitter Essentials") {
Learn how to use parse text, process edits, and perform queries with tree-sitter.

@TutorialReference(tutorial: "doc:Parsing")
@TutorialReference(tutorial: "doc:Processing-Edits")
@Comment {
@TutorialReference(tutorial: "doc:Queries")
}
}
@TutorialReference(tutorial: "doc:Queries")
}

@Comment {
@Chapter(name: "SwiftTreeSitter Features") {
Learn about APIs are that specific to SwiftTreeSitter.

@TutorialReference(tutorial: "doc:ResolvingCursors")
}
}
}
16 changes: 14 additions & 2 deletions Sources/SwiftTreeSitter/Query.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ public enum QueryPredicateError: Error {
case textContentUnavailable
}

/// An object that represents a collection of tree-sitter query statements.
///
/// Typically, query definitions are stored in a `.scm` file.
///
/// Tree-sitter's official documenation: [Pattern Matching with Queries](https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries)
public class Query {
let internalQuery: OpaquePointer
let predicateList: [[Predicate]]
Expand Down Expand Up @@ -87,6 +92,13 @@ public class Query {
return Int(ts_query_string_count(internalQuery))
}

/// Ru a query
///
/// Note that both the node **and** the tree is is part of
/// must remain valid as long as the query is being used.
///
/// - Parameter node: the root node for the query
/// - Parameter tree: keep an optional reference to the tree
public func execute(node: Node, in tree: Tree? = nil) -> QueryCursor {
let cursor = QueryCursor()

Expand Down Expand Up @@ -207,8 +219,8 @@ public class QueryCursor {
/// Note that the node **and** the Tree is is part of
/// must remain valid as long as the query is being used.
///
/// - Parameter query: they query object to execute
/// - Parameter node: they query object to execute
/// - Parameter query: the query object to execute
/// - Parameter node: the root node for the query
/// - Parameter tree: keep an optional reference to the tree
public func execute(query: Query, node: Node, in tree: Tree? = nil) {
self.activeQuery = query
Expand Down

0 comments on commit 0e413d6

Please sign in to comment.