Skip to content

Commit 9f0c3cb

Browse files
Merge pull request #6 from klothoplatform/funciters
Use new func iters format for iteration
2 parents e351b20 + fbdd50f commit 9f0c3cb

File tree

1 file changed

+51
-60
lines changed

1 file changed

+51
-60
lines changed

iter.go

Lines changed: 51 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package sitter
22

3-
import "io"
3+
import (
4+
"fmt"
5+
)
46

57
type IterMode int
68

@@ -9,71 +11,60 @@ const (
911
BFSMode
1012
)
1113

12-
// Iterator for a tree of nodes
13-
type Iterator struct {
14-
named bool
15-
mode IterMode
16-
17-
nodesToVisit []*Node
18-
}
19-
20-
// NewIterator takes a node and mode (DFS/BFS) and returns iterator over children of the node
21-
func NewIterator(n *Node, mode IterMode) *Iterator {
22-
return &Iterator{
23-
named: false,
24-
mode: mode,
25-
nodesToVisit: []*Node{n},
26-
}
27-
}
28-
29-
// NewNamedIterator takes a node and mode (DFS/BFS) and returns iterator over named children of the node
30-
func NewNamedIterator(n *Node, mode IterMode) *Iterator {
31-
return &Iterator{
32-
named: true,
33-
mode: mode,
34-
nodesToVisit: []*Node{n},
14+
// TreeIterator takes a node and mode (DFS/BFS) and returns iterator over children of the node.
15+
// named determines whether to iterate over only named children
16+
func TreeIterator(n *Node, mode IterMode, named bool) func(func(*Node) bool) {
17+
return func(yield func(*Node) bool) {
18+
nodesToVisit := []*Node{n}
19+
var current *Node
20+
for len(nodesToVisit) > 0 {
21+
switch mode {
22+
case DFSMode:
23+
current, nodesToVisit = nodesToVisit[len(nodesToVisit)-1], nodesToVisit[:len(nodesToVisit)-1]
24+
case BFSMode:
25+
current, nodesToVisit = nodesToVisit[0], nodesToVisit[1:]
26+
default:
27+
panic(fmt.Errorf("unsupported iteration mode: %v", mode))
28+
}
29+
if !yield(current) {
30+
return
31+
}
32+
if named {
33+
for i := 0; i < int(current.NamedChildCount()); i++ {
34+
nodesToVisit = append(nodesToVisit, current.NamedChild(i))
35+
}
36+
} else {
37+
for i := 0; i < int(current.ChildCount()); i++ {
38+
nodesToVisit = append(nodesToVisit, current.Child(i))
39+
}
40+
}
41+
}
3542
}
3643
}
3744

38-
func (iter *Iterator) Next() (*Node, error) {
39-
if len(iter.nodesToVisit) == 0 {
40-
return nil, io.EOF
41-
}
42-
43-
var n *Node
44-
n, iter.nodesToVisit = iter.nodesToVisit[0], iter.nodesToVisit[1:]
45-
46-
var children []*Node
47-
if iter.named {
48-
for i := 0; i < int(n.NamedChildCount()); i++ {
49-
children = append(children, n.NamedChild(i))
45+
func QueryIterator(root *Node, query *Query) func(func(map[string]*Node) bool) {
46+
return func(yield func(map[string]*Node) bool) {
47+
cursor := NewQueryCursor()
48+
cursor.Exec(query, root)
49+
captures := make(map[uint32]string)
50+
for i := uint32(0); i < query.CaptureCount(); i++ {
51+
captures[i] = query.CaptureNameForId(i)
5052
}
51-
} else {
52-
for i := 0; i < int(n.ChildCount()); i++ {
53-
children = append(children, n.Child(i))
54-
}
55-
}
5653

57-
switch iter.mode {
58-
case DFSMode:
59-
iter.nodesToVisit = append(children, iter.nodesToVisit...)
60-
case BFSMode:
61-
iter.nodesToVisit = append(iter.nodesToVisit, children...)
62-
default:
63-
panic("not implemented")
64-
}
65-
return n, nil
66-
}
54+
for {
55+
match, found := cursor.NextMatch()
56+
if !found {
57+
return
58+
}
59+
results := make(map[string]*Node)
6760

68-
func (iter *Iterator) ForEach(fn func(*Node) error) error {
69-
for {
70-
n, err := iter.Next()
71-
if err != nil {
72-
return err
73-
}
74-
err = fn(n)
75-
if err != nil {
76-
return err
61+
for _, capture := range match.Captures {
62+
results[captures[capture.Index]] = capture.Node
63+
}
64+
65+
if !yield(results) {
66+
return
67+
}
7768
}
7869
}
7970
}

0 commit comments

Comments
 (0)