#include "json_parser.hpp" #include #include #include #include #include namespace { using namespace Lgs::Json; namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace classic = boost::spirit::classic; Lgs::Json::NullT makeNull(...) { return Lgs::Json::NullT(); } struct MakeMember { typedef void result_type; template result_type operator()(Arg1& arg1, Ctx& ctx, bool& b) const { using namespace boost::fusion; auto m0 = boost::fusion::at_c<0>(arg1); auto m1 = boost::fusion::at_c<1>(arg1); ctx.attributes.car.first = m0; ctx.attributes.car.second = m1 ? *m1 : NullT(); } }; template struct JsonGrammar : public qi::grammar { JsonGrammar() : JsonGrammar::base_type(json, "json") { using qi::double_; using qi::lexeme; using qi::char_; using qi::int_; using qi::on_error; using namespace qi::labels; null = qi::lit("null")[makeNull]; non_empty_string = lexeme['"' > (char_ - '"') > *(char_ - '"') > '"']; string = lexeme['"' >> *(char_ - '"') >> '"']; number = int_; member = (non_empty_string > ':' > (value | ""))[MakeMember()]; array = '[' >> value % ',' >> ']'; object = '{' > member % ','> '}'; value = array | object | number | string | qi::bool_ | null; json = array | object; json.name("json"); object.name("object"); non_empty_string.name("member name"); } qi::rule null; qi::rule non_empty_string; qi::rule string; qi::rule number; qi::rule json; qi::rule array; qi::rule value; qi::rule object; qi::rule(), ascii::space_type> member; }; template void parseJson(BaseIterator baseFirst, BaseIterator baseLast, Value& v) { using qi::phrase_parse; using ascii::space; typedef classic::position_iterator2 Iterator; typedef JsonGrammar G; Iterator first(baseFirst, baseLast), last; G g; try { phrase_parse(first, last, g, space, v); } catch(const qi::expectation_failure& e) { const classic::file_position_base& pos = e.first.get_position(); throw ParseError(pos.line, pos.column, e.first.get_currentline()); } } struct PrinterVisitor : boost::static_visitor { PrinterVisitor(std::ostream& os) : os_(os) {} void operator()(const Array& arr) const { os_ << "["; for (auto it = arr.begin(); it != arr.end(); ++it) { if (it != arr.begin()) { os_ << ","; } boost::apply_visitor(PrinterVisitor(os_), *it); } os_ << "]"; } void operator()(const Object& obj) const { os_ << "{"; for (auto it = obj.begin(); it != obj.end(); ++it) { if (it != obj.begin()) { os_ << ","; } std::string name = it->first; os_ << '"' << name << '"' << " : "; boost::apply_visitor(PrinterVisitor(os_), it->second); } os_ << "}"; } void operator()(bool b) const { os_ << std::boolalpha << b; } void operator()(int i) const { os_ << i; } void operator()(const std::string& str) const { os_ << '"' << str << '"'; } void operator()(NullT) const { os_ << "null"; } std::ostream& os_; }; } namespace Lgs { namespace Json { ParseError::ParseError(int lineNo, int column, const std::string& line) : lineNo_(lineNo), column_(column), line_(line) { } void parseJson(std::istream& istr, Value& v) { namespace classic = boost::spirit::classic; typedef std::istreambuf_iterator IstreamIterator; typedef boost::spirit::multi_pass ForwardIterator; IstreamIterator istrIt(istr); ForwardIterator first = boost::spirit::make_default_multi_pass(istrIt); ForwardIterator last; ::parseJson(first, last, v); } void parseJson(const std::string& str, Value& v) { ::parseJson(str.begin(), str.end(), v); } void printJson(std::ostream& ostr, const Value& v) { boost::apply_visitor(PrinterVisitor(ostr), v); } std::string printJson(const Value& v) { std::ostringstream ostr; printJson(ostr, v); return ostr.str(); } } }