stmt.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. package parser
  2. import (
  3. "strings"
  4. "github.com/d5/tengo/v2/token"
  5. )
  6. // Stmt represents a statement in the AST.
  7. type Stmt interface {
  8. Node
  9. stmtNode()
  10. }
  11. // AssignStmt represents an assignment statement.
  12. type AssignStmt struct {
  13. LHS []Expr
  14. RHS []Expr
  15. Token token.Token
  16. TokenPos Pos
  17. }
  18. func (s *AssignStmt) stmtNode() {}
  19. // Pos returns the position of first character belonging to the node.
  20. func (s *AssignStmt) Pos() Pos {
  21. return s.LHS[0].Pos()
  22. }
  23. // End returns the position of first character immediately after the node.
  24. func (s *AssignStmt) End() Pos {
  25. return s.RHS[len(s.RHS)-1].End()
  26. }
  27. func (s *AssignStmt) String() string {
  28. var lhs, rhs []string
  29. for _, e := range s.LHS {
  30. lhs = append(lhs, e.String())
  31. }
  32. for _, e := range s.RHS {
  33. rhs = append(rhs, e.String())
  34. }
  35. return strings.Join(lhs, ", ") + " " + s.Token.String() +
  36. " " + strings.Join(rhs, ", ")
  37. }
  38. // BadStmt represents a bad statement.
  39. type BadStmt struct {
  40. From Pos
  41. To Pos
  42. }
  43. func (s *BadStmt) stmtNode() {}
  44. // Pos returns the position of first character belonging to the node.
  45. func (s *BadStmt) Pos() Pos {
  46. return s.From
  47. }
  48. // End returns the position of first character immediately after the node.
  49. func (s *BadStmt) End() Pos {
  50. return s.To
  51. }
  52. func (s *BadStmt) String() string {
  53. return "<bad statement>"
  54. }
  55. // BlockStmt represents a block statement.
  56. type BlockStmt struct {
  57. Stmts []Stmt
  58. LBrace Pos
  59. RBrace Pos
  60. }
  61. func (s *BlockStmt) stmtNode() {}
  62. // Pos returns the position of first character belonging to the node.
  63. func (s *BlockStmt) Pos() Pos {
  64. return s.LBrace
  65. }
  66. // End returns the position of first character immediately after the node.
  67. func (s *BlockStmt) End() Pos {
  68. return s.RBrace + 1
  69. }
  70. func (s *BlockStmt) String() string {
  71. var list []string
  72. for _, e := range s.Stmts {
  73. list = append(list, e.String())
  74. }
  75. return "{" + strings.Join(list, "; ") + "}"
  76. }
  77. // BranchStmt represents a branch statement.
  78. type BranchStmt struct {
  79. Token token.Token
  80. TokenPos Pos
  81. Label *Ident
  82. }
  83. func (s *BranchStmt) stmtNode() {}
  84. // Pos returns the position of first character belonging to the node.
  85. func (s *BranchStmt) Pos() Pos {
  86. return s.TokenPos
  87. }
  88. // End returns the position of first character immediately after the node.
  89. func (s *BranchStmt) End() Pos {
  90. if s.Label != nil {
  91. return s.Label.End()
  92. }
  93. return Pos(int(s.TokenPos) + len(s.Token.String()))
  94. }
  95. func (s *BranchStmt) String() string {
  96. var label string
  97. if s.Label != nil {
  98. label = " " + s.Label.Name
  99. }
  100. return s.Token.String() + label
  101. }
  102. // EmptyStmt represents an empty statement.
  103. type EmptyStmt struct {
  104. Semicolon Pos
  105. Implicit bool
  106. }
  107. func (s *EmptyStmt) stmtNode() {}
  108. // Pos returns the position of first character belonging to the node.
  109. func (s *EmptyStmt) Pos() Pos {
  110. return s.Semicolon
  111. }
  112. // End returns the position of first character immediately after the node.
  113. func (s *EmptyStmt) End() Pos {
  114. if s.Implicit {
  115. return s.Semicolon
  116. }
  117. return s.Semicolon + 1
  118. }
  119. func (s *EmptyStmt) String() string {
  120. return ";"
  121. }
  122. // ExportStmt represents an export statement.
  123. type ExportStmt struct {
  124. ExportPos Pos
  125. Result Expr
  126. }
  127. func (s *ExportStmt) stmtNode() {}
  128. // Pos returns the position of first character belonging to the node.
  129. func (s *ExportStmt) Pos() Pos {
  130. return s.ExportPos
  131. }
  132. // End returns the position of first character immediately after the node.
  133. func (s *ExportStmt) End() Pos {
  134. return s.Result.End()
  135. }
  136. func (s *ExportStmt) String() string {
  137. return "export " + s.Result.String()
  138. }
  139. // ExprStmt represents an expression statement.
  140. type ExprStmt struct {
  141. Expr Expr
  142. }
  143. func (s *ExprStmt) stmtNode() {}
  144. // Pos returns the position of first character belonging to the node.
  145. func (s *ExprStmt) Pos() Pos {
  146. return s.Expr.Pos()
  147. }
  148. // End returns the position of first character immediately after the node.
  149. func (s *ExprStmt) End() Pos {
  150. return s.Expr.End()
  151. }
  152. func (s *ExprStmt) String() string {
  153. return s.Expr.String()
  154. }
  155. // ForInStmt represents a for-in statement.
  156. type ForInStmt struct {
  157. ForPos Pos
  158. Key *Ident
  159. Value *Ident
  160. Iterable Expr
  161. Body *BlockStmt
  162. }
  163. func (s *ForInStmt) stmtNode() {}
  164. // Pos returns the position of first character belonging to the node.
  165. func (s *ForInStmt) Pos() Pos {
  166. return s.ForPos
  167. }
  168. // End returns the position of first character immediately after the node.
  169. func (s *ForInStmt) End() Pos {
  170. return s.Body.End()
  171. }
  172. func (s *ForInStmt) String() string {
  173. if s.Value != nil {
  174. return "for " + s.Key.String() + ", " + s.Value.String() +
  175. " in " + s.Iterable.String() + " " + s.Body.String()
  176. }
  177. return "for " + s.Key.String() + " in " + s.Iterable.String() +
  178. " " + s.Body.String()
  179. }
  180. // ForStmt represents a for statement.
  181. type ForStmt struct {
  182. ForPos Pos
  183. Init Stmt
  184. Cond Expr
  185. Post Stmt
  186. Body *BlockStmt
  187. }
  188. func (s *ForStmt) stmtNode() {}
  189. // Pos returns the position of first character belonging to the node.
  190. func (s *ForStmt) Pos() Pos {
  191. return s.ForPos
  192. }
  193. // End returns the position of first character immediately after the node.
  194. func (s *ForStmt) End() Pos {
  195. return s.Body.End()
  196. }
  197. func (s *ForStmt) String() string {
  198. var init, cond, post string
  199. if s.Init != nil {
  200. init = s.Init.String()
  201. }
  202. if s.Cond != nil {
  203. cond = s.Cond.String() + " "
  204. }
  205. if s.Post != nil {
  206. post = s.Post.String()
  207. }
  208. if init != "" || post != "" {
  209. return "for " + init + " ; " + cond + " ; " + post + s.Body.String()
  210. }
  211. return "for " + cond + s.Body.String()
  212. }
  213. // IfStmt represents an if statement.
  214. type IfStmt struct {
  215. IfPos Pos
  216. Init Stmt
  217. Cond Expr
  218. Body *BlockStmt
  219. Else Stmt // else branch; or nil
  220. }
  221. func (s *IfStmt) stmtNode() {}
  222. // Pos returns the position of first character belonging to the node.
  223. func (s *IfStmt) Pos() Pos {
  224. return s.IfPos
  225. }
  226. // End returns the position of first character immediately after the node.
  227. func (s *IfStmt) End() Pos {
  228. if s.Else != nil {
  229. return s.Else.End()
  230. }
  231. return s.Body.End()
  232. }
  233. func (s *IfStmt) String() string {
  234. var initStmt, elseStmt string
  235. if s.Init != nil {
  236. initStmt = s.Init.String() + "; "
  237. }
  238. if s.Else != nil {
  239. elseStmt = " else " + s.Else.String()
  240. }
  241. return "if " + initStmt + s.Cond.String() + " " +
  242. s.Body.String() + elseStmt
  243. }
  244. // IncDecStmt represents increment or decrement statement.
  245. type IncDecStmt struct {
  246. Expr Expr
  247. Token token.Token
  248. TokenPos Pos
  249. }
  250. func (s *IncDecStmt) stmtNode() {}
  251. // Pos returns the position of first character belonging to the node.
  252. func (s *IncDecStmt) Pos() Pos {
  253. return s.Expr.Pos()
  254. }
  255. // End returns the position of first character immediately after the node.
  256. func (s *IncDecStmt) End() Pos {
  257. return Pos(int(s.TokenPos) + 2)
  258. }
  259. func (s *IncDecStmt) String() string {
  260. return s.Expr.String() + s.Token.String()
  261. }
  262. // ReturnStmt represents a return statement.
  263. type ReturnStmt struct {
  264. ReturnPos Pos
  265. Result Expr
  266. }
  267. func (s *ReturnStmt) stmtNode() {}
  268. // Pos returns the position of first character belonging to the node.
  269. func (s *ReturnStmt) Pos() Pos {
  270. return s.ReturnPos
  271. }
  272. // End returns the position of first character immediately after the node.
  273. func (s *ReturnStmt) End() Pos {
  274. if s.Result != nil {
  275. return s.Result.End()
  276. }
  277. return s.ReturnPos + 6
  278. }
  279. func (s *ReturnStmt) String() string {
  280. if s.Result != nil {
  281. return "return " + s.Result.String()
  282. }
  283. return "return"
  284. }