Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

qasmfmt

qasmfmt is a fast formatter for OpenQASM 3.0 quantum circuit files, written in Rust.

Features

  • Fast formatting powered by Rust
  • Available as both Rust and Python package
  • CLI and library interfaces
  • stdin/stdout support for pipeline usage
  • Configuration file support (qasmfmt.toml)
  • Directory recursive processing

Installation

pip install qasmfmt

Using Cargo

cargo install qasmfmt

From source

git clone https://github.com/orangekame3/qasmfmt
cd qasmfmt
cargo install --path .

Usage

CLI

qasmfmt [OPTIONS] [PATH]...

Modes (mutually exclusive)

OptionDescription
-w, --writeWrite formatted output back to files (in-place)
--checkCheck if files are formatted (exit 1 if not)
--diffShow unified diff of formatting changes (exit 1 if diff exists)

Options

OptionDescription
-i, --indent <N>Indentation size in spaces (default: 4)
--max-width <N>Maximum line width (default: 100)
--stdin-filename <PATH>Virtual filename for stdin input
--config <PATH>Path to configuration file
--no-configDisable automatic configuration file discovery
-V, --versionPrint version
-h, --helpPrint help

Examples

# Format file (print to stdout)
qasmfmt input.qasm

# Format file in-place
qasmfmt -w input.qasm

# Check if file is formatted (for CI)
qasmfmt --check input.qasm

# Show diff
qasmfmt --diff input.qasm

# Format from stdin
echo 'OPENQASM 3.0;qubit[2]q;' | qasmfmt
echo 'OPENQASM 3.0;qubit[2]q;' | qasmfmt -

# Format from stdin with virtual filename
echo 'OPENQASM 3.0;qubit[2]q;' | qasmfmt --stdin-filename circuit.qasm -

# Custom indent size
qasmfmt -i 2 input.qasm

# Format all .qasm files in a directory (recursive)
qasmfmt -w ./circuits/

# Check all .qasm files in a directory
qasmfmt --check ./src/

# Use specific config file
qasmfmt --config ./qasmfmt.toml input.qasm

# Disable config file auto-discovery
qasmfmt --no-config input.qasm

Configuration File

qasmfmt automatically searches for qasmfmt.toml from the input file’s directory upward.

# qasmfmt.toml
indent_size = 2
max_width = 80
indent_style = "spaces"  # or "tabs"
trailing_newline = true

CLI options override configuration file settings.

Python Library

import qasmfmt

# Format string
source = "OPENQASM 3.0;qubit[2]q;h q[0];"
formatted = qasmfmt.format_str(source)
print(formatted)
# OPENQASM 3.0;
# qubit[2] q;
# h q[0];

# Format with options
formatted = qasmfmt.format_str(source, indent_size=2, max_width=80)

# Format file
formatted = qasmfmt.format_file("circuit.qasm")

# Check if file is formatted
is_formatted = qasmfmt.check_file("circuit.qasm")

Rust Library

use qasmfmt::{format, format_with_config, FormatConfig};

fn main() {
    let source = "OPENQASM 3.0;qubit[2]q;";

    // Format with default config
    let formatted = format(source).unwrap();

    // Format with custom config
    let config = FormatConfig {
        indent_size: 2,
        ..Default::default()
    };
    let formatted = format_with_config(source, config).unwrap();
}

Example

Before:

OPENQASM 3.0;include"stdgates.inc";qubit[2]q;bit[2]c;h q[0];cx q[0],q[1];c=measure q;

After:

OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
bit[2] c;
h q[0];
cx q[0], q[1];
c = measure q;

Exit Codes

CodeDescription
0Success
1Error or formatting differences found (--check, --diff)
2Usage error (e.g., mutually exclusive options, stdin with --write)

CI Integration

GitHub Actions

- name: Check OpenQASM formatting
  run: |
    pip install qasmfmt
    qasmfmt --check .

pre-commit

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: qasmfmt
        name: qasmfmt
        entry: qasmfmt --check
        language: python
        additional_dependencies: [qasmfmt]
        files: \.qasm$

License

MIT License

Installation

cargo install qasmfmt

From Source

git clone https://github.com/orangekame3/qasmfmt
cd qasmfmt
cargo install --path .

Python

pip install qasmfmt

npm

npm install qasmfmt

Verify Installation

qasmfmt --version

Getting Started

Basic Usage

Format a file (in-place):

qasmfmt input.qasm

Format multiple files:

qasmfmt *.qasm

Format from stdin:

cat input.qasm | qasmfmt

Check Mode

Check if files are already formatted (useful for CI):

qasmfmt --check input.qasm

Exit codes:

  • 0: File is formatted
  • 1: File needs formatting
  • 2: Error (parse error, file not found, etc.)

Show Diff

Preview changes without modifying files:

qasmfmt --diff input.qasm

CLI Reference

Synopsis

qasmfmt [OPTIONS] [FILES...]

Options

OptionShortDescription
--checkCheck if files are formatted (exit 1 if not)
--diffShow diff instead of writing
--help-hPrint help
--version-VPrint version

