go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/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 n == nil { 14 panic("nil") 15 } 16 if !f(n) { 17 return 18 } 19 20 // TODO(adonovan): opt: order cases using profile data. 21 switch n := n.(type) { 22 case *File: 23 walkStmts(n.Stmts, f) 24 25 case *ExprStmt: 26 Walk(n.X, f) 27 28 case *BranchStmt: 29 // no-op 30 31 case *IfStmt: 32 Walk(n.Cond, f) 33 walkStmts(n.True, f) 34 walkStmts(n.False, f) 35 36 case *AssignStmt: 37 Walk(n.LHS, f) 38 Walk(n.RHS, f) 39 40 case *DefStmt: 41 Walk(n.Name, f) 42 for _, param := range n.Params { 43 Walk(param, f) 44 } 45 walkStmts(n.Body, f) 46 47 case *ForStmt: 48 Walk(n.Vars, f) 49 Walk(n.X, f) 50 walkStmts(n.Body, f) 51 52 case *ReturnStmt: 53 if n.Result != nil { 54 Walk(n.Result, f) 55 } 56 57 case *LoadStmt: 58 Walk(n.Module, f) 59 for _, from := range n.From { 60 Walk(from, f) 61 } 62 for _, to := range n.To { 63 Walk(to, f) 64 } 65 66 case *Ident, *Literal: 67 // no-op 68 69 case *ListExpr: 70 for _, x := range n.List { 71 Walk(x, f) 72 } 73 74 case *ParenExpr: 75 Walk(n.X, f) 76 77 case *CondExpr: 78 Walk(n.Cond, f) 79 Walk(n.True, f) 80 Walk(n.False, f) 81 82 case *IndexExpr: 83 Walk(n.X, f) 84 Walk(n.Y, f) 85 86 case *DictEntry: 87 Walk(n.Key, f) 88 Walk(n.Value, f) 89 90 case *SliceExpr: 91 Walk(n.X, f) 92 if n.Lo != nil { 93 Walk(n.Lo, f) 94 } 95 if n.Hi != nil { 96 Walk(n.Hi, f) 97 } 98 if n.Step != nil { 99 Walk(n.Step, f) 100 } 101 102 case *Comprehension: 103 Walk(n.Body, f) 104 for _, clause := range n.Clauses { 105 Walk(clause, f) 106 } 107 108 case *IfClause: 109 Walk(n.Cond, f) 110 111 case *ForClause: 112 Walk(n.Vars, f) 113 Walk(n.X, f) 114 115 case *TupleExpr: 116 for _, x := range n.List { 117 Walk(x, f) 118 } 119 120 case *DictExpr: 121 for _, entry := range n.List { 122 Walk(entry, f) 123 } 124 125 case *UnaryExpr: 126 if n.X != nil { 127 Walk(n.X, f) 128 } 129 130 case *BinaryExpr: 131 Walk(n.X, f) 132 Walk(n.Y, f) 133 134 case *DotExpr: 135 Walk(n.X, f) 136 Walk(n.Name, f) 137 138 case *CallExpr: 139 Walk(n.Fn, f) 140 for _, arg := range n.Args { 141 Walk(arg, f) 142 } 143 144 case *LambdaExpr: 145 for _, param := range n.Params { 146 Walk(param, f) 147 } 148 Walk(n.Body, f) 149 150 default: 151 panic(n) 152 } 153 154 f(nil) 155 } 156 157 func walkStmts(stmts []Stmt, f func(Node) bool) { 158 for _, stmt := range stmts { 159 Walk(stmt, f) 160 } 161 }