| // Copyright 2008 Christophe Henry |
| // henry UNDERSCORE christophe AT hotmail DOT com |
| // This is an extended version of the state machine available in the boost::mpl library |
| // Distributed under the same license as the original. |
| // Copyright for the original version: |
| // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed |
| // under the Boost Software License, Version 1.0. (See accompanying |
| // file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| #ifndef BOOST_MSM_FRONT_EUML_STT_GRAMMAR_H |
| #define BOOST_MSM_FRONT_EUML_STT_GRAMMAR_H |
| |
| #include <boost/msm/front/euml/common.hpp> |
| #include <boost/mpl/vector.hpp> |
| #include <boost/mpl/eval_if.hpp> |
| |
| #include <boost/msm/front/euml/operator.hpp> |
| #include <boost/msm/front/euml/guard_grammar.hpp> |
| #include <boost/msm/front/euml/state_grammar.hpp> |
| |
| namespace proto = boost::proto; |
| |
| namespace boost { namespace msm { namespace front { namespace euml |
| { |
| |
| template <class SOURCE,class EVENT,class TARGET,class ACTION=none,class GUARD=none> |
| struct TempRow |
| { |
| typedef SOURCE Source; |
| typedef EVENT Evt; |
| typedef TARGET Target; |
| typedef ACTION Action; |
| typedef GUARD Guard; |
| }; |
| |
| template <class TEMP_ROW> |
| struct convert_to_row |
| { |
| typedef Row<typename TEMP_ROW::Source,typename TEMP_ROW::Evt,typename TEMP_ROW::Target, |
| typename TEMP_ROW::Action,typename TEMP_ROW::Guard> type; |
| }; |
| template <class TEMP_ROW> |
| struct convert_to_internal_row |
| { |
| typedef Internal<typename TEMP_ROW::Evt, |
| typename TEMP_ROW::Action,typename TEMP_ROW::Guard> type; |
| }; |
| // explicit + fork + entry point + exit point grammar |
| struct BuildEntry |
| : proto::when< |
| proto::function<proto::terminal<proto::_>,proto::terminal<state_tag>,proto::terminal<state_tag> >, |
| get_fct<proto::_child_c<0>,proto::_child_c<1>,proto::_child_c<2> >() |
| > |
| {}; |
| |
| // row grammar |
| struct BuildNextStates |
| : proto::or_< |
| proto::when< |
| proto::terminal<state_tag>, |
| proto::_ |
| >, |
| proto::when< |
| BuildEntry, |
| BuildEntry |
| >, |
| proto::when< |
| proto::comma<BuildEntry,BuildEntry >, |
| ::boost::mpl::push_back< |
| make_vector_one_row<BuildEntry(proto::_left)>(), |
| BuildEntry(proto::_right)>() |
| >, |
| proto::when < |
| proto::comma<BuildNextStates,BuildEntry >, |
| ::boost::mpl::push_back< |
| BuildNextStates(proto::_left), |
| BuildEntry(proto::_right) >() |
| > |
| > |
| {}; |
| |
| template <class EventGuard,class ActionClass> |
| struct fusion_event_action_guard |
| { |
| typedef TempRow<none,typename EventGuard::Evt,none,typename ActionClass::Action,typename EventGuard::Guard> type; |
| }; |
| |
| template <class SourceGuard,class ActionClass> |
| struct fusion_source_action_guard |
| { |
| typedef TempRow<typename SourceGuard::Source,none,none,typename ActionClass::Action,typename SourceGuard::Guard> type; |
| }; |
| |
| template <class SourceClass,class EventClass> |
| struct fusion_source_event_action_guard |
| { |
| typedef TempRow<typename SourceClass::Source,typename EventClass::Evt, |
| none,typename EventClass::Action,typename EventClass::Guard> type; |
| }; |
| template <class Left,class Right> |
| struct fusion_left_right |
| { |
| typedef TempRow<typename Right::Source,typename Right::Evt,typename Left::Target |
| ,typename Right::Action,typename Right::Guard> type; |
| }; |
| struct BuildEventPlusGuard |
| : proto::when< |
| proto::subscript<proto::terminal<event_tag>,BuildGuards >, |
| TempRow<none,proto::_left,none,none,BuildGuards(proto::_right)>() |
| > |
| {}; |
| |
| struct BuildSourceState |
| : proto::or_< |
| proto::when< |
| proto::terminal<state_tag>, |
| proto::_ |
| >, |
| proto::when< |
| BuildEntry, |
| BuildEntry |
| > |
| > |
| {}; |
| |
| struct BuildSourcePlusGuard |
| : proto::when< |
| proto::subscript<BuildSourceState,BuildGuards >, |
| TempRow<BuildSourceState(proto::_left),none,none,none,BuildGuards(proto::_right)>() |
| > |
| {}; |
| |
| struct BuildEvent |
| : proto::or_< |
| // just event without guard/action |
| proto::when< |
| proto::terminal<event_tag>, |
| TempRow<none,proto::_,none>() > |
| // event / action |
| , proto::when< |
| proto::divides<proto::terminal<event_tag>,BuildActionSequence >, |
| TempRow<none,proto::_left,none, |
| BuildActionSequence(proto::_right) >() > |
| // event [ guard ] |
| , proto::when< |
| proto::subscript<proto::terminal<event_tag>,BuildGuards >, |
| TempRow<none,proto::_left,none,none,BuildGuards(proto::_right)>() > |
| // event [ guard ] / action |
| , proto::when< |
| proto::divides<BuildEventPlusGuard, |
| BuildActionSequence >, |
| fusion_event_action_guard<BuildEventPlusGuard(proto::_left), |
| TempRow<none,none,none,BuildActionSequence(proto::_right)>() |
| >() |
| > |
| > |
| {}; |
| struct BuildSource |
| : proto::or_< |
| // after == if just state without event or guard/action |
| proto::when< |
| BuildSourceState, |
| TempRow<BuildSourceState(proto::_),none,none>() > |
| // == source / action |
| , proto::when< |
| proto::divides<BuildSourceState,BuildActionSequence >, |
| TempRow<BuildSourceState(proto::_left),none,none, |
| BuildActionSequence(proto::_right) >() > |
| // == source [ guard ] |
| , proto::when< |
| proto::subscript<BuildSourceState,BuildGuards >, |
| TempRow<BuildSourceState(proto::_left),none,none,none,BuildGuards(proto::_right)>() > |
| // == source [ guard ] / action |
| , proto::when< |
| proto::divides<BuildSourcePlusGuard, |
| BuildActionSequence >, |
| fusion_source_action_guard<BuildSourcePlusGuard(proto::_left), |
| TempRow<none,none,none,BuildActionSequence(proto::_right)>() |
| >() |
| > |
| > |
| {}; |
| |
| struct BuildRight |
| : proto::or_< |
| proto::when< |
| proto::plus<BuildSource,BuildEvent >, |
| fusion_source_event_action_guard<BuildSource(proto::_left),BuildEvent(proto::_right)>() |
| >, |
| proto::when< |
| BuildSource, |
| BuildSource |
| > |
| > |
| {}; |
| |
| struct BuildRow |
| : proto::or_< |
| // grammar 1 |
| proto::when< |
| proto::equal_to<BuildNextStates,BuildRight >, |
| convert_to_row< |
| fusion_left_right<TempRow<none,none,BuildNextStates(proto::_left)>,BuildRight(proto::_right)> >() |
| >, |
| // internal events |
| proto::when< |
| BuildRight, |
| convert_to_row< |
| fusion_left_right<TempRow<none,none,none>,BuildRight(proto::_)> >() |
| >, |
| // grammar 2 |
| proto::when< |
| proto::equal_to<BuildRight,BuildNextStates>, |
| convert_to_row< |
| fusion_left_right<TempRow<none,none,BuildNextStates(proto::_right)>,BuildRight(proto::_left)> >() |
| > |
| > |
| {}; |
| |
| // stt grammar |
| struct BuildStt |
| : proto::or_< |
| proto::when< |
| proto::comma<BuildStt,BuildStt>, |
| boost::mpl::push_back<BuildStt(proto::_left),BuildRow(proto::_right)>() |
| >, |
| proto::when < |
| BuildRow, |
| make_vector_one_row<BuildRow(proto::_)>() |
| > |
| > |
| {}; |
| |
| template <class Expr> |
| typename ::boost::mpl::eval_if< |
| typename proto::matches<Expr,BuildStt>::type, |
| boost::result_of<BuildStt(Expr)>, |
| make_invalid_type>::type |
| build_stt(Expr const& expr) |
| { |
| return typename boost::result_of<BuildStt(Expr)>::type(); |
| } |
| |
| // internal stt grammar |
| struct BuildInternalRow |
| : proto::when< |
| BuildEvent, |
| convert_to_internal_row< |
| fusion_left_right<TempRow<none,none,none>,BuildEvent(proto::_)> >() |
| > |
| {}; |
| struct BuildInternalStt |
| : proto::or_< |
| proto::when< |
| proto::comma<BuildInternalStt,BuildInternalStt>, |
| boost::mpl::push_back<BuildInternalStt(proto::_left),BuildInternalRow(proto::_right)>() |
| >, |
| proto::when < |
| BuildInternalRow, |
| make_vector_one_row<BuildInternalRow(proto::_)>() |
| > |
| > |
| {}; |
| |
| template <class Expr> |
| typename ::boost::mpl::eval_if< |
| typename proto::matches<Expr,BuildInternalStt>::type, |
| boost::result_of<BuildInternalStt(Expr)>, |
| make_invalid_type>::type |
| build_internal_stt(Expr const& expr) |
| { |
| return typename boost::result_of<BuildInternalStt(Expr)>::type(); |
| } |
| |
| |
| }}}} |
| #endif //BOOST_MSM_FRONT_EUML_STT_GRAMMAR_H |