1use super::ast::ParsedStatement;
2use nom::{
3 IResult,
4 branch::alt,
5 bytes::complete::{tag, take_while, take_while1},
6 character::complete::{alpha1, alphanumeric1, char, digit1, space0, space1},
7 combinator::{map, map_res, opt, recognize, value},
8 multi::{many0, separated_list0},
9 sequence::{delimited, pair, tuple},
10};
11
12fn identifier(input: &str) -> IResult<&str, String> {
15 map(
16 recognize(pair(
17 alt((alpha1, tag("_"))),
18 many0(alt((alphanumeric1, tag("_")))),
19 )),
20 |s: &str| s.to_string(),
21 )(input)
22}
23
24fn usize_parser(input: &str) -> IResult<&str, usize> {
25 map_res(digit1, |s: &str| s.parse::<usize>())(input)
26}
27
28fn float_parser(input: &str) -> IResult<&str, f64> {
29 map_res(
30 recognize(tuple((
31 opt(tag("-")),
32 digit1,
33 opt(tuple((tag("."), digit1))),
34 ))),
35 |s: &str| s.parse::<f64>(),
36 )(input)
37}
38
39pub fn comment(input: &str) -> IResult<&str, ()> {
40 value((), pair(tag("//"), take_while(|c| c != '\n')))(input)
41}
42
43pub fn openqasm_version(input: &str) -> IResult<&str, String> {
46 map(
47 tuple((
48 tag("OPENQASM"),
49 space1,
50 take_while1(|c: char| c != ';'),
51 tag(";"),
52 )),
53 |(_, _, version, _): (&str, &str, &str, &str)| version.to_string(),
54 )(input)
55}
56
57pub fn include(input: &str) -> IResult<&str, ParsedStatement> {
58 value(
59 ParsedStatement::Ignore,
60 tuple((
61 tag("include"),
62 space1,
63 delimited(char('"'), take_while1(|c| c != '"'), char('"')),
64 tag(";"),
65 )),
66 )(input)
67}
68
69pub fn qreg(input: &str) -> IResult<&str, ParsedStatement> {
70 map(
71 tuple((
72 tag("qreg"),
73 space1,
74 identifier,
75 delimited(char('['), usize_parser, char(']')),
76 tag(";"),
77 )),
78 |(_, _, name, size, _)| ParsedStatement::QReg(name, size),
79 )(input)
80}
81
82pub fn creg(input: &str) -> IResult<&str, ParsedStatement> {
83 map(
84 tuple((
85 tag("creg"),
86 space1,
87 identifier,
88 delimited(char('['), usize_parser, char(']')),
89 tag(";"),
90 )),
91 |(_, _, name, size, _)| ParsedStatement::CReg(name, size),
92 )(input)
93}
94
95fn qubit_ref(input: &str) -> IResult<&str, (String, usize)> {
96 pair(identifier, delimited(char('['), usize_parser, char(']')))(input)
97}
98
99pub fn gate_call(input: &str) -> IResult<&str, ParsedStatement> {
100 let (input, name) = identifier(input)?;
101 let (input, params) = opt(delimited(
102 char('('),
103 separated_list0(tuple((space0, char(','), space0)), float_parser),
104 char(')'),
105 ))(input)?;
106 let (input, _) = space1(input)?;
107 let (input, qubits) = separated_list0(tuple((space0, char(','), space0)), qubit_ref)(input)?;
108 let (input, _) = tag(";")(input)?;
109
110 Ok((
111 input,
112 ParsedStatement::Gate(name, qubits, params.unwrap_or_default()),
113 ))
114}
115
116pub fn measure(input: &str) -> IResult<&str, ParsedStatement> {
117 map(
118 tuple((
119 tag("measure"),
120 space1,
121 qubit_ref,
122 space0,
123 tag("->"),
124 space0,
125 qubit_ref,
126 tag(";"),
127 )),
128 |(_, _, q, _, _, _, c, _)| ParsedStatement::Measure(q, c),
129 )(input)
130}