github.com/google/skylark@v0.0.0-20181101142754-a5f7082aabed/syntax/walk.go (about) 1 // Copyright 2017 The Bazel Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package syntax 6 7 // Walk traverses a syntax tree in depth-first order. 8 // It starts by calling f(n); n must not be nil. 9 // If f returns true, Walk calls itself 10 // recursively for each non-nil child of n. 11 // Walk then calls f(nil). 12 func Walk(n Node, f func(Node) bool) { 13 if !f(n) { 14 return 15 } 16 17 // TODO(adonovan): opt: order cases using profile data. 18 switch n := n.(type) { 19 case *File: 20 walkStmts(n.Stmts, f) 21 22 case *ExprStmt: 23 Walk(n.X, f) 24 25 case *BranchStmt: 26 // no-op 27 28 case *IfStmt: 29 Walk(n.Cond, f) 30 walkStmts(n.True, f) 31 walkStmts(n.False, f) 32 33 case *AssignStmt: 34 Walk(n.RHS, f) 35 Walk(n.LHS, f) 36 37 case *DefStmt: 38 Walk(n.Name, f) 39 for _, param := range n.Function.Params { 40 Walk(param, f) 41 } 42 walkStmts(n.Function.Body, f) 43 44 case *ForStmt: 45 Walk(n.Vars, f) 46 Walk(n.X, f) 47 walkStmts(n.Body, f) 48 49 case *ReturnStmt: 50 if n.Result != nil { 51 Walk(n.Result, f) 52 } 53 54 case *LoadStmt: 55 Walk(n.Module, f) 56 for _, from := range n.From { 57 Walk(from, f) 58 } 59 for _, to := range n.To { 60 Walk(to, f) 61 } 62 63 case *Ident, *Literal: 64 // no-op 65 66 case *ListExpr: 67 for _, x := range n.List { 68 Walk(x, f) 69 } 70 71 case *ParenExpr: 72 Walk(n.X, f) 73 74 case *CondExpr: 75 Walk(n.Cond, f) 76 Walk(n.True, f) 77 Walk(n.False, f) 78 79 case *IndexExpr: 80 Walk(n.X, f) 81 Walk(n.Y, f) 82 83 case *DictEntry: 84 Walk(n.Key, f) 85 Walk(n.Value, f) 86 87 case *SliceExpr: 88 Walk(n.X, f) 89 if n.Lo != nil { 90 Walk(n.Lo, f) 91 } 92 if n.Hi != nil { 93 Walk(n.Hi, f) 94 } 95 if n.Step != nil { 96 Walk(n.Step, f) 97 } 98 99 case *Comprehension: 100 for _, clause := range n.Clauses { 101 Walk(clause, f) 102 } 103 Walk(n.Body, f) 104 105 case *IfClause: 106 Walk(n.Cond, f) 107 108 case *ForClause: 109 Walk(n.Vars, f) 110 Walk(n.X, f) 111 112 case *TupleExpr: 113 for _, x := range n.List { 114 Walk(x, f) 115 } 116 117 case *DictExpr: 118 for _, entry := range n.List { 119 entry := entry.(*DictEntry) 120 Walk(entry.Key, f) 121 Walk(entry.Value, f) 122 } 123 124 case *UnaryExpr: 125 Walk(n.X, f) 126 127 case *BinaryExpr: 128 Walk(n.X, f) 129 Walk(n.Y, f) 130 131 case *DotExpr: 132 Walk(n.X, f) 133 Walk(n.Name, f) 134 135 case *CallExpr: 136 Walk(n.Fn, f) 137 for _, arg := range n.Args { 138 Walk(arg, f) 139 } 140 141 case *LambdaExpr: 142 for _, param := range n.Function.Params { 143 Walk(param, f) 144 } 145 walkStmts(n.Function.Body, f) 146 147 default: 148 panic(n) 149 } 150 151 f(nil) 152 } 153 154 func walkStmts(stmts []Stmt, f func(Node) bool) { 155 for _, stmt := range stmts { 156 Walk(stmt, f) 157 } 158 }