+
+ inline int getIndentLevelIdx() {
+ static int i = ios_base::xalloc();
+ return i;
+ }
+
+ ostream& indent(ostream& os) { os << setw(2*os.iword(getIndentLevelIdx())) << ""; return os; }
+ ostream& indent_inc(ostream& os) { os.iword(getIndentLevelIdx())++; return os; }
+ ostream& indent_dec(ostream& os) { os.iword(getIndentLevelIdx())--; return os; }
+
+ class State;
+
+ class Context : public map<string, State*> {
+ public:
+ iterator add(State *state);
+ Context *findContext(const string &name);
+ };
+
+ class State : public Context
+ {
+ string initialInnerState;
+ public:
+ const string name;
+ explicit State(string name) : name(name) {}
+ void setInitialInnerState(string name) { initialInnerState = name; }
+ friend ostream& operator<<(ostream& os, const State& s);
+ };
+
+
+ Context::iterator Context::add(State *state)
+ {
+ pair<iterator, bool> ret = insert(value_type(state->name, state));
+ return ret.first;
+ }
+
+ Context *Context::findContext(const string &name)
+ {
+ iterator i = find(name), e;
+ if (i != end())
+ return i->second;
+ for (i = begin(), e = end(); i != e; ++i) {
+ Context *c = i->second->findContext(name);
+ if (c)
+ return c;
+ }
+ return 0;
+ }
+
+
+ ostream& operator<<(ostream& os, const Context& c);
+
+ ostream& operator<<(ostream& os, const State& s)
+ {
+ if (s.size()) {
+ os << indent << "subgraph cluster_" << s.name << " {\n" << indent_inc;
+ os << indent << "label = \"" << s.name << "\"\n";
+ }
+ os << indent << "" << s.name << "\n";
+ if (s.size()) {
+ os << indent << s.initialInnerState << " [peripheries=2]\n";
+ os << static_cast<Context>(s);
+ os << indent_dec << indent << "}\n";
+ }
+ return os;
+ }
+
+
+ ostream& operator<<(ostream& os, const Context& c)
+ {
+ for (Context::const_iterator i = c.begin(), e = c.end(); i != e; i++) {
+ os << *i->second;
+ }
+ return os;
+ }
+
+