parser.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include <sstream>
  2. #include "parser.h"
  3. #include "utils.h"
  4. namespace json {
  5. std::string bad_near(const std::string &type, const unsigned int &pos) {
  6. std::ostringstream err;
  7. err << "bad type of '" << type << "' near position [" << pos << ']';
  8. return err.str();
  9. }
  10. std::string bad_near(const char &c, const unsigned int &pos) {
  11. std::ostringstream err;
  12. err << "bad character '" << c << "' near position [" << pos << ']';
  13. return err.str();
  14. }
  15. char Parser::next_real() {
  16. while (std::isspace(_str[_idx])) _idx++;
  17. return _str[_idx];
  18. }
  19. bool Parser::is_str_end(unsigned const &pos) {
  20. unsigned front = pos;
  21. while (_str[front] == '\\') front--;
  22. return (pos - front) % 2 == 0;
  23. }
  24. Value Parser::_parse() {
  25. char next = next_real();
  26. switch (next) {
  27. case 'n':
  28. return parse_null();
  29. case 't':
  30. case 'f':
  31. return parse_bool();
  32. case '-':
  33. case '0':
  34. case '1':
  35. case '2':
  36. case '3':
  37. case '4':
  38. case '5':
  39. case '6':
  40. case '7':
  41. case '8':
  42. case '9':
  43. return parse_number();
  44. case '"':
  45. return parse_string();
  46. case '[':
  47. return parse_list();
  48. case '{':
  49. return parse_dict();
  50. default:
  51. throw std::logic_error(bad_near(_str[_idx], _idx));
  52. }
  53. }
  54. Value Parser::parse_null() {
  55. if (_str.compare(_idx, 4, "null") == 0) {
  56. _idx += 4;
  57. return {};
  58. }
  59. throw std::logic_error(bad_near("null", _idx));
  60. }
  61. Value Parser::parse_bool() {
  62. if (_str.compare(_idx, 4, "true") == 0) {
  63. _idx += 4;
  64. return Value(true);
  65. }
  66. if (_str.compare(_idx, 5, "false") == 0) {
  67. _idx += 5;
  68. return Value(false);
  69. }
  70. throw std::logic_error(bad_near("bool", _idx));
  71. }
  72. Value Parser::parse_number() {
  73. unsigned start = _idx;
  74. if (_str[_idx] == '-') _idx++;
  75. if (std::isdigit(_str[_idx])) {
  76. while (std::isdigit(_str[_idx])) _idx++;
  77. // decimal
  78. if (_str[_idx] == '.') {
  79. _idx++;
  80. if (std::isdigit(_str[_idx])) {
  81. while (std::isdigit(_str[_idx])) _idx++;
  82. return Value(std::strtod(_str.c_str() + start, nullptr));
  83. } else throw std::logic_error(bad_near("number", _idx));
  84. }
  85. if (_str[_idx] != '.')
  86. return Value(std::strtol(_str.c_str() + start, nullptr, 10));
  87. } else throw std::logic_error(bad_near("number", _idx));
  88. // 不会到这里
  89. return {};
  90. }
  91. Value Parser::parse_string() {
  92. unsigned start = ++_idx;
  93. auto end = _str.find('"', _idx);
  94. if (end != std::string::npos) {
  95. // 可能是 \" 而不是真正的字符串结尾
  96. while (true) {
  97. if (is_str_end(end - 1)) break;
  98. end = _str.find('"', end + 1);
  99. if (end == std::string::npos) throw std::logic_error(bad_near("string", _idx));
  100. }
  101. _idx = end + 1;
  102. return Value(_str.substr(start, end - start));
  103. }
  104. throw std::logic_error(bad_near("string", _idx));
  105. }
  106. Value Parser::parse_list() {
  107. std::vector<Value> list;
  108. _idx++;
  109. char c;
  110. while (true) {
  111. c = next_real();
  112. if (c == ',') _idx++;
  113. else if (c == ']') {
  114. _idx++;
  115. return Value(list);
  116. } else list.push_back(_parse());
  117. }
  118. }
  119. Value Parser::parse_dict() {
  120. std::map<std::string, Value> dict;
  121. _idx++;
  122. char c;
  123. string_type key;
  124. while (true) {
  125. c = next_real();
  126. if (c == '"') {
  127. key = parse_string().value<string_type>();
  128. if (next_real() == ':') {
  129. _idx++;
  130. dict[key] = _parse();
  131. } else throw std::logic_error(bad_near("dict", _idx));
  132. } else if (c == ',') _idx++;
  133. else if (c == '}') {
  134. _idx++;
  135. return Value(dict);
  136. } else throw std::logic_error(bad_near("dict", _idx));
  137. }
  138. }
  139. Parser::Parser() {
  140. _str = "";
  141. _idx = 0;
  142. }
  143. Value Parser::parse(const std::string &str) {
  144. _str = hm::trim(str);
  145. auto max = _str.size() - 1;
  146. if (max < 0) throw std::logic_error("blank string");
  147. if (!((_str[0] == '{' && _str[max] == '}') || (_str[0] == '[' && _str[max] == ']')))
  148. throw std::logic_error("bad json string");
  149. _idx = 0;
  150. return _parse();
  151. }
  152. }