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