From b11e9f2eaeea6ef8b67e1736f39cc805d4739bfe Mon Sep 17 00:00:00 2001 From: Matthieu Dartiailh Date: Tue, 14 Nov 2023 10:13:14 +0100 Subject: [PATCH] Python grammar fixes: typing in parser class and f-string fix (#97) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * python.gram: fix several typing issues in the base parser class typing * python: fix small issue in f-string parsing --- data/python.gram | 25 +++++++++++++++++-------- tests/python_parser/data/fstrings.py | 2 +- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/data/python.gram b/data/python.gram index c1f478b..b6853f2 100644 --- a/data/python.gram +++ b/data/python.gram @@ -227,13 +227,13 @@ class Parser(Parser): node.ctx = context return node - def ensure_real(self, number: ast.Constant) -> float: + def ensure_real(self, number: tokenize.TokenInfo) -> float: value = ast.literal_eval(number.string) if type(value) is complex: self.raise_syntax_error_known_location("real number required in complex literal", number) return value - def ensure_imaginary(self, number: ast.Constant) -> complex: + def ensure_imaginary(self, number: tokenize.TokenInfo) -> complex: value = ast.literal_eval(number.string) if type(value) is not complex: self.raise_syntax_error_known_location("imaginary number required in complex literal", number) @@ -340,7 +340,7 @@ class Parser(Parser): args += (err.end_lineno + line_offset - 2, err.end_offset) err_args = (err.msg, args) # Ensure we do not keep the frame alive longer than necessary - # by explicitely deleting the error once we got what we needed out + # by explicitly deleting the error once we got what we needed out # of it del err @@ -434,7 +434,7 @@ class Parser(Parser): message: str, start: Optional[Tuple[int, int]] = None, end: Optional[Tuple[int, int]] = None - ) -> None: + ) -> SyntaxError: line_from_token = start is None and end is None if start is None or end is None: tok = self._tokenizer.diagnose() @@ -466,14 +466,20 @@ class Parser(Parser): ) -> NoReturn: raise self._build_syntax_error(message, start, end) - def make_syntax_error(self, message: str) -> None: + def make_syntax_error(self, message: str) -> SyntaxError: return self._build_syntax_error(message) def expect_forced(self, res: Any, expectation: str) -> Optional[tokenize.TokenInfo]: if res is None: last_token = self._tokenizer.diagnose() end = last_token.start - if sys.version_info >= (3, 12) or (sys.version_info >= (3, 11) and last_token.type != 4): # i.e. not a \n + if ( + sys.version_info >= (3, 12) + or ( + sys.version_info >= (3, 11) + and last_token.type != 4 + ) + ): # i.e. not a \n end = last_token.end self.raise_raw_syntax_error( f"expected {expectation}", last_token.start, end @@ -483,7 +489,10 @@ class Parser(Parser): def raise_syntax_error(self, message: str) -> NoReturn: """Raise a syntax error.""" tok = self._tokenizer.diagnose() - raise self._build_syntax_error(message, tok.start, tok.end if sys.version_info >= (3, 12) or tok.type != 4 else tok.start) + raise self._build_syntax_error( + message, tok.start, + tok.end if sys.version_info >= (3, 12) or tok.type != 4 else tok.start + ) def raise_syntax_error_known_location( self, message: str, node: Union[ast.AST, tokenize.TokenInfo] @@ -532,7 +541,7 @@ class Parser(Parser): def raise_syntax_error_invalid_target( self, target: Target, node: Optional[ast.AST] - ) -> NoReturn: + ) -> None: invalid_target = self.get_invalid_target(target, node) if invalid_target is None: diff --git a/tests/python_parser/data/fstrings.py b/tests/python_parser/data/fstrings.py index c2773e7..5281796 100644 --- a/tests/python_parser/data/fstrings.py +++ b/tests/python_parser/data/fstrings.py @@ -65,6 +65,6 @@ f'{expr:}' - +f'{expr:d}' foo = 3.14159 verbosePrint(f'Foo {foo:.3} bar.')