blob: 7850a41cd79f958cb0cd77bef5ce3474f2988f1c [file] [log] [blame]
Alan Donovan312d1a52017-10-02 10:10:28 -04001// 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 provides a Skylark parser and abstract syntax tree.
6package syntax
7
8// A Node is a node in a Skylark syntax tree.
9type Node interface {
10 // Span returns the start and end position of the expression.
11 Span() (start, end Position)
12}
13
14// Start returns the start position of the expression.
15func Start(n Node) Position {
16 start, _ := n.Span()
17 return start
18}
19
20// End returns the end position of the expression.
21func End(n Node) Position {
22 _, end := n.Span()
23 return end
24}
25
26// A File represents a Skylark file.
27type File struct {
28 Path string
29 Stmts []Stmt
30
31 // set by resolver:
32 Locals []*Ident // this file's (comprehension-)local variables
33}
34
35func (x *File) Span() (start, end Position) {
36 if len(x.Stmts) == 0 {
37 return
38 }
39 start, _ = x.Stmts[0].Span()
40 _, end = x.Stmts[len(x.Stmts)-1].Span()
41 return start, end
42}
43
44// A Stmt is a Skylark statement.
45type Stmt interface {
46 Node
47 stmt()
48}
49
50func (*AssignStmt) stmt() {}
51func (*BranchStmt) stmt() {}
52func (*DefStmt) stmt() {}
53func (*ExprStmt) stmt() {}
54func (*ForStmt) stmt() {}
55func (*IfStmt) stmt() {}
56func (*LoadStmt) stmt() {}
57func (*ReturnStmt) stmt() {}
58
59// An AssignStmt represents an assignment:
60// x = 0
61// x, y = y, x
62// x += 1
63type AssignStmt struct {
64 OpPos Position
65 Op Token // = EQ | {PLUS,MINUS,STAR,PERCENT}_EQ
66 LHS Expr
67 RHS Expr
68}
69
70func (x *AssignStmt) Span() (start, end Position) {
71 start, _ = x.LHS.Span()
72 _, end = x.RHS.Span()
73 return
74}
75
76// A Function represents the common parts of LambdaExpr and DefStmt.
77type Function struct {
78 StartPos Position // position of DEF or LAMBDA token
79 Params []Expr // param = ident | ident=expr | *ident | **ident
80 Body []Stmt
81
82 // set by resolver:
83 HasVarargs bool // whether params includes *args (convenience)
84 HasKwargs bool // whether params includes **kwargs (convenience)
85 Locals []*Ident // this function's local variables, parameters first
86 FreeVars []*Ident // enclosing local variables to capture in closure
87}
88
89func (x *Function) Span() (start, end Position) {
90 _, end = x.Body[len(x.Body)-1].Span()
91 return x.StartPos, end
92}
93
94// A DefStmt represents a function definition.
95type DefStmt struct {
96 Def Position
97 Name *Ident
98 Function
99}
100
101func (x *DefStmt) Span() (start, end Position) {
102 _, end = x.Function.Body[len(x.Body)-1].Span()
103 return x.Def, end
104}
105
106// An ExprStmt is an expression evaluated for side effects.
107type ExprStmt struct {
108 X Expr
109}
110
111func (x *ExprStmt) Span() (start, end Position) {
112 return x.X.Span()
113}
114
115// An IfStmt is a conditional: If Cond: True; else: False.
116// 'elseif' is desugared into a chain of IfStmts.
117type IfStmt struct {
118 If Position // IF or ELIF
119 Cond Expr
120 True []Stmt
121 ElsePos Position // ELSE or ELIF
122 False []Stmt // optional
123}
124
125func (x *IfStmt) Span() (start, end Position) {
126 body := x.False
127 if body == nil {
128 body = x.True
129 }
130 _, end = body[len(body)-1].Span()
131 return x.If, end
132}
133
134// A LoadStmt loads another module and binds names from it:
135// load(Module, "x", y="foo").
136//
137// The AST is slightly unfaithful to the concrete syntax here because
138// Skylark's load statement, so that it can be implemented in Python,
139// binds some names (like y above) with an identifier and some (like x)
140// without. For consistency we create fake identifiers for all the
141// strings.
142type LoadStmt struct {
143 Load Position
144 Module *Literal // a string
145 From []*Ident // name defined in loading module
146 To []*Ident // name in loaded module
147 Rparen Position
148}
149
150func (x *LoadStmt) Span() (start, end Position) {
151 return x.Load, x.Rparen
152}
153
154// A BranchStmt changes the flow of control: break, continue, pass.
155type BranchStmt struct {
156 Token Token // = BREAK | CONTINUE | PASS
157 TokenPos Position
158}
159
160func (x *BranchStmt) Span() (start, end Position) {
161 return x.TokenPos, x.TokenPos.add(x.Token.String())
162}
163
164// A ReturnStmt returns from a function.
165type ReturnStmt struct {
166 Return Position
167 Result Expr // may be nil
168}
169
170func (x *ReturnStmt) Span() (start, end Position) {
171 if x.Result == nil {
172 return x.Return, x.Return.add("return")
173 }
174 _, end = x.Result.Span()
175 return x.Return, end
176}
177
178// An Expr is a Skylark expression.
179type Expr interface {
180 Node
181 expr()
182}
183
184func (*BinaryExpr) expr() {}
185func (*CallExpr) expr() {}
186func (*Comprehension) expr() {}
187func (*CondExpr) expr() {}
188func (*DictEntry) expr() {}
189func (*DictExpr) expr() {}
190func (*DotExpr) expr() {}
191func (*Ident) expr() {}
192func (*IndexExpr) expr() {}
193func (*LambdaExpr) expr() {}
194func (*ListExpr) expr() {}
195func (*Literal) expr() {}
196func (*SliceExpr) expr() {}
197func (*TupleExpr) expr() {}
198func (*UnaryExpr) expr() {}
199
200// An Ident represents an identifier.
201type Ident struct {
202 NamePos Position
203 Name string
204
205 // set by resolver:
206
207 Scope uint8 // one of resolve.{Undefined,Local,Free,Global,Builtin}
208 Index int // index into enclosing {DefStmt,File}.Locals (if scope==Local) or DefStmt.FreeVars (if scope==Free)
209}
210
211func (x *Ident) Span() (start, end Position) {
212 return x.NamePos, x.NamePos.add(x.Name)
213}
214
215// A Literal represents a literal string or number.
216type Literal struct {
217 Token Token // = STRING | INT
218 TokenPos Position
219 Raw string // uninterpreted text
220 Value interface{} // = string | int
221}
222
223func (x *Literal) Span() (start, end Position) {
224 return x.TokenPos, x.TokenPos.add(x.Raw)
225}
226
227// A CallExpr represents a function call expression: Fn(Args).
228type CallExpr struct {
229 Fn Expr
230 Lparen Position
231 Args []Expr
232 Rparen Position
233}
234
235func (x *CallExpr) Span() (start, end Position) {
236 start, _ = x.Fn.Span()
237 return start, x.Rparen.add(")")
238}
239
240// A DotExpr represents a field or method selector: X.Name.
241type DotExpr struct {
242 X Expr
243 Dot Position
244 NamePos Position
245 Name *Ident
246}
247
248func (x *DotExpr) Span() (start, end Position) {
249 start, _ = x.X.Span()
250 _, end = x.Name.Span()
251 return
252}
253
254// A Comprehension represents a list or dict comprehension:
255// [Body for ... if ...] or {Body for ... if ...}
256type Comprehension struct {
257 Curly bool // {x:y for ...} or {x for ...}, not [x for ...]
258 Lbrack Position
259 Body Expr
260 Clauses []Node // = *ForClause | *IfClause
261 Rbrack Position
262}
263
264func (x *Comprehension) Span() (start, end Position) {
265 return x.Lbrack, x.Rbrack.add("]")
266}
267
268// A ForStmt represents a loop: for Vars in X: Body.
269type ForStmt struct {
270 For Position
271 Vars Expr // name, or tuple of names
272 X Expr
273 Body []Stmt
274}
275
276func (x *ForStmt) Span() (start, end Position) {
277 _, end = x.Body[len(x.Body)-1].Span()
278 return x.For, end
279}
280
281// A ForClause represents a for clause in a list comprehension: for Vars in X.
282type ForClause struct {
283 For Position
284 Vars Expr // name, or tuple of names
285 In Position
286 X Expr
287}
288
289func (x *ForClause) Span() (start, end Position) {
290 _, end = x.X.Span()
291 return x.For, end
292}
293
294// An IfClause represents an if clause in a list comprehension: if Cond.
295type IfClause struct {
296 If Position
297 Cond Expr
298}
299
300func (x *IfClause) Span() (start, end Position) {
301 _, end = x.Cond.Span()
302 return x.If, end
303}
304
305// A DictExpr represents a dictionary literal: { List }.
306type DictExpr struct {
307 Lbrace Position
308 List []Expr // all *DictEntrys
309 Rbrace Position
310}
311
312func (x *DictExpr) Span() (start, end Position) {
313 return x.Lbrace, x.Rbrace.add("}")
314}
315
316// A DictEntry represents a dictionary entry: Key: Value.
317// Used only within a DictExpr.
318type DictEntry struct {
319 Key Expr
320 Colon Position
321 Value Expr
322}
323
324func (x *DictEntry) Span() (start, end Position) {
325 start, _ = x.Key.Span()
326 _, end = x.Value.Span()
327 return start, end
328}
329
330// A LambdaExpr represents an inline function abstraction.
331//
332// Although they may be added in future, lambda expressions are not
333// currently part of the Skylark spec, so their use is controlled by the
334// resolver.AllowLambda flag.
335type LambdaExpr struct {
336 Lambda Position
337 Function
338}
339
340func (x *LambdaExpr) Span() (start, end Position) {
341 _, end = x.Function.Body[len(x.Body)-1].Span()
342 return x.Lambda, end
343}
344
345// A ListExpr represents a list literal: [ List ].
346type ListExpr struct {
347 Lbrack Position
348 List []Expr
349 Rbrack Position
350}
351
352func (x *ListExpr) Span() (start, end Position) {
353 return x.Lbrack, x.Rbrack.add("]")
354}
355
356// CondExpr represents the conditional: X if COND else ELSE.
357type CondExpr struct {
358 If Position
359 Cond Expr
360 True Expr
361 ElsePos Position
362 False Expr
363}
364
365func (x *CondExpr) Span() (start, end Position) {
366 start, _ = x.True.Span()
367 _, end = x.False.Span()
368 return start, end
369}
370
371// A TupleExpr represents a tuple literal: (List).
372type TupleExpr struct {
373 Lparen Position // optional (e.g. in x, y = 0, 1), but required if List is empty
374 List []Expr
375 Rparen Position
376}
377
378func (x *TupleExpr) Span() (start, end Position) {
379 if x.Lparen.IsValid() {
380 return x.Lparen, x.Rparen
381 } else {
382 return Start(x.List[0]), End(x.List[len(x.List)-1])
383 }
384}
385
386// A UnaryExpr represents a unary expression: Op X.
387type UnaryExpr struct {
388 OpPos Position
389 Op Token
390 X Expr
391}
392
393func (x *UnaryExpr) Span() (start, end Position) {
394 _, end = x.X.Span()
395 return x.OpPos, end
396}
397
398// A BinaryExpr represents a binary expression: X Op Y.
399type BinaryExpr struct {
400 X Expr
401 OpPos Position
402 Op Token
403 Y Expr
404}
405
406func (x *BinaryExpr) Span() (start, end Position) {
407 start, _ = x.X.Span()
408 _, end = x.Y.Span()
409 return start, end
410}
411
412// A SliceExpr represents a slice or substring expression: X[Lo:Hi:Step].
413type SliceExpr struct {
414 X Expr
415 Lbrack Position
416 Lo, Hi, Step Expr // all optional
417 Rbrack Position
418}
419
420func (x *SliceExpr) Span() (start, end Position) {
421 start, _ = x.X.Span()
422 return start, x.Rbrack
423}
424
425// An IndexExpr represents an index expression: X[Y].
426type IndexExpr struct {
427 X Expr
428 Lbrack Position
429 Y Expr
430 Rbrack Position
431}
432
433func (x *IndexExpr) Span() (start, end Position) {
434 start, _ = x.X.Span()
435 return start, x.Rbrack
436}