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