Skip to main content

quil_rs/parser/
command.rs

1use nom::branch::alt;
2use nom::combinator::{map, map_res, opt};
3use nom::multi::{many0, many1, separated_list0, separated_list1};
4use nom::sequence::{delimited, preceded, tuple};
5
6use crate::expression::Expression;
7use crate::instruction::{
8    Arithmetic, ArithmeticOperator, BinaryLogic, BinaryOperator, CalibrationDefinition,
9    CalibrationIdentifier, Call, Capture, CircuitDefinition, Comparison, ComparisonOperator,
10    Convert, Declaration, DefGateSequence, Delay, Exchange, Fence, FrameDefinition, GateDefinition,
11    GateSpecification, GateType, Include, Instruction, Jump, JumpUnless, JumpWhen, Label, Load,
12    MeasureCalibrationDefinition, MeasureCalibrationIdentifier, Measurement, Move, PauliSum,
13    Pragma, PragmaArgument, Pulse, Qubit, RawCapture, Reset, SetFrequency, SetPhase, SetScale,
14    ShiftFrequency, ShiftPhase, Store, SwapPhases, Target, UnaryLogic, UnaryOperator,
15    UnresolvedCallArgument, ValidationError, Waveform, WaveformDefinition,
16};
17
18use crate::parser::common::parse_sequence_elements;
19use crate::parser::instruction::parse_block;
20use crate::parser::InternalParserResult;
21use crate::{real, token};
22
23use super::common::{parse_memory_reference_with_brackets, parse_variable_qubit};
24use super::{
25    common::{
26        parse_arithmetic_operand, parse_binary_logic_operand, parse_comparison_operand,
27        parse_frame_attribute, parse_frame_identifier, parse_gate_modifier, parse_matrix,
28        parse_memory_reference, parse_pauli_terms, parse_permutation, parse_qubit, parse_sharing,
29        parse_vector, parse_waveform_invocation, parse_waveform_name,
30    },
31    expression::parse_expression,
32    InternalParseError, ParserErrorKind, ParserInput,
33};
34
35/// Parse an arithmetic instruction of the form `destination source`.
36/// Called using the arithmetic operator itself (such as `ADD`) which should be previously parsed.
37pub(crate) fn parse_arithmetic(
38    operator: ArithmeticOperator,
39    input: ParserInput,
40) -> InternalParserResult<Instruction> {
41    let (input, destination) = parse_memory_reference(input)?;
42    let (input, source) = parse_arithmetic_operand(input)?;
43
44    Ok((
45        input,
46        Instruction::Arithmetic(Arithmetic {
47            operator,
48            destination,
49            source,
50        }),
51    ))
52}
53
54/// Parse a comparison instruction of the form `addr addr ( addr | number )`.
55/// Called using the comparison operator itself (such as `EQ`) which should be previously parsed.
56pub(crate) fn parse_comparison(
57    operator: ComparisonOperator,
58    input: ParserInput,
59) -> InternalParserResult<Instruction> {
60    let (input, destination) = parse_memory_reference(input)?;
61    let (input, lhs) = parse_memory_reference(input)?;
62    let (input, rhs) = parse_comparison_operand(input)?;
63
64    Ok((
65        input,
66        Instruction::Comparison(Comparison {
67            operator,
68            destination,
69            lhs,
70            rhs,
71        }),
72    ))
73}
74
75/// Parse a logical binary instruction of the form `addr ( addr | INT )`.
76/// Called using the logical operator itself (such as `AND`) which should be previously parsed.
77pub(crate) fn parse_logical_binary(
78    operator: BinaryOperator,
79    input: ParserInput,
80) -> InternalParserResult<Instruction> {
81    let (input, destination) = parse_memory_reference(input)?;
82    let (input, source) = parse_binary_logic_operand(input)?;
83
84    Ok((
85        input,
86        Instruction::BinaryLogic(BinaryLogic {
87            operator,
88            destination,
89            source,
90        }),
91    ))
92}
93
94/// Parse a logical unary instruction of the form `addr`.
95/// Called using the logical operator itself (such as `NOT`) which should be previously parsed.
96pub(crate) fn parse_logical_unary(
97    operator: UnaryOperator,
98    input: ParserInput,
99) -> InternalParserResult<Instruction> {
100    let (input, operand) = parse_memory_reference(input)?;
101
102    Ok((
103        input,
104        Instruction::UnaryLogic(UnaryLogic { operator, operand }),
105    ))
106}
107
108/// Parse the contents of a `DECLARE` instruction.
109pub(crate) fn parse_declare<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
110    let (input, name) = token!(Identifier(v))(input)?;
111    let (input, size) = parse_vector(input)?;
112    let (input, sharing) = parse_sharing(input)?;
113
114    Ok((
115        input,
116        Instruction::Declaration(Declaration {
117            name,
118            size,
119            sharing,
120        }),
121    ))
122}
123
124/// Parse the contents of a `CALL` instruction.
125///
126/// Note, the `CALL` instruction here is unresolved; it can only be resolved within the
127/// full context of a program from an [`crate::instruction::extern_call::ExternSignatureMap`].
128///
129/// Call instructions are of the form:
130///     `CALL @ms{Identifier} @rep[:min 1]{@group{@ms{Identifier} @alt @ms{Memory Reference} @alt @ms{Complex}}}`
131///
132/// For additional detail, see ["Call" in the Quil specification](https://github.com/quil-lang/quil/blob/7f532c7cdde9f51eae6abe7408cc868fba9f91f6/specgen/spec/sec-other.s).
133pub(crate) fn parse_call<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
134    let (input, name) = token!(Identifier(v))(input)?;
135
136    let (input, arguments) = many0(parse_call_argument)(input)?;
137    let call = Call { name, arguments };
138
139    Ok((input, Instruction::Call(call)))
140}
141
142fn parse_call_argument<'a>(
143    input: ParserInput<'a>,
144) -> InternalParserResult<'a, UnresolvedCallArgument> {
145    alt((
146        map(
147            parse_memory_reference_with_brackets,
148            UnresolvedCallArgument::MemoryReference,
149        ),
150        map(token!(Identifier(v)), UnresolvedCallArgument::Identifier),
151        map(
152            super::expression::parse_immediate_value,
153            UnresolvedCallArgument::Immediate,
154        ),
155    ))(input)
156}
157
158/// Parse the contents of a `CAPTURE` instruction.
159///
160/// Unlike most other instructions, this can be _prefixed_ with the NONBLOCKING keyword,
161/// and thus it expects and parses the CAPTURE token itself.
162pub(crate) fn parse_capture(
163    input: ParserInput,
164    blocking: bool,
165) -> InternalParserResult<Instruction> {
166    let (input, frame) = parse_frame_identifier(input)?;
167    let (input, waveform) = parse_waveform_invocation(input)?;
168    let (input, memory_reference) = parse_memory_reference(input)?;
169
170    Ok((
171        input,
172        Instruction::Capture(Capture {
173            blocking,
174            frame,
175            memory_reference,
176            waveform,
177        }),
178    ))
179}
180
181/// Parse the contents of a `CONVERT` instruction.
182pub(crate) fn parse_convert(input: ParserInput) -> InternalParserResult<Instruction> {
183    let (input, to) = parse_memory_reference(input)?;
184    let (input, from) = parse_memory_reference(input)?;
185    Ok((
186        input,
187        Instruction::Convert(Convert {
188            destination: to,
189            source: from,
190        }),
191    ))
192}
193
194/// Parse the contents of a `DEFCAL` instruction (including `DEFCAL MEASURE`),
195/// following the `DEFCAL` token.
196pub(crate) fn parse_defcal<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
197    use crate::parser::lexer::Command::Measure;
198    let (input, defcal_measure) = opt(token!(Command(Measure)))(input)?;
199    match defcal_measure {
200        Some(_) => parse_defcal_measure(input),
201        None => parse_defcal_gate(input),
202    }
203}
204
205/// Parse the contents of a `DEFCAL` instruction (but not `DEFCAL MEASURE`),
206/// following the `DEFCAL` token.
207pub(crate) fn parse_defcal_gate<'a>(
208    input: ParserInput<'a>,
209) -> InternalParserResult<'a, Instruction> {
210    let (input, modifiers) = many0(parse_gate_modifier)(input)?;
211    let (input, name) = token!(Identifier(v))(input)?;
212    let (input, parameters) = opt(delimited(
213        token!(LParenthesis),
214        separated_list0(token!(Comma), parse_expression),
215        token!(RParenthesis),
216    ))(input)?;
217    let parameters = parameters.unwrap_or_default();
218    let (input, qubits) = many0(parse_qubit)(input)?;
219    let (input, _) = token!(Colon)(input)?;
220    let (input, instructions) = parse_block(input)?;
221    Ok((
222        input,
223        Instruction::CalibrationDefinition(CalibrationDefinition {
224            identifier: CalibrationIdentifier {
225                name,
226                parameters,
227                qubits,
228                modifiers,
229            },
230            instructions,
231        }),
232    ))
233}
234
235/// Parse the contents of a `DEFCAL MEASURE` instruction, following the `MEASURE` token.
236pub(crate) fn parse_defcal_measure<'a>(
237    input: ParserInput<'a>,
238) -> InternalParserResult<'a, Instruction> {
239    let (input, name) = opt(preceded(token!(Bang), token!(Identifier(name))))(input)?;
240    let (input, qubit) = parse_qubit(input)?;
241    let (input, target) = opt(token!(Identifier(t)))(input)?;
242    let (input, _) = token!(Colon)(input)?;
243    let (input, instructions) = parse_block(input)?;
244    Ok((
245        input,
246        Instruction::MeasureCalibrationDefinition(MeasureCalibrationDefinition {
247            identifier: MeasureCalibrationIdentifier {
248                name,
249                qubit,
250                target,
251            },
252            instructions,
253        }),
254    ))
255}
256
257/// Parse the contents of a `DEFFRAME` instruction.
258pub(crate) fn parse_defframe<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
259    let (input, identifier) = parse_frame_identifier(input)?;
260    let (input, _) = token!(Colon)(input)?;
261    let (input, attribute_pairs) = many1(parse_frame_attribute)(input)?;
262    let attributes = attribute_pairs.into_iter().collect();
263
264    Ok((
265        input,
266        Instruction::FrameDefinition(FrameDefinition {
267            identifier,
268            attributes,
269        }),
270    ))
271}
272
273/// Parse the contents of a `DEFGATE` instruction.
274pub(crate) fn parse_defgate<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
275    let (input, name) = token!(Identifier(v))(input)?;
276    let (input, parameters) = opt(delimited(
277        token!(LParenthesis),
278        separated_list0(token!(Comma), token!(Variable(v))),
279        token!(RParenthesis),
280    ))(input)?;
281    let (input, mut arguments) = opt(many0(token!(Identifier(v))))(input)?;
282    let (input, gate_type) = opt(preceded(
283        token!(As),
284        alt((
285            map(token!(Matrix), |()| GateType::Matrix),
286            map(token!(Permutation), |()| GateType::Permutation),
287            map(token!(PauliSum), |()| GateType::PauliSum),
288            map(token!(Sequence), |()| GateType::Sequence),
289        )),
290    ))(input)?;
291
292    let (input, _) = token!(Colon)(input)?;
293
294    let gate_type = gate_type.unwrap_or(GateType::Matrix);
295    let (input, specification) = match gate_type {
296        GateType::Matrix => map(parse_matrix, GateSpecification::Matrix)(input)?,
297        GateType::Permutation => map(parse_permutation, GateSpecification::Permutation)(input)?,
298        GateType::PauliSum => map_res(parse_pauli_terms, |terms| {
299            Ok(GateSpecification::PauliSum(
300                PauliSum::new(arguments.take().unwrap_or_default(), terms)
301                    .map_err(ValidationError::from)
302                    .map_err(|e| InternalParseError::from_kind(input, ParserErrorKind::from(e)))?,
303            ))
304        })(input)?,
305        GateType::Sequence => map_res(parse_sequence_elements, |gates| {
306            let gate_sequence =
307                DefGateSequence::try_new(arguments.take().unwrap_or_default(), gates)
308                    .map_err(ValidationError::from)
309                    .map_err(ParserErrorKind::from)
310                    .map_err(|e| InternalParseError::from_kind(input, e))?;
311            Ok(GateSpecification::Sequence(gate_sequence))
312        })(input)?,
313    };
314
315    Ok((
316        input,
317        Instruction::GateDefinition(GateDefinition {
318            name,
319            parameters: parameters.unwrap_or_default(),
320            specification,
321        }),
322    ))
323}
324
325/// Parse the contents of a `DEFWAVEFORM` instruction.
326pub(crate) fn parse_defwaveform<'a>(
327    input: ParserInput<'a>,
328) -> InternalParserResult<'a, Instruction> {
329    let (input, name) = parse_waveform_name(input)?;
330    let (input, parameters) = opt(delimited(
331        token!(LParenthesis),
332        separated_list0(token!(Comma), token!(Variable(v))),
333        token!(RParenthesis),
334    ))(input)?;
335    let parameters = parameters.unwrap_or_default();
336
337    let (input, _) = tuple((token!(Colon), token!(NewLine), token!(Indentation)))(input)?;
338    let (input, matrix) = separated_list1(token!(Comma), parse_expression)(input)?;
339
340    Ok((
341        input,
342        Instruction::WaveformDefinition(WaveformDefinition {
343            name,
344            definition: Waveform { matrix, parameters },
345        }),
346    ))
347}
348
349pub(crate) fn parse_defcircuit<'a>(
350    input: ParserInput<'a>,
351) -> InternalParserResult<'a, Instruction> {
352    let (input, name) = token!(Identifier(v))(input)?;
353    let (input, parameters) = opt(delimited(
354        token!(LParenthesis),
355        separated_list0(token!(Comma), token!(Variable(v))),
356        token!(RParenthesis),
357    ))(input)?;
358    let parameters = parameters.unwrap_or_default();
359    let (input, qubit_variables) = many0(parse_variable_qubit)(input)?;
360    let (input, _) = token!(Colon)(input)?;
361    let (input, instructions) = parse_block(input)?;
362
363    Ok((
364        input,
365        Instruction::CircuitDefinition(CircuitDefinition {
366            name,
367            parameters,
368            qubit_variables,
369            instructions,
370        }),
371    ))
372}
373
374/// Parse the contents of a `DELAY` instruction.
375pub(crate) fn parse_delay<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
376    let (input, mut qubits) = many0(parse_qubit)(input)?;
377    let (input, frame_names) = many0(token!(String(v)))(input)?;
378    // If there is no intervening frame name and the delay is an integer, it will have been parsed
379    // as a qubit. We check for and correct that condition here.
380    let (input, duration) = parse_expression(input).or_else(|e| {
381        if let Some(Qubit::Fixed(index)) = qubits.last() {
382            let duration = *index as f64;
383            qubits.pop();
384            Ok((input, Expression::Number(real!(duration))))
385        } else {
386            Err(e)
387        }
388    })?;
389
390    Ok((
391        input,
392        Instruction::Delay(Delay {
393            duration,
394            frame_names,
395            qubits,
396        }),
397    ))
398}
399
400/// Parse the contents of an `EXCHANGE` instruction.
401pub(crate) fn parse_exchange(input: ParserInput) -> InternalParserResult<Instruction> {
402    let (input, left) = parse_memory_reference(input)?;
403    let (input, right) = parse_memory_reference(input)?;
404
405    Ok((input, Instruction::Exchange(Exchange { left, right })))
406}
407
408/// Parse the contents of a `FENCE` instruction.
409pub(crate) fn parse_fence(input: ParserInput) -> InternalParserResult<Instruction> {
410    let (input, qubits) = many0(parse_qubit)(input)?;
411
412    Ok((input, Instruction::Fence(Fence { qubits })))
413}
414
415/// Parse the contents of a `JUMP` instruction.
416pub(crate) fn parse_jump<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
417    let (input, target) = token!(Target(v))(input)?;
418    Ok((
419        input,
420        Instruction::Jump(Jump {
421            target: Target::Fixed(target),
422        }),
423    ))
424}
425
426/// Parse the contents of a `JUMP-WHEN` instruction.
427pub(crate) fn parse_jump_when<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
428    let (input, target) = token!(Target(v))(input)?;
429    let (input, condition) = parse_memory_reference(input)?;
430    Ok((
431        input,
432        Instruction::JumpWhen(JumpWhen {
433            target: Target::Fixed(target),
434            condition,
435        }),
436    ))
437}
438
439/// Parse the contents of a `JUMP-UNLESS` instruction.
440pub(crate) fn parse_jump_unless<'a>(
441    input: ParserInput<'a>,
442) -> InternalParserResult<'a, Instruction> {
443    let (input, target) = token!(Target(v))(input)?;
444    let (input, condition) = parse_memory_reference(input)?;
445    Ok((
446        input,
447        Instruction::JumpUnless(JumpUnless {
448            target: Target::Fixed(target),
449            condition,
450        }),
451    ))
452}
453
454/// Parse the contents of a `DECLARE` instruction.
455pub(crate) fn parse_label<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
456    let (input, name) = token!(Target(v))(input)?;
457    Ok((
458        input,
459        Instruction::Label(Label {
460            target: Target::Fixed(name),
461        }),
462    ))
463}
464
465/// Parse the contents of a `MOVE` instruction.
466pub(crate) fn parse_move(input: ParserInput) -> InternalParserResult<Instruction> {
467    let (input, destination) = parse_memory_reference(input)?;
468    let (input, source) = parse_arithmetic_operand(input)?;
469    Ok((
470        input,
471        Instruction::Move(Move {
472            destination,
473            source,
474        }),
475    ))
476}
477
478/// Parse the contents of a `LOAD` instruction.
479pub(crate) fn parse_load<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
480    let (input, destination) = parse_memory_reference(input)?;
481    let (input, source) = token!(Identifier(v))(input)?;
482    let (input, offset) = parse_memory_reference(input)?;
483
484    Ok((
485        input,
486        Instruction::Load(Load {
487            destination,
488            source,
489            offset,
490        }),
491    ))
492}
493
494/// Parse the contents of a `STORE` instruction.
495pub(crate) fn parse_store<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
496    let (input, destination) = token!(Identifier(v))(input)?;
497    let (input, offset) = parse_memory_reference(input)?;
498    let (input, source) = parse_arithmetic_operand(input)?;
499
500    Ok((
501        input,
502        Instruction::Store(Store {
503            destination,
504            offset,
505            source,
506        }),
507    ))
508}
509
510/// Parse the contents of a `PRAGMA` instruction.
511pub(crate) fn parse_pragma<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
512    let (input, pragma_type) = token!(Identifier(v))(input)?;
513    let (input, arguments) = many0(alt((
514        map(token!(Identifier(v)), PragmaArgument::Identifier),
515        map(token!(Integer(i)), PragmaArgument::Integer),
516    )))(input)?;
517    let (input, data) = opt(token!(String(v)))(input)?;
518    Ok((
519        input,
520        Instruction::Pragma(Pragma {
521            name: pragma_type,
522            arguments,
523            data,
524        }),
525    ))
526}
527
528/// Parse the contents of a `PULSE` instruction.
529pub(crate) fn parse_pulse(input: ParserInput, blocking: bool) -> InternalParserResult<Instruction> {
530    let (input, frame) = parse_frame_identifier(input)?;
531    let (input, waveform) = parse_waveform_invocation(input)?;
532
533    Ok((
534        input,
535        Instruction::Pulse(Pulse {
536            blocking,
537            frame,
538            waveform,
539        }),
540    ))
541}
542
543/// Parse the contents of a `RAW-CAPTURE` instruction.
544pub(crate) fn parse_raw_capture(
545    input: ParserInput,
546    blocking: bool,
547) -> InternalParserResult<Instruction> {
548    let (input, frame) = parse_frame_identifier(input)?;
549    let (input, duration) = parse_expression(input)?;
550    let (input, memory_reference) = parse_memory_reference(input)?;
551
552    Ok((
553        input,
554        Instruction::RawCapture(RawCapture {
555            blocking,
556            frame,
557            duration,
558            memory_reference,
559        }),
560    ))
561}
562
563/// Parse the contents of a `RESET` instruction.
564pub(crate) fn parse_reset(input: ParserInput) -> InternalParserResult<Instruction> {
565    let (input, qubit) = opt(parse_qubit)(input)?;
566
567    Ok((input, Instruction::Reset(Reset { qubit })))
568}
569
570/// Parse the contents of a `SET-FREQUENCY` instruction.
571pub(crate) fn parse_set_frequency(input: ParserInput) -> InternalParserResult<Instruction> {
572    let (input, frame) = parse_frame_identifier(input)?;
573    let (input, frequency) = parse_expression(input)?;
574
575    Ok((
576        input,
577        Instruction::SetFrequency(SetFrequency { frame, frequency }),
578    ))
579}
580
581/// Parse the contents of a `SET-PHASE` instruction.
582pub(crate) fn parse_set_phase(input: ParserInput) -> InternalParserResult<Instruction> {
583    let (input, frame) = parse_frame_identifier(input)?;
584    let (input, phase) = parse_expression(input)?;
585
586    Ok((input, Instruction::SetPhase(SetPhase { frame, phase })))
587}
588
589/// Parse the contents of a `SET-SCALE` instruction.
590pub(crate) fn parse_set_scale(input: ParserInput) -> InternalParserResult<Instruction> {
591    let (input, frame) = parse_frame_identifier(input)?;
592    let (input, scale) = parse_expression(input)?;
593
594    Ok((input, Instruction::SetScale(SetScale { frame, scale })))
595}
596
597/// Parse the contents of a `SHIFT-FREQUENCY` instruction.
598pub(crate) fn parse_shift_frequency(input: ParserInput) -> InternalParserResult<Instruction> {
599    let (input, frame) = parse_frame_identifier(input)?;
600    let (input, frequency) = parse_expression(input)?;
601
602    Ok((
603        input,
604        Instruction::ShiftFrequency(ShiftFrequency { frame, frequency }),
605    ))
606}
607
608/// Parse the contents of a `SHIFT-PHASE` instruction.
609pub(crate) fn parse_shift_phase(input: ParserInput) -> InternalParserResult<Instruction> {
610    let (input, frame) = parse_frame_identifier(input)?;
611    let (input, phase) = parse_expression(input)?;
612
613    Ok((input, Instruction::ShiftPhase(ShiftPhase { frame, phase })))
614}
615
616/// Parse the contents of a `SWAP-PHASES` instruction.
617pub(crate) fn parse_swap_phases(input: ParserInput) -> InternalParserResult<Instruction> {
618    let (input, frame_1) = parse_frame_identifier(input)?;
619    let (input, frame_2) = parse_frame_identifier(input)?;
620
621    Ok((
622        input,
623        Instruction::SwapPhases(SwapPhases { frame_1, frame_2 }),
624    ))
625}
626
627/// Parse the contents of a `MEASURE` instruction.
628pub(crate) fn parse_measurement<'a>(
629    input: ParserInput<'a>,
630) -> InternalParserResult<'a, Instruction> {
631    let (input, name) = opt(preceded(token!(Bang), token!(Identifier(name))))(input)?;
632    let (input, qubit) = parse_qubit(input)?;
633    let (input, target) = match parse_memory_reference(input) {
634        Ok((input, target)) => (input, Some(target)),
635        Err(_) => (input, None),
636    };
637
638    Ok((
639        input,
640        Instruction::Measurement(Measurement {
641            name,
642            qubit,
643            target,
644        }),
645    ))
646}
647
648/// Parse the contents of an `INCLUDE` instruction.
649pub(crate) fn parse_include<'a>(input: ParserInput<'a>) -> InternalParserResult<'a, Instruction> {
650    let (input, filename) = token!(String(v))(input)?;
651    Ok((input, Instruction::Include(Include { filename })))
652}
653
654#[cfg(test)]
655mod tests {
656    use crate::expression::{
657        Expression, ExpressionFunction, FunctionCallExpression, InfixExpression, InfixOperator,
658        PrefixExpression, PrefixOperator,
659    };
660    use crate::instruction::{
661        Call, DefGateSequence, DefGateSequenceError, GateDefinition, GateSpecification, Offset,
662        PauliGate, PauliSum, PauliTerm, PragmaArgument, Sharing, UnresolvedCallArgument,
663    };
664    use crate::parser::lexer::lex;
665    use crate::parser::Token;
666    use crate::{imag, real};
667    use crate::{
668        instruction::{
669            CircuitDefinition, Declaration, Gate, Instruction, Measurement, MemoryReference,
670            Pragma, Qubit, ScalarType, Vector,
671        },
672        make_test,
673    };
674    use internment::ArcIntern;
675    use num_complex::Complex64;
676    use rstest::*;
677
678    use super::{parse_declare, parse_defcircuit, parse_defgate, parse_measurement, parse_pragma};
679
680    make_test!(
681        declare_instruction_length_1,
682        parse_declare,
683        "ro BIT",
684        Instruction::Declaration(Declaration {
685            name: "ro".to_owned(),
686            size: Vector {
687                data_type: ScalarType::Bit,
688                length: 1
689            },
690            sharing: None,
691        })
692    );
693
694    make_test!(
695        declare_instruction_length_n,
696        parse_declare,
697        "ro INTEGER[5]",
698        Instruction::Declaration(Declaration {
699            name: "ro".to_owned(),
700            size: Vector {
701                data_type: ScalarType::Integer,
702                length: 5
703            },
704            sharing: None,
705        })
706    );
707
708    make_test!(
709        declare_instruction_sharing,
710        parse_declare,
711        "ro REAL[1] SHARING bar",
712        Instruction::Declaration(Declaration {
713            name: "ro".to_owned(),
714            size: Vector {
715                data_type: ScalarType::Real,
716                length: 1,
717            },
718            sharing: Some(Sharing {
719                name: "bar".to_string(),
720                offsets: vec![]
721            })
722        })
723    );
724
725    make_test!(
726        declare_instruction_sharing_offsets,
727        parse_declare,
728        "ro REAL[1] SHARING bar OFFSET 2 BIT 3 INTEGER",
729        Instruction::Declaration(Declaration {
730            name: "ro".to_owned(),
731            size: Vector {
732                data_type: ScalarType::Real,
733                length: 1,
734            },
735            sharing: Some(Sharing {
736                name: "bar".to_string(),
737                offsets: vec![
738                    Offset {
739                        offset: 2,
740                        data_type: ScalarType::Bit
741                    },
742                    Offset {
743                        offset: 3,
744                        data_type: ScalarType::Integer
745                    }
746                ],
747            })
748        })
749    );
750
751    make_test!(
752        measure_into_register,
753        parse_measurement,
754        "0 ro[0]",
755        Instruction::Measurement(Measurement {
756            name: None,
757            qubit: Qubit::Fixed(0),
758            target: Some(MemoryReference {
759                name: String::from("ro"),
760                index: 0
761            })
762        })
763    );
764
765    make_test!(
766        named_measure_into_register,
767        parse_measurement,
768        "!midcircuit 0 ro[0]",
769        Instruction::Measurement(Measurement {
770            name: Some(String::from("midcircuit")),
771            qubit: Qubit::Fixed(0),
772            target: Some(MemoryReference {
773                name: String::from("ro"),
774                index: 0
775            })
776        })
777    );
778
779    make_test!(
780        measure_discard,
781        parse_measurement,
782        "0",
783        Instruction::Measurement(Measurement {
784            name: None,
785            qubit: Qubit::Fixed(0),
786            target: None
787        })
788    );
789
790    make_test!(
791        named_measure_discard,
792        parse_measurement,
793        "!midcircuit 0",
794        Instruction::Measurement(Measurement {
795            name: Some(String::from("midcircuit")),
796            qubit: Qubit::Fixed(0),
797            target: None
798        })
799    );
800
801    make_test!(
802        measure_named_qubit,
803        parse_measurement,
804        "q0 ro[0]",
805        Instruction::Measurement(Measurement {
806            name: None,
807            qubit: Qubit::Variable(String::from("q0")),
808            target: Some(MemoryReference {
809                name: String::from("ro"),
810                index: 0
811            })
812        })
813    );
814
815    make_test!(
816        named_measure_named_qubit,
817        parse_measurement,
818        "!midcircuit q0 ro[0]",
819        Instruction::Measurement(Measurement {
820            name: Some(String::from("midcircuit")),
821            qubit: Qubit::Variable(String::from("q0")),
822            target: Some(MemoryReference {
823                name: String::from("ro"),
824                index: 0
825            })
826        })
827    );
828
829    make_test!(
830        measure_named_qubit_discard,
831        parse_measurement,
832        "q0",
833        Instruction::Measurement(Measurement {
834            name: None,
835            qubit: Qubit::Variable(String::from("q0")),
836            target: None
837        })
838    );
839
840    make_test!(
841        named_measure_named_qubit_discard,
842        parse_measurement,
843        "!midcircuit q0",
844        Instruction::Measurement(Measurement {
845            name: Some(String::from("midcircuit")),
846            qubit: Qubit::Variable(String::from("q0")),
847            target: None
848        })
849    );
850
851    make_test!(
852        pragma_inline_json_single_quotes,
853        parse_pragma,
854        "FILTER-NODE q35_unclassified \"{'module':'lodgepole.filters.io','filter_type':'DataBuffer','source':'q35_ro_rx/filter','publish':true,'params':{},'_type':'FilterNode'}\"",
855        Instruction::Pragma(Pragma {
856            name: "FILTER-NODE".to_owned(),
857            arguments: vec![PragmaArgument::Identifier("q35_unclassified".to_string())],
858            data: Some("{'module':'lodgepole.filters.io','filter_type':'DataBuffer','source':'q35_ro_rx/filter','publish':true,'params':{},'_type':'FilterNode'}".to_owned())
859        })
860    );
861
862    make_test!(
863        pragma_inline_json_double_quotes,
864        parse_pragma,
865        r#"FILTER-NODE q35_unclassified "{\"module\":\"lodgepole.filters.io\",\"filter_type\":\"DataBuffer\",\"source\":\"q35_ro_rx/filter\",\"publish\":true,\"params\":{},\"_type\":\"FilterNode\"}""#,
866        Instruction::Pragma(Pragma {
867            name: "FILTER-NODE".to_owned(),
868            arguments: vec![PragmaArgument::Identifier("q35_unclassified".to_string())],
869            data: Some(r#"{"module":"lodgepole.filters.io","filter_type":"DataBuffer","source":"q35_ro_rx/filter","publish":true,"params":{},"_type":"FilterNode"}"#.to_owned())
870        })
871    );
872
873    make_test!(
874        pragma_integer_argument,
875        parse_pragma,
876        "READOUT-POVM 0 \"(0.9 0.19999999999999996 0.09999999999999998 0.8)\"",
877        Instruction::Pragma(Pragma {
878            name: "READOUT-POVM".to_string(),
879            arguments: vec![PragmaArgument::Integer(0)],
880            data: Some("(0.9 0.19999999999999996 0.09999999999999998 0.8)".to_string()),
881        })
882    );
883
884    make_test!(
885        pragma_identifier_and_integer_argument,
886        parse_pragma,
887        "NAME identifier 0 \"data\"",
888        Instruction::Pragma(Pragma {
889            name: "NAME".to_string(),
890            arguments: vec![
891                PragmaArgument::Identifier("identifier".to_string()),
892                PragmaArgument::Integer(0)
893            ],
894            data: Some("data".to_string()),
895        })
896    );
897
898    make_test!(
899        defcircuit_no_params,
900        parse_defcircuit,
901        "BELL a b:
902    H a
903    CNOT a b",
904        Instruction::CircuitDefinition(CircuitDefinition {
905            name: "BELL".to_owned(),
906            parameters: vec![],
907            qubit_variables: vec!["a".to_owned(), "b".to_owned()],
908            instructions: vec![
909                Instruction::Gate(Gate {
910                    name: "H".to_owned(),
911                    parameters: vec![],
912                    qubits: vec![Qubit::Variable("a".to_owned())],
913                    modifiers: vec![],
914                }),
915                Instruction::Gate(Gate {
916                    name: "CNOT".to_owned(),
917                    parameters: vec![],
918                    qubits: vec![
919                        Qubit::Variable("a".to_owned()),
920                        Qubit::Variable("b".to_owned())
921                    ],
922                    modifiers: vec![],
923                })
924            ]
925        })
926    );
927
928    make_test!(
929        defcircuit_with_params,
930        parse_defcircuit,
931        "BELL(%a) a b:
932    RZ(%a) a
933    RX(%a) a
934    RZ(%a) a
935    CNOT a b",
936        Instruction::CircuitDefinition(CircuitDefinition {
937            name: "BELL".to_owned(),
938            parameters: vec!["a".to_owned()],
939            qubit_variables: vec!["a".to_owned(), "b".to_owned()],
940            instructions: vec![
941                Instruction::Gate(Gate {
942                    name: "RZ".to_owned(),
943                    parameters: vec![Expression::Variable("a".to_owned())],
944                    qubits: vec![Qubit::Variable("a".to_owned())],
945                    modifiers: vec![],
946                }),
947                Instruction::Gate(Gate {
948                    name: "RX".to_owned(),
949                    parameters: vec![Expression::Variable("a".to_owned())],
950                    qubits: vec![Qubit::Variable("a".to_owned())],
951                    modifiers: vec![],
952                }),
953                Instruction::Gate(Gate {
954                    name: "RZ".to_owned(),
955                    parameters: vec![Expression::Variable("a".to_owned())],
956                    qubits: vec![Qubit::Variable("a".to_owned())],
957                    modifiers: vec![],
958                }),
959                Instruction::Gate(Gate {
960                    name: "CNOT".to_owned(),
961                    parameters: vec![],
962                    qubits: vec![
963                        Qubit::Variable("a".to_owned()),
964                        Qubit::Variable("b".to_owned())
965                    ],
966                    modifiers: vec![],
967                })
968            ]
969        })
970    );
971
972    make_test!(
973        defgate,
974        parse_defgate,
975        r#"H:
976    1/sqrt(2), 1/sqrt(2)
977    1/sqrt(2), -1/sqrt(2)"#,
978        {
979            // 1/sqrt(2)
980            let expression = Expression::Infix(InfixExpression {
981                left: ArcIntern::new(Expression::Number(real!(1.0))),
982                operator: InfixOperator::Slash,
983                right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
984                    function: crate::expression::ExpressionFunction::SquareRoot,
985                    expression: ArcIntern::new(Expression::Number(real!(2.0))),
986                })),
987            });
988
989            // -1/sqrt(2)
990            let negative_expression = Expression::Infix(InfixExpression {
991                left: ArcIntern::new(Expression::Prefix(PrefixExpression {
992                    operator: PrefixOperator::Minus,
993                    expression: ArcIntern::new(Expression::Number(real!(1.0))),
994                })),
995                operator: InfixOperator::Slash,
996                right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
997                    function: crate::expression::ExpressionFunction::SquareRoot,
998                    expression: ArcIntern::new(Expression::Number(real!(2.0))),
999                })),
1000            });
1001
1002            Instruction::GateDefinition(GateDefinition {
1003                name: "H".to_string(),
1004                parameters: vec![],
1005                specification: GateSpecification::Matrix(vec![
1006                    vec![expression.clone(), expression.clone()],
1007                    vec![expression, negative_expression],
1008                ]),
1009            })
1010        }
1011    );
1012
1013    make_test!(
1014        defgate_parameterized,
1015        parse_defgate,
1016        r#"RX(%theta):
1017    cos(%theta/2), -i*sin(%theta/2)
1018    -i*sin(%theta/2), cos(%theta/2)"#,
1019        Instruction::GateDefinition(GateDefinition {
1020            name: "RX".to_string(),
1021            parameters: vec!["theta".to_string()],
1022            specification: GateSpecification::Matrix(vec![
1023                vec![
1024                    Expression::FunctionCall(FunctionCallExpression {
1025                        function: crate::expression::ExpressionFunction::Cosine,
1026                        expression: ArcIntern::new(Expression::Infix(InfixExpression {
1027                            left: ArcIntern::new(Expression::Variable("theta".to_string())),
1028                            operator: InfixOperator::Slash,
1029                            right: ArcIntern::new(Expression::Number(real!(2.0))),
1030                        })),
1031                    }),
1032                    Expression::Infix(InfixExpression {
1033                        left: ArcIntern::new(Expression::Prefix(PrefixExpression {
1034                            operator: PrefixOperator::Minus,
1035                            expression: ArcIntern::new(Expression::Number(imag!(1f64)))
1036                        })),
1037                        operator: InfixOperator::Star,
1038                        right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
1039                            function: ExpressionFunction::Sine,
1040                            expression: ArcIntern::new(Expression::Infix(InfixExpression {
1041                                left: ArcIntern::new(Expression::Variable("theta".to_string())),
1042                                operator: InfixOperator::Slash,
1043                                right: ArcIntern::new(Expression::Number(real!(2.0))),
1044                            })),
1045                        })),
1046                    })
1047                ],
1048                vec![
1049                    Expression::Infix(InfixExpression {
1050                        left: ArcIntern::new(Expression::Prefix(PrefixExpression {
1051                            operator: PrefixOperator::Minus,
1052                            expression: ArcIntern::new(Expression::Number(imag!(1f64)))
1053                        })),
1054                        operator: InfixOperator::Star,
1055                        right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
1056                            function: ExpressionFunction::Sine,
1057                            expression: ArcIntern::new(Expression::Infix(InfixExpression {
1058                                left: ArcIntern::new(Expression::Variable("theta".to_string())),
1059                                operator: InfixOperator::Slash,
1060                                right: ArcIntern::new(Expression::Number(real!(2.0))),
1061                            })),
1062                        })),
1063                    }),
1064                    Expression::FunctionCall(FunctionCallExpression {
1065                        function: crate::expression::ExpressionFunction::Cosine,
1066                        expression: ArcIntern::new(Expression::Infix(InfixExpression {
1067                            left: ArcIntern::new(Expression::Variable("theta".to_string())),
1068                            operator: InfixOperator::Slash,
1069                            right: ArcIntern::new(Expression::Number(real!(2.0))),
1070                        })),
1071                    }),
1072                ],
1073            ]),
1074        })
1075    );
1076
1077    make_test!(
1078        defgate_permutation,
1079        parse_defgate,
1080        r#"CCNOT AS PERMUTATION:
1081    0, 1, 2, 3, 4, 5, 7, 6"#,
1082        Instruction::GateDefinition(GateDefinition {
1083            name: "CCNOT".to_string(),
1084            parameters: vec![],
1085            specification: GateSpecification::Permutation(vec![0, 1, 2, 3, 4, 5, 7, 6]),
1086        })
1087    );
1088
1089    make_test!(
1090        defgate_pauli_sum,
1091        parse_defgate,
1092        r#"PauliSumGate(%theta) p q AS PAULI-SUM:
1093    ZZ((-%theta)/4) p q
1094    Y(%theta/4) p
1095    X(%theta/4) q"#,
1096        Instruction::GateDefinition(GateDefinition {
1097            name: "PauliSumGate".to_string(),
1098            parameters: vec!["theta".to_string()],
1099            specification: GateSpecification::PauliSum(PauliSum {
1100                arguments: vec!["p".to_string(), "q".to_string()],
1101                terms: vec![
1102                    PauliTerm {
1103                        arguments: vec![
1104                            (PauliGate::Z, "p".to_string()),
1105                            (PauliGate::Z, "q".to_string())
1106                        ],
1107                        expression: Expression::Infix(InfixExpression {
1108                            left: ArcIntern::new(Expression::Prefix(PrefixExpression {
1109                                operator: PrefixOperator::Minus,
1110                                expression: ArcIntern::new(Expression::Variable(
1111                                    "theta".to_string()
1112                                ))
1113                            })),
1114                            operator: InfixOperator::Slash,
1115                            right: ArcIntern::new(Expression::Number(real!(4.0)))
1116                        }),
1117                    },
1118                    PauliTerm {
1119                        arguments: vec![(PauliGate::Y, "p".to_string())],
1120                        expression: Expression::Infix(InfixExpression {
1121                            left: ArcIntern::new(Expression::Variable("theta".to_string())),
1122                            operator: InfixOperator::Slash,
1123                            right: ArcIntern::new(Expression::Number(real!(4.0)))
1124                        }),
1125                    },
1126                    PauliTerm {
1127                        arguments: vec![(PauliGate::X, "q".to_string())],
1128                        expression: Expression::Infix(InfixExpression {
1129                            left: ArcIntern::new(Expression::Variable("theta".to_string())),
1130                            operator: InfixOperator::Slash,
1131                            right: ArcIntern::new(Expression::Number(real!(4.0)))
1132                        }),
1133                    },
1134                ]
1135            })
1136        })
1137    );
1138
1139    /// Test case for parsing a `CALL` instruction.
1140    struct ParseCallTestCase {
1141        /// The input to parse.
1142        input: &'static str,
1143        /// The remaining tokens after parsing.
1144        remainder: Vec<Token>,
1145        /// The expected result.
1146        expected: Result<Call, String>,
1147    }
1148
1149    impl ParseCallTestCase {
1150        /// Basic call with arguments.
1151        fn case_01() -> Self {
1152            Self {
1153                input: "foo integer[0] 1.0 bar",
1154                remainder: vec![],
1155                expected: Ok(Call {
1156                    name: "foo".to_string(),
1157                    arguments: vec![
1158                        UnresolvedCallArgument::MemoryReference(MemoryReference {
1159                            name: "integer".to_string(),
1160                            index: 0,
1161                        }),
1162                        UnresolvedCallArgument::Immediate(real!(1.0)),
1163                        UnresolvedCallArgument::Identifier("bar".to_string()),
1164                    ],
1165                }),
1166            }
1167        }
1168
1169        /// No arguments does in fact parse.
1170        fn case_02() -> Self {
1171            Self {
1172                input: "foo",
1173                remainder: vec![],
1174                expected: Ok(Call {
1175                    name: "foo".to_string(),
1176                    arguments: vec![],
1177                }),
1178            }
1179        }
1180
1181        /// Invalid identifier.
1182        fn case_03() -> Self {
1183            Self {
1184                input: "INCLUDE",
1185                remainder: vec![],
1186                expected: Err(
1187                    "ExpectedToken { actual: COMMAND(INCLUDE), expected: \"Identifier\" }"
1188                        .to_string(),
1189                ),
1190            }
1191        }
1192
1193        /// Valid with leftover
1194        fn case_04() -> Self {
1195            Self {
1196                input: "foo integer[0] 1.0 bar; baz",
1197                remainder: vec![Token::Semicolon, Token::Identifier("baz".to_string())],
1198                expected: Ok(Call {
1199                    name: "foo".to_string(),
1200                    arguments: vec![
1201                        UnresolvedCallArgument::MemoryReference(MemoryReference {
1202                            name: "integer".to_string(),
1203                            index: 0,
1204                        }),
1205                        UnresolvedCallArgument::Immediate(real!(1.0)),
1206                        UnresolvedCallArgument::Identifier("bar".to_string()),
1207                    ],
1208                }),
1209            }
1210        }
1211    }
1212
1213    /// Test that the `parse_call` function works as expected.
1214    #[rstest]
1215    #[case(ParseCallTestCase::case_01())]
1216    #[case(ParseCallTestCase::case_02())]
1217    #[case(ParseCallTestCase::case_03())]
1218    #[case(ParseCallTestCase::case_04())]
1219    fn test_parse_call(#[case] test_case: ParseCallTestCase) {
1220        let input = ::nom_locate::LocatedSpan::new(test_case.input);
1221        let tokens = lex(input).unwrap();
1222        match (test_case.expected, super::parse_call(&tokens)) {
1223            (Ok(expected), Ok((remainder, parsed))) => {
1224                assert_eq!(parsed, Instruction::Call(expected));
1225                let remainder: Vec<_> = remainder.iter().map(|t| t.as_token().clone()).collect();
1226                assert_eq!(remainder, test_case.remainder);
1227            }
1228            (Ok(expected), Err(e)) => {
1229                panic!("Expected {expected:?}, got error: {e:?}");
1230            }
1231            (Err(expected), Ok((_, parsed))) => {
1232                panic!("Expected error: {expected:?}, got {parsed:?}");
1233            }
1234            (Err(expected), Err(found)) => {
1235                let found = format!("{found:?}");
1236                assert!(found.contains(&expected), "`{expected}` not in `{found}`");
1237            }
1238        }
1239    }
1240
1241    struct ParseGateDefinitionTestCase {
1242        /// The input to parse.
1243        input: &'static str,
1244        /// The remaining tokens after parsing.
1245        remainder: Vec<Token>,
1246        /// The expected result.
1247        expected: Result<GateDefinition, String>,
1248    }
1249
1250    impl ParseGateDefinitionTestCase {
1251        fn simple_sequence() -> Self {
1252            const SIMPLE_SEQUENCE: &str = r"seq1(%param01) q1 AS SEQUENCE:
1253    RX(%param01) q1";
1254            let gate1 = Gate::new(
1255                "RX",
1256                vec![Expression::Variable("param01".to_string())],
1257                vec![Qubit::Variable("q1".to_string())],
1258                vec![],
1259            )
1260            .expect("must be valid gate");
1261            let gate_sequence = DefGateSequence::try_new(vec!["q1".to_string()], vec![gate1])
1262                .expect("must be valid sequence");
1263            Self {
1264                input: SIMPLE_SEQUENCE,
1265                remainder: vec![],
1266                expected: Ok(GateDefinition {
1267                    name: "seq1".to_string(),
1268                    parameters: vec!["param01".to_string()],
1269                    specification: GateSpecification::Sequence(gate_sequence),
1270                }),
1271            }
1272        }
1273
1274        fn simple_2q() -> Self {
1275            const SIMPLE_2Q: &str = r"seq1(%param01, %param02) q1 q2 AS SEQUENCE:
1276    RX(%param01) q1
1277    RX(%param02) q2";
1278            let gate1 = Gate::new(
1279                "RX",
1280                vec![Expression::Variable("param01".to_string())],
1281                vec![Qubit::Variable("q1".to_string())],
1282                vec![],
1283            )
1284            .expect("must be valid gate");
1285            let gate2 = Gate::new(
1286                "RX",
1287                vec![Expression::Variable("param02".to_string())],
1288                vec![Qubit::Variable("q2".to_string())],
1289                vec![],
1290            )
1291            .expect("must be valid gate");
1292            let gate_sequence = DefGateSequence::try_new(
1293                vec!["q1".to_string(), "q2".to_string()],
1294                vec![gate1, gate2],
1295            )
1296            .expect("must be valid sequence");
1297            Self {
1298                input: SIMPLE_2Q,
1299                remainder: vec![],
1300                expected: Ok(GateDefinition {
1301                    name: "seq1".to_string(),
1302                    parameters: vec!["param01".to_string(), "param02".to_string()],
1303                    specification: GateSpecification::Sequence(gate_sequence),
1304                }),
1305            }
1306        }
1307
1308        fn no_parameters() -> Self {
1309            const NO_PARAMETERS: &str = r"seq1() q1 AS SEQUENCE:
1310    RX(pi/2) q1";
1311            let gate1 = Gate::new(
1312                "RX",
1313                vec![Expression::Infix(InfixExpression {
1314                    left: ArcIntern::new(Expression::PiConstant()),
1315                    operator: InfixOperator::Slash,
1316                    right: ArcIntern::new(Expression::Number(Complex64 { re: 2.0, im: 0.0 })),
1317                })],
1318                vec![Qubit::Variable("q1".to_string())],
1319                vec![],
1320            )
1321            .expect("must be valid gate");
1322            let gate_sequence = DefGateSequence::try_new(vec!["q1".to_string()], vec![gate1])
1323                .expect("must be valid sequence");
1324            Self {
1325                input: NO_PARAMETERS,
1326                remainder: vec![],
1327                expected: Ok(GateDefinition {
1328                    name: "seq1".to_string(),
1329                    parameters: vec![],
1330                    specification: GateSpecification::Sequence(gate_sequence),
1331                }),
1332            }
1333        }
1334
1335        fn no_parentheses() -> Self {
1336            const NO_PARENTHESES: &str = r"seq1 q1 AS SEQUENCE:
1337    RX(pi/2) q1";
1338            let gate1 = Gate::new(
1339                "RX",
1340                vec![Expression::Infix(InfixExpression {
1341                    left: ArcIntern::new(Expression::PiConstant()),
1342                    operator: InfixOperator::Slash,
1343                    right: ArcIntern::new(Expression::Number(Complex64 { re: 2.0, im: 0.0 })),
1344                })],
1345                vec![Qubit::Variable("q1".to_string())],
1346                vec![],
1347            )
1348            .expect("must be valid gate");
1349            let gate_sequence = DefGateSequence::try_new(vec!["q1".to_string()], vec![gate1])
1350                .expect("must be valid sequence");
1351            Self {
1352                input: NO_PARENTHESES,
1353                remainder: vec![],
1354                expected: Ok(GateDefinition {
1355                    name: "seq1".to_string(),
1356                    parameters: vec![],
1357                    specification: GateSpecification::Sequence(gate_sequence),
1358                }),
1359            }
1360        }
1361
1362        fn unused_argument() -> Self {
1363            const NO_PARAMETERS: &str = r"seq1(%param01) q1 q2 AS SEQUENCE:
1364    RX(pi/2) q1";
1365            let gate1 = Gate::new(
1366                "RX",
1367                vec![Expression::Infix(InfixExpression {
1368                    left: ArcIntern::new(Expression::PiConstant()),
1369                    operator: InfixOperator::Slash,
1370                    right: ArcIntern::new(Expression::Number(Complex64 { re: 2.0, im: 0.0 })),
1371                })],
1372                vec![Qubit::Variable("q1".to_string())],
1373                vec![],
1374            )
1375            .expect("must be valid gate");
1376            let gate_sequence =
1377                DefGateSequence::try_new(vec!["q1".to_string(), "q2".to_string()], vec![gate1])
1378                    .expect("must be valid sequence");
1379            Self {
1380                input: NO_PARAMETERS,
1381                remainder: vec![],
1382                expected: Ok(GateDefinition {
1383                    name: "seq1".to_string(),
1384                    parameters: vec!["param01".to_string()],
1385                    specification: GateSpecification::Sequence(gate_sequence),
1386                }),
1387            }
1388        }
1389
1390        fn error_undefined_gate_sequence_element_qubit() -> Self {
1391            const UNDEFINED_QUBIT: &str = r"seq1(%param01) q1 AS SEQUENCE:
1392    RZ(%param01) q1
1393    ISWAP q1 doesnt_exist_qubit";
1394            Self {
1395                input: UNDEFINED_QUBIT,
1396                remainder: vec![],
1397                expected: Err(format!(
1398                    "{:?}",
1399                    DefGateSequenceError::UndefinedGateSequenceElementQubit {
1400                        gate_index: 1,
1401                        qubit_argument_index: 1,
1402                        argument_name: "doesnt_exist_qubit".to_string(),
1403                    }
1404                )),
1405            }
1406        }
1407
1408        fn error_invalid_gate_sequence_element_qubit() -> Self {
1409            const INVALID_QUBIT: &str = r"seq1(%param01) q1 AS SEQUENCE:
1410    RZ(%param01) q1
1411    ISWAP q1 3";
1412            Self {
1413                input: INVALID_QUBIT,
1414                remainder: vec![],
1415                expected: Err(format!(
1416                    "{:?}",
1417                    DefGateSequenceError::InvalidGateSequenceElementQubit {
1418                        gate_index: 1,
1419                        qubit_argument_index: 1,
1420                        qubit: Qubit::Fixed(3)
1421                    }
1422                )),
1423            }
1424        }
1425
1426        fn error_at_least_one_qubit() -> Self {
1427            const AT_LEAST_ONE_QUBIT: &str = r"seq1() AS SEQUENCE:
1428    RX(pi/2) q1";
1429            Self {
1430                input: AT_LEAST_ONE_QUBIT,
1431                remainder: vec![],
1432                expected: Err(format!(
1433                    "{:?}",
1434                    DefGateSequenceError::AtLeastOneQubitParameterRequired
1435                )),
1436            }
1437        }
1438    }
1439
1440    #[rstest]
1441    #[case::simple_sequence(ParseGateDefinitionTestCase::simple_sequence())]
1442    #[case::simple_2q(ParseGateDefinitionTestCase::simple_2q())]
1443    #[case::no_parameters(ParseGateDefinitionTestCase::no_parameters())]
1444    #[case::no_parentheses(ParseGateDefinitionTestCase::no_parentheses())]
1445    #[case::unused_argument(ParseGateDefinitionTestCase::unused_argument())]
1446    #[case::error_undefined_gate_sequence_element_qubit(
1447        ParseGateDefinitionTestCase::error_undefined_gate_sequence_element_qubit()
1448    )]
1449    #[case::error_invalid_gate_sequence_element_qubit(
1450        ParseGateDefinitionTestCase::error_invalid_gate_sequence_element_qubit()
1451    )]
1452    #[case::error_at_least_one_qubit(ParseGateDefinitionTestCase::error_at_least_one_qubit())]
1453    fn test_parse_gate_definition(#[case] test_case: ParseGateDefinitionTestCase) {
1454        let input = ::nom_locate::LocatedSpan::new(test_case.input);
1455        let tokens = lex(input).unwrap();
1456        match (test_case.expected, super::parse_defgate(&tokens)) {
1457            (Ok(expected), Ok((remainder, parsed))) => {
1458                assert_eq!(parsed, Instruction::GateDefinition(expected));
1459                let remainder: Vec<_> = remainder.iter().map(|t| t.as_token().clone()).collect();
1460                assert_eq!(remainder, test_case.remainder);
1461            }
1462            (Ok(expected), Err(e)) => {
1463                panic!("Expected {expected:?}, got error: {e:?}");
1464            }
1465            (Err(expected), Ok((_, parsed))) => {
1466                panic!("Expected error: {expected:?}, got {parsed:?}");
1467            }
1468            (Err(expected), Err(found)) => {
1469                let found = format!("{found:?}");
1470                assert!(found.contains(&expected), "`{expected}` not in `{found}`");
1471            }
1472        }
1473    }
1474}