Skip to main content

quantrs2_circuit/qasm/
parser.rs

1//! Parser for `OpenQASM` 3.0
2
3use 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/// Parser error types
13#[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/// Token types for lexing
41#[derive(Debug, Clone, PartialEq)]
42enum Token {
43    // Keywords
44    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    // Identifiers and literals
66    Identifier(String),
67    Integer(i64),
68    Float(f64),
69    String(String),
70
71    // Operators
72    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    // Delimiters
97    LeftParen,
98    RightParen,
99    LeftBracket,
100    RightBracket,
101    LeftBrace,
102    RightBrace,
103    Semicolon,
104    Comma,
105    Colon,
106    Dot,
107
108    // Special
109    Eof,
110}
111
112/// Lexer for tokenizing QASM input
113struct 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                // Skip line comment
147                while self.current.is_some() && self.current != Some('\n') {
148                    self.advance();
149                }
150            } else if ch == '/' && self.peek() == Some('*') {
151                // Skip block comment
152                self.advance(); // skip '/'
153                self.advance(); // skip '*'
154                while self.current.is_some() {
155                    if self.current == Some('*') && self.peek() == Some('/') {
156                        self.advance(); // skip '*'
157                        self.advance(); // skip '/'
158                        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(); // skip opening quote
223
224        while let Some(ch) = self.current {
225            if ch == '"' {
226                self.advance(); // skip closing quote
227                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
433/// QASM parser
434pub struct QasmParser<'a> {
435    lexer: Lexer<'a>,
436    current_token: Token,
437    /// Symbol table for tracking declarations
438    symbols: HashMap<String, SymbolType>,
439}
440
441#[derive(Debug, Clone)]
442enum SymbolType {
443    QuantumRegister(usize),
444    ClassicalRegister(usize),
445    Gate(Vec<String>, Vec<String>), // params, qubits
446    /// A `const` declaration carrying its evaluated numeric value, so later
447    /// references (e.g. `qubit[n] q;`) can resolve the size.
448    Constant(f64),
449    Variable,
450}
451
452/// Evaluate a binary operator over two `f64` constant operands.
453///
454/// Comparison and logical operators return `1.0`/`0.0`; bitwise and shift
455/// operators coerce their operands to `i64`.
456fn 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
482/// Evaluate a unary operator over an `f64` constant operand.
483fn 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
506/// `true` if `expr` calls a function or indexes a value anywhere in its tree.
507///
508/// Used to decide whether a `const` declaration that failed to fold to a
509/// numeric value at parse time is deferrable to the validator's semantic
510/// checks (function arity / existence, non-array indexing) rather than a
511/// hard parse error.
512fn 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
523/// Evaluate a math function call in a constant expression.
524fn 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    /// Create a new parser for the given input
578    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    /// Parse a complete QASM program
590    pub fn parse_program(&mut self) -> Result<QasmProgram, ParseError> {
591        // Parse version declaration
592        self.expect_token(&Token::OpenQasm)?;
593        let version = self.parse_version()?;
594        self.expect_token(&Token::Semicolon)?;
595
596        // Parse includes
597        let mut includes = Vec::new();
598        while self.current_token == Token::Include {
599            includes.push(self.parse_include()?);
600        }
601
602        // Parse declarations and statements
603        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                // Check if next token is a dot followed by a number
656                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            // qubit[size] name format
699            self.advance()?; // consume [
700
701            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                    // Register size given as a named `const`; resolve it.
709                    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            // qubit name format (single qubit)
737            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        // Add to symbol table
754        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            // bit[size] name format
765            self.advance()?; // consume [
766
767            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                    // Register size given as a named `const`; resolve it.
775                    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            // bit name format (single bit)
803            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        // Add to symbol table
820        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        // Parse parameters
841        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        // Parse qubit arguments
868        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        // Parse body
889        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        // Add to symbol table
899        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        // Evaluate the constant now so later references (e.g. register sizes)
933        // can resolve it. Constants must be expressible from previously-defined
934        // constants and literals only.
935        //
936        // Division of labor with the validator: the parser's job is to accept
937        // every *syntactically* valid program and build an AST; deeper
938        // semantic checks that require a full symbol/type table -- function
939        // arity, unknown function names, indexing a non-array value -- belong
940        // to `QasmValidator` (see `validate_expression` /
941        // `builtin_function_return_type` in validator.rs), which already
942        // implements them faithfully. So when evaluation fails specifically
943        // because the expression calls a function or indexes something, we
944        // don't hard-fail the parse: we record the constant as non-numeric
945        // (deferring the semantic error to `validate_qasm3`) instead of
946        // duplicating (and risking disagreeing with) the validator's checks.
947        // A constant that is malformed in a way the validator does *not*
948        // re-check (e.g. referencing a genuinely undefined identifier) is
949        // still a hard parse error.
950        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    /// Resolve a named constant to a register size (a non-negative integer).
968    ///
969    /// Returns [`ParseError::UndefinedIdentifier`] if `name` was never declared
970    /// (or is not a `const`), and [`ParseError::TypeMismatch`] if its value is
971    /// not a finite non-negative integer.
972    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    /// Evaluate a constant expression to an `f64`.
991    ///
992    /// Supports numeric literals (including `pi`/`tau`/`euler`), references to
993    /// previously-declared `const`s, and the standard binary/unary operators and
994    /// math functions. Non-constant constructs (array indexing, unknown
995    /// identifiers/functions, string literals) yield a [`ParseError`].
996    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                // Could be gate application, assignment, or function call
1047                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    // Simplified implementations for brevity - full parser would implement all methods
1058
1059    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        // Parse first qubit -> classical pair
1066        qubits.push(self.parse_qubit_ref()?);
1067        self.expect_token(&Token::Arrow)?;
1068        targets.push(self.parse_classical_ref()?);
1069
1070        // Parse additional pairs
1071        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                // Function call or gate with parameters
1231                self.parse_gate_or_call(name)
1232            }
1233            Token::LeftBracket | Token::Identifier(_) => {
1234                // Gate application
1235                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                // Parse qubits
1245                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        // Parse modifiers
1266        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        // Parse gate name
1302        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        // Parse parameters if present
1314        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        // Parse qubits
1330        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        // Check if this is followed by qubits (gate) or semicolon (function call)
1366        match &self.current_token {
1367            Token::Identifier(_) | Token::LeftBracket => {
1368                // Gate with parameters
1369                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                // Function call
1390                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                // Slice
1427                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                // Single index
1447                self.expect_token(&Token::RightBracket)?;
1448                Ok(QubitRef::Single {
1449                    register,
1450                    index: start,
1451                })
1452            }
1453        } else {
1454            // Entire register
1455            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                // Slice
1487                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                // Single index
1507                self.expect_token(&Token::RightBracket)?;
1508                Ok(ClassicalRef::Single {
1509                    register,
1510                    index: start,
1511                })
1512            }
1513        } else {
1514            // Entire register
1515            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                    // Function call
1672                    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                // Check for special constants
1724                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
1769/// Parse a QASM 3.0 string into an AST
1770pub 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        // The named constant `n` must resolve to 5 — not the old hardcoded 4.
1843        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        // An unresolved constant must be a hard error, not a silent default.
1871        assert!(parse_qasm3(input).is_err());
1872    }
1873}