CtrlK
BlogDocsLog inGet started
Tessl Logo

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

Pending
Overview
Eval results
Files

parser.mddocs/

Text Parsing

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]

Capabilities

Main Parsing Function

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

Span Management Functions

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

Parser Visitor Class

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 methods

Error Handling

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

Usage Examples

Basic Parsing

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

Error Recovery Mode

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

Advanced Usage with Span Information

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 node

Working with Complex Programs

import 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}")

Installation Requirements

The parser functionality requires additional dependencies:

pip install openqasm3[parser]

This installs:

  • antlr4-python3-runtime: ANTLR runtime for Python
  • importlib_metadata: Metadata utilities (Python < 3.10)

The parser uses ANTLR-generated lexer and parser classes from the main OpenQASM repository grammar files.

Supported Language Features

The parser supports the complete OpenQASM 3 specification including:

  • Quantum declarations: qubits, quantum gates, gate modifiers
  • Classical types: integers, floats, complex, angles, bits, booleans, arrays
  • Control flow: if/else, while loops, for-in loops, switch statements
  • Subroutines: classical functions with parameters and return types
  • Measurements: quantum measurements with classical assignment
  • Timing: delay instructions, boxes, duration literals
  • Calibration: defcalgrammar, defcal, cal blocks
  • Advanced features: include statements, pragmas, annotations
  • Type system: full OpenQASM 3 type system with arrays and references

Error Reporting

The parser provides detailed error reporting with:

  • Syntax errors: Line and column information for invalid syntax
  • Semantic errors: Context-aware errors for type mismatches and scope violations
  • Span information: Source location tracking for all AST nodes
  • Error recovery: Optional permissive mode for partial parsing

Install with Tessl CLI

npx tessl i tessl/pypi-openqasm3

docs

ast-nodes.md

code-generation.md

index.md

parser.md

utilities.md

visitors.md

tile.json