openqasm 0.1.2

Parser and translator for OpenQASM 2.0
Documentation
use crate::ast::{Program, Decl, Stmt, Expr, Reg, Span, FileSpan, Symbol};
use super::Token;

grammar(file: usize);

extern {
    type Location = usize;
    type Error = FileSpan;

    enum Token {
        "OPENQASM 2.0" => Token::OPENQASM,
        "include" => Token::Include,
        "qreg" => Token::QReg,
        "creg" => Token::CReg,
        "gate" => Token::Gate,
        "opaque" => Token::Opaque,
        "measure" => Token::Measure,
        "reset" => Token::Reset,
        "barrier" => Token::Barrier,
        "if" => Token::If,
        "(" => Token::LParen,
        ")" => Token::RParen,
        "{" => Token::LBrace,
        "}" => Token::RBrace,
        "==" => Token::Equals,
        ";" => Token::Semicolon,
        "," => Token::Comma,
        "U" => Token::U,
        "CX" => Token::CX,
        "pi" => Token::Pi,
        "sin" => Token::Sin,
        "cos" => Token::Cos,
        "tan" => Token::Tan,
        "exp" => Token::Exp,
        "ln" => Token::Ln,
        "sqrt" => Token::Sqrt,
        "^" => Token::Pow,
        "*" => Token::Mul,
        "/" => Token::Div,
        "+" => Token::Add,
        "-" => Token::Sub,
        "[" => Token::LBracket,
        "]" => Token::RBracket,
        "->" => Token::Arrow,
        identifier => Token::Identifier(<Symbol>),
        integer => Token::Integer(<u64>),
        real => Token::Real(<f32>),
        string => Token::String(<Symbol>)
    }
}

pub(crate) TopLevel: Program = "OPENQASM 2.0" ";" <decls:Span<Decl>*> => Program { decls };

pub(crate) Included: Program = ("OPENQASM 2.0" ";")? <decls:Span<Decl>*> => Program { decls };

Decl: Decl = {
    "include" <filename:Span<String>> ";" => Decl::Include { file: filename },
    "qreg" <reg:Span<Reg>> ";" => Decl::QReg { reg },
    "creg" <reg:Span<Reg>> ";" => Decl::CReg { reg },
    "opaque" <name:Span<Ident>> <params:MaybeList<Span<Ident>>> <args:Sep<Span<Ident>, ",">> ";" 
        => Decl::Def { name, params, args, body: None },
    "gate" <name:Span<Ident>> <params:MaybeList<Span<Ident>>> <args:Sep<Span<Ident>, ",">> "{" 
        <body:Span<Stmt>*>
    "}" => Decl::Def { name, params, args, body: Some(body) },
    <Span<Stmt>> => Decl::Stmt(<>)
};

Stmt: Stmt = {
    "U" "(" <theta:Span<Expr>> "," <phi:Span<Expr>> "," <lambda:Span<Expr>> ")" <reg:Span<Reg>> ";" => 
        Stmt::U { theta, phi, lambda, reg},
    "CX" <copy:Span<Reg>> "," <xor:Span<Reg>> ";" => Stmt::CX { copy, xor },
    "measure" <from:Span<Reg>> "->" <to:Span<Reg>> ";" => Stmt::Measure { from, to },
    "reset" <reg:Span<Reg>> ";" => Stmt::Reset { reg },
    "barrier" <regs:Sep<Span<Reg>, ",">> ";" => Stmt::Barrier { regs },
    <name:Span<Ident>> <params:MaybeList<Span<Expr>>> <args:Sep<Span<Reg>, ",">> ";" => Stmt::Gate { name, params, args },
    "if" "(" <reg:Span<Reg>> "==" <val:Span<Int>> ")" <then:Span<Stmt>> => Stmt::Conditional { reg, val, then }
};

Expr: Expr = {
    <l:Span<Expr>> "+" <r:Span<ExprTerm>> => Expr::Add(l, r),
    <l:Span<Expr>> "-" <r:Span<ExprTerm>> => Expr::Sub(l, r),
    <ExprTerm>
};

ExprTerm: Expr = {
    <l:Span<ExprTerm>> "*" <r:Span<ExprFactor>> => Expr::Mul(l, r),
    <l:Span<ExprTerm>> "/" <r:Span<ExprFactor>> => Expr::Div(l, r),
    <ExprFactor>
};

ExprFactor: Expr = {
    "-" <Span<ExprFactor>> => Expr::Neg(<>),
    <l:Span<ExprAtom>> "^" <r:Span<ExprFactor>> => Expr::Pow(l, r),
    <ExprAtom>
};

ExprAtom: Expr = {
    "pi" => Expr::Pi,
    <Real> => Expr::Real(<>),
    <Int> => Expr::Int(<>),
    <Ident> => Expr::Var(<>),
    "sin" "(" <Span<Expr>> ")" => Expr::Sin(<>),
    "cos" "(" <Span<Expr>> ")" => Expr::Cos(<>),
    "tan" "(" <Span<Expr>> ")" => Expr::Tan(<>),
    "exp" "(" <Span<Expr>> ")" => Expr::Exp(<>),
    "ln" "(" <Span<Expr>> ")" => Expr::Ln(<>),
    "sqrt" "(" <Span<Expr>> ")" => Expr::Sqrt(<>),
    "(" <Expr> ")"
};

Reg: Reg = {
    <name:Ident> => Reg { name, index: None },
    <name:Ident> "[" <index:Int> "]" => Reg { name, index: Some(index) }
};

Ident: Symbol = <identifier>;
Int: u64 = <integer>;
Real: f32 = <real>;
String: Symbol = <string>;

MaybeList<T>: Vec<T> = {
    => Vec::new(),
    "(" <Sep<T, ",">> ")"
};

Span<T>: Span<T> = <left:@L> <inner:T> <right:@R> => Span { span: FileSpan { start: left, end: right, file }, inner: Box::new(inner) };

Sep<U, V>: Vec<U> = {
    => Vec::new(),
    <init:(<U> V)*> <tail:U> => {
        let mut init = init;
        init.push(tail);
        init
    }
};