go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/syntax/testdata/errors.star (about) 1 # Tests of parse errors. 2 # This is a "chunked" file; each "---" line demarcates a new parser input. 3 # 4 # TODO(adonovan): lots more tests. 5 6 x = 1 + 7 2 ### "got newline, want primary expression" 8 9 --- 10 11 _ = *x ### `got '\*', want primary` 12 13 --- 14 # trailing comma is ok 15 16 def f(a, ): pass 17 def f(*args, ): pass 18 def f(**kwargs, ): pass 19 20 --- 21 22 # Parameters are validated later. 23 def f(**kwargs, *args, *, b=1, a, **kwargs, *args, *, b=1, a): 24 pass 25 26 --- 27 28 def f(a, *-b, c): # ### `got '-', want ','` 29 pass 30 31 --- 32 33 def f(**kwargs, *args, b=1, a, **kwargs, *args, b=1, a): 34 pass 35 36 --- 37 38 def pass(): ### "not an identifier" 39 pass 40 41 --- 42 43 def f : ### `got ':', want '\('` 44 45 --- 46 # trailing comma is ok 47 48 f(a, ) 49 f(*args, ) 50 f(**kwargs, ) 51 52 --- 53 54 f(a=1, *, b=2) ### `got ',', want primary` 55 56 --- 57 58 _ = {x:y for y in z} # ok 59 _ = {x for y in z} ### `got for, want ':'` 60 61 --- 62 63 def f(): 64 pass 65 pass ### `unindent does not match any outer indentation level` 66 67 --- 68 def f(): pass 69 --- 70 # Blank line after pass => outdent. 71 def f(): 72 pass 73 74 --- 75 # No blank line after pass; EOF acts like a newline. 76 def f(): 77 pass 78 --- 79 # This is a well known parsing ambiguity in Python. 80 # Python 2.7 accepts it but Python3 and Starlark reject it. 81 _ = [x for x in lambda: True, lambda: False if x()] ### "got lambda, want primary" 82 83 _ = [x for x in (lambda: True, lambda: False) if x()] # ok in all dialects 84 85 --- 86 # Starlark, following Python 3, allows an unparenthesized 87 # tuple after 'in' only in a for statement but not in a comprehension. 88 # (Python 2.7 allows both.) 89 for x in 1, 2, 3: 90 print(x) 91 92 _ = [x for x in 1, 2, 3] ### `got ',', want ']', for, or if` 93 --- 94 # Unparenthesized tuple is not allowed as operand of 'if' in comprehension. 95 _ = [a for b in c if 1, 2] ### `got ',', want ']', for, or if` 96 97 --- 98 # Lambda is ok though. 99 _ = [a for b in c if lambda: d] # ok 100 101 # But the body of such a lambda may not be a conditional: 102 _ = [a for b in c if (lambda: d if e else f)] # ok 103 _ = [a for b in c if lambda: d if e else f] ### "got else, want ']'" 104 105 --- 106 # A lambda is not allowed as the operand of a 'for' clause. 107 _ = [a for b in lambda: c] ### `got lambda, want primary` 108 109 --- 110 # Comparison operations are not associative. 111 112 _ = (0 == 1) == 2 # ok 113 _ = 0 == (1 == 2) # ok 114 _ = 0 == 1 == 2 ### "== does not associate with ==" 115 116 --- 117 118 _ = (0 <= i) < n # ok 119 _ = 0 <= (i < n) # ok 120 _ = 0 <= i < n ### "<= does not associate with <" 121 122 --- 123 124 _ = (a in b) not in c # ok 125 _ = a in (b not in c) # ok 126 _ = a in b not in c ### "in does not associate with not in" 127 128 --- 129 # shift/reduce ambiguity is reduced 130 _ = [x for x in a if b else c] ### `got else, want ']', for, or if` 131 --- 132 [a for b in c else d] ### `got else, want ']', for, or if` 133 --- 134 _ = a + b not c ### "got identifier, want in" 135 --- 136 f(1+2 = 3) ### "keyword argument must have form name=expr" 137 --- 138 print(1, 2, 3 139 ### `got end of file, want '\)'` 140 --- 141 _ = a if b ### "conditional expression without else clause" 142 --- 143 load("") ### "load statement must import at least 1 symbol" 144 --- 145 load("", 1) ### `load operand must be "name" or localname="name" \(got int literal\)` 146 --- 147 load("a", "x") # ok 148 --- 149 load(1, 2) ### "first operand of load statement must be a string literal" 150 --- 151 load("a", x) ### `load operand must be "x" or x="originalname"` 152 --- 153 load("a", x2=x) ### `original name of loaded symbol must be quoted: x2="originalname"` 154 --- 155 # All of these parse. 156 load("a", "x") 157 load("a", "x", y2="y") 158 load("a", x2="x", "y") # => positional-before-named arg check happens later (!) 159 --- 160 # 'load' is not an identifier 161 load = 1 ### `got '=', want '\('` 162 --- 163 # 'load' is not an identifier 164 f(load()) ### `got load, want primary` 165 --- 166 # 'load' is not an identifier 167 def load(): ### `not an identifier` 168 pass 169 --- 170 # 'load' is not an identifier 171 def f(load): ### `not an identifier` 172 pass 173 --- 174 # A load statement allows a trailing comma. 175 load("module", "x",) 176 --- 177 x = 1 + 178 2 ### "got newline, want primary expression" 179 --- 180 def f(): 181 pass 182 # this used to cause a spurious indentation error 183 --- 184 print 1 2 ### `got int literal, want newline` 185 186 --- 187 # newlines are not allowed in raw string literals 188 raw = r'a ### `unexpected newline in string` 189 b' 190 191 --- 192 # The parser permits an unparenthesized tuple expression for the first index. 193 x[1, 2:] # ok 194 --- 195 # But not if it has a trailing comma. 196 x[1, 2,:] ### `got ':', want primary` 197 --- 198 # Trailing tuple commas are permitted only within parens; see b/28867036. 199 (a, b,) = 1, 2 # ok 200 c, d = 1, 2 # ok 201 --- 202 a, b, = 1, 2 ### `unparenthesized tuple with trailing comma` 203 --- 204 a, b = 1, 2, ### `unparenthesized tuple with trailing comma` 205 206 --- 207 # See github.com/google/starlark-go/issues/48 208 a = max(range(10))) ### `unexpected '\)'` 209 210 --- 211 # github.com/google/starlark-go/issues/85 212 s = "\x-0" ### `invalid escape sequence`