SHARE
TWEET

Untitled

a guest May 19th, 2017 41 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // WIP -- not done yet :)
  2.  
  3. #include <optional>
  4. #include <string_view>
  5. #include <unordered_map>
  6. #include <variant>
  7. #include <vector>
  8.  
  9. namespace json {
  10.  
  11. struct Wrapper;
  12. using Null = std::nullptr_t;
  13. using Bool = bool;
  14. using Number = double;
  15. using String = std::string_view;
  16. using Array = std::vector<Value>;
  17. using Object = std::unordered_map<String, Value>;
  18. using Value = std::variant<Bool, Number, String, Array, Object, Null>;
  19.  
  20. struct Wrapper {
  21.   operator Value& () { return v; }
  22.   operator const Value& () const { return v; }
  23. };
  24.  
  25. namespace detail {
  26.  
  27. std::optional<Object> parseObject() {
  28.   Object object;
  29.   if(!accept('{'))
  30.     return {};
  31.   if (expect('}'))
  32.     return object;
  33.   while (true) {
  34.     if (auto s = parseString(); s) {
  35.       if (!expect(':'))
  36.         return {};
  37.       if (auto v = parseValue(); v)
  38.         object.emplace(s, v);
  39.       else
  40.         return {};
  41.       if (expect(','))
  42.         continue;
  43.       if (expect('}')
  44.         return object;
  45.       return {};
  46.     }
  47.     return {};
  48.   }
  49. }
  50.  
  51. std::optional<Array> parseArray() {
  52.   Array array;
  53.   if (!accept('['))
  54.     return {};
  55.   if (expect(']'))
  56.     return array;
  57.   while (true) {
  58.     if (auto v = parseValue(); v) {
  59.       array.emplace_back(v);
  60.       if (expect(','))
  61.         continue;
  62.       if (expect(']'))
  63.         return array;
  64.       return {};
  65.     }
  66.     return {};
  67.   }
  68. }
  69.  
  70. std::optional<String> parseString() {
  71.   if (!accept('"'))
  72.     return {};
  73.   auto ptr = std::next(ctx.ptr());
  74.   unsigned length{0};
  75.   while (true) {
  76.     ctx.advance(1);
  77.     if (ctx.prev() != '\\' && ctx.curr() == '"')
  78.       return {ptr, length};
  79.     ++length;
  80.   }
  81.   return {};
  82. }
  83.  
  84. std::optional<Number> parseNumber() {
  85.   auto ptr = ctx.ptr();
  86.   accept('-');
  87.   if (!check(::isdigit))
  88.     return {};
  89.   while (check(::isdigit))
  90.     ;
  91.   if (accept('.')) {
  92.     if (!check(::isdigit))
  93.       return {};
  94.     while (check(::isdigit))
  95.       ;
  96.   }
  97.   if (accept('e') || accept('E')) {
  98.     accept('+') || accept('-');
  99.     if (!check(::isdigit))
  100.       return {};
  101.     while (check(::isdigit))
  102.       ;
  103.   }
  104.   String asString{ptr, ctx.ptr() - ptr};
  105.   return std::stod(asString);
  106. }
  107.  
  108. std::optional<Value> parseValue() {
  109.   if (accept("true"))
  110.     return bool{true};
  111.   if (accept("false"))
  112.     return bool{false};
  113.   if (accept("null"))
  114.     return nullptr;
  115.   if (auto n = parseNumber(); n)
  116.     return n;
  117.   if (auto s = parseString(); s)
  118.     return s;
  119.   if (auto o = parseObject(); o)
  120.     return o;
  121.   if (auto a = parseArray(); a)
  122.     return a;
  123.   return {};
  124. }
  125.  
  126. } // end namespace detail
  127.  
  128. std::optional<Object> parse() {
  129.   return detail::parseObject();
  130. }
  131.  
  132. } // end namespace json
RAW Paste Data
Top