#include #include #include #include #include #include #include using namespace boost::spirit; using namespace boost; using namespace std; typedef function2 grammar_cb; struct record_grammar:public grammar{ record_grammar( grammar_cb &property_name, grammar_cb &property_value, grammar_cb &end_property, grammar_cb &record_type, grammar_cb &record_name, grammar_cb &end_record): property_name(property_name), property_value(property_value), end_property(end_property), record_type(record_type), record_name(record_name), end_record(end_record){ } template struct definition{ rule identifier; rule string_literal; rule prop_decl; rule prop_list; rule record_list; rule record; definition(const record_grammar &self){ identifier = lexeme_d[ alpha_p >> *(alnum_p | ch_p('_') ) ]; string_literal = lexeme_d[ ch_p('"') >> *( (anychar_p - ch_p('"') ) | str_p("\\\"") ) >> ch_p('"') ]; prop_decl = ( identifier[self.property_name] >> ch_p('=') >> string_literal[self.property_value] )[self.end_property]; prop_list = prop_decl >> *(ch_p(',') >> prop_decl); record_list = record >> *(ch_p(',') >> record); record = ( identifier[self.record_type] >> identifier[self.record_name] >> ch_p('{') >> !( ( prop_list >> !(ch_p(',') >> record_list) ) | record_list ) >> ch_p('}') )[self.end_record]; }; rule const& start(){return record_list;} }; grammar_cb &property_name; grammar_cb &property_value; grammar_cb &end_property; grammar_cb &record_type; grammar_cb &record_name; grammar_cb &end_record; }; struct property_info{ string name, value; }; struct record_info{ string type; string name; vector properties; vector sub_records; }; class document{ public: document(){ record_stack.push(record_info()); } parse_info<> parse(const std::string &data){ grammar_cb property_name_f(bind(&document::property_name, this, _1,_2)); grammar_cb property_value_f(bind(&document::property_value, this, _1,_2)); grammar_cb end_property_f(bind(&document::end_property, this, _1,_2)); grammar_cb record_type_f(bind(&document::record_type, this, _1,_2)); grammar_cb record_name_f(bind(&document::record_name, this, _1,_2)); grammar_cb end_record_f(bind(&document::end_record, this, _1, _2)); record_grammar g( property_name_f, property_value_f, end_property_f, record_type_f, record_name_f, end_record_f); parse_info<> info = boost::spirit::parse(data.c_str(), g >> eps_p, space_p); return info; } const record_info & result(){ return record_stack.top(); } void print(){ for(vector::const_iterator it = record_stack.top().sub_records.begin(); it != record_stack.top().sub_records.end(); it++){ print("", *it); } } private: void print(const string &prefix, const record_info &r){ cout << prefix << "." << r.name << endl; cout << "\ttype:" << r.type << endl; cout << "\tproperties(" << r.properties.size() << "):" << endl; for(vector::const_iterator it = r.properties.begin(); it != r.properties.end(); it++){ cout << "\t\t" << it->name << "=" << it->value << endl; } for(vector::const_iterator it = r.sub_records.begin(); it != r.sub_records.end(); it++){ print(prefix + "." + r.name, *it); } } void property_name(const char *start, const char *end){ current_property.name = string(start, end); } void property_value(const char *start, const char *end){ current_property.value = string(start, end); } void end_property(const char *start, const char *end){ record_stack.top().properties.push_back(current_property); } void record_type(const char *start, const char *end){ record_stack.push(record_info()); record_stack.top().type = string(start, end); } void record_name(const char *start, const char *end){ record_stack.top().name = string(start, end); } void end_record(const char *start, const char *end){ record_info top = record_stack.top(); record_stack.pop(); record_stack.top().sub_records.push_back(top); } stack record_stack; property_info current_property; }; int main(){ string input; string temp; while(getline(cin, temp)){ input += temp; } document d; parse_info<> info = d.parse(input); if(!info.full){ cout << "Error found at location: " << info.stop << endl; }else{ d.print(); } }