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
}
};