walk.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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 *BinaryExpression:
  37. if n != nil {
  38. Walk(v, n.Left)
  39. Walk(v, n.Right)
  40. }
  41. case *BlockStatement:
  42. if n != nil {
  43. for _, s := range n.List {
  44. Walk(v, s)
  45. }
  46. }
  47. case *BooleanLiteral:
  48. case *BracketExpression:
  49. if n != nil {
  50. Walk(v, n.Left)
  51. Walk(v, n.Member)
  52. }
  53. case *BranchStatement:
  54. if n != nil {
  55. Walk(v, n.Label)
  56. }
  57. case *CallExpression:
  58. if n != nil {
  59. Walk(v, n.Callee)
  60. for _, a := range n.ArgumentList {
  61. Walk(v, a)
  62. }
  63. }
  64. case *CaseStatement:
  65. if n != nil {
  66. Walk(v, n.Test)
  67. for _, c := range n.Consequent {
  68. Walk(v, c)
  69. }
  70. }
  71. case *CatchStatement:
  72. if n != nil {
  73. Walk(v, n.Parameter)
  74. Walk(v, n.Body)
  75. }
  76. case *ConditionalExpression:
  77. if n != nil {
  78. Walk(v, n.Test)
  79. Walk(v, n.Consequent)
  80. Walk(v, n.Alternate)
  81. }
  82. case *DebuggerStatement:
  83. case *DoWhileStatement:
  84. if n != nil {
  85. Walk(v, n.Test)
  86. Walk(v, n.Body)
  87. }
  88. case *DotExpression:
  89. if n != nil {
  90. Walk(v, n.Left)
  91. }
  92. case *EmptyExpression:
  93. case *EmptyStatement:
  94. case *ExpressionStatement:
  95. if n != nil {
  96. Walk(v, n.Expression)
  97. }
  98. case *ForInStatement:
  99. if n != nil {
  100. Walk(v, n.Into)
  101. Walk(v, n.Source)
  102. Walk(v, n.Body)
  103. }
  104. case *ForStatement:
  105. if n != nil {
  106. Walk(v, n.Initializer)
  107. Walk(v, n.Update)
  108. Walk(v, n.Test)
  109. Walk(v, n.Body)
  110. }
  111. case *FunctionLiteral:
  112. if n != nil {
  113. Walk(v, n.Name)
  114. for _, p := range n.ParameterList.List {
  115. Walk(v, p)
  116. }
  117. Walk(v, n.Body)
  118. }
  119. case *FunctionStatement:
  120. if n != nil {
  121. Walk(v, n.Function)
  122. }
  123. case *Identifier:
  124. case *IfStatement:
  125. if n != nil {
  126. Walk(v, n.Test)
  127. Walk(v, n.Consequent)
  128. Walk(v, n.Alternate)
  129. }
  130. case *LabelledStatement:
  131. if n != nil {
  132. Walk(v, n.Statement)
  133. }
  134. case *NewExpression:
  135. if n != nil {
  136. Walk(v, n.Callee)
  137. for _, a := range n.ArgumentList {
  138. Walk(v, a)
  139. }
  140. }
  141. case *NullLiteral:
  142. case *NumberLiteral:
  143. case *ObjectLiteral:
  144. if n != nil {
  145. for _, p := range n.Value {
  146. Walk(v, p.Value)
  147. }
  148. }
  149. case *Program:
  150. if n != nil {
  151. for _, b := range n.Body {
  152. Walk(v, b)
  153. }
  154. }
  155. case *RegExpLiteral:
  156. case *ReturnStatement:
  157. if n != nil {
  158. Walk(v, n.Argument)
  159. }
  160. case *SequenceExpression:
  161. if n != nil {
  162. for _, e := range n.Sequence {
  163. Walk(v, e)
  164. }
  165. }
  166. case *StringLiteral:
  167. case *SwitchStatement:
  168. if n != nil {
  169. Walk(v, n.Discriminant)
  170. for _, c := range n.Body {
  171. Walk(v, c)
  172. }
  173. }
  174. case *ThisExpression:
  175. case *ThrowStatement:
  176. if n != nil {
  177. Walk(v, n.Argument)
  178. }
  179. case *TryStatement:
  180. if n != nil {
  181. Walk(v, n.Body)
  182. Walk(v, n.Catch)
  183. Walk(v, n.Finally)
  184. }
  185. case *UnaryExpression:
  186. if n != nil {
  187. Walk(v, n.Operand)
  188. }
  189. case *VariableExpression:
  190. if n != nil {
  191. Walk(v, n.Initializer)
  192. }
  193. case *VariableStatement:
  194. if n != nil {
  195. for _, e := range n.List {
  196. Walk(v, e)
  197. }
  198. }
  199. case *WhileStatement:
  200. if n != nil {
  201. Walk(v, n.Test)
  202. Walk(v, n.Body)
  203. }
  204. case *WithStatement:
  205. if n != nil {
  206. Walk(v, n.Object)
  207. Walk(v, n.Body)
  208. }
  209. default:
  210. panic(fmt.Sprintf("Walk: unexpected node type %T", n))
  211. }
  212. }