Reference OpenQASM AST in Python - contains the reference abstract syntax tree (AST) for representing OpenQASM 3 programs, tools to parse text into this AST, and tools to manipulate the AST
—
Parse OpenQASM 3 source code into the reference AST with full language support and error reporting. The parser converts textual OpenQASM 3 programs into structured AST representations that can be analyzed, manipulated, and converted back to text.
Note: Parsing functionality requires the [parser] extra installation: pip install openqasm3[parser]
Parse complete OpenQASM 3 programs from text with comprehensive language support.
def parse(input_: str, *, permissive: bool = False) -> ast.Program:
"""
Parse a complete OpenQASM 3 program from text into the reference AST.
Args:
input_: A string containing a complete OpenQASM 3 program
permissive: If True, enables ANTLR error recovery for partial parsing
If False (default), raises exceptions on syntax errors
Returns:
A complete ast.Program node representing the parsed program
Raises:
QASM3ParsingError: When the program cannot be correctly parsed
ImportError: If the [parser] extra is not installed
"""Functions for managing source location information in parsed AST nodes.
def get_span(node: Union[ParserRuleContext, TerminalNode]) -> ast.Span:
"""
Extract source location span information from ANTLR parser nodes.
Args:
node: ANTLR parser node (ParserRuleContext or TerminalNode)
Returns:
ast.Span object with line/column information using ANTLR convention
(starting line number is 1, starting column number is 0)
"""
def add_span(node: _NodeT, span: ast.Span) -> _NodeT:
"""
Attach span information to an AST node.
Args:
node: Any AST node (must inherit from ast.QASMNode)
span: Source location span to attach
Returns:
The same node with span information attached
"""
def combine_span(first: ast.Span, second: ast.Span) -> ast.Span:
"""
Merge two spans into a single span covering both ranges.
Args:
first: First span to combine
second: Second span to combine
Returns:
Combined span covering the range from first.start to second.end
"""
def span(func):
"""
Function decorator that automatically attaches span information to AST nodes.
This decorator is used internally by visitor methods to automatically
attach source location information to AST nodes returned by the method.
Args:
func: Function to decorate (typically visitor methods)
Returns:
Decorated function with automatic span attachment
"""Advanced AST visitor for transforming ANTLR parse trees into OpenQASM 3 reference AST.
class QASMNodeVisitor(qasm3ParserVisitor):
"""
Main AST visitor class that transforms ANTLR parse tree into OpenQASM3 reference AST.
This class extends the ANTLR-generated visitor and provides comprehensive
visitor methods for all OpenQASM 3 language constructs. It handles:
- Context and scope management with stack-based tracking
- Error handling and validation during AST generation
- Support for all statement types, expressions, and declarations
- Proper type checking and semantic validation
"""
def visitProgram(self, ctx) -> ast.Program:
"""Entry point for program AST generation"""
def _push_context(self, context_type: str) -> None:
"""Push a new context onto the context stack"""
def _push_scope(self, scope_type: str) -> None:
"""Push a new scope onto the scope stack"""
def _in_global_scope(self) -> bool:
"""Check if currently in global scope"""
def _in_gate(self) -> bool:
"""Check if currently inside a gate definition"""
def _in_subroutine(self) -> bool:
"""Check if currently inside a subroutine definition"""
def _in_loop(self) -> bool:
"""Check if currently inside a loop construct"""
# Visitor methods for all AST node types (50+ methods)
def visitQubitDeclaration(self, ctx) -> ast.QubitDeclaration: ...
def visitQuantumGateDefinition(self, ctx) -> ast.QuantumGateDefinition: ...
def visitClassicalDeclaration(self, ctx) -> ast.ClassicalDeclaration: ...
def visitSubroutineDefinition(self, ctx) -> ast.SubroutineDefinition: ...
def visitBranchingStatement(self, ctx) -> ast.BranchingStatement: ...
def visitWhileLoop(self, ctx) -> ast.WhileLoop: ...
def visitForInLoop(self, ctx) -> ast.ForInLoop: ...
# ... and many more visitor methodsException classes for parsing error reporting.
class QASM3ParsingError(Exception):
"""
Exception raised during AST generation phase when a program cannot be correctly parsed.
This exception is thrown for semantic errors during the AST visitor phase,
such as type mismatches, scope violations, or invalid language constructs.
Syntax errors from the ANTLR parser are converted to this exception type.
"""import openqasm3
# Parse a simple OpenQASM 3 program
qasm_source = '''
OPENQASM 3.0;
qubit[2] q;
h q[0];
cx q[0], q[1];
measure q -> c;
'''
try:
program = openqasm3.parse(qasm_source)
print(f"Successfully parsed program with {len(program.statements)} statements")
print(f"Program version: {program.version}")
except openqasm3.parser.QASM3ParsingError as e:
print(f"Parsing failed: {e}")import openqasm3
# Parse with permissive mode for error recovery
incomplete_source = '''
OPENQASM 3.0;
qubit[2] q;
h q[0];
// Missing semicolon and incomplete statement
cx q[0]
'''
try:
# Permissive mode attempts to recover from syntax errors
program = openqasm3.parse(incomplete_source, permissive=True)
print("Parsed with error recovery")
except openqasm3.parser.QASM3ParsingError as e:
print(f"Even permissive parsing failed: {e}")from openqasm3.parser import parse, get_span, add_span
# Parse with full span information
source = "qubit q;"
program = parse(source)
# Access span information for error reporting
for stmt in program.statements:
if stmt.span:
print(f"Statement at line {stmt.span.start_line}, "
f"columns {stmt.span.start_column}-{stmt.span.end_column}")
# Custom visitor with span handling
from openqasm3.parser import QASMNodeVisitor
from openqasm3 import ast
class CustomVisitor(QASMNodeVisitor):
def visitQubitDeclaration(self, ctx):
node = super().visitQubitDeclaration(ctx)
# Add custom processing with span information
if node.span:
print(f"Found qubit declaration at line {node.span.start_line}")
return nodeimport openqasm3
# Parse a complex program with multiple constructs
complex_source = '''
OPENQASM 3.0;
include "stdgates.inc";
// Declare qubits and classical bits
qubit[3] q;
bit[3] c;
// Define a custom gate
gate bell(angle[32] theta) q0, q1 {
h q0;
rx(theta) q1;
cx q0, q1;
}
// Use classical variables and control flow
int[32] shots = 1000;
for int i in [0:shots-1] {
// Apply the custom gate
bell(pi/4) q[0], q[1];
// Conditional measurement
if (measure q[0] -> c[0] == 1) {
x q[2];
}
}
'''
program = openqasm3.parse(complex_source)
# Analyze the parsed program
print(f"Program version: {program.version}")
print(f"Number of statements: {len(program.statements)}")
# Count different statement types
statement_counts = {}
for stmt in program.statements:
stmt_type = type(stmt).__name__
statement_counts[stmt_type] = statement_counts.get(stmt_type, 0) + 1
for stmt_type, count in statement_counts.items():
print(f"{stmt_type}: {count}")The parser functionality requires additional dependencies:
pip install openqasm3[parser]This installs:
antlr4-python3-runtime: ANTLR runtime for Pythonimportlib_metadata: Metadata utilities (Python < 3.10)The parser uses ANTLR-generated lexer and parser classes from the main OpenQASM repository grammar files.
The parser supports the complete OpenQASM 3 specification including:
The parser provides detailed error reporting with:
Install with Tessl CLI
npx tessl i tessl/pypi-openqasm3