// 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::or_< proto::when< proto::function<proto::terminal<proto::_>,proto::terminal<state_tag>,proto::terminal<state_tag> >, get_fct<proto::_child_c<0>,get_state_name<proto::_child_c<1>() >(),get_state_name<proto::_child_c<2>() >() >() > > {}; // row grammar struct BuildNextStates : proto::or_< proto::when< proto::terminal<state_tag>, get_state_name<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::or_< proto::when< proto::subscript<proto::terminal<event_tag>, GuardGrammar >, TempRow<none,proto::_left,none,none, GuardGrammar(proto::_right)>(proto::_right) > > {}; struct BuildSourceState : proto::or_< proto::when< proto::terminal<state_tag>, get_state_name<proto::_>() >, proto::when< BuildEntry, BuildEntry > > {}; struct BuildSourcePlusGuard : proto::when< proto::subscript<BuildSourceState,GuardGrammar >, TempRow<BuildSourceState(proto::_left),none,none,none,GuardGrammar(proto::_right)>(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>,ActionGrammar >, TempRow<none,proto::_left,none,ActionGrammar(proto::_right) >(proto::_right) > // event [ guard ] , proto::when< proto::subscript<proto::terminal<event_tag>,GuardGrammar >, TempRow<none,proto::_left,none,none,GuardGrammar(proto::_right)>(proto::_right) > // event [ guard ] / action , proto::when< proto::divides<BuildEventPlusGuard, ActionGrammar>, fusion_event_action_guard<BuildEventPlusGuard(proto::_left), TempRow<none,none,none,ActionGrammar(proto::_right)>(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,ActionGrammar >, TempRow<BuildSourceState(proto::_left),none,none,ActionGrammar(proto::_right) >(proto::_right) > // == source [ guard ] , proto::when< proto::subscript<BuildSourceState,GuardGrammar >, TempRow<BuildSourceState(proto::_left),none,none,none,GuardGrammar(proto::_right)>(proto::_right) > // == source [ guard ] / action , proto::when< proto::divides<BuildSourcePlusGuard, ActionGrammar >, fusion_source_action_guard<BuildSourcePlusGuard(proto::_left), TempRow<none,none,none,ActionGrammar(proto::_right)>(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&) { 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&) { return typename boost::result_of<BuildInternalStt(Expr)>::type(); } }}}} #endif //BOOST_MSM_FRONT_EUML_STT_GRAMMAR_H