// Based on the grammar found at:
// https://web.archive.org/web/20041213234742/http://www.graphviz.org/cvs/doc/info/lang.html
//
-// See documentation for this code at:
+// See documentation for this code at:
// http://www.boost.org/libs/graph/doc/read_graphviz.html
//
#define PHOENIX_LIMIT 6
#define BOOST_SPIRIT_CLOSURE_LIMIT 6
-
#include <boost/spirit/include/classic_multi_pass.hpp>
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/throw_exception.hpp>
-namespace phoenix {
+namespace phoenix
+{
// Workaround: std::map::operator[] uses a different return type than all
// other standard containers. Phoenix doesn't account for that.
-template <typename TK, typename T0, typename T1>
-struct binary_operator<index_op, std::map<TK,T0>, T1>
+template < typename TK, typename T0, typename T1 >
+struct binary_operator< index_op, std::map< TK, T0 >, T1 >
{
- typedef typename std::map<TK,T0>::mapped_type& result_type;
- static result_type eval(std::map<TK,T0>& container, T1 const& index)
- { return container[index]; }
+ typedef typename std::map< TK, T0 >::mapped_type& result_type;
+ static result_type eval(std::map< TK, T0 >& container, T1 const& index)
+ {
+ return container[index];
+ }
};
} // namespace phoenix
-namespace boost {
-namespace detail {
-namespace graph {
-
-
-/////////////////////////////////////////////////////////////////////////////
-// Application-specific type definitions
-/////////////////////////////////////////////////////////////////////////////
-
-typedef std::set<edge_t> edges_t;
-typedef std::set<node_t> nodes_t;
-typedef std::set<id_t> ids_t;
-typedef std::map<edge_t,ids_t> edge_map_t;
-typedef std::map<node_t,ids_t> node_map_t;
-typedef std::map<id_t,id_t> props_t;
-typedef std::map<id_t,props_t> subgraph_props_t;
-typedef boost::function2<void, id_t const&, id_t const&> actor_t;
-typedef std::vector<edge_t> edge_stack_t;
-typedef std::map<id_t,nodes_t> subgraph_nodes_t;
-typedef std::map<id_t,edges_t> subgraph_edges_t;
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-// Stack frames used by semantic actions
-/////////////////////////////////////////////////////////////////////////////
-struct id_closure : boost::spirit::classic::closure<id_closure, node_t> {
- member1 name;
-};
-
-
-struct node_id_closure : boost::spirit::classic::closure<node_id_closure, node_t> {
- member1 name;
-};
-
-struct attr_list_closure : boost::spirit::classic::closure<attr_list_closure, actor_t> {
- member1 prop_actor;
-};
-
-struct property_closure : boost::spirit::classic::closure<property_closure, id_t, id_t> {
- member1 key;
- member2 value;
-};
-
-struct data_stmt_closure : boost::spirit::classic::closure<data_stmt_closure,
- nodes_t,nodes_t,edge_stack_t,bool,node_t> {
- member1 sources;
- member2 dests;
- member3 edge_stack;
- member4 saw_node;
- member5 active_node;
-};
-
-struct subgraph_closure : boost::spirit::classic::closure<subgraph_closure,
- nodes_t, edges_t, node_t> {
- member1 nodes;
- member2 edges;
- member3 name;
-};
+namespace boost
+{
+namespace detail
+{
+ namespace graph
+ {
-/////////////////////////////////////////////////////////////////////////////
-// Grammar and Actions for the DOT Language
-/////////////////////////////////////////////////////////////////////////////
-
-// Grammar for a dot file.
-struct dot_grammar : public boost::spirit::classic::grammar<dot_grammar> {
- mutate_graph& graph_;
- explicit dot_grammar(mutate_graph& graph) : graph_(graph) { }
-
- template <class ScannerT>
- struct definition {
-
- definition(dot_grammar const& self) : self(self), subgraph_depth(0),
- keyword_p("0-9a-zA-Z_") {
- using namespace boost::spirit::classic;
- using namespace phoenix;
-
- // RG - Future Work
- // - Handle multi-line strings using \ line continuation
- // - Make keywords case insensitive
- ID
- = ( lexeme_d[((alpha_p | ch_p('_')) >> *(alnum_p | ch_p('_')))]
- | real_p
- | lexeme_d[confix_p('"', *c_escape_ch_p, '"')]
- | comment_nest_p('<', '>')
- )[ID.name = construct_<std::string>(arg1,arg2)]
- ;
-
- a_list
- = list_p( ID[(a_list.key = arg1),
- (a_list.value = "true")
- ]
- >> !( ch_p('=')
- >> ID[a_list.value = arg1])
- [phoenix::bind(&definition::call_prop_actor)
- (var(*this),a_list.key,a_list.value)],!ch_p(','));
-
- attr_list = +(ch_p('[') >> !a_list >> ch_p(']'));
-
- // RG - disregard port id's for now.
- port_location
- = (ch_p(':') >> ID)
- | (ch_p(':') >> ch_p('(') >> ID >> ch_p(',') >> ID >> ch_p(')'))
- ;
-
- port_angle = ch_p('@') >> ID;
-
- port
- = port_location >> (!port_angle)
- | port_angle >> (!port_location);
-
-
- node_id
- = ( ID[node_id.name = arg1] >> (!port) )
- [phoenix::bind(&definition::memoize_node)(var(*this))];
-
- graph_stmt
- = (ID[graph_stmt.key = arg1] >>
- ch_p('=') >>
- ID[graph_stmt.value = arg1])
- [phoenix::bind(&definition::call_graph_prop)
- (var(*this),graph_stmt.key,graph_stmt.value)]
- ; // Graph property.
-
- attr_stmt
- = (as_lower_d[keyword_p("graph")]
- >> attr_list(actor_t(phoenix::bind(&definition::default_graph_prop)
- (var(*this),arg1,arg2))))
- | (as_lower_d[keyword_p("node")]
- >> attr_list(actor_t(phoenix::bind(&definition::default_node_prop)
- (var(*this),arg1,arg2))))
- | (as_lower_d[keyword_p("edge")]
- >> attr_list(actor_t(phoenix::bind(&definition::default_edge_prop)
- (var(*this),arg1,arg2))))
- ;
-
- // edge_head is set depending on the graph type (directed/undirected)
- edgeop = ch_p('-') >> ch_p(boost::ref(edge_head));
-
- edgeRHS
- = +( edgeop[(data_stmt.sources = data_stmt.dests),
- (data_stmt.dests = construct_<nodes_t>())]
- >> ( subgraph[data_stmt.dests = arg1]
- | node_id[phoenix::bind(&definition::insert_node)
- (var(*this),data_stmt.dests,arg1)]
- )
- [phoenix::bind(&definition::activate_edge)
- (var(*this),data_stmt.sources,data_stmt.dests,
- var(edges), var(default_edge_props))]
- );
-
-
- // To avoid backtracking, edge, node, and subgraph statements are
- // processed as one nonterminal.
- data_stmt
- = ( subgraph[(data_stmt.dests = arg1),// will get moved in rhs
- (data_stmt.saw_node = false)]
- | node_id[(phoenix::bind(&definition::insert_node)
- (var(*this),data_stmt.dests,arg1)),
- (data_stmt.saw_node = true),
+ /////////////////////////////////////////////////////////////////////////////
+ // Application-specific type definitions
+ /////////////////////////////////////////////////////////////////////////////
+
+ typedef std::set< edge_t > edges_t;
+ typedef std::set< node_t > nodes_t;
+ typedef std::set< id_t > ids_t;
+ typedef std::map< edge_t, ids_t > edge_map_t;
+ typedef std::map< node_t, ids_t > node_map_t;
+ typedef std::map< id_t, id_t > props_t;
+ typedef std::map< id_t, props_t > subgraph_props_t;
+ typedef boost::function2< void, id_t const&, id_t const& > actor_t;
+ typedef std::vector< edge_t > edge_stack_t;
+ typedef std::map< id_t, nodes_t > subgraph_nodes_t;
+ typedef std::map< id_t, edges_t > subgraph_edges_t;
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Stack frames used by semantic actions
+ /////////////////////////////////////////////////////////////////////////////
+ struct id_closure
+ : boost::spirit::classic::closure< id_closure, node_t >
+ {
+ member1 name;
+ };
+
+ struct node_id_closure
+ : boost::spirit::classic::closure< node_id_closure, node_t >
+ {
+ member1 name;
+ };
+
+ struct attr_list_closure
+ : boost::spirit::classic::closure< attr_list_closure, actor_t >
+ {
+ member1 prop_actor;
+ };
+
+ struct property_closure
+ : boost::spirit::classic::closure< property_closure, id_t, id_t >
+ {
+ member1 key;
+ member2 value;
+ };
+
+ struct data_stmt_closure
+ : boost::spirit::classic::closure< data_stmt_closure, nodes_t, nodes_t,
+ edge_stack_t, bool, node_t >
+ {
+ member1 sources;
+ member2 dests;
+ member3 edge_stack;
+ member4 saw_node;
+ member5 active_node;
+ };
+
+ struct subgraph_closure
+ : boost::spirit::classic::closure< subgraph_closure, nodes_t, edges_t,
+ node_t >
+ {
+ member1 nodes;
+ member2 edges;
+ member3 name;
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Grammar and Actions for the DOT Language
+ /////////////////////////////////////////////////////////////////////////////
+
+ // Grammar for a dot file.
+ struct dot_grammar
+ : public boost::spirit::classic::grammar< dot_grammar >
+ {
+ mutate_graph& graph_;
+ explicit dot_grammar(mutate_graph& graph) : graph_(graph) {}
+
+ template < class ScannerT > struct definition
+ {
+
+ definition(dot_grammar const& self)
+ : self(self), subgraph_depth(0), keyword_p("0-9a-zA-Z_")
+ {
+ using namespace boost::spirit::classic;
+ using namespace phoenix;
+
+ // RG - Future Work
+ // - Handle multi-line strings using \ line continuation
+ // - Make keywords case insensitive
+ ID = (lexeme_d[(
+ (alpha_p | ch_p('_')) >> *(alnum_p | ch_p('_')))]
+ | real_p | lexeme_d[confix_p('"', *c_escape_ch_p, '"')]
+ | comment_nest_p('<', '>'))[ID.name
+ = construct_< std::string >(arg1, arg2)];
+
+ a_list = list_p(
+ ID[(a_list.key = arg1), (a_list.value = "true")] >> !(
+ ch_p('=') >> ID[a_list.value = arg1])[phoenix::bind(
+ &definition::call_prop_actor)(
+ var(*this), a_list.key, a_list.value)],
+ !ch_p(','));
+
+ attr_list = +(ch_p('[') >> !a_list >> ch_p(']'));
+
+ // RG - disregard port id's for now.
+ port_location = (ch_p(':') >> ID)
+ | (ch_p(':') >> ch_p('(') >> ID >> ch_p(',') >> ID
+ >> ch_p(')'));
+
+ port_angle = ch_p('@') >> ID;
+
+ port = port_location >> (!port_angle)
+ | port_angle >> (!port_location);
+
+ node_id
+ = (ID[node_id.name = arg1] >> (!port))[phoenix::bind(
+ &definition::memoize_node)(var(*this))];
+
+ graph_stmt = (ID[graph_stmt.key = arg1] >> ch_p('=')
+ >> ID[graph_stmt.value = arg1])[phoenix::bind(
+ &definition::call_graph_prop)(var(*this),
+ graph_stmt.key, graph_stmt.value)]; // Graph property.
+
+ attr_stmt
+ = (as_lower_d[keyword_p("graph")] >> attr_list(actor_t(
+ phoenix::bind(&definition::default_graph_prop)(
+ var(*this), arg1, arg2))))
+ | (as_lower_d[keyword_p("node")] >> attr_list(actor_t(
+ phoenix::bind(&definition::default_node_prop)(
+ var(*this), arg1, arg2))))
+ | (as_lower_d[keyword_p("edge")] >> attr_list(actor_t(
+ phoenix::bind(&definition::default_edge_prop)(
+ var(*this), arg1, arg2))));
+
+ // edge_head is set depending on the graph type
+ // (directed/undirected)
+ edgeop = ch_p('-') >> ch_p(boost::ref(edge_head));
+
+ edgeRHS = +(edgeop[(data_stmt.sources = data_stmt.dests),
+ (data_stmt.dests = construct_< nodes_t >())]
+ >> (subgraph[data_stmt.dests = arg1]
+ | node_id[phoenix::bind(&definition::insert_node)(
+ var(*this), data_stmt.dests, arg1)])
+ [phoenix::bind(&definition::activate_edge)(
+ var(*this), data_stmt.sources, data_stmt.dests,
+ var(edges), var(default_edge_props))]);
+
+ // To avoid backtracking, edge, node, and subgraph
+ // statements are processed as one nonterminal.
+ data_stmt
+ = (subgraph[(data_stmt.dests
+ = arg1), // will get moved in rhs
+ (data_stmt.saw_node = false)]
+ | node_id[(phoenix::bind(
+ &definition::insert_node)(
+ var(*this), data_stmt.dests, arg1)),
+ (data_stmt.saw_node = true),
#ifdef BOOST_GRAPH_DEBUG
- (std::cout << val("AcTive Node: ") << arg1 << "\n"),
+ (std::cout << val("AcTive Node: ") << arg1
+ << "\n"),
#endif // BOOST_GRAPH_DEBUG
- (data_stmt.active_node = arg1)]
- ) >> if_p(edgeRHS)[
- !attr_list(
- actor_t(phoenix::bind(&definition::edge_prop)
- (var(*this),arg1,arg2)))
- ].else_p[
- if_p(data_stmt.saw_node)[
- !attr_list(
- actor_t(phoenix::bind(&definition::node_prop)
- (var(*this),arg1,arg2)))
- ] // otherwise it's a subgraph, nothing more to do.
- ];
-
-
- stmt
- = graph_stmt
- | attr_stmt
- | data_stmt
- ;
-
- stmt_list = *( stmt >> !ch_p(';') );
-
- subgraph
- = !( as_lower_d[keyword_p("subgraph")]
- >> (!ID[(subgraph.name = arg1),
- (subgraph.nodes = (var(subgraph_nodes))[arg1]),
- (subgraph.edges = (var(subgraph_edges))[arg1])])
- )
- >> ch_p('{')[++var(subgraph_depth)]
- >> stmt_list
- >> ch_p('}')[--var(subgraph_depth)]
- [(var(subgraph_nodes))[subgraph.name] = subgraph.nodes]
- [(var(subgraph_edges))[subgraph.name] = subgraph.edges]
-
- | as_lower_d[keyword_p("subgraph")]
- >> ID[(subgraph.nodes = (var(subgraph_nodes))[arg1]),
- (subgraph.edges = (var(subgraph_edges))[arg1])]
- ;
-
- the_grammar
- = (!as_lower_d[keyword_p("strict")])
- >> ( as_lower_d[keyword_p("graph")][
- (var(edge_head) = '-'),
- (phoenix::bind(&definition::check_undirected)(var(*this)))]
- | as_lower_d[keyword_p("digraph")][
- (var(edge_head) = '>'),
- (phoenix::bind(&definition::check_directed)(var(*this)))]
- )
- >> (!ID) >> ch_p('{') >> stmt_list >> ch_p('}');
-
- } // definition()
-
- typedef boost::spirit::classic::rule<ScannerT> rule_t;
-
- rule_t const& start() const { return the_grammar; }
-
-
- //
- // Semantic actions
- //
-
- void check_undirected() {
- if(self.graph_.is_directed())
- boost::throw_exception(boost::undirected_graph_error());
- }
-
- void check_directed() {
- if(!self.graph_.is_directed())
- boost::throw_exception(boost::directed_graph_error());
- }
-
- void memoize_node() {
- id_t const& node = node_id.name();
- props_t& node_props = default_node_props;
-
- if(nodes.find(node) == nodes.end()) {
- nodes.insert(node);
- self.graph_.do_add_vertex(node);
-
- node_map.insert(std::make_pair(node,ids_t()));
+ (data_stmt.active_node = arg1)])
+ >> if_p(edgeRHS)[!attr_list(actor_t(phoenix::bind(
+ &definition::edge_prop)(
+ var(*this), arg1, arg2)))]
+ .else_p[if_p(data_stmt.saw_node)[!attr_list(
+ actor_t(phoenix::bind(
+ &definition::node_prop)(var(*this), arg1,
+ arg2)))] // otherwise it's a subgraph,
+ // nothing more to do.
+ ];
+
+ stmt = graph_stmt | attr_stmt | data_stmt;
+
+ stmt_list = *(stmt >> !ch_p(';'));
+
+ subgraph = !(as_lower_d[keyword_p("subgraph")]
+ >> (!ID[(subgraph.name = arg1),
+ (subgraph.nodes
+ = (var(subgraph_nodes))[arg1]),
+ (subgraph.edges
+ = (var(subgraph_edges))[arg1])]))
+ >> ch_p('{')[++var(subgraph_depth)] >> stmt_list
+ >> ch_p('}')[--var(subgraph_depth)]
+ [(var(subgraph_nodes))[subgraph.name]
+ = subgraph.nodes]
+ [(var(subgraph_edges))[subgraph.name]
+ = subgraph.edges]
+
+ | as_lower_d[keyword_p("subgraph")]
+ >> ID[(subgraph.nodes
+ = (var(subgraph_nodes))[arg1]),
+ (subgraph.edges = (var(subgraph_edges))[arg1])];
+
+ the_grammar = (!as_lower_d[keyword_p("strict")])
+ >> (as_lower_d[keyword_p(
+ "graph")][(var(edge_head) = '-'),
+ (phoenix::bind(&definition::check_undirected)(
+ var(*this)))]
+ | as_lower_d[keyword_p(
+ "digraph")][(var(edge_head) = '>'),
+ (phoenix::bind(&definition::check_directed)(
+ var(*this)))])
+ >> (!ID) >> ch_p('{') >> stmt_list >> ch_p('}');
+
+ } // definition()
+
+ typedef boost::spirit::classic::rule< ScannerT > rule_t;
+
+ rule_t const& start() const { return the_grammar; }
+
+ //
+ // Semantic actions
+ //
+
+ void check_undirected()
+ {
+ if (self.graph_.is_directed())
+ boost::throw_exception(boost::undirected_graph_error());
+ }
+
+ void check_directed()
+ {
+ if (!self.graph_.is_directed())
+ boost::throw_exception(boost::directed_graph_error());
+ }
+
+ void memoize_node()
+ {
+ id_t const& node = node_id.name();
+ props_t& node_props = default_node_props;
+
+ if (nodes.find(node) == nodes.end())
+ {
+ nodes.insert(node);
+ self.graph_.do_add_vertex(node);
+
+ node_map.insert(std::make_pair(node, ids_t()));
#ifdef BOOST_GRAPH_DEBUG
- std::cout << "Add new node " << node << std::endl;
+ std::cout << "Add new node " << node << std::endl;
#endif // BOOST_GRAPH_DEBUG
- // Set the default properties for this edge
- // RG: Here I would actually set the properties
- for(props_t::iterator i = node_props.begin();
- i != node_props.end(); ++i) {
- set_node_property(node,i->first,i->second);
- }
- if(subgraph_depth > 0) {
- subgraph.nodes().insert(node);
- // Set the subgraph's default properties as well
- props_t& props = subgraph_node_props[subgraph.name()];
- for(props_t::iterator i = props.begin(); i != props.end(); ++i) {
- set_node_property(node,i->first,i->second);
- }
- }
- } else {
+ // Set the default properties for this edge
+ // RG: Here I would actually set the properties
+ for (props_t::iterator i = node_props.begin();
+ i != node_props.end(); ++i)
+ {
+ set_node_property(node, i->first, i->second);
+ }
+ if (subgraph_depth > 0)
+ {
+ subgraph.nodes().insert(node);
+ // Set the subgraph's default properties as well
+ props_t& props
+ = subgraph_node_props[subgraph.name()];
+ for (props_t::iterator i = props.begin();
+ i != props.end(); ++i)
+ {
+ set_node_property(node, i->first, i->second);
+ }
+ }
+ }
+ else
+ {
#ifdef BOOST_GRAPH_DEBUG
- std::cout << "See node " << node << std::endl;
+ std::cout << "See node " << node << std::endl;
#endif // BOOST_GRAPH_DEBUG
- }
- }
-
- void activate_edge(nodes_t& sources, nodes_t& dests, edges_t& edges,
- props_t& edge_props) {
- edge_stack_t& edge_stack = data_stmt.edge_stack();
- for(nodes_t::iterator i = sources.begin(); i != sources.end(); ++i) {
- for(nodes_t::iterator j = dests.begin(); j != dests.end(); ++j) {
- // Create the edge and push onto the edge stack.
+ }
+ }
+
+ void activate_edge(nodes_t& sources, nodes_t& dests,
+ edges_t& edges, props_t& edge_props)
+ {
+ edge_stack_t& edge_stack = data_stmt.edge_stack();
+ for (nodes_t::iterator i = sources.begin();
+ i != sources.end(); ++i)
+ {
+ for (nodes_t::iterator j = dests.begin();
+ j != dests.end(); ++j)
+ {
+ // Create the edge and push onto the edge stack.
#ifdef BOOST_GRAPH_DEBUG
- std::cout << "Edge " << *i << " to " << *j << std::endl;
+ std::cout << "Edge " << *i << " to " << *j
+ << std::endl;
#endif // BOOST_GRAPH_DEBUG
- edge_t edge = edge_t::new_edge();
- edge_stack.push_back(edge);
- edges.insert(edge);
- edge_map.insert(std::make_pair(edge,ids_t()));
-
- // Add the real edge.
- self.graph_.do_add_edge(edge, *i, *j);
-
- // Set the default properties for this edge
- for(props_t::iterator k = edge_props.begin();
- k != edge_props.end(); ++k) {
- set_edge_property(edge,k->first,k->second);
- }
- if(subgraph_depth > 0) {
- subgraph.edges().insert(edge);
- // Set the subgraph's default properties as well
- props_t& props = subgraph_edge_props[subgraph.name()];
- for(props_t::iterator k = props.begin(); k != props.end(); ++k) {
- set_edge_property(edge,k->first,k->second);
- }
- }
- }
- }
- }
-
- // node_prop - Assign the property for the current active node.
- void node_prop(id_t const& key, id_t const& value) {
- node_t& active_object = data_stmt.active_node();
- set_node_property(active_object, key, value);
- }
-
- // edge_prop - Assign the property for the current active edges.
- void edge_prop(id_t const& key, id_t const& value) {
- edge_stack_t const& active_edges_ = data_stmt.edge_stack();
- for (edge_stack_t::const_iterator i = active_edges_.begin();
- i != active_edges_.end(); ++i) {
- set_edge_property(*i,key,value);
- }
- }
-
- // default_graph_prop - Store as a graph property.
- void default_graph_prop(id_t const& key, id_t const& value) {
+ edge_t edge = edge_t::new_edge();
+ edge_stack.push_back(edge);
+ edges.insert(edge);
+ edge_map.insert(std::make_pair(edge, ids_t()));
+
+ // Add the real edge.
+ self.graph_.do_add_edge(edge, *i, *j);
+
+ // Set the default properties for this edge
+ for (props_t::iterator k = edge_props.begin();
+ k != edge_props.end(); ++k)
+ {
+ set_edge_property(edge, k->first, k->second);
+ }
+ if (subgraph_depth > 0)
+ {
+ subgraph.edges().insert(edge);
+ // Set the subgraph's default properties as well
+ props_t& props
+ = subgraph_edge_props[subgraph.name()];
+ for (props_t::iterator k = props.begin();
+ k != props.end(); ++k)
+ {
+ set_edge_property(
+ edge, k->first, k->second);
+ }
+ }
+ }
+ }
+ }
+
+ // node_prop - Assign the property for the current active node.
+ void node_prop(id_t const& key, id_t const& value)
+ {
+ node_t& active_object = data_stmt.active_node();
+ set_node_property(active_object, key, value);
+ }
+
+ // edge_prop - Assign the property for the current active edges.
+ void edge_prop(id_t const& key, id_t const& value)
+ {
+ edge_stack_t const& active_edges_ = data_stmt.edge_stack();
+ for (edge_stack_t::const_iterator i = active_edges_.begin();
+ i != active_edges_.end(); ++i)
+ {
+ set_edge_property(*i, key, value);
+ }
+ }
+
+ // default_graph_prop - Store as a graph property.
+ void default_graph_prop(id_t const& key, id_t const& value)
+ {
#ifdef BOOST_GRAPH_DEBUG
- std::cout << key << " = " << value << std::endl;
+ std::cout << key << " = " << value << std::endl;
#endif // BOOST_GRAPH_DEBUG
- self.graph_.set_graph_property(key, value);
- }
-
- // default_node_prop - declare default properties for any future new nodes
- void default_node_prop(id_t const& key, id_t const& value) {
- nodes_t& nodes_ =
- subgraph_depth == 0 ? nodes : subgraph.nodes();
- props_t& node_props_ =
- subgraph_depth == 0 ?
- default_node_props :
- subgraph_node_props[subgraph.name()];
-
- // add this to the selected list of default node properties.
- node_props_[key] = value;
- // for each node, set its property to default-constructed value
- // if it hasn't been set already.
- // set the dynamic property map value
- for(nodes_t::iterator i = nodes_.begin(); i != nodes_.end(); ++i)
- if(node_map[*i].find(key) == node_map[*i].end()) {
- set_node_property(*i,key,id_t());
- }
- }
-
- // default_edge_prop - declare default properties for any future new edges
- void default_edge_prop(id_t const& key, id_t const& value) {
- edges_t& edges_ =
- subgraph_depth == 0 ? edges : subgraph.edges();
- props_t& edge_props_ =
- subgraph_depth == 0 ?
- default_edge_props :
- subgraph_edge_props[subgraph.name()];
-
- // add this to the list of default edge properties.
- edge_props_[key] = value;
- // for each edge, set its property to be empty string
- // set the dynamic property map value
- for(edges_t::iterator i = edges_.begin(); i != edges_.end(); ++i)
- if(edge_map[*i].find(key) == edge_map[*i].end())
- set_edge_property(*i,key,id_t());
- }
-
- // helper function
- void insert_node(nodes_t& nodes, id_t const& name) {
- nodes.insert(name);
- }
-
- void call_prop_actor(std::string const& lhs, std::string const& rhs) {
- actor_t& actor = attr_list.prop_actor();
- // If first and last characters of the rhs are double-quotes,
- // remove them.
- if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"')
- actor(lhs, rhs.substr(1, rhs.size()-2));
- else
- actor(lhs,rhs);
- }
-
- void call_graph_prop(std::string const& lhs, std::string const& rhs) {
- // If first and last characters of the rhs are double-quotes,
- // remove them.
- if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"')
- this->default_graph_prop(lhs, rhs.substr(1, rhs.size()-2));
- else
- this->default_graph_prop(lhs,rhs);
- }
-
- void set_node_property(node_t const& node, id_t const& key,
- id_t const& value) {
-
- // Add the property key to the "set" table to avoid default overwrite
- node_map[node].insert(key);
- // Set the user's property map
- self.graph_.set_node_property(key, node, value);
+ self.graph_.set_graph_property(key, value);
+ }
+
+ // default_node_prop - declare default properties for any future
+ // new nodes
+ void default_node_prop(id_t const& key, id_t const& value)
+ {
+ nodes_t& nodes_
+ = subgraph_depth == 0 ? nodes : subgraph.nodes();
+ props_t& node_props_ = subgraph_depth == 0
+ ? default_node_props
+ : subgraph_node_props[subgraph.name()];
+
+ // add this to the selected list of default node properties.
+ node_props_[key] = value;
+ // for each node, set its property to default-constructed
+ // value
+ // if it hasn't been set already.
+ // set the dynamic property map value
+ for (nodes_t::iterator i = nodes_.begin();
+ i != nodes_.end(); ++i)
+ if (node_map[*i].find(key) == node_map[*i].end())
+ {
+ set_node_property(*i, key, id_t());
+ }
+ }
+
+ // default_edge_prop - declare default properties for any future
+ // new edges
+ void default_edge_prop(id_t const& key, id_t const& value)
+ {
+ edges_t& edges_
+ = subgraph_depth == 0 ? edges : subgraph.edges();
+ props_t& edge_props_ = subgraph_depth == 0
+ ? default_edge_props
+ : subgraph_edge_props[subgraph.name()];
+
+ // add this to the list of default edge properties.
+ edge_props_[key] = value;
+ // for each edge, set its property to be empty string
+ // set the dynamic property map value
+ for (edges_t::iterator i = edges_.begin();
+ i != edges_.end(); ++i)
+ if (edge_map[*i].find(key) == edge_map[*i].end())
+ set_edge_property(*i, key, id_t());
+ }
+
+ // helper function
+ void insert_node(nodes_t& nodes, id_t const& name)
+ {
+ nodes.insert(name);
+ }
+
+ void call_prop_actor(
+ std::string const& lhs, std::string const& rhs)
+ {
+ actor_t& actor = attr_list.prop_actor();
+ // If first and last characters of the rhs are
+ // double-quotes, remove them.
+ if (!rhs.empty() && rhs[0] == '"'
+ && rhs[rhs.size() - 1] == '"')
+ actor(lhs, rhs.substr(1, rhs.size() - 2));
+ else
+ actor(lhs, rhs);
+ }
+
+ void call_graph_prop(
+ std::string const& lhs, std::string const& rhs)
+ {
+ // If first and last characters of the rhs are
+ // double-quotes, remove them.
+ if (!rhs.empty() && rhs[0] == '"'
+ && rhs[rhs.size() - 1] == '"')
+ this->default_graph_prop(
+ lhs, rhs.substr(1, rhs.size() - 2));
+ else
+ this->default_graph_prop(lhs, rhs);
+ }
+
+ void set_node_property(
+ node_t const& node, id_t const& key, id_t const& value)
+ {
+
+ // Add the property key to the "set" table to avoid default
+ // overwrite
+ node_map[node].insert(key);
+ // Set the user's property map
+ self.graph_.set_node_property(key, node, value);
#ifdef BOOST_GRAPH_DEBUG
- // Tell the world
- std::cout << node << ": " << key << " = " << value << std::endl;
+ // Tell the world
+ std::cout << node << ": " << key << " = " << value
+ << std::endl;
#endif // BOOST_GRAPH_DEBUG
- }
+ }
- void set_edge_property(edge_t const& edge, id_t const& key,
- id_t const& value) {
+ void set_edge_property(
+ edge_t const& edge, id_t const& key, id_t const& value)
+ {
- // Add the property key to the "set" table to avoid default overwrite
- edge_map[edge].insert(key);
- // Set the user's property map
- self.graph_.set_edge_property(key, edge, value);
+ // Add the property key to the "set" table to avoid default
+ // overwrite
+ edge_map[edge].insert(key);
+ // Set the user's property map
+ self.graph_.set_edge_property(key, edge, value);
#ifdef BOOST_GRAPH_DEBUG
- // Tell the world
-#if 0 // RG - edge representation changed,
+ // Tell the world
+#if 0 // RG - edge representation changed,
std::cout << "(" << edge.first << "," << edge.second << "): "
#else
- std::cout << "an edge: "
+ std::cout << "an edge: "
#endif // 0
- << key << " = " << value << std::endl;
+ << key << " = " << value << std::endl;
#endif // BOOST_GRAPH_DEBUG
- }
-
- // Variables explicitly initialized
- dot_grammar const& self;
- // if subgraph_depth > 0, then we're processing a subgraph.
- int subgraph_depth;
-
- // Keywords;
- const boost::spirit::classic::distinct_parser<> keyword_p;
- //
- // rules that make up the grammar
- //
- boost::spirit::classic::rule<ScannerT,id_closure::context_t> ID;
- boost::spirit::classic::rule<ScannerT,property_closure::context_t> a_list;
- boost::spirit::classic::rule<ScannerT,attr_list_closure::context_t> attr_list;
- rule_t port_location;
- rule_t port_angle;
- rule_t port;
- boost::spirit::classic::rule<ScannerT,node_id_closure::context_t> node_id;
- boost::spirit::classic::rule<ScannerT,property_closure::context_t> graph_stmt;
- rule_t attr_stmt;
- boost::spirit::classic::rule<ScannerT,data_stmt_closure::context_t> data_stmt;
- boost::spirit::classic::rule<ScannerT,subgraph_closure::context_t> subgraph;
- rule_t edgeop;
- rule_t edgeRHS;
- rule_t stmt;
- rule_t stmt_list;
- rule_t the_grammar;
-
-
- // The grammar uses edge_head to dynamically set the syntax for edges
- // directed graphs: edge_head = '>', and so edgeop = "->"
- // undirected graphs: edge_head = '-', and so edgeop = "--"
- char edge_head;
-
-
- //
- // Support data structures
- //
-
- nodes_t nodes; // list of node names seen
- edges_t edges; // list of edges seen
- node_map_t node_map; // remember the properties set for each node
- edge_map_t edge_map; // remember the properties set for each edge
-
- subgraph_nodes_t subgraph_nodes; // per-subgraph lists of nodes
- subgraph_edges_t subgraph_edges; // per-subgraph lists of edges
-
- props_t default_node_props; // global default node properties
- props_t default_edge_props; // global default edge properties
- subgraph_props_t subgraph_node_props; // per-subgraph default node properties
- subgraph_props_t subgraph_edge_props; // per-subgraph default edge properties
- }; // struct definition
-}; // struct dot_grammar
-
-
-
-//
-// dot_skipper - GraphViz whitespace and comment skipper
-//
-struct dot_skipper : public boost::spirit::classic::grammar<dot_skipper>
-{
- dot_skipper() {}
-
- template <typename ScannerT>
- struct definition
- {
- definition(dot_skipper const& /*self*/) {
- using namespace boost::spirit::classic;
- using namespace phoenix;
- // comment forms
- skip = eol_p >> comment_p("#")
- | space_p
- | comment_p("//")
+ }
+
+ // Variables explicitly initialized
+ dot_grammar const& self;
+ // if subgraph_depth > 0, then we're processing a subgraph.
+ int subgraph_depth;
+
+ // Keywords;
+ const boost::spirit::classic::distinct_parser<> keyword_p;
+ //
+ // rules that make up the grammar
+ //
+ boost::spirit::classic::rule< ScannerT, id_closure::context_t >
+ ID;
+ boost::spirit::classic::rule< ScannerT,
+ property_closure::context_t >
+ a_list;
+ boost::spirit::classic::rule< ScannerT,
+ attr_list_closure::context_t >
+ attr_list;
+ rule_t port_location;
+ rule_t port_angle;
+ rule_t port;
+ boost::spirit::classic::rule< ScannerT,
+ node_id_closure::context_t >
+ node_id;
+ boost::spirit::classic::rule< ScannerT,
+ property_closure::context_t >
+ graph_stmt;
+ rule_t attr_stmt;
+ boost::spirit::classic::rule< ScannerT,
+ data_stmt_closure::context_t >
+ data_stmt;
+ boost::spirit::classic::rule< ScannerT,
+ subgraph_closure::context_t >
+ subgraph;
+ rule_t edgeop;
+ rule_t edgeRHS;
+ rule_t stmt;
+ rule_t stmt_list;
+ rule_t the_grammar;
+
+ // The grammar uses edge_head to dynamically set the syntax for
+ // edges directed graphs: edge_head = '>', and so edgeop = "->"
+ // undirected graphs: edge_head = '-', and so edgeop = "--"
+ char edge_head;
+
+ //
+ // Support data structures
+ //
+
+ nodes_t nodes; // list of node names seen
+ edges_t edges; // list of edges seen
+ node_map_t
+ node_map; // remember the properties set for each node
+ edge_map_t
+ edge_map; // remember the properties set for each edge
+
+ subgraph_nodes_t subgraph_nodes; // per-subgraph lists of nodes
+ subgraph_edges_t subgraph_edges; // per-subgraph lists of edges
+
+ props_t default_node_props; // global default node properties
+ props_t default_edge_props; // global default edge properties
+ subgraph_props_t
+ subgraph_node_props; // per-subgraph default node properties
+ subgraph_props_t
+ subgraph_edge_props; // per-subgraph default edge properties
+ }; // struct definition
+ }; // struct dot_grammar
+
+ //
+ // dot_skipper - GraphViz whitespace and comment skipper
+ //
+ struct dot_skipper
+ : public boost::spirit::classic::grammar< dot_skipper >
+ {
+ dot_skipper() {}
+
+ template < typename ScannerT > struct definition
+ {
+ definition(dot_skipper const& /*self*/)
+ {
+ using namespace boost::spirit::classic;
+ using namespace phoenix;
+ // comment forms
+ skip = eol_p >> comment_p("#") | space_p | comment_p("//")
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
- | confix_p(str_p("/*") ,*anychar_p, str_p("*/"))
+ | confix_p(str_p("/*"), *anychar_p, str_p("*/"))
#else
- | confix_p("/*" ,*anychar_p, "*/")
+ | confix_p("/*", *anychar_p, "*/")
#endif
- ;
+ ;
#ifdef BOOST_SPIRIT_DEBUG
- BOOST_SPIRIT_DEBUG_RULE(skip);
+ BOOST_SPIRIT_DEBUG_RULE(skip);
#endif
- }
+ }
- boost::spirit::classic::rule<ScannerT> skip;
- boost::spirit::classic::rule<ScannerT> const&
- start() const { return skip; }
- }; // definition
-}; // dot_skipper
+ boost::spirit::classic::rule< ScannerT > skip;
+ boost::spirit::classic::rule< ScannerT > const& start() const
+ {
+ return skip;
+ }
+ }; // definition
+ }; // dot_skipper
-} // namespace graph
+ } // namespace graph
} // namespace detail
-template <typename MultiPassIterator, typename MutableGraph>
+template < typename MultiPassIterator, typename MutableGraph >
bool read_graphviz_spirit(MultiPassIterator begin, MultiPassIterator end,
- MutableGraph& graph, dynamic_properties& dp,
- std::string const& node_id = "node_id") {
- using namespace boost;
- using namespace boost::spirit::classic;
+ MutableGraph& graph, dynamic_properties& dp,
+ std::string const& node_id = "node_id")
+{
+ using namespace boost;
+ using namespace boost::spirit::classic;
- typedef MultiPassIterator iterator_t;
- typedef skip_parser_iteration_policy< boost::detail::graph::dot_skipper>
- iter_policy_t;
- typedef scanner_policies<iter_policy_t> scanner_policies_t;
- typedef scanner<iterator_t, scanner_policies_t> scanner_t;
+ typedef MultiPassIterator iterator_t;
+ typedef skip_parser_iteration_policy< boost::detail::graph::dot_skipper >
+ iter_policy_t;
+ typedef scanner_policies< iter_policy_t > scanner_policies_t;
+ typedef scanner< iterator_t, scanner_policies_t > scanner_t;
- ::boost::detail::graph::mutate_graph_impl<MutableGraph>
- m_graph(graph, dp, node_id);
+ ::boost::detail::graph::mutate_graph_impl< MutableGraph > m_graph(
+ graph, dp, node_id);
- ::boost::detail::graph::dot_grammar p(m_graph);
- ::boost::detail::graph::dot_skipper skip_p;
+ ::boost::detail::graph::dot_grammar p(m_graph);
+ ::boost::detail::graph::dot_skipper skip_p;
- iter_policy_t iter_policy(skip_p);
- scanner_policies_t policies(iter_policy);
+ iter_policy_t iter_policy(skip_p);
+ scanner_policies_t policies(iter_policy);
- scanner_t scan(begin, end, policies);
+ scanner_t scan(begin, end, policies);
- bool ok = p.parse(scan);
- m_graph.finish_building_graph();
- return ok;
+ bool ok = p.parse(scan);
+ m_graph.finish_building_graph();
+ return ok;
}
} // namespace boost