walk.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package ast
  2. import "fmt"
  3. // Visitor Enter method is invoked for each node encountered by Walk.
  4. // If the result visitor w is not nil, Walk visits each of the children
  5. // of node with the visitor v, followed by a call of the Exit method.
  6. type Visitor interface {
  7. Enter(n Node) (v Visitor)
  8. Exit(n Node)
  9. }
  10. // Walk traverses an AST in depth-first order: It starts by calling
  11. // v.Enter(node); node must not be nil. If the visitor v returned by
  12. // v.Enter(node) is not nil, Walk is invoked recursively with visitor
  13. // v for each of the non-nil children of node, followed by a call
  14. // of v.Exit(node).
  15. func Walk(v Visitor, n Node) {
  16. if n == nil {
  17. return
  18. }
  19. if v = v.Enter(n); v == nil {
  20. return
  21. }
  22. defer v.Exit(n)
  23. switch n := n.(type) {
  24. case *ArrayLiteral:
  25. if n != nil {
  26. for _, ex := range n.Value {
  27. Walk(v, ex)
  28. }
  29. }
  30. case *AssignExpression:
  31. if n != nil {
  32. Walk(v, n.Left)
  33. Walk(v, n.Right)
  34. }
  35. case *BadExpression:
  36. case *BadStatement:
  37. case *BinaryExpression:
  38. if n != nil {
  39. Walk(v, n.Left)
  40. Walk(v, n.Right)
  41. }
  42. case *BlockStatement:
  43. if n != nil {
  44. for _, s := range n.List {
  45. Walk(v, s)
  46. }
  47. }
  48. case *BooleanLiteral:
  49. case *BracketExpression:
  50. if n != nil {
  51. Walk(v, n.Left)
  52. Walk(v, n.Member)
  53. }
  54. case *BranchStatement:
  55. if n != nil {
  56. Walk(v, n.Label)
  57. }
  58. case *CallExpression:
  59. if n != nil {
  60. Walk(v, n.Callee)
  61. for _, a := range n.ArgumentList {
  62. Walk(v, a)
  63. }
  64. }
  65. case *CaseStatement:
  66. if n != nil {
  67. Walk(v, n.Test)
  68. for _, c := range n.Consequent {
  69. Walk(v, c)
  70. }
  71. }
  72. case *CatchStatement:
  73. if n != nil {
  74. Walk(v, n.Parameter)
  75. Walk(v, n.Body)
  76. }
  77. case *ConditionalExpression:
  78. if n != nil {
  79. Walk(v, n.Test)
  80. Walk(v, n.Consequent)
  81. Walk(v, n.Alternate)
  82. }
  83. case *DebuggerStatement:
  84. case *DoWhileStatement:
  85. if n != nil {
  86. Walk(v, n.Test)
  87. Walk(v, n.Body)
  88. }
  89. case *DotExpression:
  90. if n != nil {
  91. Walk(v, n.Left)
  92. Walk(v, n.Identifier)
  93. }
  94. case *EmptyExpression:
  95. case *EmptyStatement:
  96. case *ExpressionStatement:
  97. if n != nil {
  98. Walk(v, n.Expression)
  99. }
  100. case *ForInStatement:
  101. if n != nil {
  102. Walk(v, n.Into)
  103. Walk(v, n.Source)
  104. Walk(v, n.Body)
  105. }
  106. case *ForStatement:
  107. if n != nil {
  108. Walk(v, n.Initializer)
  109. Walk(v, n.Update)
  110. Walk(v, n.Test)
  111. Walk(v, n.Body)
  112. }
  113. case *FunctionLiteral:
  114. if n != nil {
  115. Walk(v, n.Name)
  116. for _, p := range n.ParameterList.List {
  117. Walk(v, p)
  118. }
  119. Walk(v, n.Body)
  120. }
  121. case *FunctionStatement:
  122. if n != nil {
  123. Walk(v, n.Function)
  124. }
  125. case *Identifier:
  126. case *IfStatement:
  127. if n != nil {
  128. Walk(v, n.Test)
  129. Walk(v, n.Consequent)
  130. Walk(v, n.Alternate)
  131. }
  132. case *LabelledStatement:
  133. if n != nil {
  134. Walk(v, n.Label)
  135. Walk(v, n.Statement)
  136. }
  137. case *NewExpression:
  138. if n != nil {
  139. Walk(v, n.Callee)
  140. for _, a := range n.ArgumentList {
  141. Walk(v, a)
  142. }
  143. }
  144. case *NullLiteral:
  145. case *NumberLiteral:
  146. case *ObjectLiteral:
  147. if n != nil {
  148. for _, p := range n.Value {
  149. Walk(v, p.Value)
  150. }
  151. }
  152. case *Program:
  153. if n != nil {
  154. for _, b := range n.Body {
  155. Walk(v, b)
  156. }
  157. }
  158. case *RegExpLiteral:
  159. case *ReturnStatement:
  160. if n != nil {
  161. Walk(v, n.Argument)
  162. }
  163. case *SequenceExpression:
  164. if n != nil {
  165. for _, e := range n.Sequence {
  166. Walk(v, e)
  167. }
  168. }
  169. case *StringLiteral:
  170. case *SwitchStatement:
  171. if n != nil {
  172. Walk(v, n.Discriminant)
  173. for _, c := range n.Body {
  174. Walk(v, c)
  175. }
  176. }
  177. case *ThisExpression:
  178. case *ThrowStatement:
  179. if n != nil {
  180. Walk(v, n.Argument)
  181. }
  182. case *TryStatement:
  183. if n != nil {
  184. Walk(v, n.Body)
  185. Walk(v, n.Catch)
  186. Walk(v, n.Finally)
  187. }
  188. case *UnaryExpression:
  189. if n != nil {
  190. Walk(v, n.Operand)
  191. }
  192. case *VariableExpression:
  193. if n != nil {
  194. Walk(v, n.Initializer)
  195. }
  196. case *VariableStatement:
  197. if n != nil {
  198. for _, e := range n.List {
  199. Walk(v, e)
  200. }
  201. }
  202. case *WhileStatement:
  203. if n != nil {
  204. Walk(v, n.Test)
  205. Walk(v, n.Body)
  206. }
  207. case *WithStatement:
  208. if n != nil {
  209. Walk(v, n.Object)
  210. Walk(v, n.Body)
  211. }
  212. default:
  213. panic(fmt.Sprintf("Walk: unexpected node type %T", n))
  214. }
  215. }