or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

ast-nodes.mdcode-generation.mdindex.mdparser.mdutilities.mdvisitors.md
tile.json

tessl/pypi-openqasm3

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

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/openqasm3@1.0.x

To install, run

npx @tessl/cli install tessl/pypi-openqasm3@1.0.0

index.mddocs/

OpenQASM 3 Python Reference

A comprehensive Python library that provides the reference abstract syntax tree (AST) for representing OpenQASM 3 programs, tools to parse text into this AST, and tools to manipulate the AST. This package enables developers to build OpenQASM 3 compiler passes, quantum circuit analyzers, and other quantum language processing tools in Python.

Package Information

  • Package Name: openqasm3
  • Language: Python
  • Installation:
    • Base package: pip install openqasm3 (AST, visitors, code generation only)
    • With parsing: pip install openqasm3[parser] (includes text-to-AST parsing)
  • License: Apache 2.0
  • Supported Python: ≥3.7

Core Imports

import openqasm3

Common imports for working with AST nodes:

from openqasm3 import ast

For parsing (requires [parser] extra):

from openqasm3 import parse
# or
import openqasm3
program = openqasm3.parse(qasm_source)

For AST manipulation:

from openqasm3 import visitor

For code generation:

from openqasm3 import dump, dumps

Basic Usage

import openqasm3
from openqasm3 import ast

# Parse OpenQASM 3 source code into AST (requires [parser] extra)
qasm_source = '''
OPENQASM 3.0;
qubit[2] q;
h q[0];
cx q[0], q[1];
'''

program = openqasm3.parse(qasm_source)
print(f"Program has {len(program.statements)} statements")

# Create AST nodes programmatically
qubit_decl = ast.QubitDeclaration(
    qubit=ast.Identifier("q"),
    size=ast.IntegerLiteral(2)
)

# Convert AST back to OpenQASM 3 text
qasm_text = openqasm3.dumps(program)
print(qasm_text)

# Walk and analyze AST using visitor pattern
class GateCounter(openqasm3.visitor.QASMVisitor):
    def __init__(self):
        self.gate_count = 0
    
    def visit_QuantumGate(self, node):
        self.gate_count += 1
        self.generic_visit(node)

counter = GateCounter()
counter.visit(program)
print(f"Found {counter.gate_count} quantum gates")

Architecture

The OpenQASM 3 Python reference follows a layered architecture:

  • AST Layer: Complete node hierarchy representing all OpenQASM 3 language constructs
  • Parser Layer: ANTLR-based parser for converting text to AST (optional)
  • Visitor Layer: Visitor and transformer patterns for AST traversal and manipulation
  • Printer Layer: AST-to-text conversion with configurable formatting
  • Utilities: Expression precedence, specification metadata, and type helpers

This design enables maximum reusability across quantum compiler toolchains, development environments, and language processing applications.

Capabilities

AST Node Hierarchy

Complete abstract syntax tree representing all OpenQASM 3 language constructs including quantum gates, classical code, control flow, type system, and calibration blocks.

# Base classes
@dataclass
class QASMNode:
    span: Optional[Span] = field(init=False, default=None, compare=False)

@dataclass  
class Statement(QASMNode):
    annotations: List[Annotation] = field(init=False, default_factory=list)

class Expression(QASMNode):
    pass

class ClassicalType(QASMNode):
    pass

# Program structure
@dataclass
class Program(QASMNode):
    statements: List[Union[Statement, Pragma]]
    version: Optional[str] = None

# Key statement types
@dataclass
class QubitDeclaration(Statement):
    qubit: Identifier
    size: Optional[Expression] = None

@dataclass
class QuantumGateDefinition(Statement):
    name: Identifier
    arguments: List[Identifier]
    qubits: List[Identifier]
    body: List[QuantumStatement]

@dataclass
class ClassicalDeclaration(Statement):
    type: ClassicalType
    identifier: Identifier
    init_expression: Optional[Union[Expression, QuantumMeasurement]] = None

@dataclass
class SubroutineDefinition(Statement):
    name: Identifier
    arguments: List[Union[ClassicalArgument, QuantumArgument]]
    body: List[Statement]
    return_type: Optional[ClassicalType] = None

