diff options
author | Alan Donovan <adonovan@google.com> | 2024-03-11 17:16:44 -0400 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2024-05-15 21:44:50 +0000 |
commit | 7730e5b78308b966a1fe913cdd3086c84e0a2e25 (patch) | |
tree | d2c34ee8774f50a9a7c4c2a221b7cd715be8719c | |
parent | 3c8f9256067bb3917d7cae05cffdb56dc29e4b3c (diff) | |
download | go-7730e5b78308b966a1fe913cdd3086c84e0a2e25.tar.gz go-7730e5b78308b966a1fe913cdd3086c84e0a2e25.zip |
go/ast: add Preorder go1.23 iterator
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 #66339
Change-Id: I438b3c23780c91ed589871ad3b8822d54e8fabc7
Reviewed-on: https://go-review.googlesource.com/c/go/+/570680
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
-rw-r--r-- | api/next/66339.txt | 1 | ||||
-rw-r--r-- | doc/next/6-stdlib/99-minor/go/ast/66339.md | 2 | ||||
-rw-r--r-- | src/go/ast/example_test.go | 35 | ||||
-rw-r--r-- | src/go/ast/walk.go | 22 |
4 files changed, 59 insertions, 1 deletions
diff --git a/api/next/66339.txt b/api/next/66339.txt new file mode 100644 index 0000000000..a6b45adcd2 --- /dev/null +++ b/api/next/66339.txt @@ -0,0 +1 @@ +pkg go/ast, func Preorder(Node) iter.Seq[Node] #66339 diff --git a/doc/next/6-stdlib/99-minor/go/ast/66339.md b/doc/next/6-stdlib/99-minor/go/ast/66339.md new file mode 100644 index 0000000000..0eec51ecd6 --- /dev/null +++ b/doc/next/6-stdlib/99-minor/go/ast/66339.md @@ -0,0 +1,2 @@ +The new [Preorder] function returns a convenient iterator over all the +nodes of a syntax tree. diff --git a/src/go/ast/example_test.go b/src/go/ast/example_test.go index 4ce42fb153..31b32efece 100644 --- a/src/go/ast/example_test.go +++ b/src/go/ast/example_test.go @@ -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. diff --git a/src/go/ast/walk.go b/src/go/ast/walk.go index 59e6fc174d..0cd604ef1f 100644 --- a/src/go/ast/walk.go +++ b/src/go/ast/walk.go @@ -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 @@ -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 + }) + } +} |