C++ 可视化sml状态机
我第一次在boost sml中构建了一个更大的状态机,需要一种可视化(例如,导出到graphviz)整个状态机的方法。你知道怎么做吗?有没有办法迭代状态机的结构并打印出来 免责声明:我对SML没有任何经验(必须找到它的位置) 第一次尝试,嗯 然而,尝试使用C++ 可视化sml状态机,c++,boost,C++,Boost,我第一次在boost sml中构建了一个更大的状态机,需要一种可视化(例如,导出到graphviz)整个状态机的方法。你知道怎么做吗?有没有办法迭代状态机的结构并打印出来 免责声明:我对SML没有任何经验(必须找到它的位置) 第一次尝试,嗯 然而,尝试使用visit\u current\u states界面做一些事情,我想到了这个。。。在给定事件列表的情况下,映射出(复合)状态机的实现不是很好: #include <boost/sml.hpp> namespace sml = bo
visit\u current\u states
界面做一些事情,我想到了这个。。。在给定事件列表的情况下,映射出(复合)状态机的实现不是很好:
#include <boost/sml.hpp>
namespace sml = boost::sml;
namespace aux = sml::aux;
struct e1 {};
struct e2 {};
struct e3 {};
struct e4 {};
struct e5 {};
struct sub {
auto operator()() const {
using namespace sml;
// clang-format off
return make_transition_table(
*"idle"_s + event<e3> = "sub1"_s
, "sub1"_s + event<e4> = X
);
// clang-format on
}
};
struct composite {
auto operator()() const {
using namespace sml;
// clang-format off
return make_transition_table(
*"idle"_s + event<e1> = "s1"_s
, "s1"_s + event<e2> = state<sub>
, state<sub> + event<e5> = X
);
// clang-format on
}
};
#include <boost/hana.hpp>
#include <boost/core/demangle.hpp>
#include <iostream>
#include <iomanip>
namespace mapper {
namespace hana = boost::hana;
using namespace std::string_literals;
using boost::core::demangle;
template <typename F> struct ycombine {
ycombine(F f):f(f) {}
F f;
template <typename... A>
auto operator()(A... a) const { return f(*this, a...); };
};
hana::tuple<e1,e2,e3,e4,e5> events;
template <class TSM> class Vis {
public:
explicit Vis(const TSM& sm, std::string prefix = "") : sm_{ sm }, prefix(prefix) {}
template <class TSub>
void operator()(aux::string<boost::sml::sm<TSub>>) const {
auto subname = aux::get_type_name<TSub>();
Vis nvis(sm_, prefix + '/' + subname);
sm_.template visit_current_states<aux::identity<TSub>>(nvis);
prefix = nvis.prefix;
}
template <class TState> void operator()(TState state) const {
prefix += "/"s + state.c_str();
}
private:
const TSM& sm_;
public:
mutable std::string prefix;
};
template <typename SM>
std::string get_current(SM const& sm) {
Vis<SM> v{sm};
sm.visit_current_states(v);
return v.prefix;
};
}
int main() {
using namespace mapper;
auto recurse = ycombine {
[](auto self, auto sm) {
hana::for_each(events, [=](auto ev) {
auto clone = sm;
auto from = get_current(clone);
clone.process_event(ev);
auto to = get_current(clone);
if (from != to) {
std::cout
<< std::quoted(from) << " -> "
<< std::quoted(to)
<< " [label=" << std::quoted(demangle(typeid(ev).name())) << "]\n";
self(clone);
}
});
} };
std::cout << "digraph {\n";
recurse(sml::sm<composite>{});
std::cout << "}\n";
}
为了获得灵感,输出:
@startuml
[*] --> idle
idle --> s1 : e1
s1 --> s2 : e2 [guard] / action
s2 --> s1 : e3 [guard]
s2 --> terminate : e4 / action
@enduml
显然,不是graphviz,但实际上看起来更“可信”,因为
- 它类似于某种标准的UML符号
- 是由图书馆的作者写的吗
- 包括我无法提供的细节(主要是因为不知道他们的存在/工作)
天哪,我怎么会忽略了垃圾场的例子:(该死……谢谢!我猜是这样的:)我印象深刻,你从没有看过SML就把它拔了出来。你是如何发现访问美国的?我已经看了3个星期的页面,今天才发现它,试图了解visitor.cpp示例中发生了什么。我想我对库源进行了一些关键字搜索,包括示例。就我所记得的,我在最后一个样本中匹配了它?虽然你仍然可以找到它,但这个例子似乎不是。似乎该示例仅被删除,提交消息确认其文档不足。我敢肯定,我刚刚在实际结账时使用了灰色,而我恰好是在添加了该样本一个月之后:)
@startuml
[*] --> idle
idle --> s1 : e1
s1 --> s2 : e2 [guard] / action
s2 --> s1 : e3 [guard]
s2 --> terminate : e4 / action
@enduml