Skip to content

Commit

Permalink
go/ast: add Preorder go1.23 iterator
Browse files Browse the repository at this point in the history
This CL adds a new function Preorder that makes it
easier to iterate over the nodes of a syntax tree.
In particular, break, continue, and return retain
their usual continuations.

Fixes golang#66339

Change-Id: I438b3c23780c91ed589871ad3b8822d54e8fabc7
Reviewed-on: https://go-review.googlesource.com/c/go/+/570680
Reviewed-by: Robert Findley <[email protected]>
Auto-Submit: Alan Donovan <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
adonovan authored and gopherbot committed May 15, 2024
1 parent 3c8f925 commit 7730e5b
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 1 deletion.
1 change: 1 addition & 0 deletions api/next/66339.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pkg go/ast, func Preorder(Node) iter.Seq[Node] #66339
2 changes: 2 additions & 0 deletions doc/next/6-stdlib/99-minor/go/ast/66339.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The new [Preorder] function returns a convenient iterator over all the
nodes of a syntax tree.
35 changes: 35 additions & 0 deletions src/go/ast/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,41 @@ func main() {
// 61 }
}

func ExamplePreorder() {
src := `
package p
func f(x, y int) {
print(x + y)
}
`

fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
panic(err)
}

// Print identifiers in order
for n := range ast.Preorder(f) {
id, ok := n.(*ast.Ident)
if !ok {
continue
}
fmt.Println(id.Name)
}

// Output:
// p
// f
// x
// y
// int
// print
// x
// y
}

// This example illustrates how to remove a variable declaration
// in a Go program while maintaining correct comment association
// using an ast.CommentMap.
Expand Down
22 changes: 21 additions & 1 deletion src/go/ast/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

package ast

import "fmt"
import (
"fmt"
"iter"
)

// A Visitor's Visit method is invoked for each node encountered by [Walk].
// If the result visitor w is not nil, [Walk] visits each of the children
Expand Down Expand Up @@ -368,3 +371,20 @@ func (f inspector) Visit(node Node) Visitor {
func Inspect(node Node, f func(Node) bool) {
Walk(inspector(f), node)
}

// Preorder returns an iterator over all the nodes of the syntax tree
// beneath (and including) the specified root, in depth-first
// preorder.
//
// For greater control over the traversal of each subtree, use [Inspect].
func Preorder(root Node) iter.Seq[Node] {
return func(yield func(Node) bool) {
ok := true
Inspect(root, func(n Node) bool {
if n != nil && !yield(n) {
ok = false
}
return ok
})
}
}

0 comments on commit 7730e5b

Please sign in to comment.