129
vendor/go.starlark.net/syntax/grammar.txt
generated
vendored
Normal file
129
vendor/go.starlark.net/syntax/grammar.txt
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
|
||||
Grammar of Starlark
|
||||
==================
|
||||
|
||||
File = {Statement | newline} eof .
|
||||
|
||||
Statement = DefStmt | IfStmt | ForStmt | WhileStmt | SimpleStmt .
|
||||
|
||||
DefStmt = 'def' identifier '(' [Parameters [',']] ')' ':' Suite .
|
||||
|
||||
Parameters = Parameter {',' Parameter}.
|
||||
|
||||
Parameter = identifier | identifier '=' Test | '*' | '*' identifier | '**' identifier .
|
||||
|
||||
IfStmt = 'if' Test ':' Suite {'elif' Test ':' Suite} ['else' ':' Suite] .
|
||||
|
||||
ForStmt = 'for' LoopVariables 'in' Expression ':' Suite .
|
||||
|
||||
WhileStmt = 'while' Test ':' Suite .
|
||||
|
||||
Suite = [newline indent {Statement} outdent] | SimpleStmt .
|
||||
|
||||
SimpleStmt = SmallStmt {';' SmallStmt} [';'] '\n' .
|
||||
# NOTE: '\n' optional at EOF
|
||||
|
||||
SmallStmt = ReturnStmt
|
||||
| BreakStmt | ContinueStmt | PassStmt
|
||||
| AssignStmt
|
||||
| ExprStmt
|
||||
| LoadStmt
|
||||
.
|
||||
|
||||
ReturnStmt = 'return' [Expression] .
|
||||
BreakStmt = 'break' .
|
||||
ContinueStmt = 'continue' .
|
||||
PassStmt = 'pass' .
|
||||
AssignStmt = Expression ('=' | '+=' | '-=' | '*=' | '/=' | '//=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=') Expression .
|
||||
ExprStmt = Expression .
|
||||
|
||||
LoadStmt = 'load' '(' string {',' [identifier '='] string} [','] ')' .
|
||||
|
||||
Test = LambdaExpr
|
||||
| IfExpr
|
||||
| PrimaryExpr
|
||||
| UnaryExpr
|
||||
| BinaryExpr
|
||||
.
|
||||
|
||||
LambdaExpr = 'lambda' [Parameters] ':' Test .
|
||||
|
||||
IfExpr = Test 'if' Test 'else' Test .
|
||||
|
||||
PrimaryExpr = Operand
|
||||
| PrimaryExpr DotSuffix
|
||||
| PrimaryExpr CallSuffix
|
||||
| PrimaryExpr SliceSuffix
|
||||
.
|
||||
|
||||
Operand = identifier
|
||||
| int | float | string
|
||||
| ListExpr | ListComp
|
||||
| DictExpr | DictComp
|
||||
| '(' [Expression [',']] ')'
|
||||
| ('-' | '+') PrimaryExpr
|
||||
.
|
||||
|
||||
DotSuffix = '.' identifier .
|
||||
CallSuffix = '(' [Arguments [',']] ')' .
|
||||
SliceSuffix = '[' [Expression] [':' Test [':' Test]] ']' .
|
||||
|
||||
Arguments = Argument {',' Argument} .
|
||||
Argument = Test | identifier '=' Test | '*' Test | '**' Test .
|
||||
|
||||
ListExpr = '[' [Expression [',']] ']' .
|
||||
ListComp = '[' Test {CompClause} ']'.
|
||||
|
||||
DictExpr = '{' [Entries [',']] '}' .
|
||||
DictComp = '{' Entry {CompClause} '}' .
|
||||
Entries = Entry {',' Entry} .
|
||||
Entry = Test ':' Test .
|
||||
|
||||
CompClause = 'for' LoopVariables 'in' Test | 'if' Test .
|
||||
|
||||
UnaryExpr = 'not' Test .
|
||||
|
||||
BinaryExpr = Test {Binop Test} .
|
||||
|
||||
Binop = 'or'
|
||||
| 'and'
|
||||
| '==' | '!=' | '<' | '>' | '<=' | '>=' | 'in' | 'not' 'in'
|
||||
| '|'
|
||||
| '^'
|
||||
| '&'
|
||||
| '-' | '+'
|
||||
| '*' | '%' | '/' | '//'
|
||||
.
|
||||
|
||||
Expression = Test {',' Test} .
|
||||
# NOTE: trailing comma permitted only when within [...] or (...).
|
||||
|
||||
LoopVariables = PrimaryExpr {',' PrimaryExpr} .
|
||||
|
||||
|
||||
# Notation (similar to Go spec):
|
||||
- lowercase and 'quoted' items are lexical tokens.
|
||||
- Capitalized names denote grammar productions.
|
||||
- (...) implies grouping
|
||||
- x | y means either x or y.
|
||||
- [x] means x is optional
|
||||
- {x} means x is repeated zero or more times
|
||||
- The end of each declaration is marked with a period.
|
||||
|
||||
# Tokens
|
||||
- spaces: newline, eof, indent, outdent.
|
||||
- identifier.
|
||||
- literals: string, int, float.
|
||||
- plus all quoted tokens such as '+=', 'return'.
|
||||
|
||||
# Notes:
|
||||
- Ambiguity is resolved using operator precedence.
|
||||
- The grammar does not enforce the legal order of params and args,
|
||||
nor that the first compclause must be a 'for'.
|
||||
|
||||
TODO:
|
||||
- explain how the lexer generates indent, outdent, and newline tokens.
|
||||
- why is unary NOT separated from unary - and +?
|
||||
- the grammar is (mostly) in LL(1) style so, for example,
|
||||
dot expressions are formed suffixes, not complete expressions,
|
||||
which makes the spec harder to read. Reorganize into non-LL(1) form?
|
||||
1029
vendor/go.starlark.net/syntax/parse.go
generated
vendored
Normal file
1029
vendor/go.starlark.net/syntax/parse.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
269
vendor/go.starlark.net/syntax/quote.go
generated
vendored
Normal file
269
vendor/go.starlark.net/syntax/quote.go
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
// Copyright 2017 The Bazel Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package syntax
|
||||
|
||||
// Starlark quoted string utilities.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// unesc maps single-letter chars following \ to their actual values.
|
||||
var unesc = [256]byte{
|
||||
'a': '\a',
|
||||
'b': '\b',
|
||||
'f': '\f',
|
||||
'n': '\n',
|
||||
'r': '\r',
|
||||
't': '\t',
|
||||
'v': '\v',
|
||||
'\\': '\\',
|
||||
'\'': '\'',
|
||||
'"': '"',
|
||||
}
|
||||
|
||||
// esc maps escape-worthy bytes to the char that should follow \.
|
||||
var esc = [256]byte{
|
||||
'\a': 'a',
|
||||
'\b': 'b',
|
||||
'\f': 'f',
|
||||
'\n': 'n',
|
||||
'\r': 'r',
|
||||
'\t': 't',
|
||||
'\v': 'v',
|
||||
'\\': '\\',
|
||||
'\'': '\'',
|
||||
'"': '"',
|
||||
}
|
||||
|
||||
// notEsc is a list of characters that can follow a \ in a string value
|
||||
// without having to escape the \. That is, since ( is in this list, we
|
||||
// quote the Go string "foo\\(bar" as the Python literal "foo\(bar".
|
||||
// This really does happen in BUILD files, especially in strings
|
||||
// being used as shell arguments containing regular expressions.
|
||||
const notEsc = " !#$%&()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~"
|
||||
|
||||
// unquote unquotes the quoted string, returning the actual
|
||||
// string value, whether the original was triple-quoted, and
|
||||
// an error describing invalid input.
|
||||
func unquote(quoted string) (s string, triple bool, err error) {
|
||||
// Check for raw prefix: means don't interpret the inner \.
|
||||
raw := false
|
||||
if strings.HasPrefix(quoted, "r") {
|
||||
raw = true
|
||||
quoted = quoted[1:]
|
||||
}
|
||||
|
||||
if len(quoted) < 2 {
|
||||
err = fmt.Errorf("string literal too short")
|
||||
return
|
||||
}
|
||||
|
||||
if quoted[0] != '"' && quoted[0] != '\'' || quoted[0] != quoted[len(quoted)-1] {
|
||||
err = fmt.Errorf("string literal has invalid quotes")
|
||||
return
|
||||
}
|
||||
|
||||
// Check for triple quoted string.
|
||||
quote := quoted[0]
|
||||
if len(quoted) >= 6 && quoted[1] == quote && quoted[2] == quote && quoted[:3] == quoted[len(quoted)-3:] {
|
||||
triple = true
|
||||
quoted = quoted[3 : len(quoted)-3]
|
||||
} else {
|
||||
quoted = quoted[1 : len(quoted)-1]
|
||||
}
|
||||
|
||||
// Now quoted is the quoted data, but no quotes.
|
||||
// If we're in raw mode or there are no escapes or
|
||||
// carriage returns, we're done.
|
||||
var unquoteChars string
|
||||
if raw {
|
||||
unquoteChars = "\r"
|
||||
} else {
|
||||
unquoteChars = "\\\r"
|
||||
}
|
||||
if !strings.ContainsAny(quoted, unquoteChars) {
|
||||
s = quoted
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise process quoted string.
|
||||
// Each iteration processes one escape sequence along with the
|
||||
// plain text leading up to it.
|
||||
buf := new(strings.Builder)
|
||||
for {
|
||||
// Remove prefix before escape sequence.
|
||||
i := strings.IndexAny(quoted, unquoteChars)
|
||||
if i < 0 {
|
||||
i = len(quoted)
|
||||
}
|
||||
buf.WriteString(quoted[:i])
|
||||
quoted = quoted[i:]
|
||||
|
||||
if len(quoted) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// Process carriage return.
|
||||
if quoted[0] == '\r' {
|
||||
buf.WriteByte('\n')
|
||||
if len(quoted) > 1 && quoted[1] == '\n' {
|
||||
quoted = quoted[2:]
|
||||
} else {
|
||||
quoted = quoted[1:]
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Process escape sequence.
|
||||
if len(quoted) == 1 {
|
||||
err = fmt.Errorf(`truncated escape sequence \`)
|
||||
return
|
||||
}
|
||||
|
||||
switch quoted[1] {
|
||||
default:
|
||||
// In Python, if \z (for some byte z) is not a known escape sequence
|
||||
// then it appears as literal text in the string.
|
||||
buf.WriteString(quoted[:2])
|
||||
quoted = quoted[2:]
|
||||
|
||||
case '\n':
|
||||
// Ignore the escape and the line break.
|
||||
quoted = quoted[2:]
|
||||
|
||||
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '\'', '"':
|
||||
// One-char escape
|
||||
buf.WriteByte(unesc[quoted[1]])
|
||||
quoted = quoted[2:]
|
||||
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||
// Octal escape, up to 3 digits.
|
||||
n := int(quoted[1] - '0')
|
||||
quoted = quoted[2:]
|
||||
for i := 1; i < 3; i++ {
|
||||
if len(quoted) == 0 || quoted[0] < '0' || '7' < quoted[0] {
|
||||
break
|
||||
}
|
||||
n = n*8 + int(quoted[0]-'0')
|
||||
quoted = quoted[1:]
|
||||
}
|
||||
if n >= 256 {
|
||||
// NOTE: Python silently discards the high bit,
|
||||
// so that '\541' == '\141' == 'a'.
|
||||
// Let's see if we can avoid doing that in BUILD files.
|
||||
err = fmt.Errorf(`invalid escape sequence \%03o`, n)
|
||||
return
|
||||
}
|
||||
buf.WriteByte(byte(n))
|
||||
|
||||
case 'x':
|
||||
// Hexadecimal escape, exactly 2 digits.
|
||||
if len(quoted) < 4 {
|
||||
err = fmt.Errorf(`truncated escape sequence %s`, quoted)
|
||||
return
|
||||
}
|
||||
n, err1 := strconv.ParseUint(quoted[2:4], 16, 0)
|
||||
if err1 != nil {
|
||||
err = fmt.Errorf(`invalid escape sequence %s`, quoted[:4])
|
||||
return
|
||||
}
|
||||
buf.WriteByte(byte(n))
|
||||
quoted = quoted[4:]
|
||||
}
|
||||
}
|
||||
|
||||
s = buf.String()
|
||||
return
|
||||
}
|
||||
|
||||
// indexByte returns the index of the first instance of b in s, or else -1.
|
||||
func indexByte(s string, b byte) int {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == b {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// hex is a list of the hexadecimal digits, for use in quoting.
|
||||
// We always print lower-case hexadecimal.
|
||||
const hex = "0123456789abcdef"
|
||||
|
||||
// quote returns the quoted form of the string value "x".
|
||||
// If triple is true, quote uses the triple-quoted form """x""".
|
||||
func quote(unquoted string, triple bool) string {
|
||||
q := `"`
|
||||
if triple {
|
||||
q = `"""`
|
||||
}
|
||||
|
||||
buf := new(strings.Builder)
|
||||
buf.WriteString(q)
|
||||
|
||||
for i := 0; i < len(unquoted); i++ {
|
||||
c := unquoted[i]
|
||||
if c == '"' && triple && (i+1 < len(unquoted) && unquoted[i+1] != '"' || i+2 < len(unquoted) && unquoted[i+2] != '"') {
|
||||
// Can pass up to two quotes through, because they are followed by a non-quote byte.
|
||||
buf.WriteByte(c)
|
||||
if i+1 < len(unquoted) && unquoted[i+1] == '"' {
|
||||
buf.WriteByte(c)
|
||||
i++
|
||||
}
|
||||
continue
|
||||
}
|
||||
if triple && c == '\n' {
|
||||
// Can allow newline in triple-quoted string.
|
||||
buf.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
if c == '\'' {
|
||||
// Can allow ' since we always use ".
|
||||
buf.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
if c == '\\' {
|
||||
if i+1 < len(unquoted) && indexByte(notEsc, unquoted[i+1]) >= 0 {
|
||||
// Can pass \ through when followed by a byte that
|
||||
// known not to be a valid escape sequence and also
|
||||
// that does not trigger an escape sequence of its own.
|
||||
// Use this, because various BUILD files do.
|
||||
buf.WriteByte('\\')
|
||||
buf.WriteByte(unquoted[i+1])
|
||||
i++
|
||||
continue
|
||||
}
|
||||
}
|
||||
if esc[c] != 0 {
|
||||
buf.WriteByte('\\')
|
||||
buf.WriteByte(esc[c])
|
||||
continue
|
||||
}
|
||||
if c < 0x20 || c >= 0x80 {
|
||||
// BUILD files are supposed to be Latin-1, so escape all control and high bytes.
|
||||
// I'd prefer to use \x here, but Blaze does not implement
|
||||
// \x in quoted strings (b/7272572).
|
||||
buf.WriteByte('\\')
|
||||
buf.WriteByte(hex[c>>6]) // actually octal but reusing hex digits 0-7.
|
||||
buf.WriteByte(hex[(c>>3)&7])
|
||||
buf.WriteByte(hex[c&7])
|
||||
/*
|
||||
buf.WriteByte('\\')
|
||||
buf.WriteByte('x')
|
||||
buf.WriteByte(hex[c>>4])
|
||||
buf.WriteByte(hex[c&0xF])
|
||||
*/
|
||||
continue
|
||||
}
|
||||
buf.WriteByte(c)
|
||||
continue
|
||||
}
|
||||
|
||||
buf.WriteString(q)
|
||||
return buf.String()
|
||||
}
|
||||
1089
vendor/go.starlark.net/syntax/scan.go
generated
vendored
Normal file
1089
vendor/go.starlark.net/syntax/scan.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
529
vendor/go.starlark.net/syntax/syntax.go
generated
vendored
Normal file
529
vendor/go.starlark.net/syntax/syntax.go
generated
vendored
Normal file
@@ -0,0 +1,529 @@
|
||||
// Copyright 2017 The Bazel Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package syntax provides a Starlark parser and abstract syntax tree.
|
||||
package syntax // import "go.starlark.net/syntax"
|
||||
|
||||
// A Node is a node in a Starlark syntax tree.
|
||||
type Node interface {
|
||||
// Span returns the start and end position of the expression.
|
||||
Span() (start, end Position)
|
||||
|
||||
// Comments returns the comments associated with this node.
|
||||
// It returns nil if RetainComments was not specified during parsing,
|
||||
// or if AllocComments was not called.
|
||||
Comments() *Comments
|
||||
|
||||
// AllocComments allocates a new Comments node if there was none.
|
||||
// This makes possible to add new comments using Comments() method.
|
||||
AllocComments()
|
||||
}
|
||||
|
||||
// A Comment represents a single # comment.
|
||||
type Comment struct {
|
||||
Start Position
|
||||
Text string // without trailing newline
|
||||
}
|
||||
|
||||
// Comments collects the comments associated with an expression.
|
||||
type Comments struct {
|
||||
Before []Comment // whole-line comments before this expression
|
||||
Suffix []Comment // end-of-line comments after this expression (up to 1)
|
||||
|
||||
// For top-level expressions only, After lists whole-line
|
||||
// comments following the expression.
|
||||
After []Comment
|
||||
}
|
||||
|
||||
// A commentsRef is a possibly-nil reference to a set of comments.
|
||||
// A commentsRef is embedded in each type of syntax node,
|
||||
// and provides its Comments and AllocComments methods.
|
||||
type commentsRef struct{ ref *Comments }
|
||||
|
||||
// Comments returns the comments associated with a syntax node,
|
||||
// or nil if AllocComments has not yet been called.
|
||||
func (cr commentsRef) Comments() *Comments { return cr.ref }
|
||||
|
||||
// AllocComments enables comments to be associated with a syntax node.
|
||||
func (cr *commentsRef) AllocComments() {
|
||||
if cr.ref == nil {
|
||||
cr.ref = new(Comments)
|
||||
}
|
||||
}
|
||||
|
||||
// Start returns the start position of the expression.
|
||||
func Start(n Node) Position {
|
||||
start, _ := n.Span()
|
||||
return start
|
||||
}
|
||||
|
||||
// End returns the end position of the expression.
|
||||
func End(n Node) Position {
|
||||
_, end := n.Span()
|
||||
return end
|
||||
}
|
||||
|
||||
// A File represents a Starlark file.
|
||||
type File struct {
|
||||
commentsRef
|
||||
Path string
|
||||
Stmts []Stmt
|
||||
|
||||
Module interface{} // a *resolve.Module, set by resolver
|
||||
}
|
||||
|
||||
func (x *File) Span() (start, end Position) {
|
||||
if len(x.Stmts) == 0 {
|
||||
return
|
||||
}
|
||||
start, _ = x.Stmts[0].Span()
|
||||
_, end = x.Stmts[len(x.Stmts)-1].Span()
|
||||
return start, end
|
||||
}
|
||||
|
||||
// A Stmt is a Starlark statement.
|
||||
type Stmt interface {
|
||||
Node
|
||||
stmt()
|
||||
}
|
||||
|
||||
func (*AssignStmt) stmt() {}
|
||||
func (*BranchStmt) stmt() {}
|
||||
func (*DefStmt) stmt() {}
|
||||
func (*ExprStmt) stmt() {}
|
||||
func (*ForStmt) stmt() {}
|
||||
func (*WhileStmt) stmt() {}
|
||||
func (*IfStmt) stmt() {}
|
||||
func (*LoadStmt) stmt() {}
|
||||
func (*ReturnStmt) stmt() {}
|
||||
|
||||
// An AssignStmt represents an assignment:
|
||||
// x = 0
|
||||
// x, y = y, x
|
||||
// x += 1
|
||||
type AssignStmt struct {
|
||||
commentsRef
|
||||
OpPos Position
|
||||
Op Token // = EQ | {PLUS,MINUS,STAR,PERCENT}_EQ
|
||||
LHS Expr
|
||||
RHS Expr
|
||||
}
|
||||
|
||||
func (x *AssignStmt) Span() (start, end Position) {
|
||||
start, _ = x.LHS.Span()
|
||||
_, end = x.RHS.Span()
|
||||
return
|
||||
}
|
||||
|
||||
// A DefStmt represents a function definition.
|
||||
type DefStmt struct {
|
||||
commentsRef
|
||||
Def Position
|
||||
Name *Ident
|
||||
Params []Expr // param = ident | ident=expr | * | *ident | **ident
|
||||
Body []Stmt
|
||||
|
||||
Function interface{} // a *resolve.Function, set by resolver
|
||||
}
|
||||
|
||||
func (x *DefStmt) Span() (start, end Position) {
|
||||
_, end = x.Body[len(x.Body)-1].Span()
|
||||
return x.Def, end
|
||||
}
|
||||
|
||||
// An ExprStmt is an expression evaluated for side effects.
|
||||
type ExprStmt struct {
|
||||
commentsRef
|
||||
X Expr
|
||||
}
|
||||
|
||||
func (x *ExprStmt) Span() (start, end Position) {
|
||||
return x.X.Span()
|
||||
}
|
||||
|
||||
// An IfStmt is a conditional: If Cond: True; else: False.
|
||||
// 'elseif' is desugared into a chain of IfStmts.
|
||||
type IfStmt struct {
|
||||
commentsRef
|
||||
If Position // IF or ELIF
|
||||
Cond Expr
|
||||
True []Stmt
|
||||
ElsePos Position // ELSE or ELIF
|
||||
False []Stmt // optional
|
||||
}
|
||||
|
||||
func (x *IfStmt) Span() (start, end Position) {
|
||||
body := x.False
|
||||
if body == nil {
|
||||
body = x.True
|
||||
}
|
||||
_, end = body[len(body)-1].Span()
|
||||
return x.If, end
|
||||
}
|
||||
|
||||
// A LoadStmt loads another module and binds names from it:
|
||||
// load(Module, "x", y="foo").
|
||||
//
|
||||
// The AST is slightly unfaithful to the concrete syntax here because
|
||||
// Starlark's load statement, so that it can be implemented in Python,
|
||||
// binds some names (like y above) with an identifier and some (like x)
|
||||
// without. For consistency we create fake identifiers for all the
|
||||
// strings.
|
||||
type LoadStmt struct {
|
||||
commentsRef
|
||||
Load Position
|
||||
Module *Literal // a string
|
||||
From []*Ident // name defined in loading module
|
||||
To []*Ident // name in loaded module
|
||||
Rparen Position
|
||||
}
|
||||
|
||||
func (x *LoadStmt) Span() (start, end Position) {
|
||||
return x.Load, x.Rparen
|
||||
}
|
||||
|
||||
// ModuleName returns the name of the module loaded by this statement.
|
||||
func (x *LoadStmt) ModuleName() string { return x.Module.Value.(string) }
|
||||
|
||||
// A BranchStmt changes the flow of control: break, continue, pass.
|
||||
type BranchStmt struct {
|
||||
commentsRef
|
||||
Token Token // = BREAK | CONTINUE | PASS
|
||||
TokenPos Position
|
||||
}
|
||||
|
||||
func (x *BranchStmt) Span() (start, end Position) {
|
||||
return x.TokenPos, x.TokenPos.add(x.Token.String())
|
||||
}
|
||||
|
||||
// A ReturnStmt returns from a function.
|
||||
type ReturnStmt struct {
|
||||
commentsRef
|
||||
Return Position
|
||||
Result Expr // may be nil
|
||||
}
|
||||
|
||||
func (x *ReturnStmt) Span() (start, end Position) {
|
||||
if x.Result == nil {
|
||||
return x.Return, x.Return.add("return")
|
||||
}
|
||||
_, end = x.Result.Span()
|
||||
return x.Return, end
|
||||
}
|
||||
|
||||
// An Expr is a Starlark expression.
|
||||
type Expr interface {
|
||||
Node
|
||||
expr()
|
||||
}
|
||||
|
||||
func (*BinaryExpr) expr() {}
|
||||
func (*CallExpr) expr() {}
|
||||
func (*Comprehension) expr() {}
|
||||
func (*CondExpr) expr() {}
|
||||
func (*DictEntry) expr() {}
|
||||
func (*DictExpr) expr() {}
|
||||
func (*DotExpr) expr() {}
|
||||
func (*Ident) expr() {}
|
||||
func (*IndexExpr) expr() {}
|
||||
func (*LambdaExpr) expr() {}
|
||||
func (*ListExpr) expr() {}
|
||||
func (*Literal) expr() {}
|
||||
func (*ParenExpr) expr() {}
|
||||
func (*SliceExpr) expr() {}
|
||||
func (*TupleExpr) expr() {}
|
||||
func (*UnaryExpr) expr() {}
|
||||
|
||||
// An Ident represents an identifier.
|
||||
type Ident struct {
|
||||
commentsRef
|
||||
NamePos Position
|
||||
Name string
|
||||
|
||||
Binding interface{} // a *resolver.Binding, set by resolver
|
||||
}
|
||||
|
||||
func (x *Ident) Span() (start, end Position) {
|
||||
return x.NamePos, x.NamePos.add(x.Name)
|
||||
}
|
||||
|
||||
// A Literal represents a literal string or number.
|
||||
type Literal struct {
|
||||
commentsRef
|
||||
Token Token // = STRING | INT
|
||||
TokenPos Position
|
||||
Raw string // uninterpreted text
|
||||
Value interface{} // = string | int64 | *big.Int
|
||||
}
|
||||
|
||||
func (x *Literal) Span() (start, end Position) {
|
||||
return x.TokenPos, x.TokenPos.add(x.Raw)
|
||||
}
|
||||
|
||||
// A ParenExpr represents a parenthesized expression: (X).
|
||||
type ParenExpr struct {
|
||||
commentsRef
|
||||
Lparen Position
|
||||
X Expr
|
||||
Rparen Position
|
||||
}
|
||||
|
||||
func (x *ParenExpr) Span() (start, end Position) {
|
||||
return x.Lparen, x.Rparen.add(")")
|
||||
}
|
||||
|
||||
// A CallExpr represents a function call expression: Fn(Args).
|
||||
type CallExpr struct {
|
||||
commentsRef
|
||||
Fn Expr
|
||||
Lparen Position
|
||||
Args []Expr // arg = expr | ident=expr | *expr | **expr
|
||||
Rparen Position
|
||||
}
|
||||
|
||||
func (x *CallExpr) Span() (start, end Position) {
|
||||
start, _ = x.Fn.Span()
|
||||
return start, x.Rparen.add(")")
|
||||
}
|
||||
|
||||
// A DotExpr represents a field or method selector: X.Name.
|
||||
type DotExpr struct {
|
||||
commentsRef
|
||||
X Expr
|
||||
Dot Position
|
||||
NamePos Position
|
||||
Name *Ident
|
||||
}
|
||||
|
||||
func (x *DotExpr) Span() (start, end Position) {
|
||||
start, _ = x.X.Span()
|
||||
_, end = x.Name.Span()
|
||||
return
|
||||
}
|
||||
|
||||
// A Comprehension represents a list or dict comprehension:
|
||||
// [Body for ... if ...] or {Body for ... if ...}
|
||||
type Comprehension struct {
|
||||
commentsRef
|
||||
Curly bool // {x:y for ...} or {x for ...}, not [x for ...]
|
||||
Lbrack Position
|
||||
Body Expr
|
||||
Clauses []Node // = *ForClause | *IfClause
|
||||
Rbrack Position
|
||||
}
|
||||
|
||||
func (x *Comprehension) Span() (start, end Position) {
|
||||
return x.Lbrack, x.Rbrack.add("]")
|
||||
}
|
||||
|
||||
// A ForStmt represents a loop: for Vars in X: Body.
|
||||
type ForStmt struct {
|
||||
commentsRef
|
||||
For Position
|
||||
Vars Expr // name, or tuple of names
|
||||
X Expr
|
||||
Body []Stmt
|
||||
}
|
||||
|
||||
func (x *ForStmt) Span() (start, end Position) {
|
||||
_, end = x.Body[len(x.Body)-1].Span()
|
||||
return x.For, end
|
||||
}
|
||||
|
||||
// A WhileStmt represents a while loop: while X: Body.
|
||||
type WhileStmt struct {
|
||||
commentsRef
|
||||
While Position
|
||||
Cond Expr
|
||||
Body []Stmt
|
||||
}
|
||||
|
||||
func (x *WhileStmt) Span() (start, end Position) {
|
||||
_, end = x.Body[len(x.Body)-1].Span()
|
||||
return x.While, end
|
||||
}
|
||||
|
||||
// A ForClause represents a for clause in a list comprehension: for Vars in X.
|
||||
type ForClause struct {
|
||||
commentsRef
|
||||
For Position
|
||||
Vars Expr // name, or tuple of names
|
||||
In Position
|
||||
X Expr
|
||||
}
|
||||
|
||||
func (x *ForClause) Span() (start, end Position) {
|
||||
_, end = x.X.Span()
|
||||
return x.For, end
|
||||
}
|
||||
|
||||
// An IfClause represents an if clause in a list comprehension: if Cond.
|
||||
type IfClause struct {
|
||||
commentsRef
|
||||
If Position
|
||||
Cond Expr
|
||||
}
|
||||
|
||||
func (x *IfClause) Span() (start, end Position) {
|
||||
_, end = x.Cond.Span()
|
||||
return x.If, end
|
||||
}
|
||||
|
||||
// A DictExpr represents a dictionary literal: { List }.
|
||||
type DictExpr struct {
|
||||
commentsRef
|
||||
Lbrace Position
|
||||
List []Expr // all *DictEntrys
|
||||
Rbrace Position
|
||||
}
|
||||
|
||||
func (x *DictExpr) Span() (start, end Position) {
|
||||
return x.Lbrace, x.Rbrace.add("}")
|
||||
}
|
||||
|
||||
// A DictEntry represents a dictionary entry: Key: Value.
|
||||
// Used only within a DictExpr.
|
||||
type DictEntry struct {
|
||||
commentsRef
|
||||
Key Expr
|
||||
Colon Position
|
||||
Value Expr
|
||||
}
|
||||
|
||||
func (x *DictEntry) Span() (start, end Position) {
|
||||
start, _ = x.Key.Span()
|
||||
_, end = x.Value.Span()
|
||||
return start, end
|
||||
}
|
||||
|
||||
// A LambdaExpr represents an inline function abstraction.
|
||||
//
|
||||
// Although they may be added in future, lambda expressions are not
|
||||
// currently part of the Starlark spec, so their use is controlled by the
|
||||
// resolver.AllowLambda flag.
|
||||
type LambdaExpr struct {
|
||||
commentsRef
|
||||
Lambda Position
|
||||
Params []Expr // param = ident | ident=expr | * | *ident | **ident
|
||||
Body Expr
|
||||
|
||||
Function interface{} // a *resolve.Function, set by resolver
|
||||
}
|
||||
|
||||
func (x *LambdaExpr) Span() (start, end Position) {
|
||||
_, end = x.Body.Span()
|
||||
return x.Lambda, end
|
||||
}
|
||||
|
||||
// A ListExpr represents a list literal: [ List ].
|
||||
type ListExpr struct {
|
||||
commentsRef
|
||||
Lbrack Position
|
||||
List []Expr
|
||||
Rbrack Position
|
||||
}
|
||||
|
||||
func (x *ListExpr) Span() (start, end Position) {
|
||||
return x.Lbrack, x.Rbrack.add("]")
|
||||
}
|
||||
|
||||
// CondExpr represents the conditional: X if COND else ELSE.
|
||||
type CondExpr struct {
|
||||
commentsRef
|
||||
If Position
|
||||
Cond Expr
|
||||
True Expr
|
||||
ElsePos Position
|
||||
False Expr
|
||||
}
|
||||
|
||||
func (x *CondExpr) Span() (start, end Position) {
|
||||
start, _ = x.True.Span()
|
||||
_, end = x.False.Span()
|
||||
return start, end
|
||||
}
|
||||
|
||||
// A TupleExpr represents a tuple literal: (List).
|
||||
type TupleExpr struct {
|
||||
commentsRef
|
||||
Lparen Position // optional (e.g. in x, y = 0, 1), but required if List is empty
|
||||
List []Expr
|
||||
Rparen Position
|
||||
}
|
||||
|
||||
func (x *TupleExpr) Span() (start, end Position) {
|
||||
if x.Lparen.IsValid() {
|
||||
return x.Lparen, x.Rparen
|
||||
} else {
|
||||
return Start(x.List[0]), End(x.List[len(x.List)-1])
|
||||
}
|
||||
}
|
||||
|
||||
// A UnaryExpr represents a unary expression: Op X.
|
||||
//
|
||||
// As a special case, UnaryOp{Op:Star} may also represent
|
||||
// the star parameter in def f(*args) or def f(*, x).
|
||||
type UnaryExpr struct {
|
||||
commentsRef
|
||||
OpPos Position
|
||||
Op Token
|
||||
X Expr // may be nil if Op==STAR
|
||||
}
|
||||
|
||||
func (x *UnaryExpr) Span() (start, end Position) {
|
||||
if x.X != nil {
|
||||
_, end = x.X.Span()
|
||||
} else {
|
||||
end = x.OpPos.add("*")
|
||||
}
|
||||
return x.OpPos, end
|
||||
}
|
||||
|
||||
// A BinaryExpr represents a binary expression: X Op Y.
|
||||
//
|
||||
// As a special case, BinaryExpr{Op:EQ} may also
|
||||
// represent a named argument in a call f(k=v)
|
||||
// or a named parameter in a function declaration
|
||||
// def f(param=default).
|
||||
type BinaryExpr struct {
|
||||
commentsRef
|
||||
X Expr
|
||||
OpPos Position
|
||||
Op Token
|
||||
Y Expr
|
||||
}
|
||||
|
||||
func (x *BinaryExpr) Span() (start, end Position) {
|
||||
start, _ = x.X.Span()
|
||||
_, end = x.Y.Span()
|
||||
return start, end
|
||||
}
|
||||
|
||||
// A SliceExpr represents a slice or substring expression: X[Lo:Hi:Step].
|
||||
type SliceExpr struct {
|
||||
commentsRef
|
||||
X Expr
|
||||
Lbrack Position
|
||||
Lo, Hi, Step Expr // all optional
|
||||
Rbrack Position
|
||||
}
|
||||
|
||||
func (x *SliceExpr) Span() (start, end Position) {
|
||||
start, _ = x.X.Span()
|
||||
return start, x.Rbrack
|
||||
}
|
||||
|
||||
// An IndexExpr represents an index expression: X[Y].
|
||||
type IndexExpr struct {
|
||||
commentsRef
|
||||
X Expr
|
||||
Lbrack Position
|
||||
Y Expr
|
||||
Rbrack Position
|
||||
}
|
||||
|
||||
func (x *IndexExpr) Span() (start, end Position) {
|
||||
start, _ = x.X.Span()
|
||||
return start, x.Rbrack
|
||||
}
|
||||
163
vendor/go.starlark.net/syntax/walk.go
generated
vendored
Normal file
163
vendor/go.starlark.net/syntax/walk.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
// Copyright 2017 The Bazel Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package syntax
|
||||
|
||||
// Walk traverses a syntax tree in depth-first order.
|
||||
// It starts by calling f(n); n must not be nil.
|
||||
// If f returns true, Walk calls itself
|
||||
// recursively for each non-nil child of n.
|
||||
// Walk then calls f(nil).
|
||||
func Walk(n Node, f func(Node) bool) {
|
||||
if n == nil {
|
||||
panic("nil")
|
||||
}
|
||||
if !f(n) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(adonovan): opt: order cases using profile data.
|
||||
switch n := n.(type) {
|
||||
case *File:
|
||||
walkStmts(n.Stmts, f)
|
||||
|
||||
case *ExprStmt:
|
||||
Walk(n.X, f)
|
||||
|
||||
case *BranchStmt:
|
||||
// no-op
|
||||
|
||||
case *IfStmt:
|
||||
Walk(n.Cond, f)
|
||||
walkStmts(n.True, f)
|
||||
walkStmts(n.False, f)
|
||||
|
||||
case *AssignStmt:
|
||||
Walk(n.LHS, f)
|
||||
Walk(n.RHS, f)
|
||||
|
||||
case *DefStmt:
|
||||
Walk(n.Name, f)
|
||||
for _, param := range n.Params {
|
||||
Walk(param, f)
|
||||
}
|
||||
walkStmts(n.Body, f)
|
||||
|
||||
case *ForStmt:
|
||||
Walk(n.Vars, f)
|
||||
Walk(n.X, f)
|
||||
walkStmts(n.Body, f)
|
||||
|
||||
case *ReturnStmt:
|
||||
if n.Result != nil {
|
||||
Walk(n.Result, f)
|
||||
}
|
||||
|
||||
case *LoadStmt:
|
||||
Walk(n.Module, f)
|
||||
for _, from := range n.From {
|
||||
Walk(from, f)
|
||||
}
|
||||
for _, to := range n.To {
|
||||
Walk(to, f)
|
||||
}
|
||||
|
||||
case *Ident, *Literal:
|
||||
// no-op
|
||||
|
||||
case *ListExpr:
|
||||
for _, x := range n.List {
|
||||
Walk(x, f)
|
||||
}
|
||||
|
||||
case *ParenExpr:
|
||||
Walk(n.X, f)
|
||||
|
||||
case *CondExpr:
|
||||
Walk(n.Cond, f)
|
||||
Walk(n.True, f)
|
||||
Walk(n.False, f)
|
||||
|
||||
case *IndexExpr:
|
||||
Walk(n.X, f)
|
||||
Walk(n.Y, f)
|
||||
|
||||
case *DictEntry:
|
||||
Walk(n.Key, f)
|
||||
Walk(n.Value, f)
|
||||
|
||||
case *SliceExpr:
|
||||
Walk(n.X, f)
|
||||
if n.Lo != nil {
|
||||
Walk(n.Lo, f)
|
||||
}
|
||||
if n.Hi != nil {
|
||||
Walk(n.Hi, f)
|
||||
}
|
||||
if n.Step != nil {
|
||||
Walk(n.Step, f)
|
||||
}
|
||||
|
||||
case *Comprehension:
|
||||
Walk(n.Body, f)
|
||||
for _, clause := range n.Clauses {
|
||||
Walk(clause, f)
|
||||
}
|
||||
|
||||
case *IfClause:
|
||||
Walk(n.Cond, f)
|
||||
|
||||
case *ForClause:
|
||||
Walk(n.Vars, f)
|
||||
Walk(n.X, f)
|
||||
|
||||
case *TupleExpr:
|
||||
for _, x := range n.List {
|
||||
Walk(x, f)
|
||||
}
|
||||
|
||||
case *DictExpr:
|
||||
for _, entry := range n.List {
|
||||
entry := entry.(*DictEntry)
|
||||
Walk(entry.Key, f)
|
||||
Walk(entry.Value, f)
|
||||
}
|
||||
|
||||
case *UnaryExpr:
|
||||
if n.X != nil {
|
||||
Walk(n.X, f)
|
||||
}
|
||||
|
||||
case *BinaryExpr:
|
||||
Walk(n.X, f)
|
||||
Walk(n.Y, f)
|
||||
|
||||
case *DotExpr:
|
||||
Walk(n.X, f)
|
||||
Walk(n.Name, f)
|
||||
|
||||
case *CallExpr:
|
||||
Walk(n.Fn, f)
|
||||
for _, arg := range n.Args {
|
||||
Walk(arg, f)
|
||||
}
|
||||
|
||||
case *LambdaExpr:
|
||||
for _, param := range n.Params {
|
||||
Walk(param, f)
|
||||
}
|
||||
Walk(n.Body, f)
|
||||
|
||||
default:
|
||||
panic(n)
|
||||
}
|
||||
|
||||
f(nil)
|
||||
}
|
||||
|
||||
func walkStmts(stmts []Stmt, f func(Node) bool) {
|
||||
for _, stmt := range stmts {
|
||||
Walk(stmt, f)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user