aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/query
diff options
context:
space:
mode:
authorJP Appel <jeanpierre.appel01@gmail.com>2025-06-13 14:26:14 -0400
committerJP Appel <jeanpierre.appel01@gmail.com>2025-06-13 14:26:14 -0400
commit6b0151257a76b5f2f6aa4bbcdc027fce57cc6170 (patch)
treed7a927c21be259cec80d5688578b3c246b93cc83 /pkg/query
parente8de91eee099486200bac79406f17c149d1fcb5d (diff)
Add bfs and dfs iterators for clause trees
Diffstat (limited to 'pkg/query')
-rw-r--r--pkg/query/parser.go55
1 files changed, 55 insertions, 0 deletions
diff --git a/pkg/query/parser.go b/pkg/query/parser.go
index e8fccfe..5de803c 100644
--- a/pkg/query/parser.go
+++ b/pkg/query/parser.go
@@ -2,6 +2,7 @@ package query
import (
"fmt"
+ "iter"
"os"
"slices"
"strings"
@@ -283,6 +284,60 @@ func (c Clause) buildString(b *strings.Builder, level int) {
b.WriteString(")\n")
}
+// Depth of tree via recursion
+func (root Clause) Depth() int {
+ maxHeight := 1
+ for _, child := range root.Clauses {
+ maxHeight = max(maxHeight, child.Depth()+1)
+ }
+ return maxHeight
+}
+
+func (root *Clause) DFS() iter.Seq[*Clause] {
+ return func(yield func(*Clause) bool) {
+ stack := make([]*Clause, 0, len(root.Clauses))
+ stack = append(stack, root)
+
+ for len(stack) != 0 {
+ node := stack[len(stack)-1]
+
+ if !yield(node) {
+ return
+ }
+
+ stack := stack[:len(stack)-1]
+ stack = append(stack, node.Clauses...)
+ }
+ }
+}
+
+func (root *Clause) BFS() iter.Seq[*Clause] {
+ return func(yield func(*Clause) bool) {
+ queue := make([]*Clause, 64*len(root.Clauses))
+ queue = append(queue, root)
+ read := 0
+ write := 1
+ size := 1
+
+ // FIXME: can potentially discard values if queue is too small
+ for size != 0 {
+ node := queue[read]
+
+ if !yield(node) {
+ return
+ }
+ read = (read + 1) % len(queue)
+ size -= 1
+
+ for _, child := range node.Clauses {
+ queue[write] = child
+ write = (write + 1) % len(queue)
+ size += 1
+ }
+ }
+ }
+}
+
func Parse(tokens []Token) (*Clause, error) {
stack := make([]*Clause, 0, 10)