File indexing completed on 2025-04-27 08:49:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_MSM_FRONT_PUML_COMMON_H
0012 #define BOOST_MSM_FRONT_PUML_COMMON_H
0013
0014 #include <cstdint>
0015 #include <string>
0016 #include <string_view>
0017 #include <vector>
0018 #include <boost/any.hpp>
0019 #include <boost/fusion/mpl.hpp>
0020 #include <boost/fusion/include/as_vector.hpp>
0021 #include <boost/fusion/container/vector.hpp>
0022 #include <boost/fusion/include/insert_range.hpp>
0023 #include <boost/fusion/include/at_c.hpp>
0024 #include <boost/fusion/include/for_each.hpp>
0025 #include <boost/fusion/include/make_vector.hpp>
0026
0027 #include <boost/mpl/size.hpp>
0028
0029 #include <boost/msm/front/states.hpp>
0030
0031 #include <boost/msm/front/functor_row.hpp>
0032 #include <boost/msm/front/operator.hpp>
0033
0034 namespace boost::msm::front::puml
0035 {
0036 namespace detail {
0037 template <class T1, class T2>
0038 struct pair_type
0039 {
0040 using first = T1;
0041 using second = T2;
0042 };
0043 }
0044
0045 template<typename T>
0046 struct convert_to_msm_names
0047 {
0048 using type = T;
0049 };
0050
0051
0052 template <std::uint32_t hash,
0053 class Flags = boost::fusion::vector0<>,
0054 class Entries = boost::fusion::vector0<>,
0055 class Exits = boost::fusion::vector0<>>
0056 struct State
0057 {
0058 using generated_type = State<hash>;
0059 using flag_list = boost::fusion::vector0<>;
0060 using entries = Entries;
0061 using exits = Exits;
0062 using internal_flag_list = Flags;
0063
0064 template <class Event, class FSM>
0065 void on_entry(Event& evt, FSM& fsm)
0066 {
0067 boost::fusion::for_each(Entries{},
0068 [&](auto action_guard_pair)
0069 {
0070 if constexpr (
0071 std::is_same_v<typename decltype(action_guard_pair)::second,boost::msm::front::none>)
0072 {
0073 typename decltype(action_guard_pair)::first{}(evt, fsm, *this, *this);
0074 }
0075 else
0076 {
0077 if (typename decltype(action_guard_pair)::second{}(evt, fsm, *this, *this))
0078 {
0079 typename decltype(action_guard_pair)::first{}(evt, fsm, *this, *this);
0080 }
0081 }
0082 });
0083 }
0084 template <class Event, class FSM>
0085 void on_exit(Event& evt, FSM& fsm)
0086 {
0087 boost::fusion::for_each(Exits{},
0088 [&](auto action_guard_pair)
0089 {
0090 if constexpr (
0091 std::is_same_v<typename decltype(action_guard_pair)::second, boost::msm::front::none>)
0092 {
0093 typename decltype(action_guard_pair)::first{}(evt, fsm, *this, *this);
0094 }
0095 else
0096 {
0097 if (typename decltype(action_guard_pair)::second{}(evt, fsm, *this, *this))
0098 {
0099 typename decltype(action_guard_pair)::first{}(evt, fsm, *this, *this);
0100 }
0101 }
0102 });
0103 }
0104
0105 typedef ::boost::mpl::vector<> internal_transition_table;
0106 typedef ::boost::fusion::vector<> internal_transition_table11;
0107 typedef ::boost::fusion::vector<> transition_table;
0108 typedef ::boost::fusion::vector0<> deferred_events;
0109
0110 };
0111 template <std::uint32_t hash>
0112 struct Event
0113 {
0114
0115 };
0116 template <std::uint32_t hash>
0117 struct Action
0118 {
0119
0120 };
0121 template <std::uint32_t hash>
0122 struct Guard
0123 {
0124
0125 };
0126 template <std::uint32_t hash>
0127 struct Flag
0128 {
0129
0130 };
0131
0132
0133 namespace detail {
0134
0135 static constexpr std::uint32_t crc_table[256] =
0136 {
0137 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0138 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0139 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0140 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0141 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0142 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0143 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0144 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0145 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0146 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0147 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0148 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0149 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0150 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0151 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0152 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0153 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0154 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0155 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0156 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0157 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0158 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0159 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0160 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0161 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0162 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0163 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0164 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0165 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0166 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0167 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0168 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0169 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0170 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0171 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0172 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0173 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0174 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0175 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0176 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0177 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0178 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0179 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0180 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0181 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0182 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0183 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0184 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0185 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0186 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0187 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0188 0x2d02ef8dL
0189 };
0190 constexpr std::uint32_t crc32(std::string_view str)
0191 {
0192 std::uint32_t crc = 0xffffffff;
0193 for (auto c : str)
0194 crc = (crc >> 8) ^ boost::msm::front::puml::detail::crc_table[(crc ^ c) & 0xff];
0195 return crc ^ 0xffffffff;
0196 }
0197
0198
0199 constexpr std::string_view cleanup_token(const std::string_view& str)
0200 {
0201 auto first_not_whitespace = str.find_first_not_of("- \t");
0202 auto last_not_whitespace = str.find_last_not_of("- \t");
0203 if (first_not_whitespace != std::string::npos && last_not_whitespace != std::string::npos)
0204 {
0205
0206 return str.substr(first_not_whitespace, last_not_whitespace - first_not_whitespace + 1);
0207 }
0208 else
0209 {
0210 return std::string_view{};
0211 }
0212 }
0213
0214 struct Transition
0215 {
0216 std::string_view source;
0217 std::string_view target;
0218 std::string_view event;
0219 std::string_view guard;
0220 std::string_view action;
0221 };
0222
0223
0224
0225 constexpr boost::msm::front::puml::detail::Transition
0226 parse_guards(std::string_view part)
0227 {
0228 boost::msm::front::puml::detail::Transition res;
0229 auto start_pos = part.find("[");
0230 auto end_pos = part.find("]");
0231
0232 if (start_pos != std::string::npos && end_pos != std::string::npos)
0233 {
0234 ++start_pos;
0235 res.guard = boost::msm::front::puml::detail::cleanup_token(part.substr(start_pos, end_pos - start_pos));
0236 }
0237 return res;
0238 }
0239
0240
0241
0242 constexpr boost::msm::front::puml::detail::Transition parse_row_right(std::string_view part)
0243 {
0244 auto action_pos = part.find("/");
0245 auto guard_pos = part.find("[");
0246 auto evt_pos = part.find(":");
0247 auto internal_pos = part.find("-");
0248 bool is_internal_transition =
0249 internal_pos != std::string::npos && internal_pos > evt_pos && internal_pos <= action_pos && internal_pos <= guard_pos;
0250 auto start_event_name_pos = (internal_pos == std::string::npos) ? evt_pos : internal_pos;
0251
0252 boost::msm::front::puml::detail::Transition res;
0253
0254
0255 if (evt_pos != std::string::npos && !is_internal_transition)
0256 {
0257 res.target = boost::msm::front::puml::detail::cleanup_token(part.substr(0, evt_pos));
0258 }
0259 else if (!is_internal_transition)
0260 {
0261 res.target = boost::msm::front::puml::detail::cleanup_token(part);
0262 }
0263
0264 if (action_pos == std::string::npos && guard_pos == std::string::npos)
0265 {
0266 res.event = boost::msm::front::puml::detail::cleanup_token(part.substr(start_event_name_pos + 1));
0267 }
0268 else
0269 {
0270 auto length = std::min(action_pos, guard_pos) > 1 + start_event_name_pos ?
0271 std::min(action_pos, guard_pos) - 1 - start_event_name_pos
0272 : 0;
0273 res.event = boost::msm::front::puml::detail::cleanup_token(part.substr(start_event_name_pos + 1, length));
0274 }
0275
0276
0277 if (action_pos != std::string::npos && guard_pos != std::string::npos)
0278 {
0279 res.action = boost::msm::front::puml::detail::cleanup_token(part.substr(action_pos + 1, guard_pos - 1 - action_pos));
0280 }
0281 else if (action_pos != std::string::npos)
0282 {
0283
0284 res.action = boost::msm::front::puml::detail::cleanup_token(part.substr(action_pos + 1));
0285 }
0286
0287 res.guard = boost::msm::front::puml::detail::parse_guards(
0288 boost::msm::front::puml::detail::cleanup_token(part)).guard;
0289 return res;
0290 }
0291
0292 constexpr boost::msm::front::puml::detail::Transition parse_row(std::string_view row)
0293 {
0294 auto arrow_pos = row.find("->");
0295 auto puml_event_pos = row.find(":");
0296 auto left = row.substr(0, arrow_pos);
0297 auto right = row.substr(arrow_pos + 2);
0298
0299 if (puml_event_pos != std::string::npos)
0300 {
0301 return boost::msm::front::puml::detail::Transition{
0302 boost::msm::front::puml::detail::cleanup_token(left),
0303 boost::msm::front::puml::detail::parse_row_right(right).target,
0304 boost::msm::front::puml::detail::parse_row_right(right).event,
0305 boost::msm::front::puml::detail::parse_row_right(right).guard,
0306 boost::msm::front::puml::detail::parse_row_right(right).action };
0307 }
0308 else if (arrow_pos != std::string::npos)
0309 {
0310
0311 return boost::msm::front::puml::detail::Transition{
0312 boost::msm::front::puml::detail::cleanup_token(left),
0313 boost::msm::front::puml::detail::cleanup_token(right),
0314 std::string_view{},
0315 std::string_view{},
0316 std::string_view{}
0317 };
0318 }
0319 return boost::msm::front::puml::detail::Transition{};
0320 }
0321
0322
0323 constexpr int count_transitions(std::string_view s)
0324 {
0325
0326 int occurrences = 0;
0327 std::string::size_type pos = 0;
0328 auto target = "->";
0329 while ((pos = s.find(target, pos)) != std::string::npos)
0330 {
0331 ++occurrences;
0332 pos += 2;
0333 }
0334 return occurrences;
0335 };
0336 constexpr int count_inits(std::string_view s, std::size_t occurrences=0)
0337 {
0338 auto target = "[*]";
0339 auto star_pos = s.find(target);
0340 auto endl_after_pos = s.find("\n", star_pos);
0341 auto arrow_after_pos = s.find("->", star_pos);
0342 if (star_pos != std::string::npos &&
0343 star_pos < arrow_after_pos &&
0344 arrow_after_pos < endl_after_pos)
0345 {
0346 return count_inits(s.substr(endl_after_pos), occurrences + 1);
0347 }
0348 return occurrences;
0349 };
0350 constexpr int count_actions(std::string_view s)
0351 {
0352 int occurrences = 0;
0353 if (!s.empty())
0354 {
0355 occurrences = 1;
0356 }
0357 std::string::size_type pos = 0;
0358 auto target = ",";
0359 while ((pos = s.find(target, pos)) != std::string::npos)
0360 {
0361 ++occurrences;
0362 pos += 1;
0363 }
0364 return occurrences;
0365 };
0366
0367 template <int t>
0368 constexpr
0369 auto parse_stt(std::string_view stt)
0370 {
0371 auto prev_pos = std::string::size_type(0);
0372 auto pos = std::string::size_type(0);
0373 auto trans_cpt = 0;
0374 do
0375 {
0376 pos = stt.find("\n", prev_pos);
0377 auto transition_symbol = stt.find("->", prev_pos);
0378 auto init_symbol = stt.find("[*]", prev_pos);
0379 if (init_symbol < pos || transition_symbol >= pos)
0380 {
0381 prev_pos = pos + 1;
0382 }
0383 else
0384 {
0385 if (trans_cpt == t)
0386 {
0387 return boost::msm::front::puml::detail::parse_row(stt.substr(prev_pos, pos - prev_pos));
0388 }
0389 prev_pos = pos + 1;
0390 ++trans_cpt;
0391 }
0392 } while (pos != std::string::npos);
0393
0394 return boost::msm::front::puml::detail::Transition{};
0395 }
0396
0397 template <int a>
0398 constexpr auto parse_action(std::string_view actions)
0399 {
0400
0401 auto prev_pos = std::string::size_type(0);
0402 auto pos = std::string::size_type(0);
0403 auto action_cpt = 0;
0404 do
0405 {
0406 pos = actions.find(",", prev_pos);
0407 if (action_cpt == a)
0408 {
0409 return boost::msm::front::puml::detail::cleanup_token(actions.substr(prev_pos, pos - prev_pos));
0410 }
0411 ++action_cpt;
0412 prev_pos = pos + 1;
0413 } while (pos != std::string::npos);
0414
0415 return std::string_view{};
0416 }
0417
0418
0419 template <int t>
0420 constexpr
0421 auto parse_inits(std::string_view stt)
0422 {
0423
0424
0425 auto prev_pos = std::string::size_type(0);
0426 auto pos = std::string::size_type(0);
0427 auto trans_cpt = 0;
0428 do
0429 {
0430 pos = stt.find("\n", prev_pos);
0431 auto init_symbol = stt.find("[*]", prev_pos);
0432 if (pos > init_symbol)
0433 {
0434 auto init_symbol2 = stt.find("->", init_symbol);
0435 if (pos > init_symbol2)
0436 {
0437 if (trans_cpt == t)
0438 {
0439 return cleanup_token(stt.substr(init_symbol2 + 2, pos - init_symbol2 - 2));
0440 }
0441 ++trans_cpt;
0442 }
0443 }
0444 prev_pos = pos + 1;
0445 } while (pos != std::string::npos);
0446
0447 return std::string_view{};
0448 }
0449 }
0450
0451 constexpr std::uint32_t by_name(std::string_view str)
0452 {
0453 return boost::msm::front::puml::detail::crc32(str) ^ 0xFFFFFFFF;
0454 }
0455
0456
0457 template<>
0458 struct convert_to_msm_names<State<by_name("")>>
0459 {
0460 using type = boost::msm::front::none;
0461 };
0462 template<>
0463 struct convert_to_msm_names<Event< by_name("")>>
0464 {
0465 using type = boost::msm::front::none;
0466 };
0467 template<>
0468 struct convert_to_msm_names<Action< by_name("")>>
0469 {
0470 using type = boost::msm::front::none;
0471 };
0472 template<>
0473 struct convert_to_msm_names<Guard< by_name("")>>
0474 {
0475 using type = boost::msm::front::none;
0476 };
0477 template<>
0478 struct convert_to_msm_names<Action< by_name("defer")>>
0479 {
0480 using type = boost::msm::front::Defer;
0481 };
0482 template<>
0483 struct convert_to_msm_names<Event< by_name("*")>>
0484 {
0485 using type = boost::any;
0486 };
0487
0488 namespace detail
0489 {
0490 template <class Func>
0491 constexpr auto parse_guard_simple(Func guard_func)
0492 {
0493 constexpr auto and_pos = guard_func().find("&&");
0494 constexpr auto or_pos = guard_func().find("||");
0495 constexpr auto not_pos = guard_func().find("!");
0496 constexpr auto parens_begin_pos = guard_func().find("(");
0497 constexpr auto parens_end_pos = guard_func().find(")");
0498 constexpr auto last_and_pos = guard_func().find("&&", parens_end_pos);
0499 constexpr auto last_or_pos = guard_func().find("||", parens_end_pos);
0500
0501
0502 if constexpr (parens_begin_pos != std::string::npos && parens_end_pos != std::string::npos &&
0503 last_or_pos != std::string::npos && parens_end_pos < last_or_pos)
0504 {
0505 return boost::msm::front::Or_<
0506 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0507 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(0, last_or_pos)); })),
0508 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0509 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(last_or_pos + 2)); })) > {};
0510 }
0511 else if constexpr (parens_begin_pos != std::string::npos && parens_end_pos != std::string::npos &&
0512 last_and_pos != std::string::npos && parens_end_pos < last_and_pos)
0513 {
0514 return boost::msm::front::And_<
0515 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0516 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(0, last_and_pos)); })),
0517 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0518 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(last_and_pos + 2)); })) > {};
0519 }
0520 else if constexpr (parens_begin_pos != std::string::npos && parens_end_pos != std::string::npos &&
0521 or_pos != std::string::npos && or_pos < and_pos && or_pos < parens_begin_pos)
0522 {
0523 return boost::msm::front::Or_<
0524 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0525 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(0, or_pos)); })),
0526 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0527 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(or_pos + 2)); })) > {};
0528 }
0529 else if constexpr (parens_begin_pos != std::string::npos && parens_end_pos != std::string::npos &&
0530 and_pos != std::string::npos && and_pos < or_pos && and_pos < parens_begin_pos)
0531 {
0532 return boost::msm::front::And_<
0533 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0534 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(0, and_pos)); })),
0535 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0536 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(and_pos + 2)); })) > {};
0537 }
0538 else if constexpr (parens_begin_pos != std::string::npos && parens_end_pos != std::string::npos &&
0539 not_pos != std::string::npos && not_pos < parens_begin_pos)
0540 {
0541 return boost::msm::front::Not_<decltype(boost::msm::front::puml::detail::parse_guard_simple(
0542 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(not_pos + 1)); })) > {};
0543 }
0544 else if constexpr (parens_begin_pos != std::string::npos && parens_end_pos != std::string::npos)
0545 {
0546 return boost::msm::front::puml::detail::parse_guard_simple(
0547 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(parens_begin_pos + 1, parens_end_pos - (parens_begin_pos + 1))); });
0548 }
0549 else if constexpr (and_pos == std::string::npos && or_pos == std::string::npos && not_pos == std::string::npos)
0550 {
0551 return typename boost::msm::front::puml::convert_to_msm_names < Guard <by_name(guard_func())> >::type{};
0552 }
0553
0554 else if constexpr (or_pos != std::string::npos)
0555 {
0556 return boost::msm::front::Or_<
0557 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0558 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(0, or_pos)); })),
0559 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0560 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(or_pos + 2)); })) > {};
0561 }
0562 else if constexpr (and_pos != std::string::npos)
0563 {
0564 return boost::msm::front::And_<
0565 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0566 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(0, and_pos)); })),
0567 decltype(boost::msm::front::puml::detail::parse_guard_simple(
0568 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(and_pos + 2)); })) > {};
0569 }
0570 else
0571 {
0572 return boost::msm::front::Not_<decltype(boost::msm::front::puml::detail::parse_guard_simple(
0573 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(not_pos + 1)); })) > {};
0574 }
0575 }
0576 template <class Func>
0577 constexpr auto parse_guard_advanced(Func guard_func)
0578 {
0579 constexpr auto and_pos = guard_func().find("And(");
0580 constexpr auto or_pos = guard_func().find("Or(");
0581 constexpr auto not_pos = guard_func().find("Not(");
0582
0583 if constexpr (and_pos == std::string::npos && or_pos == std::string::npos && not_pos == std::string::npos)
0584 {
0585 return typename boost::msm::front::puml::convert_to_msm_names < Guard <by_name(guard_func())> >::type{};
0586 }
0587
0588 else if constexpr (or_pos != std::string::npos)
0589 {
0590 constexpr auto comma_pos = guard_func().find(",", or_pos);
0591 constexpr auto endparens_pos = guard_func().find(")", or_pos);
0592 return boost::msm::front::Or_<
0593 decltype(boost::msm::front::puml::detail::parse_guard_advanced(
0594 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(or_pos + 3, comma_pos - (or_pos + 3))); })),
0595 decltype(boost::msm::front::puml::detail::parse_guard_advanced(
0596 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(comma_pos + 1, endparens_pos - (comma_pos + 1))); }))
0597 > {};
0598 }
0599 else if constexpr (and_pos != std::string::npos)
0600 {
0601 constexpr auto comma_pos = guard_func().find(",", and_pos);
0602 constexpr auto endparens_pos = guard_func().find(")", and_pos);
0603 return boost::msm::front::And_<
0604 decltype(boost::msm::front::puml::detail::parse_guard_advanced(
0605 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(and_pos + 4, comma_pos - (and_pos + 4))); })),
0606 decltype(boost::msm::front::puml::detail::parse_guard_advanced(
0607 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(comma_pos + 1, endparens_pos - (comma_pos + 1))); }))
0608 > {};
0609 }
0610 else
0611 {
0612 constexpr auto endparens_pos = guard_func().find(")", not_pos);
0613 return boost::msm::front::Not_<
0614 decltype(boost::msm::front::puml::detail::parse_guard_advanced(
0615 [=]() {return boost::msm::front::puml::detail::cleanup_token(guard_func().substr(not_pos + 4, endparens_pos - (not_pos + 4))); }))
0616 > {};
0617 }
0618 }
0619
0620 template <class Func>
0621 constexpr auto parse_guard(Func guard_func)
0622 {
0623 if constexpr (guard_func().find("And(") != std::string::npos ||
0624 guard_func().find("Or(") != std::string::npos ||
0625 guard_func().find("Not(") != std::string::npos)
0626 {
0627 return boost::msm::front::puml::detail::parse_guard_advanced(guard_func);
0628 }
0629 else
0630 {
0631 return boost::msm::front::puml::detail::parse_guard_simple(guard_func);
0632 }
0633 }
0634
0635 constexpr int count_terminates(std::string_view s, std::size_t occurrences = 0)
0636 {
0637 if (s.empty())
0638 return occurrences;
0639 auto star_pos = s.find("[*]");
0640 auto arrow_pos = s.rfind("->", star_pos);
0641 auto endl_before_pos = s.rfind("\n", star_pos);
0642 if (star_pos != std::string::npos &&
0643 arrow_pos != std::string::npos &&
0644 arrow_pos > endl_before_pos )
0645 {
0646 return count_terminates(s.substr(star_pos + 3), occurrences + 1);
0647 }
0648 else if(star_pos != std::string::npos)
0649 {
0650 return count_terminates(s.substr(star_pos + 3), occurrences);
0651 }
0652 return occurrences;
0653 };
0654
0655 template <class Func, class T>
0656 constexpr auto parse_terminate(Func stt, auto state_name, T vec = T{})
0657 {
0658 if constexpr (stt().empty())
0659 {
0660 return vec;
0661 }
0662 else
0663 {
0664 constexpr auto star_pos = stt().find("[*]");
0665 constexpr auto arrow_pos = stt().rfind("->", star_pos);
0666 constexpr auto endl_before_pos = stt().rfind("\n", star_pos);
0667 constexpr auto state_pos = stt().rfind(state_name(), arrow_pos);
0668
0669 if constexpr (
0670 star_pos != std::string::npos &&
0671 arrow_pos != std::string::npos &&
0672 arrow_pos > endl_before_pos &&
0673 state_pos != std::string::npos &&
0674 state_pos > endl_before_pos &&
0675 cleanup_token(stt().substr(state_pos, arrow_pos - state_pos)) == state_name())
0676 {
0677 return
0678 typename ::boost::mpl::push_back<
0679 T,
0680 boost::msm::TerminateFlag
0681 >::type{};
0682 }
0683 else if constexpr (star_pos != std::string::npos)
0684 {
0685 return parse_terminate(
0686 [=]() {return stt().substr(star_pos + 3); },
0687 state_name,
0688 vec);
0689 }
0690 else
0691 {
0692 return vec;
0693 }
0694 }
0695
0696 };
0697
0698 template <class Func, class T = boost::fusion::vector0<>>
0699 constexpr auto parse_flags(Func stt, auto state_name, T vec = T{})
0700 {
0701 constexpr auto flag_pos = stt().find("flag");
0702
0703 if constexpr (flag_pos != std::string::npos)
0704 {
0705
0706 constexpr auto endl_after_flag_pos = stt().find("\n", flag_pos);
0707 constexpr auto col_pos = stt().rfind(":",flag_pos);
0708 constexpr auto endl_before_flag_pos = stt().rfind("\n", flag_pos);
0709
0710 if constexpr (endl_after_flag_pos != std::string::npos)
0711 {
0712
0713 if constexpr (cleanup_token(stt().substr(endl_before_flag_pos+1,col_pos- (endl_before_flag_pos+1))) == state_name())
0714 {
0715
0716 return parse_flags(
0717 [=]() {return stt().substr(endl_after_flag_pos + 1); },
0718 state_name,
0719 typename ::boost::mpl::push_back<
0720 T,
0721 typename boost::msm::front::puml::convert_to_msm_names<
0722 boost::msm::front::puml::Flag< by_name(cleanup_token(stt().substr(flag_pos + 4, endl_after_flag_pos - (flag_pos + 4))))>>::type
0723 >::type{});
0724 }
0725 else
0726 {
0727
0728 return parse_flags(
0729 [=]() {return stt().substr(endl_after_flag_pos + 1); },
0730 state_name,
0731 vec);
0732 }
0733 }
0734 else
0735 {
0736
0737 if constexpr (cleanup_token(stt().substr(endl_before_flag_pos + 1, col_pos - (endl_before_flag_pos + 1))) == state_name())
0738 {
0739 return typename ::boost::mpl::push_back<
0740 T,
0741 typename boost::msm::front::puml::convert_to_msm_names<
0742 boost::msm::front::puml::Flag< by_name(cleanup_token(stt().substr(flag_pos + 4, endl_after_flag_pos - (flag_pos + 4))))>>::type
0743 >::type{};
0744 }
0745 else
0746 {
0747 return vec;
0748 }
0749 }
0750 }
0751 else
0752 {
0753
0754 return vec;
0755 }
0756 }
0757
0758 template <class Func, int actions_count, int anum, class T = boost::fusion::vector<>>
0759 constexpr auto create_action_sequence_helper(Func action_func, T vec = T{})
0760 {
0761
0762 if constexpr (anum >= actions_count)
0763 {
0764 return vec;
0765 }
0766 else
0767 {
0768 return boost::msm::front::puml::detail::create_action_sequence_helper<Func, actions_count, anum + 1>(
0769 action_func,
0770 typename ::boost::mpl::push_back<
0771 T,
0772 typename boost::msm::front::puml::convert_to_msm_names<
0773 Action<by_name(boost::msm::front::puml::detail::parse_action<anum>(action_func()))>>::type >::type{});
0774 }
0775 }
0776 template <class Func>
0777 constexpr auto create_action_sequence(Func action_func)
0778 {
0779 return boost::msm::front::puml::detail::create_action_sequence_helper<
0780 Func, boost::msm::front::puml::detail::count_actions(action_func()), 0>(action_func);
0781 }
0782
0783
0784 template <class Func, class T = boost::fusion::vector0<>>
0785 constexpr auto parse_state_actions(Func stt, auto state_name, auto tag_text, T vec = T{})
0786 {
0787 constexpr auto entry_pos = stt().find(std::string_view(tag_text()));
0788 constexpr auto tag_size = std::string_view(tag_text()).length();
0789
0790 if constexpr (entry_pos != std::string::npos)
0791 {
0792
0793 constexpr auto endl_after_entry_pos = stt().find("\n", entry_pos);
0794 constexpr auto bracket_beg_after_entry_pos = stt().find("[", entry_pos);
0795
0796 constexpr auto col_pos = stt().rfind(":", entry_pos);
0797 constexpr auto endl_before_entry_pos = stt().rfind("\n", entry_pos);
0798 auto make_action_sequence = [](auto actions)
0799 {
0800 if constexpr (boost::mpl::size<decltype(actions)>::value == 1)
0801 return boost::fusion::at_c<0>(actions);
0802 else if constexpr (boost::mpl::size<decltype(actions)>::value == 0)
0803 return boost::msm::front::none{};
0804 else
0805 return boost::msm::front::ActionSequence_<decltype(actions)>{};
0806 };
0807
0808 if constexpr (endl_after_entry_pos != std::string::npos)
0809 {
0810
0811 if constexpr (by_name(cleanup_token(stt().substr(endl_before_entry_pos + 1, col_pos - (endl_before_entry_pos + 1)))) == by_name(state_name()))
0812 {
0813 if constexpr (bracket_beg_after_entry_pos != std::string::npos && bracket_beg_after_entry_pos < endl_after_entry_pos)
0814 {
0815 constexpr auto bracket_end_after_entry_pos = stt().find("]", entry_pos);
0816 auto guard_l = [=]() {return stt().substr(bracket_beg_after_entry_pos +1, bracket_end_after_entry_pos - (bracket_beg_after_entry_pos +1)) ; };
0817 auto action_l = [=]() {return stt().substr(entry_pos + tag_size, bracket_beg_after_entry_pos - (entry_pos + tag_size)); };
0818
0819
0820 return parse_state_actions(
0821 [=]() {return stt().substr(endl_after_entry_pos + 1); },
0822 state_name,
0823 tag_text,
0824 typename ::boost::mpl::push_back<
0825 T,
0826 boost::msm::front::puml::detail::pair_type<
0827 decltype(make_action_sequence(boost::msm::front::puml::detail::create_action_sequence(action_l))),
0828 typename boost::msm::front::puml::convert_to_msm_names<
0829 decltype(boost::msm::front::puml::detail::parse_guard(guard_l))>::type
0830 >
0831 >::type{});
0832 }
0833 else
0834 {
0835
0836 auto action_l = [=]() {return stt().substr(entry_pos + tag_size, endl_after_entry_pos - (entry_pos + tag_size)); };
0837
0838 return parse_state_actions(
0839 [=]() {return stt().substr(endl_after_entry_pos + 1); },
0840 state_name,
0841 tag_text,
0842 typename ::boost::mpl::push_back<
0843 T,
0844 boost::msm::front::puml::detail::pair_type<
0845 decltype(make_action_sequence(boost::msm::front::puml::detail::create_action_sequence(action_l))),
0846 typename boost::msm::front::puml::convert_to_msm_names<
0847 boost::msm::front::puml::Guard<by_name("")>>::type
0848 >
0849 >::type{});
0850 }
0851
0852 }
0853 else
0854 {
0855
0856 return parse_state_actions(
0857 [=]() {return stt().substr(endl_after_entry_pos + 1); },
0858 state_name,
0859 tag_text,
0860 vec);
0861 }
0862 }
0863
0864 else
0865 {
0866
0867 if constexpr (by_name(cleanup_token(stt().substr(endl_before_entry_pos + 1, col_pos - (endl_before_entry_pos + 1)))) == by_name(state_name()))
0868 {
0869 if constexpr (bracket_beg_after_entry_pos != std::string::npos && bracket_beg_after_entry_pos < endl_after_entry_pos)
0870 {
0871 constexpr auto bracket_end_after_entry_pos = stt().find("]", entry_pos);
0872 auto guard_l = [stt]() {return stt().substr(bracket_beg_after_entry_pos +1, bracket_end_after_entry_pos - (bracket_beg_after_entry_pos +1)) ; };
0873
0874
0875
0876 auto action_l = [stt]() {return stt().substr(entry_pos + tag_size, bracket_beg_after_entry_pos - (entry_pos + tag_size)); };
0877
0878 return
0879 typename ::boost::mpl::push_back<
0880 T,
0881 boost::msm::front::puml::detail::pair_type<
0882 decltype(make_action_sequence(boost::msm::front::puml::detail::create_action_sequence(action_l))),
0883 decltype(boost::msm::front::puml::detail::parse_guard(guard_l))
0884 >
0885 >::type{};
0886 }
0887 else
0888 {
0889 auto action_l = [stt]() {return stt().substr(entry_pos + tag_size, endl_after_entry_pos - (entry_pos + tag_size)); };
0890
0891 return
0892 typename ::boost::mpl::push_back<
0893 T,
0894 boost::msm::front::puml::detail::pair_type <
0895 decltype(make_action_sequence(boost::msm::front::puml::detail::create_action_sequence(action_l))),
0896 boost::msm::front::puml::Guard<by_name("")>
0897 >
0898 >::type{};
0899 }
0900
0901 }
0902 else
0903 {
0904 return vec;
0905 }
0906 }
0907 }
0908 else
0909 {
0910
0911 return vec;
0912 }
0913 }
0914
0915
0916 template <class Func, int transitions, int tnum, class T = boost::fusion::vector<>>
0917 constexpr auto create_transition_table_helper(Func stt, T vec = T{})
0918 {
0919
0920 if constexpr (tnum >= transitions)
0921 {
0922 return vec;
0923 }
0924 else
0925 {
0926 auto guard_l = [stt]() {return boost::msm::front::puml::detail::parse_stt<tnum>(stt()).guard; };
0927 auto action_l = [stt]() {return boost::msm::front::puml::detail::parse_stt<tnum>(stt()).action; };
0928 auto source_l = [stt]() {return boost::msm::front::puml::detail::parse_stt<tnum>(stt()).source; };
0929 auto target_l = [stt]() {return boost::msm::front::puml::detail::parse_stt<tnum>(stt()).target; };
0930 auto stt_l = [stt]() {return std::string_view(stt()); };
0931 auto entry_l = []() {return "entry"; };
0932 auto exit_l = []() {return "exit"; };
0933
0934 auto make_action_sequence = [](auto actions)
0935 {
0936 if constexpr (boost::mpl::size<decltype(actions)>::value == 1)
0937 return boost::fusion::at_c<0>(actions);
0938 else if constexpr (boost::mpl::size<decltype(actions)>::value == 0)
0939 return boost::msm::front::none{};
0940 else
0941 return boost::msm::front::ActionSequence_<decltype(actions)>{};
0942 };
0943
0944
0945 using one_row =
0946 boost::msm::front::Row <
0947 State < by_name(boost::msm::front::puml::detail::parse_stt<tnum>(stt()).source),
0948 decltype(boost::msm::front::puml::detail::parse_terminate(
0949 stt_l, source_l, boost::msm::front::puml::detail::parse_flags(stt_l,source_l))),
0950 decltype(parse_state_actions(stt_l,source_l, entry_l)),
0951 decltype(parse_state_actions(stt_l,source_l, exit_l))
0952 >,
0953 typename boost::msm::front::puml::convert_to_msm_names<
0954 Event< by_name(boost::msm::front::puml::detail::parse_stt<tnum>(stt()).event)>>::type,
0955 typename boost::msm::front::puml::convert_to_msm_names<
0956 State< by_name(boost::msm::front::puml::detail::parse_stt<tnum>(stt()).target),
0957 decltype(boost::msm::front::puml::detail::parse_terminate(
0958 stt_l, target_l, boost::msm::front::puml::detail::parse_flags(stt_l,target_l))),
0959 decltype(parse_state_actions(stt_l, target_l, entry_l)),
0960 decltype(parse_state_actions(stt_l, target_l, exit_l))
0961 >>::type,
0962 decltype(make_action_sequence(boost::msm::front::puml::detail::create_action_sequence(action_l))),
0963 decltype(boost::msm::front::puml::detail::parse_guard(guard_l))
0964 >;
0965
0966 return boost::msm::front::puml::detail::create_transition_table_helper<Func, transitions, tnum + 1>(
0967 stt, typename ::boost::mpl::push_back< T, one_row>::type{});
0968 }
0969 }
0970
0971
0972 template <class Func, int regions, int rnum, class T = boost::fusion::vector<>>
0973 constexpr auto create_inits_helper(Func stt, T vec = T{})
0974 {
0975
0976 if constexpr (rnum >= regions)
0977 {
0978 return vec;
0979 }
0980 else
0981 {
0982 return boost::msm::front::puml::detail::create_inits_helper<Func, regions, rnum + 1>(
0983 stt, typename ::boost::mpl::push_back< T, State<by_name(boost::msm::front::puml::detail::parse_inits<rnum>(stt()))> >::type{});
0984 }
0985 }
0986
0987
0988 }
0989
0990
0991
0992 template <class Func>
0993 constexpr auto create_transition_table(Func stt_func)
0994 {
0995 return boost::msm::front::puml::detail::create_transition_table_helper<
0996 Func,
0997 boost::msm::front::puml::detail::count_transitions(
0998 stt_func()) -
0999 boost::msm::front::puml::detail::count_inits(stt_func()) -
1000 boost::msm::front::puml::detail::count_terminates(stt_func())
1001 , 0>(stt_func);
1002 }
1003
1004 template <class Func>
1005 constexpr auto create_initial_states(Func stt_func)
1006 {
1007 return boost::msm::front::puml::detail::create_inits_helper<
1008 Func,
1009 boost::msm::front::puml::detail::count_inits(stt_func()), 0>(stt_func);
1010 }
1011
1012 template <class Func>
1013 constexpr auto create_fsm_table(Func stt_func)
1014 {
1015 return boost::msm::front::puml::detail::pair_type <
1016 decltype(
1017 boost::msm::front::puml::detail::create_transition_table_helper<
1018 Func,
1019 boost::msm::front::puml::detail::count_transitions(
1020 stt_func()) -
1021 boost::msm::front::puml::detail::count_inits(stt_func()) -
1022 boost::msm::front::puml::detail::count_terminates(stt_func())
1023 , 0>(stt_func)),
1024 decltype(
1025 boost::msm::front::puml::detail::create_inits_helper<
1026 Func,
1027 boost::msm::front::puml::detail::count_inits(stt_func()), 0>(stt_func))>{};
1028 }
1029
1030 }
1031
1032
1033 #define BOOST_MSM_PUML_DECLARE_TABLE(stt) \
1034 using Stt = decltype(create_fsm_table([]() {return stt;})); \
1035 using transition_table = typename Stt::first; \
1036 using initial_state = typename Stt::second;
1037
1038
1039 #endif