open-standards/wai/tools/tree-sitter-openqasm/grammar.js
Transaction Science 0f5e2268d4
Some checks failed
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 7s
wai-audit collector and player integration / does this change touch it (pull_request) Successful in 9s
WAI energy receipts / does this change touch it (pull_request) Successful in 13s
WAI conformance / does this change touch it (pull_request) Successful in 14s
WAI examples / WAI examples · does this change touch them (pull_request) Successful in 6s
wai-quantum command line / does this change touch it (pull_request) Successful in 7s
wai-quantum dataflow member / does this change touch it (pull_request) Successful in 8s
wai-quantum CUDA member / does this change touch it (pull_request) Successful in 9s
wai-quantum signal processor / does this change touch it (pull_request) Successful in 8s
wai-quantum editors / does this change touch it (pull_request) Successful in 6s
wai-quantum FPGA member / does this change touch it (pull_request) Successful in 7s
wai-quantum HIP member / does this change touch it (pull_request) Successful in 8s
wai-quantum Metal member / does this change touch it (pull_request) Successful in 7s
wai-quantum OpenQASM reader / does this change touch it (pull_request) Successful in 8s
wai-quantum npu-cores member / does this change touch it (pull_request) Successful in 6s
wai-quantum neural-processor member / does this change touch it (pull_request) Successful in 8s
wai-quantum OpenCL member / does this change touch it (pull_request) Successful in 9s
wai-quantum for Python / does this change touch it (pull_request) Successful in 10s
wai-quantum-qpu / does this change touch it (pull_request) Successful in 7s
wai-quantum matrix-extension member / does this change touch it (pull_request) Successful in 7s
wai-quantum service / does this change touch it (pull_request) Successful in 9s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 8s
wai-quantum tensor-engine member / does this change touch it (pull_request) Successful in 6s
wai-quantum CUDA member / member · CUDA (jetson-hub) (pull_request) Successful in 30s
wai-quantum portable tensor program / does this change touch it (pull_request) Successful in 7s
wai-quantum CPU vector units / does this change touch it (pull_request) Successful in 7s
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 8s
wai-sink-android native sink library / does this change touch it (pull_request) Successful in 6s
wai-sink-swift native sink package / does this change touch it (pull_request) Successful in 6s
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Successful in 6s
wai-web wasm32 / does this change touch it (pull_request) Successful in 6s
wai-quantum OpenCL member / member · OpenCL GPU and CPU (jetson-hub) (pull_request) Successful in 29s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 27s
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Successful in 26s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Successful in 1m44s
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Successful in 2m14s
standards workspaces build + test / macOS energy backends (pull_request) Failing after 2m12s
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Successful in 3m10s
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Successful in 2m57s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m26s
wai-quantum HIP member / member · HIP (framework-128gb) (pull_request) Successful in 28s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 1m23s
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Successful in 4m37s
wai-quantum npu-cores member / member · npu-cores, neural processor (framework-128gb silicon) (pull_request) Successful in 1m17s
wai-quantum OpenCL member / member · OpenCL GPU (framework-128gb) (pull_request) Successful in 23s
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Successful in 12s
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Successful in 5m41s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 6s
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Successful in 17s
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Successful in 6m40s
wai-audit collector and player integration / collector · linux (pull_request) Successful in 1m8s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 3m26s
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Successful in 9m5s
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Successful in 7m28s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 9m35s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 9m39s
wai-quantum command line / command line · macos (pull_request) Successful in 58s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 14s
wai-quantum dataflow member / member · dataflow device absent (macos) (pull_request) Successful in 25s
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m3s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 52s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 37s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 3m15s
wai-quantum editors / editors · macos (pull_request) Successful in 1m6s
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m26s
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Successful in 9m53s
wai-quantum CUDA member / member · CUDA absent (linux) (pull_request) Successful in 32s
wai-quantum FPGA member / member · FPGA datapath, simulated (macos) (pull_request) Successful in 1m33s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 13m2s
wai-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Successful in 9m39s
wai-quantum command line / command line · linux (pull_request) Successful in 2m3s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 8m45s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m51s
wai-quantum Metal member / member · Metal (macos) (pull_request) Successful in 56s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 45s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 30s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 23s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 13m13s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:b140) (pull_request) Successful in 4m10s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 11m26s
wai-quantum FPGA member / member · FPGA simulation absent (linux) (pull_request) Successful in 19s
wai-quantum Metal member / member · Metal absent (linux) (pull_request) Successful in 30s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:401e) (pull_request) Successful in 4m42s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 2m49s
wai-quantum editors / editors · linux (pull_request) Successful in 1m36s
wai-quantum OpenQASM reader / corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 35s
wai-quantum neural-processor member / member · neural processor absent (linux) (pull_request) Successful in 20s
wai-quantum OpenCL member / member · OpenCL absent (linux) (pull_request) Successful in 25s
wai-quantum OpenQASM reader / reader and corpus · linux (pull_request) Successful in 1m13s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m50s
wai-quantum matrix-extension member / member · matrix extension, emulated (aarch64 Linux) (pull_request) Successful in 17s
wai-quantum-qpu / clients against their contracts (linux) (pull_request) Successful in 40s
wai-quantum service / service · linux (pull_request) Successful in 56s
wai-quantum for Python / python · linux (pull_request) Successful in 1m52s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 14m44s
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Successful in 42s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 10m6s
wai-quantum OpenCL member / member · OpenCL GPU (macos) (pull_request) Successful in 33s
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Successful in 22s
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Successful in 11s
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Successful in 40s
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Successful in 23s
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Successful in 10s
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Successful in 23s
wai-quantum for Python / python · macos (pull_request) Successful in 1m47s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 3m40s
wai-quantum-qpu / credentials in the keychain (macos) (pull_request) Successful in 21s
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Successful in 22m52s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 23m2s
wai-quantum matrix-extension member / member · matrix extension absent (macos) (pull_request) Successful in 15s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 23m58s
wai-quantum neural-processor member / member · neural processor (macos) (pull_request) Successful in 10m31s
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Successful in 18s
wai-quantum service / service · macos (pull_request) Successful in 58s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 2m30s
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Successful in 17s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Successful in 4m55s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Successful in 3m29s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 20m35s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 1m55s
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Successful in 13m40s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 3m7s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 2m56s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m40s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 6m52s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 5m13s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 7m12s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 8m44s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 17m32s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h0m53s
tree-sitter-openqasm: an output declaration may name its value, as the reader takes it
The editors' CI parses every program in the repository; the OpenQASM 3
corpus's lang/output.qasm declares `output int[32] n = 3;`, which the
engine's reader takes and the grammar refused. The generated parser is
regenerated; 97 of 97 programs parse, and fmt holds on all of them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 22:39:46 -04:00

