diff --git a/Lib/test/test_flufl.py b/Lib/test/test_flufl.py index bd6267d45ae..62360d9f9e4 100644 --- a/Lib/test/test_flufl.py +++ b/Lib/test/test_flufl.py @@ -22,7 +22,6 @@ def test_barry_as_bdfl(self): # parser reports the start of the token self.assertEqual(cm.exception.offset, 3) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_guido_as_bdfl(self): code = '2 {0} 3' compile(code.format('!='), '', 'exec') @@ -50,7 +49,6 @@ def test_barry_as_bdfl_look_ma_with_no_compiler_flags(self): self.assertEqual(cm.exception.lineno, 1) self.assertEqual(cm.exception.offset, len(code) - 4) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_barry_as_bdfl_relative_import(self): code = "from .__future__ import barry_as_FLUFL;2 {0} 3" compile(code.format('!='), '', 'exec') diff --git a/crates/compiler/src/lib.rs b/crates/compiler/src/lib.rs index 7562e8939b9..fc9b67614b5 100644 --- a/crates/compiler/src/lib.rs +++ b/crates/compiler/src/lib.rs @@ -362,9 +362,45 @@ fn cpython_parse_diagnostic_override( )); } + // `2 <> 3` outside Barry mode: ruff lexes `<` then an unexpected `>` and + // reports `ExpectedExpression` starting at the `>`. CPython's tokenizer + // treats `<>` as a single obsolete token and points at its start (the + // `<`) instead, so shift the reported location back over it. + source_error!(barry_flufl_obsolete_operator_error(error, source_text)); + + // CPython's PEG parser collapses a bare "expected an expression" failure + // into the generic "invalid syntax" message. rustpython-vm's `vm_new.rs` + // does this same collapse for its own callers; rustpython-compiler has no + // vm dependency, so mirror it here. + if matches!(&error.error, parser::ParseErrorType::ExpectedExpression) { + let (loc, end_loc) = adjusted_error_locations(source_file, error.location); + return Some(NormalizedParseDiagnostic::new( + parser::ParseErrorType::OtherError("invalid syntax".into()), + loc, + end_loc, + )); + } + None } +fn barry_flufl_obsolete_operator_error( + error: &parser::ParseError, + source: &str, +) -> Option<(String, usize, usize)> { + if !matches!(&error.error, parser::ParseErrorType::ExpectedExpression) { + return None; + } + let start = error.location.start().to_usize(); + if start == 0 || source.as_bytes().get(start - 1) != Some(&b'<') { + return None; + } + if source.as_bytes().get(start) != Some(&b'>') { + return None; + } + Some(("invalid syntax".to_string(), start - 1, start + 1)) +} + fn eof_parse_diagnostic( error: &parser::ParseError, source_file: &SourceFile,