xref: /aosp_15_r20/external/starlark-go/syntax/syntax.go (revision 4947cdc739c985f6d86941e22894f5cefe7c9e9a)
1*4947cdc7SCole Faust// Copyright 2017 The Bazel Authors. All rights reserved.
2*4947cdc7SCole Faust// Use of this source code is governed by a BSD-style
3*4947cdc7SCole Faust// license that can be found in the LICENSE file.
4*4947cdc7SCole Faust
5*4947cdc7SCole Faust// Package syntax provides a Starlark parser and abstract syntax tree.
6*4947cdc7SCole Faustpackage syntax // import "go.starlark.net/syntax"
7*4947cdc7SCole Faust
8*4947cdc7SCole Faust// A Node is a node in a Starlark syntax tree.
9*4947cdc7SCole Fausttype Node interface {
10*4947cdc7SCole Faust	// Span returns the start and end position of the expression.
11*4947cdc7SCole Faust	Span() (start, end Position)
12*4947cdc7SCole Faust
13*4947cdc7SCole Faust	// Comments returns the comments associated with this node.
14*4947cdc7SCole Faust	// It returns nil if RetainComments was not specified during parsing,
15*4947cdc7SCole Faust	// or if AllocComments was not called.
16*4947cdc7SCole Faust	Comments() *Comments
17*4947cdc7SCole Faust
18*4947cdc7SCole Faust	// AllocComments allocates a new Comments node if there was none.
19*4947cdc7SCole Faust	// This makes possible to add new comments using Comments() method.
20*4947cdc7SCole Faust	AllocComments()
21*4947cdc7SCole Faust}
22*4947cdc7SCole Faust
23*4947cdc7SCole Faust// A Comment represents a single # comment.
24*4947cdc7SCole Fausttype Comment struct {
25*4947cdc7SCole Faust	Start Position
26*4947cdc7SCole Faust	Text  string // without trailing newline
27*4947cdc7SCole Faust}
28*4947cdc7SCole Faust
29*4947cdc7SCole Faust// Comments collects the comments associated with an expression.
30*4947cdc7SCole Fausttype Comments struct {
31*4947cdc7SCole Faust	Before []Comment // whole-line comments before this expression
32*4947cdc7SCole Faust	Suffix []Comment // end-of-line comments after this expression (up to 1)
33*4947cdc7SCole Faust
34*4947cdc7SCole Faust	// For top-level expressions only, After lists whole-line
35*4947cdc7SCole Faust	// comments following the expression.
36*4947cdc7SCole Faust	After []Comment
37*4947cdc7SCole Faust}
38*4947cdc7SCole Faust
39*4947cdc7SCole Faust// A commentsRef is a possibly-nil reference to a set of comments.
40*4947cdc7SCole Faust// A commentsRef is embedded in each type of syntax node,
41*4947cdc7SCole Faust// and provides its Comments and AllocComments methods.
42*4947cdc7SCole Fausttype commentsRef struct{ ref *Comments }
43*4947cdc7SCole Faust
44*4947cdc7SCole Faust// Comments returns the comments associated with a syntax node,
45*4947cdc7SCole Faust// or nil if AllocComments has not yet been called.
46*4947cdc7SCole Faustfunc (cr commentsRef) Comments() *Comments { return cr.ref }
47*4947cdc7SCole Faust
48*4947cdc7SCole Faust// AllocComments enables comments to be associated with a syntax node.
49*4947cdc7SCole Faustfunc (cr *commentsRef) AllocComments() {
50*4947cdc7SCole Faust	if cr.ref == nil {
51*4947cdc7SCole Faust		cr.ref = new(Comments)
52*4947cdc7SCole Faust	}
53*4947cdc7SCole Faust}
54*4947cdc7SCole Faust
55*4947cdc7SCole Faust// Start returns the start position of the expression.
56*4947cdc7SCole Faustfunc Start(n Node) Position {
57*4947cdc7SCole Faust	start, _ := n.Span()
58*4947cdc7SCole Faust	return start
59*4947cdc7SCole Faust}
60*4947cdc7SCole Faust
61*4947cdc7SCole Faust// End returns the end position of the expression.
62*4947cdc7SCole Faustfunc End(n Node) Position {
63*4947cdc7SCole Faust	_, end := n.Span()
64*4947cdc7SCole Faust	return end
65*4947cdc7SCole Faust}
66*4947cdc7SCole Faust
67*4947cdc7SCole Faust// A File represents a Starlark file.
68*4947cdc7SCole Fausttype File struct {
69*4947cdc7SCole Faust	commentsRef
70*4947cdc7SCole Faust	Path  string
71*4947cdc7SCole Faust	Stmts []Stmt
72*4947cdc7SCole Faust
73*4947cdc7SCole Faust	Module interface{} // a *resolve.Module, set by resolver
74*4947cdc7SCole Faust}
75*4947cdc7SCole Faust
76*4947cdc7SCole Faustfunc (x *File) Span() (start, end Position) {
77*4947cdc7SCole Faust	if len(x.Stmts) == 0 {
78*4947cdc7SCole Faust		return
79*4947cdc7SCole Faust	}
80*4947cdc7SCole Faust	start, _ = x.Stmts[0].Span()
81*4947cdc7SCole Faust	_, end = x.Stmts[len(x.Stmts)-1].Span()
82*4947cdc7SCole Faust	return start, end
83*4947cdc7SCole Faust}
84*4947cdc7SCole Faust
85*4947cdc7SCole Faust// A Stmt is a Starlark statement.
86*4947cdc7SCole Fausttype Stmt interface {
87*4947cdc7SCole Faust	Node
88*4947cdc7SCole Faust	stmt()
89*4947cdc7SCole Faust}
90*4947cdc7SCole Faust
91*4947cdc7SCole Faustfunc (*AssignStmt) stmt() {}
92*4947cdc7SCole Faustfunc (*BranchStmt) stmt() {}
93*4947cdc7SCole Faustfunc (*DefStmt) stmt()    {}
94*4947cdc7SCole Faustfunc (*ExprStmt) stmt()   {}
95*4947cdc7SCole Faustfunc (*ForStmt) stmt()    {}
96*4947cdc7SCole Faustfunc (*WhileStmt) stmt()  {}
97*4947cdc7SCole Faustfunc (*IfStmt) stmt()     {}
98*4947cdc7SCole Faustfunc (*LoadStmt) stmt()   {}
99*4947cdc7SCole Faustfunc (*ReturnStmt) stmt() {}
100*4947cdc7SCole Faust
101*4947cdc7SCole Faust// An AssignStmt represents an assignment:
102*4947cdc7SCole Faust//	x = 0
103*4947cdc7SCole Faust//	x, y = y, x
104*4947cdc7SCole Faust// 	x += 1
105*4947cdc7SCole Fausttype AssignStmt struct {
106*4947cdc7SCole Faust	commentsRef
107*4947cdc7SCole Faust	OpPos Position
108*4947cdc7SCole Faust	Op    Token // = EQ | {PLUS,MINUS,STAR,PERCENT}_EQ
109*4947cdc7SCole Faust	LHS   Expr
110*4947cdc7SCole Faust	RHS   Expr
111*4947cdc7SCole Faust}
112*4947cdc7SCole Faust
113*4947cdc7SCole Faustfunc (x *AssignStmt) Span() (start, end Position) {
114*4947cdc7SCole Faust	start, _ = x.LHS.Span()
115*4947cdc7SCole Faust	_, end = x.RHS.Span()
116*4947cdc7SCole Faust	return
117*4947cdc7SCole Faust}
118*4947cdc7SCole Faust
119*4947cdc7SCole Faust// A DefStmt represents a function definition.
120*4947cdc7SCole Fausttype DefStmt struct {
121*4947cdc7SCole Faust	commentsRef
122*4947cdc7SCole Faust	Def    Position
123*4947cdc7SCole Faust	Name   *Ident
124*4947cdc7SCole Faust	Params []Expr // param = ident | ident=expr | * | *ident | **ident
125*4947cdc7SCole Faust	Body   []Stmt
126*4947cdc7SCole Faust
127*4947cdc7SCole Faust	Function interface{} // a *resolve.Function, set by resolver
128*4947cdc7SCole Faust}
129*4947cdc7SCole Faust
130*4947cdc7SCole Faustfunc (x *DefStmt) Span() (start, end Position) {
131*4947cdc7SCole Faust	_, end = x.Body[len(x.Body)-1].Span()
132*4947cdc7SCole Faust	return x.Def, end
133*4947cdc7SCole Faust}
134*4947cdc7SCole Faust
135*4947cdc7SCole Faust// An ExprStmt is an expression evaluated for side effects.
136*4947cdc7SCole Fausttype ExprStmt struct {
137*4947cdc7SCole Faust	commentsRef
138*4947cdc7SCole Faust	X Expr
139*4947cdc7SCole Faust}
140*4947cdc7SCole Faust
141*4947cdc7SCole Faustfunc (x *ExprStmt) Span() (start, end Position) {
142*4947cdc7SCole Faust	return x.X.Span()
143*4947cdc7SCole Faust}
144*4947cdc7SCole Faust
145*4947cdc7SCole Faust// An IfStmt is a conditional: If Cond: True; else: False.
146*4947cdc7SCole Faust// 'elseif' is desugared into a chain of IfStmts.
147*4947cdc7SCole Fausttype IfStmt struct {
148*4947cdc7SCole Faust	commentsRef
149*4947cdc7SCole Faust	If      Position // IF or ELIF
150*4947cdc7SCole Faust	Cond    Expr
151*4947cdc7SCole Faust	True    []Stmt
152*4947cdc7SCole Faust	ElsePos Position // ELSE or ELIF
153*4947cdc7SCole Faust	False   []Stmt   // optional
154*4947cdc7SCole Faust}
155*4947cdc7SCole Faust
156*4947cdc7SCole Faustfunc (x *IfStmt) Span() (start, end Position) {
157*4947cdc7SCole Faust	body := x.False
158*4947cdc7SCole Faust	if body == nil {
159*4947cdc7SCole Faust		body = x.True
160*4947cdc7SCole Faust	}
161*4947cdc7SCole Faust	_, end = body[len(body)-1].Span()
162*4947cdc7SCole Faust	return x.If, end
163*4947cdc7SCole Faust}
164*4947cdc7SCole Faust
165*4947cdc7SCole Faust// A LoadStmt loads another module and binds names from it:
166*4947cdc7SCole Faust// load(Module, "x", y="foo").
167*4947cdc7SCole Faust//
168*4947cdc7SCole Faust// The AST is slightly unfaithful to the concrete syntax here because
169*4947cdc7SCole Faust// Starlark's load statement, so that it can be implemented in Python,
170*4947cdc7SCole Faust// binds some names (like y above) with an identifier and some (like x)
171*4947cdc7SCole Faust// without.  For consistency we create fake identifiers for all the
172*4947cdc7SCole Faust// strings.
173*4947cdc7SCole Fausttype LoadStmt struct {
174*4947cdc7SCole Faust	commentsRef
175*4947cdc7SCole Faust	Load   Position
176*4947cdc7SCole Faust	Module *Literal // a string
177*4947cdc7SCole Faust	From   []*Ident // name defined in loading module
178*4947cdc7SCole Faust	To     []*Ident // name in loaded module
179*4947cdc7SCole Faust	Rparen Position
180*4947cdc7SCole Faust}
181*4947cdc7SCole Faust
182*4947cdc7SCole Faustfunc (x *LoadStmt) Span() (start, end Position) {
183*4947cdc7SCole Faust	return x.Load, x.Rparen
184*4947cdc7SCole Faust}
185*4947cdc7SCole Faust
186*4947cdc7SCole Faust// ModuleName returns the name of the module loaded by this statement.
187*4947cdc7SCole Faustfunc (x *LoadStmt) ModuleName() string { return x.Module.Value.(string) }
188*4947cdc7SCole Faust
189*4947cdc7SCole Faust// A BranchStmt changes the flow of control: break, continue, pass.
190*4947cdc7SCole Fausttype BranchStmt struct {
191*4947cdc7SCole Faust	commentsRef
192*4947cdc7SCole Faust	Token    Token // = BREAK | CONTINUE | PASS
193*4947cdc7SCole Faust	TokenPos Position
194*4947cdc7SCole Faust}
195*4947cdc7SCole Faust
196*4947cdc7SCole Faustfunc (x *BranchStmt) Span() (start, end Position) {
197*4947cdc7SCole Faust	return x.TokenPos, x.TokenPos.add(x.Token.String())
198*4947cdc7SCole Faust}
199*4947cdc7SCole Faust
200*4947cdc7SCole Faust// A ReturnStmt returns from a function.
201*4947cdc7SCole Fausttype ReturnStmt struct {
202*4947cdc7SCole Faust	commentsRef
203*4947cdc7SCole Faust	Return Position
204*4947cdc7SCole Faust	Result Expr // may be nil
205*4947cdc7SCole Faust}
206*4947cdc7SCole Faust
207*4947cdc7SCole Faustfunc (x *ReturnStmt) Span() (start, end Position) {
208*4947cdc7SCole Faust	if x.Result == nil {
209*4947cdc7SCole Faust		return x.Return, x.Return.add("return")
210*4947cdc7SCole Faust	}
211*4947cdc7SCole Faust	_, end = x.Result.Span()
212*4947cdc7SCole Faust	return x.Return, end
213*4947cdc7SCole Faust}
214*4947cdc7SCole Faust
215*4947cdc7SCole Faust// An Expr is a Starlark expression.
216*4947cdc7SCole Fausttype Expr interface {
217*4947cdc7SCole Faust	Node
218*4947cdc7SCole Faust	expr()
219*4947cdc7SCole Faust}
220*4947cdc7SCole Faust
221*4947cdc7SCole Faustfunc (*BinaryExpr) expr()    {}
222*4947cdc7SCole Faustfunc (*CallExpr) expr()      {}
223*4947cdc7SCole Faustfunc (*Comprehension) expr() {}
224*4947cdc7SCole Faustfunc (*CondExpr) expr()      {}
225*4947cdc7SCole Faustfunc (*DictEntry) expr()     {}
226*4947cdc7SCole Faustfunc (*DictExpr) expr()      {}
227*4947cdc7SCole Faustfunc (*DotExpr) expr()       {}
228*4947cdc7SCole Faustfunc (*Ident) expr()         {}
229*4947cdc7SCole Faustfunc (*IndexExpr) expr()     {}
230*4947cdc7SCole Faustfunc (*LambdaExpr) expr()    {}
231*4947cdc7SCole Faustfunc (*ListExpr) expr()      {}
232*4947cdc7SCole Faustfunc (*Literal) expr()       {}
233*4947cdc7SCole Faustfunc (*ParenExpr) expr()     {}
234*4947cdc7SCole Faustfunc (*SliceExpr) expr()     {}
235*4947cdc7SCole Faustfunc (*TupleExpr) expr()     {}
236*4947cdc7SCole Faustfunc (*UnaryExpr) expr()     {}
237*4947cdc7SCole Faust
238*4947cdc7SCole Faust// An Ident represents an identifier.
239*4947cdc7SCole Fausttype Ident struct {
240*4947cdc7SCole Faust	commentsRef
241*4947cdc7SCole Faust	NamePos Position
242*4947cdc7SCole Faust	Name    string
243*4947cdc7SCole Faust
244*4947cdc7SCole Faust	Binding interface{} // a *resolver.Binding, set by resolver
245*4947cdc7SCole Faust}
246*4947cdc7SCole Faust
247*4947cdc7SCole Faustfunc (x *Ident) Span() (start, end Position) {
248*4947cdc7SCole Faust	return x.NamePos, x.NamePos.add(x.Name)
249*4947cdc7SCole Faust}
250*4947cdc7SCole Faust
251*4947cdc7SCole Faust// A Literal represents a literal string or number.
252*4947cdc7SCole Fausttype Literal struct {
253*4947cdc7SCole Faust	commentsRef
254*4947cdc7SCole Faust	Token    Token // = STRING | BYTES | INT | FLOAT
255*4947cdc7SCole Faust	TokenPos Position
256*4947cdc7SCole Faust	Raw      string      // uninterpreted text
257*4947cdc7SCole Faust	Value    interface{} // = string | int64 | *big.Int | float64
258*4947cdc7SCole Faust}
259*4947cdc7SCole Faust
260*4947cdc7SCole Faustfunc (x *Literal) Span() (start, end Position) {
261*4947cdc7SCole Faust	return x.TokenPos, x.TokenPos.add(x.Raw)
262*4947cdc7SCole Faust}
263*4947cdc7SCole Faust
264*4947cdc7SCole Faust// A ParenExpr represents a parenthesized expression: (X).
265*4947cdc7SCole Fausttype ParenExpr struct {
266*4947cdc7SCole Faust	commentsRef
267*4947cdc7SCole Faust	Lparen Position
268*4947cdc7SCole Faust	X      Expr
269*4947cdc7SCole Faust	Rparen Position
270*4947cdc7SCole Faust}
271*4947cdc7SCole Faust
272*4947cdc7SCole Faustfunc (x *ParenExpr) Span() (start, end Position) {
273*4947cdc7SCole Faust	return x.Lparen, x.Rparen.add(")")
274*4947cdc7SCole Faust}
275*4947cdc7SCole Faust
276*4947cdc7SCole Faust// A CallExpr represents a function call expression: Fn(Args).
277*4947cdc7SCole Fausttype CallExpr struct {
278*4947cdc7SCole Faust	commentsRef
279*4947cdc7SCole Faust	Fn     Expr
280*4947cdc7SCole Faust	Lparen Position
281*4947cdc7SCole Faust	Args   []Expr // arg = expr | ident=expr | *expr | **expr
282*4947cdc7SCole Faust	Rparen Position
283*4947cdc7SCole Faust}
284*4947cdc7SCole Faust
285*4947cdc7SCole Faustfunc (x *CallExpr) Span() (start, end Position) {
286*4947cdc7SCole Faust	start, _ = x.Fn.Span()
287*4947cdc7SCole Faust	return start, x.Rparen.add(")")
288*4947cdc7SCole Faust}
289*4947cdc7SCole Faust
290*4947cdc7SCole Faust// A DotExpr represents a field or method selector: X.Name.
291*4947cdc7SCole Fausttype DotExpr struct {
292*4947cdc7SCole Faust	commentsRef
293*4947cdc7SCole Faust	X       Expr
294*4947cdc7SCole Faust	Dot     Position
295*4947cdc7SCole Faust	NamePos Position
296*4947cdc7SCole Faust	Name    *Ident
297*4947cdc7SCole Faust}
298*4947cdc7SCole Faust
299*4947cdc7SCole Faustfunc (x *DotExpr) Span() (start, end Position) {
300*4947cdc7SCole Faust	start, _ = x.X.Span()
301*4947cdc7SCole Faust	_, end = x.Name.Span()
302*4947cdc7SCole Faust	return
303*4947cdc7SCole Faust}
304*4947cdc7SCole Faust
305*4947cdc7SCole Faust// A Comprehension represents a list or dict comprehension:
306*4947cdc7SCole Faust// [Body for ... if ...] or {Body for ... if ...}
307*4947cdc7SCole Fausttype Comprehension struct {
308*4947cdc7SCole Faust	commentsRef
309*4947cdc7SCole Faust	Curly   bool // {x:y for ...} or {x for ...}, not [x for ...]
310*4947cdc7SCole Faust	Lbrack  Position
311*4947cdc7SCole Faust	Body    Expr
312*4947cdc7SCole Faust	Clauses []Node // = *ForClause | *IfClause
313*4947cdc7SCole Faust	Rbrack  Position
314*4947cdc7SCole Faust}
315*4947cdc7SCole Faust
316*4947cdc7SCole Faustfunc (x *Comprehension) Span() (start, end Position) {
317*4947cdc7SCole Faust	return x.Lbrack, x.Rbrack.add("]")
318*4947cdc7SCole Faust}
319*4947cdc7SCole Faust
320*4947cdc7SCole Faust// A ForStmt represents a loop: for Vars in X: Body.
321*4947cdc7SCole Fausttype ForStmt struct {
322*4947cdc7SCole Faust	commentsRef
323*4947cdc7SCole Faust	For  Position
324*4947cdc7SCole Faust	Vars Expr // name, or tuple of names
325*4947cdc7SCole Faust	X    Expr
326*4947cdc7SCole Faust	Body []Stmt
327*4947cdc7SCole Faust}
328*4947cdc7SCole Faust
329*4947cdc7SCole Faustfunc (x *ForStmt) Span() (start, end Position) {
330*4947cdc7SCole Faust	_, end = x.Body[len(x.Body)-1].Span()
331*4947cdc7SCole Faust	return x.For, end
332*4947cdc7SCole Faust}
333*4947cdc7SCole Faust
334*4947cdc7SCole Faust// A WhileStmt represents a while loop: while X: Body.
335*4947cdc7SCole Fausttype WhileStmt struct {
336*4947cdc7SCole Faust	commentsRef
337*4947cdc7SCole Faust	While Position
338*4947cdc7SCole Faust	Cond  Expr
339*4947cdc7SCole Faust	Body  []Stmt
340*4947cdc7SCole Faust}
341*4947cdc7SCole Faust
342*4947cdc7SCole Faustfunc (x *WhileStmt) Span() (start, end Position) {
343*4947cdc7SCole Faust	_, end = x.Body[len(x.Body)-1].Span()
344*4947cdc7SCole Faust	return x.While, end
345*4947cdc7SCole Faust}
346*4947cdc7SCole Faust
347*4947cdc7SCole Faust// A ForClause represents a for clause in a list comprehension: for Vars in X.
348*4947cdc7SCole Fausttype ForClause struct {
349*4947cdc7SCole Faust	commentsRef
350*4947cdc7SCole Faust	For  Position
351*4947cdc7SCole Faust	Vars Expr // name, or tuple of names
352*4947cdc7SCole Faust	In   Position
353*4947cdc7SCole Faust	X    Expr
354*4947cdc7SCole Faust}
355*4947cdc7SCole Faust
356*4947cdc7SCole Faustfunc (x *ForClause) Span() (start, end Position) {
357*4947cdc7SCole Faust	_, end = x.X.Span()
358*4947cdc7SCole Faust	return x.For, end
359*4947cdc7SCole Faust}
360*4947cdc7SCole Faust
361*4947cdc7SCole Faust// An IfClause represents an if clause in a list comprehension: if Cond.
362*4947cdc7SCole Fausttype IfClause struct {
363*4947cdc7SCole Faust	commentsRef
364*4947cdc7SCole Faust	If   Position
365*4947cdc7SCole Faust	Cond Expr
366*4947cdc7SCole Faust}
367*4947cdc7SCole Faust
368*4947cdc7SCole Faustfunc (x *IfClause) Span() (start, end Position) {
369*4947cdc7SCole Faust	_, end = x.Cond.Span()
370*4947cdc7SCole Faust	return x.If, end
371*4947cdc7SCole Faust}
372*4947cdc7SCole Faust
373*4947cdc7SCole Faust// A DictExpr represents a dictionary literal: { List }.
374*4947cdc7SCole Fausttype DictExpr struct {
375*4947cdc7SCole Faust	commentsRef
376*4947cdc7SCole Faust	Lbrace Position
377*4947cdc7SCole Faust	List   []Expr // all *DictEntrys
378*4947cdc7SCole Faust	Rbrace Position
379*4947cdc7SCole Faust}
380*4947cdc7SCole Faust
381*4947cdc7SCole Faustfunc (x *DictExpr) Span() (start, end Position) {
382*4947cdc7SCole Faust	return x.Lbrace, x.Rbrace.add("}")
383*4947cdc7SCole Faust}
384*4947cdc7SCole Faust
385*4947cdc7SCole Faust// A DictEntry represents a dictionary entry: Key: Value.
386*4947cdc7SCole Faust// Used only within a DictExpr.
387*4947cdc7SCole Fausttype DictEntry struct {
388*4947cdc7SCole Faust	commentsRef
389*4947cdc7SCole Faust	Key   Expr
390*4947cdc7SCole Faust	Colon Position
391*4947cdc7SCole Faust	Value Expr
392*4947cdc7SCole Faust}
393*4947cdc7SCole Faust
394*4947cdc7SCole Faustfunc (x *DictEntry) Span() (start, end Position) {
395*4947cdc7SCole Faust	start, _ = x.Key.Span()
396*4947cdc7SCole Faust	_, end = x.Value.Span()
397*4947cdc7SCole Faust	return start, end
398*4947cdc7SCole Faust}
399*4947cdc7SCole Faust
400*4947cdc7SCole Faust// A LambdaExpr represents an inline function abstraction.
401*4947cdc7SCole Faust//
402*4947cdc7SCole Faust// Although they may be added in future, lambda expressions are not
403*4947cdc7SCole Faust// currently part of the Starlark spec, so their use is controlled by the
404*4947cdc7SCole Faust// resolver.AllowLambda flag.
405*4947cdc7SCole Fausttype LambdaExpr struct {
406*4947cdc7SCole Faust	commentsRef
407*4947cdc7SCole Faust	Lambda Position
408*4947cdc7SCole Faust	Params []Expr // param = ident | ident=expr | * | *ident | **ident
409*4947cdc7SCole Faust	Body   Expr
410*4947cdc7SCole Faust
411*4947cdc7SCole Faust	Function interface{} // a *resolve.Function, set by resolver
412*4947cdc7SCole Faust}
413*4947cdc7SCole Faust
414*4947cdc7SCole Faustfunc (x *LambdaExpr) Span() (start, end Position) {
415*4947cdc7SCole Faust	_, end = x.Body.Span()
416*4947cdc7SCole Faust	return x.Lambda, end
417*4947cdc7SCole Faust}
418*4947cdc7SCole Faust
419*4947cdc7SCole Faust// A ListExpr represents a list literal: [ List ].
420*4947cdc7SCole Fausttype ListExpr struct {
421*4947cdc7SCole Faust	commentsRef
422*4947cdc7SCole Faust	Lbrack Position
423*4947cdc7SCole Faust	List   []Expr
424*4947cdc7SCole Faust	Rbrack Position
425*4947cdc7SCole Faust}
426*4947cdc7SCole Faust
427*4947cdc7SCole Faustfunc (x *ListExpr) Span() (start, end Position) {
428*4947cdc7SCole Faust	return x.Lbrack, x.Rbrack.add("]")
429*4947cdc7SCole Faust}
430*4947cdc7SCole Faust
431*4947cdc7SCole Faust// CondExpr represents the conditional: X if COND else ELSE.
432*4947cdc7SCole Fausttype CondExpr struct {
433*4947cdc7SCole Faust	commentsRef
434*4947cdc7SCole Faust	If      Position
435*4947cdc7SCole Faust	Cond    Expr
436*4947cdc7SCole Faust	True    Expr
437*4947cdc7SCole Faust	ElsePos Position
438*4947cdc7SCole Faust	False   Expr
439*4947cdc7SCole Faust}
440*4947cdc7SCole Faust
441*4947cdc7SCole Faustfunc (x *CondExpr) Span() (start, end Position) {
442*4947cdc7SCole Faust	start, _ = x.True.Span()
443*4947cdc7SCole Faust	_, end = x.False.Span()
444*4947cdc7SCole Faust	return start, end
445*4947cdc7SCole Faust}
446*4947cdc7SCole Faust
447*4947cdc7SCole Faust// A TupleExpr represents a tuple literal: (List).
448*4947cdc7SCole Fausttype TupleExpr struct {
449*4947cdc7SCole Faust	commentsRef
450*4947cdc7SCole Faust	Lparen Position // optional (e.g. in x, y = 0, 1), but required if List is empty
451*4947cdc7SCole Faust	List   []Expr
452*4947cdc7SCole Faust	Rparen Position
453*4947cdc7SCole Faust}
454*4947cdc7SCole Faust
455*4947cdc7SCole Faustfunc (x *TupleExpr) Span() (start, end Position) {
456*4947cdc7SCole Faust	if x.Lparen.IsValid() {
457*4947cdc7SCole Faust		return x.Lparen, x.Rparen
458*4947cdc7SCole Faust	} else {
459*4947cdc7SCole Faust		return Start(x.List[0]), End(x.List[len(x.List)-1])
460*4947cdc7SCole Faust	}
461*4947cdc7SCole Faust}
462*4947cdc7SCole Faust
463*4947cdc7SCole Faust// A UnaryExpr represents a unary expression: Op X.
464*4947cdc7SCole Faust//
465*4947cdc7SCole Faust// As a special case, UnaryOp{Op:Star} may also represent
466*4947cdc7SCole Faust// the star parameter in def f(*args) or def f(*, x).
467*4947cdc7SCole Fausttype UnaryExpr struct {
468*4947cdc7SCole Faust	commentsRef
469*4947cdc7SCole Faust	OpPos Position
470*4947cdc7SCole Faust	Op    Token
471*4947cdc7SCole Faust	X     Expr // may be nil if Op==STAR
472*4947cdc7SCole Faust}
473*4947cdc7SCole Faust
474*4947cdc7SCole Faustfunc (x *UnaryExpr) Span() (start, end Position) {
475*4947cdc7SCole Faust	if x.X != nil {
476*4947cdc7SCole Faust		_, end = x.X.Span()
477*4947cdc7SCole Faust	} else {
478*4947cdc7SCole Faust		end = x.OpPos.add("*")
479*4947cdc7SCole Faust	}
480*4947cdc7SCole Faust	return x.OpPos, end
481*4947cdc7SCole Faust}
482*4947cdc7SCole Faust
483*4947cdc7SCole Faust// A BinaryExpr represents a binary expression: X Op Y.
484*4947cdc7SCole Faust//
485*4947cdc7SCole Faust// As a special case, BinaryExpr{Op:EQ} may also
486*4947cdc7SCole Faust// represent a named argument in a call f(k=v)
487*4947cdc7SCole Faust// or a named parameter in a function declaration
488*4947cdc7SCole Faust// def f(param=default).
489*4947cdc7SCole Fausttype BinaryExpr struct {
490*4947cdc7SCole Faust	commentsRef
491*4947cdc7SCole Faust	X     Expr
492*4947cdc7SCole Faust	OpPos Position
493*4947cdc7SCole Faust	Op    Token
494*4947cdc7SCole Faust	Y     Expr
495*4947cdc7SCole Faust}
496*4947cdc7SCole Faust
497*4947cdc7SCole Faustfunc (x *BinaryExpr) Span() (start, end Position) {
498*4947cdc7SCole Faust	start, _ = x.X.Span()
499*4947cdc7SCole Faust	_, end = x.Y.Span()
500*4947cdc7SCole Faust	return start, end
501*4947cdc7SCole Faust}
502*4947cdc7SCole Faust
503*4947cdc7SCole Faust// A SliceExpr represents a slice or substring expression: X[Lo:Hi:Step].
504*4947cdc7SCole Fausttype SliceExpr struct {
505*4947cdc7SCole Faust	commentsRef
506*4947cdc7SCole Faust	X            Expr
507*4947cdc7SCole Faust	Lbrack       Position
508*4947cdc7SCole Faust	Lo, Hi, Step Expr // all optional
509*4947cdc7SCole Faust	Rbrack       Position
510*4947cdc7SCole Faust}
511*4947cdc7SCole Faust
512*4947cdc7SCole Faustfunc (x *SliceExpr) Span() (start, end Position) {
513*4947cdc7SCole Faust	start, _ = x.X.Span()
514*4947cdc7SCole Faust	return start, x.Rbrack
515*4947cdc7SCole Faust}
516*4947cdc7SCole Faust
517*4947cdc7SCole Faust// An IndexExpr represents an index expression: X[Y].
518*4947cdc7SCole Fausttype IndexExpr struct {
519*4947cdc7SCole Faust	commentsRef
520*4947cdc7SCole Faust	X      Expr
521*4947cdc7SCole Faust	Lbrack Position
522*4947cdc7SCole Faust	Y      Expr
523*4947cdc7SCole Faust	Rbrack Position
524*4947cdc7SCole Faust}
525*4947cdc7SCole Faust
526*4947cdc7SCole Faustfunc (x *IndexExpr) Span() (start, end Position) {
527*4947cdc7SCole Faust	start, _ = x.X.Span()
528*4947cdc7SCole Faust	return start, x.Rbrack
529*4947cdc7SCole Faust}
530