34 #ifndef QASM_PARSER_H_ 35 #define QASM_PARSER_H_ 46 Preprocessor& pp_lexer_;
49 bool supress_errors_ =
false;
50 Token current_token_ = Token();
60 Parser(Preprocessor& pp_lexer) : pp_lexer_(pp_lexer) {}
67 std::unique_ptr<QCircuit> parse() {
69 auto result = parse_program();
71 throw exception::ParseError(
"qpp::qasm::Parser::parse()");
74 return result.to_QCircuit();
83 void consume_token(
bool reset =
false) {
84 current_token_ = pp_lexer_.next_token();
86 supress_errors_ =
false;
99 Token expect_and_consume_token(Token::Kind expected) {
100 if (current_token_.is_not(expected)) {
102 if (!supress_errors_) {
103 std::cerr << current_token_.location();
104 std::cerr <<
": expected " << expected;
105 std::cerr <<
" but got " << current_token_.kind() <<
"\n";
107 supress_errors_ =
true;
109 return current_token_;
112 auto return_token = current_token_;
126 Token consume_until(Token::Kind expected) {
127 while (current_token_.is_not(expected) &&
128 current_token_.is_not(Token::Kind::eof)) {
130 if (!supress_errors_) {
131 std::cerr << current_token_.location();
132 std::cerr <<
": expected " << expected;
133 std::cerr <<
" but got " << current_token_.kind() <<
"\n";
135 supress_errors_ =
true;
140 auto return_token = current_token_;
154 bool try_and_consume_token(Token::Kind expected) {
155 if (current_token_.is_not(expected)) {
177 QASM parse_program() {
178 std::vector<StatementPtr> ret;
184 while (!current_token_.is(Token::Kind::eof)) {
185 switch (current_token_.kind()) {
187 case Token::Kind::kw_creg:
188 ret.emplace_back(parse_reg_decl(
false));
190 case Token::Kind::kw_qreg:
191 ret.emplace_back(parse_reg_decl(
true));
194 case Token::Kind::kw_gate:
195 ret.emplace_back(parse_gate_decl());
198 case Token::Kind::kw_opaque:
199 ret.emplace_back(parse_opaque_decl());
203 case Token::Kind::identifier:
204 case Token::Kind::kw_cx:
205 case Token::Kind::kw_measure:
206 case Token::Kind::kw_reset:
207 case Token::Kind::kw_u:
208 ret.emplace_back(parse_qop());
211 case Token::Kind::kw_barrier:
212 ret.emplace_back(parse_barrier());
215 case Token::Kind::kw_if:
216 ret.emplace_back(parse_if());
221 if (!supress_errors_) {
222 std::cerr << current_token_.location();
223 std::cerr <<
": expected a declaration or statement";
224 std::cerr <<
" but got " << current_token_.kind()
227 supress_errors_ =
true;
230 consume_until(Token::Kind::semicolon);
235 return QASM(bits_, qubits_, std::move(ret));
243 void parse_header() {
245 expect_and_consume_token(Token::Kind::kw_openqasm);
246 expect_and_consume_token(Token::Kind::real);
247 consume_until(Token::Kind::semicolon);
259 StatementPtr parse_reg_decl(
bool quantum) {
260 auto loc = current_token_.location();
263 auto identifier = expect_and_consume_token(Token::Kind::identifier);
264 expect_and_consume_token(Token::Kind::l_square);
265 auto size = expect_and_consume_token(Token::Kind::nninteger);
266 expect_and_consume_token(Token::Kind::r_square);
267 consume_until(Token::Kind::semicolon);
269 quantum ? qubits_ += (int) size : bits_ += (
int) size;
270 return StatementPtr(
new RegisterDecl(loc, identifier, quantum, size));
283 StatementPtr parse_gate_decl() {
284 auto loc = current_token_.location();
287 auto identifier = expect_and_consume_token(Token::Kind::identifier);
289 std::vector<ident> c_params;
290 if (try_and_consume_token(Token::Kind::l_paren)) {
291 c_params = parse_idlist();
292 expect_and_consume_token(Token::Kind::r_paren);
295 auto q_params = parse_idlist();
297 expect_and_consume_token(Token::Kind::l_brace);
298 std::vector<GatePtr> body;
299 if (!try_and_consume_token(Token::Kind::r_brace)) {
300 body = parse_goplist();
301 expect_and_consume_token(Token::Kind::r_brace);
304 return StatementPtr(
new GateDecl(loc, identifier,
false, c_params,
305 q_params, std::move(body)));
318 StatementPtr parse_opaque_decl() {
319 auto loc = current_token_.location();
322 auto identifier = expect_and_consume_token(Token::Kind::identifier);
324 std::vector<ident> c_params;
325 if (try_and_consume_token(Token::Kind::l_paren)) {
326 c_params = parse_idlist();
327 expect_and_consume_token(Token::Kind::r_paren);
330 auto q_params = parse_idlist();
333 new GateDecl(loc, identifier,
true, c_params, q_params, {}));
345 std::vector<GatePtr> parse_goplist() {
346 std::vector<GatePtr> ret;
347 bool finished =
false;
350 switch (current_token_.kind()) {
351 case Token::Kind::kw_cx:
352 case Token::Kind::kw_u:
353 case Token::Kind::identifier:
354 case Token::Kind::kw_barrier:
355 ret.emplace_back(parse_gop());
377 StatementPtr parse_qop() {
378 switch (current_token_.kind()) {
379 case Token::Kind::kw_cx:
380 case Token::Kind::kw_u:
381 case Token::Kind::identifier:
382 return StatementPtr(parse_gop());
384 case Token::Kind::kw_measure:
385 return parse_measure();
387 case Token::Kind::kw_reset:
388 return parse_reset();
392 if (!supress_errors_) {
393 std::cerr << current_token_.location();
394 std::cerr <<
": expected a quantum operation, but got ";
395 std::cerr << current_token_.kind() <<
"\n";
397 supress_errors_ =
true;
417 GatePtr parse_gop() {
418 switch (current_token_.kind()) {
419 case Token::Kind::kw_u:
420 return parse_unitary();
422 case Token::Kind::kw_cx:
425 case Token::Kind::identifier:
426 return parse_gate_statement();
428 case Token::Kind::kw_barrier:
429 return parse_barrier();
433 if (!supress_errors_) {
434 std::cerr << current_token_.location();
435 std::cerr <<
": expected a gate operation but got ";
436 std::cerr << current_token_.kind() <<
"\n";
438 supress_errors_ =
true;
454 std::vector<ident> parse_idlist() {
455 std::vector<ident> ret;
459 auto identifier = expect_and_consume_token(Token::Kind::identifier);
460 ret.push_back(identifier);
461 if (!try_and_consume_token(Token::Kind::comma)) {
478 Varinfo parse_argument() {
479 auto loc = current_token_.location();
481 auto id = expect_and_consume_token(Token::Kind::identifier);
482 if (try_and_consume_token(Token::Kind::l_square)) {
483 auto offset = expect_and_consume_token(Token::Kind::nninteger);
484 expect_and_consume_token(Token::Kind::r_square);
486 return Varinfo(loc,
id, offset);
489 return Varinfo(loc,
id);
501 std::vector<Varinfo> parse_anylist() {
502 std::vector<Varinfo> ret;
506 auto arg = parse_argument();
508 if (!try_and_consume_token(Token::Kind::comma)) {
525 std::vector<ExprPtr> parse_explist() {
527 std::vector<ExprPtr> ret;
530 auto exp = parse_exp();
531 ret.push_back(std::move(exp));
532 if (!try_and_consume_token(Token::Kind::comma)) {
554 ExprPtr parse_exp(
int min_precedence = 1) {
555 auto loc = current_token_.location();
557 auto lexp = parse_atom();
559 auto next_min_precedence = min_precedence;
561 switch (current_token_.kind()) {
562 case Token::Kind::plus:
563 if (min_precedence > 1) {
566 next_min_precedence = 2;
569 case Token::Kind::minus:
570 if (min_precedence > 1) {
573 next_min_precedence = 2;
576 case Token::Kind::star:
577 if (min_precedence > 2) {
580 next_min_precedence = 3;
583 case Token::Kind::slash:
584 if (min_precedence > 2) {
587 next_min_precedence = 3;
590 case Token::Kind::caret:
591 if (min_precedence > 3) {
594 next_min_precedence = 4;
601 auto bop = parse_binaryop();
602 auto rexp = parse_exp(next_min_precedence);
604 ExprPtr(
new BExpr(loc, std::move(lexp), bop, std::move(rexp)));
616 ExprPtr parse_atom() {
617 auto loc = current_token_.location();
619 switch (current_token_.kind()) {
620 case Token::Kind::l_paren: {
622 auto exp = parse_exp();
623 expect_and_consume_token(Token::Kind::r_paren);
627 case Token::Kind::minus: {
629 auto exp = parse_exp();
630 return ExprPtr(
new UExpr(loc, UnaryOp::Neg, std::move(exp)));
633 case Token::Kind::identifier: {
634 auto identifier = current_token_;
636 return ExprPtr(
new VarExpr(loc, identifier));
638 case Token::Kind::nninteger: {
639 auto integer = current_token_;
641 return ExprPtr(
new IntExpr(loc, integer));
643 case Token::Kind::kw_pi:
645 return ExprPtr(
new PiExpr(loc));
646 case Token::Kind::real: {
647 auto real = current_token_;
649 return ExprPtr(
new RealExpr(loc, real));
652 case Token::Kind::kw_sin:
653 case Token::Kind::kw_cos:
654 case Token::Kind::kw_tan:
655 case Token::Kind::kw_exp:
656 case Token::Kind::kw_ln:
657 case Token::Kind::kw_sqrt: {
658 auto op = parse_unaryop();
659 expect_and_consume_token(Token::Kind::l_paren);
660 auto exp = parse_exp();
661 expect_and_consume_token(Token::Kind::r_paren);
662 return ExprPtr(
new UExpr(loc, op, std::move(exp)));
667 if (!supress_errors_) {
668 std::cerr << current_token_.location();
669 std::cerr <<
": expected an atomic expression but got ";
670 std::cerr << current_token_.kind() <<
"\n";
672 supress_errors_ =
true;
685 BinaryOp parse_binaryop() {
686 switch (current_token_.kind()) {
687 case Token::Kind::plus:
689 return BinaryOp::Plus;
690 case Token::Kind::minus:
692 return BinaryOp::Minus;
693 case Token::Kind::star:
695 return BinaryOp::Times;
696 case Token::Kind::slash:
698 return BinaryOp::Divide;
699 case Token::Kind::caret:
701 return BinaryOp::Pow;
704 if (!supress_errors_) {
705 std::cerr << current_token_.location();
706 std::cerr <<
": expected a binary operator but got ";
707 std::cerr << current_token_.kind() <<
"\n";
709 supress_errors_ =
true;
712 return BinaryOp::Plus;
722 UnaryOp parse_unaryop() {
723 switch (current_token_.kind()) {
724 case Token::Kind::kw_sin:
727 case Token::Kind::kw_cos:
730 case Token::Kind::kw_tan:
733 case Token::Kind::kw_exp:
736 case Token::Kind::kw_ln:
739 case Token::Kind::kw_sqrt:
741 return UnaryOp::Sqrt;
744 if (!supress_errors_) {
745 std::cerr << current_token_.location();
746 std::cerr <<
": expected a unary operator but got ";
747 std::cerr << current_token_.kind() <<
"\n";
749 supress_errors_ =
true;
763 GatePtr parse_cnot() {
764 auto loc = current_token_.location();
766 expect_and_consume_token(Token::Kind::kw_cx);
767 auto ctrl = parse_argument();
768 expect_and_consume_token(Token::Kind::comma);
769 auto tgt = parse_argument();
770 consume_until(Token::Kind::semicolon);
772 return GatePtr(
new CNOTGate(loc, ctrl, tgt));
782 GatePtr parse_unitary() {
783 auto loc = current_token_.location();
785 expect_and_consume_token(Token::Kind::kw_u);
786 expect_and_consume_token(Token::Kind::l_paren);
787 auto theta = parse_exp();
788 expect_and_consume_token(Token::Kind::comma);
789 auto phi = parse_exp();
790 expect_and_consume_token(Token::Kind::comma);
791 auto lambda = parse_exp();
792 expect_and_consume_token(Token::Kind::r_paren);
793 auto arg = parse_argument();
794 consume_until(Token::Kind::semicolon);
796 return GatePtr(
new UGate(loc, std::move(theta), std::move(phi),
797 std::move(lambda), arg));
808 GatePtr parse_gate_statement() {
809 auto loc = current_token_.location();
811 auto id = expect_and_consume_token(Token::Kind::identifier);
812 std::vector<ExprPtr> c_args;
813 if (try_and_consume_token(Token::Kind::l_paren)) {
814 c_args = parse_explist();
815 expect_and_consume_token(Token::Kind::r_paren);
818 auto q_args = parse_anylist();
819 consume_until(Token::Kind::semicolon);
821 return GatePtr(
new DeclaredGate(loc,
id, std::move(c_args), q_args));
831 StatementPtr parse_measure() {
832 auto loc = current_token_.location();
834 expect_and_consume_token(Token::Kind::kw_measure);
835 auto q_arg = parse_argument();
836 expect_and_consume_token(Token::Kind::arrow);
837 auto c_arg = parse_argument();
838 consume_until(Token::Kind::semicolon);
840 return StatementPtr(
new MeasureStatement(loc, q_arg, c_arg));
850 StatementPtr parse_reset() {
851 auto loc = current_token_.location();
853 expect_and_consume_token(Token::Kind::kw_reset);
854 auto arg = parse_argument();
855 consume_until(Token::Kind::semicolon);
857 return StatementPtr(
new ResetStatement(loc, arg));
867 GatePtr parse_barrier() {
868 auto loc = current_token_.location();
870 expect_and_consume_token(Token::Kind::kw_barrier);
871 auto args = parse_anylist();
872 consume_until(Token::Kind::semicolon);
874 return GatePtr(
new BarrierGate(loc, args));
884 StatementPtr parse_if() {
885 auto loc = current_token_.location();
887 expect_and_consume_token(Token::Kind::kw_if);
888 expect_and_consume_token(Token::Kind::l_paren);
889 auto identifier = expect_and_consume_token(Token::Kind::identifier);
890 expect_and_consume_token(Token::Kind::equalequal);
891 auto integer = expect_and_consume_token(Token::Kind::nninteger);
892 expect_and_consume_token(Token::Kind::r_paren);
893 auto op = parse_qop();
896 new IfStatement(loc, identifier, integer, std::move(op)));
Quantum++ main namespace.
Definition: circuits.h:35