syntax: parse "not not x"
+Test
Change-Id: I888b3dbe4ee4a73702adb4182da2a35286ad10dc
diff --git a/syntax/parse.go b/syntax/parse.go
index b733b8b..2bcc6f2 100644
--- a/syntax/parse.go
+++ b/syntax/parse.go
@@ -538,7 +538,7 @@
// expr = NOT expr
if p.tok == NOT && prec == int(precedence[NOT]) {
pos := p.nextToken()
- x := p.parseTestPrec(prec + 1)
+ x := p.parseTestPrec(prec)
return &UnaryExpr{
OpPos: pos,
Op: NOT,
@@ -591,16 +591,16 @@
// Unary MINUS, unary PLUS, and TILDE have higher precedence so are handled in parsePrimary.
// See https://github.com/google/skylark/blob/master/doc/spec.md#binary-operators
var preclevels = [...][]Token{
- {OR}, // or
- {AND}, // and
- {NOT}, // not (unary)
+ {OR}, // or
+ {AND}, // and
+ {NOT}, // not (unary)
{EQL, NEQ, LT, GT, LE, GE, IN, NOT_IN}, // == != < > <= >= in not in
- {PIPE}, // |
- {CIRCUMFLEX}, // ^
- {AMP}, // &
- {LTLT, GTGT}, // << >>
- {MINUS, PLUS}, // -
- {STAR, PERCENT, SLASH, SLASHSLASH}, // * % / //
+ {PIPE}, // |
+ {CIRCUMFLEX}, // ^
+ {AMP}, // &
+ {LTLT, GTGT}, // << >>
+ {MINUS, PLUS}, // -
+ {STAR, PERCENT, SLASH, SLASHSLASH}, // * % / //
}
func init() {
@@ -759,7 +759,7 @@
// | '[' ... // list literal or comprehension
// | '{' ... // dict literal or comprehension
// | '(' ... // tuple or parenthesized expression
-// | ('-'|'+') primary_with_suffix
+// | ('-'|'+'|'~') primary_with_suffix
func (p *parser) parsePrimary() Expr {
switch p.tok {
case IDENT:
@@ -805,8 +805,7 @@
Rparen: rparen,
}
- case MINUS, PLUS, TILDE:
- // unary minus/plus/tilde:
+ case MINUS, PLUS, TILDE: // unary
tok := p.tok
pos := p.nextToken()
x := p.parsePrimaryWithSuffix()
diff --git a/testdata/bool.sky b/testdata/bool.sky
index 19de9c2..4e6e622 100644
--- a/testdata/bool.sky
+++ b/testdata/bool.sky
@@ -5,17 +5,20 @@
# truth
assert.true(True)
assert.true(not False)
+assert.true(not not True)
# bool conversion
-assert.eq([bool(), bool(1), bool(0), bool("hello"), bool("")],
- [False, True, False, True, False])
+assert.eq(
+ [bool(), bool(1), bool(0), bool("hello"), bool("")],
+ [False, True, False, True, False],
+)
# comparison
assert.true(None == None)
assert.true(None != False)
assert.true(None != True)
-assert.eq(1==1, True)
-assert.eq(1==2, False)
+assert.eq(1 == 1, True)
+assert.eq(1 == 2, False)
assert.true(False == False)
assert.true(True == True)
@@ -34,10 +37,11 @@
# short-circuit evaluation of 'and' and 'or':
# 'or' yields the first true operand, or the last if all are false.
-assert.eq(0 or "" or [] or 0, 0)
-assert.eq(0 or "" or [] or 123 or 1/0, 123)
-assert.fails(lambda: 0 or "" or [] or 0 or 1/0, "division by zero")
+assert.eq(0 or "" or [] or 0, 0)
+assert.eq(0 or "" or [] or 123 or 1 / 0, 123)
+assert.fails(lambda : 0 or "" or [] or 0 or 1 / 0, "division by zero")
+
# 'and' yields the first false operand, or the last if all are true.
-assert.eq(1 and "a" and [1] and 123, 123)
-assert.eq(1 and "a" and [1] and 0 and 1/0, 0)
-assert.fails(lambda: 1 and "a" and [1] and 123 and 1/0, "division by zero")
+assert.eq(1 and "a" and [1] and 123, 123)
+assert.eq(1 and "a" and [1] and 0 and 1 / 0, 0)
+assert.fails(lambda : 1 and "a" and [1] and 123 and 1 / 0, "division by zero")