#pragma once #include #include #include #include #include #include #include #include #include #define LOC_ARG const Location &location namespace plsm { namespace ast { class Location { public: Location(const std::string &file, std::pair start, std::pair end) : file(file), start(start), end(end) {} const std::string file; const std::pair start, end; static Location json() { return Location("", {-1, -1}, {-1, -1}); }; }; class ASTNode { public: ASTNode(LOC_ARG) : location(location) {} virtual ~ASTNode() = default; const Location location; virtual boost::json::value toJson() = 0; virtual std::string toJsonString() { return boost::json::serialize(toJson()); } static std::unique_ptr fromJson(boost::json::value json); virtual bool isExpr() { return false; } virtual bool isStmt() { return false; } virtual bool isType() { return false; } protected: template static inline boost::json::value getJsonProperty(boost::json::value json, std::string property) { boost::json::value prop; try { if (!json.as_object().contains(property)) throw std::exception(); prop = json.as_object().at(property); } catch (...) { std::cout << boost::json::serialize(json) << std::endl; throw std::runtime_error("missing property '" + property + "' in " + typeid(CurrNode).name() + "::fromJson"); } return prop; } template static inline T getJsonValue(boost::json::value json, std::string property) { auto prop = getJsonProperty(json, property); try { return boost::json::value_to(prop); } catch (...) { throw std::runtime_error("invalid value for property '" + property + "' in " + typeid(CurrNode).name() + "::fromJson"); } } template static inline auto fromJsonProperty(boost::json::value json, std::string property) { return SubNode::fromJson(getJsonProperty(json, property)); } template static inline auto fromJsonVector(boost::json::value json, std::string property) { auto arr = getJsonProperty(json, property).as_array(); std::vector> result; for (auto &el : arr) { result.push_back(SubNode::fromJson(el)); } return result; } }; class Expr : public ASTNode { public: Expr(LOC_ARG) : ASTNode(location) {} static std::unique_ptr fromJson(boost::json::value json); virtual bool isExpr() override { return true; } }; class Stmt : public ASTNode { public: Stmt(LOC_ARG) : ASTNode(location) {} static std::unique_ptr fromJson(boost::json::value json); virtual bool isStmt() override { return true; } }; class Type : public ASTNode { public: Type(LOC_ARG) : ASTNode(location) {} static std::unique_ptr fromJson(boost::json::value json); virtual bool isType() override { return true; } }; } // namespace ast } // namespace plsm