/* * C++ コードの生成 */ fout.open((fsm.name + ".h").c_str()); /* * 宣言部 (ヘッダ) */ if ( fsm.header.empty() ) { fout << "#ifndef __" << fsm.name << "_h__" LN << "#define __" << fsm.name << "_h__" LN LN; } else { fout << "#ifndef __" << fsm.header << '_' << fsm.name << "_h__" LN << "#define __" << fsm.header << '_' << fsm.name << "_h__" LN LN; } fout << "namespace " << fsm.name << " {" LN LN; /* * Context 宣言 */ fout << "class FSM;" LN LN "class Context {" LN "public:" LN " virtual void error(const char* state_name, const char* event_name) =0;" LN; for ( nit = fsm.action_names.begin(); nit != fsm.action_names.end(); ++nit ) { fout << " virtual void " << *nit << "(FSM* fsm) =0;" LN; } fout << "};" LN LN; /* * State(base) 宣言 */ fout << "class State {" LN "public:" LN << " virtual const char* getName() const =0;" LN << " virtual void enter(FSM* fsm);" LN << " virtual void exit(FSM* fsm);" LN; for ( nit = fsm.event_names.begin(); nit != fsm.event_names.end(); ++nit ) { fout << " virtual void " << *nit << "(FSM* fsm);" LN; } fout << "};" LN LN; /* * State 宣言 */ for ( sit = fsm.states.begin(); sit != fsm.states.end(); ++sit) { fout << "class " << sit->name << "State : public State {" LN "public:" LN << " virtual const char* getName() const;" LN; if ( !sit->enter.empty() ) { fout << " virtual void enter(FSM* fsm);" LN; } if ( !sit->exit.empty() ) { fout << " virtual void exit(FSM* fsm);" LN; } for ( eit = sit->events.begin(); eit != sit->events.end(); ++eit ) { fout << " virtual void " << eit->name << "(FSM* fsm);" LN; } fout << "};" LN LN; } /* * FSM 宣言 */ fout << "class FSM {" LN " Context* context_;" LN " State* state_;" LN " State* newstate_;" LN " State* terminal_;" LN; for ( nit = fsm.state_names.begin(); nit != fsm.state_names.end(); ++nit ) { fout << " static " << *nit << "State " << *nit << "_;" LN; } fout << "public:" LN " FSM() { state_ = &" << fsm.initial << "_; "; if ( fsm.terminal.empty() ) { fout << "terminal_ = 0; }" LN; } else { fout << "terminal_ = &" << fsm.terminal << "_; }" LN; } fout << " bool isTerminated() const { return state_ == terminal_; }" LN LN << " void setContext(Context* context) { context_ = context; }" LN << " Context* getContext() const { return context_; }" LN LN << " void setNewState(State* state) { newstate_ = state; }" LN << " State* getNewState() { return newstate_; }" LN LN << " void setState(State* state) { state_ = state; }" LN << " void setState() { state_ = newstate_; }" LN << " State* getState() { return state_; }" LN LN; for ( nit = fsm.state_names.begin(); nit != fsm.state_names.end(); ++nit ) { fout << " static State* " << *nit << "() { return &" << *nit << "_; }" LN; } fout << LN; for ( nit = fsm.event_names.begin(); nit != fsm.event_names.end(); ++nit ) { fout << " void " << *nit << "() { state_->" << *nit << "(this); }" LN; } fout << "};" LN LN; fout << "}" LN LN; fout << "#endif" LN; fout.close(); /* * 実装部 */ fout.open((fsm.name + ".cpp").c_str()); if ( fsm.header.empty() ) { fout << "#include \"" << fsm.name << ".h\"" LN LN; } else { fout << "#include \"" << fsm.header << '/' << fsm.name << ".h\"" LN LN; } fout << "namespace " << fsm.name << " {" LN LN; /* * Context 実装 */ // 実装すべきものはなにもない。 /* * State(base) 実装 */ fout << "void State::enter(FSM* fsm) {}" LN "void State::exit(FSM* fsm) {}" LN; for ( nit = fsm.event_names.begin(); nit != fsm.event_names.end(); ++nit ) { fout << "void State::" << *nit << "(FSM* fsm) { fsm->getContext()->error(getName(), \"" << *nit << "\"); }" LN; } fout << LN; /* * State 実装 */ for ( sit = fsm.states.begin(); sit != fsm.states.end(); ++sit) { fout << "const char* " << sit->name << "State::getName() const {" " return \"" << sit->name << "\"; }" LN; if ( !sit->enter.empty() ) { fout << "void " << sit->name << "State::enter(FSM* fsm) { fsm->getContext()->" << sit->enter << "(fsm); }" LN; } if ( !sit->exit.empty() ) { fout << "void " << sit->name << "State::exit(FSM* fsm) { fsm->getContext()->" << sit->exit << "(fsm); }" LN; } fout << LN; for ( eit = sit->events.begin(); eit != sit->events.end(); ++eit ) { fout << "void " << sit->name << "State::" << eit->name << "(FSM* fsm) {" LN " Context* context = fsm->getContext();" LN; if ( eit->transition.empty() ) { fout << " fsm->setNewState(this);" LN; } else { fout << " fsm->setNewState(fsm->" << eit->transition << "());" LN; } if ( !eit->action.empty() ) { fout << " context->" << eit->action << "(fsm);" LN; } States::const_iterator tit = eit->transition.empty() ? sit : fsm.states.find(State(eit->transition)); if ( eit->transition.empty() ) { fout << " if ( fsm->getNewState() != this ) {" LN " exit(fsm);" LN " fsm->setState();" LN " fsm->getState()->enter(fsm);" LN " } else {" LN " fsm->setState();" LN " }" LN; } else { if ( !sit->exit.empty() ) { fout << " exit(fsm);" LN; } fout << " fsm->setState();" LN; if ( !tit->enter.empty() ) { fout << " fsm->getState()->enter(fsm);" LN; } } fout << "}" LN LN; } fout << sit->name << "State FSM::" << sit->name << "_;" LN LN; } fout << "}" LN; fout.close();