2015-10-16 20:12:26 +00:00
|
|
|
package ast
|
2015-10-16 19:58:38 +00:00
|
|
|
|
2015-10-24 20:12:28 +00:00
|
|
|
import "fmt"
|
|
|
|
|
2015-10-16 19:58:38 +00:00
|
|
|
// Walk traverses an AST in depth-first order: It starts by calling fn(node);
|
|
|
|
// node must not be nil. If f returns true, Walk invokes f recursively for
|
|
|
|
// each of the non-nil children of node, followed by a call of f(nil).
|
|
|
|
func Walk(node Node, fn func(Node) bool) {
|
|
|
|
if !fn(node) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
switch n := node.(type) {
|
2015-10-30 22:15:36 +00:00
|
|
|
case *File:
|
|
|
|
Walk(n.Node, fn)
|
2015-10-16 19:58:38 +00:00
|
|
|
case *ObjectList:
|
2015-10-16 20:12:26 +00:00
|
|
|
for _, item := range n.Items {
|
2015-10-16 19:58:38 +00:00
|
|
|
Walk(item, fn)
|
|
|
|
}
|
|
|
|
case *ObjectKey:
|
|
|
|
// nothing to do
|
|
|
|
case *ObjectItem:
|
2015-10-16 20:12:26 +00:00
|
|
|
for _, k := range n.Keys {
|
2015-10-16 19:58:38 +00:00
|
|
|
Walk(k, fn)
|
|
|
|
}
|
2015-10-16 20:12:26 +00:00
|
|
|
Walk(n.Val, fn)
|
2015-10-16 19:58:38 +00:00
|
|
|
case *LiteralType:
|
|
|
|
// nothing to do
|
|
|
|
case *ListType:
|
2015-10-16 20:12:26 +00:00
|
|
|
for _, l := range n.List {
|
2015-10-16 19:58:38 +00:00
|
|
|
Walk(l, fn)
|
|
|
|
}
|
|
|
|
case *ObjectType:
|
2015-10-16 22:14:40 +00:00
|
|
|
for _, l := range n.List.Items {
|
2015-10-16 19:58:38 +00:00
|
|
|
Walk(l, fn)
|
|
|
|
}
|
2015-10-24 20:12:28 +00:00
|
|
|
default:
|
|
|
|
fmt.Printf(" unknown type: %T\n", n)
|
2015-10-16 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn(nil)
|
|
|
|
}
|