diff options
Diffstat (limited to 'syntax/testdata/errors.star')
-rw-r--r-- | syntax/testdata/errors.star | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/syntax/testdata/errors.star b/syntax/testdata/errors.star new file mode 100644 index 0000000..558845c --- /dev/null +++ b/syntax/testdata/errors.star @@ -0,0 +1,196 @@ +# Tests of parse errors. +# This is a "chunked" file; each "---" line demarcates a new parser input. +# +# TODO(adonovan): lots more tests. + +x = 1 + +2 ### "got newline, want primary expression" + +--- + +_ = *x ### `got '\*', want primary` + +--- + +def f(a, ): # trailing comma is ok + pass + +--- + +def f(*args, ): ### `got '\)', want parameter` + pass + +--- + +def f(**kwargs, ): ### `got '\)', want parameter` + pass + +--- + +def pass(): ### "not an identifier" + pass + +--- + +def f : ### `got ':', want '\('` + +--- + +f(a, ) # trailing comma is ok + +--- + +f(*args, ) ### `got '\)', want argument` + +--- + +f(**kwargs, ) ### `got '\)', want argument` + +--- + +_ = {x:y for y in z} # ok +_ = {x for y in z} ### `got for, want ':'` + +--- + +def f(): + pass + pass ### `unindent does not match any outer indentation level` + +--- +def f(): pass +--- +# Blank line after pass => outdent. +def f(): + pass + +--- +# No blank line after pass; EOF acts like a newline. +def f(): + pass +--- +# This is a well known parsing ambiguity in Python. +# Python 2.7 accepts it but Python3 and Starlark reject it. +_ = [x for x in lambda: True, lambda: False if x()] ### "got lambda, want primary" + +_ = [x for x in (lambda: True, lambda: False) if x()] # ok in all dialects + +--- +# Starlark, following Python 3, allows an unparenthesized +# tuple after 'in' only in a for statement but not in a comprehension. +# (Python 2.7 allows both.) +for x in 1, 2, 3: + print(x) + +_ = [x for x in 1, 2, 3] ### `got ',', want ']', for, or if` +--- +# Unparenthesized tuple is not allowed as operand of 'if' in comprehension. +_ = [a for b in c if 1, 2] ### `got ',', want ']', for, or if` + +--- +# Lambda is ok though. +_ = [a for b in c if lambda: d] # ok + +# But the body of such a lambda may not be a conditional: +_ = [a for b in c if (lambda: d if e else f)] # ok +_ = [a for b in c if lambda: d if e else f] ### "got else, want ']'" + +--- +# A lambda is not allowed as the operand of a 'for' clause. +_ = [a for b in lambda: c] ### `got lambda, want primary` + +--- +# Comparison operations are not associative. + +_ = (0 == 1) == 2 # ok +_ = 0 == (1 == 2) # ok +_ = 0 == 1 == 2 ### "== does not associate with ==" + +--- + +_ = (0 <= i) < n # ok +_ = 0 <= (i < n) # ok +_ = 0 <= i < n ### "<= does not associate with <" + +--- + +_ = (a in b) not in c # ok +_ = a in (b not in c) # ok +_ = a in b not in c ### "in does not associate with not in" + +--- +# shift/reduce ambiguity is reduced +_ = [x for x in a if b else c] ### `got else, want ']', for, or if` +--- +[a for b in c else d] ### `got else, want ']', for, or if` +--- +_ = a + b not c ### "got identifier, want in" +--- +f(1+2 = 3) ### "keyword argument must have form name=expr" +--- +print(1, 2, 3 ### `got end of file, want '\)'` +--- +_ = a if b ### "conditional expression without else clause" +--- +load("") ### "load statement must import at least 1 symbol" +--- +load("", 1) ### `load operand must be "name" or localname="name" \(got int literal\)` +--- +load("a", "x") # ok +--- +load(1, 2) ### "first operand of load statement must be a string literal" +--- +load("a", x) ### `load operand must be "x" or x="originalname"` +--- +load("a", x2=x) ### `original name of loaded symbol must be quoted: x2="originalname"` +--- +# All of these parse. +load("a", "x") +load("a", "x", y2="y") +load("a", x2="x", "y") # => positional-before-named arg check happens later (!) +--- +# 'load' is not an identifier +load = 1 ### `got '=', want '\('` +--- +# 'load' is not an identifier +f(load()) ### `got load, want primary` +--- +# 'load' is not an identifier +def load(): ### `not an identifier` + pass +--- +# 'load' is not an identifier +def f(load): ### `not an identifier` + pass +--- +# A load statement allows a trailing comma. +load("module", "x",) +--- +x = 1 + +2 ### "got newline, want primary expression" +--- +def f(): + pass +# this used to cause a spurious indentation error +--- +print 1 2 ### `got int literal, want newline` + +--- +# newlines are not allowed in raw string literals +raw = r'a ### `unexpected newline in string` +b' + +--- +# The parser permits an unparenthesized tuple expression for the first index. +x[1, 2:] # ok +--- +# But not if it has a trailing comma. +x[1, 2,:] ### `got ':', want primary` +--- +# Trailing tuple commas are permitted only within parens; see b/28867036. +(a, b,) = 1, 2 # ok +c, d = 1, 2 # ok +--- +a, b, = 1, 2 ### `unparenthesized tuple with trailing comma` +--- +a, b = 1, 2, ### `unparenthesized tuple with trailing comma` |