diff --git a/include/staq/output/json.hpp b/include/staq/output/json.hpp index 82e3f0ff..b0656ae5 100644 --- a/include/staq/output/json.hpp +++ b/include/staq/output/json.hpp @@ -70,6 +70,7 @@ class JSONOutputter final : public Visitor { j["cargs"] = {arg1.json_val(), arg2.json_val(), arg3.json_val()}; json_.push_back(j); } + void visit(CNOTGate& gd) override { json j; j["type"] = "Gate"; @@ -78,7 +79,9 @@ class JSONOutputter final : public Visitor { gd.tgt().accept(arg1); j["name"] = "CNOTGate"; j["qargs"] = {arg0.json_val(), arg1.json_val()}; + json_.push_back(j); } + void visit(BarrierGate& gd) override { using namespace qasmtools::ast; json j; @@ -90,7 +93,9 @@ class JSONOutputter final : public Visitor { va.accept(jva); j["qargs"].push_back(jva.json_val()); }); + json_.push_back(j); } + void visit(DeclaredGate& gd) override { using namespace qasmtools::ast; json j; @@ -108,6 +113,7 @@ class JSONOutputter final : public Visitor { va.accept(jva); j["cargs"].push_back(jva.json_val()); }); + json_.push_back(j); } void visit(AncillaDecl& ad) override { @@ -204,55 +210,6 @@ class JSONOutputter final : public Visitor { json_.push_back(j); } - // void visit(qasmtools::ast::Gate& g) override { - // using namespace qasmtools::ast; - // json j; - // - // j["type"] = "Gate"; - // if (UGate* gd = dynamic_cast(&g)) { - // JSONOutputter arg0, arg1, arg2, arg3; - // gd->arg().accept(arg0); - // gd->arg().accept(arg1); - // gd->arg().accept(arg2); - // gd->arg().accept(arg3); - // j["name"] = "UGate"; - // j["qargs"] = {arg0.json_val()}; - // j["cargs"] = {arg1.json_val(), arg2.json_val(), arg3.json_val()}; - // } else if (CNOTGate* gd = dynamic_cast(&g)) { - // //(typeid(g) == typeid(CNOTGate)) { - // JSONOutputter arg0, arg1; - // gd->ctrl().accept(arg0); - // gd->tgt().accept(arg1); - // j["name"] = "CNOTGate"; - // j["qargs"] = {arg0.json_val(), arg1.json_val()}; - // } else if (BarrierGate* gd = dynamic_cast(&g)) { - // j["name"] = "BarrierGate"; - // j["qargs"] = {}; - // gd->foreach_arg([&j](VarAccess& va) { - // JSONOutputter jva; - // va.accept(jva); - // j["qargs"].push_back(jva.json_val()); - // }); - // } else if (DeclaredGate* gd = dynamic_cast(&g)) { - // j["name"] = gd->name(); - // j["qargs"] = {}; - // j["cargs"] = {}; - // gd->foreach_qarg([&j](VarAccess& va) { - // JSONOutputter jva; - // va.accept(jva); - // j["qargs"].push_back(jva.json_val()); - // }); - // gd->foreach_carg([&j](Expr& va) { - // JSONOutputter jva; - // va.accept(jva); - // j["cargs"].push_back(jva.json_val()); - // }); - // } else { - // throw ""; - // } - // json_.push_back(j); - // } - void visit(GateDecl& gd) override { using namespace qasmtools::ast; json j; diff --git a/src/tools/json.cpp b/src/tools/json.cpp index 4f8b2a79..33d972bf 100644 --- a/src/tools/json.cpp +++ b/src/tools/json.cpp @@ -1,5 +1,6 @@ #include "staq/output/json.hpp" #include +#include #include #include #include @@ -8,234 +9,28 @@ #include "qasmtools/ast/var.hpp" #include "qasmtools/parser/parser.hpp" -// using json = nlohmann::json; -// -// /* Forward declarations */ -// // [x] class VarAccess; -// // [x] class BExpr,UExpr,PiExpr,IntExpr,RealExpr,VarExpr; -// // [ ] class MeasureStmt,ResetStmt,IfStmt, -// // [x] class UGate,CNOTGate,BarrierGate,DeclaredGate, -// // [ ] class GateDecl,OracleDecl,RegisterDecl,AncillaDecl; -// // [ ] class Program; -// -// json jsonify(qasmtools::ast::VarAccess&); -// json jsonify(qasmtools::ast::Expr&); -// json jsonify(qasmtools::ast::Gate&); -// json jsonify(qasmtools::ast::GateDecl&); -// json jsonify(qasmtools::ast::Stmt&); -// json jsonify(qasmtools::ast::MeasureStmt&); -// json jsonify(qasmtools::ast::ResetStmt&); -// json jsonify(qasmtools::ast::OracleDecl&); -// json jsonify(qasmtools::ast::RegisterDecl&); -// json jsonify(qasmtools::ast::AncillaDecl&); -// json jsonify(qasmtools::ast::IfStmt&); -// json jsonify(qasmtools::ast::Program&); -// -// json jsonify(qasmtools::ast::AncillaDecl& ad) { -// json j; -// j["type"] = "AncillaDecl"; -// j["name"] = ad.id(); -// j["size"] = ad.size(); -// j["is_dirty"] = (ad.is_dirty() ? 1 : 0); -// return j; -// } -// -// json jsonify(qasmtools::ast::RegisterDecl& rd) { -// json j; -// j["type"] = "RegisterDecl"; -// j["name"] = rd.id(); -// j["is_quantum"] = (rd.is_quantum() ? 1 : 0); -// j["size"] = rd.size(); -// return j; -// } -// -// json jsonify(qasmtools::ast::OracleDecl& od) { -// // TODO: verify that this is doing what it needs to do -// json j; -// j["type"] = "OracleDecl"; -// j["name"] = od.fname(); -// j["params"] = od.params(); -// return j; -// } -// -// json jsonify(qasmtools::ast::IfStmt& ist) { -// // TODO: Improve this later. -// json j; -// std::stringstream in; -// ist.pretty_print(in, false); -// j["type"] = "IfStmt"; -// j["name"] = "If"; -// j["body"] = in.str(); -// return j; -// } -// -// json jsonify(qasmtools::ast::ResetStmt& rst) { -// json j; -// j["type"] = "ResetStmt"; -// j["name"] = "Reset"; -// j["qarg"] = jsonify(rst.arg()); -// return j; -// } -// -// json jsonify(qasmtools::ast::MeasureStmt& mst) { -// json j; -// j["type"] = "MeasureStmt"; -// j["name"] = "Measurement"; -// j["qarg"] = jsonify(mst.q_arg()); -// j["carg"] = jsonify(mst.c_arg()); -// return j; -// } -// -// json jsonify(qasmtools::ast::VarAccess& va) { -// json j; -// j["type"] = "VarAccess"; -// j["name"] = "qubit"; -// j["symbol"] = va.var(); -// j["offset"] = {}; -// if (va.offset().has_value()) { -// j["offset"].push_back(va.offset().value()); -// } -// return j; -// } -// -// json jsonify(qasmtools::ast::Expr& expr) { -// json j; -// std::stringstream in; -// expr.pretty_print(in); -// auto ev = expr.constant_eval(); -// j["type"] = "Expr"; -// j["expr"] = in.str(); -// j["val"] = {}; -// if (ev.has_value()) { -// j["val"].push_back(ev.value()); -// } -// return j; -// } -// -// json jsonify(qasmtools::ast::Gate& g) { -// using namespace qasmtools::ast; -// json j; -// j["type"] = "Gate"; -// if (UGate* gd = dynamic_cast(&g)) { -// j["name"] = "UGate"; -// j["qargs"] = {jsonify(gd->arg())}; -// j["cargs"] = {jsonify(gd->theta()), jsonify(gd->phi()), -// jsonify(gd->lambda())}; -// } else if (CNOTGate* gd = dynamic_cast(&g)) { -// j["name"] = "CNOTGate"; -// j["qargs"] = {jsonify(gd->ctrl()), jsonify(gd->tgt())}; -// } else if (BarrierGate* gd = dynamic_cast(&g)) { -// j["name"] = "BarrierGate"; -// j["qargs"] = {}; -// gd->foreach_arg( -// [&j](VarAccess& va) { j["qargs"].push_back(jsonify(va)); }); -// } else if (DeclaredGate* gd = dynamic_cast(&g)) { -// j["name"] = gd->name(); -// j["qargs"] = {}; -// j["cargs"] = {}; -// gd->foreach_qarg( -// [&j](VarAccess& va) { j["qargs"].push_back(jsonify(va)); }); -// gd->foreach_carg([&j](Expr& va) { j["cargs"].push_back(jsonify(va)); -// }); -// } else { -// throw ""; -// } -// return j; -// } -// -// json jsonify(qasmtools::ast::GateDecl& gd) { -// using namespace qasmtools::ast; -// json j; -// j["type"] = "GateDecl"; -// j["name"] = gd.id(); -// j["q_params"] = gd.q_params(); -// j["c_params"] = gd.c_params(); -// j["body"] = {}; // process the body of a GateDecl; -// gd.foreach_stmt([&j](Stmt& st) { j["body"].push_back(jsonify(st)); }); -// return j; -// } -// -// json jsonify(qasmtools::ast::Stmt& st) { -// using namespace qasmtools::ast; -// if (GateDecl* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else if (Gate* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else if (Gate* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else if (MeasureStmt* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else if (ResetStmt* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else if (OracleDecl* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else if (RegisterDecl* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else if (AncillaDecl* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else if (IfStmt* gd = dynamic_cast(&st)) { -// return jsonify(*gd); -// } else { -// throw ""; -// } -// } -// -// json jsonify(qasmtools::ast::Program& p) { -// using namespace qasmtools::ast; -// json j; -// p.foreach_stmt([&](Stmt& st) { j.push_back(jsonify(st)); }); -// return j; -// } - int main(int argc, char** argv) { - // using namespace staq; - using qasmtools::parser::parse_file; - - if (argc == 1) { - std::cout << "Usage: staq [PASSES/OPTIONS] FILE.qasm\n" - << "Run with --help for more information.\n"; - return 0; - } - std::string input_qasm; + using qasmtools::parser::parse_stdin; + std::string filename; - CLI::App app{"staq -- A full-stack quantum processing toolkit"}; - app.allow_extras(); - - app.add_option("FILE.qasm", input_qasm, "OpenQASM circuit") - ->required() - ->check(CLI::ExistingFile); + CLI::App app{"QASM to JSON converter"}; + app.add_option("-o,--output", filename, "Output to a file"); CLI11_PARSE(app, argc, argv); - try { - auto prog = parse_file(input_qasm); // Default std_include=true - if (!prog) { - // This case might not be reached if parse_file throws on error, - // but good to keep for parsers that might return nullptr. - std::cerr << "Error: failed to parse \"" << input_qasm - << "\" (parser returned null).\n"; - return 1; - } - - // was working before: - // json jsonified = jsonify(*prog); - // std::cout << jsonified.dump() << std::endl; - + auto prog = parse_stdin(); + if (prog) { staq::output::JSONOutputter jo; prog->accept(jo); - std::cout << jo.json_val().dump() << std::endl; - return 0; - } catch (const qasmtools::parser::ParseError& e) { - std::cerr << "ParseError: " << e.what() << std::endl; - std::cerr - << "Parsing failed. The error messages above this one (if any) " - "from the parser provide details about the location of the " - "syntax error(s) in the QASM file." - << std::endl; - return 1; - } catch (const std::exception& e) { - std::cerr << "An unexpected error occurred: " << e.what() << std::endl; + if (filename.empty()) { + std::cout << jo.json_val().dump() << std::endl; + } else { + std::fstream fout(filename); + fout << jo.json_val().dump() << std::endl; + fout.close(); + } + } else { + std::cerr << "Error: failed to parse " << std::endl; return 1; } - return 0; }