#include #include "parser.h" #include "utils.h" namespace json { std::string bad_near(const std::string &type, const unsigned int &pos) { std::ostringstream err; err << "bad type of '" << type << "' near position [" << pos << ']'; return err.str(); } std::string bad_near(const char &c, const unsigned int &pos) { std::ostringstream err; err << "bad character '" << c << "' near position [" << pos << ']'; return err.str(); } char Parser::next_real() { while (std::isspace(_str[_idx])) _idx++; return _str[_idx]; } bool Parser::is_str_end(unsigned const &pos) { unsigned front = pos; while (_str[front] == '\\') front--; return (pos - front) % 2 == 0; } Value Parser::_parse() { char next = next_real(); switch (next) { case 'n': return parse_null(); case 't': case 'f': return parse_bool(); case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return parse_number(); case '"': return parse_string(); case '[': return parse_list(); case '{': return parse_dict(); default: throw std::logic_error(bad_near(_str[_idx], _idx)); } } Value Parser::parse_null() { if (_str.compare(_idx, 4, "null") == 0) { _idx += 4; return {}; } throw std::logic_error(bad_near("null", _idx)); } Value Parser::parse_bool() { if (_str.compare(_idx, 4, "true") == 0) { _idx += 4; return Value(true); } if (_str.compare(_idx, 5, "false") == 0) { _idx += 5; return Value(false); } throw std::logic_error(bad_near("bool", _idx)); } Value Parser::parse_number() { unsigned start = _idx; if (_str[_idx] == '-') _idx++; if (std::isdigit(_str[_idx])) { while (std::isdigit(_str[_idx])) _idx++; // decimal if (_str[_idx] == '.') { _idx++; if (std::isdigit(_str[_idx])) { while (std::isdigit(_str[_idx])) _idx++; return Value(std::strtod(_str.c_str() + start, nullptr)); } else throw std::logic_error(bad_near("number", _idx)); } if (_str[_idx] != '.') return Value(std::strtol(_str.c_str() + start, nullptr, 10)); } else throw std::logic_error(bad_near("number", _idx)); // 不会到这里 return {}; } Value Parser::parse_string() { unsigned start = ++_idx; auto end = _str.find('"', _idx); if (end != std::string::npos) { // 可能是 \" 而不是真正的字符串结尾 while (true) { if (is_str_end(end - 1)) break; end = _str.find('"', end + 1); if (end == std::string::npos) throw std::logic_error(bad_near("string", _idx)); } _idx = end + 1; return Value(_str.substr(start, end - start)); } throw std::logic_error(bad_near("string", _idx)); } Value Parser::parse_list() { std::vector list; _idx++; char c; while (true) { c = next_real(); if (c == ',') _idx++; else if (c == ']') { _idx++; return Value(list); } else list.push_back(_parse()); } } Value Parser::parse_dict() { std::map dict; _idx++; char c; string_type key; while (true) { c = next_real(); if (c == '"') { key = parse_string().value(); if (next_real() == ':') { _idx++; dict[key] = _parse(); } else throw std::logic_error(bad_near("dict", _idx)); } else if (c == ',') _idx++; else if (c == '}') { _idx++; return Value(dict); } else throw std::logic_error(bad_near("dict", _idx)); } } Parser::Parser() { _str = ""; _idx = 0; } Value Parser::parse(const std::string &str) { _str = hm::trim(str); auto max = _str.size() - 1; if (max < 0) throw std::logic_error("blank string"); if (!((_str[0] == '{' && _str[max] == '}') || (_str[0] == '[' && _str[max] == ']'))) throw std::logic_error("bad json string"); _idx = 0; return _parse(); } }