diff --git a/source/openpulse/openpulse/parser.py b/source/openpulse/openpulse/parser.py index ab8bd0e..5f9c6d2 100644 --- a/source/openpulse/openpulse/parser.py +++ b/source/openpulse/openpulse/parser.py @@ -87,7 +87,14 @@ def parse_openpulse( try: tree = parser.calibrationBlock() except (RecognitionException, ParseCancellationException) as exc: - raise OpenPulseParsingError() from exc + msg = "" + # With BailErrorStrategy, we should be able to recover and report + # information about the offending token. + if isinstance(exc, ParseCancellationException) and exc.args: + tok = getattr(exc.args[0], "offendingToken", None) + if tok is not None: + msg = f"Unexpected token '{tok.text}' at line {tok.line}, column {tok.start}." + raise OpenPulseParsingError(msg) from exc result = ( OpenPulseNodeVisitor(in_defcal).visitCalibrationBlock(tree) if tree.children diff --git a/source/openpulse/tests/test_openpulse_parser.py b/source/openpulse/tests/test_openpulse_parser.py index 555a509..b59836a 100644 --- a/source/openpulse/tests/test_openpulse_parser.py +++ b/source/openpulse/tests/test_openpulse_parser.py @@ -383,7 +383,7 @@ def test_permissive_parsing(capsys): captured = capsys.readouterr() assert captured.err.strip() == "line 2:9 no viable alternative at input 'int;'" - with pytest.raises(OpenPulseParsingError): + with pytest.raises(OpenPulseParsingError, match=r"Unexpected token ';' at line 2, column 10."): # This is stricter -- we fail as soon as ANTLR sees a problem parse(p) captured = capsys.readouterr()