Skip to content
Open
16 changes: 16 additions & 0 deletions Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ is_bitwise_or[CmpopExprPair*]: 'is' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, I

bitwise_or[expr_ty]:
| a=bitwise_or '|' b=bitwise_xor { _PyAST_BinOp(a, BitOr, b, EXTRA) }
| invalid_bitwise_or
| bitwise_xor

bitwise_xor[expr_ty]:
Expand All @@ -827,6 +828,7 @@ bitwise_xor[expr_ty]:

bitwise_and[expr_ty]:
| a=bitwise_and '&' b=shift_expr { _PyAST_BinOp(a, BitAnd, b, EXTRA) }
| invalid_bitwise_and
| shift_expr

shift_expr[expr_ty]:
Expand Down Expand Up @@ -1638,3 +1640,17 @@ invalid_type_params:
RAISE_SYNTAX_ERROR_STARTING_FROM(
token,
"Type parameter list cannot be empty")}

invalid_bitwise_and:
| a=bitwise_and b='&' c='&' {
_PyPegen_tokens_are_adjacent(b, c)
? RAISE_SYNTAX_ERROR_KNOWN_RANGE(b, c, "invalid syntax. Maybe you meant 'and' or '&' instead of '&&'?")
: NULL
}

invalid_bitwise_or:
| a=bitwise_or b='|' c='|' {
_PyPegen_tokens_are_adjacent(b, c)
? RAISE_SYNTAX_ERROR_KNOWN_RANGE(b, c, "invalid syntax. Maybe you meant 'or' or '|' instead of '||'?")
: NULL
}
44 changes: 44 additions & 0 deletions Lib/test/test_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -3505,6 +3505,50 @@ def test_ifexp_body_stmt_else_stmt(self):
]:
self._check_error(f"x = {lhs_stmt} if 1 else {rhs_stmt}", msg)

def test_double_ampersand(self):
self._check_error(
"a && b",
r"Maybe you meant 'and' or '&' instead of '&&'\?",
lineno=1,
end_lineno=1,
offset=3,
end_offset=5,
)
self._check_error(
"a & & b",
Comment thread
serhiy-storchaka marked this conversation as resolved.
"invalid syntax",
Comment thread
serhiy-storchaka marked this conversation as resolved.
lineno=1,
end_lineno=1,
offset=5,
end_offset=6,
)
self._check_error(
"(a &\n & b)",
"invalid syntax",
lineno=2,
end_lineno=2,
offset=5,
end_offset=6,
)

def test_double_pipe(self):
self._check_error(
"a || b",
r"Maybe you meant 'or' or '|' instead of '||'\?",
lineno=1,
end_lineno=1,
offset=3,
end_offset=5,
)
self._check_error(
"a | | b",
"invalid syntax",
lineno=1,
end_lineno=1,
offset=5,
end_offset=6,
)


class LazyImportRestrictionTestCase(SyntaxErrorTestCase):
"""Test syntax restrictions for lazy imports."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve :exc:`SyntaxError` message for ``&&`` and ``||`` operators, suggesting ``and``/``&`` and ``or``/``|`` respectively.
Loading
Loading