Skip to main content

q_rust/parser/
rules.rs

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
12// --- Helpers ---
13
14fn 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
43// --- QASM Parsers ---
44
45pub 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}