Behavior

  • Default: Format files in-place
  • No files given: Read from stdin, write to stdout
  • With --check: Exit with 1 if files would be reformatted
  • With --diff: Show diff, do not modify files

Examples

# Format files in place
qasmfmt input.qasm
qasmfmt src/*.qasm

# Check if formatted (for CI)
qasmfmt --check input.qasm

# Show diff
qasmfmt --diff input.qasm

# Format from stdin
cat input.qasm | qasmfmt
echo "OPENQASM 3.0;qubit q;" | qasmfmt

# Format all QASM files recursively
find . -name "*.qasm" | xargs qasmfmt

Exit Codes

CodeMeaning
0Success
1Would reformat (with --check)
2Error (parse error, IO error)

Configuration

Configuration File

qasmfmt looks for qasmfmt.toml in the current directory.

# qasmfmt.toml

# Number of spaces per indentation level
indent_size = 2

# Maximum line width
max_width = 100

Options

OptionTypeDefaultDescription
indent_sizeinteger2Spaces per indent level
max_widthinteger100Maximum line width

Formatting Rules

This document defines the formatting rules for qasmfmt. Rules are based on analysis of examples from the official OpenQASM repository.


1. Version Declaration

// Before
OPENQASM  3.0;

// After
OPENQASM 3.0;
  • Single space between OPENQASM and version number

2. Include Statement

// Before
include"stdgates.inc";

// After
include "stdgates.inc";
  • Single space between include and file path

3. Declarations

3.1 Qubit Declaration

// Before
qubit[2]q;
qubitq;

// After
qubit[2] q;
qubit q;
  • No space between type and [
  • Single space between ] and identifier
  • Single space between type and identifier (when no array)

3.2 Classical Bit Declaration

// Before
bit[4]c;
bit c=0;

// After
bit[4] c;
bit c = 0;
  • Same rules as qubit declaration
  • Spaces around = for initialization

3.3 Constant/Variable Declaration

// Before
const int[32]n=3;

// After
const int[32] n = 3;

4. Gate Calls

4.1 Basic Gates

// Before
hq[0];

// After
h q[0];
  • Single space between gate name and arguments

4.2 Multiple Arguments

// Before
cxq[0],q[1];

// After
cx q[0], q[1];
  • Single space after comma
  • No space before comma

4.3 Parameterized Gates

// Before
rz(pi/4)q[0];
cphase(pi/2)q[0],q[1];

// After
rz(pi / 4) q[0];
cphase(pi / 2) q[0], q[1];
  • No space between gate name and (
  • Spaces around operators inside parameters
  • Single space between ) and arguments

5. Operators

5.1 Arithmetic Operators

// Before
pi/4+pi/8

// After
pi / 4 + pi / 8
  • Spaces around +, -, *, /

5.2 Comparison Operators

// Before
c==1
n!=0

// After
c == 1
n != 0
  • Spaces around ==, !=, <, >, <=, >=

5.3 Logical Operators

// Before
a&&b
c||d

// After
a && b
c || d

5.4 Assignment Operator

// Before
c=measure q;

// After
c = measure q;

6. Control Flow

6.1 If Statement

// Before
if(c==1)x q;
if(c==1){x q;}

// After
if (c == 1) x q;
if (c == 1) { x q; }
  • Single space between if and (
  • Single space between ) and statement/{

6.2 If-Else Statement

if (c == 1) {
  x q;
} else {
  z q;
}
  • Single space between } and else
  • Single space between else and {

6.3 While Statement

// Before
while(flags!=0){...}

// After
while (flags != 0) {
  ...
}

6.4 For Statement

for int i in [0:n] {
  ...
}

7. Gate Definition

// Before
gate mygate(theta)q{rz(theta)q;h q;}

// After
gate mygate(theta) q {
  rz(theta) q;
  h q;
}
  • Single space between gate and gate name
  • Single space between ) and qubit arguments
  • Single space between arguments and {
  • Body indented by 2 spaces
  • } on its own line

8. Subroutine Definition (def)

// Before
def myfunc(qubit q)->bit{bit b;measure q->b;return b;}

// After
def myfunc(qubit q) -> bit {
  bit b;
  measure q -> b;
  return b;
}
  • Spaces around ->
  • Body indented by 2 spaces

9. Measure Statement

9.1 Assignment Form

// Before
c=measure q;

// After
c = measure q;

9.2 Arrow Form

// Before
measure q->c;

// After
measure q -> c;
  • Spaces around ->

10. Barrier / Reset

barrier q;
reset q;
  • Single space between keyword and arguments

11. Indentation

  • Indent size: 2 spaces (default)
  • Style: Spaces only (no tabs)
gate mygate q {
  h q;
  if (c == 1) {
    x q;
  }
}

12. Blank Lines

12.1 After Include

OPENQASM 3.0;
include "stdgates.inc";

qubit q;
  • One blank line after include block

12.2 Around Gate/Def Definitions

qubit q;

gate mygate q {
  h q;
}

h q;
  • One blank line before and after gate/def definitions

12.3 Consecutive Blank Lines

  • Multiple consecutive blank lines are collapsed to one

13. Trailing

13.1 Trailing Whitespace

  • Trailing whitespace on each line is removed

13.2 Trailing Newline

  • Single newline at end of file (default)

Rule Summary

CategoryRuleExample
SpacingAfter includeinclude "file";
SpacingBetween type and identifierqubit[2] q;
SpacingBetween gate and argumentsh q;
SpacingAfter commacx q[0], q[1];
SpacingAround operatorsa + b, c == 1
SpacingBefore braces{ ... }
SpacingAfter if/whileif (cond)
IndentationInside blocks2 spaces
Blank linesAfter include1 line
Blank linesAround gate/def1 line

OpenQASM 3.0 Style Analysis

Analysis Date: January 2026

This document summarizes the analysis of examples from the official openqasm/openqasm repository.

Analyzed Files

  • teleport.qasm
  • qft.qasm
  • rb.qasm
  • gateteleport.qasm
  • rus.qasm
  • inverseqft1.qasm

Observed Style Patterns

1. Comments

// Line comment
/* Block comment */

