1use super::ast::{
4 BinaryOp, ClassicalRef, ComparisonOp, Condition, Declaration, Expression, ForLoop,
5 GateDefinition, Literal, Measurement, QasmGate, QasmProgram, QasmRegister, QasmStatement,
6 QubitRef, UnaryOp,
7};
8use std::collections::HashMap;
9use std::str::FromStr;
10use thiserror::Error;
11
12#[derive(Debug, Error)]
14pub enum ParseError {
15 #[error("Unexpected token: {0}")]
16 UnexpectedToken(String),
17
18 #[error("Expected {expected}, found {found}")]
19 ExpectedToken { expected: String, found: String },
20
21 #[error("Invalid syntax: {0}")]
22 InvalidSyntax(String),
23
24 #[error("Undefined identifier: {0}")]
25 UndefinedIdentifier(String),
26
27 #[error("Type mismatch: {0}")]
28 TypeMismatch(String),
29
30 #[error("Invalid number: {0}")]
31 InvalidNumber(String),
32
33 #[error("Unexpected end of input")]
34 UnexpectedEof,
35
36 #[error("Version mismatch: expected 3.0, found {0}")]
37 VersionMismatch(String),
38}
39
40#[derive(Debug, Clone, PartialEq)]
42enum Token {
43 OpenQasm,
45 Include,
46 Qubit,
47 Bit,
48 Gate,
49 Measure,
50 Reset,
51 Barrier,
52 If,
53 Else,
54 For,
55 While,
56 In,
57 Const,
58 Def,
59 Return,
60 Delay,
61 Ctrl,
62 Inv,
63 Pow,
64
65 Identifier(String),
67 Integer(i64),
68 Float(f64),
69 String(String),
70
71 Plus,
73 Minus,
74 Star,
75 Slash,
76 Percent,
77 Power,
78 Assign,
79 Eq,
80 Ne,
81 Lt,
82 Le,
83 Gt,
84 Ge,
85 And,
86 Or,
87 Not,
88 BitAnd,
89 BitOr,
90 BitXor,
91 BitNot,
92 Shl,
93 Shr,
94 Arrow,
95
96 LeftParen,
98 RightParen,
99 LeftBracket,
100 RightBracket,
101 LeftBrace,
102 RightBrace,
103 Semicolon,
104 Comma,
105 Colon,
106 Dot,
107
108 Eof,
110}
111
112struct Lexer<'a> {
114 input: &'a str,
115 position: usize,
116 current: Option<char>,
117}
118
119impl<'a> Lexer<'a> {
120 fn new(input: &'a str) -> Self {
121 let mut lexer = Lexer {
122 input,
123 position: 0,
124 current: None,
125 };
126 lexer.advance();
127 lexer
128 }
129
130 fn advance(&mut self) {
131 self.current = self.input.chars().nth(self.position);
132 if self.current.is_some() {
133 self.position += 1;
134 }
135 }
136
137 fn peek(&self) -> Option<char> {
138 self.input.chars().nth(self.position)
139 }
140
141 fn skip_whitespace(&mut self) {
142 while let Some(ch) = self.current {
143 if ch.is_whitespace() {
144 self.advance();
145 } else if ch == '/' && self.peek() == Some('/') {
146 while self.current.is_some() && self.current != Some('\n') {
148 self.advance();
149 }
150 } else if ch == '/' && self.peek() == Some('*') {
151 self.advance(); self.advance(); while self.current.is_some() {
155 if self.current == Some('*') && self.peek() == Some('/') {
156 self.advance(); self.advance(); break;
159 }
160 self.advance();
161 }
162 } else {
163 break;
164 }
165 }
166 }
167
168 fn read_identifier(&mut self) -> String {
169 let mut result = String::new();
170 while let Some(ch) = self.current {
171 if ch.is_alphanumeric() || ch == '_' {
172 result.push(ch);
173 self.advance();
174 } else {
175 break;
176 }
177 }
178 result
179 }
180
181 fn read_number(&mut self) -> Result<Token, ParseError> {
182 let mut result = String::new();
183 let mut has_dot = false;
184
185 while let Some(ch) = self.current {
186 if ch.is_numeric() {
187 result.push(ch);
188 self.advance();
189 } else if ch == '.' && !has_dot && self.peek().is_some_and(char::is_numeric) {
190 has_dot = true;
191 result.push(ch);
192 self.advance();
193 } else if ch == 'e' || ch == 'E' {
194 result.push(ch);
195 self.advance();
196 if let Some(sign_ch) = self.current {
197 if sign_ch == '+' || sign_ch == '-' {
198 result.push(sign_ch);
199 self.advance();
200 }
201 }
202 } else {
203 break;
204 }
205 }
206
207 if has_dot || result.contains('e') || result.contains('E') {
208 result
209 .parse::<f64>()
210 .map(Token::Float)
211 .map_err(|_| ParseError::InvalidNumber(result))
212 } else {
213 result
214 .parse::<i64>()
215 .map(Token::Integer)
216 .map_err(|_| ParseError::InvalidNumber(result))
217 }
218 }
219
220 fn read_string(&mut self) -> Result<String, ParseError> {
221 let mut result = String::new();
222 self.advance(); while let Some(ch) = self.current {
225 if ch == '"' {
226 self.advance(); return Ok(result);
228 } else if ch == '\\' {
229 self.advance();
230 match self.current {
231 Some('n') => result.push('\n'),
232 Some('t') => result.push('\t'),
233 Some('r') => result.push('\r'),
234 Some('\\') => result.push('\\'),
235 Some('"') => result.push('"'),
236 _ => return Err(ParseError::InvalidSyntax("Invalid escape sequence".into())),
237 }
238 self.advance();
239 } else {
240 result.push(ch);
241 self.advance();
242 }
243 }
244
245 Err(ParseError::UnexpectedEof)
246 }
247
248 fn next_token(&mut self) -> Result<Token, ParseError> {
249 self.skip_whitespace();
250
251 match self.current {
252 None => Ok(Token::Eof),
253 Some(ch) => match ch {
254 '+' => {
255 self.advance();
256 Ok(Token::Plus)
257 }
258 '*' => {
259 self.advance();
260 if self.current == Some('*') {
261 self.advance();
262 Ok(Token::Power)
263 } else {
264 Ok(Token::Star)
265 }
266 }
267 '/' => {
268 self.advance();
269 Ok(Token::Slash)
270 }
271 '%' => {
272 self.advance();
273 Ok(Token::Percent)
274 }
275 '(' => {
276 self.advance();
277 Ok(Token::LeftParen)
278 }
279 ')' => {
280 self.advance();
281 Ok(Token::RightParen)
282 }
283 '[' => {
284 self.advance();
285 Ok(Token::LeftBracket)
286 }
287 ']' => {
288 self.advance();
289 Ok(Token::RightBracket)
290 }
291 '{' => {
292 self.advance();
293 Ok(Token::LeftBrace)
294 }
295 '}' => {
296 self.advance();
297 Ok(Token::RightBrace)
298 }
299 ';' => {
300 self.advance();
301 Ok(Token::Semicolon)
302 }
303 ',' => {
304 self.advance();
305 Ok(Token::Comma)
306 }
307 ':' => {
308 self.advance();
309 Ok(Token::Colon)
310 }
311 '.' => {
312 self.advance();
313 Ok(Token::Dot)
314 }
315 '~' => {
316 self.advance();
317 Ok(Token::BitNot)
318 }
319 '"' => self.read_string().map(Token::String),
320 '-' => {
321 self.advance();
322 if self.current == Some('>') {
323 self.advance();
324 Ok(Token::Arrow)
325 } else {
326 Ok(Token::Minus)
327 }
328 }
329 '=' => {
330 self.advance();
331 if self.current == Some('=') {
332 self.advance();
333 Ok(Token::Eq)
334 } else {
335 Ok(Token::Assign)
336 }
337 }
338 '!' => {
339 self.advance();
340 if self.current == Some('=') {
341 self.advance();
342 Ok(Token::Ne)
343 } else {
344 Ok(Token::Not)
345 }
346 }
347 '<' => {
348 self.advance();
349 match self.current {
350 Some('=') => {
351 self.advance();
352 Ok(Token::Le)
353 }
354 Some('<') => {
355 self.advance();
356 Ok(Token::Shl)
357 }
358 _ => Ok(Token::Lt),
359 }
360 }
361 '>' => {
362 self.advance();
363 match self.current {
364 Some('=') => {
365 self.advance();
366 Ok(Token::Ge)
367 }
368 Some('>') => {
369 self.advance();
370 Ok(Token::Shr)
371 }
372 _ => Ok(Token::Gt),
373 }
374 }
375 '&' => {
376 self.advance();
377 if self.current == Some('&') {
378 self.advance();
379 Ok(Token::And)
380 } else {
381 Ok(Token::BitAnd)
382 }
383 }
384 '|' => {
385 self.advance();
386 if self.current == Some('|') {
387 self.advance();
388 Ok(Token::Or)
389 } else {
390 Ok(Token::BitOr)
391 }
392 }
393 '^' => {
394 self.advance();
395 Ok(Token::BitXor)
396 }
397 _ if ch.is_alphabetic() || ch == '_' => {
398 let ident = self.read_identifier();
399 Ok(match ident.as_str() {
400 "OPENQASM" => Token::OpenQasm,
401 "include" => Token::Include,
402 "qubit" => Token::Qubit,
403 "bit" => Token::Bit,
404 "gate" => Token::Gate,
405 "measure" => Token::Measure,
406 "reset" => Token::Reset,
407 "barrier" => Token::Barrier,
408 "if" => Token::If,
409 "else" => Token::Else,
410 "for" => Token::For,
411 "while" => Token::While,
412 "in" => Token::In,
413 "const" => Token::Const,
414 "def" => Token::Def,
415 "return" => Token::Return,
416 "delay" => Token::Delay,
417 "ctrl" => Token::Ctrl,
418 "inv" => Token::Inv,
419 "pow" => Token::Pow,
420 "pi" => Token::Identifier("pi".into()),
421 "e" => Token::Identifier("e".into()),
422 "tau" => Token::Identifier("tau".into()),
423 _ => Token::Identifier(ident),
424 })
425 }
426 _ if ch.is_numeric() => self.read_number(),
427 _ => Err(ParseError::UnexpectedToken(ch.to_string())),
428 },
429 }
430 }
431}
432
433pub struct QasmParser<'a> {
435 lexer: Lexer<'a>,
436 current_token: Token,
437 symbols: HashMap<String, SymbolType>,
439}
440
441#[derive(Debug, Clone)]
442enum SymbolType {
443 QuantumRegister(usize),
444 ClassicalRegister(usize),
445 Gate(Vec<String>, Vec<String>), Constant(f64),
449 Variable,
450}
451
452fn eval_const_binary(op: BinaryOp, l: f64, r: f64) -> f64 {
457 let bool_to_f64 = |b: bool| if b { 1.0 } else { 0.0 };
458 match op {
459 BinaryOp::Add => l + r,
460 BinaryOp::Sub => l - r,
461 BinaryOp::Mul => l * r,
462 BinaryOp::Div => l / r,
463 BinaryOp::Mod => l % r,
464 BinaryOp::Pow => l.powf(r),
465 BinaryOp::Eq => bool_to_f64((l - r).abs() < f64::EPSILON),
466 BinaryOp::Ne => bool_to_f64((l - r).abs() >= f64::EPSILON),
467 BinaryOp::Lt => bool_to_f64(l < r),
468 BinaryOp::Le => bool_to_f64(l <= r),
469 BinaryOp::Gt => bool_to_f64(l > r),
470 BinaryOp::Ge => bool_to_f64(l >= r),
471 BinaryOp::And => bool_to_f64(l != 0.0 && r != 0.0),
472 BinaryOp::Or => bool_to_f64(l != 0.0 || r != 0.0),
473 BinaryOp::Xor => bool_to_f64((l != 0.0) ^ (r != 0.0)),
474 BinaryOp::BitAnd => ((l as i64) & (r as i64)) as f64,
475 BinaryOp::BitOr => ((l as i64) | (r as i64)) as f64,
476 BinaryOp::BitXor => ((l as i64) ^ (r as i64)) as f64,
477 BinaryOp::Shl => ((l as i64) << (r as i64)) as f64,
478 BinaryOp::Shr => ((l as i64) >> (r as i64)) as f64,
479 }
480}
481
482fn eval_const_unary(op: UnaryOp, v: f64) -> f64 {
484 match op {
485 UnaryOp::Neg => -v,
486 UnaryOp::Not => {
487 if v == 0.0 {
488 1.0
489 } else {
490 0.0
491 }
492 }
493 UnaryOp::BitNot => (!(v as i64)) as f64,
494 UnaryOp::Sin => v.sin(),
495 UnaryOp::Cos => v.cos(),
496 UnaryOp::Tan => v.tan(),
497 UnaryOp::Asin => v.asin(),
498 UnaryOp::Acos => v.acos(),
499 UnaryOp::Atan => v.atan(),
500 UnaryOp::Exp => v.exp(),
501 UnaryOp::Ln => v.ln(),
502 UnaryOp::Sqrt => v.sqrt(),
503 }
504}
505
506fn expr_contains_function_or_index(expr: &Expression) -> bool {
513 match expr {
514 Expression::Literal(_) | Expression::Variable(_) => false,
515 Expression::Binary(_, lhs, rhs) => {
516 expr_contains_function_or_index(lhs) || expr_contains_function_or_index(rhs)
517 }
518 Expression::Unary(_, inner) => expr_contains_function_or_index(inner),
519 Expression::Function(_, _) | Expression::Index(_, _) => true,
520 }
521}
522
523fn eval_const_function(name: &str, args: &[f64]) -> Result<f64, ParseError> {
525 let arity_err = |expected: usize| {
526 ParseError::InvalidSyntax(format!(
527 "function '{name}' expects {expected} argument(s), got {}",
528 args.len()
529 ))
530 };
531 match name {
532 "sin" | "cos" | "tan" | "asin" | "acos" | "atan" | "exp" | "ln" | "log2" | "log10"
533 | "sqrt" | "abs" | "floor" | "ceil" | "round" => {
534 if args.len() != 1 {
535 return Err(arity_err(1));
536 }
537 let v = args[0];
538 Ok(match name {
539 "sin" => v.sin(),
540 "cos" => v.cos(),
541 "tan" => v.tan(),
542 "asin" => v.asin(),
543 "acos" => v.acos(),
544 "atan" => v.atan(),
545 "exp" => v.exp(),
546 "ln" => v.ln(),
547 "log2" => v.log2(),
548 "log10" => v.log10(),
549 "sqrt" => v.sqrt(),
550 "abs" => v.abs(),
551 "floor" => v.floor(),
552 "ceil" => v.ceil(),
553 "round" => v.round(),
554 _ => unreachable!(),
555 })
556 }
557 "pow" | "atan2" | "min" | "max" => {
558 if args.len() != 2 {
559 return Err(arity_err(2));
560 }
561 let (a, b) = (args[0], args[1]);
562 Ok(match name {
563 "pow" => a.powf(b),
564 "atan2" => a.atan2(b),
565 "min" => a.min(b),
566 "max" => a.max(b),
567 _ => unreachable!(),
568 })
569 }
570 _ => Err(ParseError::InvalidSyntax(format!(
571 "unknown function '{name}' in constant expression"
572 ))),
573 }
574}
575
576impl<'a> QasmParser<'a> {
577 pub fn new(input: &'a str) -> Result<Self, ParseError> {
579 let mut lexer = Lexer::new(input);
580 let current_token = lexer.next_token()?;
581
582 Ok(QasmParser {
583 lexer,
584 current_token,
585 symbols: HashMap::new(),
586 })
587 }
588
589 pub fn parse_program(&mut self) -> Result<QasmProgram, ParseError> {
591 self.expect_token(&Token::OpenQasm)?;
593 let version = self.parse_version()?;
594 self.expect_token(&Token::Semicolon)?;
595
596 let mut includes = Vec::new();
598 while self.current_token == Token::Include {
599 includes.push(self.parse_include()?);
600 }
601
602 let mut declarations = Vec::new();
604 let mut statements = Vec::new();
605
606 while self.current_token != Token::Eof {
607 match &self.current_token {
608 Token::Qubit => declarations.push(self.parse_quantum_register()?),
609 Token::Bit => declarations.push(self.parse_classical_register()?),
610 Token::Gate => declarations.push(self.parse_gate_definition()?),
611 Token::Const => declarations.push(self.parse_constant()?),
612 _ => statements.push(self.parse_statement()?),
613 }
614 }
615
616 Ok(QasmProgram {
617 version,
618 includes,
619 declarations,
620 statements,
621 })
622 }
623
624 fn advance(&mut self) -> Result<(), ParseError> {
625 self.current_token = self.lexer.next_token()?;
626 Ok(())
627 }
628
629 fn expect_token(&mut self, expected: &Token) -> Result<(), ParseError> {
630 if std::mem::discriminant(&self.current_token) == std::mem::discriminant(expected) {
631 self.advance()
632 } else {
633 Err(ParseError::ExpectedToken {
634 expected: format!("{expected:?}"),
635 found: format!("{:?}", self.current_token),
636 })
637 }
638 }
639
640 fn parse_version(&mut self) -> Result<String, ParseError> {
641 match &self.current_token {
642 Token::Float(v) => {
643 let version = if *v == 3.0 {
644 "3.0".to_string()
645 } else {
646 format!("{v}")
647 };
648 if !version.starts_with("3.") {
649 return Err(ParseError::VersionMismatch(version));
650 }
651 self.advance()?;
652 Ok(version)
653 }
654 Token::Integer(v) if *v == 3 => {
655 self.advance()?;
657 if self.current_token == Token::Dot {
658 self.advance()?;
659 if let Token::Integer(minor) = self.current_token.clone() {
660 let minor_val = minor;
661 self.advance()?;
662 Ok(format!("3.{minor_val}"))
663 } else {
664 Ok("3.0".to_string())
665 }
666 } else {
667 Ok("3.0".to_string())
668 }
669 }
670 _ => Err(ParseError::ExpectedToken {
671 expected: "version number".into(),
672 found: format!("{:?}", self.current_token),
673 }),
674 }
675 }
676
677 fn parse_include(&mut self) -> Result<String, ParseError> {
678 self.expect_token(&Token::Include)?;
679
680 match &self.current_token {
681 Token::String(s) => {
682 let include = s.clone();
683 self.advance()?;
684 self.expect_token(&Token::Semicolon)?;
685 Ok(include)
686 }
687 _ => Err(ParseError::ExpectedToken {
688 expected: "string".into(),
689 found: format!("{:?}", self.current_token),
690 }),
691 }
692 }
693
694 fn parse_quantum_register(&mut self) -> Result<Declaration, ParseError> {
695 self.expect_token(&Token::Qubit)?;
696
697 let (size, name) = if self.current_token == Token::LeftBracket {
698 self.advance()?; let size = match &self.current_token {
702 Token::Integer(n) => {
703 let size = *n as usize;
704 self.advance()?;
705 size
706 }
707 Token::Identifier(const_name) => {
708 let const_name = const_name.clone();
710 self.advance()?;
711 self.resolve_register_size(&const_name)?
712 }
713 _ => {
714 return Err(ParseError::ExpectedToken {
715 expected: "integer or identifier".into(),
716 found: format!("{:?}", self.current_token),
717 })
718 }
719 };
720
721 self.expect_token(&Token::RightBracket)?;
722
723 let name = match &self.current_token {
724 Token::Identifier(s) => s.clone(),
725 _ => {
726 return Err(ParseError::ExpectedToken {
727 expected: "identifier".into(),
728 found: format!("{:?}", self.current_token),
729 })
730 }
731 };
732 self.advance()?;
733
734 (size, name)
735 } else {
736 let name = match &self.current_token {
738 Token::Identifier(s) => s.clone(),
739 _ => {
740 return Err(ParseError::ExpectedToken {
741 expected: "identifier".into(),
742 found: format!("{:?}", self.current_token),
743 })
744 }
745 };
746 self.advance()?;
747
748 (1, name)
749 };
750
751 self.expect_token(&Token::Semicolon)?;
752
753 self.symbols
755 .insert(name.clone(), SymbolType::QuantumRegister(size));
756
757 Ok(Declaration::QuantumRegister(QasmRegister { name, size }))
758 }
759
760 fn parse_classical_register(&mut self) -> Result<Declaration, ParseError> {
761 self.expect_token(&Token::Bit)?;
762
763 let (size, name) = if self.current_token == Token::LeftBracket {
764 self.advance()?; let size = match &self.current_token {
768 Token::Integer(n) => {
769 let size = *n as usize;
770 self.advance()?;
771 size
772 }
773 Token::Identifier(const_name) => {
774 let const_name = const_name.clone();
776 self.advance()?;
777 self.resolve_register_size(&const_name)?
778 }
779 _ => {
780 return Err(ParseError::ExpectedToken {
781 expected: "integer or identifier".into(),
782 found: format!("{:?}", self.current_token),
783 })
784 }
785 };
786
787 self.expect_token(&Token::RightBracket)?;
788
789 let name = match &self.current_token {
790 Token::Identifier(s) => s.clone(),
791 _ => {
792 return Err(ParseError::ExpectedToken {
793 expected: "identifier".into(),
794 found: format!("{:?}", self.current_token),
795 })
796 }
797 };
798 self.advance()?;
799
800 (size, name)
801 } else {
802 let name = match &self.current_token {
804 Token::Identifier(s) => s.clone(),
805 _ => {
806 return Err(ParseError::ExpectedToken {
807 expected: "identifier".into(),
808 found: format!("{:?}", self.current_token),
809 })
810 }
811 };
812 self.advance()?;
813
814 (1, name)
815 };
816
817 self.expect_token(&Token::Semicolon)?;
818
819 self.symbols
821 .insert(name.clone(), SymbolType::ClassicalRegister(size));
822
823 Ok(Declaration::ClassicalRegister(QasmRegister { name, size }))
824 }
825
826 fn parse_gate_definition(&mut self) -> Result<Declaration, ParseError> {
827 self.expect_token(&Token::Gate)?;
828
829 let name = match &self.current_token {
830 Token::Identifier(s) => s.clone(),
831 _ => {
832 return Err(ParseError::ExpectedToken {
833 expected: "identifier".into(),
834 found: format!("{:?}", self.current_token),
835 })
836 }
837 };
838 self.advance()?;
839
840 let mut params = Vec::new();
842 if self.current_token == Token::LeftParen {
843 self.advance()?;
844
845 while self.current_token != Token::RightParen {
846 match &self.current_token {
847 Token::Identifier(s) => {
848 params.push(s.clone());
849 self.advance()?;
850 }
851 _ => {
852 return Err(ParseError::ExpectedToken {
853 expected: "identifier".into(),
854 found: format!("{:?}", self.current_token),
855 })
856 }
857 }
858
859 if self.current_token == Token::Comma {
860 self.advance()?;
861 }
862 }
863
864 self.expect_token(&Token::RightParen)?;
865 }
866
867 let mut qubits = Vec::new();
869 while self.current_token != Token::LeftBrace {
870 match &self.current_token {
871 Token::Identifier(s) => {
872 qubits.push(s.clone());
873 self.advance()?;
874 }
875 _ => {
876 return Err(ParseError::ExpectedToken {
877 expected: "identifier".into(),
878 found: format!("{:?}", self.current_token),
879 })
880 }
881 }
882
883 if self.current_token == Token::Comma {
884 self.advance()?;
885 }
886 }
887
888 self.expect_token(&Token::LeftBrace)?;
890 let mut body = Vec::new();
891
892 while self.current_token != Token::RightBrace {
893 body.push(self.parse_statement()?);
894 }
895
896 self.expect_token(&Token::RightBrace)?;
897
898 self.symbols.insert(
900 name.clone(),
901 SymbolType::Gate(params.clone(), qubits.clone()),
902 );
903
904 Ok(Declaration::GateDefinition(GateDefinition {
905 name,
906 params,
907 qubits,
908 body,
909 }))
910 }
911
912 fn parse_constant(&mut self) -> Result<Declaration, ParseError> {
913 self.expect_token(&Token::Const)?;
914
915 let name = match &self.current_token {
916 Token::Identifier(s) => s.clone(),
917 _ => {
918 return Err(ParseError::ExpectedToken {
919 expected: "identifier".into(),
920 found: format!("{:?}", self.current_token),
921 })
922 }
923 };
924 self.advance()?;
925
926 self.expect_token(&Token::Assign)?;
927
928 let expr = self.parse_expression()?;
929
930 self.expect_token(&Token::Semicolon)?;
931
932 match self.eval_const_expr(&expr) {
951 Ok(value) => {
952 self.symbols
953 .insert(name.clone(), SymbolType::Constant(value));
954 }
955 Err(err) => {
956 if expr_contains_function_or_index(&expr) {
957 self.symbols.insert(name.clone(), SymbolType::Variable);
958 } else {
959 return Err(err);
960 }
961 }
962 }
963
964 Ok(Declaration::Constant(name, expr))
965 }
966
967 fn resolve_register_size(&self, name: &str) -> Result<usize, ParseError> {
973 match self.symbols.get(name) {
974 Some(SymbolType::Constant(value)) => {
975 let value = *value;
976 if !value.is_finite() || value < 0.0 || value.fract() != 0.0 {
977 return Err(ParseError::TypeMismatch(format!(
978 "constant '{name}' = {value} is not a valid register size (expected a non-negative integer)"
979 )));
980 }
981 Ok(value as usize)
982 }
983 Some(_) => Err(ParseError::TypeMismatch(format!(
984 "'{name}' is not a constant and cannot be used as a register size"
985 ))),
986 None => Err(ParseError::UndefinedIdentifier(name.to_string())),
987 }
988 }
989
990 fn eval_const_expr(&self, expr: &Expression) -> Result<f64, ParseError> {
997 match expr {
998 Expression::Literal(lit) => match lit {
999 Literal::Integer(n) => Ok(*n as f64),
1000 Literal::Float(x) => Ok(*x),
1001 Literal::Bool(b) => Ok(if *b { 1.0 } else { 0.0 }),
1002 Literal::Pi => Ok(std::f64::consts::PI),
1003 Literal::Tau => Ok(std::f64::consts::TAU),
1004 Literal::Euler => Ok(std::f64::consts::E),
1005 Literal::String(s) => Err(ParseError::TypeMismatch(format!(
1006 "string literal \"{s}\" is not a numeric constant"
1007 ))),
1008 },
1009 Expression::Variable(name) => match self.symbols.get(name) {
1010 Some(SymbolType::Constant(value)) => Ok(*value),
1011 Some(_) => Err(ParseError::TypeMismatch(format!(
1012 "'{name}' is not a constant and cannot appear in a constant expression"
1013 ))),
1014 None => Err(ParseError::UndefinedIdentifier(name.clone())),
1015 },
1016 Expression::Binary(op, lhs, rhs) => {
1017 let l = self.eval_const_expr(lhs)?;
1018 let r = self.eval_const_expr(rhs)?;
1019 Ok(eval_const_binary(*op, l, r))
1020 }
1021 Expression::Unary(op, inner) => {
1022 let v = self.eval_const_expr(inner)?;
1023 Ok(eval_const_unary(*op, v))
1024 }
1025 Expression::Function(name, args) => {
1026 let values: Result<Vec<f64>, ParseError> =
1027 args.iter().map(|a| self.eval_const_expr(a)).collect();
1028 eval_const_function(name, &values?)
1029 }
1030 Expression::Index(name, _) => Err(ParseError::TypeMismatch(format!(
1031 "array index into '{name}' is not a constant expression"
1032 ))),
1033 }
1034 }
1035
1036 fn parse_statement(&mut self) -> Result<QasmStatement, ParseError> {
1037 match &self.current_token {
1038 Token::Measure => self.parse_measure(),
1039 Token::Reset => self.parse_reset(),
1040 Token::Barrier => self.parse_barrier(),
1041 Token::If => self.parse_if(),
1042 Token::For => self.parse_for(),
1043 Token::While => self.parse_while(),
1044 Token::Delay => self.parse_delay(),
1045 Token::Identifier(_) => {
1046 self.parse_identifier_statement()
1048 }
1049 Token::Ctrl | Token::Inv | Token::Pow => self.parse_modified_gate(),
1050 _ => Err(ParseError::UnexpectedToken(format!(
1051 "{:?}",
1052 self.current_token
1053 ))),
1054 }
1055 }
1056
1057 fn parse_measure(&mut self) -> Result<QasmStatement, ParseError> {
1060 self.expect_token(&Token::Measure)?;
1061
1062 let mut qubits = Vec::new();
1063 let mut targets = Vec::new();
1064
1065 qubits.push(self.parse_qubit_ref()?);
1067 self.expect_token(&Token::Arrow)?;
1068 targets.push(self.parse_classical_ref()?);
1069
1070 while self.current_token == Token::Comma {
1072 self.advance()?;
1073 qubits.push(self.parse_qubit_ref()?);
1074 self.expect_token(&Token::Arrow)?;
1075 targets.push(self.parse_classical_ref()?);
1076 }
1077
1078 self.expect_token(&Token::Semicolon)?;
1079
1080 Ok(QasmStatement::Measure(Measurement { qubits, targets }))
1081 }
1082
1083 fn parse_reset(&mut self) -> Result<QasmStatement, ParseError> {
1084 self.expect_token(&Token::Reset)?;
1085
1086 let mut qubits = Vec::new();
1087 qubits.push(self.parse_qubit_ref()?);
1088
1089 while self.current_token == Token::Comma {
1090 self.advance()?;
1091 qubits.push(self.parse_qubit_ref()?);
1092 }
1093
1094 self.expect_token(&Token::Semicolon)?;
1095
1096 Ok(QasmStatement::Reset(qubits))
1097 }
1098
1099 fn parse_barrier(&mut self) -> Result<QasmStatement, ParseError> {
1100 self.expect_token(&Token::Barrier)?;
1101
1102 let mut qubits = Vec::new();
1103
1104 if self.current_token != Token::Semicolon {
1105 qubits.push(self.parse_qubit_ref()?);
1106
1107 while self.current_token == Token::Comma {
1108 self.advance()?;
1109 qubits.push(self.parse_qubit_ref()?);
1110 }
1111 }
1112
1113 self.expect_token(&Token::Semicolon)?;
1114
1115 Ok(QasmStatement::Barrier(qubits))
1116 }
1117
1118 fn parse_if(&mut self) -> Result<QasmStatement, ParseError> {
1119 self.expect_token(&Token::If)?;
1120 self.expect_token(&Token::LeftParen)?;
1121
1122 let condition = self.parse_condition()?;
1123
1124 self.expect_token(&Token::RightParen)?;
1125
1126 let statement = Box::new(self.parse_statement()?);
1127
1128 Ok(QasmStatement::If(condition, statement))
1129 }
1130
1131 fn parse_for(&mut self) -> Result<QasmStatement, ParseError> {
1132 self.expect_token(&Token::For)?;
1133
1134 let variable = match &self.current_token {
1135 Token::Identifier(s) => s.clone(),
1136 _ => {
1137 return Err(ParseError::ExpectedToken {
1138 expected: "identifier".into(),
1139 found: format!("{:?}", self.current_token),
1140 })
1141 }
1142 };
1143 self.advance()?;
1144
1145 self.expect_token(&Token::In)?;
1146 self.expect_token(&Token::LeftBracket)?;
1147
1148 let start = self.parse_expression()?;
1149 self.expect_token(&Token::Colon)?;
1150 let end = self.parse_expression()?;
1151
1152 let step = if self.current_token == Token::Colon {
1153 self.advance()?;
1154 Some(self.parse_expression()?)
1155 } else {
1156 None
1157 };
1158
1159 self.expect_token(&Token::RightBracket)?;
1160 self.expect_token(&Token::LeftBrace)?;
1161
1162 let mut body = Vec::new();
1163 while self.current_token != Token::RightBrace {
1164 body.push(self.parse_statement()?);
1165 }
1166
1167 self.expect_token(&Token::RightBrace)?;
1168
1169 Ok(QasmStatement::For(ForLoop {
1170 variable,
1171 start,
1172 end,
1173 step,
1174 body,
1175 }))
1176 }
1177
1178 fn parse_while(&mut self) -> Result<QasmStatement, ParseError> {
1179 self.expect_token(&Token::While)?;
1180 self.expect_token(&Token::LeftParen)?;
1181
1182 let condition = self.parse_condition()?;
1183
1184 self.expect_token(&Token::RightParen)?;
1185 self.expect_token(&Token::LeftBrace)?;
1186
1187 let mut body = Vec::new();
1188 while self.current_token != Token::RightBrace {
1189 body.push(self.parse_statement()?);
1190 }
1191
1192 self.expect_token(&Token::RightBrace)?;
1193
1194 Ok(QasmStatement::While(condition, body))
1195 }
1196
1197 fn parse_delay(&mut self) -> Result<QasmStatement, ParseError> {
1198 self.expect_token(&Token::Delay)?;
1199 self.expect_token(&Token::LeftBracket)?;
1200
1201 let duration = self.parse_expression()?;
1202
1203 self.expect_token(&Token::RightBracket)?;
1204
1205 let mut qubits = Vec::new();
1206
1207 if self.current_token != Token::Semicolon {
1208 qubits.push(self.parse_qubit_ref()?);
1209
1210 while self.current_token == Token::Comma {
1211 self.advance()?;
1212 qubits.push(self.parse_qubit_ref()?);
1213 }
1214 }
1215
1216 self.expect_token(&Token::Semicolon)?;
1217
1218 Ok(QasmStatement::Delay(duration, qubits))
1219 }
1220
1221 fn parse_identifier_statement(&mut self) -> Result<QasmStatement, ParseError> {
1222 let name = match &self.current_token {
1223 Token::Identifier(s) => s.clone(),
1224 _ => return Err(ParseError::InvalidSyntax("Expected identifier".into())),
1225 };
1226 self.advance()?;
1227
1228 match &self.current_token {
1229 Token::LeftParen => {
1230 self.parse_gate_or_call(name)
1232 }
1233 Token::LeftBracket | Token::Identifier(_) => {
1234 let mut gate = QasmGate {
1236 name,
1237 params: Vec::new(),
1238 qubits: Vec::new(),
1239 control: None,
1240 inverse: false,
1241 power: None,
1242 };
1243
1244 gate.qubits.push(self.parse_qubit_ref()?);
1246
1247 while self.current_token == Token::Comma {
1248 self.advance()?;
1249 gate.qubits.push(self.parse_qubit_ref()?);
1250 }
1251
1252 self.expect_token(&Token::Semicolon)?;
1253
1254 Ok(QasmStatement::Gate(gate))
1255 }
1256 _ => Err(ParseError::InvalidSyntax("Invalid statement".into())),
1257 }
1258 }
1259
1260 fn parse_modified_gate(&mut self) -> Result<QasmStatement, ParseError> {
1261 let mut control = None;
1262 let mut inverse = false;
1263 let mut power = None;
1264
1265 loop {
1267 match &self.current_token {
1268 Token::Ctrl => {
1269 self.advance()?;
1270 if self.current_token == Token::LeftParen {
1271 self.advance()?;
1272 control = Some(match &self.current_token {
1273 Token::Integer(n) => *n as usize,
1274 _ => {
1275 return Err(ParseError::ExpectedToken {
1276 expected: "integer".into(),
1277 found: format!("{:?}", self.current_token),
1278 })
1279 }
1280 });
1281 self.advance()?;
1282 self.expect_token(&Token::RightParen)?;
1283 } else {
1284 control = Some(1);
1285 }
1286 }
1287 Token::Inv => {
1288 inverse = true;
1289 self.advance()?;
1290 }
1291 Token::Pow => {
1292 self.advance()?;
1293 self.expect_token(&Token::LeftParen)?;
1294 power = Some(self.parse_expression()?);
1295 self.expect_token(&Token::RightParen)?;
1296 }
1297 _ => break,
1298 }
1299 }
1300
1301 let name = match &self.current_token {
1303 Token::Identifier(s) => s.clone(),
1304 _ => {
1305 return Err(ParseError::ExpectedToken {
1306 expected: "gate name".into(),
1307 found: format!("{:?}", self.current_token),
1308 })
1309 }
1310 };
1311 self.advance()?;
1312
1313 let mut params = Vec::new();
1315 if self.current_token == Token::LeftParen {
1316 self.advance()?;
1317
1318 while self.current_token != Token::RightParen {
1319 params.push(self.parse_expression()?);
1320
1321 if self.current_token == Token::Comma {
1322 self.advance()?;
1323 }
1324 }
1325
1326 self.expect_token(&Token::RightParen)?;
1327 }
1328
1329 let mut qubits = Vec::new();
1331 qubits.push(self.parse_qubit_ref()?);
1332
1333 while self.current_token == Token::Comma {
1334 self.advance()?;
1335 qubits.push(self.parse_qubit_ref()?);
1336 }
1337
1338 self.expect_token(&Token::Semicolon)?;
1339
1340 Ok(QasmStatement::Gate(QasmGate {
1341 name,
1342 params,
1343 qubits,
1344 control,
1345 inverse,
1346 power,
1347 }))
1348 }
1349
1350 fn parse_gate_or_call(&mut self, name: String) -> Result<QasmStatement, ParseError> {
1351 self.expect_token(&Token::LeftParen)?;
1352
1353 let mut args = Vec::new();
1354
1355 while self.current_token != Token::RightParen {
1356 args.push(self.parse_expression()?);
1357
1358 if self.current_token == Token::Comma {
1359 self.advance()?;
1360 }
1361 }
1362
1363 self.expect_token(&Token::RightParen)?;
1364
1365 match &self.current_token {
1367 Token::Identifier(_) | Token::LeftBracket => {
1368 let mut qubits = Vec::new();
1370 qubits.push(self.parse_qubit_ref()?);
1371
1372 while self.current_token == Token::Comma {
1373 self.advance()?;
1374 qubits.push(self.parse_qubit_ref()?);
1375 }
1376
1377 self.expect_token(&Token::Semicolon)?;
1378
1379 Ok(QasmStatement::Gate(QasmGate {
1380 name,
1381 params: args,
1382 qubits,
1383 control: None,
1384 inverse: false,
1385 power: None,
1386 }))
1387 }
1388 Token::Semicolon => {
1389 self.advance()?;
1391 Ok(QasmStatement::Call(name, args))
1392 }
1393 _ => Err(ParseError::InvalidSyntax(
1394 "Expected qubits or semicolon".into(),
1395 )),
1396 }
1397 }
1398
1399 fn parse_qubit_ref(&mut self) -> Result<QubitRef, ParseError> {
1400 let register = match &self.current_token {
1401 Token::Identifier(s) => s.clone(),
1402 _ => {
1403 return Err(ParseError::ExpectedToken {
1404 expected: "register name".into(),
1405 found: format!("{:?}", self.current_token),
1406 })
1407 }
1408 };
1409 self.advance()?;
1410
1411 if self.current_token == Token::LeftBracket {
1412 self.advance()?;
1413
1414 let start = match &self.current_token {
1415 Token::Integer(n) => *n as usize,
1416 _ => {
1417 return Err(ParseError::ExpectedToken {
1418 expected: "integer".into(),
1419 found: format!("{:?}", self.current_token),
1420 })
1421 }
1422 };
1423 self.advance()?;
1424
1425 if self.current_token == Token::Colon {
1426 self.advance()?;
1428 let end = match &self.current_token {
1429 Token::Integer(n) => *n as usize,
1430 _ => {
1431 return Err(ParseError::ExpectedToken {
1432 expected: "integer".into(),
1433 found: format!("{:?}", self.current_token),
1434 })
1435 }
1436 };
1437 self.advance()?;
1438 self.expect_token(&Token::RightBracket)?;
1439
1440 Ok(QubitRef::Slice {
1441 register,
1442 start,
1443 end,
1444 })
1445 } else {
1446 self.expect_token(&Token::RightBracket)?;
1448 Ok(QubitRef::Single {
1449 register,
1450 index: start,
1451 })
1452 }
1453 } else {
1454 Ok(QubitRef::Register(register))
1456 }
1457 }
1458
1459 fn parse_classical_ref(&mut self) -> Result<ClassicalRef, ParseError> {
1460 let register = match &self.current_token {
1461 Token::Identifier(s) => s.clone(),
1462 _ => {
1463 return Err(ParseError::ExpectedToken {
1464 expected: "register name".into(),
1465 found: format!("{:?}", self.current_token),
1466 })
1467 }
1468 };
1469 self.advance()?;
1470
1471 if self.current_token == Token::LeftBracket {
1472 self.advance()?;
1473
1474 let start = match &self.current_token {
1475 Token::Integer(n) => *n as usize,
1476 _ => {
1477 return Err(ParseError::ExpectedToken {
1478 expected: "integer".into(),
1479 found: format!("{:?}", self.current_token),
1480 })
1481 }
1482 };
1483 self.advance()?;
1484
1485 if self.current_token == Token::Colon {
1486 self.advance()?;
1488 let end = match &self.current_token {
1489 Token::Integer(n) => *n as usize,
1490 _ => {
1491 return Err(ParseError::ExpectedToken {
1492 expected: "integer".into(),
1493 found: format!("{:?}", self.current_token),
1494 })
1495 }
1496 };
1497 self.advance()?;
1498 self.expect_token(&Token::RightBracket)?;
1499
1500 Ok(ClassicalRef::Slice {
1501 register,
1502 start,
1503 end,
1504 })
1505 } else {
1506 self.expect_token(&Token::RightBracket)?;
1508 Ok(ClassicalRef::Single {
1509 register,
1510 index: start,
1511 })
1512 }
1513 } else {
1514 Ok(ClassicalRef::Register(register))
1516 }
1517 }
1518
1519 fn parse_expression(&mut self) -> Result<Expression, ParseError> {
1520 self.parse_or_expression()
1521 }
1522
1523 fn parse_or_expression(&mut self) -> Result<Expression, ParseError> {
1524 let mut left = self.parse_and_expression()?;
1525
1526 while self.current_token == Token::Or {
1527 self.advance()?;
1528 let right = self.parse_and_expression()?;
1529 left = Expression::Binary(BinaryOp::Or, Box::new(left), Box::new(right));
1530 }
1531
1532 Ok(left)
1533 }
1534
1535 fn parse_and_expression(&mut self) -> Result<Expression, ParseError> {
1536 let mut left = self.parse_equality_expression()?;
1537
1538 while self.current_token == Token::And {
1539 self.advance()?;
1540 let right = self.parse_equality_expression()?;
1541 left = Expression::Binary(BinaryOp::And, Box::new(left), Box::new(right));
1542 }
1543
1544 Ok(left)
1545 }
1546
1547 fn parse_equality_expression(&mut self) -> Result<Expression, ParseError> {
1548 let mut left = self.parse_relational_expression()?;
1549
1550 loop {
1551 let op = match &self.current_token {
1552 Token::Eq => BinaryOp::Eq,
1553 Token::Ne => BinaryOp::Ne,
1554 _ => break,
1555 };
1556 self.advance()?;
1557
1558 let right = self.parse_relational_expression()?;
1559 left = Expression::Binary(op, Box::new(left), Box::new(right));
1560 }
1561
1562 Ok(left)
1563 }
1564
1565 fn parse_relational_expression(&mut self) -> Result<Expression, ParseError> {
1566 let mut left = self.parse_additive_expression()?;
1567
1568 loop {
1569 let op = match &self.current_token {
1570 Token::Lt => BinaryOp::Lt,
1571 Token::Le => BinaryOp::Le,
1572 Token::Gt => BinaryOp::Gt,
1573 Token::Ge => BinaryOp::Ge,
1574 _ => break,
1575 };
1576 self.advance()?;
1577
1578 let right = self.parse_additive_expression()?;
1579 left = Expression::Binary(op, Box::new(left), Box::new(right));
1580 }
1581
1582 Ok(left)
1583 }
1584
1585 fn parse_additive_expression(&mut self) -> Result<Expression, ParseError> {
1586 let mut left = self.parse_multiplicative_expression()?;
1587
1588 loop {
1589 let op = match &self.current_token {
1590 Token::Plus => BinaryOp::Add,
1591 Token::Minus => BinaryOp::Sub,
1592 _ => break,
1593 };
1594 self.advance()?;
1595
1596 let right = self.parse_multiplicative_expression()?;
1597 left = Expression::Binary(op, Box::new(left), Box::new(right));
1598 }
1599
1600 Ok(left)
1601 }
1602
1603 fn parse_multiplicative_expression(&mut self) -> Result<Expression, ParseError> {
1604 let mut left = self.parse_unary_expression()?;
1605
1606 loop {
1607 let op = match &self.current_token {
1608 Token::Star => BinaryOp::Mul,
1609 Token::Slash => BinaryOp::Div,
1610 Token::Percent => BinaryOp::Mod,
1611 _ => break,
1612 };
1613 self.advance()?;
1614
1615 let right = self.parse_unary_expression()?;
1616 left = Expression::Binary(op, Box::new(left), Box::new(right));
1617 }
1618
1619 Ok(left)
1620 }
1621
1622 fn parse_unary_expression(&mut self) -> Result<Expression, ParseError> {
1623 match &self.current_token {
1624 Token::Minus => {
1625 self.advance()?;
1626 Ok(Expression::Unary(
1627 UnaryOp::Neg,
1628 Box::new(self.parse_unary_expression()?),
1629 ))
1630 }
1631 Token::Not => {
1632 self.advance()?;
1633 Ok(Expression::Unary(
1634 UnaryOp::Not,
1635 Box::new(self.parse_unary_expression()?),
1636 ))
1637 }
1638 Token::BitNot => {
1639 self.advance()?;
1640 Ok(Expression::Unary(
1641 UnaryOp::BitNot,
1642 Box::new(self.parse_unary_expression()?),
1643 ))
1644 }
1645 _ => self.parse_postfix_expression(),
1646 }
1647 }
1648
1649 fn parse_postfix_expression(&mut self) -> Result<Expression, ParseError> {
1650 let mut expr = self.parse_primary_expression()?;
1651
1652 loop {
1653 match &self.current_token {
1654 Token::LeftBracket => {
1655 self.advance()?;
1656 let index = self.parse_expression()?;
1657 self.expect_token(&Token::RightBracket)?;
1658
1659 match expr {
1660 Expression::Variable(name) => {
1661 expr = Expression::Index(name, Box::new(index));
1662 }
1663 _ => {
1664 return Err(ParseError::InvalidSyntax(
1665 "Cannot index non-variable".into(),
1666 ))
1667 }
1668 }
1669 }
1670 Token::LeftParen => {
1671 self.advance()?;
1673 let mut args = Vec::new();
1674
1675 while self.current_token != Token::RightParen {
1676 args.push(self.parse_expression()?);
1677 if self.current_token == Token::Comma {
1678 self.advance()?;
1679 }
1680 }
1681
1682 self.expect_token(&Token::RightParen)?;
1683
1684 match expr {
1685 Expression::Variable(name) => {
1686 expr = Expression::Function(name, args);
1687 }
1688 _ => {
1689 return Err(ParseError::InvalidSyntax(
1690 "Cannot call non-function".into(),
1691 ))
1692 }
1693 }
1694 }
1695 _ => break,
1696 }
1697 }
1698
1699 Ok(expr)
1700 }
1701
1702 fn parse_primary_expression(&mut self) -> Result<Expression, ParseError> {
1703 match &self.current_token {
1704 Token::Integer(n) => {
1705 let value = *n;
1706 self.advance()?;
1707 Ok(Expression::Literal(Literal::Integer(value)))
1708 }
1709 Token::Float(f) => {
1710 let value = *f;
1711 self.advance()?;
1712 Ok(Expression::Literal(Literal::Float(value)))
1713 }
1714 Token::String(s) => {
1715 let value = s.clone();
1716 self.advance()?;
1717 Ok(Expression::Literal(Literal::String(value)))
1718 }
1719 Token::Identifier(s) => {
1720 let name = s.clone();
1721 self.advance()?;
1722
1723 match name.as_str() {
1725 "pi" => Ok(Expression::Literal(Literal::Pi)),
1726 "e" => Ok(Expression::Literal(Literal::Euler)),
1727 "tau" => Ok(Expression::Literal(Literal::Tau)),
1728 _ => Ok(Expression::Variable(name)),
1729 }
1730 }
1731 Token::LeftParen => {
1732 self.advance()?;
1733 let expr = self.parse_expression()?;
1734 self.expect_token(&Token::RightParen)?;
1735 Ok(expr)
1736 }
1737 _ => Err(ParseError::UnexpectedToken(format!(
1738 "{:?}",
1739 self.current_token
1740 ))),
1741 }
1742 }
1743
1744 fn parse_condition(&mut self) -> Result<Condition, ParseError> {
1745 let left = self.parse_expression()?;
1746
1747 let op = match &self.current_token {
1748 Token::Eq => ComparisonOp::Eq,
1749 Token::Ne => ComparisonOp::Ne,
1750 Token::Lt => ComparisonOp::Lt,
1751 Token::Le => ComparisonOp::Le,
1752 Token::Gt => ComparisonOp::Gt,
1753 Token::Ge => ComparisonOp::Ge,
1754 _ => {
1755 return Err(ParseError::ExpectedToken {
1756 expected: "comparison operator".into(),
1757 found: format!("{:?}", self.current_token),
1758 })
1759 }
1760 };
1761 self.advance()?;
1762
1763 let right = self.parse_expression()?;
1764
1765 Ok(Condition { left, op, right })
1766 }
1767}
1768
1769pub fn parse_qasm3(input: &str) -> Result<QasmProgram, ParseError> {
1771 let mut parser = QasmParser::new(input)?;
1772 parser.parse_program()
1773}
1774
1775#[cfg(test)]
1776mod tests {
1777 use super::*;
1778
1779 #[test]
1780 fn test_parse_simple_circuit() {
1781 let input = r#"
1782OPENQASM 3.0;
1783include "stdgates.inc";
1784
1785qubit[2] q;
1786bit[2] c;
1787
1788h q[0];
1789cx q[0], q[1];
1790measure q -> c;
1791"#;
1792
1793 let result = parse_qasm3(input);
1794 assert!(result.is_ok());
1795
1796 let program = result.expect("parse_qasm3 should succeed for valid input");
1797 assert_eq!(program.version, "3.0");
1798 assert_eq!(program.includes, vec!["stdgates.inc"]);
1799 assert_eq!(program.declarations.len(), 2);
1800 assert_eq!(program.statements.len(), 3);
1801 }
1802
1803 #[test]
1804 fn test_parse_gate_definition() {
1805 let input = r"
1806OPENQASM 3.0;
1807
1808gate mygate(theta) q {
1809 rx(theta) q;
1810 ry(theta/2) q;
1811}
1812
1813qubit q;
1814mygate(pi/4) q;
1815";
1816
1817 let result = parse_qasm3(input);
1818 assert!(result.is_ok());
1819 }
1820
1821 #[test]
1822 fn test_const_register_size() {
1823 use super::super::ast::Declaration;
1824
1825 let input = r#"
1826OPENQASM 3.0;
1827const n = 5;
1828qubit[n] q;
1829bit[n] c;
1830"#;
1831 let program = parse_qasm3(input).expect("parse_qasm3 should succeed");
1832
1833 let mut q_size = None;
1834 let mut c_size = None;
1835 for decl in &program.declarations {
1836 match decl {
1837 Declaration::QuantumRegister(reg) => q_size = Some(reg.size),
1838 Declaration::ClassicalRegister(reg) => c_size = Some(reg.size),
1839 _ => {}
1840 }
1841 }
1842 assert_eq!(q_size, Some(5));
1844 assert_eq!(c_size, Some(5));
1845 }
1846
1847 #[test]
1848 fn test_const_register_size_arithmetic() {
1849 use super::super::ast::Declaration;
1850
1851 let input = r#"
1852OPENQASM 3.0;
1853const n = 2 + 3;
1854qubit[n] q;
1855"#;
1856 let program = parse_qasm3(input).expect("parse_qasm3 should succeed");
1857 let size = program.declarations.iter().find_map(|d| match d {
1858 Declaration::QuantumRegister(reg) => Some(reg.size),
1859 _ => None,
1860 });
1861 assert_eq!(size, Some(5));
1862 }
1863
1864 #[test]
1865 fn test_undefined_const_register_size_errors() {
1866 let input = r#"
1867OPENQASM 3.0;
1868qubit[undefined_n] q;
1869"#;
1870 assert!(parse_qasm3(input).is_err());
1872 }
1873}