AST Nodes

Text Parsing

Parse OpenQASM 3 source code into the reference AST with full language support and error reporting. Requires the [parser] extra installation.

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
    """

Parser

AST Visitors and Transformers

Visitor and transformer patterns for systematic AST traversal, analysis, and modification with optional context support.

class QASMVisitor(Generic[T]):
    def visit(self, node: QASMNode, context: Optional[T] = None):
        """Visit a node and dispatch to the appropriate visitor method"""
        
    def generic_visit(self, node: QASMNode, context: Optional[T] = None):
        """Called if no explicit visitor function exists for a node"""

class QASMTransformer(QASMVisitor[T]):
    def generic_visit(self, node: QASMNode, context: Optional[T] = None) -> QASMNode:
        """Visit and potentially modify nodes and their children"""

Visitors

Code Generation

Convert AST nodes back to valid OpenQASM 3 text with configurable formatting and complete language support.

def dump(node: ast.QASMNode, file: io.TextIOBase, **kwargs) -> None:
    """Write textual OpenQASM 3 code representing an AST node to an open stream"""

def dumps(node: ast.QASMNode, **kwargs) -> str:
    """Get a string representation of OpenQASM 3 code from an AST node"""

class Printer(QASMVisitor[PrinterState]):
    def __init__(self, stream: io.TextIOBase, indent: str = "  ", 
                 chain_else_if: bool = True, old_measurement: bool = False):
        """Initialize the printer with formatting options"""
        
    def visit(self, node: ast.QASMNode, context: Optional[PrinterState] = None) -> None:
        """Main entry point for visiting nodes and generating code"""

Code Generation

Utilities and Metadata

Expression precedence handling, specification version metadata, and other utility functions for working with OpenQASM 3 ASTs.

# Specification metadata
supported_versions: List[str]  # ["3.0", "3.1"]

# Expression precedence
def precedence(node_type: type) -> int:
    """
    Get the precedence level for an expression node type.
    Higher numbers indicate higher precedence (tighter binding).
    """

Utilities

Types

# Core enums
class AccessControl(Enum):
    readonly = "readonly"
    mutable = "mutable"

class TimeUnit(Enum):
    dt = "dt"
    ns = "ns"
    us = "us"
    ms = "ms"
    s = "s"

class BinaryOperator(Enum):
    # Comparison operators
    GT = ">"
    LT = "<"
    GTE = ">="
    LTE = "<="
    EQ = "=="
    NE = "!="
    # Logical operators
    LOGICAL_AND = "&&"
    LOGICAL_OR = "||"
    # Bitwise operators
    BITWISE_OR = "|"
    BITWISE_XOR = "^"
    BITWISE_AND = "&"
    LSHIFT = "<<"
    RSHIFT = ">>"
    # Arithmetic operators
    PLUS = "+"
    MINUS = "-"
    TIMES = "*"
    DIVIDE = "/"
    MODULO = "%"
    POWER = "**"

class UnaryOperator(Enum):
    BITWISE_NOT = "~"
    LOGICAL_NOT = "!"
    MINUS = "-"

class AssignmentOperator(Enum):
    EQUALS = "="
    PLUS_EQUALS = "+="
    MINUS_EQUALS = "-="
    TIMES_EQUALS = "*="
    DIVIDE_EQUALS = "/="
    BITWISE_AND_EQUALS = "&="
    BITWISE_OR_EQUALS = "|="
    BITWISE_NOT_EQUALS = "~="
    BITWISE_XOR_EQUALS = "^="
    LSHIFT_EQUALS = "<<="
    RSHIFT_EQUALS = ">>="
    MODULO_EQUALS = "%="
    POWER_EQUALS = "**="

class GateModifierName(Enum):
    inv = "inv"
    pow = "pow"
    ctrl = "ctrl"
    negctrl = "negctrl"

class IOKeyword(Enum):
    input = "input"
    output = "output"

# Location information
@dataclass
class Span:
    start_line: int
    start_column: int
    end_line: int
    end_column: int

# Type aliases
IndexElement = Union[DiscreteSet, List[Union[Expression, RangeDefinition]]]