2. OPENQASM Declaration

OPENQASM 3;  // With semicolon, without dot

Sometimes omitted (some examples start with include)

3. Include Statement

include "stdgates.inc";
  • Space between include and filename

4. Declarations

qubit[4] q;
bit[4] c;
const int[32] n = 3;
  • No space between type and [
  • Space between ] and identifier

5. Gate Calls

h q[0];
cx q[0], q[1];
cphase(pi / 2) q[1], q[0];
rz(pi/4) a;
  • Space between gate name and arguments
  • Space after comma
  • Inconsistent spacing inside parameters (pi / 2 and pi/4 both appear)

6. Gate/Def Definitions

gate post q { }

def segment(qubit[2] anc, qubit psi) -> bit[2] {
  bit[2] b;
  reset anc;
  ...
  return b;
}
  • Space before braces
  • Body indented by 2 spaces

7. If Statement

if(c0==1) z q[2];
if(c1==1) { x q[2]; }
if (r == 1) z q;

Inconsistent points:

  • if( vs if ( - presence/absence of space
  • Spacing around ==
  • Braces for single statements

8. While Statement

while(int[2](flags) != 0) {
  flags = segment(ancilla, input_qubit);
}

9. Measure

c0 = measure q[0];     // Assignment form
measure q -> c;        // Arrow form

Both forms are used

10. Barrier

barrier q;

Inconsistent Points (to be unified by qasmfmt)

ItemOfficial Examplesqasmfmt Policy
if( vs if (MixedUnify to if (
Spacing around ==MixedSpaces on both sides of ==
Spacing inside parametersMixedUnify to pi / 2
Braces for single statementsMixedAllow without braces

Proposed qasmfmt Rules

Confirmed Rules (consistent in official examples)

✓ Space after include
✓ Space between type and identifier (qubit[2] q)
✓ Space between gate name and arguments (h q)
✓ Space after comma
✓ 2-space indent inside blocks
✓ Space before braces

Normalization Rules (qasmfmt will enforce)

→ Space after if ( and while (
→ Spaces around comparison operators (== != < >)
→ Spaces around arithmetic operators (+ - * /)
→ Spaces around assignment operator (=)

Configurable (future)

? Indentation: 2 or 4 spaces
? Maximum line width: 80 or 100

Architecture

Overview

qasmfmt uses a pipeline architecture inspired by rustfmt:

Source Code
    ↓
┌─────────────┐
│   Parser    │  ← oq3_syntax
└─────────────┘
    ↓
┌─────────────┐
│     AST     │
└─────────────┘
    ↓
┌─────────────┐
│  IR (Doc)   │  ← Intermediate Representation
└─────────────┘
    ↓
┌─────────────┐
│   Printer   │  ← Pretty Printer
└─────────────┘
    ↓
Formatted Code

Modules

ModuleDescription
configConfiguration handling
errorError types
irIntermediate representation (Doc)
printerPretty printer
formatAST to IR conversion
commentComment extraction

IR (Doc)

The intermediate representation is based on Wadler’s “A prettier printer”:

#![allow(unused)]
fn main() {
enum Doc {
    Nil,
    Text(String),
    Hardline,
    Softline,
    Concat(Vec<Doc>),
    Indent(Box<Doc>),
    Group(Box<Doc>),
}
}

Dependencies

  • oq3_syntax - OpenQASM 3.0 parser
  • serde - Serialization
  • thiserror - Error handling

Contributing

Development Setup

git clone https://github.com/orangekame3/qasmfmt
cd qasmfmt
cargo build

Running Tests

cargo test

Code Style

Format code before committing:

cargo fmt
cargo clippy

Pull Requests

  1. Fork the repository
  2. Create a feature branch
  3. Make changes
  4. Run tests
  5. Submit PR

Reporting Issues

Please include:

  • qasmfmt version
  • Input QASM code
  • Expected output
  • Actual output