411 lines
13 KiB
JavaScript

/**
* @file OpenQASM 3, and the OpenQASM 2 forms in common use, for tree-sitter.
* @license Apache-2.0
*
* The grammar reads what is written: every statement of OpenQASM 3.1
* (declarations of every type, gates and subroutines, modifiers, control
* flow, timing, calibrations, pragmas and annotations) and OpenQASM 2's
* `qreg`, `creg`, `opaque`, `measure q -> c` and `if(c==1)`. It does not say
* what a program means; the engine's reader does.
*/
/// <reference types="tree-sitter-cli/dsl" />
// @ts-check
const PREC = {
logical_or: 1,
logical_and: 2,
bit_or: 3,
bit_xor: 4,
bit_and: 5,
equality: 6,
comparison: 7,
shift: 8,
additive: 9,
multiplicative: 10,
unary: 11,
power: 12,
call: 13,
index: 14,
};
const DECIMAL = /[0-9](_?[0-9])*/;
const FLOAT = choice(
seq(DECIMAL, '.', optional(DECIMAL), optional(/[eE][+-]?[0-9]+/)),
seq('.', DECIMAL, optional(/[eE][+-]?[0-9]+/)),
seq(DECIMAL, /[eE][+-]?[0-9]+/),
);
/**
* One or more of `rule`, separated by commas, with an optional trailing comma.
* @param {RuleOrLiteral} rule
*/
function commaSep1(rule) {
return seq(rule, repeat(seq(',', rule)), optional(','));
}
module.exports = grammar({
name: 'openqasm',
extras: $ => [/\s/, $.line_comment, $.block_comment],
word: $ => $.identifier,
conflicts: $ => [
// After a name and `[`: `g[100ns] q;` calls a gate for a duration,
// `c[0] = …` assigns, and `c[0];` is an expression.
[$.gate_call, $.indexed_identifier, $._expression],
// `rx(θ)[100ns] q;` calls a gate for a duration; `f(x)[0];` indexes a call's value.
[$.gate_call, $.call_expression],
],
rules: {
source_file: $ => seq(optional($.version), repeat($._statement_or_scope)),
version: $ => seq('OPENQASM', field('number', choice($.integer_literal, $.float_literal)), ';'),
_statement_or_scope: $ => choice($._statement, $.scope),
scope: $ => seq('{', repeat($._statement_or_scope), '}'),
_statement: $ => choice(
$.pragma,
$.annotation,
$.include,
$.calibration_grammar,
$.quantum_declaration,
$.old_style_declaration,
$.classical_declaration,
$.const_declaration,
$.io_declaration,
$.alias_declaration,
$.gate_definition,
$.opaque_declaration,
$.subroutine_definition,
$.extern_declaration,
$.calibration,
$.calibration_definition,
$.gate_call,
$.gphase_call,
$.measure_statement,
$.reset_statement,
$.barrier_statement,
$.delay_statement,
$.box_statement,
$.assignment_statement,
$.expression_statement,
$.if_statement,
$.for_statement,
$.while_statement,
$.switch_statement,
$.return_statement,
$.break_statement,
$.continue_statement,
$.end_statement,
),
pragma: _ => token(seq(choice('#pragma', 'pragma'), /[^\n]*/)),
annotation: _ => token(seq('@', /[A-Za-z_][A-Za-z0-9_.]*/, /[^\n]*/)),
include: $ => seq('include', field('path', $.string), ';'),
calibration_grammar: $ => seq('defcalgrammar', field('name', $.string), ';'),
// Declarations.
quantum_declaration: $ => seq(field('type', $.qubit_type), field('name', $.identifier), ';'),
qubit_type: $ => seq('qubit', optional($.designator)),
old_style_declaration: $ => seq(choice('qreg', 'creg'), field('name', $.identifier), optional($.designator), ';'),
classical_declaration: $ => seq(
field('type', choice($.scalar_type, $.array_type)),
field('name', $.identifier),
optional(seq('=', field('value', $._declaration_value))),
';',
),
const_declaration: $ => seq('const', field('type', $.scalar_type), field('name', $.identifier), '=', field('value', $._declaration_value), ';'),
// `output` may name its value at once (`output int[32] n = 3;`), as the
// engine's reader takes it; `input` takes its value when the program is read.
io_declaration: $ => choice(
seq('input', field('type', choice($.scalar_type, $.array_type)), field('name', $.identifier), ';'),
seq('output', field('type', choice($.scalar_type, $.array_type)), field('name', $.identifier), optional(seq('=', field('value', $._expression))), ';'),
),
alias_declaration: $ => seq('let', field('name', $.identifier), '=', field('value', $.alias_expression), ';'),
_declaration_value: $ => choice($._expression, $.array_literal, $.measure_expression),
designator: $ => seq('[', $._expression, ']'),
scalar_type: $ => choice(
seq(choice('bit', 'int', 'uint', 'float', 'angle'), optional($.designator)),
'bool',
'duration',
'stretch',
seq('complex', optional(seq('[', $.scalar_type, ']'))),
),
array_type: $ => seq('array', '[', $.scalar_type, ',', commaSep1($._expression), ']'),
array_reference_type: $ => seq(
choice('readonly', 'mutable'),
'array',
'[',
$.scalar_type,
',',
choice(commaSep1($._expression), seq('#dim', '=', $._expression)),
']',
),
// Gates, subroutines and calibrations.
gate_definition: $ => seq(
'gate',
field('name', $.identifier),
optional(field('parameters', $.gate_parameters)),
field('qubits', $.identifier_list),
field('body', $.scope),
),
opaque_declaration: $ => seq('opaque', field('name', $.identifier), optional(field('parameters', $.gate_parameters)), field('qubits', $.identifier_list), ';'),
gate_parameters: $ => seq('(', optional(commaSep1($.identifier)), ')'),
identifier_list: $ => commaSep1($.identifier),
subroutine_definition: $ => seq(
'def',
field('name', $.identifier),
field('parameters', $.parameter_list),
optional(field('return_type', $.return_signature)),
field('body', $.scope),
),
parameter_list: $ => seq('(', optional(commaSep1($.parameter)), ')'),
parameter: $ => choice(
seq(field('type', choice($.scalar_type, $.qubit_type, $.array_reference_type)), field('name', $.identifier)),
seq(choice('creg', 'qreg'), field('name', $.identifier), optional($.designator)),
),
return_signature: $ => seq('->', $.scalar_type),
extern_declaration: $ => seq(
'extern',
field('name', $.identifier),
'(',
optional(commaSep1(choice($.scalar_type, $.array_reference_type, seq('creg', optional($.designator))))),
')',
optional(field('return_type', $.return_signature)),
';',
),
calibration: $ => seq('cal', field('body', $.calibration_block)),
calibration_definition: $ => seq(
'defcal',
field('target', choice('measure', 'reset', 'delay', $.identifier)),
optional(seq('(', optional(commaSep1(choice($.parameter, $._expression))), ')')),
commaSep1(choice($.hardware_qubit, $.identifier)),
optional(field('return_type', $.return_signature)),
field('body', $.calibration_block),
),
// A calibration's body is in its own grammar: kept as text, its braces matched.
calibration_block: $ => seq('{', repeat(choice($.calibration_text, $.calibration_block)), '}'),
calibration_text: _ => token(prec(-1, /[^{}\s][^{}]*/)),
// Quantum statements.
gate_call: $ => seq(
repeat($.gate_modifier),
field('name', $.identifier),
optional(field('arguments', $.argument_list)),
optional(field('duration', $.designator)),
field('operands', $.operand_list),
';',
),
gphase_call: $ => seq(
repeat($.gate_modifier),
'gphase',
optional(field('arguments', $.argument_list)),
optional(field('duration', $.designator)),
optional(field('operands', $.operand_list)),
';',
),
gate_modifier: $ => seq(
choice(
'inv',
seq('pow', '(', $._expression, ')'),
seq(choice('ctrl', 'negctrl'), optional(seq('(', $._expression, ')'))),
),
'@',
),
operand_list: $ => commaSep1($._operand),
_operand: $ => choice($.indexed_identifier, $.hardware_qubit),
indexed_identifier: $ => prec.left(seq($.identifier, repeat($.index))),
index: $ => seq('[', choice($.set_expression, commaSep1(choice($._expression, $.range_expression))), ']'),
measure_statement: $ => seq($.measure_expression, optional(seq('->', field('target', $.indexed_identifier))), ';'),
measure_expression: $ => seq('measure', field('operand', $._operand)),
reset_statement: $ => seq('reset', field('operand', $._operand), ';'),
barrier_statement: $ => seq('barrier', optional($.operand_list), ';'),
delay_statement: $ => seq('delay', field('duration', $.designator), optional($.operand_list), ';'),
box_statement: $ => seq('box', optional(field('duration', $.designator)), field('body', $.scope)),
// Classical statements.
assignment_statement: $ => seq(
field('left', $.indexed_identifier),
field('operator', choice('=', '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=', '~=', '<<=', '>>=', '**=')),
field('right', choice($._expression, $.measure_expression)),
';',
),
expression_statement: $ => seq($._expression, ';'),
if_statement: $ => prec.right(seq(
'if',
'(',
field('condition', $._expression),
')',
field('consequence', $._statement_or_scope),
optional(seq('else', field('alternative', $._statement_or_scope))),
)),
for_statement: $ => seq(
'for',
optional(field('type', $.scalar_type)),
field('variable', $.identifier),
'in',
field('iterable', choice($.set_expression, $.range, $.identifier)),
field('body', $._statement_or_scope),
),
range: $ => seq('[', $.range_expression, ']'),
while_statement: $ => seq('while', '(', field('condition', $._expression), ')', field('body', $._statement_or_scope)),
switch_statement: $ => seq('switch', '(', field('value', $._expression), ')', '{', repeat(choice($.case_clause, $.default_clause)), '}'),
case_clause: $ => seq('case', commaSep1($._expression), field('body', $.scope)),
default_clause: $ => seq('default', field('body', $.scope)),
return_statement: $ => seq('return', optional(choice($._expression, $.measure_expression)), ';'),
break_statement: _ => seq('break', ';'),
continue_statement: _ => seq('continue', ';'),
end_statement: _ => seq('end', ';'),
// Expressions.
_expression: $ => choice(
$.identifier,
$.hardware_qubit,
$.integer_literal,
$.float_literal,
$.imaginary_literal,
$.timing_literal,
$.boolean_literal,
$.string,
$.parenthesized_expression,
$.index_expression,
$.call_expression,
$.cast_expression,
$.durationof_expression,
$.unary_expression,
$.binary_expression,
),
parenthesized_expression: $ => seq('(', $._expression, ')'),
index_expression: $ => prec(PREC.index, seq(field('value', $._expression), $.index)),
call_expression: $ => seq(field('function', $.identifier), field('arguments', $.argument_list)),
argument_list: $ => seq('(', optional(commaSep1($._expression)), ')'),
cast_expression: $ => prec(PREC.call, seq(field('type', choice($.scalar_type, $.array_type)), '(', $._expression, ')')),
durationof_expression: $ => seq('durationof', '(', $.scope, ')'),
unary_expression: $ => prec(PREC.unary, seq(field('operator', choice('-', '+', '!', '~')), field('operand', $._expression))),
binary_expression: $ => {
/** @type {[string[], number, 'left' | 'right'][]} */
const table = [
[['**'], PREC.power, 'right'],
[['*', '/', '%'], PREC.multiplicative, 'left'],
[['+', '-'], PREC.additive, 'left'],
[['<<', '>>'], PREC.shift, 'left'],
[['<', '>', '<=', '>='], PREC.comparison, 'left'],
[['==', '!='], PREC.equality, 'left'],
[['&'], PREC.bit_and, 'left'],
[['^'], PREC.bit_xor, 'left'],
[['|'], PREC.bit_or, 'left'],
[['&&'], PREC.logical_and, 'left'],
[['||'], PREC.logical_or, 'left'],
];
return choice(...table.map(([ops, p, assoc]) => {
const op = ops.length === 1 ? ops[0] : choice(...ops);
const rule = seq(field('left', $._expression), field('operator', op), field('right', $._expression));
return assoc === 'right' ? prec.right(p, rule) : prec.left(p, rule);
}));
},
alias_expression: $ => seq($._expression, repeat(seq('++', $._expression))),
range_expression: $ => prec.right(seq(
optional(field('start', $._expression)),
':',
optional(field('step_or_end', $._expression)),
optional(seq(':', optional(field('end', $._expression)))),
)),
set_expression: $ => seq('{', commaSep1($._expression), '}'),
array_literal: $ => seq('{', optional(commaSep1(choice($._expression, $.array_literal))), '}'),
// Literals and names.
integer_literal: _ => token(choice(/0[bB][01](_?[01])*/, /0[oO][0-7](_?[0-7])*/, /0[xX][0-9a-fA-F](_?[0-9a-fA-F])*/, DECIMAL)),
float_literal: _ => token(FLOAT),
imaginary_literal: _ => token(seq(choice(FLOAT, DECIMAL), /[ \t]*/, 'im')),
timing_literal: _ => token(seq(choice(FLOAT, DECIMAL), choice('dt', 'ns', 'us', 'µs', 'ms', 's'))),
boolean_literal: _ => choice('true', 'false'),
string: _ => token(choice(/"[^"\n]*"/, /'[^'\n]*'/)),
hardware_qubit: _ => /\$[0-9]+/,
identifier: _ => /[\p{L}_][\p{L}\p{N}_]*/u,
line_comment: _ => token(seq('//', /[^\n]*/)),
block_comment: _ => token(seq('/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/')),
},
});