Skip to content

Instantly share code, notes, and snippets.

@tenntenn
Created December 31, 2016 01:55
Show Gist options
  • Save tenntenn/f938d5849157fc44790321b6ae9246cc to your computer and use it in GitHub Desktop.
Save tenntenn/f938d5849157fc44790321b6ae9246cc to your computer and use it in GitHub Desktop.
抽象構文木(AST)をトラバースする #golang ref: http://qiita.com/tenntenn/items/f029425a844687a0e64b
func Inspect(node Node, f func(Node) bool)
expr, err := parser.ParseExpr(`1+1`)
if err != nil {
log.Fatalln("Error:", err)
}
ast.Inspect(expr, func(n ast.Node) bool {
fmt.Printf("%[1]T %[1]v\n", n)
return true
})
*ast.BinaryExpr (+)
├── *ast.BasicLit (1)
└── *ast.BasicLit (1)
*ast.BinaryExpr &{0x1050e150 2 + 0x1050e160}
*ast.BasicLit &{1 INT 1}
<nil> <nil>
*ast.BasicLit &{3 INT 1}
<nil> <nil>
<nil> <nil>
expr, err := parser.ParseExpr(`1+1`)
if err != nil {
log.Fatalln("Error:", err)
}
var i int
ast.Inspect(expr, func(n ast.Node) bool {
fmt.Printf("%s%[2]T %[2]v\n", strings.Repeat(" ", i), n)
if n != nil {
i++
} else {
i--
}
return true
})
*ast.BinaryExpr &{0x1050e150 2 + 0x1050e160}
*ast.BasicLit &{1 INT 1}
<nil> <nil>
*ast.BasicLit &{3 INT 1}
<nil> <nil>
<nil> <nil>
type inspector func(Node) bool
func (f inspector) Visit(node Node) Visitor {
if f(node) {
return f
}
return nil
}
// Inspect traverses an AST in depth-first order: It starts by calling
// f(node); node must not be nil. If f returns true, Inspect invokes f
// recursively for each of the non-nil children of node, followed by a
// call of f(nil).
//
func Inspect(node Node, f func(Node) bool) {
Walk(inspector(f), node)
}
func Walk(v Visitor, node Node)
type Visitor interface {
Visit(node Node) (w Visitor)
}
package main
import (
"fmt"
"go/ast"
"go/parser"
"log"
)
type visitorFunc func(node ast.Node) (w ast.Visitor)
func (f visitorFunc) Visit(node ast.Node) (w ast.Visitor) {
return f(node)
}
func main() {
expr, err := parser.ParseExpr(`1+1`)
if err != nil {
log.Fatalln("Error:", err)
}
var v1, v2 visitorFunc
v1 = visitorFunc(func(node ast.Node) (w ast.Visitor) {
fmt.Printf("%T\n", node)
switch node.(type) {
case *ast.BinaryExpr:
return v2
}
return nil
})
v2 = visitorFunc(func(node ast.Node) (w ast.Visitor) {
if node == nil {
return nil
}
lit := node.(*ast.BasicLit)
fmt.Printf("BasicLit: %s\n", lit.Value)
return nil
})
ast.Walk(v1, expr)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment