From 4b1786578a6f115ec1775b0a571502acd74391bb Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Tue, 5 Sep 2023 15:44:55 +0100 Subject: [PATCH] Handle final comments with no terminating newline in OpenQASM 2 Previously, if an OpenQASM 2 program to be parsed ended in a comment with no terminating '\n', the lexer would fail to notice the end of the file and would instead attempt to emit the second '/' of the comment introduction as a 'Slash` token. --- crates/qasm2/src/lex.rs | 7 +++++-- .../fix-qasm2-final-comment-f0904c3e13215a00.yaml | 5 +++++ test/python/qasm2/test_structure.py | 14 +++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/fix-qasm2-final-comment-f0904c3e13215a00.yaml diff --git a/crates/qasm2/src/lex.rs b/crates/qasm2/src/lex.rs index a6b3a6abac90..bab01f1bccab 100644 --- a/crates/qasm2/src/lex.rs +++ b/crates/qasm2/src/lex.rs @@ -665,8 +665,11 @@ impl TokenStream { b'}' => TokenType::RBrace, b'/' => { if let Some(b'/') = self.peek_byte()? { - self.advance_line()?; - return self.next(context); + return if self.advance_line()? == 0 { + Ok(None) + } else { + self.next(context) + } } else { TokenType::Slash } diff --git a/releasenotes/notes/fix-qasm2-final-comment-f0904c3e13215a00.yaml b/releasenotes/notes/fix-qasm2-final-comment-f0904c3e13215a00.yaml new file mode 100644 index 000000000000..53f114caf3e4 --- /dev/null +++ b/releasenotes/notes/fix-qasm2-final-comment-f0904c3e13215a00.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + OpenQASM 2 programs that end in comments with no terminating newline character will now parse + successfully. Fixed `#10770 `__. diff --git a/test/python/qasm2/test_structure.py b/test/python/qasm2/test_structure.py index 813dbd1e96d2..c0a66e9d2fe4 100644 --- a/test/python/qasm2/test_structure.py +++ b/test/python/qasm2/test_structure.py @@ -39,10 +39,22 @@ from . import gate_builder -class TestEmpty(QiskitTestCase): +@ddt.ddt +class TestWhitespace(QiskitTestCase): def test_allows_empty(self): self.assertEqual(qiskit.qasm2.loads(""), QuantumCircuit()) + @ddt.data("", "\n", "\r\n", "\n ") + def test_empty_except_comment(self, terminator): + program = "// final comment" + terminator + self.assertEqual(qiskit.qasm2.loads(program), QuantumCircuit()) + + @ddt.data("", "\n", "\r\n", "\n ") + def test_final_comment(self, terminator): + # This is similar to the empty-circuit test, except that we also have an instruction. + program = "qreg q[2]; // final comment" + terminator + self.assertEqual(qiskit.qasm2.loads(program), QuantumCircuit(QuantumRegister(2, "q"))) + class TestVersion(QiskitTestCase): def test_complete_version(self):