#define BOOST_SPIRIT_DEBUG 1 #define PHOENIX_LIMIT 6 #define BOOST_SPIRIT_CLOSURE_LIMIT 6 #include #include #include #include #include #include #include #include #include #include using namespace boost; using namespace boost::spirit; //======== my data struture template class ToString { public: static const T Convert (T val) { return val; } }; template class Data { public: Data () {} Data (const T val) : m_value (val) {} virtual ~Data(){} const T get_Value (void) const { return m_value; } virtual const std::string get_Name (void) const = 0; const std::string get_Label (void) { std::stringstream out; out << this->get_Name() << std::endl << "Value: " << ToString::Convert(m_value) << std::endl; return out.str(); } private: T m_value; }; class Unsigned_Int_Data : public Data { public: Unsigned_Int_Data (uint32_t val) : Data (val) {} ~Unsigned_Int_Data(){} virtual const std::string get_Name (void) const { return "Unsigned Int Data"; } }; class Float_Data : public Data { public: Float_Data (float val) : Data (val) {} ~Float_Data(){} virtual const std::string get_Name (void) const { return "Float Data"; } }; class Data_Factory { private: static boost::shared_ptr m_factory; public: boost::shared_ptr< Data > get_Uint (uint32_t val) { return boost::shared_ptr< Data > ( new Unsigned_Int_Data(val)); } boost::shared_ptr< Data > get_Float (float val) { return boost::shared_ptr< Data > ( new Float_Data (val) ); } static boost::shared_ptr get_Factory () { if (m_factory.get() == 0) { m_factory.reset (new Data_Factory()); } return m_factory; } private: Data_Factory () {} }; boost::shared_ptr Data_Factory::m_factory; class Data_Graph { public: typedef property< vertex_index_t, uint32_t, property< vertex_name_t, boost::shared_ptr > > VertexProperty; typedef adjacency_list // VertexProperties Graph_Type; typedef graph_traits::vertex_descriptor Vertex; typedef graph_traits::edge_descriptor Edge; typedef std::map IdVertexMap; Data_Graph () {} void add_Source ( boost::shared_ptr obj_ptr ) { bool found; IdVertexMap::iterator pos; Vertex node; boost::tie (pos, found) = m_index.insert (std::make_pair(obj_ptr->get_ID(), node)); if (found) { // Insertion was successful // Make a new vertex and return handle to 'node' node = add_vertex(m_graph); // Get list of Datas boost::property_map::type clist = get(vertex_name, m_graph); // Assign component to vertex position clist[node] = obj_ptr; // Add vertex handle to map position pos->second = node; // Get list of indexes boost::property_map::type ilist = get(vertex_index, m_graph); ilist[node] = obj_ptr->get_ID(); } else { std::cerr << "ERROR: Duplicate source found. Skipping Data" << std::endl; return; } } void add_Data (uint32_t parent_id, boost::shared_ptr obj_ptr) { IdVertexMap::iterator pos; IdVertexMap::iterator cpos; Vertex child_node; bool cfound; pos = m_index.find (parent_id); if (pos != m_index.end()) { boost::tie (cpos, cfound) = m_index.insert (std::make_pair(obj_ptr->get_ID(), child_node)); if (cfound) { // Insertion was successful // Make a new vertex and return handle to 'node' child_node = add_vertex(m_graph); // Get list of Datas boost::property_map::type clist = get(vertex_name,m_graph); // Assign component to vertex position clist[child_node] = obj_ptr; // Add vertex handle to map position cpos->second = child_node; // Get list of indexes boost::property_map::type ilist = get(vertex_index, m_graph); ilist[child_node] = obj_ptr->get_ID(); } else { std::cerr << "ERROR: Duplicate child found. Skipping Data #" << obj_ptr->get_ID() << std::endl << obj_ptr->get_Name() << std::endl; return; } } else { std::cerr << "ERROR: Cannot find parent. Skipping adding component #" << obj_ptr->get_ID() << std::endl << obj_ptr->get_Name() << std::endl; return; } // Add edge from parent to child Edge link; if (! (add_edge ( pos->second, child_node, m_graph).second)) { std::cerr << "ERROR: Duplicate edge exists from " << parent_id << " to " << obj_ptr->get_ID() << std::endl; return; } } const Graph_Type& get_Graph () { return m_graph; } boost::shared_ptr get_Data (const Vertex& node) { // Get list of Datas boost::property_map::type clist = get(vertex_name, m_graph); // Assign component to vertex position return clist[node]; } private: Graph_Type m_graph; IdVertexMap m_index; }; class Data_Writer { public: Data_Writer (const boost::shared_ptr g) : m_graph (g) {} std::string operator[](const Data_Graph::Vertex& v) const { boost::shared_ptr obj_ptr = m_graph->get_Data(v); return obj_ptr->get_Label(); } private: const boost::shared_ptr m_graph; }; class Graph_Grammar : public grammar { public: Graph_Grammar (boost::shared_ptr data) : m_data (data) {} struct string_closure : closure { member1 text; }; struct source_closure : closure { member1 node_id; member2 name; }; struct node_closure : closure { member1 child_id; member2 name; member3 parent_id; }; static boost::shared_ptr get_Data (const uint32_t id, const std::string name, const uint32_t = 0) { boost::shared_ptr factory = Data_Factory::get_Factory(); boost::shared_ptr obj_ptr; if (name.compare("uint") == 0) { obj_ptr = factory->get_Uint (id); } else if (name.compare("float") == 0) { obj_ptr = factory->get_Float (id); } return obj_ptr; } struct construct_Data_ { template struct result { typedef void type; }; template void operator()(Data& data, const ID& id, const Name& name, const Parent_ID& pid) const { boost::shared_ptr obj_ptr = Graph_Grammar::get_Data (id,name,pid); data->add_Data ( pid, obj_ptr ); } }; phoenix::function construct_Data; struct construct_Source_ { template struct result { typedef void type; }; template void operator()(Data& data, const ID& id, const Name& name) const { boost::shared_ptr obj_ptr = Graph_Grammar::get_Data (id,name); data->add_Source ( obj_ptr ); } }; phoenix::function construct_Source; template struct definition { rule graph; rule source_node; rule node; rule name; definition(Graph_Grammar const& self) { graph = source_node >> while_p (~epsilon_p(end_p)) [ node ]; source_node = as_lower_d[str_p("source")] >> ch_p('{') >> uint_p [source_node.node_id = phoenix::arg1] >> ch_p(',') >> name [source_node.name = phoenix::arg1] >> str_p("};") [ self.construct_Source (self.m_data, source_node.node_id, source_node.name) ]; // Read this and add a semantic action to create a // File_Data_Source_Config object. Add to m_data. node = as_lower_d[str_p("node")] >> ch_p('{') >> uint_p [node.child_id = phoenix::arg1] >> ch_p(',') >> name [node.name = phoenix::arg1] >> ch_p (',') >> uint_p[node.parent_id = phoenix::arg1] >> str_p("};") [self.construct_Data (self.m_data, node.child_id, node.name, node.parent_id)]; name = ch_p('"') >> (alnum_p >> *(alnum_p | ch_p('_'))) [ name.text = phoenix::construct_(phoenix::arg1, phoenix::arg2) ] >> ch_p('"'); BOOST_SPIRIT_DEBUG_NODE(graph); BOOST_SPIRIT_DEBUG_NODE(source_node); BOOST_SPIRIT_DEBUG_NODE(node); BOOST_SPIRIT_DEBUG_NODE(name); } rule const& start() const { return graph; } }; mutable boost::shared_ptr m_data; }; template bool parse_i (const std::string & file, const Grammar& grammar) { boost::spirit::file_iterator<> first(file); if (!first) { std::cerr << "Configuration_Parser: Unable to open file '" << file << "'!" << std::endl; return false; } const boost::spirit::file_iterator<> last = first.make_end(); typedef typename boost::spirit::position_iterator < boost::spirit::file_iterator<> > iterator_t; const parse_info info = boost::spirit::parse(iterator_t(first, last, file), iterator_t(), grammar, boost::spirit::space_p | boost::spirit::comment_p("#")); if (!info.full) { const boost::spirit::file_position fp = info.stop.get_position(); std::cerr << "Parsing of file '" << fp.file << "' failed at line " << fp.line << ", column " << fp.column << ".\n"; } return info.full; } int main () { // read Graph2 and all internal properties boost::shared_ptr m_data (new Data_Graph()); Graph_Grammar grmr (m_data); std::ofstream file ("test.txt"); file << "source{0,\"uint\"};" << std::endl; file << "node{1,\"float\",0};" << std::endl; file << "node{2,\"uint\",0};" << std::endl; file << "node{3,\"uint\",1};" << std::endl; file.close(); if (!parse_i("test.txt", grmr)) { std::cerr << "Invalid configuration file format." << std::endl; } std::ofstream gfile ("test.dot"); write_graphviz (gfile, m_data->get_Graph(), make_label_writer(Data_Writer(m_data))); return 0; }