diff --git a/parso/python/errors.py b/parso/python/errors.py index afe65b3..325c2ff 100644 --- a/parso/python/errors.py +++ b/parso/python/errors.py @@ -845,9 +845,8 @@ class _FStringRule(SyntaxRule): message_backslash = "f-string expression part cannot include a backslash" # f'{"\"}' or f'{"\\"}' message_comment = "f-string expression part cannot include '#'" # f'{#}' "f-string: unterminated string" # f'{"}' - "f-string: mismatched '(', '{', or '['" message_conversion = "f-string: invalid conversion character: expected 's', 'r', or 'a'" - "f-string: expecting '}'" # f'{' + message_incomplete = "f-string: expecting '}'" # f'{' @classmethod def _load_grammar(cls): @@ -865,6 +864,8 @@ class _FStringRule(SyntaxRule): for child in parsed.children: if child.type == 'expression': self._check_expression(child) + elif child.type == 'error_node': + self.add_issue(child, message=self.message_incomplete) def _check_python_expr(self, python_expr): value = python_expr.value diff --git a/parso/python/fstring.py b/parso/python/fstring.py index 8487a2a..7de632c 100644 --- a/parso/python/fstring.py +++ b/parso/python/fstring.py @@ -5,7 +5,7 @@ from parso.utils import split_lines from parso.python.tokenize import Token from parso.python import token from parso import parser -from parso.tree import TypedLeaf +from parso.tree import TypedLeaf, ErrorNode, ErrorLeaf version36 = PythonVersionInfo(3, 6) @@ -189,3 +189,18 @@ class Parser(parser.BaseParser): # TODO this is so ugly. leaf_type = TokenNamespace.token_map[type].lower() return TypedLeaf(leaf_type, value, start_pos, prefix) + + def error_recovery(self, pgen_grammar, stack, arcs, typ, value, start_pos, prefix, + add_token_callback): + if not self._error_recovery: + return super(Parser, self).error_recovery( + pgen_grammar, stack, arcs, typ, value, start_pos, prefix, + add_token_callback + ) + + dfa, state, (type_, nodes) = stack[1] + stack[0][2][1].append(ErrorNode(nodes)) + stack[1:] = [] + #error_leaf = tree.PythonErrorLeaf(tok_name[typ].lower(), value, start_pos, prefix) + + add_token_callback(typ, value, start_pos, prefix) diff --git a/parso/python/parser.py b/parso/python/parser.py index 15f80e6..039d625 100644 --- a/parso/python/parser.py +++ b/parso/python/parser.py @@ -135,11 +135,6 @@ class Parser(BaseParser): def error_recovery(self, pgen_grammar, stack, arcs, typ, value, start_pos, prefix, add_token_callback): - """ - This parser is written in a dynamic way, meaning that this parser - allows using different grammars (even non-Python). However, error - recovery is purely written for Python. - """ def get_symbol_and_nodes(stack): for dfa, state, (type_, nodes) in stack: symbol = pgen_grammar.number2symbol[type_] diff --git a/test/failing_examples.py b/test/failing_examples.py index 9145289..7827db6 100644 --- a/test/failing_examples.py +++ b/test/failing_examples.py @@ -146,6 +146,7 @@ FAILING_EXAMPLES = [ 'f"{#}"', "f'{1!b}'", "f'{1:{5:{3}}}'", + "f'{'", ] GLOBAL_NONLOCAL_ERROR = [