syntax.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. /*
  2. Copyright 2016 Google Inc. All Rights Reserved.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. // Package build implements parsing and printing of BUILD files.
  14. package build
  15. // Syntax data structure definitions.
  16. import (
  17. "strings"
  18. "unicode/utf8"
  19. )
  20. // A Position describes the position between two bytes of input.
  21. type Position struct {
  22. Line int // line in input (starting at 1)
  23. LineRune int // rune in line (starting at 1)
  24. Byte int // byte in input (starting at 0)
  25. }
  26. // add returns the position at the end of s, assuming it starts at p.
  27. func (p Position) add(s string) Position {
  28. p.Byte += len(s)
  29. if n := strings.Count(s, "\n"); n > 0 {
  30. p.Line += n
  31. s = s[strings.LastIndex(s, "\n")+1:]
  32. p.LineRune = 1
  33. }
  34. p.LineRune += utf8.RuneCountInString(s)
  35. return p
  36. }
  37. // An Expr represents an input element.
  38. type Expr interface {
  39. // Span returns the start and end position of the expression,
  40. // excluding leading or trailing comments.
  41. Span() (start, end Position)
  42. // Comment returns the comments attached to the expression.
  43. // This method would normally be named 'Comments' but that
  44. // would interfere with embedding a type of the same name.
  45. Comment() *Comments
  46. }
  47. // A Comment represents a single # comment.
  48. type Comment struct {
  49. Start Position
  50. Token string // without trailing newline
  51. }
  52. // Comments collects the comments associated with an expression.
  53. type Comments struct {
  54. Before []Comment // whole-line comments before this expression
  55. Suffix []Comment // end-of-line comments after this expression
  56. // For top-level expressions only, After lists whole-line
  57. // comments following the expression.
  58. After []Comment
  59. }
  60. // Comment returns the receiver. This isn't useful by itself, but
  61. // a Comments struct is embedded into all the expression
  62. // implementation types, and this gives each of those a Comment
  63. // method to satisfy the Expr interface.
  64. func (c *Comments) Comment() *Comments {
  65. return c
  66. }
  67. // stmtsEnd returns the end position of the last non-nil statement
  68. func stmtsEnd(stmts []Expr) Position {
  69. for i := len(stmts) - 1; i >= 0; i-- {
  70. if stmts[i] != nil {
  71. _, end := stmts[i].Span()
  72. return end
  73. }
  74. }
  75. return Position{}
  76. }
  77. // A File represents an entire BUILD or .bzl file.
  78. type File struct {
  79. Path string // file path, relative to workspace directory
  80. Pkg string // optional; the package of the file
  81. Type FileType
  82. Comments
  83. Stmt []Expr
  84. }
  85. // DisplayPath returns the filename if it's not empty, "<stdin>" otherwise
  86. func (f *File) DisplayPath() string {
  87. if f.Path == "" {
  88. return "<stdin>"
  89. }
  90. return f.Path
  91. }
  92. func (f *File) Span() (start, end Position) {
  93. if len(f.Stmt) == 0 {
  94. p := Position{Line: 1, LineRune: 1}
  95. return p, p
  96. }
  97. start = Position{}
  98. end = stmtsEnd(f.Stmt)
  99. return start, end
  100. }
  101. // A CommentBlock represents a top-level block of comments separate
  102. // from any rule.
  103. type CommentBlock struct {
  104. Comments
  105. Start Position
  106. }
  107. func (x *CommentBlock) Span() (start, end Position) {
  108. return x.Start, x.Start
  109. }
  110. // An Ident represents an identifier.
  111. type Ident struct {
  112. Comments
  113. NamePos Position
  114. Name string
  115. }
  116. func (x *Ident) Span() (start, end Position) {
  117. return x.NamePos, x.NamePos.add(x.Name)
  118. }
  119. // BranchStmt represents a `pass`, `break`, or `continue` statement.
  120. type BranchStmt struct {
  121. Comments
  122. Token string // pass, break, continue
  123. TokenPos Position
  124. }
  125. func (x *BranchStmt) Span() (start, end Position) {
  126. return x.TokenPos, x.TokenPos.add(x.Token)
  127. }
  128. func (x *Ident) asString() *StringExpr {
  129. _, end := x.Span()
  130. return &StringExpr{
  131. Comments: x.Comments,
  132. Start: x.NamePos,
  133. Value: x.Name,
  134. End: end,
  135. }
  136. }
  137. // A LiteralExpr represents a literal number.
  138. type LiteralExpr struct {
  139. Comments
  140. Start Position
  141. Token string // identifier token
  142. }
  143. func (x *LiteralExpr) Span() (start, end Position) {
  144. return x.Start, x.Start.add(x.Token)
  145. }
  146. // A StringExpr represents a single literal string.
  147. type StringExpr struct {
  148. Comments
  149. Start Position
  150. Value string // string value (decoded)
  151. TripleQuote bool // triple quote output
  152. End Position
  153. // To allow specific formatting of string literals,
  154. // at least within our requirements, record the
  155. // preferred form of Value. This field is a hint:
  156. // it is only used if it is a valid quoted form for Value.
  157. Token string
  158. }
  159. func (x *StringExpr) Span() (start, end Position) {
  160. return x.Start, x.End
  161. }
  162. // An End represents the end of a parenthesized or bracketed expression.
  163. // It is a place to hang comments.
  164. type End struct {
  165. Comments
  166. Pos Position
  167. }
  168. func (x *End) Span() (start, end Position) {
  169. return x.Pos, x.Pos.add(")")
  170. }
  171. // A CallExpr represents a function call expression: X(List).
  172. type CallExpr struct {
  173. Comments
  174. X Expr
  175. ListStart Position // position of (
  176. List []Expr
  177. End // position of )
  178. ForceCompact bool // force compact (non-multiline) form when printing
  179. ForceMultiLine bool // force multiline form when printing
  180. }
  181. func (x *CallExpr) Span() (start, end Position) {
  182. start, _ = x.X.Span()
  183. return start, x.End.Pos.add(")")
  184. }
  185. // A DotExpr represents a field selector: X.Name.
  186. type DotExpr struct {
  187. Comments
  188. X Expr
  189. Dot Position
  190. NamePos Position
  191. Name string
  192. }
  193. func (x *DotExpr) Span() (start, end Position) {
  194. start, _ = x.X.Span()
  195. return start, x.NamePos.add(x.Name)
  196. }
  197. // A Comprehension represents a list comprehension expression: [X for ... if ...].
  198. type Comprehension struct {
  199. Comments
  200. Curly bool // curly braces (as opposed to square brackets)
  201. Lbrack Position
  202. Body Expr
  203. Clauses []Expr // = *ForClause | *IfClause
  204. ForceMultiLine bool // split expression across multiple lines
  205. End
  206. }
  207. func (x *Comprehension) Span() (start, end Position) {
  208. return x.Lbrack, x.End.Pos.add("]")
  209. }
  210. // A ForClause represents a for clause in a list comprehension: for Var in Expr.
  211. type ForClause struct {
  212. Comments
  213. For Position
  214. Vars Expr
  215. In Position
  216. X Expr
  217. }
  218. func (x *ForClause) Span() (start, end Position) {
  219. _, end = x.X.Span()
  220. return x.For, end
  221. }
  222. // An IfClause represents an if clause in a list comprehension: if Cond.
  223. type IfClause struct {
  224. Comments
  225. If Position
  226. Cond Expr
  227. }
  228. func (x *IfClause) Span() (start, end Position) {
  229. _, end = x.Cond.Span()
  230. return x.If, end
  231. }
  232. // A KeyValueExpr represents a dictionary entry: Key: Value.
  233. type KeyValueExpr struct {
  234. Comments
  235. Key Expr
  236. Colon Position
  237. Value Expr
  238. }
  239. func (x *KeyValueExpr) Span() (start, end Position) {
  240. start, _ = x.Key.Span()
  241. _, end = x.Value.Span()
  242. return start, end
  243. }
  244. // A DictExpr represents a dictionary literal: { List }.
  245. type DictExpr struct {
  246. Comments
  247. Start Position
  248. List []Expr // all *KeyValueExprs
  249. End
  250. ForceMultiLine bool // force multiline form when printing
  251. }
  252. func (x *DictExpr) Span() (start, end Position) {
  253. return x.Start, x.End.Pos.add("}")
  254. }
  255. // A ListExpr represents a list literal: [ List ].
  256. type ListExpr struct {
  257. Comments
  258. Start Position
  259. List []Expr
  260. End
  261. ForceMultiLine bool // force multiline form when printing
  262. }
  263. func (x *ListExpr) Span() (start, end Position) {
  264. return x.Start, x.End.Pos.add("]")
  265. }
  266. // A SetExpr represents a set literal: { List }.
  267. type SetExpr struct {
  268. Comments
  269. Start Position
  270. List []Expr
  271. End
  272. ForceMultiLine bool // force multiline form when printing
  273. }
  274. func (x *SetExpr) Span() (start, end Position) {
  275. return x.Start, x.End.Pos.add("}")
  276. }
  277. // A TupleExpr represents a tuple literal: (List)
  278. type TupleExpr struct {
  279. Comments
  280. NoBrackets bool // true if a tuple has no brackets, e.g. `a, b = x`
  281. Start Position
  282. List []Expr
  283. End
  284. ForceCompact bool // force compact (non-multiline) form when printing
  285. ForceMultiLine bool // force multiline form when printing
  286. }
  287. func (x *TupleExpr) Span() (start, end Position) {
  288. if !x.NoBrackets {
  289. return x.Start, x.End.Pos.add(")")
  290. }
  291. start, _ = x.List[0].Span()
  292. _, end = x.List[len(x.List)-1].Span()
  293. return start, end
  294. }
  295. // A UnaryExpr represents a unary expression: Op X.
  296. type UnaryExpr struct {
  297. Comments
  298. OpStart Position
  299. Op string
  300. X Expr
  301. }
  302. func (x *UnaryExpr) Span() (start, end Position) {
  303. if x.X == nil {
  304. return x.OpStart, x.OpStart
  305. }
  306. _, end = x.X.Span()
  307. return x.OpStart, end
  308. }
  309. // A BinaryExpr represents a binary expression: X Op Y.
  310. type BinaryExpr struct {
  311. Comments
  312. X Expr
  313. OpStart Position
  314. Op string
  315. LineBreak bool // insert line break between Op and Y
  316. Y Expr
  317. }
  318. func (x *BinaryExpr) Span() (start, end Position) {
  319. start, _ = x.X.Span()
  320. _, end = x.Y.Span()
  321. return start, end
  322. }
  323. // An AssignExpr represents a binary expression with `=`: LHS = RHS.
  324. type AssignExpr struct {
  325. Comments
  326. LHS Expr
  327. OpPos Position
  328. Op string
  329. LineBreak bool // insert line break between Op and RHS
  330. RHS Expr
  331. }
  332. func (x *AssignExpr) Span() (start, end Position) {
  333. start, _ = x.LHS.Span()
  334. _, end = x.RHS.Span()
  335. return start, end
  336. }
  337. // A ParenExpr represents a parenthesized expression: (X).
  338. type ParenExpr struct {
  339. Comments
  340. Start Position
  341. X Expr
  342. End
  343. ForceMultiLine bool // insert line break after opening ( and before closing )
  344. }
  345. func (x *ParenExpr) Span() (start, end Position) {
  346. return x.Start, x.End.Pos.add(")")
  347. }
  348. // A SliceExpr represents a slice expression: expr[from:to] or expr[from:to:step] .
  349. type SliceExpr struct {
  350. Comments
  351. X Expr
  352. SliceStart Position
  353. From Expr
  354. FirstColon Position
  355. To Expr
  356. SecondColon Position
  357. Step Expr
  358. End Position
  359. }
  360. func (x *SliceExpr) Span() (start, end Position) {
  361. start, _ = x.X.Span()
  362. return start, x.End.add("]")
  363. }
  364. // An IndexExpr represents an index expression: X[Y].
  365. type IndexExpr struct {
  366. Comments
  367. X Expr
  368. IndexStart Position
  369. Y Expr
  370. End Position
  371. }
  372. func (x *IndexExpr) Span() (start, end Position) {
  373. start, _ = x.X.Span()
  374. return start, x.End.add("]")
  375. }
  376. // A Function represents the common parts of LambdaExpr and DefStmt
  377. type Function struct {
  378. Comments
  379. StartPos Position // position of DEF or LAMBDA token
  380. Params []Expr
  381. Body []Expr
  382. }
  383. func (x *Function) Span() (start, end Position) {
  384. _, end = x.Body[len(x.Body)-1].Span()
  385. return x.StartPos, end
  386. }
  387. // A LambdaExpr represents a lambda expression: lambda Var: Expr.
  388. type LambdaExpr struct {
  389. Comments
  390. Function
  391. }
  392. func (x *LambdaExpr) Span() (start, end Position) {
  393. return x.Function.Span()
  394. }
  395. // ConditionalExpr represents the conditional: X if TEST else ELSE.
  396. type ConditionalExpr struct {
  397. Comments
  398. Then Expr
  399. IfStart Position
  400. Test Expr
  401. ElseStart Position
  402. Else Expr
  403. }
  404. // Span returns the start and end position of the expression,
  405. // excluding leading or trailing comments.
  406. func (x *ConditionalExpr) Span() (start, end Position) {
  407. start, _ = x.Then.Span()
  408. _, end = x.Else.Span()
  409. return start, end
  410. }
  411. // A LoadStmt loads another module and binds names from it:
  412. // load(Module, "x", y="foo").
  413. //
  414. // The AST is slightly unfaithful to the concrete syntax here because
  415. // Skylark's load statement, so that it can be implemented in Python,
  416. // binds some names (like y above) with an identifier and some (like x)
  417. // without. For consistency we create fake identifiers for all the
  418. // strings.
  419. type LoadStmt struct {
  420. Comments
  421. Load Position
  422. Module *StringExpr
  423. From []*Ident // name defined in loading module
  424. To []*Ident // name in loaded module
  425. Rparen End
  426. ForceCompact bool // force compact (non-multiline) form when printing
  427. }
  428. func (x *LoadStmt) Span() (start, end Position) {
  429. return x.Load, x.Rparen.Pos.add(")")
  430. }
  431. // A DefStmt represents a function definition expression: def foo(List):.
  432. type DefStmt struct {
  433. Comments
  434. Function
  435. Name string
  436. ColonPos Position // position of the ":"
  437. ForceCompact bool // force compact (non-multiline) form when printing the arguments
  438. ForceMultiLine bool // force multiline form when printing the arguments
  439. }
  440. func (x *DefStmt) Span() (start, end Position) {
  441. return x.Function.Span()
  442. }
  443. // HeaderSpan returns the span of the function header `def f(...):`
  444. func (x *DefStmt) HeaderSpan() (start, end Position) {
  445. return x.Function.StartPos, x.ColonPos
  446. }
  447. // A ReturnStmt represents a return statement: return f(x).
  448. type ReturnStmt struct {
  449. Comments
  450. Return Position
  451. Result Expr // may be nil
  452. }
  453. func (x *ReturnStmt) Span() (start, end Position) {
  454. if x.Result == nil {
  455. return x.Return, x.Return.add("return")
  456. }
  457. _, end = x.Result.Span()
  458. return x.Return, end
  459. }
  460. // A ForStmt represents a for loop block: for x in range(10):.
  461. type ForStmt struct {
  462. Comments
  463. Function
  464. For Position // position of for
  465. Vars Expr
  466. X Expr
  467. Body []Expr
  468. }
  469. func (x *ForStmt) Span() (start, end Position) {
  470. end = stmtsEnd(x.Body)
  471. return x.For, end
  472. }
  473. // An IfStmt represents an if-else block: if x: ... else: ... .
  474. // `elif`s are treated as a chain of `IfStmt`s.
  475. type IfStmt struct {
  476. Comments
  477. If Position // position of if
  478. Cond Expr
  479. True []Expr
  480. ElsePos End // position of else or elif
  481. False []Expr // optional
  482. }
  483. func (x *IfStmt) Span() (start, end Position) {
  484. body := x.False
  485. if body == nil {
  486. body = x.True
  487. }
  488. end = stmtsEnd(body)
  489. return x.If, end
  490. }