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