Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -1287,6 +1287,12 @@ invalid_named_expression(memo):
| a=expression ':=' expression {
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
a, "cannot use assignment expressions with %s", _PyPegen_get_expr_name(a)) }
| a=expression '&''&' b=expression {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. This is actually a different feature. You can even open a separate issue and PR for this (if there is no already open). Anyway, this is a nice improvement.

I suggest to add also cases for <> ("not equal" in Pascal and Python 2), "=<", "=>" and "=!" (typo in "<=", ">=" and "!="), "===" ("is" in JavaScript and PHP).

RAISE_SYNTAX_ERROR_KNOWN_RANGE(
a, b, "invalid syntax '&&'. Use 'and' instead.") }
| a=expression '|''|' b=expression {
RAISE_SYNTAX_ERROR_KNOWN_RANGE(
a, b, "invalid syntax '||'. Use 'or' instead.") }
| a=NAME '=' b=bitwise_or !('='|':=') {
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?") }
| !(list|tuple|genexp|'True'|'None'|'False') a=bitwise_or b='=' bitwise_or !('='|':=') {
Expand Down
27 changes: 26 additions & 1 deletion Lib/traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -1485,8 +1485,12 @@ def _find_keyword_typos(self):
# Limit the number of possible matches to try
max_matches = 3
matches = []

hint = _get_cross_language_keyword_hint(wrong_name)
if hint:
matches.append(hint)
if _suggestions is not None:
suggestion = _suggestions._generate_suggestions(keyword.kwlist, wrong_name)
suggestion = _suggestions._generate_suggestions(keyword.kwlist + keyword.softkwlist, wrong_name)
if suggestion:
matches.append(suggestion)
matches.extend(difflib.get_close_matches(wrong_name, keyword.kwlist, n=max_matches, cutoff=0.5))
Expand Down Expand Up @@ -1787,6 +1791,20 @@ def print(self, *, file=None, chain=True, **kwargs):
})


# Cross-language keyword suggestions.
_CROSS_LANGUAGE_KEYWORD_HINTS = frozendict({
# C/C++ equivalents
'switch': 'match',
'delete': 'del',
# function define equivalents
'function': 'def',
'func': 'def',
# null equivalents
'NULL': 'None',
'null': 'None',
'nil': 'None',
})

def _substitution_cost(ch_a, ch_b):
if ch_a == ch_b:
return 0
Expand Down Expand Up @@ -1866,6 +1884,13 @@ def _get_cross_language_hint(obj, wrong_name):
return None


def _get_cross_language_keyword_hint(wrong_name):
"""Check if wrong_name is a common keyword from another language
"""
hint = _CROSS_LANGUAGE_KEYWORD_HINTS.get(wrong_name)
return hint
Comment on lines +1890 to +1891

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
hint = _CROSS_LANGUAGE_KEYWORD_HINTS.get(wrong_name)
return hint
return _CROSS_LANGUAGE_KEYWORD_HINTS.get(wrong_name)

Or maybe just call the get method directly if there isn't any extra logic?



def _get_safe___dir__(obj):
# Use obj.__dir__() to avoid a TypeError when calling dir(obj).
# See gh-131001 and gh-139933.
Expand Down
68 changes: 68 additions & 0 deletions Parser/parser.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading